added picons loading only for the selected bouquet

This commit is contained in:
DYefremov
2021-05-11 12:46:26 +03:00
parent a99c1e00b9
commit 2656d0b3a9
4 changed files with 127 additions and 54 deletions

View File

@@ -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:

View File

@@ -3423,6 +3423,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. """

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2
<!-- Generated with glade 3.22.1
The MIT License (MIT)
@@ -988,7 +988,7 @@ Author: Dmitriy Yefremov
<property name="wide_handle">True</property>
<child>
<object class="GtkBox" id="satellites_box">
<property name="width_request">250</property>
<property name="width_request">180</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">2</property>
@@ -1016,6 +1016,7 @@ Author: Dmitriy Yefremov
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Loading data...</property>
<property name="ellipsize">end</property>
</object>
<packing>
<property name="expand">False</property>
@@ -1027,6 +1028,7 @@ Author: Dmitriy Yefremov
<object class="GtkSpinner" id="loading_data_spinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">5</property>
<property name="active">True</property>
</object>
<packing>
@@ -1040,24 +1042,7 @@ Author: Dmitriy Yefremov
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">5</property>
<property name="column_spacing">2</property>
<child>
<object class="GtkCheckButton" id="satellite_filter_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="focus_on_click">False</property>
<property name="receives_default">False</property>
<property name="valign">center</property>
<property name="image_position">right</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_satellite_filter_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<property name="column_spacing">5</property>
<child>
<object class="GtkLabel" id="satellite_filter_label">
<property name="visible">True</property>
@@ -1069,6 +1054,17 @@ Author: Dmitriy Yefremov
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="satellite_filter_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="active">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@@ -1149,24 +1145,71 @@ Author: Dmitriy Yefremov
</child>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">True</property>
<property name="resize">True</property>
<property name="shrink">False</property>
</packing>
</child>
<child>
<object class="GtkBox" id="proveders_pox">
<property name="width_request">280</property>
<property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">2</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkLabel" id="provider_header_label">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkLabel" id="provider_header_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">5</property>
<property name="ellipsize">end</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="bouquet_filter_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="column_spacing">5</property>
<child>
<object class="GtkSwitch" id="bouquet_filter_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="bouquet_filter_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Load only for selected bouquet</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@@ -1396,7 +1439,7 @@ Author: Dmitriy Yefremov
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
<property name="shrink">False</property>
</packing>
</child>
</object>

View File

@@ -26,7 +26,6 @@
#
import concurrent.futures
import os
import re
import shutil
@@ -165,7 +164,9 @@ class PiconsDialog:
self._resize_100_60_radio_button = builder.get_object("resize_100_60_radio_button")
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._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)
@@ -508,6 +509,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)
@@ -553,14 +555,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):
@@ -587,7 +593,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):
@@ -678,13 +684,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.
@@ -706,27 +712,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))