From e076bfffce8e6896511544678839678f36ec478d Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sat, 15 May 2021 13:13:02 +0300 Subject: [PATCH] added picons loading only for the selected bouquet --- app/tools/picons.py | 16 +++++-- app/ui/main_app_window.py | 4 ++ app/ui/picons_manager.glade | 85 ++++++++++++++++++++++++++++--------- app/ui/picons_manager.py | 67 ++++++++++++++++++----------- 4 files changed, 123 insertions(+), 49 deletions(-) diff --git a/app/tools/picons.py b/app/tools/picons.py index a56cafe0..eb6f859c 100644 --- a/app/tools/picons.py +++ b/app/tools/picons.py @@ -107,7 +107,7 @@ class PiconsCzDownloader: def get_sat_providers(self, url): return self._providers.get(url, []) - def download(self, provider, picons_path): + def download(self, provider, picons_path, picon_ids=None): self._HEADER["Referer"] = provider.url with requests.get(url=provider.url, headers=self._HEADER, stream=True) as request: if request.reason == "OK": @@ -117,11 +117,11 @@ class PiconsCzDownloader: for data in request.iter_content(chunk_size=1024): f.write(data) self._appender("Extracting: {}\n".format(provider.on_id)) - self.extract(dest, picons_path) + self.extract(dest, picons_path, picon_ids) else: log("{} [download] error: {}".format(self.__class__.__name__, request.reason)) - def extract(self, src, dest): + def extract(self, src, dest, picon_ids=None): """ Extracts 7z archives. """ # TODO: think about https://github.com/miurahr/py7zr cmd = ["7zr", "l", src] @@ -134,12 +134,20 @@ class PiconsCzDownloader: log("{} [extract] error: {}".format(self.__class__.__name__, e)) raise PiconsError(e) + is_filter = bool(picon_ids) + ids = picon_ids or self._picon_ids to_extract = [] + for o in re.finditer(self._FILE_PATTERN, out): p_id = o.group(1).decode("utf-8", errors="ignore") - if p_id in self._picon_ids: + if p_id in ids: to_extract.append(p_id) + if is_filter and not to_extract: + if os.path.isfile(src): + os.remove(src) + raise PiconsError("No matching picons found!") + cmd = ["7zr", "e", src, "-o{}".format(dest), "-y", "-r"] cmd.extend(to_extract) try: diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 2ffbaa01..da975e7f 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -3571,6 +3571,10 @@ class Application(Gtk.Application): def current_services(self): return self._services + @property + def current_bouquets(self): + return self._bouquets + @property def picons_buffer(self): """ Returns a copy and clears the current buffer. """ diff --git a/app/ui/picons_manager.glade b/app/ui/picons_manager.glade index abaccbfc..d60bdc2f 100644 --- a/app/ui/picons_manager.glade +++ b/app/ui/picons_manager.glade @@ -898,23 +898,7 @@ Author: Dmitriy Yefremov True False - 2 - - - True - True - False - False - center - right - True - True - - - 1 - 0 - - + 5 True @@ -926,6 +910,17 @@ Author: Dmitriy Yefremov 0 + + + True + True + True + + + 1 + 0 + + False @@ -1018,11 +1013,57 @@ Author: Dmitriy Yefremov vertical 2 - + True False - start - 10 + 10 + + + True + False + start + end + + + False + True + 0 + + + + + True + False + 5 + + + True + True + + + 1 + 0 + + + + + True + False + Load only for selected bouquet + + + 0 + 0 + + + + + False + True + end + 1 + + False @@ -1051,9 +1092,10 @@ Author: Dmitriy Yefremov 15 - Providers + Name True 0.5 + 1 @@ -1137,6 +1179,7 @@ Author: Dmitriy Yefremov Selected + 7 diff --git a/app/ui/picons_manager.py b/app/ui/picons_manager.py index ffc7109f..bcd83d64 100644 --- a/app/ui/picons_manager.py +++ b/app/ui/picons_manager.py @@ -26,7 +26,6 @@ # -import concurrent.futures import os import re import shutil @@ -161,10 +160,13 @@ class PiconsDialog: self._resize_no_radio_button = builder.get_object("resize_no_radio_button") self._resize_220_132_radio_button = builder.get_object("resize_220_132_radio_button") self._resize_100_60_radio_button = builder.get_object("resize_100_60_radio_button") + self._explorer_action_box = builder.get_object("explorer_action_box") self._satellite_label = builder.get_object("satellite_label") self._provider_header_label = builder.get_object("provider_header_label") - self._satellite_filter_button = builder.get_object("satellite_filter_button") - self._explorer_action_box = builder.get_object("explorer_action_box") + self._satellite_filter_switch = builder.get_object("satellite_filter_switch") + self._bouquet_filter_switch = builder.get_object("bouquet_filter_switch") + self._bouquet_filter_grid = builder.get_object("bouquet_filter_grid") + self._header_download_box = builder.get_object("header_download_box") self._satellite_label.bind_property("visible", builder.get_object("loading_data_label"), "visible", 4) self._satellite_label.bind_property("visible", builder.get_object("loading_data_spinner"), "visible", 4) self._satellite_label.bind_property("visible", self._download_source_button, "sensitive") @@ -509,6 +511,7 @@ class PiconsDialog: def on_download_source_changed(self, button): self._download_src = self.DownloadSource(button.get_active_id()) self.set_providers_header() + self._bouquet_filter_grid.set_sensitive(self._download_src is self.DownloadSource.PICON_CZ) GLib.idle_add(self._providers_view.get_model().clear) self.init_satellites(self._satellites_view) @@ -554,14 +557,18 @@ class PiconsDialog: @run_idle def set_providers_header(self): msg = "{} [{}]" + tooltip = "" if self._download_src is self.DownloadSource.PICON_CZ: - msg = msg.format(get_message("Package"), "https://picon.cz (by ChocholouĊĦek)") + tooltip = "https://picon.cz (by ChocholouĊĦek)" + msg = msg.format(get_message("Package"), tooltip) elif self._download_src is self.DownloadSource.LYNG_SAT: - msg = msg.format(get_message("Providers"), "https://www.lyngsat.com") + tooltip = "https://www.lyngsat.com" + msg = msg.format(get_message("Providers"), tooltip) else: msg = "" self._provider_header_label.set_text(msg) + self._provider_header_label.set_tooltip_text(tooltip) @run_task def get_satellites(self, view): @@ -588,7 +595,7 @@ class PiconsDialog: GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW) def append_satellites(self, model, sats): - is_filter = self._satellite_filter_button.get_active() + is_filter = self._satellite_filter_switch.get_active() model.clear() try: for sat in sorted(sats): @@ -679,13 +686,13 @@ class PiconsDialog: if not self._resize_no_radio_button.get_active(): self.resize(picons_path) - else: - self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO) finally: GLib.idle_add(self._cancel_button.hide) self._is_downloading = False def get_picons_for_lyngsat(self, path, providers): + import concurrent.futures + with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: picons = [] # Getting links to picons. @@ -707,27 +714,39 @@ class PiconsDialog: for future in not_done: future.cancel() concurrent.futures.wait(not_done) + self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO) def get_picons_for_picon_cz(self, path, providers): - with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: - futures = {executor.submit(self._picon_cz_downloader.download, p, path): p for p in providers} - for future in concurrent.futures.as_completed(futures): - if not self._is_downloading: - executor.shutdown() - return + p_ids = None + if self._bouquet_filter_switch.get_active(): + p_ids = self.get_bouquet_picon_ids() + if not p_ids: + return - try: - future.result() - except PiconsError as e: - self.append_output("Error: {}\n".format(str(e))) + try: + # We download it sequentially. + for p in providers: + self._picon_cz_downloader.download(p, path, p_ids) + except PiconsError as e: + self.append_output("Error: {}\n".format(str(e))) + self.show_info_message(str(e), Gtk.MessageType.ERROR) + else: + self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO) - done, not_done = concurrent.futures.wait(futures, timeout=0) - while self._is_downloading and not_done: - done, not_done = concurrent.futures.wait(not_done, timeout=5) + def get_bouquet_picon_ids(self): + """ Returns picon ids for selected bouquet or None. """ + bq_selected = self._app.check_bouquet_selection() + if not bq_selected: + return - for future in not_done: - future.cancel() - concurrent.futures.wait(not_done) + model, paths = self._app.bouquets_view.get_selection().get_selected_rows() + if len(paths) > 1: + self.show_dialog("Please, select only one bouquet!", DialogType.ERROR) + return + + fav_bouquet = self._app.current_bouquets[bq_selected] + services = self._app.current_services + return {services.get(fav_id).picon_id for fav_id in fav_bouquet} def process_provider(self, prv, picons_path): self.append_output("Getting links to picons for: {}.\n".format(prv.name))