2017-12-24 01:40:30 +03:00
|
|
|
""" This is helper module for ui """
|
2018-01-31 00:13:42 +03:00
|
|
|
import os
|
2018-02-01 14:02:59 +03:00
|
|
|
import shutil
|
2019-01-27 23:28:53 +03:00
|
|
|
import urllib.request
|
|
|
|
|
|
2018-08-18 10:21:40 +03:00
|
|
|
from gi.repository import GdkPixbuf, GLib
|
2018-01-31 00:13:42 +03:00
|
|
|
|
2018-04-14 00:05:08 +03:00
|
|
|
from app.commons import run_task
|
2018-01-01 23:42:40 +03:00
|
|
|
from app.eparser import Service
|
2018-04-04 16:52:58 +03:00
|
|
|
from app.eparser.ecommons import Flag, BouquetService, Bouquet, BqType
|
2018-01-01 17:28:19 +03:00
|
|
|
from app.eparser.enigma.bouquets import BqServiceType, to_bouquet_id
|
2019-12-22 20:42:29 +03:00
|
|
|
from app.settings import SettingsType
|
2018-12-18 19:23:44 +03:00
|
|
|
from .uicommons import ViewTarget, BqGenType, Gtk, Gdk, HIDE_ICON, LOCKED_ICON, KeyboardKey, Column
|
2018-04-10 13:04:21 +03:00
|
|
|
from .dialogs import show_dialog, DialogType, get_chooser_dialog, WaitDialog
|
2017-12-20 16:46:15 +03:00
|
|
|
|
|
|
|
|
|
2017-12-24 01:40:30 +03:00
|
|
|
# ***************** Markers *******************#
|
2017-12-23 22:25:29 +03:00
|
|
|
|
2019-06-26 15:38:34 +03:00
|
|
|
def insert_marker(view, bouquets, selected_bouquet, services, parent_window):
|
2017-12-20 16:46:15 +03:00
|
|
|
"""" Inserts marker into bouquet services list. """
|
|
|
|
|
response = show_dialog(DialogType.INPUT, parent_window)
|
|
|
|
|
if response == Gtk.ResponseType.CANCEL:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if not response.strip():
|
|
|
|
|
show_dialog(DialogType.ERROR, parent_window, "The text of marker is empty, please try again!")
|
|
|
|
|
return
|
|
|
|
|
|
2019-09-04 10:39:46 +03:00
|
|
|
fav_id = "1:64:0:0:0:0:0:0:0:0::{}\n#DESCRIPTION {}\n".format(response, response)
|
2017-12-20 16:46:15 +03:00
|
|
|
s_type = BqServiceType.MARKER.name
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
2018-12-18 19:23:44 +03:00
|
|
|
marker = (None, None, response, None, None, s_type, None, fav_id, None, None, None)
|
2018-02-06 13:56:17 +03:00
|
|
|
itr = model.insert_before(model.get_iter(paths[0]), marker) if paths else model.insert(0, marker)
|
2017-12-20 16:46:15 +03:00
|
|
|
bouquets[selected_bouquet].insert(model.get_path(itr)[0], fav_id)
|
2019-09-04 10:39:46 +03:00
|
|
|
services[fav_id] = Service(None, None, None, response, None, None, None, s_type, *[None] * 9, 0, fav_id, None)
|
2017-12-20 16:46:15 +03:00
|
|
|
|
|
|
|
|
|
2017-12-24 01:40:30 +03:00
|
|
|
# ***************** Movement *******************#
|
2017-12-23 22:25:29 +03:00
|
|
|
|
2018-04-16 18:50:48 +03:00
|
|
|
def move_items(key, view: Gtk.TreeView):
|
|
|
|
|
""" Move items in the tree view """
|
2017-12-23 22:25:29 +03:00
|
|
|
selection = view.get_selection()
|
|
|
|
|
model, paths = selection.get_selected_rows()
|
|
|
|
|
|
|
|
|
|
if paths:
|
2018-04-16 18:50:48 +03:00
|
|
|
mod_length = len(model)
|
2018-09-18 14:40:24 +03:00
|
|
|
if mod_length == len(paths):
|
|
|
|
|
return
|
2018-04-16 18:50:48 +03:00
|
|
|
cursor_path = view.get_cursor()[0]
|
|
|
|
|
max_path = Gtk.TreePath.new_from_indices((mod_length,))
|
|
|
|
|
min_path = Gtk.TreePath.new_from_indices((0,))
|
|
|
|
|
is_tree_store = False
|
|
|
|
|
|
|
|
|
|
if type(model) is Gtk.TreeStore:
|
|
|
|
|
parent_paths = list(filter(lambda p: p.get_depth() == 1, paths))
|
|
|
|
|
if parent_paths:
|
|
|
|
|
paths = parent_paths
|
|
|
|
|
min_path = model.get_path(model.get_iter_first())
|
2018-04-16 19:42:48 +03:00
|
|
|
view.collapse_all()
|
|
|
|
|
if mod_length == len(paths):
|
|
|
|
|
return
|
2018-04-16 18:50:48 +03:00
|
|
|
else:
|
|
|
|
|
if not is_some_level(paths):
|
|
|
|
|
return
|
|
|
|
|
parent_itr = model.iter_parent(model.get_iter(paths[0]))
|
|
|
|
|
parent_index = model.get_path(parent_itr)
|
|
|
|
|
children_num = model.iter_n_children(parent_itr)
|
2018-11-05 11:09:15 +03:00
|
|
|
if key in (KeyboardKey.PAGE_DOWN, KeyboardKey.END, KeyboardKey.END_KP, KeyboardKey.PAGE_DOWN_KP):
|
2018-04-16 18:50:48 +03:00
|
|
|
children_num -= 1
|
|
|
|
|
min_path = Gtk.TreePath.new_from_string("{}:{}".format(parent_index, 0))
|
|
|
|
|
max_path = Gtk.TreePath.new_from_string("{}:{}".format(parent_index, children_num))
|
|
|
|
|
is_tree_store = True
|
|
|
|
|
|
2018-11-05 00:31:44 +03:00
|
|
|
if key is KeyboardKey.UP:
|
2018-04-16 18:50:48 +03:00
|
|
|
top_path = Gtk.TreePath(paths[0])
|
2019-01-30 14:39:58 +03:00
|
|
|
set_cursor(top_path, paths, selection, view)
|
2018-04-16 18:50:48 +03:00
|
|
|
top_path.prev()
|
|
|
|
|
move_up(top_path, model, paths)
|
2018-11-05 00:31:44 +03:00
|
|
|
elif key is KeyboardKey.DOWN:
|
2018-04-16 18:50:48 +03:00
|
|
|
down_path = Gtk.TreePath(paths[-1])
|
2019-01-30 14:39:58 +03:00
|
|
|
set_cursor(down_path, paths, selection, view)
|
2018-04-16 18:50:48 +03:00
|
|
|
down_path.next()
|
|
|
|
|
if down_path < max_path:
|
|
|
|
|
move_down(down_path, model, paths)
|
|
|
|
|
else:
|
|
|
|
|
max_path.prev()
|
|
|
|
|
move_down(max_path, model, paths)
|
2018-11-05 11:09:15 +03:00
|
|
|
elif key in (KeyboardKey.PAGE_UP, KeyboardKey.HOME, KeyboardKey.PAGE_UP_KP, KeyboardKey.HOME_KP):
|
2018-04-16 18:50:48 +03:00
|
|
|
move_up(min_path if is_tree_store else cursor_path, model, paths)
|
2018-11-05 11:09:15 +03:00
|
|
|
elif key in (KeyboardKey.PAGE_DOWN, KeyboardKey.END, KeyboardKey.END_KP, KeyboardKey.PAGE_DOWN_KP):
|
2018-04-16 18:50:48 +03:00
|
|
|
move_down(max_path if is_tree_store else cursor_path, model, paths)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def move_up(top_path, model, paths):
|
|
|
|
|
top_iter = model.get_iter(top_path)
|
|
|
|
|
for path in paths:
|
|
|
|
|
itr = model.get_iter(path)
|
|
|
|
|
model.move_before(itr, top_iter)
|
|
|
|
|
top_path.next()
|
|
|
|
|
top_iter = model.get_iter(top_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def move_down(down_path, model, paths):
|
|
|
|
|
top_iter = model.get_iter(down_path)
|
|
|
|
|
for path in reversed(paths):
|
|
|
|
|
itr = model.get_iter(path)
|
|
|
|
|
model.move_after(itr, top_iter)
|
|
|
|
|
down_path.prev()
|
|
|
|
|
top_iter = model.get_iter(down_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_some_level(paths):
|
|
|
|
|
for i in range(1, len(paths)):
|
|
|
|
|
prev = paths[i - 1]
|
|
|
|
|
current = paths[i]
|
|
|
|
|
if len(prev) != len(current) or (len(prev) == 2 and len(current) == 2 and prev[0] != current[0]):
|
|
|
|
|
return
|
|
|
|
|
return True
|
2017-12-23 22:25:29 +03:00
|
|
|
|
|
|
|
|
|
2019-01-30 14:39:58 +03:00
|
|
|
def set_cursor(dest_path, paths, selection, view):
|
|
|
|
|
view.set_cursor(dest_path, view.get_column(0), False)
|
|
|
|
|
for p in paths:
|
|
|
|
|
selection.select_path(p)
|
|
|
|
|
|
|
|
|
|
|
2018-02-18 11:23:31 +03:00
|
|
|
# ***************** Rename *******************#
|
2017-12-24 01:40:30 +03:00
|
|
|
|
2018-10-25 16:00:25 +03:00
|
|
|
def rename(view, parent_window, target, fav_view=None, service_view=None, services=None):
|
2018-09-11 15:21:05 +03:00
|
|
|
selection = get_selection(view, parent_window)
|
|
|
|
|
if not selection:
|
2017-12-24 01:40:30 +03:00
|
|
|
return
|
|
|
|
|
|
2018-09-11 15:21:05 +03:00
|
|
|
model, paths = selection
|
2017-12-24 01:40:30 +03:00
|
|
|
itr = model.get_iter(paths)
|
2018-10-25 16:00:25 +03:00
|
|
|
f_id, srv_name, srv_type = None, None, None
|
2017-12-24 01:40:30 +03:00
|
|
|
|
|
|
|
|
if target is ViewTarget.SERVICES:
|
2018-12-18 19:23:44 +03:00
|
|
|
name, fav_id = model.get(itr, Column.SRV_SERVICE, Column.SRV_FAV_ID)
|
2017-12-24 01:40:30 +03:00
|
|
|
f_id = fav_id
|
|
|
|
|
response = show_dialog(DialogType.INPUT, parent_window, name)
|
|
|
|
|
if response == Gtk.ResponseType.CANCEL:
|
|
|
|
|
return
|
2018-10-25 16:00:25 +03:00
|
|
|
srv_name = response
|
2018-12-18 19:23:44 +03:00
|
|
|
model.set_value(itr, Column.SRV_SERVICE, response)
|
2017-12-24 01:40:30 +03:00
|
|
|
if fav_view is not None:
|
|
|
|
|
for row in fav_view.get_model():
|
2018-12-18 19:23:44 +03:00
|
|
|
if row[Column.FAV_ID] == fav_id:
|
|
|
|
|
row[Column.FAV_SERVICE] = response
|
2017-12-24 01:40:30 +03:00
|
|
|
break
|
|
|
|
|
elif target is ViewTarget.FAV:
|
2018-12-18 19:23:44 +03:00
|
|
|
name, srv_type, fav_id = model.get(itr, Column.FAV_SERVICE, Column.FAV_TYPE, Column.FAV_ID)
|
2017-12-24 01:40:30 +03:00
|
|
|
f_id = fav_id
|
|
|
|
|
response = show_dialog(DialogType.INPUT, parent_window, name)
|
|
|
|
|
if response == Gtk.ResponseType.CANCEL:
|
|
|
|
|
return
|
|
|
|
|
|
2018-10-25 16:00:25 +03:00
|
|
|
srv_name = response
|
2018-12-18 19:23:44 +03:00
|
|
|
model.set_value(itr, Column.FAV_SERVICE, response)
|
2017-12-24 01:40:30 +03:00
|
|
|
|
|
|
|
|
if service_view is not None:
|
2018-02-06 13:56:17 +03:00
|
|
|
for row in get_base_model(service_view.get_model()):
|
2018-12-18 19:23:44 +03:00
|
|
|
if row[Column.SRV_FAV_ID] == fav_id:
|
|
|
|
|
row[Column.SRV_SERVICE] = response
|
2017-12-24 01:40:30 +03:00
|
|
|
break
|
|
|
|
|
|
2018-10-25 16:00:25 +03:00
|
|
|
old_srv = services.get(f_id, None)
|
|
|
|
|
if old_srv:
|
|
|
|
|
if srv_type == BqServiceType.IPTV.name or srv_type == BqServiceType.MARKER.name:
|
2018-10-26 19:28:40 +03:00
|
|
|
l, sep, r = f_id.partition("#DESCRIPTION")
|
|
|
|
|
old_name = old_srv.service.strip()
|
|
|
|
|
new_name = srv_name.strip()
|
|
|
|
|
new_fav_id = "".join((new_name.join(l.rsplit(old_name, 1)), sep, new_name.join(r.rsplit(old_name, 1))))
|
2018-10-25 16:00:25 +03:00
|
|
|
services[f_id] = old_srv._replace(service=srv_name, fav_id=new_fav_id)
|
|
|
|
|
else:
|
|
|
|
|
services[f_id] = old_srv._replace(service=srv_name)
|
2017-12-24 01:40:30 +03:00
|
|
|
|
|
|
|
|
|
2018-09-11 15:21:05 +03:00
|
|
|
def get_selection(view, parent):
|
|
|
|
|
""" Returns (model, paths) if possible """
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
|
|
|
|
model = get_base_model(model)
|
|
|
|
|
|
|
|
|
|
if not paths:
|
|
|
|
|
return
|
|
|
|
|
elif len(paths) > 1:
|
|
|
|
|
show_dialog(DialogType.ERROR, parent, "Please, select only one item!")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
return model, paths
|
|
|
|
|
|
|
|
|
|
|
2017-12-24 16:43:05 +03:00
|
|
|
# ***************** Flags *******************#
|
|
|
|
|
|
2018-09-29 21:57:17 +03:00
|
|
|
def set_flags(flag, services_view, fav_view, services, blacklist):
|
2017-12-24 16:43:05 +03:00
|
|
|
""" Updates flags for services. Returns True if any was changed. """
|
|
|
|
|
target = ViewTarget.SERVICES if services_view.is_focus() else ViewTarget.FAV if fav_view.is_focus() else None
|
|
|
|
|
if not target:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
model, paths = None, None
|
|
|
|
|
|
|
|
|
|
if target is ViewTarget.SERVICES:
|
|
|
|
|
model, paths = services_view.get_selection().get_selected_rows()
|
|
|
|
|
elif target is ViewTarget.FAV:
|
2017-12-24 20:54:56 +03:00
|
|
|
model, paths = fav_view.get_selection().get_selected_rows()
|
2017-12-24 16:43:05 +03:00
|
|
|
|
|
|
|
|
if not paths:
|
|
|
|
|
return
|
|
|
|
|
|
2018-01-25 21:05:24 +03:00
|
|
|
model = get_base_model(model)
|
|
|
|
|
|
2018-02-17 16:23:41 +03:00
|
|
|
if flag is Flag.HIDE:
|
2017-12-29 19:49:01 +03:00
|
|
|
if target is ViewTarget.SERVICES:
|
2018-09-29 21:57:17 +03:00
|
|
|
set_hide(services, model, paths)
|
2017-12-29 19:49:01 +03:00
|
|
|
else:
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_ids = [model.get_value(model.get_iter(path), Column.FAV_ID) for path in paths]
|
2018-01-25 21:05:24 +03:00
|
|
|
srv_model = get_base_model(services_view.get_model())
|
2018-12-18 19:23:44 +03:00
|
|
|
srv_paths = [row.path for row in srv_model if row[Column.SRV_FAV_ID] in fav_ids]
|
2018-09-29 21:57:17 +03:00
|
|
|
set_hide(services, srv_model, srv_paths)
|
2018-02-17 16:23:41 +03:00
|
|
|
elif flag is Flag.LOCK:
|
2018-09-29 21:57:17 +03:00
|
|
|
set_lock(blacklist, services, model, paths, target, services_model=get_base_model(services_view.get_model()))
|
2017-12-24 16:43:05 +03:00
|
|
|
|
2018-09-29 21:57:17 +03:00
|
|
|
update_fav_model(fav_view, services)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_fav_model(fav_view, services):
|
|
|
|
|
for row in get_base_model(fav_view.get_model()):
|
2018-12-18 19:23:44 +03:00
|
|
|
srv = services.get(row[Column.FAV_ID], None)
|
2018-09-29 21:57:17 +03:00
|
|
|
if srv:
|
2018-12-18 19:23:44 +03:00
|
|
|
row[Column.FAV_LOCKED], row[Column.FAV_HIDE] = srv.locked, srv.hide
|
2017-12-24 16:43:05 +03:00
|
|
|
|
|
|
|
|
|
2018-09-29 21:57:17 +03:00
|
|
|
def set_lock(blacklist, services, model, paths, target, services_model):
|
2018-12-18 19:23:44 +03:00
|
|
|
col_num = Column.SRV_LOCKED if target is ViewTarget.SERVICES else Column.FAV_LOCKED
|
2017-12-24 16:43:05 +03:00
|
|
|
locked = has_locked_hide(model, paths, col_num)
|
2017-12-24 20:54:56 +03:00
|
|
|
|
|
|
|
|
ids = []
|
|
|
|
|
|
2017-12-24 16:43:05 +03:00
|
|
|
for path in paths:
|
|
|
|
|
itr = model.get_iter(path)
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_id = model.get_value(itr, Column.SRV_FAV_ID if target is ViewTarget.SERVICES else Column.FAV_ID)
|
2018-09-29 21:57:17 +03:00
|
|
|
srv = services.get(fav_id, None)
|
|
|
|
|
if srv:
|
|
|
|
|
bq_id = to_bouquet_id(srv)
|
2018-01-28 23:10:54 +03:00
|
|
|
if not bq_id:
|
|
|
|
|
continue
|
2017-12-24 16:43:05 +03:00
|
|
|
blacklist.discard(bq_id) if locked else blacklist.add(bq_id)
|
2017-12-24 20:54:56 +03:00
|
|
|
model.set_value(itr, col_num, None if locked else LOCKED_ICON)
|
2018-09-29 21:57:17 +03:00
|
|
|
services[fav_id] = srv._replace(locked=None if locked else LOCKED_ICON)
|
2017-12-24 20:54:56 +03:00
|
|
|
ids.append(fav_id)
|
|
|
|
|
|
|
|
|
|
if target is ViewTarget.FAV and ids:
|
2018-09-29 21:57:17 +03:00
|
|
|
gen = update_services_model(ids, locked, services_model)
|
|
|
|
|
GLib.idle_add(lambda: next(gen, False))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_services_model(ids, locked, services_model):
|
|
|
|
|
for srv in services_model:
|
2018-12-18 19:23:44 +03:00
|
|
|
if srv[Column.SRV_FAV_ID] in ids:
|
|
|
|
|
srv[Column.SRV_LOCKED] = None if locked else LOCKED_ICON
|
2018-09-29 21:57:17 +03:00
|
|
|
yield True
|
2017-12-24 16:43:05 +03:00
|
|
|
|
|
|
|
|
|
2018-09-29 21:57:17 +03:00
|
|
|
def set_hide(services, model, paths):
|
2018-12-18 19:23:44 +03:00
|
|
|
col_num = Column.SRV_HIDE
|
2017-12-24 16:43:05 +03:00
|
|
|
hide = has_locked_hide(model, paths, col_num)
|
|
|
|
|
|
|
|
|
|
for path in paths:
|
|
|
|
|
itr = model.get_iter(path)
|
2017-12-24 20:54:56 +03:00
|
|
|
model.set_value(itr, col_num, None if hide else HIDE_ICON)
|
2017-12-24 16:43:05 +03:00
|
|
|
flags = [*model.get_value(itr, 0).split(",")]
|
|
|
|
|
index, flag = None, None
|
|
|
|
|
for i, fl in enumerate(flags):
|
|
|
|
|
if fl.startswith("f:"):
|
|
|
|
|
index = i
|
|
|
|
|
flag = fl
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
value = int(flag[2:]) if flag else 0
|
|
|
|
|
|
|
|
|
|
if not hide:
|
2018-02-19 23:18:01 +03:00
|
|
|
if Flag.is_hide(value):
|
2017-12-24 16:43:05 +03:00
|
|
|
continue # skip if already hidden
|
2018-02-17 16:23:41 +03:00
|
|
|
value += Flag.HIDE.value
|
2017-12-24 16:43:05 +03:00
|
|
|
else:
|
2018-02-19 23:18:01 +03:00
|
|
|
if not Flag.is_hide(value):
|
2017-12-24 16:43:05 +03:00
|
|
|
continue # skip if already allowed to show
|
2018-02-17 16:23:41 +03:00
|
|
|
value -= Flag.HIDE.value
|
2017-12-24 16:43:05 +03:00
|
|
|
|
2017-12-29 19:49:01 +03:00
|
|
|
if value == 0 and index is not None:
|
2018-01-02 17:38:01 +03:00
|
|
|
del flags[index]
|
2017-12-24 16:43:05 +03:00
|
|
|
else:
|
2018-02-20 23:34:07 +03:00
|
|
|
value = "f:{:02d}".format(value)
|
2017-12-29 19:49:01 +03:00
|
|
|
if index is not None:
|
|
|
|
|
flags[index] = value
|
|
|
|
|
else:
|
|
|
|
|
flags.append(value)
|
2017-12-24 16:43:05 +03:00
|
|
|
|
|
|
|
|
model.set_value(itr, 0, (",".join(reversed(sorted(flags)))))
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_id = model.get_value(itr, Column.SRV_FAV_ID)
|
2018-09-29 21:57:17 +03:00
|
|
|
srv = services.get(fav_id, None)
|
|
|
|
|
if srv:
|
|
|
|
|
services[fav_id] = srv._replace(hide=None if hide else HIDE_ICON)
|
2017-12-24 16:43:05 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def has_locked_hide(model, paths, col_num):
|
|
|
|
|
for path in paths:
|
|
|
|
|
if model.get_value(model.get_iter(path), col_num):
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2017-12-24 20:54:56 +03:00
|
|
|
# ***************** Location *******************#
|
|
|
|
|
|
|
|
|
|
def locate_in_services(fav_view, services_view, parent_window):
|
|
|
|
|
""" Locating and scrolling to the service """
|
|
|
|
|
model, paths = fav_view.get_selection().get_selected_rows()
|
|
|
|
|
|
|
|
|
|
if not paths:
|
|
|
|
|
return
|
|
|
|
|
elif len(paths) > 1:
|
|
|
|
|
show_dialog(DialogType.ERROR, parent_window, "Please, select only one item!")
|
|
|
|
|
return
|
|
|
|
|
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_id = model.get_value(model.get_iter(paths[0]), Column.FAV_ID)
|
2017-12-24 20:54:56 +03:00
|
|
|
for index, row in enumerate(services_view.get_model()):
|
2018-12-18 19:23:44 +03:00
|
|
|
if row[Column.SRV_FAV_ID] == fav_id:
|
2017-12-24 20:54:56 +03:00
|
|
|
scroll_to(index, services_view)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
2017-12-25 19:50:35 +03:00
|
|
|
def scroll_to(index, view, paths=None):
|
2017-12-24 20:54:56 +03:00
|
|
|
""" Scrolling to and selecting given index(path) """
|
2017-12-25 19:50:35 +03:00
|
|
|
if paths is not None:
|
|
|
|
|
view.expand_row(paths[0], 0)
|
2017-12-24 20:54:56 +03:00
|
|
|
view.scroll_to_cell(index, None)
|
|
|
|
|
selection = view.get_selection()
|
|
|
|
|
selection.unselect_all()
|
|
|
|
|
selection.select_path(index)
|
|
|
|
|
|
|
|
|
|
|
2018-01-31 00:13:42 +03:00
|
|
|
# ***************** Picons *********************#
|
|
|
|
|
|
2018-08-18 10:21:40 +03:00
|
|
|
def update_picons_data(path, picons):
|
2018-01-31 00:13:42 +03:00
|
|
|
if not os.path.exists(path):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
for file in os.listdir(path):
|
2018-02-01 21:43:44 +03:00
|
|
|
picons[file] = get_picon_pixbuf(path + file)
|
2018-01-31 00:13:42 +03:00
|
|
|
|
2018-08-18 10:21:40 +03:00
|
|
|
|
|
|
|
|
def append_picons(picons, model):
|
|
|
|
|
def append_picons_data(pcs, mod):
|
|
|
|
|
for r in mod:
|
2018-12-18 19:23:44 +03:00
|
|
|
mod.set_value(mod.get_iter(r.path), Column.SRV_PICON, pcs.get(r[Column.SRV_PICON_ID], None))
|
2018-08-18 10:21:40 +03:00
|
|
|
yield True
|
|
|
|
|
|
|
|
|
|
app = append_picons_data(picons, model)
|
|
|
|
|
GLib.idle_add(lambda: next(app, False), priority=GLib.PRIORITY_LOW)
|
2018-01-31 00:13:42 +03:00
|
|
|
|
|
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
def assign_picon(target, srv_view, fav_view, transient, picons, settings, services):
|
2018-02-01 21:43:44 +03:00
|
|
|
view = srv_view if target is ViewTarget.SERVICES else fav_view
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
|
|
|
|
if not is_only_one_item_selected(paths, transient):
|
|
|
|
|
return
|
|
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
response = get_chooser_dialog(transient, settings, "*.png", "png files")
|
2018-01-31 00:13:42 +03:00
|
|
|
if response == Gtk.ResponseType.CANCEL:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if not str(response).endswith(".png"):
|
|
|
|
|
show_dialog(DialogType.ERROR, transient, text="No png file is selected!")
|
|
|
|
|
return
|
|
|
|
|
|
2018-12-18 19:23:44 +03:00
|
|
|
picon_pos = Column.SRV_PICON
|
2018-02-01 21:43:44 +03:00
|
|
|
model = get_base_model(model)
|
|
|
|
|
itr = model.get_iter(paths)
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_id = model.get_value(itr, Column.SRV_FAV_ID if target is ViewTarget.SERVICES else Column.FAV_ID)
|
|
|
|
|
picon_id = services.get(fav_id)[Column.SRV_PICON_ID]
|
2018-02-01 21:43:44 +03:00
|
|
|
|
|
|
|
|
if picon_id:
|
|
|
|
|
if os.path.isfile(response):
|
2019-12-22 20:42:29 +03:00
|
|
|
picons_path = settings.picons_local_path
|
2019-12-15 19:01:27 +03:00
|
|
|
os.makedirs(os.path.dirname(picons_path), exist_ok=True)
|
|
|
|
|
picon_file = picons_path + picon_id
|
2018-02-01 21:43:44 +03:00
|
|
|
shutil.copy(response, picon_file)
|
|
|
|
|
picon = get_picon_pixbuf(picon_file)
|
|
|
|
|
picons[picon_id] = picon
|
|
|
|
|
model.set_value(itr, picon_pos, picon)
|
|
|
|
|
if target is ViewTarget.SERVICES:
|
2018-12-18 19:23:44 +03:00
|
|
|
set_picon(fav_id, fav_view.get_model(), picon, Column.FAV_ID, picon_pos)
|
2018-02-01 21:43:44 +03:00
|
|
|
else:
|
2018-12-18 19:23:44 +03:00
|
|
|
set_picon(fav_id, get_base_model(srv_view.get_model()), picon, Column.SRV_FAV_ID, picon_pos)
|
2018-02-01 21:43:44 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_picon(fav_id, model, picon, fav_id_pos, picon_pos):
|
|
|
|
|
for row in model:
|
|
|
|
|
if row[fav_id_pos] == fav_id:
|
|
|
|
|
row[picon_pos] = picon
|
|
|
|
|
break
|
|
|
|
|
|
2018-01-31 00:13:42 +03:00
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
def remove_picon(target, srv_view, fav_view, picons, settings):
|
2018-02-01 13:10:06 +03:00
|
|
|
view = srv_view if target is ViewTarget.SERVICES else fav_view
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
|
|
|
|
model = get_base_model(model)
|
|
|
|
|
|
|
|
|
|
fav_ids = []
|
|
|
|
|
picon_ids = []
|
2018-12-18 19:23:44 +03:00
|
|
|
picon_pos = Column.SRV_PICON # picon position is equal for services and fav
|
2018-02-01 14:02:59 +03:00
|
|
|
|
2018-02-01 13:10:06 +03:00
|
|
|
for path in paths:
|
|
|
|
|
itr = model.get_iter(path)
|
|
|
|
|
model.set_value(itr, picon_pos, None)
|
|
|
|
|
if target is ViewTarget.SERVICES:
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_ids.append(model.get_value(itr, Column.SRV_FAV_ID))
|
|
|
|
|
picon_ids.append(model.get_value(itr, Column.SRV_PICON_ID))
|
2018-02-01 13:10:06 +03:00
|
|
|
else:
|
2018-12-18 19:23:44 +03:00
|
|
|
srv_type, fav_id = model.get(itr, Column.FAV_TYPE, Column.FAV_ID)
|
2018-09-16 15:41:06 +03:00
|
|
|
if srv_type == BqServiceType.IPTV.name:
|
|
|
|
|
picon_ids.append("{}_{}_{}_{}_{}_{}_{}_{}_{}_{}.png".format(*fav_id.split(":")[0:10]).strip())
|
|
|
|
|
else:
|
|
|
|
|
fav_ids.append(fav_id)
|
2018-02-01 13:10:06 +03:00
|
|
|
|
2018-09-16 15:41:06 +03:00
|
|
|
def remove(md, path, it):
|
2018-12-18 19:23:44 +03:00
|
|
|
if md.get_value(it, Column.FAV_ID if target is ViewTarget.SERVICES else Column.SRV_FAV_ID) in fav_ids:
|
2018-09-16 15:41:06 +03:00
|
|
|
md.set_value(it, picon_pos, None)
|
2018-02-01 13:10:06 +03:00
|
|
|
if target is ViewTarget.FAV:
|
2018-12-18 19:23:44 +03:00
|
|
|
picon_ids.append(md.get_value(it, Column.SRV_PICON_ID))
|
2018-02-01 13:10:06 +03:00
|
|
|
|
|
|
|
|
fav_view.get_model().foreach(remove) if target is ViewTarget.SERVICES else get_base_model(
|
|
|
|
|
srv_view.get_model()).foreach(remove)
|
|
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
remove_picons(settings, picon_ids, picons)
|
2018-02-01 13:10:06 +03:00
|
|
|
|
|
|
|
|
|
2018-01-31 00:13:42 +03:00
|
|
|
def copy_picon_reference(target, view, services, clipboard, transient):
|
|
|
|
|
""" Copying picon id to clipboard """
|
|
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
2018-02-01 21:43:44 +03:00
|
|
|
if not is_only_one_item_selected(paths, transient):
|
2018-01-31 00:13:42 +03:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if target is ViewTarget.SERVICES:
|
2018-12-18 19:23:44 +03:00
|
|
|
picon_id = model.get_value(model.get_iter(paths), Column.SRV_PICON_ID)
|
2018-01-31 00:13:42 +03:00
|
|
|
if picon_id:
|
|
|
|
|
clipboard.set_text(picon_id.rstrip(".png"), -1)
|
|
|
|
|
else:
|
|
|
|
|
show_dialog(DialogType.ERROR, transient, "No reference is present!")
|
|
|
|
|
elif target is ViewTarget.FAV:
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_id = model.get_value(model.get_iter(paths), Column.FAV_ID)
|
2018-01-31 00:13:42 +03:00
|
|
|
srv = services.get(fav_id, None)
|
|
|
|
|
if srv and srv.picon_id:
|
|
|
|
|
clipboard.set_text(srv.picon_id.rstrip(".png"), -1)
|
|
|
|
|
else:
|
|
|
|
|
show_dialog(DialogType.ERROR, transient, "No reference is present!")
|
|
|
|
|
|
|
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
def remove_all_unused_picons(settings, picons, services):
|
2019-03-03 12:50:40 +03:00
|
|
|
ids = {s.picon_id for s in services}
|
|
|
|
|
pcs = list(filter(lambda x: x not in ids, picons))
|
2019-12-15 19:01:27 +03:00
|
|
|
remove_picons(settings, pcs, picons)
|
2019-03-03 12:50:40 +03:00
|
|
|
|
|
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
def remove_picons(settings, picon_ids, picons):
|
2019-12-22 20:42:29 +03:00
|
|
|
pions_path = settings.picons_local_path
|
|
|
|
|
backup_path = settings.backup_local_path + "picons/"
|
2019-03-03 12:50:40 +03:00
|
|
|
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
|
|
|
|
for p_id in picon_ids:
|
|
|
|
|
picons[p_id] = None
|
|
|
|
|
src = pions_path + p_id
|
|
|
|
|
if os.path.isfile(src):
|
|
|
|
|
shutil.move(src, backup_path + p_id)
|
|
|
|
|
|
|
|
|
|
|
2018-02-01 21:43:44 +03:00
|
|
|
def is_only_one_item_selected(paths, transient):
|
|
|
|
|
if len(paths) > 1:
|
|
|
|
|
show_dialog(DialogType.ERROR, transient, "Please, select only one item!")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if not paths:
|
|
|
|
|
show_dialog(DialogType.ERROR, transient, "No selected item!")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_picon_pixbuf(path):
|
|
|
|
|
return GdkPixbuf.Pixbuf.new_from_file_at_scale(filename=path, width=32, height=32, preserve_aspect_ratio=True)
|
|
|
|
|
|
|
|
|
|
|
2018-04-03 22:47:29 +03:00
|
|
|
# ***************** Bouquets *********************#
|
|
|
|
|
|
2019-12-22 20:42:29 +03:00
|
|
|
def gen_bouquets(view, bq_view, transient, gen_type, tv_types, s_type, callback):
|
2018-04-04 16:52:58 +03:00
|
|
|
""" Auto-generate and append list of bouquets """
|
2018-12-18 19:23:44 +03:00
|
|
|
fav_id_index = Column.SRV_FAV_ID
|
|
|
|
|
index = Column.SRV_TYPE
|
|
|
|
|
if gen_type in (BqGenType.PACKAGE, BqGenType.EACH_PACKAGE):
|
|
|
|
|
index = Column.SRV_PACKAGE
|
|
|
|
|
elif gen_type in (BqGenType.SAT, BqGenType.EACH_SAT):
|
|
|
|
|
index = Column.SRV_POS
|
|
|
|
|
|
2018-04-03 22:47:29 +03:00
|
|
|
model, paths = view.get_selection().get_selected_rows()
|
2019-12-22 20:42:29 +03:00
|
|
|
bq_type = BqType.BOUQUET.value if s_type is SettingsType.NEUTRINO_MP else BqType.TV.value
|
2018-04-07 23:49:36 +03:00
|
|
|
if gen_type in (BqGenType.SAT, BqGenType.PACKAGE, BqGenType.TYPE):
|
2018-04-04 16:52:58 +03:00
|
|
|
if not is_only_one_item_selected(paths, transient):
|
|
|
|
|
return
|
2018-12-18 19:23:44 +03:00
|
|
|
service = Service(*model[paths][:Column.SRV_TOOLTIP])
|
2018-04-04 16:52:58 +03:00
|
|
|
if service.service_type not in tv_types:
|
|
|
|
|
bq_type = BqType.RADIO.value
|
|
|
|
|
append_bouquets(bq_type, bq_view, callback, fav_id_index, index, model,
|
2018-04-07 23:49:36 +03:00
|
|
|
[service.package if gen_type is BqGenType.PACKAGE else
|
2019-12-22 20:42:29 +03:00
|
|
|
service.pos if gen_type is BqGenType.SAT else service.service_type], s_type)
|
2018-04-07 23:49:36 +03:00
|
|
|
else:
|
2018-04-10 13:04:21 +03:00
|
|
|
wait_dialog = WaitDialog(transient)
|
|
|
|
|
wait_dialog.show()
|
|
|
|
|
append_bouquets(bq_type, bq_view, callback, fav_id_index, index, model,
|
2019-12-22 20:42:29 +03:00
|
|
|
{row[index] for row in model}, s_type, wait_dialog)
|
2018-04-04 16:52:58 +03:00
|
|
|
|
|
|
|
|
|
2018-04-07 23:49:36 +03:00
|
|
|
@run_task
|
2019-12-22 20:42:29 +03:00
|
|
|
def append_bouquets(bq_type, bq_view, callback, fav_id_index, index, model, names, s_type, wait_dialog=None):
|
|
|
|
|
bq_index = 0 if s_type is SettingsType.ENIGMA_2 else 1
|
2018-04-10 13:32:43 +03:00
|
|
|
bq_view.expand_row(Gtk.TreePath(bq_index), 0)
|
2018-04-04 16:52:58 +03:00
|
|
|
bqs_model = bq_view.get_model()
|
|
|
|
|
bouquets_names = get_bouquets_names(bqs_model)
|
2018-04-10 13:04:21 +03:00
|
|
|
|
2018-04-04 16:52:58 +03:00
|
|
|
for pos, name in enumerate(sorted(names)):
|
2018-04-03 22:47:29 +03:00
|
|
|
if name not in bouquets_names:
|
|
|
|
|
services = [BouquetService(None, BqServiceType.DEFAULT, row[fav_id_index], 0)
|
|
|
|
|
for row in model if row[index] == name]
|
2018-04-04 16:52:58 +03:00
|
|
|
callback(Bouquet(name=name, type=bq_type, services=services, locked=None, hidden=None),
|
2018-04-10 13:32:43 +03:00
|
|
|
bqs_model.get_iter(bq_index))
|
2018-04-03 22:47:29 +03:00
|
|
|
|
2018-04-10 13:04:21 +03:00
|
|
|
if wait_dialog is not None:
|
|
|
|
|
wait_dialog.destroy()
|
|
|
|
|
|
2018-04-03 22:47:29 +03:00
|
|
|
|
|
|
|
|
def get_bouquets_names(model):
|
|
|
|
|
""" Returns all current bouquets names """
|
|
|
|
|
bouquets_names = []
|
|
|
|
|
for row in model:
|
|
|
|
|
itr = row.iter
|
|
|
|
|
if model.iter_has_child(itr):
|
|
|
|
|
num_of_children = model.iter_n_children(itr)
|
|
|
|
|
for num in range(num_of_children):
|
|
|
|
|
child_itr = model.iter_nth_child(itr, num)
|
|
|
|
|
bouquets_names.append(model[child_itr][0])
|
|
|
|
|
return bouquets_names
|
|
|
|
|
|
|
|
|
|
|
2018-01-11 17:59:59 +03:00
|
|
|
# ***************** Others *********************#
|
|
|
|
|
|
2019-12-15 19:01:27 +03:00
|
|
|
def update_entry_data(entry, dialog, settings):
|
2018-01-11 17:59:59 +03:00
|
|
|
""" Updates value in text entry from chooser dialog """
|
2019-12-15 19:01:27 +03:00
|
|
|
response = show_dialog(dialog_type=DialogType.CHOOSER, transient=dialog, settings=settings)
|
2018-01-11 17:59:59 +03:00
|
|
|
if response not in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
|
|
|
|
entry.set_text(response)
|
|
|
|
|
return response
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2018-01-25 21:05:24 +03:00
|
|
|
def get_base_model(model):
|
|
|
|
|
""" Returns base tree model if has wrappers ("TreeModelSort" and "TreeModelFilter") """
|
|
|
|
|
if type(model) is Gtk.TreeModelSort:
|
|
|
|
|
return model.get_model().get_model()
|
|
|
|
|
return model
|
|
|
|
|
|
|
|
|
|
|
2018-11-02 23:13:31 +03:00
|
|
|
def get_model_data(view):
|
|
|
|
|
""" Returns model name and base model from the given view """
|
|
|
|
|
model = get_base_model(view.get_model())
|
|
|
|
|
model_name = model.get_name()
|
|
|
|
|
return model_name, model
|
|
|
|
|
|
|
|
|
|
|
2018-05-01 21:05:18 +03:00
|
|
|
def append_text_to_tview(char, view):
|
|
|
|
|
""" Appending text and scrolling to a given line in the text view. """
|
|
|
|
|
buf = view.get_buffer()
|
|
|
|
|
buf.insert_at_cursor(char)
|
|
|
|
|
insert = buf.get_insert()
|
|
|
|
|
view.scroll_to_mark(insert, 0.0, True, 0.0, 1.0)
|
|
|
|
|
|
|
|
|
|
|
2019-12-22 20:42:29 +03:00
|
|
|
def get_iptv_url(row, s_type):
|
2018-07-03 19:30:45 +03:00
|
|
|
""" Returns url from iptv type row """
|
2019-12-22 20:42:29 +03:00
|
|
|
data = row[Column.FAV_ID].split(":" if s_type is SettingsType.ENIGMA_2 else "::")
|
|
|
|
|
if s_type is SettingsType.ENIGMA_2:
|
2018-08-19 10:55:41 +03:00
|
|
|
data = list(filter(lambda x: "http" in x, data))
|
|
|
|
|
if data:
|
|
|
|
|
url = data[0]
|
2019-12-22 20:42:29 +03:00
|
|
|
return urllib.request.unquote(url) if s_type is SettingsType.ENIGMA_2 else url
|
2018-07-03 19:30:45 +03:00
|
|
|
|
|
|
|
|
|
2018-10-21 11:10:45 +03:00
|
|
|
def on_popup_menu(menu, event):
|
|
|
|
|
""" Shows popup menu for the view """
|
|
|
|
|
if event.get_event_type() == Gdk.EventType.BUTTON_PRESS and event.button == Gdk.BUTTON_SECONDARY:
|
|
|
|
|
menu.popup(None, None, None, None, event.button, event.time)
|
|
|
|
|
|
|
|
|
|
|
2017-12-20 16:46:15 +03:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
pass
|