✨ Result pagination implement for GUI.
This commit is contained in:
+1
-1
@@ -168,7 +168,7 @@ profile = "black"
|
|||||||
multi_line_output = 3
|
multi_line_output = 3
|
||||||
indent = 4
|
indent = 4
|
||||||
color_output = true
|
color_output = true
|
||||||
known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"]
|
known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "helper", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"]
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
|
# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
|
||||||
|
|||||||
+10
-4
@@ -2,6 +2,8 @@ import math
|
|||||||
import sys
|
import sys
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
|
|
||||||
|
from helper.tidal import items_all_results, search_all_results
|
||||||
|
|
||||||
from tidal_dl_ng.helper.path import get_format_template
|
from tidal_dl_ng.helper.path import get_format_template
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -250,13 +252,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def populate_tree_results(self, results: [ResultSearch]):
|
def populate_tree_results(self, results: [ResultSearch]):
|
||||||
self.tr_results.clear()
|
self.tr_results.clear()
|
||||||
|
count_digits: int = int(math.log10(len(results))) + 1
|
||||||
|
|
||||||
for item in results:
|
for item in results:
|
||||||
# Format seconds to mm:ss.
|
# Format seconds to mm:ss.
|
||||||
m, s = divmod(item.duration_sec, 60)
|
m, s = divmod(item.duration_sec, 60)
|
||||||
duration: str = f"{m:02d}:{s:02d}"
|
duration: str = f"{m:02d}:{s:02d}"
|
||||||
# Since sorting happens only by string, we need to pad the index and add 1 (to avoid start at 0)
|
# Since sorting happens only by string, we need to pad the index and add 1 (to avoid start at 0)
|
||||||
index: str = f"{item.position + 1:03}"
|
index: str = str(item.position + 1).zfill(count_digits)
|
||||||
child = QtWidgets.QTreeWidgetItem()
|
child = QtWidgets.QTreeWidgetItem()
|
||||||
|
|
||||||
child.setText(0, index)
|
child.setText(0, index)
|
||||||
@@ -269,7 +272,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self.tr_results.addTopLevelItem(child)
|
self.tr_results.addTopLevelItem(child)
|
||||||
|
|
||||||
def search(self, query: str, types_media: SearchTypes) -> [ResultSearch]:
|
def search(self, query: str, types_media: SearchTypes) -> [ResultSearch]:
|
||||||
result_search: [dict[str, SearchTypes]] = self.tidal.session.search(query, models=types_media, limit=999)
|
result_search: dict[str, [SearchTypes]] = search_all_results(
|
||||||
|
session=self.tidal.session, needle=query, types_media=types_media
|
||||||
|
)
|
||||||
result: [ResultSearch] = []
|
result: [ResultSearch] = []
|
||||||
|
|
||||||
for _media_type, l_media in result_search.items():
|
for _media_type, l_media in result_search.items():
|
||||||
@@ -386,8 +391,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
item = self.tr_lists_user.itemAt(point)
|
item = self.tr_lists_user.itemAt(point)
|
||||||
media_list = item.data(3, QtCore.Qt.ItemDataRole.UserRole)
|
media_list = item.data(3, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
media_items = media_list.items()
|
# Get all results
|
||||||
result = self.search_result_to_model(media_items)
|
media_items: [Track | Video] = items_all_results(media_list)
|
||||||
|
result: [ResultSearch] = self.search_result_to_model(media_items)
|
||||||
|
|
||||||
self.populate_tree_results(result)
|
self.populate_tree_results(result)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from tidalapi import Track
|
from tidalapi import Album, Mix, Playlist, Session, Track, Video
|
||||||
|
from tidalapi.session import SearchTypes
|
||||||
|
|
||||||
from tidal_dl_ng.constants import MediaType
|
from tidal_dl_ng.constants import MediaType
|
||||||
|
|
||||||
@@ -41,3 +42,53 @@ def get_tidal_media_type(url_media: str) -> MediaType | bool:
|
|||||||
result = MediaType.MIX
|
result = MediaType.MIX
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def search_all_results(session: Session, needle: str, types_media: SearchTypes = None) -> dict[str, [SearchTypes]]:
|
||||||
|
limit: int = 300
|
||||||
|
offset: int = 0
|
||||||
|
done: bool = False
|
||||||
|
result: dict[str, [SearchTypes]] = {}
|
||||||
|
|
||||||
|
while not done:
|
||||||
|
tmp_result: dict[str, [SearchTypes]] = session.search(
|
||||||
|
query=needle, models=types_media, limit=limit, offset=offset
|
||||||
|
)
|
||||||
|
tmp_done: bool = True
|
||||||
|
|
||||||
|
for key, value in tmp_result.items():
|
||||||
|
# Append pagination results, if there are any
|
||||||
|
if offset == 0:
|
||||||
|
result = tmp_result
|
||||||
|
tmp_done = False
|
||||||
|
elif bool(value):
|
||||||
|
result[key] += value
|
||||||
|
tmp_done = False
|
||||||
|
|
||||||
|
# Next page
|
||||||
|
offset += limit
|
||||||
|
done = tmp_done
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def items_all_results(media_list: [Mix | Playlist | Album]) -> [Track | Video]:
|
||||||
|
limit: int = 100
|
||||||
|
offset: int = 0
|
||||||
|
done: bool = False
|
||||||
|
result: [Track | Video] = []
|
||||||
|
|
||||||
|
if isinstance(media_list, Mix):
|
||||||
|
result = media_list.items()
|
||||||
|
else:
|
||||||
|
while not done:
|
||||||
|
tmp_result: [Track | Video] = media_list.items(limit=limit, offset=offset)
|
||||||
|
|
||||||
|
if bool(tmp_result):
|
||||||
|
result += tmp_result
|
||||||
|
# Get the next page in the next iteration.
|
||||||
|
offset += limit
|
||||||
|
else:
|
||||||
|
done = True
|
||||||
|
|
||||||
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user