2020-11-02 21:55:34 +03:00
|
|
|
import concurrent.futures
|
2017-11-15 17:54:16 +03:00
|
|
|
import re
|
2018-05-05 22:01:50 +03:00
|
|
|
import time
|
2017-10-31 20:49:36 +03:00
|
|
|
from math import fabs
|
|
|
|
|
|
2019-05-26 22:11:52 +03:00
|
|
|
from gi.repository import GLib
|
|
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
from app.commons import run_idle, run_task, log
|
2017-11-09 19:01:09 +03:00
|
|
|
from app.eparser import get_satellites, write_satellites, Satellite, Transponder
|
2019-03-22 00:54:44 +03:00
|
|
|
from app.eparser.ecommons import PLS_MODE, get_key_by_value
|
2020-11-02 21:55:34 +03:00
|
|
|
from app.tools.satellites import SatellitesParser, SatelliteSource, ServicesParser
|
2020-04-19 13:23:18 +03:00
|
|
|
from .dialogs import show_dialog, DialogType, get_dialogs_string, get_chooser_dialog
|
2018-10-21 11:10:45 +03:00
|
|
|
from .main_helper import move_items, scroll_to, append_text_to_tview, get_base_model, on_popup_menu
|
2020-04-21 14:43:57 +03:00
|
|
|
from .search import SearchProvider
|
|
|
|
|
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TEXT_DOMAIN, MOVE_KEYS, KeyboardKey, IS_GNOME_SESSION, MOD_MASK
|
2017-10-14 13:23:34 +03:00
|
|
|
|
2019-05-10 14:42:32 +03:00
|
|
|
_UI_PATH = UI_RESOURCES_PATH + "satellites_dialog.glade"
|
|
|
|
|
|
2017-10-14 13:23:34 +03:00
|
|
|
|
2017-11-01 20:15:22 +03:00
|
|
|
def show_satellites_dialog(transient, options):
|
2018-04-25 17:26:29 +03:00
|
|
|
SatellitesDialog(transient, options).show()
|
2017-10-14 13:23:34 +03:00
|
|
|
|
|
|
|
|
|
2017-10-30 16:20:19 +03:00
|
|
|
class SatellitesDialog:
|
2017-11-09 19:01:09 +03:00
|
|
|
_aggr = [None for x in range(9)] # aggregate
|
|
|
|
|
|
2019-12-13 13:31:07 +03:00
|
|
|
def __init__(self, transient, settings):
|
2019-12-22 20:42:29 +03:00
|
|
|
self._data_path = settings.data_local_path + "satellites.xml"
|
2019-12-13 13:31:07 +03:00
|
|
|
self._settings = settings
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2017-11-03 23:39:15 +03:00
|
|
|
handlers = {"on_open": self.on_open,
|
2017-10-30 16:20:19 +03:00
|
|
|
"on_remove": self.on_remove,
|
|
|
|
|
"on_save": self.on_save,
|
2018-07-13 17:12:02 +03:00
|
|
|
"on_save_as": self.on_save_as,
|
2018-04-25 17:26:29 +03:00
|
|
|
"on_update": self.on_update,
|
2017-12-23 22:25:29 +03:00
|
|
|
"on_up": self.on_up,
|
|
|
|
|
"on_down": self.on_down,
|
2018-10-21 11:10:45 +03:00
|
|
|
"on_popup_menu": on_popup_menu,
|
2017-11-11 00:08:40 +03:00
|
|
|
"on_satellite_add": self.on_satellite_add,
|
|
|
|
|
"on_transponder_add": self.on_transponder_add,
|
2017-11-01 20:15:22 +03:00
|
|
|
"on_edit": self.on_edit,
|
|
|
|
|
"on_key_release": self.on_key_release,
|
2017-11-03 23:39:15 +03:00
|
|
|
"on_row_activated": self.on_row_activated,
|
2017-11-10 13:38:03 +03:00
|
|
|
"on_resize": self.on_resize,
|
|
|
|
|
"on_quit": self.on_quit}
|
2017-10-30 16:20:19 +03:00
|
|
|
|
|
|
|
|
builder = Gtk.Builder()
|
2018-03-02 17:06:53 +03:00
|
|
|
builder.set_translation_domain(TEXT_DOMAIN)
|
2019-05-10 14:42:32 +03:00
|
|
|
builder.add_objects_from_string(get_dialogs_string(_UI_PATH),
|
|
|
|
|
("satellites_editor_window", "satellites_tree_store", "popup_menu",
|
|
|
|
|
"left_header_menu", "popup_menu_add_image", "popup_menu_add_image_2"))
|
2017-10-30 16:20:19 +03:00
|
|
|
builder.connect_signals(handlers)
|
|
|
|
|
|
2018-08-05 00:54:30 +03:00
|
|
|
self._window = builder.get_object("satellites_editor_window")
|
|
|
|
|
self._window.set_transient_for(transient)
|
2017-11-03 23:39:15 +03:00
|
|
|
self._sat_view = builder.get_object("satellites_editor_tree_view")
|
2017-11-01 20:15:22 +03:00
|
|
|
# Setting the last size of the dialog window if it was saved
|
2019-12-13 13:31:07 +03:00
|
|
|
window_size = self._settings.get("sat_editor_window_size")
|
2017-11-01 20:15:22 +03:00
|
|
|
if window_size:
|
2018-08-05 00:54:30 +03:00
|
|
|
self._window.resize(*window_size)
|
2017-11-01 20:15:22 +03:00
|
|
|
|
2017-10-30 16:20:19 +03:00
|
|
|
self._stores = {3: builder.get_object("pol_store"),
|
|
|
|
|
4: builder.get_object("fec_store"),
|
|
|
|
|
5: builder.get_object("system_store"),
|
|
|
|
|
6: builder.get_object("mod_store")}
|
2019-05-26 22:11:52 +03:00
|
|
|
|
2019-05-30 12:57:31 +03:00
|
|
|
self.load_satellites_list(self._sat_view.get_model())
|
|
|
|
|
|
|
|
|
|
def load_satellites_list(self, model):
|
|
|
|
|
gen = self.on_satellites_list_load(model)
|
2019-05-26 22:11:52 +03:00
|
|
|
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2018-04-25 17:26:29 +03:00
|
|
|
def show(self):
|
2018-08-05 00:54:30 +03:00
|
|
|
self._window.show()
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2017-11-01 20:15:22 +03:00
|
|
|
def on_resize(self, window):
|
|
|
|
|
""" Stores new size properties for dialog window after resize """
|
2019-12-13 13:31:07 +03:00
|
|
|
if self._settings:
|
|
|
|
|
self._settings.add("sat_editor_window_size", window.get_size())
|
2017-11-01 20:15:22 +03:00
|
|
|
|
2018-07-13 17:12:02 +03:00
|
|
|
@run_idle
|
2018-07-05 17:59:17 +03:00
|
|
|
def on_quit(self, *args):
|
2018-08-05 00:54:30 +03:00
|
|
|
self._window.destroy()
|
2017-11-10 13:38:03 +03:00
|
|
|
|
2018-07-13 17:12:02 +03:00
|
|
|
@run_idle
|
2017-11-03 23:39:15 +03:00
|
|
|
def on_open(self, model):
|
2020-04-21 14:43:57 +03:00
|
|
|
response = get_chooser_dialog(self._window, self._settings, "satellites.xml", ("*.xml",))
|
2020-04-19 13:23:18 +03:00
|
|
|
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
2017-12-13 13:52:19 +03:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if not str(response).endswith("satellites.xml"):
|
2018-08-05 00:54:30 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._window, text="No satellites.xml file is selected!")
|
2017-12-13 13:52:19 +03:00
|
|
|
return
|
2020-04-19 13:23:18 +03:00
|
|
|
|
2017-12-13 13:52:19 +03:00
|
|
|
self._data_path = response
|
2019-05-30 12:57:31 +03:00
|
|
|
self.load_satellites_list(model)
|
2017-11-03 23:39:15 +03:00
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def on_row_activated(view, path, column):
|
|
|
|
|
if view.row_expanded(path):
|
|
|
|
|
view.collapse_row(path)
|
|
|
|
|
else:
|
|
|
|
|
view.expand_row(path, column)
|
|
|
|
|
|
2017-12-23 22:25:29 +03:00
|
|
|
def on_up(self, item):
|
2018-11-05 00:31:44 +03:00
|
|
|
move_items(KeyboardKey.UP, self._sat_view)
|
2017-12-23 22:25:29 +03:00
|
|
|
|
|
|
|
|
def on_down(self, item):
|
2018-11-05 00:31:44 +03:00
|
|
|
move_items(KeyboardKey.DOWN, self._sat_view)
|
2017-12-23 22:25:29 +03:00
|
|
|
|
2017-11-01 20:15:22 +03:00
|
|
|
def on_key_release(self, view, event):
|
|
|
|
|
""" Handling keystrokes """
|
2018-11-09 14:14:24 +03:00
|
|
|
key_code = event.hardware_keycode
|
|
|
|
|
if not KeyboardKey.value_exist(key_code):
|
|
|
|
|
return
|
|
|
|
|
key = KeyboardKey(key_code)
|
2020-04-19 13:23:18 +03:00
|
|
|
ctrl = event.state & MOD_MASK
|
2017-11-01 20:15:22 +03:00
|
|
|
|
2018-11-05 00:31:44 +03:00
|
|
|
if key is KeyboardKey.DELETE:
|
2017-11-01 20:15:22 +03:00
|
|
|
self.on_remove(view)
|
2018-11-05 00:31:44 +03:00
|
|
|
elif key is KeyboardKey.INSERT:
|
2017-11-11 00:08:40 +03:00
|
|
|
pass
|
2018-11-05 00:31:44 +03:00
|
|
|
elif ctrl and key is KeyboardKey.E:
|
2017-11-01 20:15:22 +03:00
|
|
|
self.on_edit(view)
|
2018-11-05 00:31:44 +03:00
|
|
|
elif ctrl and key is KeyboardKey.S:
|
2017-11-03 23:39:15 +03:00
|
|
|
self.on_satellite()
|
2018-11-05 00:31:44 +03:00
|
|
|
elif ctrl and key is KeyboardKey.T:
|
2017-11-03 23:39:15 +03:00
|
|
|
self.on_transponder()
|
2018-04-16 19:42:48 +03:00
|
|
|
elif ctrl and key in MOVE_KEYS:
|
2017-12-23 22:25:29 +03:00
|
|
|
move_items(key, self._sat_view)
|
2018-11-05 00:31:44 +03:00
|
|
|
elif key is KeyboardKey.LEFT or key is KeyboardKey.RIGHT:
|
2018-04-14 00:05:08 +03:00
|
|
|
view.do_unselect_all(view)
|
2017-11-01 20:15:22 +03:00
|
|
|
|
2017-10-30 16:20:19 +03:00
|
|
|
def on_satellites_list_load(self, model):
|
|
|
|
|
""" Load satellites data into model """
|
2017-11-09 19:01:09 +03:00
|
|
|
try:
|
|
|
|
|
satellites = get_satellites(self._data_path)
|
2019-05-26 22:11:52 +03:00
|
|
|
yield True
|
2017-11-09 19:01:09 +03:00
|
|
|
except FileNotFoundError as e:
|
2018-08-05 00:54:30 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._window, getattr(e, "message", str(e)) +
|
2017-11-09 19:01:09 +03:00
|
|
|
"\n\nPlease, download files from receiver or setup your path for read data!")
|
2019-05-26 22:11:52 +03:00
|
|
|
return
|
2017-11-09 19:01:09 +03:00
|
|
|
else:
|
|
|
|
|
model.clear()
|
2019-05-26 22:11:52 +03:00
|
|
|
for sat in satellites:
|
|
|
|
|
append_satellite(model, sat)
|
|
|
|
|
yield True
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
def on_add(self, view):
|
2017-11-09 19:01:09 +03:00
|
|
|
""" Common adding """
|
2017-10-31 20:49:36 +03:00
|
|
|
self.on_edit(view, force=True)
|
|
|
|
|
|
2017-11-11 00:08:40 +03:00
|
|
|
def on_satellite_add(self, item):
|
|
|
|
|
self.on_satellite(None)
|
|
|
|
|
|
|
|
|
|
def on_transponder_add(self, item):
|
|
|
|
|
self.on_transponder(None)
|
|
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
def on_edit(self, view, force=False):
|
2017-11-09 19:01:09 +03:00
|
|
|
""" Common edit """
|
2017-11-11 00:08:40 +03:00
|
|
|
paths = self.check_selection(view, "Please, select only one item!")
|
2017-11-09 19:01:09 +03:00
|
|
|
if not paths:
|
2017-10-31 20:49:36 +03:00
|
|
|
return
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
model = view.get_model()
|
2017-11-01 20:15:22 +03:00
|
|
|
itr = model.get_iter(paths[0])
|
|
|
|
|
row = model.get(itr, *[x for x in range(view.get_n_columns())])
|
2017-11-11 00:08:40 +03:00
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
if row[-1]: # satellite
|
2017-11-09 19:01:09 +03:00
|
|
|
self.on_satellite(None if force else Satellite(row[0], None, row[-1], None), itr)
|
2017-10-30 16:20:19 +03:00
|
|
|
else:
|
2017-11-26 20:40:22 +03:00
|
|
|
self.on_transponder(None if force else Transponder(*row[1:-2]), itr)
|
2017-10-31 20:49:36 +03:00
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
def on_satellite(self, satellite=None, edited_itr=None):
|
|
|
|
|
""" Create or edit satellite"""
|
2018-08-05 00:54:30 +03:00
|
|
|
sat_dialog = SatelliteDialog(self._window, satellite)
|
2017-10-31 20:49:36 +03:00
|
|
|
sat = sat_dialog.run()
|
|
|
|
|
sat_dialog.destroy()
|
|
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
if sat:
|
|
|
|
|
view = self._sat_view
|
|
|
|
|
model = view.get_model()
|
|
|
|
|
if satellite and edited_itr:
|
|
|
|
|
model.set(edited_itr, {0: sat.name, 10: sat.flags, 11: sat.position})
|
|
|
|
|
else:
|
|
|
|
|
index = self.get_sat_position_index(sat.position, model)
|
|
|
|
|
model.insert(None, index, [sat.name, *self._aggr, sat.flags, sat.position])
|
2017-12-25 19:50:35 +03:00
|
|
|
scroll_to(index, view)
|
2017-11-09 19:01:09 +03:00
|
|
|
|
|
|
|
|
def on_transponder(self, transponder=None, edited_itr=None):
|
|
|
|
|
""" Create or edit transponder """
|
2017-11-15 17:54:16 +03:00
|
|
|
|
|
|
|
|
paths = self.check_selection(self._sat_view, "Please, select only one satellite!")
|
|
|
|
|
if paths is None:
|
|
|
|
|
return
|
|
|
|
|
elif len(paths) == 0:
|
2018-08-05 00:54:30 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._window, "No satellite is selected!")
|
2017-11-11 00:08:40 +03:00
|
|
|
return
|
|
|
|
|
|
2018-08-05 00:54:30 +03:00
|
|
|
dialog = TransponderDialog(self._window, transponder)
|
2017-10-31 20:49:36 +03:00
|
|
|
tr = dialog.run()
|
|
|
|
|
dialog.destroy()
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
if tr:
|
|
|
|
|
view = self._sat_view
|
|
|
|
|
model = view.get_model()
|
|
|
|
|
if transponder and edited_itr:
|
|
|
|
|
model.set(edited_itr, {1: tr.frequency, 2: tr.symbol_rate, 3: tr.polarization,
|
|
|
|
|
4: tr.fec_inner, 5: tr.system, 6: tr.modulation,
|
|
|
|
|
7: tr.pls_mode, 8: tr.pls_code, 9: tr.is_id})
|
|
|
|
|
else:
|
2017-11-11 00:08:40 +03:00
|
|
|
row = ["Transponder:", *tr, None, None]
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
|
|
|
|
itr = model.get_iter(paths[0])
|
|
|
|
|
view.expand_row(paths[0], 0)
|
|
|
|
|
# Get parent iter if selected transponder
|
|
|
|
|
parent_itr = model.iter_parent(itr)
|
|
|
|
|
if parent_itr:
|
|
|
|
|
itr = parent_itr
|
2017-11-17 15:20:17 +03:00
|
|
|
freq = int(tr.frequency if tr.frequency else 0)
|
2017-11-11 00:08:40 +03:00
|
|
|
tr_itr = model.iter_children(itr)
|
|
|
|
|
# Inserting according to frequency value.
|
|
|
|
|
while tr_itr:
|
|
|
|
|
cur_freq = int(model.get_value(tr_itr, 1))
|
|
|
|
|
if freq <= cur_freq:
|
|
|
|
|
path = model.get_path(tr_itr)
|
|
|
|
|
index = path.get_indices()[1]
|
|
|
|
|
model.insert(model.iter_parent(tr_itr), index, row)
|
2017-12-25 19:50:35 +03:00
|
|
|
scroll_to(path, view)
|
2017-11-11 00:08:40 +03:00
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
tr_itr = model.iter_next(tr_itr)
|
|
|
|
|
else:
|
|
|
|
|
itr = model.append(itr, row)
|
2017-12-24 20:54:56 +03:00
|
|
|
scroll_to(model.get_path(itr), view)
|
2017-11-09 19:01:09 +03:00
|
|
|
|
|
|
|
|
def get_sat_position_index(self, pos, model):
|
|
|
|
|
""" Search and returns index after given position """
|
|
|
|
|
pos = int(pos)
|
|
|
|
|
row = next(filter(lambda r: int(r[-1]) >= pos, model), None)
|
|
|
|
|
|
|
|
|
|
return row.path[0] if row else len(model)
|
|
|
|
|
|
2017-11-11 00:08:40 +03:00
|
|
|
def check_selection(self, view, message):
|
2017-11-09 19:01:09 +03:00
|
|
|
""" Checks if any row is selected. Shows error dialog if selected more than one.
|
|
|
|
|
|
|
|
|
|
returns selected path or None
|
|
|
|
|
"""
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
2018-05-10 23:28:51 +03:00
|
|
|
if len(paths) > 1:
|
2018-08-05 00:54:30 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._window, message)
|
2017-11-09 19:01:09 +03:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
return paths
|
2017-11-01 20:15:22 +03:00
|
|
|
|
2017-10-30 16:20:19 +03:00
|
|
|
@staticmethod
|
|
|
|
|
def on_remove(view):
|
|
|
|
|
selection = view.get_selection()
|
|
|
|
|
model, paths = selection.get_selected_rows()
|
2017-10-31 20:49:36 +03:00
|
|
|
|
2018-05-10 23:28:51 +03:00
|
|
|
for itr in [model.get_iter(path) for path in paths]:
|
2017-10-30 16:20:19 +03:00
|
|
|
model.remove(itr)
|
|
|
|
|
|
2018-07-13 17:12:02 +03:00
|
|
|
@run_idle
|
2017-10-30 16:20:19 +03:00
|
|
|
def on_save(self, view):
|
2018-08-05 00:54:30 +03:00
|
|
|
if show_dialog(DialogType.QUESTION, self._window) == Gtk.ResponseType.CANCEL:
|
2017-11-09 19:01:09 +03:00
|
|
|
return
|
|
|
|
|
|
2017-10-30 16:20:19 +03:00
|
|
|
model = view.get_model()
|
|
|
|
|
satellites = []
|
|
|
|
|
model.foreach(self.parse_data, satellites)
|
2017-11-12 23:39:27 +03:00
|
|
|
write_satellites(satellites, self._data_path)
|
2017-10-30 16:20:19 +03:00
|
|
|
|
2018-07-13 17:12:02 +03:00
|
|
|
def on_save_as(self, item):
|
|
|
|
|
response = self.get_file_dialog_response(Gtk.FileChooserAction.SAVE)
|
|
|
|
|
if response == Gtk.ResponseType.CANCEL:
|
|
|
|
|
return
|
2018-08-05 00:54:30 +03:00
|
|
|
show_dialog(DialogType.ERROR, transient=self._window, text="Not implemented yet!")
|
2018-07-13 17:12:02 +03:00
|
|
|
|
|
|
|
|
@run_idle
|
2018-04-30 18:37:02 +03:00
|
|
|
def on_update(self, item):
|
2020-11-02 21:55:34 +03:00
|
|
|
SatellitesUpdateDialog(self._window, self._settings, self._sat_view.get_model()).show()
|
2018-04-25 17:26:29 +03:00
|
|
|
|
2017-10-30 16:20:19 +03:00
|
|
|
@staticmethod
|
|
|
|
|
def parse_data(model, path, itr, sats):
|
|
|
|
|
if model.iter_has_child(itr):
|
|
|
|
|
num_of_children = model.iter_n_children(itr)
|
|
|
|
|
transponders = []
|
|
|
|
|
num_columns = model.get_n_columns()
|
|
|
|
|
|
|
|
|
|
for num in range(num_of_children):
|
|
|
|
|
transponder_itr = model.iter_nth_child(itr, num)
|
|
|
|
|
transponder = model.get(transponder_itr, *[item for item in range(num_columns)])
|
|
|
|
|
transponders.append(Transponder(*transponder[1:-2]))
|
|
|
|
|
|
|
|
|
|
sat = model.get(itr, *[item for item in range(num_columns)])
|
|
|
|
|
satellite = Satellite(sat[0], sat[-2], sat[-1], transponders)
|
|
|
|
|
sats.append(satellite)
|
|
|
|
|
|
2018-11-05 11:09:15 +03:00
|
|
|
|
2018-04-30 18:37:02 +03:00
|
|
|
# ***************** Transponder dialog *******************#
|
|
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
class TransponderDialog:
|
|
|
|
|
""" Shows dialog for adding or edit transponder """
|
|
|
|
|
|
|
|
|
|
def __init__(self, transient, transponder: Transponder = None):
|
2017-11-15 17:54:16 +03:00
|
|
|
|
|
|
|
|
handlers = {"on_entry_changed": self.on_entry_changed}
|
|
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
builder = Gtk.Builder()
|
2018-03-02 17:06:53 +03:00
|
|
|
builder.set_translation_domain(TEXT_DOMAIN)
|
2019-05-10 14:42:32 +03:00
|
|
|
builder.add_objects_from_string(get_dialogs_string(_UI_PATH).format(use_header=IS_GNOME_SESSION),
|
|
|
|
|
("transponder_dialog", "pol_store", "fec_store", "mod_store", "system_store",
|
|
|
|
|
"pls_mode_store"))
|
2017-11-15 17:54:16 +03:00
|
|
|
builder.connect_signals(handlers)
|
2017-10-31 20:49:36 +03:00
|
|
|
|
|
|
|
|
self._dialog = builder.get_object("transponder_dialog")
|
|
|
|
|
self._dialog.set_transient_for(transient)
|
|
|
|
|
self._freq_entry = builder.get_object("freq_entry")
|
|
|
|
|
self._rate_entry = builder.get_object("rate_entry")
|
|
|
|
|
self._pol_box = builder.get_object("pol_box")
|
|
|
|
|
self._fec_box = builder.get_object("fec_box")
|
|
|
|
|
self._sys_box = builder.get_object("sys_box")
|
|
|
|
|
self._mod_box = builder.get_object("mod_box")
|
|
|
|
|
self._pls_mode_box = builder.get_object("pls_mode_box")
|
|
|
|
|
self._pls_code_entry = builder.get_object("pls_code_entry")
|
|
|
|
|
self._is_id_entry = builder.get_object("is_id_entry")
|
2017-11-15 17:54:16 +03:00
|
|
|
# pattern for frequency and rate entries (only digits)
|
2020-11-02 21:55:34 +03:00
|
|
|
self._pattern = re.compile(r"\D")
|
2017-11-15 17:54:16 +03:00
|
|
|
# style
|
|
|
|
|
self._style_provider = Gtk.CssProvider()
|
2017-12-25 19:50:35 +03:00
|
|
|
self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css")
|
2017-11-15 17:54:16 +03:00
|
|
|
self._freq_entry.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider,
|
|
|
|
|
Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
|
|
|
|
self._rate_entry.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider,
|
|
|
|
|
Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
2017-10-31 20:49:36 +03:00
|
|
|
if transponder:
|
|
|
|
|
self.init_transponder(transponder)
|
|
|
|
|
|
|
|
|
|
def run(self):
|
2017-11-21 16:18:31 +03:00
|
|
|
while self._dialog.run() != Gtk.ResponseType.CANCEL:
|
|
|
|
|
tr = self.to_transponder()
|
|
|
|
|
if self.is_accept(tr):
|
|
|
|
|
return tr
|
2017-12-09 16:25:54 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._dialog, "Please check your parameters and try again.")
|
2017-10-31 20:49:36 +03:00
|
|
|
|
|
|
|
|
def destroy(self):
|
|
|
|
|
self._dialog.destroy()
|
|
|
|
|
|
|
|
|
|
def init_transponder(self, transponder):
|
|
|
|
|
self._freq_entry.set_text(transponder.frequency)
|
|
|
|
|
self._rate_entry.set_text(transponder.symbol_rate)
|
|
|
|
|
self._pol_box.set_active_id(transponder.polarization)
|
|
|
|
|
self._fec_box.set_active_id(transponder.fec_inner)
|
|
|
|
|
self._sys_box.set_active_id(transponder.system)
|
|
|
|
|
self._mod_box.set_active_id(transponder.modulation)
|
2019-03-12 10:39:55 +03:00
|
|
|
self._pls_mode_box.set_active_id(PLS_MODE.get(transponder.pls_mode, None))
|
2017-10-31 20:49:36 +03:00
|
|
|
self._is_id_entry.set_text(transponder.is_id if transponder.is_id else "")
|
|
|
|
|
self._pls_code_entry.set_text(transponder.pls_code if transponder.pls_code else "")
|
|
|
|
|
|
|
|
|
|
def to_transponder(self):
|
|
|
|
|
return Transponder(frequency=self._freq_entry.get_text(),
|
2017-11-01 20:15:22 +03:00
|
|
|
symbol_rate=self._rate_entry.get_text(),
|
2017-10-31 20:49:36 +03:00
|
|
|
polarization=self._pol_box.get_active_id(),
|
|
|
|
|
fec_inner=self._fec_box.get_active_id(),
|
|
|
|
|
system=self._sys_box.get_active_id(),
|
|
|
|
|
modulation=self._mod_box.get_active_id(),
|
2019-03-22 00:54:44 +03:00
|
|
|
pls_mode=get_key_by_value(PLS_MODE, self._pls_mode_box.get_active_id()),
|
2017-10-31 20:49:36 +03:00
|
|
|
pls_code=self._pls_code_entry.get_text(),
|
|
|
|
|
is_id=self._is_id_entry.get_text())
|
|
|
|
|
|
2017-11-15 17:54:16 +03:00
|
|
|
def on_entry_changed(self, entry):
|
|
|
|
|
entry.set_name("digit-entry" if self._pattern.search(entry.get_text()) else "GtkEntry")
|
|
|
|
|
|
2017-11-21 16:18:31 +03:00
|
|
|
def is_accept(self, tr):
|
|
|
|
|
if self._pattern.search(tr.frequency) or not tr.frequency:
|
|
|
|
|
return False
|
|
|
|
|
elif self._pattern.search(tr.symbol_rate) or not tr.symbol_rate:
|
|
|
|
|
return False
|
|
|
|
|
elif None in (tr.polarization, tr.fec_inner, tr.system, tr.modulation):
|
|
|
|
|
return False
|
|
|
|
|
elif self._pattern.search(tr.pls_code) or self._pattern.search(tr.is_id):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
|
2018-04-30 18:37:02 +03:00
|
|
|
# ***************** Satellite dialog *******************#
|
|
|
|
|
|
2017-10-31 20:49:36 +03:00
|
|
|
class SatelliteDialog:
|
|
|
|
|
""" Shows dialog for adding or edit satellite """
|
|
|
|
|
|
|
|
|
|
def __init__(self, transient, satellite: Satellite = None):
|
|
|
|
|
builder = Gtk.Builder()
|
2018-03-02 17:06:53 +03:00
|
|
|
builder.set_translation_domain(TEXT_DOMAIN)
|
2019-05-10 14:42:32 +03:00
|
|
|
builder.add_objects_from_string(get_dialogs_string(_UI_PATH).format(use_header=IS_GNOME_SESSION),
|
|
|
|
|
("satellite_dialog", "side_store", "pos_adjustment"))
|
2017-10-31 20:49:36 +03:00
|
|
|
|
|
|
|
|
self._dialog = builder.get_object("satellite_dialog")
|
|
|
|
|
self._dialog.set_transient_for(transient)
|
|
|
|
|
self._sat_name = builder.get_object("sat_name_entry")
|
|
|
|
|
self._sat_position = builder.get_object("sat_position_button")
|
|
|
|
|
self._side = builder.get_object("side_box")
|
|
|
|
|
|
|
|
|
|
if satellite:
|
|
|
|
|
self._sat_name.set_text(satellite.name[0:satellite.name.find("(")].strip())
|
|
|
|
|
pos = satellite.position
|
|
|
|
|
pos = float("{}.{}".format(pos[:-1], pos[-1:]))
|
|
|
|
|
self._sat_position.set_value(fabs(pos))
|
2017-11-17 15:20:17 +03:00
|
|
|
self._side.set_active(0 if pos >= 0 else 1) # E or W
|
2017-10-31 20:49:36 +03:00
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
if self._dialog.run() == Gtk.ResponseType.CANCEL:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
return self.to_satellite()
|
|
|
|
|
|
|
|
|
|
def destroy(self):
|
|
|
|
|
self._dialog.destroy()
|
|
|
|
|
|
|
|
|
|
def to_satellite(self):
|
|
|
|
|
name = self._sat_name.get_text()
|
2017-11-01 20:15:22 +03:00
|
|
|
pos = round(self._sat_position.get_value(), 1)
|
2017-10-31 20:49:36 +03:00
|
|
|
side = self._side.get_active()
|
2017-11-01 20:15:22 +03:00
|
|
|
name = "{} ({}{})".format(name, pos, self._side.get_active_id())
|
2017-10-31 20:49:36 +03:00
|
|
|
pos = "{}{}{}".format("-" if side == 1 else "", *str(pos).split("."))
|
|
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
return Satellite(name=name, flags="0", position=pos, transponders=None)
|
2017-10-31 20:49:36 +03:00
|
|
|
|
|
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
# ********************** Update dialogs ************************ #
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
class UpdateDialog:
|
|
|
|
|
""" Base dialog for update satellites, transponders and services from the web."""
|
2018-05-07 00:44:46 +03:00
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
def __init__(self, transient, settings, title=None):
|
2018-04-30 18:37:02 +03:00
|
|
|
handlers = {"on_update_satellites_list": self.on_update_satellites_list,
|
2020-11-02 21:55:34 +03:00
|
|
|
"on_receive_data": self.on_receive_data,
|
2018-04-30 18:37:02 +03:00
|
|
|
"on_cancel_receive": self.on_cancel_receive,
|
2020-11-02 21:55:34 +03:00
|
|
|
"on_satellite_toggled": self.on_satellite_toggled,
|
|
|
|
|
"on_transponder_toggled": self.on_transponder_toggled,
|
2018-05-05 22:01:50 +03:00
|
|
|
"on_info_bar_close": self.on_info_bar_close,
|
2018-05-07 00:44:46 +03:00
|
|
|
"on_filter_toggled": self.on_filter_toggled,
|
|
|
|
|
"on_find_toggled": self.on_find_toggled,
|
2018-10-21 11:10:45 +03:00
|
|
|
"on_popup_menu": on_popup_menu,
|
2018-07-12 19:11:32 +03:00
|
|
|
"on_select_all": self.on_select_all,
|
|
|
|
|
"on_unselect_all": self.on_unselect_all,
|
2018-05-07 15:19:05 +03:00
|
|
|
"on_filter": self.on_filter,
|
2018-05-07 18:19:00 +03:00
|
|
|
"on_search": self.on_search,
|
|
|
|
|
"on_search_down": self.on_search_down,
|
|
|
|
|
"on_search_up": self.on_search_up,
|
2018-04-30 18:37:02 +03:00
|
|
|
"on_quit": self.on_quit}
|
2018-05-07 00:44:46 +03:00
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
self._settings = settings
|
|
|
|
|
self._download_task = False
|
|
|
|
|
self._parser = None
|
|
|
|
|
self._size_name = "{}_window_size".format("_".join(re.findall("[A-Z][^A-Z]*", self.__class__.__name__))).lower()
|
|
|
|
|
|
2018-04-30 18:37:02 +03:00
|
|
|
builder = Gtk.Builder()
|
|
|
|
|
builder.set_translation_domain(TEXT_DOMAIN)
|
|
|
|
|
builder.add_objects_from_file(UI_RESOURCES_PATH + "satellites_dialog.glade",
|
2018-09-10 22:37:42 +03:00
|
|
|
("satellites_update_window", "update_source_store", "update_sat_list_store",
|
2018-05-07 15:19:05 +03:00
|
|
|
"update_sat_list_model_filter", "update_sat_list_model_sort", "side_store",
|
2018-07-12 19:11:32 +03:00
|
|
|
"pos_adjustment", "pos_adjustment2", "satellites_update_popup_menu",
|
2020-11-02 21:55:34 +03:00
|
|
|
"remove_selection_image", "update_transponder_store", "update_service_store"))
|
2018-04-30 18:37:02 +03:00
|
|
|
builder.connect_signals(handlers)
|
|
|
|
|
|
2018-09-10 22:37:42 +03:00
|
|
|
self._window = builder.get_object("satellites_update_window")
|
|
|
|
|
self._window.set_transient_for(transient)
|
2020-11-02 21:55:34 +03:00
|
|
|
if title:
|
|
|
|
|
self._window.set_title(title)
|
|
|
|
|
|
|
|
|
|
self._transponder_paned = builder.get_object("sat_update_tr_paned")
|
2018-04-30 18:37:02 +03:00
|
|
|
self._sat_view = builder.get_object("sat_update_tree_view")
|
2020-11-02 21:55:34 +03:00
|
|
|
self._transponder_view = builder.get_object("sat_update_tr_view")
|
|
|
|
|
self._service_view = builder.get_object("sat_update_srv_view")
|
2018-05-10 00:44:42 +03:00
|
|
|
self._source_box = builder.get_object("source_combo_box")
|
2018-05-01 21:05:18 +03:00
|
|
|
self._sat_update_expander = builder.get_object("sat_update_expander")
|
|
|
|
|
self._text_view = builder.get_object("text_view")
|
2020-11-02 21:55:34 +03:00
|
|
|
self._receive_button = builder.get_object("receive_data_button")
|
2018-05-05 22:01:50 +03:00
|
|
|
self._sat_update_info_bar = builder.get_object("sat_update_info_bar")
|
|
|
|
|
self._info_bar_message_label = builder.get_object("info_bar_message_label")
|
2020-11-02 21:55:34 +03:00
|
|
|
self._receive_button.bind_property("visible", builder.get_object("cancel_data_button"), "visible", 4)
|
2018-05-07 18:19:00 +03:00
|
|
|
# Filter
|
2018-07-06 22:26:27 +03:00
|
|
|
self._filter_bar = builder.get_object("sat_update_filter_bar")
|
2018-05-07 15:19:05 +03:00
|
|
|
self._from_pos_button = builder.get_object("from_pos_button")
|
|
|
|
|
self._to_pos_button = builder.get_object("to_pos_button")
|
|
|
|
|
self._filter_from_combo_box = builder.get_object("filter_from_combo_box")
|
|
|
|
|
self._filter_to_combo_box = builder.get_object("filter_to_combo_box")
|
|
|
|
|
self._filter_model = builder.get_object("update_sat_list_model_filter")
|
|
|
|
|
self._filter_model.set_visible_func(self.filter_function)
|
|
|
|
|
self._filter_positions = (0, 0)
|
2018-05-07 18:19:00 +03:00
|
|
|
# Search
|
2018-07-06 22:26:27 +03:00
|
|
|
self._search_bar = builder.get_object("sat_update_search_bar")
|
2018-05-07 18:19:00 +03:00
|
|
|
self._search_provider = SearchProvider((self._sat_view,),
|
|
|
|
|
builder.get_object("sat_update_search_down_button"),
|
|
|
|
|
builder.get_object("sat_update_search_up_button"))
|
|
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
window_size = self._settings.get(self._size_name)
|
|
|
|
|
if window_size:
|
|
|
|
|
self._window.resize(*window_size)
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2018-09-10 22:37:42 +03:00
|
|
|
def show(self):
|
|
|
|
|
self._window.show()
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
@property
|
|
|
|
|
def is_download(self):
|
|
|
|
|
return self._download_task
|
|
|
|
|
|
|
|
|
|
@is_download.setter
|
|
|
|
|
def is_download(self, value):
|
|
|
|
|
self._download_task = value
|
|
|
|
|
self._receive_button.set_visible(not value)
|
|
|
|
|
|
2018-09-10 22:37:42 +03:00
|
|
|
@run_idle
|
2018-04-30 18:37:02 +03:00
|
|
|
def on_update_satellites_list(self, item):
|
2020-11-02 21:55:34 +03:00
|
|
|
if self.is_download:
|
2018-09-10 22:37:42 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._window, "The task is already running!")
|
2018-04-30 18:37:02 +03:00
|
|
|
return
|
|
|
|
|
|
2018-05-07 15:19:05 +03:00
|
|
|
model = get_base_model(self._sat_view.get_model())
|
2018-04-30 18:37:02 +03:00
|
|
|
model.clear()
|
2020-11-02 21:55:34 +03:00
|
|
|
self.is_download = True
|
2018-05-10 00:44:42 +03:00
|
|
|
src = self._source_box.get_active()
|
2018-04-30 18:37:02 +03:00
|
|
|
if not self._parser:
|
2018-05-10 00:44:42 +03:00
|
|
|
self._parser = SatellitesParser()
|
|
|
|
|
|
2018-05-12 14:36:38 +03:00
|
|
|
self.get_sat_list(src, self.append_satellites)
|
|
|
|
|
|
|
|
|
|
@run_task
|
|
|
|
|
def get_sat_list(self, src, callback):
|
2018-05-10 00:44:42 +03:00
|
|
|
sats = self._parser.get_satellites_list(SatelliteSource.FLYSAT if src == 0 else SatelliteSource.LYNGSAT)
|
2018-04-30 18:37:02 +03:00
|
|
|
if sats:
|
2018-05-12 14:36:38 +03:00
|
|
|
callback(sats)
|
2020-11-02 21:55:34 +03:00
|
|
|
self.is_download = False
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2018-05-12 14:36:38 +03:00
|
|
|
@run_idle
|
|
|
|
|
def append_satellites(self, sats):
|
|
|
|
|
model = get_base_model(self._sat_view.get_model())
|
|
|
|
|
for sat in sats:
|
|
|
|
|
model.append(sat)
|
|
|
|
|
|
2018-09-10 22:37:42 +03:00
|
|
|
@run_idle
|
2020-11-02 21:55:34 +03:00
|
|
|
def on_receive_data(self, item):
|
|
|
|
|
if self.is_download:
|
2018-09-10 22:37:42 +03:00
|
|
|
show_dialog(DialogType.ERROR, self._window, "The task is already running!")
|
2018-04-30 18:37:02 +03:00
|
|
|
return
|
|
|
|
|
|
2018-09-10 22:37:42 +03:00
|
|
|
@run_idle
|
|
|
|
|
def update_expander(self):
|
|
|
|
|
self._sat_update_expander.set_expanded(True)
|
|
|
|
|
self._text_view.get_buffer().set_text("", 0)
|
|
|
|
|
|
2018-05-12 14:36:38 +03:00
|
|
|
def append_output(self):
|
|
|
|
|
@run_idle
|
|
|
|
|
def append(t):
|
|
|
|
|
append_text_to_tview(t, self._text_view)
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
text = yield
|
|
|
|
|
append(text)
|
2018-05-01 21:05:18 +03:00
|
|
|
|
2018-04-30 18:37:02 +03:00
|
|
|
def on_cancel_receive(self, item=None):
|
|
|
|
|
self._download_task = False
|
|
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
def on_satellite_toggled(self, toggle, path):
|
2018-07-12 19:44:27 +03:00
|
|
|
model = self._sat_view.get_model()
|
|
|
|
|
self.update_state(model, path, not toggle.get_active())
|
2018-05-10 23:28:51 +03:00
|
|
|
self.update_receive_button_state(self._filter_model)
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
def on_transponder_toggled(self, toggle, path):
|
|
|
|
|
model = self._transponder_view.get_model()
|
|
|
|
|
model.set_value(model.get_iter(path), 2, not toggle.get_active())
|
|
|
|
|
|
2018-04-30 18:37:02 +03:00
|
|
|
@run_idle
|
|
|
|
|
def update_receive_button_state(self, model):
|
2018-05-07 15:19:05 +03:00
|
|
|
self._receive_button.set_sensitive((any(r[4] for r in model)))
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2018-05-05 22:01:50 +03:00
|
|
|
@run_idle
|
|
|
|
|
def show_info_message(self, text, message_type):
|
|
|
|
|
self._sat_update_info_bar.set_visible(True)
|
|
|
|
|
self._sat_update_info_bar.set_message_type(message_type)
|
|
|
|
|
self._info_bar_message_label.set_text(text)
|
|
|
|
|
|
|
|
|
|
def on_info_bar_close(self, bar=None, resp=None):
|
|
|
|
|
self._sat_update_info_bar.set_visible(False)
|
|
|
|
|
|
2018-05-07 00:44:46 +03:00
|
|
|
def on_find_toggled(self, button: Gtk.ToggleToolButton):
|
2018-07-06 22:26:27 +03:00
|
|
|
self._search_bar.set_search_mode(button.get_active())
|
2018-05-07 00:44:46 +03:00
|
|
|
|
|
|
|
|
def on_filter_toggled(self, button: Gtk.ToggleToolButton):
|
2018-07-06 22:26:27 +03:00
|
|
|
self._filter_bar.set_search_mode(button.get_active())
|
2018-05-07 00:44:46 +03:00
|
|
|
|
2018-05-07 15:19:05 +03:00
|
|
|
@run_idle
|
|
|
|
|
def on_filter(self, item):
|
|
|
|
|
self._filter_positions = self.get_positions()
|
|
|
|
|
self._filter_model.refilter()
|
|
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
def filter_function(self, model, itr, data):
|
2018-05-07 15:19:05 +03:00
|
|
|
if self._filter_model is None or self._filter_model == "None":
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
from_pos, to_pos = self._filter_positions
|
|
|
|
|
if from_pos == 0 and to_pos == 0:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if from_pos > to_pos:
|
|
|
|
|
from_pos, to_pos = to_pos, from_pos
|
|
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
return from_pos <= float(self._parser.get_position(model.get(itr, 1)[0])) <= to_pos
|
2018-05-07 15:19:05 +03:00
|
|
|
|
|
|
|
|
def get_positions(self):
|
|
|
|
|
from_pos = round(self._from_pos_button.get_value(), 1) * (-1 if self._filter_from_combo_box.get_active() else 1)
|
|
|
|
|
to_pos = round(self._to_pos_button.get_value(), 1) * (-1 if self._filter_to_combo_box.get_active() else 1)
|
|
|
|
|
return from_pos, to_pos
|
|
|
|
|
|
2018-05-07 18:19:00 +03:00
|
|
|
def on_search(self, entry):
|
|
|
|
|
self._search_provider.search(entry.get_text())
|
|
|
|
|
|
|
|
|
|
def on_search_down(self, item):
|
|
|
|
|
self._search_provider.on_search_down()
|
|
|
|
|
|
|
|
|
|
def on_search_up(self, item):
|
|
|
|
|
self._search_provider.on_search_up()
|
|
|
|
|
|
2018-07-12 19:11:32 +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):
|
2018-07-12 19:44:27 +03:00
|
|
|
model = view.get_model()
|
|
|
|
|
view.get_model().foreach(lambda mod, path, itr: self.update_state(model, path, select))
|
2018-07-12 19:11:32 +03:00
|
|
|
self.update_receive_button_state(self._filter_model)
|
|
|
|
|
|
2018-07-12 19:44:27 +03:00
|
|
|
def update_state(self, model, path, select):
|
|
|
|
|
""" Updates checkbox state by given path in the list """
|
|
|
|
|
itr = self._filter_model.convert_iter_to_child_iter(model.convert_iter_to_child_iter(model.get_iter(path)))
|
|
|
|
|
self._filter_model.get_model().set_value(itr, 4, select)
|
|
|
|
|
|
2018-09-10 22:37:42 +03:00
|
|
|
def on_quit(self, window, event):
|
2020-11-02 21:55:34 +03:00
|
|
|
self._settings.add(self._size_name, window.get_size())
|
|
|
|
|
self.is_download = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SatellitesUpdateDialog(UpdateDialog):
|
|
|
|
|
""" Dialog for update satellites from the web. """
|
|
|
|
|
|
|
|
|
|
def __init__(self, transient, settings, main_model):
|
|
|
|
|
super().__init__(transient=transient, settings=settings)
|
|
|
|
|
|
|
|
|
|
self._main_model = main_model
|
|
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def on_receive_data(self, item):
|
|
|
|
|
if self.is_download:
|
|
|
|
|
show_dialog(DialogType.ERROR, self._window, "The task is already running!")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.receive_satellites()
|
|
|
|
|
|
|
|
|
|
@run_task
|
|
|
|
|
def receive_satellites(self):
|
|
|
|
|
self.is_download = True
|
|
|
|
|
self.update_expander()
|
|
|
|
|
model = self._sat_view.get_model()
|
|
|
|
|
start = time.time()
|
|
|
|
|
|
|
|
|
|
with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
|
|
|
|
|
text = "Processing: {}\n"
|
|
|
|
|
sats = []
|
|
|
|
|
appender = self.append_output()
|
|
|
|
|
next(appender)
|
|
|
|
|
futures = {executor.submit(self._parser.get_satellite, sat[:-1]): sat for sat in [r for r in model if r[4]]}
|
|
|
|
|
for future in concurrent.futures.as_completed(futures):
|
|
|
|
|
if not self.is_download:
|
|
|
|
|
self.is_download = True
|
|
|
|
|
executor.shutdown()
|
|
|
|
|
appender.send("\nCanceled\n")
|
|
|
|
|
appender.close()
|
|
|
|
|
self.is_download = False
|
|
|
|
|
return
|
|
|
|
|
data = future.result()
|
|
|
|
|
appender.send(text.format(data[0]))
|
|
|
|
|
sats.append(data)
|
|
|
|
|
|
|
|
|
|
appender.send("-" * 75 + "\n")
|
|
|
|
|
appender.send("Consumed: {:0.0f}s, {} satellites received.".format(time.time() - start, len(sats)))
|
|
|
|
|
appender.close()
|
|
|
|
|
|
|
|
|
|
sats = {s[2]: s for s in sats} # key = position, v = satellite
|
|
|
|
|
|
|
|
|
|
for row in self._main_model:
|
|
|
|
|
pos = row[-1]
|
|
|
|
|
if pos in sats:
|
|
|
|
|
sat = sats.pop(pos)
|
|
|
|
|
itr = row.iter
|
|
|
|
|
self.update_satellite(itr, row, sat)
|
|
|
|
|
|
|
|
|
|
for sat in sats.values():
|
|
|
|
|
append_satellite(self._main_model, sat)
|
|
|
|
|
|
|
|
|
|
self.is_download = False
|
|
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def update_satellite(self, itr, row, sat):
|
|
|
|
|
if self._main_model.iter_has_child(itr):
|
|
|
|
|
children = row.iterchildren()
|
|
|
|
|
for ch in children:
|
|
|
|
|
self._main_model.remove(ch.iter)
|
|
|
|
|
|
|
|
|
|
for tr in sat[3]:
|
|
|
|
|
self._main_model.append(itr, ["Transponder:", *tr, None, None])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ServicesUpdateDialog(UpdateDialog):
|
|
|
|
|
""" Dialog for updating services from the web. """
|
|
|
|
|
|
|
|
|
|
def __init__(self, transient, settings, callback):
|
|
|
|
|
super().__init__(transient=transient, settings=settings, title="Services update")
|
|
|
|
|
|
|
|
|
|
self._callback = callback
|
|
|
|
|
self._satellite_paths = {}
|
|
|
|
|
self._transponders = {}
|
|
|
|
|
self._services = {}
|
|
|
|
|
self._selected_transponders = set()
|
|
|
|
|
self._services_parser = ServicesParser(source=SatelliteSource.LYNGSAT)
|
|
|
|
|
|
|
|
|
|
self._transponder_paned.set_visible(True)
|
|
|
|
|
s_model = self._source_box.get_model()
|
|
|
|
|
s_model.remove(s_model.get_iter_first())
|
|
|
|
|
self._source_box.set_active(0)
|
|
|
|
|
self._sat_view.connect("row-activated", self.on_activate_satellite)
|
|
|
|
|
self._transponder_view.connect("row-activated", self.on_activate_transponder)
|
|
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def on_receive_data(self, item):
|
|
|
|
|
if self.is_download:
|
|
|
|
|
show_dialog(DialogType.ERROR, self._window, "The task is already running!")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.receive_services()
|
|
|
|
|
|
|
|
|
|
@run_task
|
|
|
|
|
def receive_services(self):
|
|
|
|
|
self.is_download = True
|
|
|
|
|
self.update_expander()
|
|
|
|
|
model = self._sat_view.get_model()
|
|
|
|
|
appender = self.append_output()
|
|
|
|
|
next(appender)
|
|
|
|
|
|
|
|
|
|
start = time.time()
|
|
|
|
|
non_cached_sats = []
|
|
|
|
|
sat_names = {}
|
|
|
|
|
t_names = {}
|
|
|
|
|
t_urls = []
|
|
|
|
|
services = []
|
|
|
|
|
|
|
|
|
|
for sat, url in (r[0, 3] for r in model if r[-1]):
|
|
|
|
|
if not self.is_download:
|
|
|
|
|
appender.send("\nCanceled\n")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
trs = self._transponders.get(url, None)
|
|
|
|
|
if trs:
|
|
|
|
|
for t in filter(lambda tp: tp.url in self._selected_transponders, trs):
|
|
|
|
|
t_urls.append(t.url)
|
|
|
|
|
t_names[t.url] = t.text
|
|
|
|
|
else:
|
|
|
|
|
non_cached_sats.append(url)
|
|
|
|
|
sat_names[url] = sat
|
|
|
|
|
|
|
|
|
|
if non_cached_sats:
|
|
|
|
|
with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
|
|
|
|
|
futures = {executor.submit(self._services_parser.get_transponders_links, u): u for u in non_cached_sats}
|
|
|
|
|
for future in concurrent.futures.as_completed(futures):
|
|
|
|
|
if not self.is_download:
|
|
|
|
|
appender.send("\nCanceled.\n")
|
|
|
|
|
self.is_download = False
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
appender.send("Getting transponders for: {}.\n".format(sat_names.get(futures[future])))
|
|
|
|
|
for t in future.result():
|
|
|
|
|
t_urls.append(t.url)
|
|
|
|
|
t_names[t.url] = t.text
|
|
|
|
|
|
|
|
|
|
appender.send("-" * 75 + "\n")
|
|
|
|
|
appender.send("{} transponders received.\n\n".format(len(t_urls)))
|
|
|
|
|
|
|
|
|
|
non_cached_ts = []
|
|
|
|
|
for tr in t_urls:
|
|
|
|
|
srvs = self._services.get(tr)
|
|
|
|
|
services.extend(srvs) if srvs else non_cached_ts.append(tr)
|
|
|
|
|
|
|
|
|
|
if non_cached_ts:
|
|
|
|
|
with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
|
|
|
|
|
futures = {executor.submit(self._services_parser.get_transponder_services, u): u for u in non_cached_ts}
|
|
|
|
|
for future in concurrent.futures.as_completed(futures):
|
|
|
|
|
if not self.is_download:
|
|
|
|
|
appender.send("\nCanceled.\n")
|
|
|
|
|
self.is_download = False
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
appender.send("Getting services for: {}.\n".format(t_names.get(futures[future], "")))
|
|
|
|
|
list(map(services.append, future.result()))
|
|
|
|
|
|
|
|
|
|
appender.send("-" * 75 + "\n")
|
|
|
|
|
appender.send("Consumed: {:0.0f}s, {} services received.".format(time.time() - start, len(services)))
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from app.eparser.enigma.lamedb import get_services_lines, get_services_list
|
|
|
|
|
# Used for double checking!
|
|
|
|
|
srvs = get_services_list("".join(get_services_lines(services)))
|
|
|
|
|
except ValueError as e:
|
|
|
|
|
log("ServicesUpdateDialog [on receive data] error: {}".format(e))
|
|
|
|
|
else:
|
|
|
|
|
self._callback(srvs)
|
|
|
|
|
|
|
|
|
|
self.is_download = False
|
|
|
|
|
|
|
|
|
|
@run_task
|
|
|
|
|
def get_sat_list(self, src, callback):
|
|
|
|
|
sats = self._parser.get_satellites_list(SatelliteSource.LYNGSAT)
|
|
|
|
|
if sats:
|
|
|
|
|
callback(sats)
|
|
|
|
|
self.is_download = False
|
|
|
|
|
|
|
|
|
|
def on_satellite_toggled(self, toggle, path):
|
|
|
|
|
model = self._sat_view.get_model()
|
|
|
|
|
self.update_state(model, path, not toggle.get_active())
|
|
|
|
|
self.update_receive_button_state(self._filter_model)
|
|
|
|
|
|
|
|
|
|
url = model.get_value(model.get_iter(path), 3)
|
|
|
|
|
selected = toggle.get_active()
|
|
|
|
|
transponders = self._transponders.get(url, None)
|
|
|
|
|
|
|
|
|
|
if transponders:
|
|
|
|
|
for t in transponders:
|
|
|
|
|
self._selected_transponders.add(t.url) if selected else self._selected_transponders.discard(t.url)
|
|
|
|
|
|
|
|
|
|
def on_transponder_toggled(self, toggle, path):
|
|
|
|
|
model = self._transponder_view.get_model()
|
|
|
|
|
itr = model.get_iter(path)
|
|
|
|
|
active = not toggle.get_active()
|
|
|
|
|
model.set_value(itr, 2, active)
|
|
|
|
|
url = model.get_value(itr, 1)
|
|
|
|
|
self._selected_transponders.add(url) if active else self._selected_transponders.discard(url)
|
|
|
|
|
|
|
|
|
|
s_path = self._satellite_paths.get(url)
|
|
|
|
|
if s_path:
|
|
|
|
|
sat_model = self._sat_view.get_model()
|
|
|
|
|
if active:
|
|
|
|
|
self.update_state(sat_model, s_path, active)
|
|
|
|
|
else:
|
|
|
|
|
self.update_state(sat_model, s_path, any((r[-1] for r in model)))
|
|
|
|
|
self.update_receive_button_state(self._filter_model)
|
|
|
|
|
|
|
|
|
|
@run_task
|
|
|
|
|
def on_activate_satellite(self, view, path, column):
|
|
|
|
|
url, selected = view.get_model()[path][3, 4]
|
|
|
|
|
transponders = self._transponders.get(url, None)
|
|
|
|
|
if transponders is None:
|
|
|
|
|
GLib.idle_add(view.set_sensitive, False)
|
|
|
|
|
transponders = self._services_parser.get_transponders_links(url)
|
|
|
|
|
self._transponders[url] = transponders
|
|
|
|
|
|
|
|
|
|
for t in transponders:
|
|
|
|
|
t_url = t.url
|
|
|
|
|
self._satellite_paths[t_url] = path
|
|
|
|
|
self._selected_transponders.add(t_url) if selected else self._selected_transponders.discard(t_url)
|
|
|
|
|
|
|
|
|
|
self.append_transponders(self._transponder_view.get_model(), transponders)
|
|
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def append_transponders(self, model, trs_list):
|
|
|
|
|
model.clear()
|
|
|
|
|
list(map(model.append, [(t.text, t.url, t.url in self._selected_transponders) for t in trs_list]))
|
|
|
|
|
self._sat_view.set_sensitive(True)
|
|
|
|
|
|
|
|
|
|
@run_task
|
|
|
|
|
def on_activate_transponder(self, view, path, column):
|
|
|
|
|
url = view.get_model()[path][1]
|
|
|
|
|
services = self._services.get(url, None)
|
|
|
|
|
if services is None:
|
|
|
|
|
GLib.idle_add(view.set_sensitive, False)
|
|
|
|
|
services = self._services_parser.get_transponder_services(url)
|
|
|
|
|
self._services[url] = services
|
|
|
|
|
|
|
|
|
|
self.append_services(self._service_view.get_model(), services)
|
|
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def append_services(self, model, srv_list):
|
|
|
|
|
model.clear()
|
|
|
|
|
for s in srv_list:
|
|
|
|
|
model.append((None, s.service, s.package, s.service_type, str(s.ssid), None))
|
|
|
|
|
|
|
|
|
|
self._transponder_view.set_sensitive(True)
|
|
|
|
|
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2020-11-02 21:55:34 +03:00
|
|
|
# ************************* Commons ************************* #
|
2018-04-30 18:37:02 +03:00
|
|
|
|
2018-05-02 21:23:09 +03:00
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def append_satellite(model, sat):
|
|
|
|
|
""" Common function for append satellite to the model """
|
|
|
|
|
name, flags, pos, transponders = sat
|
|
|
|
|
parent = model.append(None, [name, *(None,) * 9, flags, pos])
|
|
|
|
|
for transponder in transponders:
|
|
|
|
|
model.append(parent, ["Transponder:", *transponder, None, None])
|
|
|
|
|
|
|
|
|
|
|
2017-10-14 12:24:59 +03:00
|
|
|
if __name__ == "__main__":
|
2017-11-01 20:15:22 +03:00
|
|
|
pass
|