Add episode browser

This commit is contained in:
2022-09-13 21:33:26 -06:00
parent 1e7d9db9cc
commit a38221cca2
9 changed files with 254 additions and 18 deletions
+48 -9
View File
@@ -3,6 +3,8 @@ from typing import Type
import sys
from urllib import parse
from collections import defaultdict
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import qmlRegisterType, QQmlApplicationEngine
from PyQt5.QtQuick import QQuickImageProvider
@@ -20,11 +22,34 @@ from .qtmpv import MpvObject
import requests
class Show(QObject):
class Episode(QObject):
def __init__(self, source, parent=None):
super().__init__(parent)
self._source = source
@pyqtProperty("QString", constant=True)
def title(self):
return self._source["Title"]
@pyqtProperty(int, constant=True)
def season(self):
return self._source["Season"]
@pyqtProperty(int, constant=True)
def episode(self):
return self._source["Episode"]
@pyqtProperty("QString", constant=True)
def filename(self):
return self._source["OriginalFilename"]
class Show(QObject):
def __init__(self, source, episodes, parent=None):
super().__init__(parent)
self._source = source
self._episodes = episodes
@pyqtProperty("QString", constant=True)
def title(self) -> str:
return self._source["title"]
@@ -37,10 +62,6 @@ class Show(QObject):
def description(self) -> str:
return self._source["description"]
@pyqtProperty(int, constant=True)
def episodes(self) -> int:
return self._source["episodes"]
@pyqtProperty(int, constant=True)
def watched(self) -> int:
return self._source["watched"]
@@ -49,6 +70,10 @@ class Show(QObject):
def poster(self) -> str:
return self._source["poster"]
@pyqtProperty(list, constant=True)
def episodes(self) -> list[Episode]:
return self._episodes
class ProviderImageProvider(QQuickImageProvider):
def __init__(self, icon_data):
@@ -89,8 +114,20 @@ class Provider(QObject):
describe["icon"]
)
def default_val():
return []
episodes: dict = getUrl(self.url, "episodes")
_episodes: defaultdict[str, list[Episode]] = defaultdict(default_val)
for e in episodes["episodes"]:
_episodes[e["ShowTitle"]].append(Episode(e))
shows: dict = getUrl(self.url, "shows")
self._shows: dict[int, Show] = {e["id"]: Show(e) for e in shows["data"]}
self._shows: dict[int, Show] = {
e["id"]: Show(e, _episodes[e["title"]]) for e in shows["data"]
}
recently_added: dict = getUrl(self.url, "recently_added")
self._recently_added: list[int] = recently_added["data"]
@@ -159,11 +196,13 @@ def main():
data_source = DataSource(
[
"http://127.0.0.1:8080/a/",
"http://127.0.0.1:8080/b/",
"http://127.0.0.1:8080/c/",
# "http://127.0.0.1:8080/a/",
# "http://127.0.0.1:8080/b/",
# "http://127.0.0.1:8080/c/",
"http://127.0.0.1:32520/",
]
)
# data_source = DataSource([])
qmlRegisterType(DatabaseType(data_source), "Ikinuki.Client", 1, 0, "Database")
# qmlRegisterType(Provider, "Ikinuki.Client", 1, 0, "Provider")
+1 -1
View File
@@ -18,7 +18,7 @@ Row {
ContentView {
id: view
viewSelected: selectedView == 1
currentIndex: selectedProvider + (browse ? db.Providers.length : 0)
parentIndex: selectedProvider + (browse ? db.Providers.length : 0)
providers: db.Providers
}
function mod(n, m) {
+36 -7
View File
@@ -11,8 +11,15 @@ StackLayout {
id: tabView
property var providers: []
property bool viewSelected
state: viewSelected ? "selected" : "deselected"
property int parentIndex
property int ySelect: 0
property bool showViewActive: false
currentIndex: showViewActive ? tabView.children.length - 3 : parentIndex
//currentIndex: showView ? tabView.children.length - 3 : parentIndex
state: viewSelected ? "selected" : "deselected"
width: parent.width * viewSelected ? 0.95 : 0.8
height: parent.height
@@ -28,6 +35,10 @@ StackLayout {
provider: modelData
}
}
ShowView {
id: showView
show: providers[0].getShow(providers[0].showsAlphabetic[0])
}
states: [
State {
name: "deselected"
@@ -54,14 +65,32 @@ StackLayout {
}
]
function getCurrentIndex() {
if (showViewActive) {
var x = tabView.children.length - 1;
} else {
var x = currentIndex > (providers.length - 1) ? currentIndex + 1 : currentIndex;
}
return x;
}
Keys.onPressed: (event)=> {
var x = currentIndex > (providers.length - 1) ? currentIndex + 1 : currentIndex;
//tabView.children[currentIndex].Keys.pressed(event);
var x = getCurrentIndex()
tabView.children[x].Keys.pressed(event);
if (tabView.children[x].viewExit) {
tabView.children[x].viewExit = false;
parent.browse = false;
parent.selectedView = 0;
if (tabView.children[x].enterShow) {
showViewActive = true;
showView.show = tabView.children[x].enterShowShow;
} else if (tabView.children[x].viewExit) {
if (showViewActive) {
showViewActive = false;
tabView.children[x].xIndex = 0;
tabView.children[x].viewExit = false;
tabView.children[getCurrentIndex()].enterShow = false;
} else {
tabView.children[x].viewExit = false;
parent.browse = false;
parent.selectedView = 0;
}
}
event.accepted = true;
}
@@ -0,0 +1,34 @@
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 "./ShowView"
ScrollView {
id: root
property var episodeModel
property int scrollIndex: 0
contentHeight: root.height * 0.1 * episodeModel.length
ScrollBar.vertical.position: scrollIndex / (episodeModel.length)
clip: true
Behavior on ScrollBar.vertical.position {
NumberAnimation {
duration: 200
easing.type: Easing.Linear
}
}
Column {
Repeater {
model: episodeModel
Episode {
episode: modelData
selected: index == xIndex
height: root.height * 0.1
width: root.width
}
}
}
}
@@ -11,6 +11,8 @@ Rectangle {
id: root
property var provider
property bool viewExit: false
property bool enterShow: false
property var enterShowShow
property int currentView: 0
color: "#22282A"
Row {
@@ -76,6 +78,9 @@ Rectangle {
coverGrid.scrollIndex--;
}
}
} else if (event.key == Qt.Key_Return) {
enterShowShow = root.provider.getShow(root.provider.showsAlphabetic[(coverGrid.xIndex + coverGrid.yIndex * coverGrid.numColumns)])
enterShow = true;
}
} else if (currentView == 1) { // alphabet
if (event.key == Qt.Key_Left) {
@@ -11,8 +11,9 @@ Rectangle {
id: root
property var provider
property int ySelect: 0
property int xSelect: 0
property bool viewExit: false
property bool enterShow: false
property var enterShowShow
color: "#22282A"
Row {
Item {
@@ -82,6 +83,9 @@ Rectangle {
ySelect++;
} else if (event.key == Qt.Key_Up) {
ySelect--;
} else if (event.key == Qt.Key_Return) {
enterShowShow = provider.getShow(elementColumn.children[ySelect].showId)
enterShow = true;
}
event.accepted = true;
}
@@ -0,0 +1,76 @@
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 "./ShowView"
Rectangle {
property var show
property bool viewExit: false
property bool enterShow: false
property int xIndex: 0
color: "#22282A"
Column {
anchors.fill: parent
anchors.leftMargin: parent.width * 0.01
anchors.rightMargin: parent.width * 0.01
anchors.topMargin: parent.height * 0.05
anchors.bottomMargin: parent.height * 0.01
Text { // header
height: parent.height * 0.1
width: parent.width
text: show.title
font.pointSize: 20
color: "#cdd7d9"
}
Row { // main view
height: parent.height * 0.8
width: parent.width
spacing: parent.width * 0.01
Item {
height: parent.height
width: height * 0.68
Image {
source: show.poster
anchors.fill: parent
mipmap: true
}
}
EpisodeView {
id: episodeView
height: parent.height
width: parent.width * 0.65
episodeModel: show.episodes
}
}
Item {
height: parent.height * 0.1
width: parent.width
}
}
Keys.onPressed: (event)=> {
if (event.key == Qt.Key_Up) {
if (xIndex > 0) {
xIndex--;
if (episodeView.scrollIndex > xIndex) {
episodeView.scrollIndex--;
}
}
} else if (event.key == Qt.Key_Down) {
if (xIndex < show.episodes.length - 1) {
if (episodeView.scrollIndex < (xIndex - 8)) {
episodeView.scrollIndex++;
}
xIndex++;
}
} else if (event.key == Qt.Key_Escape) {
viewExit = true;
}
event.accepted = true;
}
}
@@ -0,0 +1,49 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 1.4
import QtQuick.Controls 2.15
import Ikinuki.Client 1.0
Item {
property var episode
property bool selected
Rectangle {
anchors.fill: parent
color: "white"
visible: selected
radius: 10
}
Row {
anchors.fill: parent
Item {
height: parent.height
width: parent.width * 0.04
}
Column {
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 4
Text {
text: {
if (modelData.season == 0) {
return "S" + modelData.episode + " " + modelData.title
} else {
return String(modelData.episode).padStart(2, "0") + ". " + modelData.title
}
}
font.pointSize: 20
color: selected ? "#3c3c3c" : "#99afb4"
}
Item {
height: parent.height * 0.1
width: parent.width
}
Text {
text: " air date"
font.pointSize: 12
color: selected ? "#3c3c3c" : "#99afb4"
}
}
}
}