Show search progress per plugin during global search
This commit is contained in:
164
addon/default.py
164
addon/default.py
@@ -147,6 +147,45 @@ def _busy_dialog():
|
||||
_busy_close()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _progress_dialog(heading: str, message: str = ""):
|
||||
"""Zeigt einen Fortschrittsdialog in Kodi und liefert eine Update-Funktion."""
|
||||
dialog = None
|
||||
try: # pragma: no cover - Kodi runtime
|
||||
if xbmcgui is not None and hasattr(xbmcgui, "DialogProgress"):
|
||||
dialog = xbmcgui.DialogProgress()
|
||||
dialog.create(heading, message)
|
||||
except Exception:
|
||||
dialog = None
|
||||
|
||||
def _update(percent: int, text: str = "") -> bool:
|
||||
if dialog is None:
|
||||
return False
|
||||
percent = max(0, min(100, int(percent)))
|
||||
try: # Kodi Matrix/Nexus
|
||||
dialog.update(percent, text)
|
||||
except TypeError:
|
||||
try: # Kodi Leia fallback
|
||||
dialog.update(percent, text, "", "")
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return bool(dialog.iscanceled())
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
try:
|
||||
yield _update
|
||||
finally:
|
||||
if dialog is not None:
|
||||
try:
|
||||
dialog.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _get_handle() -> int:
|
||||
return int(sys.argv[1]) if len(sys.argv) > 1 else -1
|
||||
|
||||
@@ -919,21 +958,27 @@ def _show_plugin_search_results(plugin_name: str, query: str) -> None:
|
||||
_set_content(handle, "movies" if plugin_name.casefold() == "einschalten" else "tvshows")
|
||||
_log(f"Suche nach Titeln (Plugin={plugin_name}): {query}")
|
||||
|
||||
list_items: list[dict[str, object]] = []
|
||||
canceled = False
|
||||
try:
|
||||
with _progress_dialog("Suche läuft", f"{plugin_name} (1/1) starte…") as progress:
|
||||
canceled = progress(5, f"{plugin_name} (1/1) Suche…")
|
||||
results = _run_async(plugin.search_titles(query))
|
||||
except Exception as exc:
|
||||
_log(f"Suche fehlgeschlagen ({plugin_name}): {exc}", xbmc.LOGWARNING)
|
||||
xbmcgui.Dialog().notification("Suche", "Suche fehlgeschlagen.", xbmcgui.NOTIFICATION_INFO, 3000)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
return
|
||||
|
||||
results = [str(t).strip() for t in (results or []) if t and str(t).strip()]
|
||||
results.sort(key=lambda value: value.casefold())
|
||||
|
||||
tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {}
|
||||
if results:
|
||||
with _busy_dialog():
|
||||
if results and not canceled:
|
||||
canceled = progress(35, f"{plugin_name} (1/1) Metadaten…")
|
||||
tmdb_prefetched = _tmdb_labels_and_art_bulk(list(results))
|
||||
for title in results:
|
||||
|
||||
total_results = max(1, len(results))
|
||||
for index, title in enumerate(results, start=1):
|
||||
if canceled:
|
||||
break
|
||||
if index == 1 or index == total_results or (index % 10 == 0):
|
||||
pct = 35 + int((index / float(total_results)) * 60)
|
||||
canceled = progress(pct, f"{plugin_name} (1/1) aufbereiten {index}/{total_results}")
|
||||
info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title))
|
||||
info_labels = dict(info_labels or {})
|
||||
info_labels.setdefault("mediatype", "tvshow")
|
||||
@@ -945,15 +990,37 @@ def _show_plugin_search_results(plugin_name: str, query: str) -> None:
|
||||
display_label = _label_with_playstate(display_label, playstate)
|
||||
direct_play = bool(plugin_name.casefold() == "einschalten" and _get_setting_bool("einschalten_enable_playback", default=False))
|
||||
extra_params = _series_url_params(plugin, title)
|
||||
list_items.append(
|
||||
{
|
||||
"label": display_label,
|
||||
"action": "play_movie" if direct_play else "seasons",
|
||||
"params": {"plugin": plugin_name, "title": title, **extra_params},
|
||||
"is_folder": (not direct_play),
|
||||
"info_labels": merged_info,
|
||||
"art": art,
|
||||
"cast": cast,
|
||||
}
|
||||
)
|
||||
except Exception as exc:
|
||||
_log(f"Suche fehlgeschlagen ({plugin_name}): {exc}", xbmc.LOGWARNING)
|
||||
xbmcgui.Dialog().notification("Suche", "Suche fehlgeschlagen.", xbmcgui.NOTIFICATION_INFO, 3000)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
return
|
||||
if canceled and not list_items:
|
||||
xbmcgui.Dialog().notification("Suche", "Suche abgebrochen.", xbmcgui.NOTIFICATION_INFO, 2500)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
return
|
||||
|
||||
for item in list_items:
|
||||
_add_directory_item(
|
||||
handle,
|
||||
display_label,
|
||||
"play_movie" if direct_play else "seasons",
|
||||
{"plugin": plugin_name, "title": title, **extra_params},
|
||||
is_folder=not direct_play,
|
||||
info_labels=merged_info,
|
||||
art=art,
|
||||
cast=cast,
|
||||
str(item["label"]),
|
||||
str(item["action"]),
|
||||
dict(item["params"]),
|
||||
is_folder=bool(item["is_folder"]),
|
||||
info_labels=item["info_labels"],
|
||||
art=item["art"],
|
||||
cast=item["cast"],
|
||||
)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
|
||||
@@ -1058,18 +1125,42 @@ def _show_search_results(query: str) -> None:
|
||||
xbmcgui.Dialog().notification("Suche", "Keine Plugins gefunden.", xbmcgui.NOTIFICATION_INFO, 3000)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
return
|
||||
for plugin_name, plugin in plugins.items():
|
||||
list_items: list[dict[str, object]] = []
|
||||
canceled = False
|
||||
plugin_entries = list(plugins.items())
|
||||
total_plugins = max(1, len(plugin_entries))
|
||||
with _progress_dialog("Suche läuft", "Suche gestartet…") as progress:
|
||||
for plugin_index, (plugin_name, plugin) in enumerate(plugin_entries, start=1):
|
||||
range_start = int(((plugin_index - 1) / float(total_plugins)) * 100)
|
||||
range_end = int((plugin_index / float(total_plugins)) * 100)
|
||||
canceled = progress(range_start, f"{plugin_name} ({plugin_index}/{total_plugins}) Suche…")
|
||||
if canceled:
|
||||
break
|
||||
try:
|
||||
results = _run_async(plugin.search_titles(query))
|
||||
except Exception as exc:
|
||||
_log(f"Suche fehlgeschlagen ({plugin_name}): {exc}", xbmc.LOGWARNING)
|
||||
continue
|
||||
results = [str(t).strip() for t in (results or []) if t and str(t).strip()]
|
||||
_log(f"Treffer ({plugin_name}): {len(results)}", xbmc.LOGDEBUG)
|
||||
tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {}
|
||||
if results:
|
||||
with _busy_dialog():
|
||||
canceled = progress(
|
||||
range_start + int((range_end - range_start) * 0.35),
|
||||
f"{plugin_name} ({plugin_index}/{total_plugins}) Metadaten…",
|
||||
)
|
||||
if canceled:
|
||||
break
|
||||
tmdb_prefetched = _tmdb_labels_and_art_bulk(list(results))
|
||||
for title in results:
|
||||
total_results = max(1, len(results))
|
||||
for title_index, title in enumerate(results, start=1):
|
||||
if title_index == 1 or title_index == total_results or (title_index % 10 == 0):
|
||||
canceled = progress(
|
||||
range_start + int((range_end - range_start) * (0.35 + 0.65 * (title_index / float(total_results)))),
|
||||
f"{plugin_name} ({plugin_index}/{total_plugins}) aufbereiten {title_index}/{total_results}",
|
||||
)
|
||||
if canceled:
|
||||
break
|
||||
info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title))
|
||||
info_labels = dict(info_labels or {})
|
||||
info_labels.setdefault("mediatype", "tvshow")
|
||||
@@ -1084,15 +1175,36 @@ def _show_search_results(query: str) -> None:
|
||||
plugin_name.casefold() == "einschalten" and _get_setting_bool("einschalten_enable_playback", default=False)
|
||||
)
|
||||
extra_params = _series_url_params(plugin, title)
|
||||
list_items.append(
|
||||
{
|
||||
"label": label,
|
||||
"action": "play_movie" if direct_play else "seasons",
|
||||
"params": {"plugin": plugin_name, "title": title, **extra_params},
|
||||
"is_folder": (not direct_play),
|
||||
"info_labels": merged_info,
|
||||
"art": art,
|
||||
"cast": cast,
|
||||
}
|
||||
)
|
||||
if canceled:
|
||||
break
|
||||
if not canceled:
|
||||
progress(100, "Suche abgeschlossen")
|
||||
if canceled and not list_items:
|
||||
xbmcgui.Dialog().notification("Suche", "Suche abgebrochen.", xbmcgui.NOTIFICATION_INFO, 2500)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
return
|
||||
|
||||
for item in list_items:
|
||||
_add_directory_item(
|
||||
handle,
|
||||
label,
|
||||
"play_movie" if direct_play else "seasons",
|
||||
{"plugin": plugin_name, "title": title, **extra_params},
|
||||
is_folder=not direct_play,
|
||||
info_labels=merged_info,
|
||||
art=art,
|
||||
cast=cast,
|
||||
str(item["label"]),
|
||||
str(item["action"]),
|
||||
dict(item["params"]),
|
||||
is_folder=bool(item["is_folder"]),
|
||||
info_labels=item["info_labels"],
|
||||
art=item["art"],
|
||||
cast=item["cast"],
|
||||
)
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user