basic kingofsat support for channels web import

This commit is contained in:
DYefremov
2021-09-30 21:41:48 +03:00
parent 68b5fcfd39
commit 4fd2939d2e
4 changed files with 553 additions and 405 deletions

View File

@@ -14,7 +14,7 @@ from app.eparser import Satellite, Transponder, is_transponder_valid
from app.eparser.ecommons import (PLS_MODE, get_key_by_value, FEC, SYSTEM, POLARIZATION, MODULATION, SERVICE_TYPE,
Service, CAS)
_HEADERS = {"User-Agent": "Mozilla/5.0 (Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0"}
_HEADERS = {"User-Agent": "Mozilla/5.0 (Linux x86_64; rv:92.0) Gecko/20100101 Firefox/92.0"}
class SatelliteSource(Enum):
@@ -170,7 +170,7 @@ class SatellitesParser(HTMLParser):
return sats
elif source is SatelliteSource.KINGOFSAT:
def get_sat(r):
return r[3], self.parse_position(r[1]), None, r[0], False
return r[3], self.parse_position(r[1]), None, r[2], False
return list(map(get_sat, filter(lambda x: len(x) == 17, self._rows)))
@@ -328,7 +328,7 @@ class ServicesParser(HTMLParser):
self._S_TYPES = {"": "2", "MPEG-2 SD": "1", "MPEG-2/SD": "1", "SD": "1", "MPEG-4 SD": "22", "MPEG-4/SD": "22",
"MPEG-4": "22", "HEVC SD": "22", "MPEG-4/HD": "25", "MPEG-4 HD": "25", "MPEG-4 HD 1080": "25",
"MPEG-4 HD 720": "25", "HEVC HD": "25", "HEVC/HD": "25", "HEVC": "31", "HEVC/UHD": "31",
"HEVC UHD": "31", "HEVC UHD 4K": "31"}
"HEVC UHD": "31", "HEVC UHD 4K": "31", "3": "Data"}
self._TR_PAT = re.compile(
r".*?(\d+)\s+([RLHV]).*(DVB-S[2]?)/?(.*PSK)?\s(T2-MI)?\s?SR-FEC:\s(\d+)-(\d/\d)\s+.*ONID-TID:\s+(\d+)-(\d+).*")
self._POS_PAT = re.compile(r".*?(\d+\.\d°[EW]).*")
@@ -344,6 +344,25 @@ class ServicesParser(HTMLParser):
self._current_cell = Cell()
self._rows = []
self._source = source
self._t_url = ""
self._use_short_names = True
@property
def source(self):
return self._source
@source.setter
def source(self, value):
self._source = value
self.reset()
@property
def use_short_names(self):
return self._use_short_names
@use_short_names.setter
def use_short_names(self, value):
self._use_short_names = value
def handle_starttag(self, tag, attrs):
if tag == "td":
@@ -351,10 +370,24 @@ class ServicesParser(HTMLParser):
elif tag == "tr":
self._is_th = True
elif tag == "a" and not self._current_cell.url:
self._current_cell.url = attrs[0][1]
if attrs:
for a in attrs:
if a[0] == "href":
self._current_cell.url = a[1]
if self._source is SatelliteSource.KINGOFSAT and self._use_short_names:
if a[0] != "title":
continue
txt = a[1]
if txt and txt.startswith("Id: "):
# Saving the 'short' name.
self._current_cell.text = txt.lstrip("Id: ")
elif tag == "img":
img_link = attrs[0][1]
if img_link.startswith("/logo/"):
if self._source is SatelliteSource.LYNGSAT:
if img_link.startswith("/logo/"):
self._current_cell.img = img_link
elif self._source is SatelliteSource.KINGOFSAT:
self._current_cell.img = img_link
def handle_data(self, data):
@@ -369,8 +402,9 @@ class ServicesParser(HTMLParser):
self._is_th = False
if tag in ("td", "th"):
final_cell = self._separator.join(self._current_cell_text).strip()
self._current_cell.text = final_cell
if not self._current_cell.text:
txt = self._separator.join(self._current_cell_text).strip()
self._current_cell.text = txt
self._current_row.append(self._current_cell)
self._current_cell_text = []
self._current_cell = Cell()
@@ -384,7 +418,7 @@ class ServicesParser(HTMLParser):
def init_data(self, url):
""" Initializes data for the given URL. """
if self._source is not SatelliteSource.LYNGSAT:
if self._source not in (SatelliteSource.LYNGSAT, SatelliteSource.KINGOFSAT):
raise ValueError("Unsupported source: {}!".format(self._source.name))
self._rows.clear()
@@ -399,13 +433,26 @@ class ServicesParser(HTMLParser):
def get_transponders_links(self, sat_url):
""" Returns transponder links. """
try:
if self._source is SatelliteSource.KINGOFSAT:
sat_url = "https://en.kingofsat.net/" + sat_url
self.init_data(sat_url)
except ValueError as e:
log(e)
else:
url = "https://www.lyngsat.com/muxes/"
return [row[0] for row in
filter(lambda x: x and len(x) > 8 and x[0].url and x[0].url.startswith(url), self._rows)]
if self._source is SatelliteSource.LYNGSAT:
url = "https://www.lyngsat.com/muxes/"
return [row[0] for row in
filter(lambda x: x and len(x) > 8 and x[0].url and x[0].url.startswith(url), self._rows)]
elif self._source is SatelliteSource.KINGOFSAT:
trs = []
for r in self._rows:
if len(r) == 13 and SatellitesParser.POS_PAT.match(r[0].text):
t_cell = r[4]
if t_cell.url and t_cell.url.startswith("tp.php?tp="):
t_cell.url = f"https://en.kingofsat.net/{t_cell.url}"
t_cell.text = f"{r[2].text} {r[3].text} {r[6].text} {r[8].text}"
trs.append(t_cell)
return trs
return []
def get_transponder_services(self, tr_url, sat_position=None, use_pids=False):
@@ -415,90 +462,155 @@ class ServicesParser(HTMLParser):
@param sat_position: custom satellite position. Sometimes required to adjust the namespace.
@param use_pids: if possible use additional pids [video, audio].
"""
services = []
try:
self._t_url = tr_url
self.init_data(tr_url)
except ValueError as e:
log(e)
else:
pos, freq, sr, fec, pol, namespace, tid, nid = sat_position or 0, 0, 0, 0, 0, 0, 0, 0
sys = "DVB-S"
pos_found = False
tr = None
# Transponder
for r in filter(lambda x: x and 6 < len(x) < 9, self._rows):
if not pos_found:
pos_tr = re.match(self._POS_PAT, r[0].text)
if not pos_tr:
continue
if not sat_position:
pos = int(SatellitesParser.get_position(
"".join(c for c in pos_tr.group(1) if c.isdigit() or c.isalpha())))
pos_found = True
if pos_found:
text = " ".join(c.text for c in r[1:])
td = re.match(self._TR_PAT, text)
if td:
freq, pol = int(td.group(1)), get_key_by_value(POLARIZATION, td.group(2))
if td.group(5):
log("Detected T2-MI transponder!")
continue
sys, mod, sr, _fec, = td.group(3), td.group(4), td.group(6), td.group(7)
nid, tid = td.group(8), td.group(9)
neg_pos = False # POS = W
# For negative (West) positions: 3600 - numeric position value!!!
namespace = "{:04x}0000".format(3600 - pos if neg_pos else pos)
inv = 2 # Default
fec = get_key_by_value(FEC, _fec)
sys = get_key_by_value(SYSTEM, sys)
tr_flag = 1
mod = get_key_by_value(MODULATION, mod)
roll_off = 0 # 35% DVB-S2/DVB-S (default)
pilot = 2 # Auto
s2_flags = "" if sys == "DVB-S" else self._S2_TR.format(tr_flag, mod or 0, roll_off, pilot)
nid, tid = int(nid), int(tid)
tr = self._TR.format(freq, sr, pol, fec, pos, inv, sys, s2_flags)
if not tr:
msg = "ServicesParser error [get transponder services]: {}"
er = "Transponder [{}] not found or its type [T2-MI, etc] not supported yet.".format(freq)
log(msg.format(er))
if self._source is SatelliteSource.LYNGSAT:
return self.get_lyngsat_services(sat_position, use_pids)
elif self._source is SatelliteSource.KINGOFSAT:
return self.get_kingofsat_services(sat_position, use_pids)
else:
return []
# Services
for r in filter(lambda x: x and len(x) == 12 and (x[0].text.isdigit()), self._rows):
sid, name, s_type, v_pid, a_pid, cas, pkg = r[0].text, r[2].text, r[4].text, r[
5].text.strip(), r[6].text.split(), r[9].text, r[10].text.strip()
def get_lyngsat_services(self, sat_position=None, use_pids=False):
services = []
pos, freq, sr, fec, pol, nsp, tid, nid = sat_position or 0, 0, 0, 0, 0, 0, 0, 0
sys = "DVB-S"
pos_found = False
tr = None
# Transponder
for r in filter(lambda x: x and 6 < len(x) < 9, self._rows):
if not pos_found:
pos_tr = re.match(self._POS_PAT, r[0].text)
if not pos_tr:
continue
try:
s_type = self._S_TYPES.get(s_type, "3") # 3 = Data
_s_type = SERVICE_TYPE.get(s_type, SERVICE_TYPE.get("3")) # str repr
sid = int(sid)
data_id = "{:04x}:{}:{:04x}:{:04x}:{}:0:0".format(sid, namespace, tid, nid, s_type)
fav_id = "{}:{}:{}:{}".format(sid, tid, nid, namespace)
picon_id = "1_0_{:X}_{}_{}_{}_{}_0_0_0.png".format(int(s_type), sid, tid, nid, namespace)
# Flags.
flags = "p:{}".format(pkg)
cas = ",".join(get_key_by_value(CAS, c) or "C:0000" for c in cas.split()) if cas else None
if use_pids:
v_pid = "c:00{:04x}".format(int(v_pid)) if v_pid else None
a_pid = ",".join(["c:01{:04x}".format(int(p)) for p in a_pid]) if a_pid else None
flags = ",".join(filter(None, (flags, v_pid, a_pid, cas)))
else:
flags = ",".join(filter(None, (flags, cas)))
if not sat_position:
pos = self.get_position(pos_tr.group(1))
services.append(Service(flags, "s", None, name, None, None, pkg, _s_type, r[1].img, picon_id,
sid, freq, sr, pol, fec, sys, pos, data_id, fav_id, tr))
except ValueError as e:
log("ServicesParser error [get transponder services]: {}".format(e))
pos_found = True
if pos_found:
text = " ".join(c.text for c in r[1:])
td = re.match(self._TR_PAT, text)
if td:
freq, pol = int(td.group(1)), get_key_by_value(POLARIZATION, td.group(2))
if td.group(5):
log("Detected T2-MI transponder!")
continue
sys, mod, sr, _fec, = td.group(3), td.group(4), td.group(6), td.group(7)
nid, tid = td.group(8), td.group(9)
sys, mod, fec, nsp, s2_flags, roll_off, pilot, inv = self.get_transponder_data(pos, _fec, sys, mod)
nid, tid = int(nid), int(tid)
tr = self._TR.format(freq, sr, pol, fec, pos, inv, sys, s2_flags)
if not tr:
er = f"Transponder [{freq}] not found or its type [T2-MI, etc] not supported yet."
log(f"ServicesParser error [get transponder services]: {er}")
return services
# Services
for r in filter(lambda x: x and len(x) == 12 and (x[0].text.isdigit()), self._rows):
sid, name, s_type, v_pid, a_pid, cas, pkg = r[0].text, r[2].text, r[4].text, r[
5].text.strip(), r[6].text.split(), r[9].text, r[10].text.strip()
try:
s_type = self._S_TYPES.get(s_type, "3") # 3 = Data
_s_type = SERVICE_TYPE.get(s_type, SERVICE_TYPE.get("3")) # str repr
flags, sid, fav_id, picon_id, data_id = self.get_service_data(s_type, pkg, sid, tid, nid, nsp,
v_pid, a_pid, cas, use_pids)
services.append(Service(flags, "s", None, name, None, None, pkg, _s_type, r[1].img, picon_id,
sid, freq, sr, pol, fec, sys, pos, data_id, fav_id, tr))
except ValueError as e:
log(f"ServicesParser error [get transponder services]: {e}")
return services
def get_kingofsat_services(self, sat_position=None, use_pids=False):
services = []
# Transponder
tr = list(filter(lambda r: len(r) == 13 and r[4].url and r[4].url.startswith("tp.php?tp="), self._rows))
if not tr:
log(f"ServicesParser error [get transponder services]: Transponder [{self._t_url}] not found!")
return services
tr = tr[0]
s_pos, freq, pol, sys, mod, sr_fec = tr[0].text, tr[2].text, tr[3].text, tr[6].text, tr[7].text, tr[8].text
tid, nid = tr[10].text, tr[11].text
pos = sat_position
if not sat_position:
pos_tr = re.match(self._POS_PAT, s_pos)
if pos_tr:
pos = self.get_position(pos_tr.group(1))
sr, fec = sr_fec.split()
pol = get_key_by_value(POLARIZATION, pol)
sys, mod, fec, nsp, s2_flags, roll_off, pilot, inv = self.get_transponder_data(pos, fec, sys, mod)
freq, nid, tid = int(float(freq)), int(nid), int(tid)
tr = self._TR.format(freq, sr, pol, fec, pos, inv, sys, s2_flags)
for r in filter(lambda x: len(x) == 14 and not x[1].text and x[7].text and x[7].text.isdigit(), self._rows):
if r[1].img == "/radio.gif":
s_type = ""
elif r[8].img == "/hd.gif":
s_type = "HEVC HD"
elif r[1].img == "/data.gif":
s_type = "Data"
else:
s_type = "SD"
s_type = self._S_TYPES.get(s_type, "3")
_s_type = SERVICE_TYPE.get(s_type, SERVICE_TYPE.get("3"))
name, pkg, cas, sid, v_pid, a_pid = r[2].text, r[5].text, r[6].text, r[7].text, None, None
flags, sid, fav_id, picon_id, data_id = self.get_service_data(s_type, pkg, sid, tid, nid, nsp,
v_pid, a_pid, cas, use_pids)
services.append(Service(flags, "s", None, name, None, None, pkg, _s_type, None, picon_id,
sid, str(freq), sr, pol, fec, sys, pos, data_id, fav_id, tr))
return services
def get_transponder_data(self, pos, fec, sys, mod):
""" Returns converted transponder data. """
sys = get_key_by_value(SYSTEM, sys)
mod = get_key_by_value(MODULATION, mod)
fec = get_key_by_value(FEC, fec)
# For negative (West) positions: 3600 - numeric position value!!!
namespace = "{:04x}0000".format(3600 - pos if pos < 0 else pos)
tr_flag = 1
roll_off = 0 # 35% DVB-S2/DVB-S (default)
pilot = 2 # Auto
s2_flags = "" if sys == "DVB-S" else self._S2_TR.format(tr_flag, mod or 0, roll_off, pilot)
inv = 2 # Default
return sys, mod, fec, namespace, s2_flags, roll_off, pilot, inv
@staticmethod
def get_service_data(s_type, pkg, sid, tid, nid, namespace, v_pid, a_pid, cas, use_pids=False):
sid = int(sid)
data_id = "{:04x}:{}:{:04x}:{:04x}:{}:0:0".format(sid, namespace, tid, nid, s_type)
fav_id = "{}:{}:{}:{}".format(sid, tid, nid, namespace)
picon_id = "1_0_{:X}_{}_{}_{}_{}_0_0_0.png".format(int(s_type), sid, tid, nid, namespace)
# Flags.
flags = "p:{}".format(pkg)
cas = ",".join(get_key_by_value(CAS, c) or "C:0000" for c in cas.split()) if cas else None
if use_pids:
v_pid = "c:00{:04x}".format(int(v_pid)) if v_pid else None
a_pid = ",".join(["c:01{:04x}".format(int(p)) for p in a_pid]) if a_pid else None
flags = ",".join(filter(None, (flags, v_pid, a_pid, cas)))
else:
flags = ",".join(filter(None, (flags, cas)))
return flags, sid, fav_id, picon_id, data_id
@staticmethod
def get_position(pos):
return int(SatellitesParser.get_position("".join(c for c in pos if c.isdigit() or c.isalpha())))
if __name__ == "__main__":
pass

View File

@@ -72,7 +72,7 @@ class EpgTool(Gtk.Box):
p_count = len(paths)
if p_count == 1:
dialog = TimerTool.TimerDialog(TimerTool.TimerAction.EVENT, model[paths][-1])
dialog = TimerTool.TimerDialog(self._app.app_window, TimerTool.TimerAction.EVENT, model[paths][-1])
response = dialog.run()
if response == Gtk.ResponseType.OK:
pass

View File

@@ -1415,6 +1415,7 @@ Author: Dmitriy Yefremov
<property name="can_focus">False</property>
<property name="margin_bottom">2</property>
<property name="orientation">vertical</property>
<property name="spacing">5</property>
<child>
<object class="GtkBox" id="sat_update_header">
<property name="visible">True</property>
@@ -1430,40 +1431,43 @@ Author: Dmitriy Yefremov
<property name="margin_bottom">5</property>
<property name="spacing">5</property>
<child>
<object class="GtkLabel" id="source_label">
<object class="GtkComboBoxText" id="source_combo_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Source:</property>
<property name="track_visited_links">False</property>
<property name="tooltip_text" translatable="yes">Source</property>
<property name="active">0</property>
<items>
<item id="FLYSAT" translatable="yes">FlySat</item>
<item id="LYNGSAT" translatable="yes">LyngSat</item>
<item id="KINGOFSAT" translatable="yes">KingOfSat</item>
</items>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="satellites_update_left_action_box">
<object class="GtkButtonBox" id="sat_update_right_action_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="layout_style">expand</property>
<child>
<object class="GtkButton" id="cancel_data_button">
<property name="label" translatable="yes">Cancel</property>
<object class="GtkButton" id="sat_update_button">
<property name="label" translatable="yes">Update</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Cancel</property>
<property name="valign">center</property>
<property name="image">sat_update_cancel_image</property>
<property name="tooltip_text" translatable="yes">Update</property>
<property name="image">sat_update_image</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_cancel_receive" swapped="no"/>
<signal name="clicked" handler="on_update_satellites_list" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -1480,9 +1484,38 @@ Author: Dmitriy Yefremov
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cancel_data_button">
<property name="label" translatable="yes">Cancel</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Cancel</property>
<property name="image">sat_update_cancel_image</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_cancel_receive" swapped="no"/>
<accelerator key="z" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="sat_update_left_action_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">expand</property>
<child>
<object class="GtkToggleButton" id="sat_update_filter_button">
<property name="label" translatable="yes">Filter</property>
@@ -1493,7 +1526,7 @@ Author: Dmitriy Yefremov
<property name="image">sat_update_filter_image</property>
<property name="always_show_image">True</property>
<signal name="toggled" handler="on_filter_toggled" swapped="no"/>
<accelerator key="f" signal="clicked" modifiers="GDK_SHIFT_MASK"/>
<accelerator key="f" signal="clicked" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</object>
<packing>
<property name="expand">False</property>
@@ -1511,7 +1544,7 @@ Author: Dmitriy Yefremov
<property name="image">sat_update_search_image</property>
<property name="always_show_image">True</property>
<signal name="toggled" handler="on_find_toggled" swapped="no"/>
<accelerator key="f" signal="clicked" modifiers="Primary"/>
<accelerator key="f" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
</object>
<packing>
<property name="expand">False</property>
@@ -1524,54 +1557,7 @@ Author: Dmitriy Yefremov
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="satellites_update_right_action_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<child>
<object class="GtkComboBoxText" id="source_combo_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">0</property>
<items>
<item id="FLYSAT" translatable="yes">FlySat</item>
<item id="LYNGSAT" translatable="yes">LyngSat</item>
<item id="KINGOFSAT" translatable="yes">KingOfSat</item>
</items>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="satellites_update_button">
<property name="label" translatable="yes">Update</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Update</property>
<property name="valign">center</property>
<property name="image">sat_update_image</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_update_satellites_list" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
</object>
@@ -1593,7 +1579,6 @@ Author: Dmitriy Yefremov
</child>
<child>
<object class="GtkSearchBar" id="sat_update_search_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox" id="search_bar_box">
@@ -1668,7 +1653,6 @@ Author: Dmitriy Yefremov
</child>
<child>
<object class="GtkSearchBar" id="sat_update_filter_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="source_header_grid">
@@ -1795,105 +1779,115 @@ Author: Dmitriy Yefremov
<property name="can_focus">True</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="orientation">vertical</property>
<property name="wide_handle">True</property>
<child>
<object class="GtkScrolledWindow" id="sat_update_scrolled_window">
<object class="GtkFrame" id="sat_update_frame">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_top">2</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="sat_update_tree_view">
<object class="GtkScrolledWindow" id="sat_update_scrolled_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">update_sat_list_model_sort</property>
<property name="search_column">0</property>
<property name="activate_on_single_click">True</property>
<signal name="button-press-event" handler="on_popup_menu" object="satellites_update_popup_menu" swapped="no"/>
<signal name="select-all" handler="on_select_all" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection">
<property name="mode">multiple</property>
</object>
</child>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeViewColumn" id="upd_satellite_column">
<property name="title" translatable="yes">Satellite</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<property name="alignment">0.5</property>
<property name="reorderable">True</property>
<property name="sort_column_id">0</property>
<child>
<object class="GtkCellRendererText" id="upd_satellite_cellrenderertext">
<property name="xalign">0.0099999997764825821</property>
<object class="GtkTreeView" id="sat_update_tree_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">update_sat_list_model_sort</property>
<property name="search_column">0</property>
<property name="activate_on_single_click">True</property>
<signal name="button-press-event" handler="on_popup_menu" object="satellites_update_popup_menu" swapped="no"/>
<signal name="select-all" handler="on_select_all" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection">
<property name="mode">multiple</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="upd_position_column">
<property name="title" translatable="yes">Position</property>
<property name="clickable">True</property>
<property name="alignment">0.5</property>
<property name="reorderable">True</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="upd_position_cellrenderertext">
<property name="xalign">0.49000000953674316</property>
<object class="GtkTreeViewColumn" id="upd_satellite_column">
<property name="title" translatable="yes">Satellite</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<property name="alignment">0.5</property>
<property name="reorderable">True</property>
<property name="sort_column_id">0</property>
<child>
<object class="GtkCellRendererText" id="upd_satellite_cellrenderertext">
<property name="xalign">0.0099999997764825821</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="upd_type_column">
<property name="title" translatable="yes">Type</property>
<property name="clickable">True</property>
<property name="alignment">0.5</property>
<property name="reorderable">True</property>
<property name="sort_column_id">2</property>
<child>
<object class="GtkCellRendererText" id="upd_type_cellrenderertext">
<property name="xalign">0.49000000953674316</property>
<object class="GtkTreeViewColumn" id="upd_position_column">
<property name="title" translatable="yes">Position</property>
<property name="clickable">True</property>
<property name="alignment">0.5</property>
<property name="reorderable">True</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="upd_position_cellrenderertext">
<property name="xalign">0.49000000953674316</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="upd_url_column">
<property name="visible">False</property>
<property name="title" translatable="yes">Url</property>
<child>
<object class="GtkCellRendererText" id="upd_url_cellrenderertext"/>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="upd_selected_column">
<property name="title" translatable="yes">Selected</property>
<property name="clickable">True</property>
<property name="reorderable">True</property>
<property name="sort_column_id">4</property>
<child>
<object class="GtkCellRendererToggle" id="upd_selected_cellrenderer">
<signal name="toggled" handler="on_satellite_toggled" swapped="no"/>
<object class="GtkTreeViewColumn" id="upd_type_column">
<property name="title" translatable="yes">Type</property>
<property name="clickable">True</property>
<property name="alignment">0.5</property>
<property name="reorderable">True</property>
<property name="sort_column_id">2</property>
<child>
<object class="GtkCellRendererText" id="upd_type_cellrenderertext">
<property name="xalign">0.49000000953674316</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="upd_url_column">
<property name="visible">False</property>
<property name="title" translatable="yes">Url</property>
<child>
<object class="GtkCellRendererText" id="upd_url_cellrenderertext"/>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="upd_selected_column">
<property name="title" translatable="yes">Selected</property>
<property name="clickable">True</property>
<property name="reorderable">True</property>
<property name="sort_column_id">4</property>
<child>
<object class="GtkCellRendererToggle" id="upd_selected_cellrenderer">
<signal name="toggled" handler="on_satellite_toggled" swapped="no"/>
</object>
<attributes>
<attribute name="active">4</attribute>
</attributes>
</child>
</object>
<attributes>
<attribute name="active">4</attribute>
</attributes>
</child>
</object>
</child>
@@ -1906,173 +1900,190 @@ Author: Dmitriy Yefremov
</packing>
</child>
<child>
<object class="GtkPaned" id="sat_update_tr_paned">
<property name="can_focus">True</property>
<property name="wide_handle">True</property>
<object class="GtkFrame" id="sat_update_tr_frame">
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkScrolledWindow" id="sat_update_tr_scrolled_window">
<object class="GtkPaned" id="sat_update_tr_paned">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="orientation">vertical</property>
<property name="wide_handle">True</property>
<child>
<object class="GtkTreeView" id="sat_update_tr_view">
<object class="GtkScrolledWindow" id="sat_update_tr_scrolled_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">update_transponder_store</property>
<property name="search_column">0</property>
<property name="activate_on_single_click">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeViewColumn" id="tr_view_tr_column">
<property name="title" translatable="yes">Transponder</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="upd_tr_renderer">
<property name="xalign">0.0099999997764825821</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
<object class="GtkTreeView" id="sat_update_tr_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">update_transponder_store</property>
<property name="search_column">0</property>
<property name="activate_on_single_click">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="tr_view_link_column">
<property name="visible">False</property>
<property name="title" translatable="yes">link</property>
<child>
<object class="GtkCellRendererText" id="upd_tr_link_renderer"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="tr_view_selected_column">
<property name="title" translatable="yes">Selected</property>
<child>
<object class="GtkCellRendererToggle" id="upd_tr_select_renderer">
<signal name="toggled" handler="on_transponder_toggled" swapped="no"/>
<object class="GtkTreeViewColumn" id="tr_view_tr_column">
<property name="title" translatable="yes">Transponder</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="upd_tr_renderer">
<property name="xalign">0.0099999997764825821</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="tr_view_link_column">
<property name="visible">False</property>
<property name="title" translatable="yes">link</property>
<child>
<object class="GtkCellRendererText" id="upd_tr_link_renderer"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="tr_view_selected_column">
<property name="title" translatable="yes">Selected</property>
<child>
<object class="GtkCellRendererToggle" id="upd_tr_select_renderer">
<signal name="toggled" handler="on_transponder_toggled" swapped="no"/>
</object>
<attributes>
<attribute name="active">2</attribute>
</attributes>
</child>
</object>
<attributes>
<attribute name="active">2</attribute>
</attributes>
</child>
</object>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="sat_update_srv_scrolled_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="sat_update_srv_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">update_service_store</property>
<property name="search_column">1</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_servcie_column">
<property name="title" translatable="yes">Service</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererPixbuf" id="srv_picon_renderer">
<property name="xpad">2</property>
</object>
<attributes>
<attribute name="pixbuf">0</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="srv_service_renderer">
<property name="xalign">0.0099999997764825821</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_package_column">
<property name="title" translatable="yes">Package</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_package_renderer">
<property name="ellipsize">end</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_type_column">
<property name="title" translatable="yes">Type</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_type_renderer">
<property name="xalign">0.49000000953674316</property>
</object>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_sid_column">
<property name="title" translatable="yes">SID</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_sid_renderer">
<property name="xalign">0.49000000953674316</property>
</object>
<attributes>
<attribute name="text">4</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_cas_column">
<property name="visible">False</property>
<property name="title" translatable="yes">CAS</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_cas_renderer">
<property name="xalign">0.49000000953674316</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="sat_update_srv_scrolled_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="sat_update_srv_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">update_service_store</property>
<property name="search_column">1</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_servcie_column">
<property name="title" translatable="yes">Service</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererPixbuf" id="srv_picon_renderer">
<property name="xpad">2</property>
</object>
<attributes>
<attribute name="pixbuf">0</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="srv_service_renderer">
<property name="xalign">0.0099999997764825821</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_package_column">
<property name="title" translatable="yes">Package</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_package_renderer">
<property name="ellipsize">end</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_type_column">
<property name="title" translatable="yes">Type</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_type_renderer">
<property name="xalign">0.49000000953674316</property>
</object>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_sid_column">
<property name="title" translatable="yes">SID</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_sid_renderer">
<property name="xalign">0.49000000953674316</property>
</object>
<attributes>
<attribute name="text">4</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="srv_view_cas_column">
<property name="title" translatable="yes">CAS</property>
<property name="expand">True</property>
<property name="alignment">0.5</property>
<child>
<object class="GtkCellRendererText" id="srv_cas_renderer">
<property name="xalign">0.49000000953674316</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>

View File

@@ -146,7 +146,7 @@ class SatellitesTool(Gtk.Box):
yield True
except FileNotFoundError as e:
msg = get_message("Please, download files from receiver or setup your path for read data!")
self._app.show_error_message("{}\n{}".format(e, msg))
self._app.show_error_message(f"{e}\n{msg}")
return
else:
model = self._satellite_view.get_model()
@@ -194,7 +194,6 @@ class SatellitesTool(Gtk.Box):
index = paths[0].get_indices()[0] + 1
model.insert(index, sat)
else:
print(sat)
model.append(sat)
def on_transponder(self, transponder=None, edited_itr=None):
@@ -254,7 +253,7 @@ class SatellitesTool(Gtk.Box):
def sat_pos_func(self, column, renderer, model, itr, data):
""" Converts and sets the satellite position value to a readable format. """
pos = int(model.get_value(itr, 2))
renderer.set_property("text", "{:0.1f}{}".format(abs(pos / 10), "W" if pos < 0 else "E"))
renderer.set_property("text", f"{abs(pos / 10):0.1f}{'W' if pos < 0 else 'E'}")
@run_idle
def on_save(self):
@@ -372,7 +371,7 @@ class SatelliteDialog:
if satellite:
self._sat_name.set_text(satellite.name)
pos = satellite.position
pos = float("{}.{}".format(pos[:-1], pos[-1:]))
pos = float(f"{pos[:-1]}.{pos[-1:]}")
self._sat_position.set_value(fabs(pos))
self._side.set_active(0 if pos >= 0 else 1) # E or W
@@ -404,6 +403,7 @@ class UpdateDialog:
"on_receive_data": self.on_receive_data,
"on_cancel_receive": self.on_cancel_receive,
"on_satellite_toggled": self.on_satellite_toggled,
"on_satellite_changed": self.on_satellite_changed,
"on_transponder_toggled": self.on_transponder_toggled,
"on_info_bar_close": self.on_info_bar_close,
"on_filter_toggled": self.on_filter_toggled,
@@ -417,7 +417,7 @@ class UpdateDialog:
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()
self._size_name = f"{'_'.join(re.findall('[A-Z][^A-Z]*', self.__class__.__name__))}_window_size".lower()
builder = get_builder(UI_RESOURCES_PATH + "satellites.glade", handlers,
objects=("satellites_update_window", "update_source_store", "update_sat_list_store",
@@ -432,7 +432,7 @@ class UpdateDialog:
if title:
self._window.set_title(title)
self._transponder_paned = builder.get_object("sat_update_tr_paned")
self._transponder_frame = builder.get_object("sat_update_tr_frame")
self._sat_view = builder.get_object("sat_update_tree_view")
self._transponder_view = builder.get_object("sat_update_tr_view")
self._service_view = builder.get_object("sat_update_srv_view")
@@ -443,6 +443,12 @@ class UpdateDialog:
self._sat_update_info_bar = builder.get_object("sat_update_info_bar")
self._info_bar_message_label = builder.get_object("info_bar_message_label")
self._receive_button.bind_property("visible", builder.get_object("cancel_data_button"), "visible", 4)
update_button = builder.get_object("sat_update_button")
self._sat_view.bind_property("sensitive", update_button, "sensitive")
self._sat_view.bind_property("sensitive", self._source_box, "sensitive")
self._sat_view.bind_property("sensitive", self._source_box, "sensitive")
self._sat_view.bind_property("sensitive", self._receive_button, "sensitive")
self._receive_button.bind_property("visible", update_button, "visible")
# Filter
self._filter_bar = builder.get_object("sat_update_filter_bar")
self._from_pos_button = builder.get_object("from_pos_button")
@@ -452,8 +458,10 @@ class UpdateDialog:
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)
self._filter_bar.bind_property("search-mode-enabled", self._filter_bar, "visible")
# Search
self._search_bar = builder.get_object("sat_update_search_bar")
self._search_bar.bind_property("search-mode-enabled", self._search_bar, "visible")
search_provider = SearchProvider(self._sat_view,
builder.get_object("sat_update_search_entry"),
builder.get_object("sat_update_search_down_button"),
@@ -477,14 +485,17 @@ class UpdateDialog:
self._receive_button.set_visible(not value)
@run_idle
def on_update_satellites_list(self, item):
def on_update_satellites_list(self, item=None):
if self.is_download:
show_dialog(DialogType.ERROR, self._window, "The task is already running!")
return
model = get_base_model(self._sat_view.get_model())
model.clear()
get_base_model(self._sat_view.get_model()).clear()
self._transponder_view.get_model().clear()
self._service_view.get_model().clear()
self.is_download = True
self._sat_view.set_sensitive(False)
src = self._source_box.get_active()
if not self._parser:
self._parser = SatellitesParser()
@@ -510,6 +521,8 @@ class UpdateDialog:
for sat in sats:
model.append(sat)
self._sat_view.set_sensitive(True)
@run_idle
def on_receive_data(self, item):
if self.is_download:
@@ -533,6 +546,9 @@ class UpdateDialog:
def on_cancel_receive(self, item=None):
self._download_task = False
def on_satellite_changed(self, box):
self.on_update_satellites_list()
def on_satellite_toggled(self, toggle, path):
model = self._sat_view.get_model()
self.update_state(model, path, not toggle.get_active())
@@ -612,6 +628,7 @@ class SatellitesUpdateDialog(UpdateDialog):
super().__init__(transient=transient, settings=settings)
self._main_model = main_model
self._source_box.connect("changed", self.on_update_satellites_list)
@run_idle
def on_receive_data(self, item):
@@ -655,15 +672,15 @@ class SatellitesUpdateDialog(UpdateDialog):
pos = row[2]
if pos in sats:
sat = sats.pop(pos)
appender.send("Updating satellite: {}\n".format(row[0]))
appender.send(f"Updating satellite: {row[0]}\n")
GLib.idle_add(self._main_model.set, row.iter, {i: v for i, v in enumerate(sat)})
for p, s in sats.items():
appender.send("Adding satellite: {}\n".format(s.name))
appender.send(f"Adding satellite: {s.name}\n")
self.append_satellite(s)
appender.send("-" * 75 + "\n")
appender.send("Consumed: {:0.0f}s, {} satellites received.\n".format(time.time() - start, sat_count))
appender.send(f"Consumed: {time.time() - start:0.0f}s, {sat_count} satellites received.\n")
appender.close()
self.is_download = False
@@ -684,11 +701,6 @@ class ServicesUpdateDialog(UpdateDialog):
self._services = {}
self._selected_transponders = set()
self._services_parser = ServicesParser(source=SatelliteSource.LYNGSAT)
self._transponder_paned.set_visible(True)
self._source_box.remove(0)
self._source_box.remove(1)
self._source_box.set_active(0)
# Transponder view popup menu
tr_popup_menu = Gtk.Menu()
select_all_item = Gtk.ImageMenuItem.new_from_stock("gtk-select-all")
@@ -705,6 +717,11 @@ class ServicesUpdateDialog(UpdateDialog):
self._transponder_view.connect("button-press-event", lambda w, e: on_popup_menu(tr_popup_menu, e))
self._transponder_view.connect("select_all", lambda w: self.update_transponder_selection(True))
self._transponder_frame.set_visible(True)
self._source_box.remove(0)
self._source_box.connect("changed", self.on_update_satellites_list)
self._source_box.set_active(0)
@run_idle
def on_receive_data(self, item):
if self.is_download:
@@ -752,13 +769,13 @@ class ServicesUpdateDialog(UpdateDialog):
self.is_download = False
return
appender.send("Getting transponders for: {}.\n".format(sat_names.get(futures[future])))
appender.send(f"Getting transponders for: {sat_names.get(futures[future])}.\n")
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)))
appender.send(f"{len(t_urls)} transponders received.\n\n")
non_cached_ts = []
for tr in t_urls:
@@ -774,11 +791,11 @@ class ServicesUpdateDialog(UpdateDialog):
self.is_download = False
return
appender.send("Getting services for: {}.\n".format(t_names.get(futures[future], "")))
appender.send(f"Getting services for: {t_names.get(futures[future], '')}.\n")
list(map(services.append, future.result()))
appender.send("-" * 75 + "\n")
appender.send("Consumed: {:0.0f}s, {} services received.".format(time.time() - start, len(services)))
appender.send(f"Consumed: {time.time() - start:0.0f}s, {len(services)} services received.")
try:
from app.eparser.enigma.lamedb import LameDbReader
@@ -786,7 +803,7 @@ class ServicesUpdateDialog(UpdateDialog):
reader = LameDbReader(path=None)
srvs = reader.get_services_list("".join(reader.get_services_lines(services)))
except ValueError as e:
log("ServicesUpdateDialog [on receive data] error: {}".format(e))
log(f"ServicesUpdateDialog [on receive data] error: {e}")
else:
self._callback(srvs)
@@ -794,7 +811,12 @@ class ServicesUpdateDialog(UpdateDialog):
@run_task
def get_sat_list(self, src, callback):
sats = self._parser.get_satellites_list(SatelliteSource.LYNGSAT)
sat_src = SatelliteSource.LYNGSAT
if src == 1:
sat_src = SatelliteSource.KINGOFSAT
self._services_parser.source = sat_src
sats = self._parser.get_satellites_list(sat_src)
if sats:
callback(sats)
self.is_download = False
@@ -838,6 +860,9 @@ class ServicesUpdateDialog(UpdateDialog):
@run_task
def on_activate_satellite(self, view, path, column):
GLib.idle_add(self._transponder_view.get_model().clear)
GLib.idle_add(self._service_view.get_model().clear)
model = view.get_model()
itr = model.get_iter(path)
url, selected = model.get_value(itr, 3), model.get_value(itr, 4)