minor rework of the picon manager

This commit is contained in:
DYefremov
2021-10-07 13:08:50 +03:00
parent bc94bb3505
commit 1e5c47c3cc
5 changed files with 1184 additions and 1110 deletions

View File

@@ -37,7 +37,7 @@ from html.parser import HTMLParser
import requests import requests
from app.commons import run_task, log from app.commons import run_task, log
from app.settings import SettingsType from app.settings import SettingsType, IS_LINUX, IS_WIN
from .satellites import _HEADERS from .satellites import _HEADERS
_ENIGMA2_PICON_KEY = "{:X}:{:X}:{}" _ENIGMA2_PICON_KEY = "{:X}:{:X}:{}"
@@ -57,7 +57,7 @@ class PiconsCzDownloader:
_PERM_URL = "https://picon.cz/download/7337" _PERM_URL = "https://picon.cz/download/7337"
_BASE_URL = "https://picon.cz/download/" _BASE_URL = "https://picon.cz/download/"
_BASE_LOGO_URL = "https://picon.cz/picon/0/" _BASE_LOGO_URL = "https://picon.cz/picon/0/"
_HEADER = {"User-Agent": "DemonEditor/1.0.10", "Referer": ""} _HEADER = {"User-Agent": "DemonEditor/2.0.0", "Referer": ""}
_LINK_PATTERN = re.compile(r"((.*)-\d+x\d+)-(.*)_by_chocholousek.7z$") _LINK_PATTERN = re.compile(r"((.*)-\d+x\d+)-(.*)_by_chocholousek.7z$")
_FILE_PATTERN = re.compile(b"\\s+(1_.*\\.png).*") _FILE_PATTERN = re.compile(b"\\s+(1_.*\\.png).*")
@@ -81,7 +81,11 @@ class PiconsCzDownloader:
name_map = self.get_name_map() name_map = self.get_name_map()
for line in request.iter_lines(): for line in request.iter_lines():
l_id, perm_link = line.decode(encoding="utf-8", errors="ignore").split(maxsplit=1) data = line.decode(encoding="utf-8", errors="ignore").split(maxsplit=1)
if len(data) != 2:
continue
l_id, perm_link = data
self._perm_links[str(l_id)] = str(perm_link) self._perm_links[str(l_id)] = str(perm_link)
data = re.match(self._LINK_PATTERN, perm_link) data = re.match(self._LINK_PATTERN, perm_link)
if data: if data:
@@ -89,7 +93,7 @@ class PiconsCzDownloader:
# Logo url. # Logo url.
logo = logo_map.get(data.group(2), None) logo = logo_map.get(data.group(2), None)
l_name = name_map.get(sat_pos, None) or sat_pos.replace(".", "") l_name = name_map.get(sat_pos, None) or sat_pos.replace(".", "")
logo_url = "{}{}/{}.png".format(self._BASE_LOGO_URL, logo, l_name) if logo else None logo_url = f"{self._BASE_LOGO_URL}{logo}/{l_name}.png" if logo else None
prv = Provider(None, data.group(1), sat_pos, self._BASE_URL + l_id, l_id, logo_url, None, False) prv = Provider(None, data.group(1), sat_pos, self._BASE_URL + l_id, l_id, logo_url, None, False)
if sat_pos in self._providers: if sat_pos in self._providers:
@@ -97,7 +101,7 @@ class PiconsCzDownloader:
else: else:
self._providers[sat_pos] = [prv] self._providers[sat_pos] = [prv]
else: else:
log("{} [get permalinks] error: {}".format(self.__class__.__name__, request.reason)) log(f"{self.__class__.__name__} [get permalinks] error: {request.reason}")
raise PiconsError(request.reason) raise PiconsError(request.reason)
@property @property
@@ -111,31 +115,36 @@ class PiconsCzDownloader:
self._HEADER["Referer"] = provider.url self._HEADER["Referer"] = provider.url
with requests.get(url=provider.url, headers=self._HEADER, stream=True) as request: with requests.get(url=provider.url, headers=self._HEADER, stream=True) as request:
if request.reason == "OK": if request.reason == "OK":
dest = "{}{}.7z".format(picons_path, provider.on_id) dest = f"{picons_path}{provider.on_id}.7z"
self._appender("Downloading: {}\n".format(provider.url)) self._appender(f"Downloading: {provider.url}\n")
with open(dest, mode="bw") as f: with open(dest, mode="bw") as f:
for data in request.iter_content(chunk_size=1024): for data in request.iter_content(chunk_size=1024):
f.write(data) f.write(data)
self._appender("Extracting: {}\n".format(provider.on_id)) self._appender(f"Extracting: {provider.on_id}\n")
self.extract(dest, picons_path, picon_ids) self.extract(dest, picons_path, picon_ids)
else: else:
log("{} [download] error: {}".format(self.__class__.__name__, request.reason)) log(f"{self.__class__.__name__} [download] error: {request.reason}")
def extract(self, src, dest, picon_ids=None): def extract(self, src, dest, picon_ids=None):
""" Extracts 7z archives. """ """ Extracts 7z archives. """
# TODO: think about https://github.com/miurahr/py7zr # TODO: think about https://github.com/miurahr/py7zr
exe = "7zr" exe = "7zr"
if not os.path.isfile("/usr/bin/7zr"): if IS_LINUX and not os.path.isfile("/usr/bin/7zr"):
raise PiconsError("7-zip [7zr] archiver not found!") raise PiconsError("7-zip [7zr] archiver not found!")
if IS_WIN:
exe = "C:\\Program Files\\7-Zip\\7z.exe"
if not os.path.isfile(exe):
raise PiconsError("7-Zip executable not found!")
cmd = [exe, "l", src] cmd = [exe, "l", src]
try: try:
out, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() out, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
if err: if err:
log("{} [extract] error: {}".format(self.__class__.__name__, err)) log(f"{self.__class__.__name__} [extract] error: {err}")
raise PiconsError(err) raise PiconsError(err)
except OSError as e: except OSError as e:
log("{} [extract] error: {}".format(self.__class__.__name__, e)) log(f"{self.__class__.__name__} [extract] error: {e}")
raise PiconsError(e) raise PiconsError(e)
is_filter = bool(picon_ids) is_filter = bool(picon_ids)
@@ -157,7 +166,7 @@ class PiconsCzDownloader:
try: try:
out, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() out, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
if err: if err:
log("{} [extract] error: {}".format(self.__class__.__name__, err)) log(f"{self.__class__.__name__} [extract] error: {err}")
raise PiconsError(err) raise PiconsError(err)
else: else:
if os.path.isfile(src): if os.path.isfile(src):
@@ -184,9 +193,9 @@ class PiconsCzDownloader:
self._provider_logos[url] = data self._provider_logos[url] = data
return data return data
else: else:
log("Downloading package logo error: {}".format(logo_request.reason)) log(f"Downloading package logo error: {logo_request.reason}")
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
log("{} error [get provider logo]: {}".format(self.__class__.__name__, e)) log(f"{self.__class__.__name__} error [get provider logo]: {e}")
def get_logos_map(self): def get_logos_map(self):
return {"piconblack": "b50", return {"piconblack": "b50",

View File

@@ -1321,14 +1321,14 @@ Author: Dmitriy Yefremov
<property name="margin_bottom">5</property> <property name="margin_bottom">5</property>
<property name="spacing">5</property> <property name="spacing">5</property>
<child> <child>
<object class="GtkToggleButton" id="filter_header_button"> <object class="GtkToggleButton" id="filter_services_button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property> <property name="sensitive">False</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="focus_on_click">False</property> <property name="focus_on_click">False</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Filter</property> <property name="tooltip_text" translatable="yes">Filter</property>
<property name="action_name">win.filter</property> <signal name="toggled" handler="on_services_filter_toggled" swapped="no"/>
<child> <child>
<object class="GtkImage" id="filter_header_button_image"> <object class="GtkImage" id="filter_header_button_image">
<property name="visible">True</property> <property name="visible">True</property>
@@ -3288,6 +3288,7 @@ Author: Dmitriy Yefremov
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Info</property> <property name="label" translatable="yes">Info</property>
<property name="ellipsize">end</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>

View File

@@ -164,6 +164,7 @@ class Application(Gtk.Application):
"on_mark_duplicates": self.on_mark_duplicates, "on_mark_duplicates": self.on_mark_duplicates,
"on_filter_changed": self.on_filter_changed, "on_filter_changed": self.on_filter_changed,
"on_filter_type_toggled": self.on_filter_type_toggled, "on_filter_type_toggled": self.on_filter_type_toggled,
"on_services_filter_toggled": self.on_services_filter_toggled,
"on_filter_satellite_toggled": self.on_filter_satellite_toggled, "on_filter_satellite_toggled": self.on_filter_satellite_toggled,
"on_assign_picon": self.on_assign_picon, "on_assign_picon": self.on_assign_picon,
"on_remove_picon": self.on_remove_picon, "on_remove_picon": self.on_remove_picon,
@@ -261,6 +262,8 @@ class Application(Gtk.Application):
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
GObject.signal_new("data-load-done", self, GObject.SIGNAL_RUN_LAST, GObject.signal_new("data-load-done", self, GObject.SIGNAL_RUN_LAST,
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
GObject.signal_new("filter-toggled", self, GObject.SIGNAL_RUN_LAST,
GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,))
builder = get_builder(UI_RESOURCES_PATH + "main.glade", handlers) builder = get_builder(UI_RESOURCES_PATH + "main.glade", handlers)
self._main_window = builder.get_object("main_window") self._main_window = builder.get_object("main_window")
@@ -325,13 +328,13 @@ class Application(Gtk.Application):
# Filter # Filter
self._services_model_filter = builder.get_object("services_model_filter") self._services_model_filter = builder.get_object("services_model_filter")
self._services_model_filter.set_visible_func(self.services_filter_function) self._services_model_filter.set_visible_func(self.services_filter_function)
self._filter_header_button = builder.get_object("filter_header_button") self._filter_services_button = builder.get_object("filter_services_button")
self._filter_entry = builder.get_object("filter_entry") self._filter_entry = builder.get_object("filter_entry")
self._filter_box = builder.get_object("filter_box") self._filter_box = builder.get_object("filter_box")
self._filter_types_model = builder.get_object("filter_types_list_store") self._filter_types_model = builder.get_object("filter_types_list_store")
self._filter_sat_pos_model = builder.get_object("filter_sat_pos_list_store") self._filter_sat_pos_model = builder.get_object("filter_sat_pos_list_store")
self._filter_only_free_button = builder.get_object("filter_only_free_button") self._filter_only_free_button = builder.get_object("filter_only_free_button")
self._services_load_spinner.bind_property("active", self._filter_header_button, "sensitive", 4) self._services_load_spinner.bind_property("active", self._filter_services_button, "sensitive", 4)
self._services_load_spinner.bind_property("active", self._filter_box, "sensitive", 4) self._services_load_spinner.bind_property("active", self._filter_box, "sensitive", 4)
# Search. # Search.
services_search_provider = SearchProvider(self._services_view, services_search_provider = SearchProvider(self._services_view,
@@ -458,9 +461,10 @@ class Application(Gtk.Application):
self.set_action("on_about_app", self.on_about_app) self.set_action("on_about_app", self.on_about_app)
self.set_action("on_close_app", self.on_close_app) self.set_action("on_close_app", self.on_close_app)
# Filter. # Filter.
filter_action = Gio.SimpleAction.new_stateful("filter", None, GLib.Variant.new_boolean(False)) filter_action = Gio.SimpleAction.new("filter", None)
filter_action.connect("change-state", self.on_filter_toggled) filter_action.connect("activate", lambda a, v: self.emit("filter-toggled", None))
self._main_window.add_action(filter_action) # For "win.*" actions! self._main_window.add_action(filter_action) # For "win.*" actions!
self.connect("filter-toggled", self.on_services_filter_toggled)
# Lock, Hide. # Lock, Hide.
self.set_action("on_hide", self.on_hide) self.set_action("on_hide", self.on_hide)
self.set_action("on_locked", self.on_locked) self.set_action("on_locked", self.on_locked)
@@ -1646,7 +1650,7 @@ class Application(Gtk.Application):
def update_data(self, data_path, callback=None): def update_data(self, data_path, callback=None):
self._profile_combo_box.set_sensitive(False) self._profile_combo_box.set_sensitive(False)
self._alt_revealer.set_visible(False) self._alt_revealer.set_visible(False)
self._filter_header_button.set_active(False) self._filter_services_button.set_active(False)
self._wait_dialog.show() self._wait_dialog.show()
yield from self.clear_current_data() yield from self.clear_current_data()
@@ -2958,15 +2962,15 @@ class Application(Gtk.Application):
# ***************** Filter and search ********************* # # ***************** Filter and search ********************* #
def on_filter_toggled(self, action, value): def on_services_filter_toggled(self, app=None, value=None):
if self._app_info_box.get_visible() or self._services_load_spinner.get_property("active"): if self._page is not Page.SERVICES and self._services_load_spinner.get_property("active"):
return True return True
action.set_state(value) active = not self._filter_box.get_visible()
self._filter_services_button.set_active(active)
self._filter_entry.grab_focus() if value else self.on_filter_changed() self._filter_entry.grab_focus() if active else self.on_filter_changed()
self.filter_set_default() self.filter_set_default()
self._filter_box.set_visible(value) self._filter_box.set_visible(active)
@run_idle @run_idle
def filter_set_default(self): def filter_set_default(self):
@@ -3551,6 +3555,10 @@ class Application(Gtk.Application):
def is_enigma(self, value): def is_enigma(self, value):
self._is_enigma = value self._is_enigma = value
@property
def page(self):
return self._page
def start_app(): def start_app():
try: try:

File diff suppressed because it is too large Load Diff

View File

@@ -57,6 +57,7 @@ class PiconManager(Gtk.Box):
self._app = app self._app = app
self._app.connect("page-changed", self.update_picons_dest) self._app.connect("page-changed", self.update_picons_dest)
self._app.connect("filter-toggled", self.on_app_filter_toggled)
self._picon_ids = picon_ids self._picon_ids = picon_ids
self._sat_positions = sat_positions self._sat_positions = sat_positions
self._BASE_URL = "www.lyngsat.com/packages/" self._BASE_URL = "www.lyngsat.com/packages/"
@@ -161,7 +162,9 @@ class PiconManager(Gtk.Box):
self._satellite_label.bind_property("visible", self._satellites_view, "sensitive") self._satellite_label.bind_property("visible", self._satellites_view, "sensitive")
self._cancel_button.bind_property("visible", self._header_download_box, "visible", 4) self._cancel_button.bind_property("visible", self._header_download_box, "visible", 4)
self._convert_button.bind_property("visible", self._header_download_box, "visible", 4) self._convert_button.bind_property("visible", self._header_download_box, "visible", 4)
self._convert_button.bind_property("visible", builder.get_object("converter_label"), "visible")
self._download_source_button.bind_property("visible", self._receive_button, "visible") self._download_source_button.bind_property("visible", self._receive_button, "visible")
self._download_source_button.bind_property("visible", builder.get_object("downloader_label"), "visible")
self._filter_bar.bind_property("search-mode-enabled", self._filter_bar, "visible") self._filter_bar.bind_property("search-mode-enabled", self._filter_bar, "visible")
self._filter_button.bind_property("active", builder.get_object("src_title_grid"), "visible") self._filter_button.bind_property("active", builder.get_object("src_title_grid"), "visible")
self._filter_button.bind_property("active", builder.get_object("dst_title_grid"), "visible") self._filter_button.bind_property("active", builder.get_object("dst_title_grid"), "visible")
@@ -169,6 +172,11 @@ class PiconManager(Gtk.Box):
self._filter_button.bind_property("visible", self._send_button, "visible") self._filter_button.bind_property("visible", self._send_button, "visible")
self._filter_button.bind_property("visible", self._download_button, "visible") self._filter_button.bind_property("visible", self._download_button, "visible")
self._filter_button.bind_property("visible", self._remove_button, "visible") self._filter_button.bind_property("visible", self._remove_button, "visible")
self._filter_button.bind_property("visible", builder.get_object("manager_label"), "visible")
self._src_button = builder.get_object("src_button")
self._src_button.bind_property("active", builder.get_object("explorer_dst_label"), "visible")
self._src_button.bind_property("active", builder.get_object("src_picon_box_frame"), "visible")
self._filter_button.bind_property("visible", self._src_button, "visible")
explorer_info_bar = builder.get_object("explorer_info_bar") explorer_info_bar = builder.get_object("explorer_info_bar")
explorer_info_bar.bind_property("visible", builder.get_object("explorer_info_bar_frame"), "visible") explorer_info_bar.bind_property("visible", builder.get_object("explorer_info_bar_frame"), "visible")
self._info_check_button.bind_property("active", explorer_info_bar, "visible") self._info_check_button.bind_property("active", explorer_info_bar, "visible")
@@ -194,6 +202,7 @@ class PiconManager(Gtk.Box):
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT): if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
return return
self._src_button.set_active(True)
self.update_picons_data(self._picons_src_view, response) self.update_picons_data(self._picons_src_view, response)
def update_picons_dest(self, app, page): def update_picons_dest(self, app, page):
@@ -246,7 +255,7 @@ class PiconManager(Gtk.Box):
if p: if p:
model.append((p, path.name, f_path)) model.append((p, path.name, f_path))
elif path.is_dir(): elif path.is_dir():
self._explorer_src_path_button.select_filename(f_path) self.update_picons_data(view, f_path)
def get_pixbuf_at_scale(self, path, width, height, p_ratio): def get_pixbuf_at_scale(self, path, width, height, p_ratio):
try: try:
@@ -647,6 +656,7 @@ class PiconManager(Gtk.Box):
if not self._resize_no_radio_button.get_active(): if not self._resize_no_radio_button.get_active():
self.resize(picons_path) self.resize(picons_path)
finally: finally:
self._app.update_picons()
GLib.idle_add(self._cancel_button.hide) GLib.idle_add(self._cancel_button.hide)
self._is_downloading = False self._is_downloading = False
@@ -793,8 +803,12 @@ class PiconManager(Gtk.Box):
# *********************** Filter **************************** # # *********************** Filter **************************** #
def on_app_filter_toggled(self, app, value):
if app.page is Page.PICONS:
self._filter_button.set_active(not self._filter_button.get_active())
def on_filter_toggled(self, button): def on_filter_toggled(self, button):
active = button.get_active() active = self._filter_button.get_active()
self._filter_bar.set_search_mode(active) self._filter_bar.set_search_mode(active)
if not active: if not active:
self._picons_filter_entry.set_text("") self._picons_filter_entry.set_text("")