From 3849efdbdabb2b6026d96c82b0268485a9301068 Mon Sep 17 00:00:00 2001 From: restitux Date: Thu, 8 Sep 2022 23:14:42 -0600 Subject: [PATCH] Refactor ContentView to add media browser --- ikinuki_client/__main__.py | 10 ++ layouts/components/BrowserView.qml | 16 ++- .../components/BrowserView/ContentView.qml | 19 +++- .../ContentView/ProviderBrowse.qml | 86 +++++++++++++++ .../ProviderBrowse/AlphabetSelector.qml | 67 ++++++++++++ .../ContentView/ProviderBrowse/BrowseShow.qml | 100 ++++++++++++++++++ .../ContentView/ProviderBrowse/CoverGrid.qml | 27 +++++ .../{ContentViewTab => ProviderBrowse}/qmldir | 0 .../{ContentViewTab.qml => ProviderHome.qml} | 11 +- .../Element.qml | 1 + .../{ContentViewTab => ProviderHome}/Show.qml | 0 .../ShowDetails.qml | 0 .../ContentView/ProviderHome/qmldir | 0 13 files changed, 322 insertions(+), 15 deletions(-) create mode 100644 layouts/components/BrowserView/ContentView/ProviderBrowse.qml create mode 100644 layouts/components/BrowserView/ContentView/ProviderBrowse/AlphabetSelector.qml create mode 100644 layouts/components/BrowserView/ContentView/ProviderBrowse/BrowseShow.qml create mode 100644 layouts/components/BrowserView/ContentView/ProviderBrowse/CoverGrid.qml rename layouts/components/BrowserView/ContentView/{ContentViewTab => ProviderBrowse}/qmldir (100%) rename layouts/components/BrowserView/ContentView/{ContentViewTab.qml => ProviderHome.qml} (90%) rename layouts/components/BrowserView/ContentView/{ContentViewTab => ProviderHome}/Element.qml (99%) rename layouts/components/BrowserView/ContentView/{ContentViewTab => ProviderHome}/Show.qml (100%) rename layouts/components/BrowserView/ContentView/{ContentViewTab => ProviderHome}/ShowDetails.qml (100%) create mode 100644 layouts/components/BrowserView/ContentView/ProviderHome/qmldir diff --git a/ikinuki_client/__main__.py b/ikinuki_client/__main__.py index e512985..04dddc6 100644 --- a/ikinuki_client/__main__.py +++ b/ikinuki_client/__main__.py @@ -111,6 +111,16 @@ class Provider(QObject): def getShow(self, id) -> Show: return self._shows[id] + @pyqtProperty(list) + def showsAlphabetic(self) -> list[int]: + return [ + elem[0] + for elem in sorted( + [(id, show) for id, show in self._shows.items()], + key=lambda elem: elem[1].title, + ) + ] + @pyqtProperty(list) def recentlyAdded(self) -> list[int]: return self._recently_added diff --git a/layouts/components/BrowserView.qml b/layouts/components/BrowserView.qml index 0675b01..5572199 100644 --- a/layouts/components/BrowserView.qml +++ b/layouts/components/BrowserView.qml @@ -1,11 +1,14 @@ import QtQuick 2.12 +import Ikinuki.Client 1.0 + import "./BrowserView" Row { + required property Database db property int selectedView: 0 property int selectedProvider: 0 - property var db + property bool browse: false Sidebar { id: sidebar maximized: selectedView == 0 @@ -15,7 +18,7 @@ Row { ContentView { id: view viewSelected: selectedView == 1 - currentIndex: selectedProvider + currentIndex: selectedProvider + (browse ? 3 : 0) providers: db.Providers } function mod(n, m) { @@ -26,11 +29,14 @@ Row { if (event.key == Qt.Key_Right) { selectedView = 1; } else if (event.key == Qt.Key_Down) { - selectedProvider = mod(selectedProvider + 1, db.Providers.length) + selectedProvider = mod(selectedProvider + 1, db.Providers.length); } else if (event.key == Qt.Key_Up) { - selectedProvider = mod(selectedProvider - 1, db.Providers.length) + selectedProvider = mod(selectedProvider - 1, db.Providers.length); + } else if (event.key == Qt.Key_Return) { + browse = true; + selectedView = 1; } else { - return + return; } event.accepted = true; } diff --git a/layouts/components/BrowserView/ContentView.qml b/layouts/components/BrowserView/ContentView.qml index 3378bfa..7e27cf7 100644 --- a/layouts/components/BrowserView/ContentView.qml +++ b/layouts/components/BrowserView/ContentView.qml @@ -9,7 +9,7 @@ import "./ContentView" StackLayout { id: tabView - property var providers + property var providers: [] property bool viewSelected state: viewSelected ? "selected" : "deselected" property int ySelect: 0 @@ -18,7 +18,13 @@ StackLayout { Repeater { model: providers - ContentViewTab{ + ProviderHome { + provider: modelData + } + } + Repeater { + model: providers + ProviderBrowse { provider: modelData } } @@ -49,9 +55,12 @@ StackLayout { ] Keys.onPressed: (event)=> { - tabView.children[currentIndex].Keys.pressed(event); - if (tabView.children[currentIndex].viewExit) { - tabView.children[currentIndex].viewExit = false; + var x = currentIndex > 2 ? currentIndex + 1 : currentIndex; + //tabView.children[currentIndex].Keys.pressed(event); + tabView.children[x].Keys.pressed(event); + if (tabView.children[x].viewExit) { + tabView.children[x].viewExit = false; + parent.browse = false; parent.selectedView = 0; } event.accepted = true; diff --git a/layouts/components/BrowserView/ContentView/ProviderBrowse.qml b/layouts/components/BrowserView/ContentView/ProviderBrowse.qml new file mode 100644 index 0000000..932e1a1 --- /dev/null +++ b/layouts/components/BrowserView/ContentView/ProviderBrowse.qml @@ -0,0 +1,86 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import QtQuick.Controls 1.4 +import QtQuick.Controls 2.15 + +import Ikinuki.Client 1.0 + +import "./ProviderBrowse" + +Rectangle { + id: root + property var provider + property bool viewExit: false + property int currentView: 0 + anchors.fill: parent + color: "#22282A" + Row { + anchors.fill: parent + Item { + height: parent.height + width: parent.width * 0.025 + } + Column { + width: parent.width * 0.95 + height: parent.height + Item { + height: 40 + width: parent.width + } + CoverGrid { + id: coverGrid + height: parent.height - 80 + width: parent.width + provider: root.provider + shows: root.provider.showsAlphabetic + selected: currentView == 0 + } + Item { + height: 40 + width: parent.width + } + } + AlphabetSelector { + id: alphabetSelector + height: parent.height + width: parent.width * 0.025 + selected: currentView == 1 + } + } + + Keys.onPressed: (event)=> { + if (currentView == 0) { // grid + if (event.key == Qt.Key_Left) { + if (coverGrid.xIndex == 0) { + viewExit = true; + } else { + coverGrid.xIndex--; + } + } else if (event.key == Qt.Key_Right) { + if (coverGrid.xIndex == coverGrid.numColumns - 1) { + currentView = 1; + } else { + coverGrid.xIndex++; + } + } else if (event.key == Qt.Key_Down) { + coverGrid.yIndex++; + } else if (event.key == Qt.Key_Up) { + coverGrid.yIndex--; + } + } else if (currentView == 1) { // alphabet + if (event.key == Qt.Key_Left) { + currentView = 0; + } else if (event.key == Qt.Key_Up) { + if (alphabetSelector.yIndex > 0) { + alphabetSelector.yIndex--; + } + } else if (event.key == Qt.Key_Down) { + if (alphabetSelector.yIndex < alphabetSelector.letters.length - 1) + alphabetSelector.yIndex++; + } + } else { + return + } + event.accepted = true; + } +} diff --git a/layouts/components/BrowserView/ContentView/ProviderBrowse/AlphabetSelector.qml b/layouts/components/BrowserView/ContentView/ProviderBrowse/AlphabetSelector.qml new file mode 100644 index 0000000..b9eee4e --- /dev/null +++ b/layouts/components/BrowserView/ContentView/ProviderBrowse/AlphabetSelector.qml @@ -0,0 +1,67 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.15 +import QtGraphicalEffects 1.12 + +Column { + property int yIndex: 0 + property bool selected + property var letters: ['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] + Item { + height: 20 + width: parent.width + } + ScrollView { + height: parent.height - 30 + width: parent.width + ScrollBar.vertical.position: { + if (yIndex > 20) { + return (5 - (25 - yIndex)) * (0.048); + } else { + return 0; + } + } + Flickable { + clip: true + Column { + spacing: 10 + Repeater { + model: letters + Item { + width: 40 + height: 40 + anchors.horizontalCenter: parent.horizontalCenter + property bool s: selected && (index == yIndex) + DropShadow { + anchors.fill: selector + verticalOffset: 5 + samples: 20 + color: "black" + opacity: 0.5 + source: selector + visible: s + } + Rectangle { + id: selector + anchors.fill: parent + color: "white" + visible: s + radius: 10 + } + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 4 + text: modelData + color: s ? "black" : "gray" + font.pointSize: 18 + } + } + } + } + } + } + Item { + height: 20 + width: parent.width + } +} diff --git a/layouts/components/BrowserView/ContentView/ProviderBrowse/BrowseShow.qml b/layouts/components/BrowserView/ContentView/ProviderBrowse/BrowseShow.qml new file mode 100644 index 0000000..c40a102 --- /dev/null +++ b/layouts/components/BrowserView/ContentView/ProviderBrowse/BrowseShow.qml @@ -0,0 +1,100 @@ +import QtQuick 2.12 +import QtQuick.Controls 1.4 +import QtGraphicalEffects 1.12 + + +Item { + property var show + property bool elemSelected + property int baseHeight: 350 + property int childHeight: baseHeight + property int childWidth: baseHeight * 0.68 + property int childHeightExpanded: baseHeight * 15 / 14 + property int childWidthExpanded: (baseHeight * 15 / 14) * 0.68 + property int borderWidth: 3 + property int borderRadius: 1 + property int borderRectHeight: childHeight + (borderWidth * 2) + property int borderRectWidth: childWidth + (borderWidth * 2) + property int borderRectHeightExpanded: childHeightExpanded + (borderWidth * 2) + property int borderRectWidthExpanded: childWidthExpanded + (borderWidth * 2) + + height: baseHeight * 1.15 + width: (baseHeight * 8 / 7) * 0.68 + Item { + id: parentElem + state: elemSelected ? "selected" : "deselected" + anchors.horizontalCenter: parent.horizontalCenter + anchors.fill: parent + DropShadow { + id: dropShadow + anchors.fill: img + verticalOffset: 15 + samples: 80 + opacity: 0.5 + color: "black" + source: img + } + Rectangle { + id: rect + color: "transparent" + border.color: "orange" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + radius: borderRadius + } + Image { + id: img + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: show.poster + mipmap: true + } + states: [ + State { + name: "deselected" + PropertyChanges { + target: rect + border.width: 0 + height: borderRectHeight + width: borderRectWidth + } + PropertyChanges { + target: dropShadow + visible: false + } + PropertyChanges { + target: img + width: childWidth + height: childHeight + } + }, + State { + name: "selected" + PropertyChanges { + target: rect + border.width: borderWidth + height: borderRectHeightExpanded + width: borderRectWidthExpanded + } + PropertyChanges { + target: dropShadow + visible: true + } + PropertyChanges { + target: img + width: childWidthExpanded + height: childHeightExpanded + } + } + ] + transitions: [ + Transition { + NumberAnimation { + properties: "border.width,width,height" + duration: 100 + easing.type: Easing.Linear + } + } + ] + } +} diff --git a/layouts/components/BrowserView/ContentView/ProviderBrowse/CoverGrid.qml b/layouts/components/BrowserView/ContentView/ProviderBrowse/CoverGrid.qml new file mode 100644 index 0000000..0868f11 --- /dev/null +++ b/layouts/components/BrowserView/ContentView/ProviderBrowse/CoverGrid.qml @@ -0,0 +1,27 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import QtQuick.Controls 1.4 +import QtQuick.Controls 2.15 + +import Ikinuki.Client 1.0 + +Grid { + id: root + clip: true + property bool selected + property int yIndex: 0 + property int xIndex: 0 + property int numColumns: 6 + property var provider + property var shows: [] + columns: numColumns + topPadding: 20 + Repeater { + id: repeater + model: shows + BrowseShow { + show: provider.getShow(modelData) + elemSelected: selected && (index == (yIndex * numColumns + xIndex)) + } + } +} diff --git a/layouts/components/BrowserView/ContentView/ContentViewTab/qmldir b/layouts/components/BrowserView/ContentView/ProviderBrowse/qmldir similarity index 100% rename from layouts/components/BrowserView/ContentView/ContentViewTab/qmldir rename to layouts/components/BrowserView/ContentView/ProviderBrowse/qmldir diff --git a/layouts/components/BrowserView/ContentView/ContentViewTab.qml b/layouts/components/BrowserView/ContentView/ProviderHome.qml similarity index 90% rename from layouts/components/BrowserView/ContentView/ContentViewTab.qml rename to layouts/components/BrowserView/ContentView/ProviderHome.qml index 0308b68..459707d 100644 --- a/layouts/components/BrowserView/ContentView/ContentViewTab.qml +++ b/layouts/components/BrowserView/ContentView/ProviderHome.qml @@ -5,9 +5,10 @@ import QtQuick.Controls 2.15 import Ikinuki.Client 1.0 -import "./ContentViewTab" +import "./ProviderHome" Rectangle { + id: root property var provider property int ySelect: 0 property int xSelect: 0 @@ -49,14 +50,14 @@ Rectangle { width: parent.width Element { title: "In Progress" - provider: modelData - repeaterModel: modelData.inProgress + provider: root.provider + repeaterModel: provider.inProgress elemSelected: viewSelected && (0 == ySelect) } Element { title: "Recently Added" - provider: modelData - repeaterModel: modelData.recentlyAdded + provider: root.provider + repeaterModel: provider.recentlyAdded elemSelected: viewSelected && (1 == ySelect) } } diff --git a/layouts/components/BrowserView/ContentView/ContentViewTab/Element.qml b/layouts/components/BrowserView/ContentView/ProviderHome/Element.qml similarity index 99% rename from layouts/components/BrowserView/ContentView/ContentViewTab/Element.qml rename to layouts/components/BrowserView/ContentView/ProviderHome/Element.qml index af564d3..605fd37 100644 --- a/layouts/components/BrowserView/ContentView/ContentViewTab/Element.qml +++ b/layouts/components/BrowserView/ContentView/ProviderHome/Element.qml @@ -3,6 +3,7 @@ import QtQuick.Controls 1.4 import QtQuick.Controls 2.15 Column { + id: root property var title property var provider property var repeaterModel diff --git a/layouts/components/BrowserView/ContentView/ContentViewTab/Show.qml b/layouts/components/BrowserView/ContentView/ProviderHome/Show.qml similarity index 100% rename from layouts/components/BrowserView/ContentView/ContentViewTab/Show.qml rename to layouts/components/BrowserView/ContentView/ProviderHome/Show.qml diff --git a/layouts/components/BrowserView/ContentView/ContentViewTab/ShowDetails.qml b/layouts/components/BrowserView/ContentView/ProviderHome/ShowDetails.qml similarity index 100% rename from layouts/components/BrowserView/ContentView/ContentViewTab/ShowDetails.qml rename to layouts/components/BrowserView/ContentView/ProviderHome/ShowDetails.qml diff --git a/layouts/components/BrowserView/ContentView/ProviderHome/qmldir b/layouts/components/BrowserView/ContentView/ProviderHome/qmldir new file mode 100644 index 0000000..e69de29