├── ui ├── delegates │ ├── SuggestVideoCard.qml │ └── qmldir ├── +android │ ├── delegates │ │ ├── SuggestVideoCard.qml │ │ └── qmldir │ ├── views │ │ ├── qmldir │ │ ├── CountdownBar.qml │ │ ├── BigTileView.qml │ │ ├── BackupListTileView.qml │ │ ├── ListTileView.qml │ │ ├── HomeTileView.qml │ │ └── TileView.qml │ ├── images │ │ ├── back.png │ │ ├── home.png │ │ ├── search.png │ │ └── history.png │ ├── youtube-logo-page.jpg │ ├── qmldir │ ├── YoutubeLogo.qml │ ├── TopBarTabButton.qml │ ├── CategoryBoxHistoryView.qml │ ├── HighlightType.qml │ ├── CategoryBoxSearchView.qml │ ├── CategoryBoxView.qml │ ├── YoutubeSearch.qml │ └── SuggestionArea.qml ├── +mediacenter │ ├── delegates │ │ └── SuggestVideoCard.qml │ ├── youtube-logo-page.jpg │ ├── test.qml │ ├── YoutubeLogo.qml │ ├── TopBarTabButton.qml │ ├── views │ │ ├── CountdownBar.qml │ │ ├── TileView.qml │ │ ├── BigTileView.qml │ │ ├── BackupListTileView.qml │ │ ├── ListTileView.qml │ │ └── HomeTileView.qml │ ├── CategoryBoxHistoryView.qml │ ├── HighlightType.qml │ ├── CategoryBoxSearchView.qml │ ├── CategoryBoxView.qml │ └── YoutubeSearch.qml ├── views │ ├── qmldir │ ├── CountdownBar.qml │ ├── BigTileView.qml │ ├── BackupListTileView.qml │ ├── ListTileView.qml │ ├── HomeTileView.qml │ └── TileView.qml ├── images │ ├── back.png │ ├── home.png │ ├── history.png │ ├── search.png │ ├── spinner.gif │ ├── information.png │ ├── media-playback-start.svg │ ├── media-playback-pause.svg │ ├── media-skip-backward.svg │ ├── media-skip-forward.svg │ ├── media-playlist-repeat.svg │ ├── media-playlist-shuffle.svg │ ├── media-album-track.svg │ ├── media-repeat-track.svg │ ├── media-repeat-playlist.svg │ ├── simple-play.svg │ ├── simple-stop.svg │ ├── simple-pause.svg │ ├── simple-next.svg │ ├── simple-previous.svg │ ├── simple-audio-off.svg │ ├── simple-audio-on.svg │ ├── simple-fullscreen.svg │ └── simple-repeat.svg ├── youtube-logo-page.jpg ├── qmldir ├── YoutubeLogo.qml ├── TopBarTabButton.qml ├── CategoryBoxHistoryView.qml ├── YoutubePlayerBackup.qml ├── HighlightType.qml ├── CategoryBoxView.qml ├── CategoryBoxSearchView.qml ├── YoutubeSearch.qml └── SuggestionArea.qml ├── vocab └── en-us │ ├── YoutubeKeyword.voc │ ├── YoutubeLauncherIdKeyword.voc │ ├── YoutubePauseKeyword.voc │ ├── YoutubeResumeKeyword.voc │ ├── YoutubeSearchPageKeyword.voc │ ├── YoutubeLiveSearchPageKeyword.voc │ ├── youtube.intent │ ├── youtube-repeat.intent │ └── youtubeopenapp.intent ├── regex └── en-us │ └── location.rx ├── res ├── icon │ └── youtube-skill.png └── desktop │ └── youtube-skill.desktop ├── settings.json ├── test └── intent │ ├── 01-youtube-play.json │ ├── 02-youtube-pause.json │ ├── 03-youtube-resume.json │ └── 04-youtube-search.json ├── requirements.txt ├── tempfix ├── README.txt └── search │ └── session │ └── session.py ├── README.md └── settingsmeta.json /ui/delegates/SuggestVideoCard.qml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /vocab/en-us/YoutubeKeyword.voc: -------------------------------------------------------------------------------- 1 | youtube -------------------------------------------------------------------------------- /regex/en-us/location.rx: -------------------------------------------------------------------------------- 1 | (at|in) (?P.*) -------------------------------------------------------------------------------- /ui/+android/delegates/SuggestVideoCard.qml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ui/+mediacenter/delegates/SuggestVideoCard.qml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /vocab/en-us/YoutubeLauncherIdKeyword.voc: -------------------------------------------------------------------------------- 1 | ID01 2 | -------------------------------------------------------------------------------- /vocab/en-us/YoutubePauseKeyword.voc: -------------------------------------------------------------------------------- 1 | pause youtube 2 | -------------------------------------------------------------------------------- /vocab/en-us/YoutubeResumeKeyword.voc: -------------------------------------------------------------------------------- 1 | resume youtube 2 | -------------------------------------------------------------------------------- /ui/delegates/qmldir: -------------------------------------------------------------------------------- 1 | ListVideoCard 1.0 ListVideoCard.qml 2 | -------------------------------------------------------------------------------- /ui/+android/delegates/qmldir: -------------------------------------------------------------------------------- 1 | ListVideoCard 1.0 ListVideoCard.qml 2 | -------------------------------------------------------------------------------- /vocab/en-us/YoutubeSearchPageKeyword.voc: -------------------------------------------------------------------------------- 1 | search youtube for 2 | -------------------------------------------------------------------------------- /vocab/en-us/YoutubeLiveSearchPageKeyword.voc: -------------------------------------------------------------------------------- 1 | show youtube live search 2 | -------------------------------------------------------------------------------- /ui/views/qmldir: -------------------------------------------------------------------------------- 1 | BigTileView 1.0 BigTileView.qml 2 | TileView 1.0 TileView.qml 3 | -------------------------------------------------------------------------------- /ui/+android/views/qmldir: -------------------------------------------------------------------------------- 1 | BigTileView 1.0 BigTileView.qml 2 | TileView 1.0 TileView.qml 3 | -------------------------------------------------------------------------------- /ui/images/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/images/back.png -------------------------------------------------------------------------------- /ui/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/images/home.png -------------------------------------------------------------------------------- /ui/images/history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/images/history.png -------------------------------------------------------------------------------- /ui/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/images/search.png -------------------------------------------------------------------------------- /ui/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/images/spinner.gif -------------------------------------------------------------------------------- /ui/youtube-logo-page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/youtube-logo-page.jpg -------------------------------------------------------------------------------- /res/icon/youtube-skill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/res/icon/youtube-skill.png -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | {"code": "4BC3-4DD2", "not_owner": true, "__mycroft_skill_firstrun": false, "label1": "null"} -------------------------------------------------------------------------------- /ui/+android/images/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/+android/images/back.png -------------------------------------------------------------------------------- /ui/+android/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/+android/images/home.png -------------------------------------------------------------------------------- /ui/images/information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/images/information.png -------------------------------------------------------------------------------- /ui/+android/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/+android/images/search.png -------------------------------------------------------------------------------- /ui/+android/images/history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/+android/images/history.png -------------------------------------------------------------------------------- /test/intent/01-youtube-play.json: -------------------------------------------------------------------------------- 1 | { 2 | "utterance": "youtube metalica", 3 | "intent_type": "youtube.intent" 4 | } 5 | -------------------------------------------------------------------------------- /ui/+android/youtube-logo-page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/+android/youtube-logo-page.jpg -------------------------------------------------------------------------------- /test/intent/02-youtube-pause.json: -------------------------------------------------------------------------------- 1 | { 2 | "utterance": "pause youtube", 3 | "intent_type": "YoutubePauseKeyword" 4 | } 5 | -------------------------------------------------------------------------------- /test/intent/03-youtube-resume.json: -------------------------------------------------------------------------------- 1 | { 2 | "utterance": "resume youtube", 3 | "intent_type": "YoutubeResumeKeyword" 4 | } 5 | -------------------------------------------------------------------------------- /ui/+mediacenter/youtube-logo-page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIIX/youtube-skill/HEAD/ui/+mediacenter/youtube-logo-page.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=1.1 2 | pafy 3 | youtube-dl 4 | bs4 5 | json_database 6 | timeago 7 | python-dateutil 8 | requests_cache 9 | -------------------------------------------------------------------------------- /test/intent/04-youtube-search.json: -------------------------------------------------------------------------------- 1 | { 2 | "utterance": "search youtube for metallica", 3 | "intent_type": "YoutubeSearchPageKeyword" 4 | } 5 | -------------------------------------------------------------------------------- /vocab/en-us/youtube.intent: -------------------------------------------------------------------------------- 1 | youtube {videoname} 2 | show video of {videoname} on youtube 3 | youtube the song {videoname} 4 | youtube the artist {videoname} 5 | -------------------------------------------------------------------------------- /ui/+mediacenter/test.qml: -------------------------------------------------------------------------------- 1 | Main 2 | { 3 | width: 400 4 | height: 400 5 | video: "https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4" 6 | } 7 | -------------------------------------------------------------------------------- /vocab/en-us/youtube-repeat.intent: -------------------------------------------------------------------------------- 1 | youtube replay 2 | youtube repeat 3 | youtube replay last video 4 | youtube repeat last video 5 | replay last video 6 | repeat last video 7 | -------------------------------------------------------------------------------- /tempfix/README.txt: -------------------------------------------------------------------------------- 1 | #### This is a temporary fix #### 2 | #### Upstream work ongoing at https://github.com/HelloChatterbox/youtube_searcher/pull/1 #### 3 | #### Credits to the original author for search backend "Jarbas @JarbasSkills" #### 4 | -------------------------------------------------------------------------------- /vocab/en-us/youtubeopenapp.intent: -------------------------------------------------------------------------------- 1 | open the youtube app 2 | open youtube app 3 | show the youtube app 4 | open the youtube application 5 | open youtube application 6 | show the youtube application 7 | show youtube app 8 | show me whats trending on youtube 9 | -------------------------------------------------------------------------------- /tempfix/search/session/session.py: -------------------------------------------------------------------------------- 1 | from requests_cache import CachedSession 2 | from datetime import timedelta 3 | 4 | session = CachedSession(backend='memory', expire_after=timedelta(hours=1)) 5 | 6 | 7 | def new_session(new_session): 8 | global session 9 | session = new_session 10 | return session 11 | 12 | -------------------------------------------------------------------------------- /res/desktop/youtube-skill.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | X-DBUS-StartupType=None 3 | X-KDE-StartupNotify=false 4 | Version=1.0 5 | Terminal=false 6 | Type=Application 7 | Name=Youtube 8 | Exec=mycroft-gui-app --hideTextInput --skill=youtube-skill.aiix.home 9 | Icon=youtube-skill 10 | Categories=VoiceApp 11 | StartupNotify=false 12 | -------------------------------------------------------------------------------- /ui/qmldir: -------------------------------------------------------------------------------- 1 | YoutubeLogo 1.0 YoutubeLogo.qml 2 | TopBarTabButton 1.0 TopBarTabButton.qml 3 | CategoryBoxHistoryView 1.0 CategoryBoxHistoryView.qml 4 | CategoryBoxHomeView 1.0 CategoryBoxHomeView.qml 5 | CategoryBoxSearchView 1.0 CategoryBoxSearchView.qml 6 | YoutubeLiveSearch 1.0 YoutubeLiveSearch.qml 7 | YoutubePlayer 1.0 YoutubePlayer.qml 8 | SeekControl 1.0 SeekControl.qml 9 | YoutubeSearch 1.0 YoutubeSearch.qml 10 | -------------------------------------------------------------------------------- /ui/+android/qmldir: -------------------------------------------------------------------------------- 1 | YoutubeLogo 1.0 YoutubeLogo.qml 2 | TopBarTabButton 1.0 TopBarTabButton.qml 3 | CategoryBoxHistoryView 1.0 CategoryBoxHistoryView.qml 4 | CategoryBoxHomeView 1.0 CategoryBoxHomeView.qml 5 | CategoryBoxSearchView 1.0 CategoryBoxSearchView.qml 6 | YoutubeLiveSearch 1.0 YoutubeLiveSearch.qml 7 | YoutubePlayer 1.0 YoutubePlayer.qml 8 | SeekControl 1.0 SeekControl.qml 9 | YoutubeSearch 1.0 YoutubeSearch.qml 10 | -------------------------------------------------------------------------------- /ui/images/media-playback-start.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-playback-pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-skip-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-skip-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-playlist-repeat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-playlist-shuffle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Youtube Player 2 | Play and stream youtube videos 3 | 4 | ## About 5 | Play and Stream Youtube Videos 6 | 7 | ## Examples 8 | * "Hey Mycroft Youtube Metallica" 9 | * "Hey Mycroft Search Youtube For Metallica" 10 | * "Hey Mycroft Pause Youtube" 11 | * "Hey Mycroft Resume Youtube" 12 | 13 | ## Credits 14 | Aix (@aiix) 15 | 16 | ## Supported Devices 17 | platform_mark2 platform_plasmoid 18 | 19 | ## Category 20 | **Media** 21 | 22 | ## Tags 23 | #Youtube 24 | #Music 25 | #Video 26 | #VideoStreaming 27 | #AudioStreaming 28 | #YoutubeVideos 29 | #Media 30 | #GUI 31 | -------------------------------------------------------------------------------- /settingsmeta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Youtube Control", 3 | "color": "#ff0000", 4 | "skillMetadata": { 5 | "sections": [ 6 | { 7 | "name": "Code", 8 | "fields": [ 9 | { 10 | "type": "label", 11 | "label": "Please go to Youtube Control copy the code XXXX-XXXX." 12 | }, 13 | { 14 | "name": "code", 15 | "type": "text", 16 | "label": "XXXX-XXXX", 17 | "value": "" 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ui/images/media-album-track.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-repeat-track.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/images/media-repeat-playlist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /ui/YoutubeLogo.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import org.kde.kirigami 2.4 as Kirigami 5 | import Mycroft 1.0 as Mycroft 6 | 7 | Mycroft.Delegate { 8 | id: logoLoadingPage 9 | property string loadingStatus: sessionData.loadingStatus 10 | 11 | onLoadingStatusChanged: { 12 | loadingStatusArea.text = "Loading: " + loadingStatus 13 | } 14 | 15 | Control { 16 | id: statusArea 17 | anchors.fill: parent 18 | 19 | background: Image { 20 | source: "./youtube-logo-page.jpg" 21 | } 22 | 23 | contentItem: Item { 24 | AnimatedImage { 25 | id: busyIndicatorComponent 26 | anchors.bottom: parent.bottom 27 | anchors.bottomMargin: statusArea.height / 6 28 | anchors.horizontalCenter: parent.horizontalCenter 29 | anchors.horizontalCenterOffset: -Kirigami.Units.gridUnit * 6 30 | width: Kirigami.Units.iconSizes.smallMedium 31 | height: Kirigami.Units.iconSizes.smallMedium 32 | playing: true 33 | source: "./images/spinner.gif" 34 | } 35 | 36 | Kirigami.Heading { 37 | id: loadingStatusArea 38 | anchors.left: busyIndicatorComponent.right 39 | anchors.leftMargin: Kirigami.Units.largeSpacing 40 | anchors.verticalCenter: busyIndicatorComponent.verticalCenter 41 | level: 2 42 | text: "Loading..." 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ui/+android/YoutubeLogo.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import org.kde.kirigami 2.4 as Kirigami 5 | import Mycroft 1.0 as Mycroft 6 | 7 | Mycroft.Delegate { 8 | id: logoLoadingPage 9 | property string loadingStatus: sessionData.loadingStatus 10 | 11 | onLoadingStatusChanged: { 12 | loadingStatusArea.text = "Loading: " + loadingStatus 13 | } 14 | 15 | Control { 16 | id: statusArea 17 | anchors.fill: parent 18 | 19 | background: Image { 20 | source: "./youtube-logo-page.jpg" 21 | } 22 | 23 | contentItem: Item { 24 | AnimatedImage { 25 | id: busyIndicatorComponent 26 | anchors.bottom: parent.bottom 27 | anchors.bottomMargin: statusArea.height / 6 28 | anchors.horizontalCenter: parent.horizontalCenter 29 | anchors.horizontalCenterOffset: -Kirigami.Units.gridUnit * 6 30 | width: Kirigami.Units.iconSizes.smallMedium 31 | height: Kirigami.Units.iconSizes.smallMedium 32 | playing: true 33 | source: "./images/spinner.gif" 34 | } 35 | 36 | Kirigami.Heading { 37 | id: loadingStatusArea 38 | anchors.left: busyIndicatorComponent.right 39 | anchors.leftMargin: Kirigami.Units.largeSpacing 40 | anchors.verticalCenter: busyIndicatorComponent.verticalCenter 41 | level: 2 42 | text: "Loading..." 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ui/+mediacenter/YoutubeLogo.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.3 3 | import QtQuick.Layouts 1.3 4 | import org.kde.kirigami 2.11 as Kirigami 5 | import org.kde.plasma.components 3.0 as PlasmaComponents 6 | import Mycroft 1.0 as Mycroft 7 | 8 | Mycroft.Delegate { 9 | id: logoLoadingPage 10 | property string loadingStatus: sessionData.loadingStatus 11 | 12 | onLoadingStatusChanged: { 13 | loadingStatusArea.text = "Loading: " + loadingStatus 14 | } 15 | 16 | Control { 17 | id: statusArea 18 | anchors.fill: parent 19 | 20 | background: Image { 21 | source: "./youtube-logo-page.jpg" 22 | } 23 | 24 | contentItem: Item { 25 | AnimatedImage { 26 | id: busyIndicatorComponent 27 | anchors.bottom: parent.bottom 28 | anchors.bottomMargin: statusArea.height / 6 29 | anchors.horizontalCenter: parent.horizontalCenter 30 | anchors.horizontalCenterOffset: -Kirigami.Units.gridUnit * 6 31 | width: Kirigami.Units.iconSizes.smallMedium 32 | height: Kirigami.Units.iconSizes.smallMedium 33 | playing: true 34 | source: "./images/spinner.gif" 35 | } 36 | 37 | Kirigami.Heading { 38 | id: loadingStatusArea 39 | anchors.left: busyIndicatorComponent.right 40 | anchors.leftMargin: Kirigami.Units.largeSpacing 41 | anchors.verticalCenter: busyIndicatorComponent.verticalCenter 42 | level: 2 43 | text: "Loading..." 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ui/+mediacenter/TopBarTabButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * Copyright 2020 Marco Martin 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import QtQuick 2.9 20 | import QtQuick.Layouts 1.4 21 | import QtQuick.Controls 2.3 as Controls 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import org.kde.plasma.core 2.0 as PlasmaCore 24 | 25 | Controls.Button { 26 | id: control 27 | Layout.fillHeight: true 28 | Layout.fillWidth: true 29 | 30 | background: Rectangle { 31 | Kirigami.Theme.colorSet: Kirigami.Theme.Button 32 | color: control.activeFocus ? Kirigami.Theme.highlightColor : "transparent" 33 | 34 | Kirigami.Separator { 35 | anchors { 36 | left: parent.left 37 | right: parent.right 38 | bottom: parent.bottom 39 | } 40 | color: Kirigami.Theme.highlightColor 41 | height: Kirigami.Units.smallSpacing 42 | visible: control.checked 43 | } 44 | } 45 | 46 | contentItem: Kirigami.Heading { 47 | id: contentHome 48 | horizontalAlignment: Text.AlignHCenter 49 | verticalAlignment: Text.AlignVCenter 50 | maximumLineCount: 1 51 | text: control.text 52 | level: 1 53 | } 54 | 55 | Keys.onReturnPressed: { 56 | control.clicked() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ui/TopBarTabButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * Copyright 2020 Marco Martin 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import QtQuick 2.9 20 | import QtQuick.Layouts 1.4 21 | import QtQuick.Controls 2.3 as Controls 22 | import org.kde.kirigami 2.8 as Kirigami 23 | 24 | Controls.Button { 25 | id: control 26 | Layout.fillHeight: true 27 | Layout.fillWidth: true 28 | property var source 29 | 30 | background: Rectangle { 31 | Kirigami.Theme.colorSet: Kirigami.Theme.Button 32 | color: control.activeFocus ? Kirigami.Theme.highlightColor : "transparent" 33 | 34 | Kirigami.Separator { 35 | anchors { 36 | left: parent.left 37 | right: parent.right 38 | bottom: parent.bottom 39 | } 40 | color: Kirigami.Theme.highlightColor 41 | height: Kirigami.Units.smallSpacing 42 | visible: control.checked 43 | } 44 | } 45 | 46 | contentItem: Item { 47 | Image { 48 | id: contentHome 49 | width: Kirigami.Units.iconSizes.medium 50 | height: Kirigami.Units.iconSizes.medium 51 | anchors.centerIn: parent 52 | source: control.source 53 | } 54 | } 55 | 56 | Keys.onReturnPressed: { 57 | control.clicked() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ui/+android/TopBarTabButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * Copyright 2020 Marco Martin 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import QtQuick 2.9 20 | import QtQuick.Layouts 1.4 21 | import QtQuick.Controls 2.3 as Controls 22 | import org.kde.kirigami 2.8 as Kirigami 23 | 24 | Controls.Button { 25 | id: control 26 | Layout.fillHeight: true 27 | Layout.fillWidth: true 28 | property var source 29 | 30 | background: Rectangle { 31 | Kirigami.Theme.colorSet: Kirigami.Theme.Button 32 | color: control.activeFocus ? Kirigami.Theme.highlightColor : "transparent" 33 | 34 | Kirigami.Separator { 35 | anchors { 36 | left: parent.left 37 | right: parent.right 38 | bottom: parent.bottom 39 | } 40 | color: Kirigami.Theme.highlightColor 41 | height: Kirigami.Units.smallSpacing 42 | visible: control.checked 43 | } 44 | } 45 | 46 | contentItem: Item { 47 | Image { 48 | id: contentHome 49 | width: Kirigami.Units.iconSizes.medium 50 | height: Kirigami.Units.iconSizes.medium 51 | anchors.centerIn: parent 52 | source: control.source 53 | } 54 | } 55 | 56 | Keys.onReturnPressed: { 57 | control.clicked() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ui/CategoryBoxHistoryView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import Mycroft 1.0 as Mycroft 24 | import "+android/views" as Views 25 | import "+android/delegates" as Delegates 26 | 27 | Item { 28 | property var historyListModel: sessionData.recentListBlob.recentList 29 | Layout.fillWidth: true 30 | Layout.fillHeight: true 31 | 32 | onFocusChanged: { 33 | if(focus){ 34 | historyGridView.forceActiveFocus() 35 | } 36 | } 37 | 38 | onHistoryListModelChanged: { 39 | historyGridView.view.forceLayout() 40 | } 41 | 42 | Views.BigTileView { 43 | id: historyGridView 44 | anchors { 45 | top: parent.top 46 | left: parent.left 47 | right: parent.right 48 | bottom: parent.bottom 49 | } 50 | focus: true 51 | model: historyListModel 52 | title: count > 0 ? "Watch History" : "No Recent History" 53 | 54 | cellWidth: view.width / 2 55 | // FIXME: componentize more all this stuff 56 | cellHeight: cellWidth / 1.8 + Kirigami.Units.gridUnit * 5 57 | delegate: Delegates.ListVideoCard { 58 | width: historyGridView.cellWidth 59 | height: historyGridView.cellHeight 60 | } 61 | KeyNavigation.up: historyCatButton 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ui/+android/CategoryBoxHistoryView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import Mycroft 1.0 as Mycroft 24 | import "+android/views" as Views 25 | import "+android/delegates" as Delegates 26 | 27 | Item { 28 | property var historyListModel: sessionData.recentListBlob.recentList 29 | Layout.fillWidth: true 30 | Layout.fillHeight: true 31 | 32 | onFocusChanged: { 33 | if(focus){ 34 | historyGridView.forceActiveFocus() 35 | } 36 | } 37 | 38 | onHistoryListModelChanged: { 39 | historyGridView.view.forceLayout() 40 | } 41 | 42 | Views.BigTileView { 43 | id: historyGridView 44 | anchors { 45 | top: parent.top 46 | left: parent.left 47 | right: parent.right 48 | bottom: parent.bottom 49 | } 50 | focus: true 51 | model: historyListModel 52 | title: count > 0 ? "Watch History" : "No Recent History" 53 | 54 | cellWidth: view.width / 2 55 | // FIXME: componentize more all this stuff 56 | cellHeight: cellWidth / 1.8 + Kirigami.Units.gridUnit * 5 57 | delegate: Delegates.ListVideoCard { 58 | width: historyGridView.cellWidth 59 | height: historyGridView.cellHeight 60 | } 61 | KeyNavigation.up: historyCatButton 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ui/views/CountdownBar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Layouts 1.4 3 | import QtQuick.Controls 2.0 as Controls 4 | import org.kde.kirigami 2.8 as Kirigami 5 | import QtGraphicalEffects 1.0 6 | import Mycroft 1.0 as Mycroft 7 | 8 | 9 | RowLayout { 10 | id: countdownArea 11 | Layout.leftMargin: Kirigami.Units.largeSpacing 12 | Layout.bottomMargin: Kirigami.Units.largeSpacing 13 | property alias imageSource: img.source 14 | property alias nextSongTitle: nextSongLabel.text 15 | spacing: Kirigami.Units.largeSpacing 16 | 17 | Kirigami.Heading { 18 | level: 3 19 | Layout.alignment: Qt.AlignLeft 20 | wrapMode: Text.WordWrap 21 | elide: Text.ElideRight 22 | color: Kirigami.Theme.textColor 23 | text: "Next:" 24 | } 25 | 26 | Rectangle { 27 | Layout.preferredWidth: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing 28 | Layout.preferredHeight: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing 29 | Layout.alignment: Qt.AlignLeft 30 | color: Kirigami.Theme.backgroundColor 31 | border.color: Kirigami.Theme.linkColor 32 | border.width: Kirigami.Units.smallSpacing 33 | radius: 250 34 | 35 | Image { 36 | id: img 37 | width: Kirigami.Units.iconSizes.huge 38 | height: Kirigami.Units.iconSizes.huge 39 | fillMode: Image.PreserveAspectCrop 40 | anchors.centerIn: parent 41 | layer.enabled: true 42 | layer.effect: OpacityMask { 43 | maskSource: imgContainer 44 | } 45 | } 46 | 47 | Rectangle{ 48 | id: imgContainer 49 | property int borderWidth: 3 50 | color: Kirigami.Theme.backgroundColor 51 | width: Kirigami.Units.iconSizes.huge 52 | height: Kirigami.Units.iconSizes.huge 53 | anchors.centerIn: parent 54 | border.color: Kirigami.Theme.linkColor 55 | border.width: borderWidth 56 | radius: 250 57 | visible: false 58 | } 59 | } 60 | 61 | Kirigami.Heading { 62 | id: nextSongLabel 63 | level: 3 64 | Layout.fillWidth: true 65 | wrapMode: Text.WordWrap 66 | elide: Text.ElideRight 67 | color: Kirigami.Theme.textColor 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ui/+android/views/CountdownBar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Layouts 1.4 3 | import QtQuick.Controls 2.0 as Controls 4 | import org.kde.kirigami 2.8 as Kirigami 5 | import QtGraphicalEffects 1.0 6 | import Mycroft 1.0 as Mycroft 7 | 8 | 9 | RowLayout { 10 | id: countdownArea 11 | Layout.leftMargin: Kirigami.Units.largeSpacing 12 | Layout.bottomMargin: Kirigami.Units.largeSpacing 13 | property alias imageSource: img.source 14 | property alias nextSongTitle: nextSongLabel.text 15 | spacing: Kirigami.Units.largeSpacing 16 | 17 | Kirigami.Heading { 18 | level: 3 19 | Layout.alignment: Qt.AlignLeft 20 | wrapMode: Text.WordWrap 21 | elide: Text.ElideRight 22 | color: Kirigami.Theme.textColor 23 | text: "Next:" 24 | } 25 | 26 | Rectangle { 27 | Layout.preferredWidth: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing 28 | Layout.preferredHeight: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing 29 | Layout.alignment: Qt.AlignLeft 30 | color: Kirigami.Theme.backgroundColor 31 | border.color: Kirigami.Theme.linkColor 32 | border.width: Kirigami.Units.smallSpacing 33 | radius: 250 34 | 35 | Image { 36 | id: img 37 | width: Kirigami.Units.iconSizes.huge 38 | height: Kirigami.Units.iconSizes.huge 39 | fillMode: Image.PreserveAspectCrop 40 | anchors.centerIn: parent 41 | layer.enabled: true 42 | layer.effect: OpacityMask { 43 | maskSource: imgContainer 44 | } 45 | } 46 | 47 | Rectangle{ 48 | id: imgContainer 49 | property int borderWidth: 3 50 | color: Kirigami.Theme.backgroundColor 51 | width: Kirigami.Units.iconSizes.huge 52 | height: Kirigami.Units.iconSizes.huge 53 | anchors.centerIn: parent 54 | border.color: Kirigami.Theme.linkColor 55 | border.width: borderWidth 56 | radius: 250 57 | visible: false 58 | } 59 | } 60 | 61 | Kirigami.Heading { 62 | id: nextSongLabel 63 | level: 3 64 | Layout.fillWidth: true 65 | wrapMode: Text.WordWrap 66 | elide: Text.ElideRight 67 | color: Kirigami.Theme.textColor 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ui/+mediacenter/views/CountdownBar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Layouts 1.4 3 | import QtQuick.Controls 2.0 as Controls 4 | import org.kde.kirigami 2.8 as Kirigami 5 | import QtGraphicalEffects 1.0 6 | import Mycroft 1.0 as Mycroft 7 | 8 | 9 | RowLayout { 10 | id: countdownArea 11 | Layout.leftMargin: Kirigami.Units.largeSpacing 12 | Layout.bottomMargin: Kirigami.Units.largeSpacing 13 | property alias imageSource: img.source 14 | property alias nextSongTitle: nextSongLabel.text 15 | spacing: Kirigami.Units.largeSpacing 16 | 17 | Kirigami.Heading { 18 | level: 3 19 | Layout.alignment: Qt.AlignLeft 20 | wrapMode: Text.WordWrap 21 | elide: Text.ElideRight 22 | color: Kirigami.Theme.textColor 23 | text: "Next:" 24 | } 25 | 26 | Rectangle { 27 | Layout.preferredWidth: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing 28 | Layout.preferredHeight: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing 29 | Layout.alignment: Qt.AlignLeft 30 | color: Kirigami.Theme.backgroundColor 31 | border.color: Kirigami.Theme.linkColor 32 | border.width: Kirigami.Units.smallSpacing 33 | radius: 250 34 | 35 | Image { 36 | id: img 37 | width: Kirigami.Units.iconSizes.huge 38 | height: Kirigami.Units.iconSizes.huge 39 | fillMode: Image.PreserveAspectCrop 40 | anchors.centerIn: parent 41 | layer.enabled: true 42 | layer.effect: OpacityMask { 43 | maskSource: imgContainer 44 | } 45 | } 46 | 47 | Rectangle{ 48 | id: imgContainer 49 | property int borderWidth: 3 50 | color: Kirigami.Theme.backgroundColor 51 | width: Kirigami.Units.iconSizes.huge 52 | height: Kirigami.Units.iconSizes.huge 53 | anchors.centerIn: parent 54 | border.color: Kirigami.Theme.linkColor 55 | border.width: borderWidth 56 | radius: 250 57 | visible: false 58 | } 59 | } 60 | 61 | Kirigami.Heading { 62 | id: nextSongLabel 63 | level: 3 64 | Layout.fillWidth: true 65 | wrapMode: Text.WordWrap 66 | elide: Text.ElideRight 67 | color: Kirigami.Theme.textColor 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ui/+mediacenter/CategoryBoxHistoryView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import org.kde.plasma.core 2.0 as PlasmaCore 24 | import org.kde.plasma.components 3.0 as PlasmaComponents3 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | import "+mediacenter/views" as Views 28 | import "+mediacenter/delegates" as Delegates 29 | 30 | Item { 31 | property var historyListModel: sessionData.recentListBlob.recentList 32 | Layout.fillWidth: true 33 | Layout.fillHeight: true 34 | 35 | onFocusChanged: { 36 | if(focus){ 37 | historyGridView.forceActiveFocus() 38 | } 39 | } 40 | 41 | onHistoryListModelChanged: { 42 | historyGridView.view.forceLayout() 43 | } 44 | 45 | Views.BigTileView { 46 | id: historyGridView 47 | anchors { 48 | top: parent.top 49 | left: parent.left 50 | right: parent.right 51 | bottom: parent.bottom 52 | } 53 | focus: true 54 | model: historyListModel 55 | title: count > 0 ? "Watch History" : "No Recent History" 56 | 57 | cellWidth: view.width / 4 58 | // FIXME: componentize more all this stuff 59 | cellHeight: cellWidth / 1.8 + Kirigami.Units.gridUnit * 5 60 | delegate: Delegates.ListVideoCard { 61 | width: historyGridView.cellWidth 62 | height: historyGridView.cellHeight 63 | } 64 | KeyNavigation.up: historyCatButton 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ui/+mediacenter/views/TileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.plasma.components 3.0 as PlasmaComponents 24 | import org.kde.kirigami 2.5 as Kirigami 25 | 26 | 27 | GridView { 28 | id: view 29 | cellWidth: parent.width >= 1500 ? parent.width / 5 : parent.width / 3 30 | cellHeight: parent.width >= 1500 ? parent.height / 2 : parent.height / 3 31 | 32 | Layout.fillWidth: true 33 | Layout.fillHeight: true 34 | 35 | //z: activeFocus ? 10: 1 36 | keyNavigationEnabled: true 37 | highlightFollowsCurrentItem: true 38 | snapMode: ListView.SnapToItem 39 | cacheBuffer: width 40 | highlightMoveDuration: Kirigami.Units.longDuration 41 | 42 | PlasmaComponents.ScrollBar.vertical: PlasmaComponents.ScrollBar { 43 | id: scrollBar 44 | opacity: 0 45 | interactive: false 46 | onOpacityChanged: disappearTimer.restart() 47 | Timer { 48 | id: disappearTimer 49 | interval: 1000 50 | onTriggered: scrollBar.opacity = 0; 51 | } 52 | Behavior on opacity { 53 | OpacityAnimator { 54 | duration: Kirigami.Units.longDuration 55 | easing.type: Easing.InOutQuad 56 | } 57 | } 58 | } 59 | 60 | Behavior on y { 61 | NumberAnimation { 62 | duration: Kirigami.Units.longDuration * 2 63 | easing.type: Easing.InOutQuad 64 | } 65 | } 66 | 67 | move: Transition { 68 | SmoothedAnimation { 69 | property: "x" 70 | duration: Kirigami.Units.longDuration 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ui/YoutubePlayerBackup.qml: -------------------------------------------------------------------------------- 1 | import QtMultimedia 5.9 2 | import QtQuick.Layouts 1.4 3 | import QtQuick 2.9 4 | import QtQuick.Controls 2.0 as Controls 5 | import org.kde.kirigami 2.4 as Kirigami 6 | import QtGraphicalEffects 1.0 7 | 8 | import Mycroft 1.0 as Mycroft 9 | 10 | import "." as Local 11 | 12 | Mycroft.Delegate { 13 | id: root 14 | 15 | property var videoSource: sessionData.video 16 | property var videoStatus: sessionData.status 17 | 18 | //graceTime: Infinity 19 | 20 | //The player is always fullscreen 21 | fillWidth: true 22 | background: Rectangle { 23 | color: "black" 24 | } 25 | leftPadding: 0 26 | topPadding: 0 27 | rightPadding: 0 28 | bottomPadding: 0 29 | 30 | onEnabledChanged: syncStatusTimer.restart() 31 | onVideoSourceChanged: syncStatusTimer.restart() 32 | Component.onCompleted: syncStatusTimer.restart() 33 | 34 | // Sometimes can't be restarted reliably immediately, put it in a timer 35 | Timer { 36 | id: syncStatusTimer 37 | interval: 0 38 | onTriggered: { 39 | if (enabled && videoStatus == "play") { 40 | video.play(); 41 | } else if (videoStatus == "stop") { 42 | video.stop(); 43 | } else { 44 | video.pause(); 45 | } 46 | } 47 | } 48 | controlBar: Local.SeekControl { 49 | id: seekControl 50 | anchors { 51 | left: parent.left 52 | right: parent.right 53 | bottom: parent.bottom 54 | } 55 | videoControl: video 56 | duration: video.duration 57 | playPosition: video.position 58 | onSeekPositionChanged: video.seek(seekPosition); 59 | z: 1000 60 | } 61 | 62 | Video { 63 | id: video 64 | anchors.fill: parent 65 | focus: true 66 | autoLoad: true 67 | autoPlay: false 68 | Keys.onSpacePressed: video.playbackState == MediaPlayer.PlayingState ? video.pause() : video.play() 69 | Keys.onLeftPressed: video.seek(video.position - 5000) 70 | Keys.onRightPressed: video.seek(video.position + 5000) 71 | source: videoSource 72 | readonly property string currentStatus: root.enabled ? root.videoStatus : "pause" 73 | 74 | onCurrentStatusChanged: {print("OOO"+currentStatus) 75 | switch(currentStatus){ 76 | case "stop": 77 | video.stop(); 78 | break; 79 | case "pause": 80 | video.pause() 81 | break; 82 | case "play": 83 | video.play() 84 | break; 85 | } 86 | } 87 | 88 | MouseArea { 89 | anchors.fill: parent 90 | onClicked: controlBarItem.opened = !controlBarItem.opened 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /ui/images/simple-play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ui/images/simple-stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /ui/HighlightType.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Daker Fernandes Pinheiro 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU Library General Public License as 6 | * published by the Free Software Foundation; either version 2, or 7 | * (at your option) any later version. 8 | * 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 13 | * 14 | * You should have received a copy of the GNU Library General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.1 21 | import org.kde.plasma.core 2.0 as PlasmaCore 22 | 23 | /** 24 | * Used to highlight an item of a list. to be used only as the "highlight" 25 | * property of the ListView and GridView primitive QML components (or their 26 | * derivates) 27 | * 28 | * Provides built-in animation of Behavior on opacity Easing.OutQuad for a 29 | * duration of 250 (defined in units.longDuration). 30 | * 31 | * (TODO, make optional? e.g. animate: false) 32 | * 33 | * @inherit QtQuick.Item 34 | */ 35 | Item { 36 | id: highlight 37 | 38 | /** true if the user is hovering over the component */ 39 | //in the case we are the highlight of a listview, it follows the mouse, so hover = true 40 | property bool hover: ListView ? true : false 41 | 42 | /** true if the mouse button is pressed over the component. */ 43 | property bool pressed: false 44 | width: ListView.view ? ListView.view.width : undefined 45 | property alias marginHints: background.margins; 46 | 47 | Connections { 48 | target: highlight.ListView.view 49 | onCurrentIndexChanged: { 50 | if (highlight.ListView.view.currentIndex >= 0) { 51 | background.opacity = 1 52 | } else { 53 | background.opacity = 0 54 | } 55 | } 56 | } 57 | 58 | Behavior on opacity { 59 | NumberAnimation { 60 | duration: units.longDuration 61 | easing.type: Easing.OutQuad 62 | } 63 | } 64 | 65 | PlasmaCore.FrameSvgItem { 66 | id: background 67 | imagePath: "widgets/viewitem" 68 | prefix: { 69 | if (pressed) 70 | return hover ? "selected+hover" : "selected"; 71 | 72 | if (hover) 73 | return "hover"; 74 | 75 | return "normal"; 76 | } 77 | 78 | Behavior on opacity { 79 | NumberAnimation { 80 | duration: units.longDuration 81 | easing.type: Easing.OutQuad 82 | } 83 | } 84 | 85 | anchors { 86 | fill: parent 87 | //FIXME: breaks listviews and highlight item 88 | // topMargin: -background.margins.top 89 | // leftMargin: -background.margins.left 90 | // bottomMargin: -background.margins.bottom 91 | // rightMargin: -background.margins.right 92 | } 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /ui/+android/HighlightType.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Daker Fernandes Pinheiro 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU Library General Public License as 6 | * published by the Free Software Foundation; either version 2, or 7 | * (at your option) any later version. 8 | * 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 13 | * 14 | * You should have received a copy of the GNU Library General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.1 21 | import org.kde.plasma.core 2.0 as PlasmaCore 22 | 23 | /** 24 | * Used to highlight an item of a list. to be used only as the "highlight" 25 | * property of the ListView and GridView primitive QML components (or their 26 | * derivates) 27 | * 28 | * Provides built-in animation of Behavior on opacity Easing.OutQuad for a 29 | * duration of 250 (defined in units.longDuration). 30 | * 31 | * (TODO, make optional? e.g. animate: false) 32 | * 33 | * @inherit QtQuick.Item 34 | */ 35 | Item { 36 | id: highlight 37 | 38 | /** true if the user is hovering over the component */ 39 | //in the case we are the highlight of a listview, it follows the mouse, so hover = true 40 | property bool hover: ListView ? true : false 41 | 42 | /** true if the mouse button is pressed over the component. */ 43 | property bool pressed: false 44 | width: ListView.view ? ListView.view.width : undefined 45 | property alias marginHints: background.margins; 46 | 47 | Connections { 48 | target: highlight.ListView.view 49 | onCurrentIndexChanged: { 50 | if (highlight.ListView.view.currentIndex >= 0) { 51 | background.opacity = 1 52 | } else { 53 | background.opacity = 0 54 | } 55 | } 56 | } 57 | 58 | Behavior on opacity { 59 | NumberAnimation { 60 | duration: units.longDuration 61 | easing.type: Easing.OutQuad 62 | } 63 | } 64 | 65 | PlasmaCore.FrameSvgItem { 66 | id: background 67 | imagePath: "widgets/viewitem" 68 | prefix: { 69 | if (pressed) 70 | return hover ? "selected+hover" : "selected"; 71 | 72 | if (hover) 73 | return "hover"; 74 | 75 | return "normal"; 76 | } 77 | 78 | Behavior on opacity { 79 | NumberAnimation { 80 | duration: units.longDuration 81 | easing.type: Easing.OutQuad 82 | } 83 | } 84 | 85 | anchors { 86 | fill: parent 87 | //FIXME: breaks listviews and highlight item 88 | // topMargin: -background.margins.top 89 | // leftMargin: -background.margins.left 90 | // bottomMargin: -background.margins.bottom 91 | // rightMargin: -background.margins.right 92 | } 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /ui/+mediacenter/HighlightType.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Daker Fernandes Pinheiro 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU Library General Public License as 6 | * published by the Free Software Foundation; either version 2, or 7 | * (at your option) any later version. 8 | * 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 13 | * 14 | * You should have received a copy of the GNU Library General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.1 21 | import org.kde.plasma.core 2.0 as PlasmaCore 22 | 23 | /** 24 | * Used to highlight an item of a list. to be used only as the "highlight" 25 | * property of the ListView and GridView primitive QML components (or their 26 | * derivates) 27 | * 28 | * Provides built-in animation of Behavior on opacity Easing.OutQuad for a 29 | * duration of 250 (defined in units.longDuration). 30 | * 31 | * (TODO, make optional? e.g. animate: false) 32 | * 33 | * @inherit QtQuick.Item 34 | */ 35 | Item { 36 | id: highlight 37 | 38 | /** true if the user is hovering over the component */ 39 | //in the case we are the highlight of a listview, it follows the mouse, so hover = true 40 | property bool hover: ListView ? true : false 41 | 42 | /** true if the mouse button is pressed over the component. */ 43 | property bool pressed: false 44 | width: ListView.view ? ListView.view.width : undefined 45 | property alias marginHints: background.margins; 46 | 47 | Connections { 48 | target: highlight.ListView.view 49 | onCurrentIndexChanged: { 50 | if (highlight.ListView.view.currentIndex >= 0) { 51 | background.opacity = 1 52 | } else { 53 | background.opacity = 0 54 | } 55 | } 56 | } 57 | 58 | Behavior on opacity { 59 | NumberAnimation { 60 | duration: units.longDuration 61 | easing.type: Easing.OutQuad 62 | } 63 | } 64 | 65 | PlasmaCore.FrameSvgItem { 66 | id: background 67 | imagePath: "widgets/viewitem" 68 | prefix: { 69 | if (pressed) 70 | return hover ? "selected+hover" : "selected"; 71 | 72 | if (hover) 73 | return "hover"; 74 | 75 | return "normal"; 76 | } 77 | 78 | Behavior on opacity { 79 | NumberAnimation { 80 | duration: units.longDuration 81 | easing.type: Easing.OutQuad 82 | } 83 | } 84 | 85 | anchors { 86 | fill: parent 87 | //FIXME: breaks listviews and highlight item 88 | // topMargin: -background.margins.top 89 | // leftMargin: -background.margins.left 90 | // bottomMargin: -background.margins.bottom 91 | // rightMargin: -background.margins.right 92 | } 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /ui/images/simple-pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ui/images/simple-next.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /ui/images/simple-previous.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /ui/views/BigTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.9 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.kirigami 2.5 as Kirigami 24 | 25 | FocusScope { 26 | id: root 27 | 28 | signal activated 29 | property string title 30 | property alias view: view 31 | property alias delegate: view.delegate 32 | property alias model: view.model 33 | property alias count: view.count 34 | property alias currentIndex: view.currentIndex 35 | property alias currentItem: view.currentItem 36 | Layout.fillWidth: true 37 | implicitHeight: view.implicitHeight + header.implicitHeight 38 | property alias cellWidth: view.cellWidth 39 | property alias cellHeight: view.cellHeight 40 | 41 | property Item navigationUp 42 | property Item navigationDown 43 | 44 | Kirigami.Heading { 45 | id: header 46 | anchors { 47 | left: parent.left 48 | right: parent.right 49 | top: parent.top 50 | leftMargin: Kirigami.Units.largeSpacing * 3 51 | } 52 | text: title 53 | color: "white" 54 | } 55 | 56 | Kirigami.Separator { 57 | z: 2 58 | anchors { 59 | bottom: view.top 60 | left: view.left 61 | right: parent.right 62 | } 63 | height: 1 64 | color: "white" 65 | opacity: 0.4 66 | visible: view.contentY > 0 67 | } 68 | 69 | GridView { 70 | id: view 71 | anchors { 72 | left: parent.left 73 | right: parent.right 74 | top: header.bottom 75 | bottom: parent.bottom 76 | topMargin: Kirigami.Units.largeSpacing * 2 77 | leftMargin: Kirigami.Units.largeSpacing * 2 78 | rightMargin: Kirigami.Units.largeSpacing * 2 79 | } 80 | focus: true 81 | z: activeFocus ? 10: 1 82 | cellWidth: parent.width / 4 83 | cellHeight: parent.height / 1.5 84 | keyNavigationEnabled: true 85 | highlightFollowsCurrentItem: true 86 | snapMode: ListView.SnapToItem 87 | cacheBuffer: width 88 | highlightMoveDuration: Kirigami.Units.longDuration 89 | clip: true 90 | 91 | onCurrentItemChanged: { 92 | positionViewAtIndex(currentIndex, GridView.Center) 93 | } 94 | 95 | move: Transition { 96 | SmoothedAnimation { 97 | property: "x" 98 | duration: Kirigami.Units.longDuration 99 | } 100 | } 101 | 102 | KeyNavigation.left: root 103 | KeyNavigation.right: root 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ui/+android/views/BigTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.9 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.kirigami 2.5 as Kirigami 24 | 25 | FocusScope { 26 | id: root 27 | 28 | signal activated 29 | property string title 30 | property alias view: view 31 | property alias delegate: view.delegate 32 | property alias model: view.model 33 | property alias count: view.count 34 | property alias currentIndex: view.currentIndex 35 | property alias currentItem: view.currentItem 36 | Layout.fillWidth: true 37 | implicitHeight: view.implicitHeight + header.implicitHeight 38 | property alias cellWidth: view.cellWidth 39 | property alias cellHeight: view.cellHeight 40 | 41 | property Item navigationUp 42 | property Item navigationDown 43 | 44 | Kirigami.Heading { 45 | id: header 46 | anchors { 47 | left: parent.left 48 | right: parent.right 49 | top: parent.top 50 | leftMargin: Kirigami.Units.largeSpacing * 3 51 | } 52 | text: title 53 | color: "white" 54 | } 55 | 56 | Kirigami.Separator { 57 | z: 2 58 | anchors { 59 | bottom: view.top 60 | left: view.left 61 | right: parent.right 62 | } 63 | height: 1 64 | color: "white" 65 | opacity: 0.4 66 | visible: view.contentY > 0 67 | } 68 | 69 | GridView { 70 | id: view 71 | anchors { 72 | left: parent.left 73 | right: parent.right 74 | top: header.bottom 75 | bottom: parent.bottom 76 | topMargin: Kirigami.Units.largeSpacing * 2 77 | leftMargin: Kirigami.Units.largeSpacing * 2 78 | rightMargin: Kirigami.Units.largeSpacing * 2 79 | } 80 | focus: true 81 | z: activeFocus ? 10: 1 82 | cellWidth: parent.width / 4 83 | cellHeight: parent.height / 1.5 84 | keyNavigationEnabled: true 85 | highlightFollowsCurrentItem: true 86 | snapMode: ListView.SnapToItem 87 | cacheBuffer: width 88 | highlightMoveDuration: Kirigami.Units.longDuration 89 | clip: true 90 | 91 | onCurrentItemChanged: { 92 | positionViewAtIndex(currentIndex, GridView.Center) 93 | } 94 | 95 | move: Transition { 96 | SmoothedAnimation { 97 | property: "x" 98 | duration: Kirigami.Units.longDuration 99 | } 100 | } 101 | 102 | KeyNavigation.left: root 103 | KeyNavigation.right: root 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ui/+mediacenter/views/BigTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.plasma.components 3.0 as PlasmaComponents 24 | import org.kde.kirigami 2.5 as Kirigami 25 | 26 | 27 | FocusScope { 28 | id: root 29 | signal activated 30 | property string title 31 | property alias view: view 32 | property alias delegate: view.delegate 33 | property alias model: view.model 34 | property alias count: view.count 35 | property alias currentIndex: view.currentIndex 36 | property alias currentItem: view.currentItem 37 | Layout.fillWidth: true 38 | implicitHeight: view.implicitHeight + header.implicitHeight 39 | property alias cellWidth: view.cellWidth 40 | property alias cellHeight: view.cellHeight 41 | 42 | property Item navigationUp 43 | property Item navigationDown 44 | 45 | Kirigami.Heading { 46 | id: header 47 | anchors { 48 | left: parent.left 49 | right: parent.right 50 | top: parent.top 51 | leftMargin: Kirigami.Units.largeSpacing * 3 52 | } 53 | text: title 54 | color: "white" 55 | } 56 | 57 | Kirigami.Separator { 58 | z: 2 59 | anchors { 60 | bottom: view.top 61 | left: view.left 62 | right: parent.right 63 | } 64 | height: 1 65 | color: "white" 66 | opacity: 0.4 67 | visible: view.contentY > 0 68 | } 69 | 70 | GridView { 71 | id: view 72 | anchors { 73 | left: parent.left 74 | right: parent.right 75 | top: header.bottom 76 | bottom: parent.bottom 77 | topMargin: Kirigami.Units.largeSpacing * 2 78 | leftMargin: Kirigami.Units.largeSpacing * 2 79 | rightMargin: Kirigami.Units.largeSpacing * 2 80 | } 81 | focus: true 82 | z: activeFocus ? 10: 1 83 | cellWidth: parent.width / 4 84 | cellHeight: parent.height / 1.5 85 | keyNavigationEnabled: true 86 | highlightFollowsCurrentItem: true 87 | snapMode: ListView.SnapToItem 88 | cacheBuffer: width 89 | highlightMoveDuration: Kirigami.Units.longDuration 90 | clip: true 91 | 92 | onCurrentItemChanged: { 93 | positionViewAtIndex(currentIndex, GridView.Center) 94 | } 95 | 96 | move: Transition { 97 | SmoothedAnimation { 98 | property: "x" 99 | duration: Kirigami.Units.longDuration 100 | } 101 | } 102 | 103 | KeyNavigation.left: root 104 | KeyNavigation.right: root 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /ui/views/BackupListTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.plasma.components 3.0 as PlasmaComponents 24 | import org.kde.kirigami 2.5 as Kirigami 25 | 26 | 27 | ListView { 28 | id: view 29 | property int columns: parent.width >= 1500 ? Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 14))) : 5 30 | 31 | readonly property int cellWidth: width / columns 32 | 33 | Layout.fillWidth: true 34 | Layout.preferredHeight: Kirigami.Units.gridUnit * 15 35 | z: activeFocus ? 10: 1 36 | keyNavigationEnabled: true 37 | highlightFollowsCurrentItem: true 38 | snapMode: ListView.SnapToItem 39 | cacheBuffer: width 40 | 41 | displayMarginBeginning: rotation.angle != 0 ? width*2 : 0 42 | displayMarginEnd: rotation.angle != 0 ? width*2 : 0 43 | highlightMoveDuration: Kirigami.Units.longDuration 44 | transform: Rotation { 45 | id: rotation 46 | axis { x: 0; y: 1; z: 0 } 47 | angle: 0 48 | property real targetAngle: 30 49 | Behavior on angle { 50 | SmoothedAnimation { 51 | duration: Kirigami.Units.longDuration * 10 52 | } 53 | } 54 | origin.x: width/2 55 | } 56 | 57 | Timer { 58 | id: rotateTimeOut 59 | interval: 25 60 | } 61 | Timer { 62 | id: rotateTimer 63 | interval: 500 64 | onTriggered: { 65 | if (rotateTimeOut.running) { 66 | rotation.angle = rotation.targetAngle; 67 | restart(); 68 | } else { 69 | rotation.angle = 0; 70 | } 71 | } 72 | } 73 | spacing: 0 74 | orientation: ListView.Horizontal 75 | 76 | property real oldContentX 77 | onContentXChanged: { 78 | if (oldContentX < contentX) { 79 | rotation.targetAngle = 30; 80 | } else { 81 | rotation.targetAngle = -30; 82 | } 83 | PlasmaComponents.ScrollBar.horizontal.opacity = 1; 84 | if (!rotateTimeOut.running) { 85 | rotateTimer.restart(); 86 | } 87 | rotateTimeOut.restart(); 88 | oldContentX = contentX; 89 | } 90 | 91 | PlasmaComponents.ScrollBar.horizontal: PlasmaComponents.ScrollBar { 92 | id: scrollBar 93 | opacity: 0 94 | interactive: false 95 | onOpacityChanged: disappearTimer.restart() 96 | Timer { 97 | id: disappearTimer 98 | interval: 1000 99 | onTriggered: scrollBar.opacity = 0; 100 | } 101 | Behavior on opacity { 102 | OpacityAnimator { 103 | duration: Kirigami.Units.longDuration 104 | easing.type: Easing.InOutQuad 105 | } 106 | } 107 | } 108 | 109 | move: Transition { 110 | SmoothedAnimation { 111 | property: "x" 112 | duration: Kirigami.Units.longDuration 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ui/+android/views/BackupListTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.plasma.components 3.0 as PlasmaComponents 24 | import org.kde.kirigami 2.5 as Kirigami 25 | 26 | 27 | ListView { 28 | id: view 29 | property int columns: parent.width >= 1500 ? Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 14))) : 5 30 | 31 | readonly property int cellWidth: width / columns 32 | 33 | Layout.fillWidth: true 34 | Layout.preferredHeight: Kirigami.Units.gridUnit * 15 35 | z: activeFocus ? 10: 1 36 | keyNavigationEnabled: true 37 | highlightFollowsCurrentItem: true 38 | snapMode: ListView.SnapToItem 39 | cacheBuffer: width 40 | 41 | displayMarginBeginning: rotation.angle != 0 ? width*2 : 0 42 | displayMarginEnd: rotation.angle != 0 ? width*2 : 0 43 | highlightMoveDuration: Kirigami.Units.longDuration 44 | transform: Rotation { 45 | id: rotation 46 | axis { x: 0; y: 1; z: 0 } 47 | angle: 0 48 | property real targetAngle: 30 49 | Behavior on angle { 50 | SmoothedAnimation { 51 | duration: Kirigami.Units.longDuration * 10 52 | } 53 | } 54 | origin.x: width/2 55 | } 56 | 57 | Timer { 58 | id: rotateTimeOut 59 | interval: 25 60 | } 61 | Timer { 62 | id: rotateTimer 63 | interval: 500 64 | onTriggered: { 65 | if (rotateTimeOut.running) { 66 | rotation.angle = rotation.targetAngle; 67 | restart(); 68 | } else { 69 | rotation.angle = 0; 70 | } 71 | } 72 | } 73 | spacing: 0 74 | orientation: ListView.Horizontal 75 | 76 | property real oldContentX 77 | onContentXChanged: { 78 | if (oldContentX < contentX) { 79 | rotation.targetAngle = 30; 80 | } else { 81 | rotation.targetAngle = -30; 82 | } 83 | PlasmaComponents.ScrollBar.horizontal.opacity = 1; 84 | if (!rotateTimeOut.running) { 85 | rotateTimer.restart(); 86 | } 87 | rotateTimeOut.restart(); 88 | oldContentX = contentX; 89 | } 90 | 91 | PlasmaComponents.ScrollBar.horizontal: PlasmaComponents.ScrollBar { 92 | id: scrollBar 93 | opacity: 0 94 | interactive: false 95 | onOpacityChanged: disappearTimer.restart() 96 | Timer { 97 | id: disappearTimer 98 | interval: 1000 99 | onTriggered: scrollBar.opacity = 0; 100 | } 101 | Behavior on opacity { 102 | OpacityAnimator { 103 | duration: Kirigami.Units.longDuration 104 | easing.type: Easing.InOutQuad 105 | } 106 | } 107 | } 108 | 109 | move: Transition { 110 | SmoothedAnimation { 111 | property: "x" 112 | duration: Kirigami.Units.longDuration 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ui/+mediacenter/views/BackupListTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Controls 2.4 as Controls 23 | import org.kde.plasma.components 3.0 as PlasmaComponents 24 | import org.kde.kirigami 2.5 as Kirigami 25 | 26 | 27 | ListView { 28 | id: view 29 | property int columns: parent.width >= 1500 ? Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 14))) : 5 30 | 31 | readonly property int cellWidth: width / columns 32 | 33 | Layout.fillWidth: true 34 | Layout.preferredHeight: Kirigami.Units.gridUnit * 15 35 | z: activeFocus ? 10: 1 36 | keyNavigationEnabled: true 37 | highlightFollowsCurrentItem: true 38 | snapMode: ListView.SnapToItem 39 | cacheBuffer: width 40 | 41 | displayMarginBeginning: rotation.angle != 0 ? width*2 : 0 42 | displayMarginEnd: rotation.angle != 0 ? width*2 : 0 43 | highlightMoveDuration: Kirigami.Units.longDuration 44 | transform: Rotation { 45 | id: rotation 46 | axis { x: 0; y: 1; z: 0 } 47 | angle: 0 48 | property real targetAngle: 30 49 | Behavior on angle { 50 | SmoothedAnimation { 51 | duration: Kirigami.Units.longDuration * 10 52 | } 53 | } 54 | origin.x: width/2 55 | } 56 | 57 | Timer { 58 | id: rotateTimeOut 59 | interval: 25 60 | } 61 | Timer { 62 | id: rotateTimer 63 | interval: 500 64 | onTriggered: { 65 | if (rotateTimeOut.running) { 66 | rotation.angle = rotation.targetAngle; 67 | restart(); 68 | } else { 69 | rotation.angle = 0; 70 | } 71 | } 72 | } 73 | spacing: 0 74 | orientation: ListView.Horizontal 75 | 76 | property real oldContentX 77 | onContentXChanged: { 78 | if (oldContentX < contentX) { 79 | rotation.targetAngle = 30; 80 | } else { 81 | rotation.targetAngle = -30; 82 | } 83 | PlasmaComponents.ScrollBar.horizontal.opacity = 1; 84 | if (!rotateTimeOut.running) { 85 | rotateTimer.restart(); 86 | } 87 | rotateTimeOut.restart(); 88 | oldContentX = contentX; 89 | } 90 | 91 | PlasmaComponents.ScrollBar.horizontal: PlasmaComponents.ScrollBar { 92 | id: scrollBar 93 | opacity: 0 94 | interactive: false 95 | onOpacityChanged: disappearTimer.restart() 96 | Timer { 97 | id: disappearTimer 98 | interval: 1000 99 | onTriggered: scrollBar.opacity = 0; 100 | } 101 | Behavior on opacity { 102 | OpacityAnimator { 103 | duration: Kirigami.Units.longDuration 104 | easing.type: Easing.InOutQuad 105 | } 106 | } 107 | } 108 | 109 | move: Transition { 110 | SmoothedAnimation { 111 | property: "x" 112 | duration: Kirigami.Units.longDuration 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ui/images/simple-audio-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 93 | 100 | 109 | 119 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /ui/images/simple-audio-on.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 93 | 100 | 109 | 118 | 127 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /ui/CategoryBoxView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import org.kde.plasma.core 2.0 as PlasmaCore 24 | import org.kde.plasma.components 3.0 as PlasmaComponents3 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | import "+mediacenter/views" as Views 28 | import "+mediacenter/delegates" as Delegates 29 | 30 | Item { 31 | property alias model: videoListView.model 32 | Layout.fillWidth: true 33 | Layout.fillHeight: true 34 | 35 | onFocusChanged: { 36 | if(focus){ 37 | console.log("here in focus") 38 | videoListView.forceActiveFocus() 39 | } 40 | } 41 | 42 | Views.TileView { 43 | id: videoListView 44 | focus: true 45 | clip: true 46 | anchors.top: parent.top 47 | anchors.left: parent.left 48 | anchors.right: parent.right 49 | anchors.bottom: controlAreaButtons.top 50 | property string currentVideoTitle 51 | property string currentVideoId 52 | delegate: Delegates.VideoCard{} 53 | 54 | KeyNavigation.up: videoQueryBox 55 | KeyNavigation.down: nextPageAvailable ? nextButton : previousButton 56 | 57 | Keys.onReturnPressed: { 58 | busyIndicatorPop.open() 59 | if(focus){ 60 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: currentVideoId, vidTitle: currentVideoTitle}) 61 | } 62 | } 63 | 64 | onCurrentItemChanged: { 65 | currentVideoId = videoListView.currentItem.videoID 66 | currentVideoTitle = videoListView.currentItem.videoTitle 67 | console.log(videoListView.currentItem.videoTitle) 68 | } 69 | } 70 | 71 | RowLayout { 72 | id: controlAreaButtons 73 | anchors.bottom: parent.bottom 74 | anchors.left: parent.left 75 | anchors.right: parent.right 76 | height: Kirigami.Units.gridUnit * 4 77 | 78 | Button { 79 | id: previousButton 80 | text: "Previous Page" 81 | Layout.preferredWidth: nextButton.visible ? parent.width / 2 : parent.width 82 | Layout.fillHeight: true 83 | icon.name: "go-previous-symbolic" 84 | enabled: nextPageAvailable ? 0 : 1 85 | visible: nextPageAvailable ? 0 : 1 86 | 87 | background: Rectangle { 88 | color: previousButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor 89 | } 90 | 91 | onClicked: { 92 | triggerGuiEvent("YoutubeSkill.PreviousPage", {"Category": categoryName}) 93 | } 94 | 95 | Keys.onReturnPressed: { 96 | triggerGuiEvent("YoutubeSkill.PreviousPage", {"Category": categoryName}) 97 | } 98 | 99 | KeyNavigation.up: videoListView 100 | } 101 | 102 | Button { 103 | id: nextButton 104 | text: "Next Page" 105 | enabled: nextPageAvailable ? 1 : 0 106 | visible: nextPageAvailable ? 1 : 0 107 | Layout.preferredWidth: previousButton.visible ? parent.width / 2 : parent.width 108 | Layout.fillHeight: true 109 | icon.name: "go-next-symbolic" 110 | 111 | background: Rectangle { 112 | color: nextButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor 113 | } 114 | 115 | onClicked: { 116 | triggerGuiEvent("YoutubeSkill.NextPage", {"Category": categoryName}) 117 | } 118 | 119 | Keys.onReturnPressed: { 120 | triggerGuiEvent("YoutubeSkill.NextPage", {"Category": categoryName}) 121 | } 122 | 123 | KeyNavigation.up: videoListView 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /ui/CategoryBoxSearchView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import Mycroft 1.0 as Mycroft 24 | import "+android/views" as Views 25 | import "+android/delegates" as Delegates 26 | 27 | Item { 28 | property var searchListModel: sessionData.searchListBlob.videoList 29 | Layout.fillWidth: true 30 | Layout.fillHeight: true 31 | 32 | onFocusChanged: { 33 | if(focus){ 34 | searchBarArea.forceActiveFocus() 35 | } 36 | } 37 | 38 | function searchYoutubeLiveResults(query){ 39 | triggerGuiEvent("YoutubeSkill.SearchLive", {"Query": query}) 40 | } 41 | 42 | Rectangle { 43 | id: searchBarArea 44 | anchors.top: parent.top 45 | anchors.topMargin: Kirigami.Units.largeSpacing 46 | height: Kirigami.Units.gridUnit * 3 47 | anchors.left: parent.left 48 | anchors.right: parent.right 49 | anchors.leftMargin: Kirigami.Units.gridUnit 50 | anchors.rightMargin: Kirigami.Units.gridUnit 51 | radius: 12 52 | color: searchBarArea.activeFocus ? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.95) : Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) 53 | 54 | Keys.onReturnPressed: { 55 | videoQueryBox.forceActiveFocus() 56 | } 57 | 58 | KeyNavigation.up: searchCatButton 59 | KeyNavigation.down: searchGridView 60 | 61 | RowLayout { 62 | anchors.fill: parent 63 | TextField { 64 | id: videoQueryBox 65 | Layout.leftMargin: Kirigami.Units.largeSpacing 66 | Layout.fillWidth: true 67 | placeholderText: "Search here..." 68 | Layout.fillHeight: true 69 | onAccepted: { 70 | searchYoutubeLiveResults(videoQueryBox.text) 71 | } 72 | KeyNavigation.down: searchGridView 73 | KeyNavigation.right: searchVideoQuery 74 | } 75 | 76 | Kirigami.Icon { 77 | id: searchVideoQuery 78 | Layout.preferredWidth: Kirigami.Units.gridUnit * 2 79 | Layout.fillHeight: true 80 | source: "search" 81 | KeyNavigation.left: videoQueryBox 82 | KeyNavigation.down: searchGridView 83 | 84 | Keys.onReturnPressed: { 85 | searchYoutubeLiveResults(videoQueryBox.text) 86 | } 87 | 88 | MouseArea { 89 | anchors.fill: parent 90 | onClicked: { 91 | searchYoutubeLiveResults(videoQueryBox.text) 92 | } 93 | } 94 | 95 | ColorOverlay { 96 | anchors.fill: parent 97 | source: searchVideoQuery 98 | color: Kirigami.Theme.highlightColor 99 | visible: searchVideoQuery.activeFocus ? 1 : 0 100 | } 101 | } 102 | } 103 | } 104 | 105 | Views.BigTileView { 106 | id: searchGridView 107 | anchors { 108 | top: searchBarArea.bottom 109 | left: parent.left 110 | right: parent.right 111 | bottom: parent.bottom 112 | topMargin: Kirigami.Units.largeSpacing 113 | } 114 | focus: true 115 | model: searchListModel 116 | Layout.fillWidth: true 117 | Layout.fillHeight: true 118 | cellWidth: view.width / 4 119 | // FIXME: componentize more all this stuff 120 | cellHeight: cellWidth / 1.8 + Kirigami.Units.gridUnit * 5 121 | title: count > 0 ? "Search Results" : " " 122 | delegate: Delegates.ListVideoCard { 123 | width: searchGridView.cellWidth 124 | height: searchGridView.cellHeight 125 | } 126 | 127 | KeyNavigation.up: searchBarArea 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /ui/+android/CategoryBoxSearchView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import Mycroft 1.0 as Mycroft 24 | import "+android/views" as Views 25 | import "+android/delegates" as Delegates 26 | 27 | Item { 28 | property var searchListModel: sessionData.searchListBlob.videoList 29 | Layout.fillWidth: true 30 | Layout.fillHeight: true 31 | 32 | onFocusChanged: { 33 | if(focus){ 34 | searchBarArea.forceActiveFocus() 35 | } 36 | } 37 | 38 | function searchYoutubeLiveResults(query){ 39 | triggerGuiEvent("YoutubeSkill.SearchLive", {"Query": query}) 40 | } 41 | 42 | Rectangle { 43 | id: searchBarArea 44 | anchors.top: parent.top 45 | anchors.topMargin: Kirigami.Units.largeSpacing 46 | height: Kirigami.Units.gridUnit * 3 47 | anchors.left: parent.left 48 | anchors.right: parent.right 49 | anchors.leftMargin: Kirigami.Units.gridUnit 50 | anchors.rightMargin: Kirigami.Units.gridUnit 51 | radius: 12 52 | color: searchBarArea.activeFocus ? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.95) : Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) 53 | 54 | Keys.onReturnPressed: { 55 | videoQueryBox.forceActiveFocus() 56 | } 57 | 58 | KeyNavigation.up: searchCatButton 59 | KeyNavigation.down: searchGridView 60 | 61 | RowLayout { 62 | anchors.fill: parent 63 | TextField { 64 | id: videoQueryBox 65 | Layout.leftMargin: Kirigami.Units.largeSpacing 66 | Layout.fillWidth: true 67 | placeholderText: "Search here..." 68 | Layout.fillHeight: true 69 | onAccepted: { 70 | searchYoutubeLiveResults(videoQueryBox.text) 71 | } 72 | KeyNavigation.down: searchGridView 73 | KeyNavigation.right: searchVideoQuery 74 | } 75 | 76 | Kirigami.Icon { 77 | id: searchVideoQuery 78 | Layout.preferredWidth: Kirigami.Units.gridUnit * 2 79 | Layout.fillHeight: true 80 | source: "search" 81 | KeyNavigation.left: videoQueryBox 82 | KeyNavigation.down: searchGridView 83 | 84 | Keys.onReturnPressed: { 85 | searchYoutubeLiveResults(videoQueryBox.text) 86 | } 87 | 88 | MouseArea { 89 | anchors.fill: parent 90 | onClicked: { 91 | searchYoutubeLiveResults(videoQueryBox.text) 92 | } 93 | } 94 | 95 | ColorOverlay { 96 | anchors.fill: parent 97 | source: searchVideoQuery 98 | color: Kirigami.Theme.highlightColor 99 | visible: searchVideoQuery.activeFocus ? 1 : 0 100 | } 101 | } 102 | } 103 | } 104 | 105 | Views.BigTileView { 106 | id: searchGridView 107 | anchors { 108 | top: searchBarArea.bottom 109 | left: parent.left 110 | right: parent.right 111 | bottom: parent.bottom 112 | topMargin: Kirigami.Units.largeSpacing 113 | } 114 | focus: true 115 | model: searchListModel 116 | Layout.fillWidth: true 117 | Layout.fillHeight: true 118 | cellWidth: view.width / 4 119 | // FIXME: componentize more all this stuff 120 | cellHeight: cellWidth / 1.8 + Kirigami.Units.gridUnit * 5 121 | title: count > 0 ? "Search Results" : " " 122 | delegate: Delegates.ListVideoCard { 123 | width: searchGridView.cellWidth 124 | height: searchGridView.cellHeight 125 | } 126 | 127 | KeyNavigation.up: searchBarArea 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /ui/images/simple-fullscreen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 104 | 111 | 118 | 126 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /ui/+mediacenter/CategoryBoxSearchView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import org.kde.plasma.core 2.0 as PlasmaCore 24 | import org.kde.plasma.components 3.0 as PlasmaComponents3 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | import "+mediacenter/views" as Views 28 | import "+mediacenter/delegates" as Delegates 29 | 30 | Item { 31 | property var searchListModel: sessionData.searchListBlob.videoList 32 | Layout.fillWidth: true 33 | Layout.fillHeight: true 34 | 35 | onFocusChanged: { 36 | if(focus){ 37 | searchBarArea.forceActiveFocus() 38 | } 39 | } 40 | 41 | function searchYoutubeLiveResults(query){ 42 | triggerGuiEvent("YoutubeSkill.SearchLive", {"Query": query}) 43 | } 44 | 45 | Rectangle { 46 | id: searchBarArea 47 | anchors.top: parent.top 48 | anchors.topMargin: Kirigami.Units.largeSpacing 49 | anchors.horizontalCenter: parent.horizontalCenter 50 | height: Kirigami.Units.gridUnit * 3 51 | width: parent.width / 3 52 | radius: 12 53 | color: searchBarArea.activeFocus ? Qt.rgba(Kirigami.Theme.highlightColor.r, Kirigami.Theme.highlightColor.g, Kirigami.Theme.highlightColor.b, 0.95) : Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) 54 | 55 | Keys.onReturnPressed: { 56 | videoQueryBox.forceActiveFocus() 57 | } 58 | 59 | KeyNavigation.up: searchCatButton 60 | KeyNavigation.down: searchGridView 61 | 62 | RowLayout { 63 | anchors.fill: parent 64 | TextField { 65 | id: videoQueryBox 66 | Layout.leftMargin: Kirigami.Units.largeSpacing 67 | Layout.fillWidth: true 68 | placeholderText: "Search here..." 69 | Layout.fillHeight: true 70 | onAccepted: { 71 | searchYoutubeLiveResults(videoQueryBox.text) 72 | } 73 | KeyNavigation.down: searchGridView 74 | KeyNavigation.right: searchVideoQuery 75 | } 76 | 77 | Kirigami.Icon { 78 | id: searchVideoQuery 79 | Layout.preferredWidth: Kirigami.Units.gridUnit * 2 80 | Layout.fillHeight: true 81 | source: "search" 82 | KeyNavigation.left: videoQueryBox 83 | KeyNavigation.down: searchGridView 84 | 85 | Keys.onReturnPressed: { 86 | searchYoutubeLiveResults(videoQueryBox.text) 87 | } 88 | 89 | MouseArea { 90 | anchors.fill: parent 91 | onClicked: { 92 | searchYoutubeLiveResults(videoQueryBox.text) 93 | } 94 | } 95 | 96 | ColorOverlay { 97 | anchors.fill: parent 98 | source: searchVideoQuery 99 | color: Kirigami.Theme.highlightColor 100 | visible: searchVideoQuery.activeFocus ? 1 : 0 101 | } 102 | } 103 | } 104 | } 105 | 106 | Views.BigTileView { 107 | id: searchGridView 108 | anchors { 109 | top: searchBarArea.bottom 110 | left: parent.left 111 | right: parent.right 112 | bottom: parent.bottom 113 | topMargin: Kirigami.Units.largeSpacing 114 | } 115 | focus: true 116 | model: searchListModel 117 | Layout.fillWidth: true 118 | Layout.fillHeight: true 119 | cellWidth: view.width / 4 120 | // FIXME: componentize more all this stuff 121 | cellHeight: cellWidth / 1.8 + Kirigami.Units.gridUnit * 5 122 | title: count > 0 ? "Search Results" : " " 123 | delegate: Delegates.ListVideoCard { 124 | width: searchGridView.cellWidth 125 | height: searchGridView.cellHeight 126 | } 127 | 128 | KeyNavigation.up: searchBarArea 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /ui/YoutubeSearch.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * Copyright 2018 Marco Martin 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import QtQuick 2.9 20 | import QtQuick.Layouts 1.4 21 | import QtGraphicalEffects 1.0 22 | import QtQuick.Controls 2.2 23 | import org.kde.kirigami 2.8 as Kirigami 24 | import org.kde.plasma.core 2.0 as PlasmaCore 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | 28 | Mycroft.Delegate { 29 | id: delegate 30 | 31 | property var videoListModel: sessionData.videoListBlob.videoList 32 | property var currentSongUrl: sessionData.currenturl 33 | property var currenttitle: sessionData.currenttitle 34 | property Component highlighter: PlasmaComponents.Highlight{} 35 | property Component emptyHighlighter: Item{} 36 | 37 | skillBackgroundSource: "https://source.unsplash.com/weekly?music" 38 | 39 | onVideoListModelChanged: { 40 | leftSearchView.forceLayout() 41 | } 42 | 43 | Keys.onBackPressed: { 44 | parent.parent.parent.currentIndex-- 45 | parent.parent.parent.currentItem.contentItem.forceActiveFocus() 46 | } 47 | 48 | ColumnLayout { 49 | id: recentlyPlayerColumn 50 | anchors.fill: parent 51 | spacing: Kirigami.Units.smallSpacing 52 | 53 | Kirigami.Heading { 54 | id: watchItemList 55 | text: "Watch More.." 56 | level: 3 57 | } 58 | 59 | Kirigami.Separator { 60 | id: sept2 61 | Layout.fillWidth: true 62 | Layout.preferredHeight: 1 63 | z: 100 64 | } 65 | 66 | ListView { 67 | id: leftSearchView 68 | keyNavigationEnabled: true 69 | highlight: focus ? highlighter : emptyHighlighter 70 | model: videoListModel 71 | focus: false 72 | interactive: true 73 | bottomMargin: delegate.controlBarItem.height + Kirigami.Units.largeSpacing 74 | Layout.fillWidth: true 75 | Layout.fillHeight: true 76 | spacing: Kirigami.Units.largeSpacing 77 | currentIndex: 0 78 | highlightRangeMode: ListView.StrictlyEnforceRange 79 | snapMode: ListView.SnapToItem 80 | 81 | delegate: Control { 82 | width: parent.width 83 | height: Kirigami.Units.gridUnit * 4 84 | 85 | background: PlasmaCore.FrameSvgItem { 86 | id: frame 87 | anchors { 88 | fill: parent 89 | } 90 | imagePath: "widgets/background" 91 | 92 | width: parent.width 93 | height: parent.height 94 | opacity: 0.9 95 | } 96 | 97 | 98 | contentItem: Item { 99 | width: parent.width 100 | height: parent.height 101 | 102 | RowLayout { 103 | id: delegateItem 104 | anchors.fill: parent 105 | anchors.margins: Kirigami.Units.smallSpacing 106 | spacing: Kirigami.Units.largeSpacing 107 | 108 | Image { 109 | id: videoImage 110 | source: modelData.videoImage 111 | Layout.preferredHeight: parent.height 112 | Layout.preferredWidth: Kirigami.Units.gridUnit * 4 113 | Layout.alignment: Qt.AlignHCenter 114 | fillMode: Image.Stretch 115 | } 116 | 117 | Label { 118 | id: videoLabel 119 | Layout.fillWidth: true 120 | text: modelData.videoTitle 121 | wrapMode: Text.WordWrap 122 | } 123 | } 124 | } 125 | 126 | Keys.onReturnPressed: { 127 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: modelData.videoID, vidTitle: modelData.videoTitle}) 128 | } 129 | } 130 | } 131 | } 132 | 133 | Component.onCompleted: { 134 | leftSearchView.forceActiveFocus() 135 | } 136 | } 137 | 138 | -------------------------------------------------------------------------------- /ui/+android/CategoryBoxView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import org.kde.plasma.core 2.0 as PlasmaCore 24 | import org.kde.plasma.components 3.0 as PlasmaComponents3 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | import "+mediacenter/views" as Views 28 | import "+mediacenter/delegates" as Delegates 29 | 30 | Item { 31 | property alias model: videoListView.model 32 | Layout.fillWidth: true 33 | Layout.fillHeight: true 34 | 35 | onFocusChanged: { 36 | if(focus){ 37 | console.log("here in focus") 38 | videoListView.forceActiveFocus() 39 | } 40 | } 41 | 42 | Views.TileView { 43 | id: videoListView 44 | focus: true 45 | clip: true 46 | anchors.top: parent.top 47 | anchors.left: parent.left 48 | anchors.right: parent.right 49 | anchors.bottom: controlAreaButtons.top 50 | property string currentVideoTitle 51 | property string currentVideoId 52 | delegate: Delegates.VideoCard{} 53 | 54 | KeyNavigation.up: videoQueryBox 55 | KeyNavigation.down: nextPageAvailable ? nextButton : previousButton 56 | 57 | Keys.onReturnPressed: { 58 | busyIndicatorPop.open() 59 | if(focus){ 60 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: currentVideoId, vidTitle: currentVideoTitle}) 61 | } 62 | } 63 | 64 | onCurrentItemChanged: { 65 | currentVideoId = videoListView.currentItem.videoID 66 | currentVideoTitle = videoListView.currentItem.videoTitle 67 | console.log(videoListView.currentItem.videoTitle) 68 | } 69 | } 70 | 71 | RowLayout { 72 | id: controlAreaButtons 73 | anchors.bottom: parent.bottom 74 | anchors.left: parent.left 75 | anchors.right: parent.right 76 | height: Kirigami.Units.gridUnit * 2.5 77 | 78 | Button { 79 | id: previousButton 80 | text: "Previous Page" 81 | Layout.preferredWidth: nextButton.visible ? parent.width / 2 : parent.width 82 | Layout.fillHeight: true 83 | icon.name: "go-previous-symbolic" 84 | enabled: nextPageAvailable ? 0 : 1 85 | visible: nextPageAvailable ? 0 : 1 86 | 87 | background: Rectangle { 88 | color: previousButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor 89 | } 90 | 91 | onClicked: { 92 | triggerGuiEvent("YoutubeSkill.PreviousPage", {"Category": categoryName}) 93 | busyIndicatorPop.open() 94 | nextButton.forceActiveFocus() 95 | } 96 | 97 | Keys.onReturnPressed: { 98 | triggerGuiEvent("YoutubeSkill.PreviousPage", {"Category": categoryName}) 99 | busyIndicatorPop.open() 100 | nextButton.forceActiveFocus() 101 | } 102 | 103 | KeyNavigation.up: videoListView 104 | } 105 | 106 | Button { 107 | id: nextButton 108 | text: "Next Page" 109 | enabled: nextPageAvailable ? 1 : 0 110 | visible: nextPageAvailable ? 1 : 0 111 | Layout.preferredWidth: previousButton.visible ? parent.width / 2 : parent.width 112 | Layout.fillHeight: true 113 | icon.name: "go-next-symbolic" 114 | 115 | background: Rectangle { 116 | color: nextButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor 117 | } 118 | 119 | onClicked: { 120 | triggerGuiEvent("YoutubeSkill.NextPage", {"Category": categoryName}) 121 | busyIndicatorPop.open() 122 | previousButton.forceActiveFocus() 123 | } 124 | 125 | Keys.onReturnPressed: { 126 | triggerGuiEvent("YoutubeSkill.NextPage", {"Category": categoryName}) 127 | busyIndicatorPop.open() 128 | previousButton.forceActiveFocus() 129 | } 130 | 131 | KeyNavigation.up: videoListView 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /ui/+mediacenter/CategoryBoxView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * 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 3 of the License, or 7 | * (at your option) any later version. 8 | 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. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | import QtQuick 2.9 19 | import QtQuick.Layouts 1.4 20 | import QtGraphicalEffects 1.0 21 | import QtQuick.Controls 2.3 22 | import org.kde.kirigami 2.8 as Kirigami 23 | import org.kde.plasma.core 2.0 as PlasmaCore 24 | import org.kde.plasma.components 3.0 as PlasmaComponents3 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | import "+mediacenter/views" as Views 28 | import "+mediacenter/delegates" as Delegates 29 | 30 | Item { 31 | property alias model: videoListView.model 32 | Layout.fillWidth: true 33 | Layout.fillHeight: true 34 | 35 | onFocusChanged: { 36 | if(focus){ 37 | console.log("here in focus") 38 | videoListView.forceActiveFocus() 39 | } 40 | } 41 | 42 | Views.TileView { 43 | id: videoListView 44 | focus: true 45 | clip: true 46 | anchors.top: parent.top 47 | anchors.left: parent.left 48 | anchors.right: parent.right 49 | anchors.bottom: controlAreaButtons.top 50 | property string currentVideoTitle 51 | property string currentVideoId 52 | delegate: Delegates.VideoCard{} 53 | 54 | KeyNavigation.up: videoQueryBox 55 | KeyNavigation.down: nextPageAvailable ? nextButton : previousButton 56 | 57 | Keys.onReturnPressed: { 58 | busyIndicatorPop.open() 59 | if(focus){ 60 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: currentVideoId, vidTitle: currentVideoTitle}) 61 | } 62 | } 63 | 64 | onCurrentItemChanged: { 65 | currentVideoId = videoListView.currentItem.videoID 66 | currentVideoTitle = videoListView.currentItem.videoTitle 67 | console.log(videoListView.currentItem.videoTitle) 68 | } 69 | } 70 | 71 | RowLayout { 72 | id: controlAreaButtons 73 | anchors.bottom: parent.bottom 74 | anchors.left: parent.left 75 | anchors.right: parent.right 76 | height: Kirigami.Units.gridUnit * 2.5 77 | 78 | Button { 79 | id: previousButton 80 | text: "Previous Page" 81 | Layout.preferredWidth: nextButton.visible ? parent.width / 2 : parent.width 82 | Layout.fillHeight: true 83 | icon.name: "go-previous-symbolic" 84 | enabled: nextPageAvailable ? 0 : 1 85 | visible: nextPageAvailable ? 0 : 1 86 | 87 | background: Rectangle { 88 | color: previousButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor 89 | } 90 | 91 | onClicked: { 92 | triggerGuiEvent("YoutubeSkill.PreviousPage", {"Category": categoryName}) 93 | busyIndicatorPop.open() 94 | nextButton.forceActiveFocus() 95 | } 96 | 97 | Keys.onReturnPressed: { 98 | triggerGuiEvent("YoutubeSkill.PreviousPage", {"Category": categoryName}) 99 | busyIndicatorPop.open() 100 | nextButton.forceActiveFocus() 101 | } 102 | 103 | KeyNavigation.up: videoListView 104 | } 105 | 106 | Button { 107 | id: nextButton 108 | text: "Next Page" 109 | enabled: nextPageAvailable ? 1 : 0 110 | visible: nextPageAvailable ? 1 : 0 111 | Layout.preferredWidth: previousButton.visible ? parent.width / 2 : parent.width 112 | Layout.fillHeight: true 113 | icon.name: "go-next-symbolic" 114 | 115 | background: Rectangle { 116 | color: nextButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor 117 | } 118 | 119 | onClicked: { 120 | triggerGuiEvent("YoutubeSkill.NextPage", {"Category": categoryName}) 121 | busyIndicatorPop.open() 122 | previousButton.forceActiveFocus() 123 | } 124 | 125 | Keys.onReturnPressed: { 126 | triggerGuiEvent("YoutubeSkill.NextPage", {"Category": categoryName}) 127 | busyIndicatorPop.open() 128 | previousButton.forceActiveFocus() 129 | } 130 | 131 | KeyNavigation.up: videoListView 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /ui/views/ListTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Window 2.2 23 | import QtQuick.Controls 2.4 as Controls 24 | import QtGraphicalEffects 1.12 25 | 26 | import org.kde.plasma.core 2.0 as PlasmaCore 27 | import org.kde.plasma.components 3.0 as PlasmaComponents 28 | import org.kde.kirigami 2.5 as Kirigami 29 | 30 | FocusScope { 31 | id: root 32 | signal activated 33 | property string title 34 | property alias view: view 35 | property alias delegate: view.delegate 36 | property alias model: view.model 37 | property alias currentIndex: view.currentIndex 38 | property alias currentItem: view.currentItem 39 | Layout.fillWidth: true 40 | 41 | implicitHeight: view.implicitHeight + header.implicitHeight 42 | property int columns: parent.width >= 1500 ? Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 14))) : 5 43 | property alias cellWidth: view.cellWidth 44 | 45 | property Item navigationUp 46 | property Item navigationDown 47 | 48 | Kirigami.Heading { 49 | id: header 50 | anchors { 51 | left: parent.left 52 | right: parent.right 53 | top: parent.top 54 | } 55 | text: title 56 | layer.enabled: true 57 | color: "white" 58 | } 59 | 60 | ListView { 61 | id: view 62 | anchors { 63 | left: parent.left 64 | right: parent.right 65 | top: header.baseline 66 | bottom: parent.bottom 67 | topMargin: Kirigami.Units.largeSpacing*2 68 | leftMargin: -Kirigami.Units.largeSpacing 69 | } 70 | focus: true 71 | 72 | z: activeFocus ? 10: 1 73 | keyNavigationEnabled: true 74 | //Centering disabled as experiment 75 | highlightRangeMode: ListView.ApplyRange 76 | 77 | highlightFollowsCurrentItem: true 78 | snapMode: ListView.SnapToItem 79 | cacheBuffer: width 80 | implicitHeight: cellWidth + Kirigami.Units.gridUnit * 3 81 | rightMargin: width-cellWidth*3 82 | readonly property int cellWidth: parent.width / 6 83 | preferredHighlightBegin: cellWidth 84 | preferredHighlightEnd: cellWidth 85 | displayMarginBeginning: cellWidth 86 | displayMarginEnd: cellWidth 87 | 88 | highlightMoveVelocity: -1 89 | highlightMoveDuration: Kirigami.Units.longDuration 90 | 91 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 92 | 93 | onMovementEnded: flickEnded() 94 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 95 | 96 | spacing: 0 97 | orientation: ListView.Horizontal 98 | 99 | move: Transition { 100 | SmoothedAnimation { 101 | property: "x" 102 | duration: Kirigami.Units.longDuration 103 | } 104 | } 105 | 106 | KeyNavigation.left: root 107 | KeyNavigation.right: root 108 | 109 | Keys.onDownPressed: { 110 | if (!navigationDown) { 111 | return; 112 | } 113 | 114 | if (navigationDown instanceof TileView) { 115 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 116 | 117 | if (navigationDown.currentIndex < 0) { 118 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 119 | } 120 | } 121 | 122 | navigationDown.forceActiveFocus(); 123 | } 124 | 125 | Keys.onUpPressed: { 126 | if (!navigationUp) { 127 | return; 128 | } 129 | 130 | if (navigationUp instanceof TileView) { 131 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 132 | 133 | if (navigationUp.currentIndex < 0) { 134 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 135 | } 136 | } 137 | 138 | navigationUp.forceActiveFocus(); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /ui/+android/views/ListTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Window 2.2 23 | import QtQuick.Controls 2.4 as Controls 24 | import QtGraphicalEffects 1.12 25 | 26 | import org.kde.plasma.core 2.0 as PlasmaCore 27 | import org.kde.plasma.components 3.0 as PlasmaComponents 28 | import org.kde.kirigami 2.5 as Kirigami 29 | 30 | FocusScope { 31 | id: root 32 | signal activated 33 | property string title 34 | property alias view: view 35 | property alias delegate: view.delegate 36 | property alias model: view.model 37 | property alias currentIndex: view.currentIndex 38 | property alias currentItem: view.currentItem 39 | Layout.fillWidth: true 40 | 41 | implicitHeight: view.implicitHeight + header.implicitHeight 42 | property int columns: parent.width >= 1500 ? Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 14))) : 5 43 | property alias cellWidth: view.cellWidth 44 | 45 | property Item navigationUp 46 | property Item navigationDown 47 | 48 | Kirigami.Heading { 49 | id: header 50 | anchors { 51 | left: parent.left 52 | right: parent.right 53 | top: parent.top 54 | } 55 | text: title 56 | layer.enabled: true 57 | color: "white" 58 | } 59 | 60 | ListView { 61 | id: view 62 | anchors { 63 | left: parent.left 64 | right: parent.right 65 | top: header.baseline 66 | bottom: parent.bottom 67 | topMargin: Kirigami.Units.largeSpacing*2 68 | leftMargin: -Kirigami.Units.largeSpacing 69 | } 70 | focus: true 71 | 72 | z: activeFocus ? 10: 1 73 | keyNavigationEnabled: true 74 | //Centering disabled as experiment 75 | highlightRangeMode: ListView.ApplyRange 76 | 77 | highlightFollowsCurrentItem: true 78 | snapMode: ListView.SnapToItem 79 | cacheBuffer: width 80 | implicitHeight: cellWidth + Kirigami.Units.gridUnit * 3 81 | rightMargin: width-cellWidth*3 82 | readonly property int cellWidth: parent.width / 6 83 | preferredHighlightBegin: cellWidth 84 | preferredHighlightEnd: cellWidth 85 | displayMarginBeginning: cellWidth 86 | displayMarginEnd: cellWidth 87 | 88 | highlightMoveVelocity: -1 89 | highlightMoveDuration: Kirigami.Units.longDuration 90 | 91 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 92 | 93 | onMovementEnded: flickEnded() 94 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 95 | 96 | spacing: 0 97 | orientation: ListView.Horizontal 98 | 99 | move: Transition { 100 | SmoothedAnimation { 101 | property: "x" 102 | duration: Kirigami.Units.longDuration 103 | } 104 | } 105 | 106 | KeyNavigation.left: root 107 | KeyNavigation.right: root 108 | 109 | Keys.onDownPressed: { 110 | if (!navigationDown) { 111 | return; 112 | } 113 | 114 | if (navigationDown instanceof TileView) { 115 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 116 | 117 | if (navigationDown.currentIndex < 0) { 118 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 119 | } 120 | } 121 | 122 | navigationDown.forceActiveFocus(); 123 | } 124 | 125 | Keys.onUpPressed: { 126 | if (!navigationUp) { 127 | return; 128 | } 129 | 130 | if (navigationUp instanceof TileView) { 131 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 132 | 133 | if (navigationUp.currentIndex < 0) { 134 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 135 | } 136 | } 137 | 138 | navigationUp.forceActiveFocus(); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /ui/+mediacenter/views/ListTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Window 2.2 23 | import QtQuick.Controls 2.4 as Controls 24 | import QtGraphicalEffects 1.12 25 | 26 | import org.kde.plasma.core 2.0 as PlasmaCore 27 | import org.kde.plasma.components 3.0 as PlasmaComponents 28 | import org.kde.kirigami 2.5 as Kirigami 29 | 30 | FocusScope { 31 | id: root 32 | signal activated 33 | property string title 34 | property alias view: view 35 | property alias delegate: view.delegate 36 | property alias model: view.model 37 | property alias currentIndex: view.currentIndex 38 | property alias currentItem: view.currentItem 39 | Layout.fillWidth: true 40 | 41 | implicitHeight: view.implicitHeight + header.implicitHeight 42 | property int columns: parent.width >= 1500 ? Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 14))) : 5 43 | property alias cellWidth: view.cellWidth 44 | 45 | property Item navigationUp 46 | property Item navigationDown 47 | 48 | Kirigami.Heading { 49 | id: header 50 | anchors { 51 | left: parent.left 52 | right: parent.right 53 | top: parent.top 54 | } 55 | text: title 56 | layer.enabled: true 57 | color: "white" 58 | } 59 | 60 | ListView { 61 | id: view 62 | anchors { 63 | left: parent.left 64 | right: parent.right 65 | top: header.baseline 66 | bottom: parent.bottom 67 | topMargin: Kirigami.Units.largeSpacing*2 68 | leftMargin: -Kirigami.Units.largeSpacing 69 | } 70 | focus: true 71 | 72 | z: activeFocus ? 10: 1 73 | keyNavigationEnabled: true 74 | //Centering disabled as experiment 75 | highlightRangeMode: ListView.ApplyRange 76 | 77 | highlightFollowsCurrentItem: true 78 | snapMode: ListView.SnapToItem 79 | cacheBuffer: width 80 | implicitHeight: cellWidth + Kirigami.Units.gridUnit * 3 81 | rightMargin: width-cellWidth*3 82 | readonly property int cellWidth: parent.width / 6 83 | preferredHighlightBegin: cellWidth 84 | preferredHighlightEnd: cellWidth 85 | displayMarginBeginning: cellWidth 86 | displayMarginEnd: cellWidth 87 | 88 | highlightMoveVelocity: -1 89 | highlightMoveDuration: Kirigami.Units.longDuration 90 | 91 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 92 | 93 | onMovementEnded: flickEnded() 94 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 95 | 96 | spacing: 0 97 | orientation: ListView.Horizontal 98 | 99 | move: Transition { 100 | SmoothedAnimation { 101 | property: "x" 102 | duration: Kirigami.Units.longDuration 103 | } 104 | } 105 | 106 | KeyNavigation.left: root 107 | KeyNavigation.right: root 108 | 109 | Keys.onDownPressed: { 110 | if (!navigationDown) { 111 | return; 112 | } 113 | 114 | if (navigationDown instanceof TileView) { 115 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 116 | 117 | if (navigationDown.currentIndex < 0) { 118 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 119 | } 120 | } 121 | 122 | navigationDown.forceActiveFocus(); 123 | } 124 | 125 | Keys.onUpPressed: { 126 | if (!navigationUp) { 127 | return; 128 | } 129 | 130 | if (navigationUp instanceof TileView) { 131 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 132 | 133 | if (navigationUp.currentIndex < 0) { 134 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 135 | } 136 | } 137 | 138 | navigationUp.forceActiveFocus(); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /ui/+android/YoutubeSearch.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * Copyright 2018 Marco Martin 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import QtQuick 2.9 20 | import QtQuick.Layouts 1.4 21 | import QtGraphicalEffects 1.0 22 | import QtQuick.Controls 2.2 23 | import org.kde.kirigami 2.8 as Kirigami 24 | import org.kde.plasma.core 2.0 as PlasmaCore 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | 28 | Mycroft.Delegate { 29 | id: delegate 30 | 31 | property var videoListModel: sessionData.videoListBlob.videoList 32 | property var currentSongUrl: sessionData.currenturl 33 | property var currenttitle: sessionData.currenttitle 34 | property Component highlighter: PlasmaComponents.Highlight{} 35 | property Component emptyHighlighter: Item{} 36 | 37 | skillBackgroundSource: "https://source.unsplash.com/weekly?music" 38 | 39 | leftPadding: 0 40 | rightPadding: 0 41 | topPadding: 0 42 | bottomPadding: 0 43 | 44 | onVideoListModelChanged: { 45 | leftSearchView.forceLayout() 46 | } 47 | 48 | Keys.onBackPressed: { 49 | parent.parent.parent.currentIndex-- 50 | parent.parent.parent.currentItem.contentItem.forceActiveFocus() 51 | } 52 | 53 | contentItem: ColumnLayout { 54 | id: recentlyPlayerColumn 55 | spacing: Kirigami.Units.smallSpacing 56 | 57 | Kirigami.Heading { 58 | id: watchItemList 59 | text: "Watch More.." 60 | level: 3 61 | } 62 | 63 | Kirigami.Separator { 64 | id: sept2 65 | Layout.fillWidth: true 66 | Layout.preferredHeight: 1 67 | z: 100 68 | } 69 | 70 | ListView { 71 | id: leftSearchView 72 | keyNavigationEnabled: true 73 | highlight: focus ? highlighter : emptyHighlighter 74 | model: videoListModel 75 | focus: false 76 | interactive: true 77 | bottomMargin: delegate.controlBarItem.height + Kirigami.Units.largeSpacing 78 | Layout.fillWidth: true 79 | Layout.fillHeight: true 80 | spacing: Kirigami.Units.largeSpacing 81 | currentIndex: 0 82 | highlightRangeMode: ListView.StrictlyEnforceRange 83 | snapMode: ListView.SnapToItem 84 | 85 | delegate: Control { 86 | width: parent.width 87 | height: Kirigami.Units.gridUnit * 4 88 | 89 | background: PlasmaCore.FrameSvgItem { 90 | id: frame 91 | anchors { 92 | fill: parent 93 | } 94 | imagePath: "widgets/background" 95 | 96 | width: parent.width 97 | height: parent.height 98 | opacity: 0.9 99 | } 100 | 101 | 102 | contentItem: Item { 103 | width: parent.width 104 | height: parent.height 105 | 106 | RowLayout { 107 | id: delegateItem 108 | anchors.fill: parent 109 | anchors.margins: Kirigami.Units.smallSpacing 110 | spacing: Kirigami.Units.largeSpacing 111 | 112 | Image { 113 | id: videoImage 114 | source: modelData.videoImage 115 | Layout.preferredHeight: parent.height 116 | Layout.preferredWidth: Kirigami.Units.gridUnit * 4 117 | Layout.alignment: Qt.AlignHCenter 118 | fillMode: Image.Stretch 119 | } 120 | 121 | Label { 122 | id: videoLabel 123 | Layout.fillWidth: true 124 | text: modelData.videoTitle 125 | wrapMode: Text.WordWrap 126 | } 127 | } 128 | } 129 | 130 | Keys.onReturnPressed: { 131 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: modelData.videoID, vidTitle: modelData.videoTitle, vidImage: modelData.videoImage, vidChannel: modelData.videoChannel, vidViews: modelData.videoViews, vidUploadDate: modelData.videoUploadDate, vidDuration: modelData.videoDuration}) 132 | } 133 | } 134 | } 135 | } 136 | 137 | Component.onCompleted: { 138 | leftSearchView.forceActiveFocus() 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /ui/+mediacenter/YoutubeSearch.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 by Aditya Mehra 3 | * Copyright 2018 Marco Martin 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | import QtQuick 2.9 20 | import QtQuick.Layouts 1.4 21 | import QtGraphicalEffects 1.0 22 | import QtQuick.Controls 2.2 23 | import org.kde.kirigami 2.8 as Kirigami 24 | import org.kde.plasma.core 2.0 as PlasmaCore 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import Mycroft 1.0 as Mycroft 27 | 28 | Mycroft.Delegate { 29 | id: delegate 30 | 31 | property var videoListModel: sessionData.videoListBlob.videoList 32 | property var currentSongUrl: sessionData.currenturl 33 | property var currenttitle: sessionData.currenttitle 34 | property Component highlighter: PlasmaComponents.Highlight{} 35 | property Component emptyHighlighter: Item{} 36 | 37 | skillBackgroundSource: "https://source.unsplash.com/weekly?music" 38 | 39 | leftPadding: 0 40 | rightPadding: 0 41 | topPadding: 0 42 | bottomPadding: 0 43 | 44 | onVideoListModelChanged: { 45 | leftSearchView.forceLayout() 46 | } 47 | 48 | Keys.onBackPressed: { 49 | parent.parent.parent.currentIndex-- 50 | parent.parent.parent.currentItem.contentItem.forceActiveFocus() 51 | } 52 | 53 | contentItem: ColumnLayout { 54 | id: recentlyPlayerColumn 55 | spacing: Kirigami.Units.smallSpacing 56 | 57 | Kirigami.Heading { 58 | id: watchItemList 59 | text: "Watch More.." 60 | level: 3 61 | } 62 | 63 | Kirigami.Separator { 64 | id: sept2 65 | Layout.fillWidth: true 66 | Layout.preferredHeight: 1 67 | z: 100 68 | } 69 | 70 | ListView { 71 | id: leftSearchView 72 | keyNavigationEnabled: true 73 | highlight: focus ? highlighter : emptyHighlighter 74 | model: videoListModel 75 | focus: false 76 | interactive: true 77 | bottomMargin: delegate.controlBarItem.height + Kirigami.Units.largeSpacing 78 | Layout.fillWidth: true 79 | Layout.fillHeight: true 80 | spacing: Kirigami.Units.largeSpacing 81 | currentIndex: 0 82 | highlightRangeMode: ListView.StrictlyEnforceRange 83 | snapMode: ListView.SnapToItem 84 | 85 | delegate: Control { 86 | width: parent.width 87 | height: Kirigami.Units.gridUnit * 4 88 | 89 | background: PlasmaCore.FrameSvgItem { 90 | id: frame 91 | anchors { 92 | fill: parent 93 | } 94 | imagePath: "widgets/background" 95 | 96 | width: parent.width 97 | height: parent.height 98 | opacity: 0.9 99 | } 100 | 101 | 102 | contentItem: Item { 103 | width: parent.width 104 | height: parent.height 105 | 106 | RowLayout { 107 | id: delegateItem 108 | anchors.fill: parent 109 | anchors.margins: Kirigami.Units.smallSpacing 110 | spacing: Kirigami.Units.largeSpacing 111 | 112 | Image { 113 | id: videoImage 114 | source: modelData.videoImage 115 | Layout.preferredHeight: parent.height 116 | Layout.preferredWidth: Kirigami.Units.gridUnit * 4 117 | Layout.alignment: Qt.AlignHCenter 118 | fillMode: Image.Stretch 119 | } 120 | 121 | Label { 122 | id: videoLabel 123 | Layout.fillWidth: true 124 | text: modelData.videoTitle 125 | wrapMode: Text.WordWrap 126 | } 127 | } 128 | } 129 | 130 | Keys.onReturnPressed: { 131 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: modelData.videoID, vidTitle: modelData.videoTitle, vidImage: modelData.videoImage, vidChannel: modelData.videoChannel, vidViews: modelData.videoViews, vidUploadDate: modelData.videoUploadDate, vidDuration: modelData.videoDuration}) 132 | } 133 | } 134 | } 135 | } 136 | 137 | Component.onCompleted: { 138 | leftSearchView.forceActiveFocus() 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /ui/views/HomeTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * 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. 8 | * 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. 13 | * 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 2.010-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.12 20 | import QtQuick.Layouts 1.4 21 | import QtQuick.Window 2.2 22 | import QtQuick.Controls 2.4 as Controls 23 | import QtGraphicalEffects 1.12 24 | 25 | import org.kde.plasma.core 2.0 as PlasmaCore 26 | import org.kde.plasma.components 3.0 as PlasmaComponents 27 | import org.kde.kirigami 2.5 as Kirigami 28 | 29 | FocusScope { 30 | id: root 31 | signal activated 32 | property string title 33 | property alias view: view 34 | property alias delegate: view.delegate 35 | property alias model: view.model 36 | property alias currentIndex: view.currentIndex 37 | property alias currentItem: view.currentItem 38 | Layout.fillWidth: true 39 | 40 | implicitHeight: view.implicitHeight + header.implicitHeight 41 | 42 | //TODO:dynamic 43 | property int columns: Math.max(3, Math.floor(width / (units.gridUnit * 8))) 44 | 45 | property alias cellWidth: view.cellWidth 46 | readonly property real screenRatio: view.Window.window ? view.Window.window.width / view.Window.window.height : 1.6 47 | 48 | property Item navigationUp 49 | property Item navigationDown 50 | 51 | Kirigami.Heading { 52 | id: header 53 | anchors { 54 | left: parent.left 55 | right: parent.right 56 | top: parent.top 57 | } 58 | text: title 59 | layer.enabled: true 60 | color: "white" 61 | } 62 | 63 | ListView { 64 | id: view 65 | anchors { 66 | left: parent.left 67 | right: parent.right 68 | top: header.baseline 69 | bottom: parent.bottom 70 | topMargin: Kirigami.Units.largeSpacing*2 71 | leftMargin: -Kirigami.Units.largeSpacing 72 | } 73 | focus: true 74 | 75 | z: activeFocus ? 10: 1 76 | keyNavigationEnabled: true 77 | //Centering disabled as experiment 78 | highlightRangeMode: ListView.ApplyRange 79 | 80 | highlightFollowsCurrentItem: true 81 | snapMode: ListView.SnapToItem 82 | cacheBuffer: width 83 | implicitHeight: cellWidth + units.gridUnit * 3 84 | rightMargin: width-cellWidth*3 85 | readonly property int cellWidth: (Kirigami.Units.iconSizes.huge + Kirigami.Units.largeSpacing*4) 86 | preferredHighlightBegin: cellWidth 87 | preferredHighlightEnd: cellWidth 88 | displayMarginBeginning: cellWidth 89 | displayMarginEnd: cellWidth 90 | 91 | highlightMoveVelocity: -1 92 | highlightMoveDuration: Kirigami.Units.longDuration 93 | 94 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 95 | 96 | onMovementEnded: flickEnded() 97 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 98 | 99 | spacing: 0 100 | orientation: ListView.Horizontal 101 | 102 | move: Transition { 103 | SmoothedAnimation { 104 | property: "x" 105 | duration: Kirigami.Units.longDuration 106 | } 107 | } 108 | 109 | KeyNavigation.left: root 110 | KeyNavigation.right: root 111 | 112 | Keys.onDownPressed: { 113 | if (!navigationDown) { 114 | return; 115 | } 116 | 117 | if (navigationDown instanceof TileView) { 118 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 119 | 120 | if (navigationDown.currentIndex < 0) { 121 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 122 | } 123 | } 124 | 125 | navigationDown.forceActiveFocus(); 126 | } 127 | 128 | Keys.onUpPressed: { 129 | if (!navigationUp) { 130 | return; 131 | } 132 | 133 | if (navigationUp instanceof TileView) { 134 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 135 | 136 | if (navigationUp.currentIndex < 0) { 137 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 138 | } 139 | } 140 | 141 | navigationUp.forceActiveFocus(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /ui/views/TileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.9 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Window 2.2 23 | import QtGraphicalEffects 1.12 24 | import QtQuick.Controls 2.4 as Controls 25 | import org.kde.kirigami 2.5 as Kirigami 26 | 27 | FocusScope { 28 | id: root 29 | signal activated 30 | property string title 31 | property alias view: view 32 | property alias delegate: view.delegate 33 | property alias model: view.model 34 | property alias currentIndex: view.currentIndex 35 | property alias currentItem: view.currentItem 36 | Layout.fillWidth: true 37 | 38 | implicitHeight: view.implicitHeight + header.implicitHeight 39 | 40 | //TODO:dynamic 41 | property int columns: Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 8))) 42 | 43 | property alias cellWidth: view.cellWidth 44 | property alias cellHeight: view.cellHeight 45 | readonly property real screenRatio: view.Window.window ? view.Window.window.width / view.Window.window.height : 1.6 46 | 47 | property Item navigationUp 48 | property Item navigationDown 49 | 50 | Kirigami.Heading { 51 | id: header 52 | anchors { 53 | left: parent.left 54 | right: parent.right 55 | top: parent.top 56 | } 57 | text: title 58 | layer.enabled: true 59 | color: "white" 60 | } 61 | 62 | ListView { 63 | id: view 64 | anchors { 65 | left: parent.left 66 | right: parent.right 67 | top: header.baseline 68 | bottom: parent.bottom 69 | topMargin: Kirigami.Units.largeSpacing*2 70 | leftMargin: -Kirigami.Units.largeSpacing 71 | } 72 | focus: true 73 | 74 | z: activeFocus ? 10: 1 75 | keyNavigationEnabled: true 76 | //Centering disabled as experiment 77 | //highlightRangeMode: ListView.ApplyRange 78 | 79 | //highlightFollowsCurrentItem: true 80 | snapMode: ListView.SnapToItem 81 | cacheBuffer: width 82 | implicitHeight: cellHeight 83 | rightMargin: width-cellWidth 84 | property int cellWidth: parent.width / 3 85 | property int cellHeight: cellWidth + Kirigami.Units.gridUnit * 3 86 | // preferredHighlightBegin: 0 87 | // preferredHighlightEnd: cellWidth 88 | displayMarginBeginning: cellWidth 89 | displayMarginEnd: cellWidth 90 | 91 | // highlightMoveVelocity: -1 92 | // highlightMoveDuration: Kirigami.Units.longDuration 93 | 94 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 95 | 96 | onMovementEnded: flickEnded() 97 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 98 | 99 | spacing: 0 100 | orientation: ListView.Horizontal 101 | 102 | move: Transition { 103 | SmoothedAnimation { 104 | property: "x" 105 | duration: Kirigami.Units.longDuration 106 | } 107 | } 108 | 109 | KeyNavigation.left: root 110 | KeyNavigation.right: root 111 | 112 | Keys.onDownPressed: { 113 | if (!navigationDown) { 114 | return; 115 | } 116 | 117 | if (navigationDown instanceof TileView) { 118 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 119 | 120 | if (navigationDown.currentIndex < 0) { 121 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 122 | } 123 | } 124 | 125 | navigationDown.forceActiveFocus(); 126 | } 127 | 128 | Keys.onUpPressed: { 129 | if (!navigationUp) { 130 | return; 131 | } 132 | 133 | if (navigationUp instanceof TileView) { 134 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 135 | 136 | if (navigationUp.currentIndex < 0) { 137 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 138 | } 139 | } 140 | 141 | navigationUp.forceActiveFocus(); 142 | } 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /ui/+android/views/HomeTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * 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. 8 | * 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. 13 | * 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 2.010-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.12 20 | import QtQuick.Layouts 1.4 21 | import QtQuick.Window 2.2 22 | import QtQuick.Controls 2.4 as Controls 23 | import QtGraphicalEffects 1.12 24 | 25 | import org.kde.plasma.core 2.0 as PlasmaCore 26 | import org.kde.plasma.components 3.0 as PlasmaComponents 27 | import org.kde.kirigami 2.5 as Kirigami 28 | 29 | FocusScope { 30 | id: root 31 | signal activated 32 | property string title 33 | property alias view: view 34 | property alias delegate: view.delegate 35 | property alias model: view.model 36 | property alias currentIndex: view.currentIndex 37 | property alias currentItem: view.currentItem 38 | Layout.fillWidth: true 39 | 40 | implicitHeight: view.implicitHeight + header.implicitHeight 41 | 42 | //TODO:dynamic 43 | property int columns: Math.max(3, Math.floor(width / (units.gridUnit * 8))) 44 | 45 | property alias cellWidth: view.cellWidth 46 | readonly property real screenRatio: view.Window.window ? view.Window.window.width / view.Window.window.height : 1.6 47 | 48 | property Item navigationUp 49 | property Item navigationDown 50 | 51 | Kirigami.Heading { 52 | id: header 53 | anchors { 54 | left: parent.left 55 | right: parent.right 56 | top: parent.top 57 | } 58 | text: title 59 | layer.enabled: true 60 | color: "white" 61 | } 62 | 63 | ListView { 64 | id: view 65 | anchors { 66 | left: parent.left 67 | right: parent.right 68 | top: header.baseline 69 | bottom: parent.bottom 70 | topMargin: Kirigami.Units.largeSpacing*2 71 | leftMargin: -Kirigami.Units.largeSpacing 72 | } 73 | focus: true 74 | 75 | z: activeFocus ? 10: 1 76 | keyNavigationEnabled: true 77 | //Centering disabled as experiment 78 | highlightRangeMode: ListView.ApplyRange 79 | 80 | highlightFollowsCurrentItem: true 81 | snapMode: ListView.SnapToItem 82 | cacheBuffer: width 83 | implicitHeight: cellWidth + units.gridUnit * 3 84 | rightMargin: width-cellWidth*3 85 | readonly property int cellWidth: (Kirigami.Units.iconSizes.huge + Kirigami.Units.largeSpacing*4) 86 | preferredHighlightBegin: cellWidth 87 | preferredHighlightEnd: cellWidth 88 | displayMarginBeginning: cellWidth 89 | displayMarginEnd: cellWidth 90 | 91 | highlightMoveVelocity: -1 92 | highlightMoveDuration: Kirigami.Units.longDuration 93 | 94 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 95 | 96 | onMovementEnded: flickEnded() 97 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 98 | 99 | spacing: 0 100 | orientation: ListView.Horizontal 101 | 102 | move: Transition { 103 | SmoothedAnimation { 104 | property: "x" 105 | duration: Kirigami.Units.longDuration 106 | } 107 | } 108 | 109 | KeyNavigation.left: root 110 | KeyNavigation.right: root 111 | 112 | Keys.onDownPressed: { 113 | if (!navigationDown) { 114 | return; 115 | } 116 | 117 | if (navigationDown instanceof TileView) { 118 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 119 | 120 | if (navigationDown.currentIndex < 0) { 121 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 122 | } 123 | } 124 | 125 | navigationDown.forceActiveFocus(); 126 | } 127 | 128 | Keys.onUpPressed: { 129 | if (!navigationUp) { 130 | return; 131 | } 132 | 133 | if (navigationUp instanceof TileView) { 134 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 135 | 136 | if (navigationUp.currentIndex < 0) { 137 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 138 | } 139 | } 140 | 141 | navigationUp.forceActiveFocus(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /ui/+android/views/TileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * Copyright 2019 Marco Martin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. 18 | */ 19 | 20 | import QtQuick 2.9 21 | import QtQuick.Layouts 1.4 22 | import QtQuick.Window 2.2 23 | import QtGraphicalEffects 1.12 24 | import QtQuick.Controls 2.4 as Controls 25 | import org.kde.kirigami 2.5 as Kirigami 26 | 27 | FocusScope { 28 | id: root 29 | signal activated 30 | property string title 31 | property alias view: view 32 | property alias delegate: view.delegate 33 | property alias model: view.model 34 | property alias currentIndex: view.currentIndex 35 | property alias currentItem: view.currentItem 36 | Layout.fillWidth: true 37 | 38 | implicitHeight: view.implicitHeight + header.implicitHeight 39 | 40 | //TODO:dynamic 41 | property int columns: Math.max(3, Math.floor(width / (Kirigami.Units.gridUnit * 8))) 42 | 43 | property alias cellWidth: view.cellWidth 44 | property alias cellHeight: view.cellHeight 45 | readonly property real screenRatio: view.Window.window ? view.Window.window.width / view.Window.window.height : 1.6 46 | 47 | property Item navigationUp 48 | property Item navigationDown 49 | 50 | Kirigami.Heading { 51 | id: header 52 | anchors { 53 | left: parent.left 54 | right: parent.right 55 | top: parent.top 56 | } 57 | text: title 58 | layer.enabled: true 59 | color: "white" 60 | } 61 | 62 | ListView { 63 | id: view 64 | anchors { 65 | left: parent.left 66 | right: parent.right 67 | top: header.baseline 68 | bottom: parent.bottom 69 | topMargin: Kirigami.Units.largeSpacing*2 70 | leftMargin: -Kirigami.Units.largeSpacing 71 | } 72 | focus: true 73 | 74 | z: activeFocus ? 10: 1 75 | keyNavigationEnabled: true 76 | //Centering disabled as experiment 77 | //highlightRangeMode: ListView.ApplyRange 78 | 79 | //highlightFollowsCurrentItem: true 80 | snapMode: ListView.SnapToItem 81 | cacheBuffer: width 82 | implicitHeight: cellHeight 83 | rightMargin: width-cellWidth 84 | property int cellWidth: parent.width / 3 85 | property int cellHeight: cellWidth + Kirigami.Units.gridUnit * 3 86 | // preferredHighlightBegin: 0 87 | // preferredHighlightEnd: cellWidth 88 | displayMarginBeginning: cellWidth 89 | displayMarginEnd: cellWidth 90 | 91 | // highlightMoveVelocity: -1 92 | // highlightMoveDuration: Kirigami.Units.longDuration 93 | 94 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 95 | 96 | onMovementEnded: flickEnded() 97 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 98 | 99 | spacing: 0 100 | orientation: ListView.Horizontal 101 | 102 | move: Transition { 103 | SmoothedAnimation { 104 | property: "x" 105 | duration: Kirigami.Units.longDuration 106 | } 107 | } 108 | 109 | KeyNavigation.left: root 110 | KeyNavigation.right: root 111 | 112 | Keys.onDownPressed: { 113 | if (!navigationDown) { 114 | return; 115 | } 116 | 117 | if (navigationDown instanceof TileView) { 118 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 119 | 120 | if (navigationDown.currentIndex < 0) { 121 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 122 | } 123 | } 124 | 125 | navigationDown.forceActiveFocus(); 126 | } 127 | 128 | Keys.onUpPressed: { 129 | if (!navigationUp) { 130 | return; 131 | } 132 | 133 | if (navigationUp instanceof TileView) { 134 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 135 | 136 | if (navigationUp.currentIndex < 0) { 137 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 138 | } 139 | } 140 | 141 | navigationUp.forceActiveFocus(); 142 | } 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /ui/+mediacenter/views/HomeTileView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Aditya Mehra 3 | * 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. 8 | * 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. 13 | * 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 2.010-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.12 20 | import QtQuick.Layouts 1.4 21 | import QtQuick.Window 2.2 22 | import QtQuick.Controls 2.4 as Controls 23 | import QtGraphicalEffects 1.12 24 | 25 | import org.kde.plasma.core 2.0 as PlasmaCore 26 | import org.kde.plasma.components 3.0 as PlasmaComponents 27 | import org.kde.kirigami 2.5 as Kirigami 28 | 29 | FocusScope { 30 | id: root 31 | signal activated 32 | property string title 33 | property alias view: view 34 | property alias delegate: view.delegate 35 | property alias model: view.model 36 | property alias currentIndex: view.currentIndex 37 | property alias currentItem: view.currentItem 38 | Layout.fillWidth: true 39 | 40 | implicitHeight: view.implicitHeight + header.implicitHeight 41 | 42 | //TODO:dynamic 43 | property int columns: Math.max(3, Math.floor(width / (units.gridUnit * 8))) 44 | 45 | property alias cellWidth: view.cellWidth 46 | readonly property real screenRatio: view.Window.window ? view.Window.window.width / view.Window.window.height : 1.6 47 | 48 | property Item navigationUp 49 | property Item navigationDown 50 | 51 | Kirigami.Heading { 52 | id: header 53 | anchors { 54 | left: parent.left 55 | right: parent.right 56 | top: parent.top 57 | } 58 | text: title 59 | layer.enabled: true 60 | color: "white" 61 | } 62 | 63 | ListView { 64 | id: view 65 | anchors { 66 | left: parent.left 67 | right: parent.right 68 | top: header.baseline 69 | bottom: parent.bottom 70 | topMargin: Kirigami.Units.largeSpacing*2 71 | leftMargin: -Kirigami.Units.largeSpacing 72 | } 73 | focus: true 74 | 75 | z: activeFocus ? 10: 1 76 | keyNavigationEnabled: true 77 | //Centering disabled as experiment 78 | highlightRangeMode: ListView.ApplyRange 79 | 80 | highlightFollowsCurrentItem: true 81 | snapMode: ListView.SnapToItem 82 | cacheBuffer: width 83 | implicitHeight: cellWidth + units.gridUnit * 3 84 | rightMargin: width-cellWidth*3 85 | readonly property int cellWidth: (Kirigami.Units.iconSizes.huge + Kirigami.Units.largeSpacing*4) 86 | preferredHighlightBegin: cellWidth 87 | preferredHighlightEnd: cellWidth 88 | displayMarginBeginning: cellWidth 89 | displayMarginEnd: cellWidth 90 | 91 | highlightMoveVelocity: -1 92 | highlightMoveDuration: Kirigami.Units.longDuration 93 | 94 | onContentWidthChanged: if (view.currentIndex === 0) view.contentX = view.originX 95 | 96 | onMovementEnded: flickEnded() 97 | onFlickEnded: currentIndex = indexAt(mapToItem(contentItem, cellWidth, 0).x, 0) 98 | 99 | spacing: 0 100 | orientation: ListView.Horizontal 101 | 102 | move: Transition { 103 | SmoothedAnimation { 104 | property: "x" 105 | duration: Kirigami.Units.longDuration 106 | } 107 | } 108 | 109 | KeyNavigation.left: root 110 | KeyNavigation.right: root 111 | 112 | Keys.onDownPressed: { 113 | if (!navigationDown) { 114 | return; 115 | } 116 | 117 | if (navigationDown instanceof TileView) { 118 | navigationDown.currentIndex = Math.min(Math.floor(navigationDown.view.indexAt(navigationDown.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationDown.view.count - 1); 119 | 120 | if (navigationDown.currentIndex < 0) { 121 | navigationDown.currentIndex = view.currentIndex > 0 ? navigationDown.view.count - 1 : 0 122 | } 123 | } 124 | 125 | navigationDown.forceActiveFocus(); 126 | } 127 | 128 | Keys.onUpPressed: { 129 | if (!navigationUp) { 130 | return; 131 | } 132 | 133 | if (navigationUp instanceof TileView) { 134 | navigationUp.currentIndex = Math.min(Math.floor(navigationUp.view.indexAt(navigationUp.view.contentX + cellWidth/2, height/2)) + (view.currentIndex - view.indexAt(view.contentX + cellWidth/2, height/2)), navigationUp.view.count - 1); 135 | 136 | if (navigationUp.currentIndex < 0) { 137 | navigationUp.currentIndex = view.currentIndex > 0 ? navigationUp.view.count - 1 : 0 138 | } 139 | } 140 | 141 | navigationUp.forceActiveFocus(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /ui/SuggestionArea.qml: -------------------------------------------------------------------------------- 1 | import QtQuick.Layouts 1.4 2 | import QtQuick 2.9 3 | import QtQuick.Controls 2.0 as Controls 4 | import org.kde.kirigami 2.8 as Kirigami 5 | import QtGraphicalEffects 1.0 6 | import Mycroft 1.0 as Mycroft 7 | import "+mediacenter/views" as Views 8 | import "+mediacenter/delegates" as Delegates 9 | import org.kde.mycroft.bigscreen 1.0 as BigScreen 10 | 11 | Rectangle { 12 | id: suggestionBox 13 | color: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.6) 14 | property var videoSuggestionList 15 | property alias suggestionListFocus: suggestListView.focus 16 | property var nxtSongBlob 17 | property int countdownSeconds: 15 18 | property int seconds: countdownSeconds 19 | anchors.left: parent.left 20 | anchors.right: parent.right 21 | anchors.verticalCenter: parent.verticalCenter 22 | implicitHeight: suggestBoxLayout.implicitHeight + Kirigami.Units.largeSpacing * 4 23 | 24 | onFocusChanged: { 25 | if(visible && focus){ 26 | suggestListView.forceActiveFocus() 27 | } 28 | } 29 | 30 | onNxtSongBlobChanged: { 31 | nextSongCdBar.imageSource = nxtSongBlob.videoImage 32 | nextSongCdBar.nextSongTitle = nxtSongBlob.videoTitle 33 | } 34 | 35 | onVideoSuggestionListChanged: { 36 | console.log(JSON.stringify(videoSuggestionList)) 37 | suggestListView.view.forceLayout() 38 | } 39 | 40 | onVisibleChanged: { 41 | if(visible) { 42 | autoPlayTimer.start() 43 | } 44 | } 45 | 46 | Timer { 47 | id: autoPlayTimer 48 | interval: 1000 49 | repeat: true 50 | onTriggered: { 51 | suggestionBox.seconds--; 52 | autoplayTimeHeading.text = "Next Video In: " + suggestionBox.seconds 53 | if(suggestionBox.seconds == 0) { 54 | running = false; 55 | suggestionBox.seconds = suggestionBox.countdownSeconds 56 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: nxtSongBlob.videoID, vidTitle: nxtSongBlob.videoTitle, vidImage: nxtSongBlob.videoImage, vidChannel: nxtSongBlob.videoChannel, vidViews: nxtSongBlob.videoViews, vidUploadDate: nxtSongBlob.videoUploadDate, vidDuration: nxtSongBlob.videoDuration}) 57 | } 58 | } 59 | } 60 | 61 | ColumnLayout { 62 | id: suggestBoxLayout 63 | anchors.fill: parent 64 | BigScreen.TileView { 65 | id: suggestListView 66 | clip: true 67 | model: videoSuggestionList 68 | delegate: Delegates.ListVideoCard{} 69 | title: "Watch Next" 70 | Layout.margins: Kirigami.Units.largeSpacing * 2 71 | cellWidth: parent.width / 4 72 | navigationDown: stopNextAutoplay 73 | } 74 | Kirigami.Separator { 75 | Layout.fillWidth: true 76 | Layout.preferredHeight: 1 77 | } 78 | RowLayout{ 79 | Layout.fillWidth: true 80 | Layout.fillHeight: true 81 | Layout.alignment: Qt.AlignHCenter 82 | 83 | Views.CountdownBar { 84 | id: nextSongCdBar 85 | Layout.preferredWidth: parent.width / 3 86 | Layout.fillHeight: true 87 | } 88 | Kirigami.Separator { 89 | Layout.fillHeight: true 90 | Layout.preferredWidth: 1 91 | } 92 | Controls.Button { 93 | id: stopNextAutoplay 94 | Layout.preferredWidth: parent.width / 3 95 | Layout.fillHeight: true 96 | text: "Cancel Autoplay" 97 | 98 | KeyNavigation.up: suggestListView 99 | 100 | onClicked: { 101 | if(autoplayTimeHeading.visible){ 102 | autoPlayTimer.stop() 103 | autoplayTimeHeading.visible = false 104 | stopNextAutoplay.text = "Next Video" 105 | suggestionBox.seconds = suggestionBox.countdownSeconds 106 | } else { 107 | suggestionBox.seconds = suggestionBox.countdownSeconds 108 | autoPlayTimer.start() 109 | autoplayTimeHeading.visible = true 110 | stopNextAutoplay.text = "Cancel Autoplay" 111 | } 112 | } 113 | 114 | Keys.onReturnPressed: { 115 | if(autoplayTimeHeading.visible){ 116 | autoPlayTimer.stop() 117 | autoplayTimeHeading.visible = false 118 | stopNextAutoplay.text = "Next Video" 119 | suggestionBox.seconds = suggestionBox.countdownSeconds 120 | } else { 121 | suggestionBox.seconds = suggestionBox.countdownSeconds 122 | autoPlayTimer.start() 123 | autoplayTimeHeading.visible = true 124 | stopNextAutoplay.text = "Cancel Autoplay" 125 | } 126 | } 127 | } 128 | 129 | Kirigami.Separator { 130 | Layout.fillHeight: true 131 | Layout.preferredWidth: 1 132 | } 133 | 134 | Kirigami.Heading { 135 | id: autoplayTimeHeading 136 | horizontalAlignment: Text.AlignHCenter 137 | verticalAlignment: Text.AlignVCenter 138 | Layout.preferredWidth: parent.width / 3 139 | Layout.fillHeight: true 140 | level: 3 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /ui/+android/SuggestionArea.qml: -------------------------------------------------------------------------------- 1 | import QtQuick.Layouts 1.4 2 | import QtQuick 2.9 3 | import QtQuick.Controls 2.0 as Controls 4 | import org.kde.kirigami 2.8 as Kirigami 5 | import QtGraphicalEffects 1.0 6 | import Mycroft 1.0 as Mycroft 7 | import "+mediacenter/views" as Views 8 | import "+mediacenter/delegates" as Delegates 9 | import org.kde.mycroft.bigscreen 1.0 as BigScreen 10 | 11 | Rectangle { 12 | id: suggestionBox 13 | color: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.6) 14 | property var videoSuggestionList 15 | property alias suggestionListFocus: suggestListView.focus 16 | property var nxtSongBlob 17 | property int countdownSeconds: 15 18 | property int seconds: countdownSeconds 19 | anchors.left: parent.left 20 | anchors.right: parent.right 21 | anchors.verticalCenter: parent.verticalCenter 22 | implicitHeight: suggestBoxLayout.implicitHeight + Kirigami.Units.largeSpacing * 4 23 | 24 | onFocusChanged: { 25 | if(visible && focus){ 26 | suggestListView.forceActiveFocus() 27 | } 28 | } 29 | 30 | onNxtSongBlobChanged: { 31 | nextSongCdBar.imageSource = nxtSongBlob.videoImage 32 | nextSongCdBar.nextSongTitle = nxtSongBlob.videoTitle 33 | } 34 | 35 | onVideoSuggestionListChanged: { 36 | console.log(JSON.stringify(videoSuggestionList)) 37 | suggestListView.view.forceLayout() 38 | } 39 | 40 | onVisibleChanged: { 41 | if(visible) { 42 | autoPlayTimer.start() 43 | } 44 | } 45 | 46 | Timer { 47 | id: autoPlayTimer 48 | interval: 1000 49 | repeat: true 50 | onTriggered: { 51 | suggestionBox.seconds--; 52 | autoplayTimeHeading.text = "Next Video In: " + suggestionBox.seconds 53 | if(suggestionBox.seconds == 0) { 54 | running = false; 55 | suggestionBox.seconds = suggestionBox.countdownSeconds 56 | Mycroft.MycroftController.sendRequest("aiix.youtube-skill.playvideo_id", {vidID: nxtSongBlob.videoID, vidTitle: nxtSongBlob.videoTitle, vidImage: nxtSongBlob.videoImage, vidChannel: nxtSongBlob.videoChannel, vidViews: nxtSongBlob.videoViews, vidUploadDate: nxtSongBlob.videoUploadDate, vidDuration: nxtSongBlob.videoDuration}) 57 | } 58 | } 59 | } 60 | 61 | ColumnLayout { 62 | id: suggestBoxLayout 63 | anchors.fill: parent 64 | BigScreen.TileView { 65 | id: suggestListView 66 | clip: true 67 | model: videoSuggestionList 68 | delegate: Delegates.ListVideoCard{} 69 | title: "Watch Next" 70 | Layout.margins: Kirigami.Units.largeSpacing * 2 71 | cellWidth: parent.width / 4 72 | navigationDown: stopNextAutoplay 73 | } 74 | Kirigami.Separator { 75 | Layout.fillWidth: true 76 | Layout.preferredHeight: 1 77 | } 78 | RowLayout{ 79 | Layout.fillWidth: true 80 | Layout.fillHeight: true 81 | Layout.alignment: Qt.AlignHCenter 82 | 83 | Views.CountdownBar { 84 | id: nextSongCdBar 85 | Layout.preferredWidth: parent.width / 3 86 | Layout.fillHeight: true 87 | } 88 | Kirigami.Separator { 89 | Layout.fillHeight: true 90 | Layout.preferredWidth: 1 91 | } 92 | Controls.Button { 93 | id: stopNextAutoplay 94 | Layout.preferredWidth: parent.width / 3 95 | Layout.fillHeight: true 96 | text: "Cancel Autoplay" 97 | 98 | KeyNavigation.up: suggestListView 99 | 100 | onClicked: { 101 | if(autoplayTimeHeading.visible){ 102 | autoPlayTimer.stop() 103 | autoplayTimeHeading.visible = false 104 | stopNextAutoplay.text = "Next Video" 105 | suggestionBox.seconds = suggestionBox.countdownSeconds 106 | } else { 107 | suggestionBox.seconds = suggestionBox.countdownSeconds 108 | autoPlayTimer.start() 109 | autoplayTimeHeading.visible = true 110 | stopNextAutoplay.text = "Cancel Autoplay" 111 | } 112 | } 113 | 114 | Keys.onReturnPressed: { 115 | if(autoplayTimeHeading.visible){ 116 | autoPlayTimer.stop() 117 | autoplayTimeHeading.visible = false 118 | stopNextAutoplay.text = "Next Video" 119 | suggestionBox.seconds = suggestionBox.countdownSeconds 120 | } else { 121 | suggestionBox.seconds = suggestionBox.countdownSeconds 122 | autoPlayTimer.start() 123 | autoplayTimeHeading.visible = true 124 | stopNextAutoplay.text = "Cancel Autoplay" 125 | } 126 | } 127 | } 128 | 129 | Kirigami.Separator { 130 | Layout.fillHeight: true 131 | Layout.preferredWidth: 1 132 | } 133 | 134 | Kirigami.Heading { 135 | id: autoplayTimeHeading 136 | horizontalAlignment: Text.AlignHCenter 137 | verticalAlignment: Text.AlignVCenter 138 | Layout.preferredWidth: parent.width / 3 139 | Layout.fillHeight: true 140 | level: 3 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /ui/images/simple-repeat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 68 | 86 | 104 | 111 | 128 | 135 | 153 | 154 | 155 | --------------------------------------------------------------------------------