Files
DemonEditor/app/ui/picons_manager.py

761 lines
33 KiB
Python
Raw Normal View History

import os
2018-01-15 14:56:17 +03:00
import re
import shutil
2018-01-12 14:32:36 +03:00
import subprocess
import tempfile
2020-05-25 11:42:41 +03:00
from pathlib import Path
2018-01-10 12:15:41 +03:00
from gi.repository import GLib, GdkPixbuf
2018-01-10 12:15:41 +03:00
2020-02-28 20:59:53 +03:00
from app.commons import run_idle, run_task, run_with_delay
2020-01-23 00:47:01 +03:00
from app.connections import upload_data, DownloadType, download_data, remove_picons
2020-04-26 19:26:36 +03:00
from app.settings import SettingsType, Settings
2020-01-23 00:47:01 +03:00
from app.tools.picons import PiconsParser, parse_providers, Provider, convert_to
from app.tools.satellites import SatellitesParser, SatelliteSource
2018-05-01 21:05:18 +03:00
from .dialogs import show_dialog, DialogType, get_message
from .main_helper import update_entry_data, append_text_to_tview, scroll_to, on_popup_menu, get_base_model, set_picon, \
get_picon_pixbuf
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TV_ICON, Column
2018-01-08 22:00:48 +03:00
class PiconsDialog:
def __init__(self, transient, settings, picon_ids, sat_positions, app):
2018-02-05 14:44:42 +03:00
self._picon_ids = picon_ids
self._sat_positions = sat_positions
self._app = app
2018-01-12 14:32:36 +03:00
self._TMP_DIR = tempfile.gettempdir() + "/"
self._BASE_URL = "www.lyngsat.com/packages/"
self._PATTERN = re.compile(r"^https://www\.lyngsat\.com/[\w-]+\.html$")
self._POS_PATTERN = re.compile(r"^\d+\.\d+[EW]?$")
2018-01-10 12:15:41 +03:00
self._current_process = None
2018-01-16 12:11:54 +03:00
self._terminate = False
self._filter_binding = None
self._services = None
self._current_picon_info = None
2018-01-10 12:15:41 +03:00
handlers = {"on_receive": self.on_receive,
2018-01-15 14:56:17 +03:00
"on_load_providers": self.on_load_providers,
2018-01-10 12:15:41 +03:00
"on_cancel": self.on_cancel,
"on_close": self.on_close,
2018-01-11 17:59:59 +03:00
"on_send": self.on_send,
2020-01-23 00:47:01 +03:00
"on_download": self.on_download,
"on_remove": self.on_remove,
2018-01-11 17:59:59 +03:00
"on_info_bar_close": self.on_info_bar_close,
2018-01-15 14:56:17 +03:00
"on_picons_dir_open": self.on_picons_dir_open,
"on_selected_toggled": self.on_selected_toggled,
2018-02-04 18:09:37 +03:00
"on_url_changed": self.on_url_changed,
2020-02-28 20:59:53 +03:00
"on_picons_filter_changed": self.on_picons_filter_changed,
2018-03-03 13:38:33 +03:00
"on_position_edited": self.on_position_edited,
2020-04-26 19:26:36 +03:00
"on_visible_page": self.on_visible_page,
"on_convert": self.on_convert,
"on_picons_src_changed": self.on_picons_src_changed,
"on_picons_dest_changed": self.on_picons_dest_changed,
2020-06-06 09:36:11 +03:00
"on_picons_src_view_drag_drop": self.on_picons_src_view_drag_drop,
"on_picons_src_view_drag_data_received": self.on_picons_src_view_drag_data_received,
"on_picons_src_view_drag_data_get": self.on_picons_src_view_drag_data_get,
"on_picons_src_view_drag_end": self.on_picons_src_view_drag_end,
"on_picon_info_image_drag_data_received": self.on_picon_info_image_drag_data_received,
"on_picons_dest_view_realize": self.on_picons_dest_view_realize,
"on_satellites_view_realize": self.on_satellites_view_realize,
"on_satellite_selection": self.on_satellite_selection,
"on_select_all": self.on_select_all,
"on_unselect_all": self.on_unselect_all,
2020-02-28 20:59:53 +03:00
"on_filter_toggled": self.on_filter_toggled,
"on_fiter_srcs_toggled": self.on_fiter_srcs_toggled,
"on_filter_services_switch": self.on_filter_services_switch,
"on_picon_activated": self.on_picon_activated,
"on_popup_menu": on_popup_menu}
2018-01-08 22:00:48 +03:00
builder = Gtk.Builder()
2020-04-26 19:26:36 +03:00
builder.add_from_file(UI_RESOURCES_PATH + "picons_manager.glade")
2018-01-08 22:00:48 +03:00
builder.connect_signals(handlers)
2018-09-07 23:10:48 +03:00
2018-01-08 22:00:48 +03:00
self._dialog = builder.get_object("picons_dialog")
self._dialog.set_transient_for(transient)
self._picons_src_view = builder.get_object("picons_src_view")
self._picons_dest_view = builder.get_object("picons_dest_view")
2020-02-28 20:59:53 +03:00
self._providers_view = builder.get_object("providers_view")
self._satellites_view = builder.get_object("satellites_view")
self._picons_src_filter_model = builder.get_object("picons_src_filter_model")
self._picons_src_filter_model.set_visible_func(self.picons_src_filter_function)
self._picons_dst_filter_model = builder.get_object("picons_dst_filter_model")
self._picons_dst_filter_model.set_visible_func(self.picons_dst_filter_function)
self._explorer_src_path_button = builder.get_object("explorer_src_path_button")
self._explorer_dest_path_button = builder.get_object("explorer_dest_path_button")
2018-01-10 12:15:41 +03:00
self._expander = builder.get_object("expander")
self._text_view = builder.get_object("text_view")
self._info_bar = builder.get_object("info_bar")
2020-02-28 20:59:53 +03:00
self._filter_bar = builder.get_object("filter_bar")
self._filter_button = builder.get_object("filter_button")
self._src_filter_button = builder.get_object("src_filter_button")
self._dst_filter_button = builder.get_object("dst_filter_button")
2020-02-28 20:59:53 +03:00
self._picons_filter_entry = builder.get_object("picons_filter_entry")
2018-01-10 18:09:44 +03:00
self._ip_entry = builder.get_object("ip_entry")
self._picons_entry = builder.get_object("picons_entry")
self._url_entry = builder.get_object("url_entry")
self._picons_dir_entry = builder.get_object("picons_dir_entry")
2018-01-11 17:59:59 +03:00
self._info_bar = builder.get_object("info_bar")
self._info_bar = builder.get_object("info_bar")
self._message_label = builder.get_object("info_bar_message_label")
self._info_check_button = builder.get_object("info_check_button")
self._picon_info_image = builder.get_object("picon_info_image")
self._picon_info_label = builder.get_object("picon_info_label")
2018-09-07 23:10:48 +03:00
self._load_providers_button = builder.get_object("load_providers_button")
self._receive_button = builder.get_object("receive_button")
self._convert_button = builder.get_object("convert_button")
2018-03-03 13:38:33 +03:00
self._enigma2_path_button = builder.get_object("enigma2_path_button")
self._save_to_button = builder.get_object("save_to_button")
2018-09-07 23:10:48 +03:00
self._send_button = builder.get_object("send_button")
self._cancel_button = builder.get_object("cancel_button")
2018-01-17 01:18:02 +03:00
self._enigma2_radio_button = builder.get_object("enigma2_radio_button")
self._neutrino_mp_radio_button = builder.get_object("neutrino_mp_radio_button")
2018-01-20 22:17:18 +03:00
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._satellite_label = builder.get_object("satellite_label")
2020-01-23 00:47:01 +03:00
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)
2020-01-23 00:47:01 +03:00
self._cancel_button.bind_property("visible", self._header_download_box, "visible", 4)
self._convert_button.bind_property("visible", self._header_download_box, "visible", 4)
2020-02-28 20:59:53 +03:00
self._load_providers_button.bind_property("visible", self._receive_button, "visible")
self._load_providers_button.bind_property("visible", builder.get_object("download_box_separator"), "visible")
self._filter_bar.bind_property("search-mode-enabled", self._filter_bar, "visible")
self._explorer_src_path_button.bind_property("sensitive", builder.get_object("picons_view_sw"), "sensitive")
self._filter_button.bind_property("active", builder.get_object("filter_service_box"), "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("visible", self._info_check_button, "visible")
self._info_check_button.bind_property("active", builder.get_object("explorer_info_bar"), "visible")
2020-02-28 20:59:53 +03:00
# Init drag-and-drop
self.init_drag_and_drop()
# Style
2018-01-15 14:56:17 +03:00
self._style_provider = Gtk.CssProvider()
self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css")
self._url_entry.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_USER)
2019-12-13 13:31:07 +03:00
self._settings = settings
2019-12-22 20:42:29 +03:00
self._s_type = settings.setting_type
2019-12-13 13:31:07 +03:00
self._ip_entry.set_text(self._settings.host)
self._picons_entry.set_text(self._settings.picons_path)
2020-04-26 19:26:36 +03:00
self._picons_dir_entry.set_text(self._settings.picons_local_path)
2020-01-23 00:47:01 +03:00
window_size = self._settings.get("picons_downloader_window_size")
if window_size:
self._dialog.resize(*window_size)
2019-12-22 20:42:29 +03:00
if not len(self._picon_ids) and self._s_type is SettingsType.ENIGMA_2:
message = get_message("To automatically set the identifiers for picons,\n"
"first load the required services list into the main application window.")
self.show_info_message(message, Gtk.MessageType.WARNING)
self._satellite_label.show()
2018-01-08 22:00:48 +03:00
def show(self):
2020-02-28 20:59:53 +03:00
self._dialog.show()
def on_picons_dest_view_realize(self, view):
self._services = {s.picon_id: s for s in self._app.current_services.values() if s.picon_id}
self._explorer_dest_path_button.select_filename(self._settings.picons_local_path)
2020-02-28 20:59:53 +03:00
def on_picons_src_changed(self, button):
self.update_picons_data(self._picons_src_view, button)
def on_picons_dest_changed(self, button):
self.update_picon_info()
self.update_picons_data(self._picons_dest_view, button)
def update_picons_data(self, view, button):
2020-02-28 20:59:53 +03:00
path = button.get_filename()
if not path or not os.path.exists(path):
return
GLib.idle_add(button.set_sensitive, False)
gen = self.update_picons(path, view, button)
2020-02-28 20:59:53 +03:00
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
def update_picons(self, path, view, button):
p_model = view.get_model()
2020-05-12 20:44:37 +03:00
if not p_model:
button.set_sensitive(True)
2020-05-12 20:44:37 +03:00
return
2020-02-28 20:59:53 +03:00
model = get_base_model(p_model)
view.set_model(None)
factor = self._app.DEL_FACTOR
2020-04-26 19:26:36 +03:00
for index, itr in enumerate([row.iter for row in model]):
model.remove(itr)
if index % factor == 0:
2020-04-26 19:26:36 +03:00
yield True
2020-02-28 20:59:53 +03:00
for file in os.listdir(path):
if self._terminate:
return
p_path = "{}/{}".format(path, file)
p = self.get_pixbuf_at_scale(p_path, 72, 48, True)
if p:
yield model.append((p, file, p_path))
2020-02-28 20:59:53 +03:00
view.set_model(p_model)
button.set_sensitive(True)
2020-02-28 20:59:53 +03:00
yield True
2020-05-25 11:42:41 +03:00
def update_picons_from_file(self, view, uri):
""" Adds picons in the view on dragging from file system. """
from urllib.parse import unquote, urlparse
path = Path(urlparse(unquote(uri)).path.strip())
f_path = str(path.resolve())
if not f_path:
return
model = get_base_model(view.get_model())
2020-05-25 11:42:41 +03:00
if path.is_file():
p = self.get_pixbuf_at_scale(f_path, 72, 48, True)
if p:
model.append((p, path.name, f_path))
2020-05-25 11:42:41 +03:00
elif path.is_dir():
self._explorer_src_path_button.select_filename(f_path)
def get_pixbuf_at_scale(self, path, width, height, p_ratio):
try:
return GdkPixbuf.Pixbuf.new_from_file_at_scale(path, width, height, p_ratio)
except GLib.GError:
pass
2020-05-25 11:42:41 +03:00
2020-02-28 20:59:53 +03:00
# ***************** Drag-and-drop ********************* #
def init_drag_and_drop(self):
self._picons_src_view.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.COPY)
self._picons_src_view.drag_source_add_uri_targets()
self._picons_src_view.enable_model_drag_dest([], Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
self._picons_src_view.drag_dest_add_text_targets()
self._picon_info_image.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
self._picon_info_image.drag_dest_add_uri_targets()
2020-02-28 20:59:53 +03:00
2020-06-06 09:36:11 +03:00
def on_picons_src_view_drag_drop(self, view, drag_context, x, y, time):
view.stop_emission_by_name("drag_drop")
2020-04-26 19:26:36 +03:00
targets = drag_context.list_targets()
view.drag_get_data(drag_context, targets[-1] if targets else Gdk.atom_intern("text/plain", False), time)
2020-06-06 09:36:11 +03:00
def on_picons_src_view_drag_data_received(self, view, drag_context, x, y, data, info, time):
view.stop_emission_by_name("drag_data_received")
txt = data.get_text()
if not txt:
return
2020-05-18 12:34:28 +03:00
if txt.startswith("file://"):
2020-05-25 11:42:41 +03:00
self.update_picons_from_file(view, txt)
2020-05-18 12:34:28 +03:00
return
itr_str, sep, src = txt.partition("::::")
if src == self._app.BQ_MODEL_NAME:
return
path, pos = view.get_dest_row_at_pos(x, y) or (None, None)
if not path:
return
model = view.get_model()
if src == self._app.FAV_MODEL_NAME:
target_view = self._app.fav_view
c_id = Column.FAV_ID
else:
target_view = self._app.services_view
c_id = Column.SRV_FAV_ID
t_mod = target_view.get_model()
2020-06-06 09:36:11 +03:00
dest_path = self._explorer_dest_path_button.get_filename() + "/"
self.update_picons_dest_view(self._app.on_assign_picon(target_view, model[path][-1], dest_path))
self.show_assign_info([t_mod.get_value(t_mod.get_iter_from_string(itr), c_id) for itr in itr_str.split(",")])
2020-06-06 09:36:11 +03:00
@run_idle
def update_picons_dest_view(self, picons):
""" Update destination view on adding/changing picons. """
if picons:
dest_model = get_base_model(self._picons_dest_view.get_model())
paths = {r[1]: r.iter for r in dest_model}
for p_path in picons:
p = self.get_pixbuf_at_scale(p_path, 72, 48, True)
if p:
p_name = Path(p_path).name
itr = paths.get(p_name, None)
if itr:
dest_model.set_value(itr, 0, p)
else:
itr = dest_model.append((p, p_name, p_path))
scroll_to(dest_model.get_path(itr), self._picons_dest_view)
@run_idle
def show_assign_info(self, fav_ids):
self._expander.set_expanded(True)
self._text_view.get_buffer().set_text("")
for i in fav_ids:
srv = self._app.current_services.get(i, None)
if srv:
info = self._app.get_hint_for_srv_list(srv)
self.append_output("Picon assignment for the service:\n{}\n{}\n".format(info, " * " * 30))
2020-06-06 09:36:11 +03:00
def on_picons_src_view_drag_data_get(self, view, drag_context, data, info, time):
model, path = view.get_selection().get_selected_rows()
if path:
data.set_uris([Path(model[path][-1]).as_uri(),
Path(self._explorer_dest_path_button.get_filename()).as_uri()])
2020-06-06 09:36:11 +03:00
def on_picons_src_view_drag_end(self, view, drag_context):
self.update_picons_dest_view(self._app.picons_buffer)
def on_picon_info_image_drag_data_received(self, img, drag_context, x, y, data, info, time):
if not self._current_picon_info:
self.show_info_message("No selected item!", Gtk.MessageType.ERROR)
return
2020-02-28 20:59:53 +03:00
uris = data.get_uris()
if len(uris) == 2:
name, fav_id = self._current_picon_info
from urllib.parse import unquote, urlparse
src = urlparse(unquote(uris[0])).path
dst = "{}/{}".format(urlparse(unquote(uris[1])).path, name)
if src != dst:
shutil.copy(src, dst)
for row in get_base_model(self._picons_dest_view.get_model()):
if name == row[1]:
row[0] = self.get_pixbuf_at_scale(row[-1], 72, 48, True)
img.set_from_pixbuf(self.get_pixbuf_at_scale(row[-1], 100, 60, True))
gen = self.update_picon_in_lists(dst, fav_id)
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
def update_picon_in_lists(self, dst, fav_id):
picon = get_picon_pixbuf(dst)
p_pos = Column.SRV_PICON
yield set_picon(fav_id, get_base_model(self._app.services_view.get_model()), picon, Column.SRV_FAV_ID, p_pos)
yield set_picon(fav_id, get_base_model(self._app.fav_view.get_model()), picon, Column.FAV_ID, p_pos)
# ******************** Download/Upload/Remove ************************* #
def on_selective_send(self, view):
self.on_send(files_filter=self.get_selected_paths(view))
def on_selective_download(self, view):
self.on_download(files_filter=self.get_selected_paths(view))
def on_selective_remove(self, view):
self.on_remove(files_filter=self.get_selected_paths(view))
def on_send(self, item=None, files_filter=None):
dest_path = self.check_dest_path()
if not dest_path:
return
settings = Settings(self._settings.settings)
settings.picons_local_path = dest_path + "/"
self.show_info_message(get_message("Please, wait..."), Gtk.MessageType.INFO)
self.run_func(lambda: upload_data(settings=settings,
download_type=DownloadType.PICONS,
callback=self.append_output,
done_callback=lambda: self.show_info_message(get_message("Done!"),
Gtk.MessageType.INFO),
files_filter=files_filter))
def on_download(self, item=None, files_filter=None):
path = self.check_dest_path()
if not path:
return
settings = Settings(self._settings.settings)
settings.picons_local_path = path + "/"
self.run_func(lambda: download_data(settings=settings,
download_type=DownloadType.PICONS,
callback=self.append_output,
files_filter=files_filter), True)
def on_remove(self, item, files_filter=None):
if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL:
return
self.run_func(lambda: remove_picons(settings=self._settings,
callback=self.append_output,
done_callback=lambda: self.show_info_message(get_message("Done!"),
Gtk.MessageType.INFO),
files_filter=files_filter))
def get_selected_paths(self, view):
model, paths = view.get_selection().get_selected_rows()
return {model[p][1] for p in paths}
def check_dest_path(self):
""" Checks the destination path and returns if present. """
if show_dialog(DialogType.QUESTION, self._dialog) != Gtk.ResponseType.OK:
return
path = self._explorer_dest_path_button.get_filename()
if not path:
show_dialog(DialogType.ERROR, transient=self._dialog, text="Select paths!")
return
return path
# ******************** Downloader ************************* #
2018-01-08 22:00:48 +03:00
def on_satellites_view_realize(self, view):
self.get_satellites(view)
@run_task
def get_satellites(self, view):
sats = SatellitesParser().get_satellites_list(SatelliteSource.LYNGSAT)
if not sats:
self.show_info_message("Getting satellites list error!", Gtk.MessageType.ERROR)
gen = self.append_satellites(view.get_model(), sats)
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
def append_satellites(self, model, sats):
try:
for sat in sats:
pos = sat[1]
name, pos = "{} ({})".format(sat[0], pos), "{}{}".format("-" if pos[-1] == "W" else "", pos[:-1])
if not self._terminate and model:
if pos in self._sat_positions:
yield model.append((name, sat[3], pos))
finally:
self._satellite_label.show()
def on_satellite_selection(self, view, path, column):
model = view.get_model()
self._url_entry.set_text(model.get(model.get_iter(path), 1)[0])
2018-01-15 14:56:17 +03:00
@run_idle
def on_load_providers(self, item):
self._expander.set_expanded(True)
self.on_info_bar_close()
self._cancel_button.show()
2018-01-15 14:56:17 +03:00
url = self._url_entry.get_text()
2020-01-23 00:47:01 +03:00
try:
self._current_process = subprocess.Popen(["wget", "-pkP", self._TMP_DIR, url],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
except FileNotFoundError as e:
self._cancel_button.hide()
self.show_info_message(str(e), Gtk.MessageType.ERROR)
else:
GLib.io_add_watch(self._current_process.stderr, GLib.IO_IN, self.write_to_buffer)
2020-02-28 20:59:53 +03:00
model = self._providers_view.get_model()
2020-01-23 00:47:01 +03:00
model.clear()
self.append_providers(url, model)
2018-03-07 22:43:42 +03:00
@run_task
def append_providers(self, url, model):
2018-01-15 14:56:17 +03:00
self._current_process.wait()
try:
self._terminate = False
providers = parse_providers(self._TMP_DIR + url[url.find("w"):])
except FileNotFoundError:
pass # NOP
else:
if providers:
for p in providers:
if self._terminate:
return
model.append((self.get_pixbuf(p[0]) if p[0] else TV_ICON, *p[1:]))
self.update_receive_button_state()
finally:
GLib.idle_add(self._cancel_button.hide)
self._terminate = False
2018-01-15 14:56:17 +03:00
def get_pixbuf(self, img_url):
return GdkPixbuf.Pixbuf.new_from_file_at_scale(filename=self._TMP_DIR + "www.lyngsat.com/" + img_url,
width=48, height=48, preserve_aspect_ratio=True)
2018-01-10 12:15:41 +03:00
def on_receive(self, item):
self._cancel_button.show()
2018-01-11 17:59:59 +03:00
self.start_download()
2018-01-10 12:15:41 +03:00
2018-01-16 01:16:03 +03:00
@run_task
2018-01-11 17:59:59 +03:00
def start_download(self):
2018-01-16 12:11:54 +03:00
if self._current_process.poll() is None:
self.show_dialog("The task is already running!", DialogType.ERROR)
return
self._terminate = False
2018-01-11 17:59:59 +03:00
self._expander.set_expanded(True)
2018-01-16 01:16:03 +03:00
providers = self.get_selected_providers()
2018-03-07 22:43:42 +03:00
for prv in providers:
if not self._POS_PATTERN.match(prv[2]):
2018-03-07 22:43:42 +03:00
self.show_info_message(
get_message("Specify the correct position value for the provider!"), Gtk.MessageType.ERROR)
2020-02-28 20:59:53 +03:00
scroll_to(prv.path, self._providers_view)
2018-03-07 22:43:42 +03:00
return
try:
for prv in providers:
if self._terminate:
return
self.process_provider(Provider(*prv))
if self._resize_no_radio_button.get_active():
2020-04-26 19:26:36 +03:00
self.resize(self._picons_dir_entry.get_text())
self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO)
finally:
GLib.idle_add(self._cancel_button.hide)
self._terminate = False
2018-01-16 01:16:03 +03:00
2018-02-04 18:09:37 +03:00
def process_provider(self, prv):
url = prv.url
2018-03-06 11:34:06 +03:00
self.show_info_message(get_message("Please, wait..."), Gtk.MessageType.INFO)
2018-01-12 14:32:36 +03:00
self._current_process = subprocess.Popen(["wget", "-pkP", self._TMP_DIR, url],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
GLib.io_add_watch(self._current_process.stderr, GLib.IO_IN, self.write_to_buffer)
self._current_process.wait()
path = self._TMP_DIR + (url[url.find("//") + 2:] if prv.single else self._BASE_URL + url[url.rfind("/") + 1:])
2020-04-26 19:26:36 +03:00
PiconsParser.parse(path, self._picons_dir_entry.get_text(),
self._TMP_DIR, prv, self._picon_ids, self.get_picons_format())
2018-01-11 17:59:59 +03:00
2018-01-10 12:15:41 +03:00
def write_to_buffer(self, fd, condition):
if condition == GLib.IO_IN:
2018-01-10 18:09:44 +03:00
char = fd.read(1)
2018-01-12 14:32:36 +03:00
self.append_output(char)
2018-01-10 12:15:41 +03:00
return True
return False
2018-01-10 12:15:41 +03:00
2018-01-12 14:32:36 +03:00
@run_idle
def append_output(self, char):
2018-05-01 21:05:18 +03:00
append_text_to_tview(char, self._text_view)
2018-01-11 17:59:59 +03:00
2018-01-20 22:17:18 +03:00
def resize(self, path):
2018-03-06 11:34:06 +03:00
self.show_info_message(get_message("Resizing..."), Gtk.MessageType.INFO)
2018-01-20 22:17:18 +03:00
command = "mogrify -resize {}! *.png".format(
2020-01-23 23:42:28 +03:00
"220x132" if self._resize_220_132_radio_button.get_active() else "100x60").split()
2018-09-01 00:49:11 +03:00
try:
self._current_process = subprocess.Popen(command, universal_newlines=True, cwd=path)
self._current_process.wait()
except FileNotFoundError as e:
self.show_info_message("Conversion error. " + str(e), Gtk.MessageType.ERROR)
2018-01-20 22:17:18 +03:00
2018-09-01 00:49:11 +03:00
def on_cancel(self, item=None):
if self.is_task_running() and show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL:
return True
self.terminate_task()
@run_task
def terminate_task(self):
self._terminate = True
2018-01-10 12:15:41 +03:00
if self._current_process:
2018-01-16 12:11:54 +03:00
self._current_process.terminate()
self.show_info_message(get_message("The task is canceled!"), Gtk.MessageType.WARNING)
2018-01-10 12:15:41 +03:00
def on_close(self, window, event):
if self.on_cancel():
return True
2020-02-28 20:59:53 +03:00
self._terminate = True
2020-01-23 00:47:01 +03:00
self.save_window_size(window)
self.clean_data()
self._app.update_picons()
GLib.idle_add(self._dialog.destroy)
2020-01-23 00:47:01 +03:00
def save_window_size(self, window):
size = window.get_size()
2020-04-26 19:26:36 +03:00
height = size.height - self._text_view.get_allocated_height() - self._info_bar.get_allocated_height()
self._settings.add("picons_downloader_window_size", (size.width, height))
2020-01-23 00:47:01 +03:00
@run_task
def clean_data(self):
path = self._TMP_DIR + "www.lyngsat.com"
if os.path.exists(path):
shutil.rmtree(path)
2018-01-10 18:09:44 +03:00
2020-01-23 00:47:01 +03:00
@run_task
2020-04-26 19:26:36 +03:00
def run_func(self, func, update=False):
2018-09-19 11:46:41 +03:00
try:
2019-09-10 00:28:38 +03:00
GLib.idle_add(self._expander.set_expanded, True)
2020-01-23 00:47:01 +03:00
GLib.idle_add(self._header_download_box.set_sensitive, False)
func()
2018-09-19 11:46:41 +03:00
except OSError as e:
self.show_info_message(str(e), Gtk.MessageType.ERROR)
2020-04-26 19:26:36 +03:00
finally:
GLib.idle_add(self._header_download_box.set_sensitive, True)
if update:
self.on_picons_dest_changed(self._explorer_dest_path_button)
2018-01-10 12:15:41 +03:00
2018-01-11 17:59:59 +03:00
def on_info_bar_close(self, bar=None, resp=None):
self._info_bar.set_visible(False)
@run_idle
def show_info_message(self, text, message_type):
self._info_bar.set_visible(True)
self._info_bar.set_message_type(message_type)
2020-05-18 12:34:28 +03:00
self._message_label.set_text(get_message(text))
2018-01-11 17:59:59 +03:00
def on_picons_dir_open(self, entry, icon, event_button):
update_entry_data(entry, self._dialog, settings=self._settings)
2018-01-11 17:59:59 +03:00
2018-01-16 01:16:03 +03:00
@run_idle
2018-01-15 14:56:17 +03:00
def on_selected_toggled(self, toggle, path):
2020-02-28 20:59:53 +03:00
model = self._providers_view.get_model()
model.set_value(model.get_iter(path), 7, not toggle.get_active())
2018-01-16 01:16:03 +03:00
self.update_receive_button_state()
2018-01-15 14:56:17 +03:00
def on_select_all(self, view):
self.update_selection(view, True)
def on_unselect_all(self, view):
self.update_selection(view, False)
def update_selection(self, view, select):
view.get_model().foreach(lambda mod, path, itr: mod.set_value(itr, 7, select))
self.update_receive_button_state()
# *********************** Filter **************************** #
2020-02-28 20:59:53 +03:00
def on_filter_toggled(self, button):
active = button.get_active()
self._filter_bar.set_search_mode(active)
if not active:
self._picons_filter_entry.set_text("")
def on_fiter_srcs_toggled(self, filter_model):
""" Activates re-filtering for model when filter check-button has toggled. """
GLib.idle_add(filter_model.refilter, priority=GLib.PRIORITY_LOW)
def on_filter_services_switch(self, button, state):
""" Activates or deactivates filtering in the main list of services. """
if state:
self._filter_binding = self._picons_filter_entry.bind_property("text", self._app.filter_entry, "text")
self._app.filter_entry.set_text(self._picons_filter_entry.get_text())
else:
if self._filter_binding:
self._filter_binding.unbind()
self._app.filter_entry.set_text("")
2020-02-28 20:59:53 +03:00
@run_with_delay(1)
def on_picons_filter_changed(self, entry):
GLib.idle_add(self._picons_src_filter_model.refilter, priority=GLib.PRIORITY_LOW)
GLib.idle_add(self._picons_dst_filter_model.refilter, priority=GLib.PRIORITY_LOW)
def picons_src_filter_function(self, model, itr, data):
return self.filter_function(itr, model, self._src_filter_button.get_active())
def picons_dst_filter_function(self, model, itr, data):
return self.filter_function(itr, model, self._dst_filter_button.get_active())
2020-02-28 20:59:53 +03:00
def filter_function(self, itr, model, active):
""" Main filtering function. """
if any((not active, model is None, model == "None")):
2020-02-28 20:59:53 +03:00
return True
t = model.get_value(itr, 1)
2020-05-10 13:22:13 +03:00
if not t:
return True
txt = self._picons_filter_entry.get_text().upper()
return txt in t.upper() or t in (
map(lambda s: s.picon_id, filter(lambda s: txt in s.service.upper(), self._app.current_services.values())))
2020-02-28 20:59:53 +03:00
def on_picon_activated(self, view):
if self._info_check_button.get_active():
model, path = view.get_selection().get_selected_rows()
if not path:
return
row = model[path][:]
name, path = row[1], row[-1]
srv = self._services.get(row[1], None)
self.update_picon_info(name, path, srv)
def update_picon_info(self, name=None, path=None, srv=None):
self._picon_info_image.set_from_pixbuf(self.get_pixbuf_at_scale(path, 100, 60, True) if path else None)
self._picon_info_label.set_text(self.get_service_info(srv))
self._current_picon_info = (name, srv.fav_id) if srv else None
def get_service_info(self, srv):
""" Returns short info about the service. """
if not srv:
return ""
if srv.service_type == "IPTV":
return self._app.get_hint_for_srv_list(srv)
header, ref = self._app.get_hint_header_info(srv)
return "{} {}: {}\n{}: {} {}: {}\n{}".format(header.rstrip(), get_message("Package"), srv.package,
get_message("System"), srv.system, get_message("Freq"), srv.freq,
ref)
def on_url_changed(self, entry):
suit = self._PATTERN.search(entry.get_text())
entry.set_name("GtkEntry" if suit else "digit-entry")
self._load_providers_button.set_sensitive(suit if suit else False)
2018-02-04 18:09:37 +03:00
def on_position_edited(self, render, path, value):
2020-02-28 20:59:53 +03:00
model = self._providers_view.get_model()
2018-02-04 18:09:37 +03:00
model.set_value(model.get_iter(path), 2, value)
2018-03-03 13:38:33 +03:00
@run_idle
2020-04-26 19:26:36 +03:00
def on_visible_page(self, stack: Gtk.Stack, param):
name = stack.get_visible_child_name()
self._convert_button.set_visible(name == "converter")
self._load_providers_button.set_visible(name == "downloader")
is_explorer = name == "explorer"
2020-02-28 20:59:53 +03:00
self._filter_button.set_visible(is_explorer)
if is_explorer:
self.on_picons_dest_changed(self._explorer_dest_path_button)
2018-03-03 13:38:33 +03:00
2018-03-04 19:37:41 +03:00
@run_idle
2018-03-03 13:38:33 +03:00
def on_convert(self, item):
2018-03-06 11:34:06 +03:00
if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL:
return
2018-03-03 13:38:33 +03:00
picons_path = self._enigma2_path_button.get_filename()
save_path = self._save_to_button.get_filename()
if not picons_path or not save_path:
show_dialog(DialogType.ERROR, transient=self._dialog, text="Select paths!")
return
2018-03-03 13:38:33 +03:00
2018-03-04 19:37:41 +03:00
self._expander.set_expanded(True)
convert_to(src_path=picons_path,
dest_path=save_path,
2019-12-22 20:42:29 +03:00
s_type=SettingsType.ENIGMA_2,
2018-03-04 19:37:41 +03:00
callback=self.append_output,
2018-03-06 11:34:06 +03:00
done_callback=lambda: self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO))
2018-03-04 19:37:41 +03:00
2018-01-16 01:16:03 +03:00
@run_idle
def update_receive_button_state(self):
try:
2019-09-10 00:37:48 +03:00
self._receive_button.set_sensitive(len(self.get_selected_providers()) > 0)
except TypeError:
2019-09-10 00:37:48 +03:00
pass # NOP
2018-01-16 01:16:03 +03:00
def get_selected_providers(self):
""" returns selected providers """
2020-02-28 20:59:53 +03:00
return [r for r in self._providers_view.get_model() if r[7]]
2018-01-16 01:16:03 +03:00
2018-01-16 12:11:54 +03:00
@run_idle
def show_dialog(self, message, dialog_type):
show_dialog(dialog_type, self._dialog, message)
2018-01-17 01:18:02 +03:00
def get_picons_format(self):
2019-12-22 20:42:29 +03:00
picon_format = SettingsType.ENIGMA_2
2018-01-17 01:18:02 +03:00
if self._neutrino_mp_radio_button.get_active():
2019-12-22 20:42:29 +03:00
picon_format = SettingsType.NEUTRINO_MP
2018-01-17 01:18:02 +03:00
return picon_format
def is_task_running(self):
return self._current_process and self._current_process.poll() is None
2018-01-08 22:00:48 +03:00
if __name__ == "__main__":
pass