Files
DemonEditor/app/ui/main_helper.py

493 lines
17 KiB
Python
Raw Normal View History

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
from enum import Enum
2018-01-31 00:13:42 +03:00
from gi.repository import GdkPixbuf
2018-04-07 23:49:36 +03:00
from app.commons import run_idle, run_task
2018-01-01 23:42:40 +03:00
from app.eparser import Service
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
from app.properties import Profile
2017-12-24 16:43:05 +03:00
from . import Gtk, Gdk, HIDE_ICON, LOCKED_ICON
2018-01-31 00:13:42 +03:00
from .dialogs import show_dialog, DialogType, get_chooser_dialog
2017-12-20 16:46:15 +03:00
2017-12-24 01:40:30 +03:00
class ViewTarget(Enum):
""" Used for set target view """
BOUQUET = 0
FAV = 1
SERVICES = 2
2018-04-03 22:47:29 +03:00
class BqGenType(Enum):
""" Bouquet generation type """
SAT = 0
EACH_SAT = 1
PACKAGE = 2
EACH_PACKAGE = 3
2018-04-07 23:49:36 +03:00
TYPE = 4
EACH_TYPE = 5
2018-04-03 22:47:29 +03:00
2017-12-24 01:40:30 +03:00
# ***************** Markers *******************#
2017-12-23 22:25:29 +03:00
2017-12-20 16:46:15 +03:00
def insert_marker(view, bouquets, selected_bouquet, channels, parent_window):
"""" 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
2017-12-21 12:38:45 +03:00
# Searching for max num value in all marker services (if empty default = 0)
2018-01-28 23:10:54 +03:00
max_num = max(map(lambda num: int(num.data_id, 18),
2017-12-21 12:38:45 +03:00
filter(lambda ch: ch.service_type == BqServiceType.MARKER.name, channels.values())), default=0)
max_num = '{:x}'.format(max_num + 1)
fav_id = "1:64:{}:0:0:0:0:0:0:0::{}\n#DESCRIPTION {}\n".format(max_num, response, response)
2017-12-20 16:46:15 +03:00
s_type = BqServiceType.MARKER.name
model, paths = view.get_selection().get_selected_rows()
2018-02-06 13:56:17 +03:00
marker = (None, None, response, None, None, s_type, None, fav_id, None)
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)
2018-02-06 13:56:17 +03:00
channels[fav_id] = Service(None, None, None, response, None, None, None, s_type, *[None] * 9, max_num, fav_id, None)
2017-12-20 16:46:15 +03:00
2017-12-23 22:25:29 +03:00
def edit_marker(view, bouquets, selected_bouquet, channels, parent_window):
2017-12-20 16:46:15 +03:00
""" Edits marker text """
model, paths = view.get_selection().get_selected_rows()
itr = model.get_iter(paths[0])
name, fav_id = model.get(itr, 2, 7)
response = show_dialog(DialogType.INPUT, parent_window, text=name)
if response == Gtk.ResponseType.CANCEL:
return
bq_services = bouquets[selected_bouquet]
index = bq_services.index(fav_id)
old_ch = channels.pop(fav_id, None)
new_fav_id = "{}::{}\n#DESCRIPTION {}\n".format(fav_id.split("::")[0], response, response)
model.set(itr, {2: response, 7: new_fav_id})
2018-03-15 23:10:22 +03:00
channels[new_fav_id] = old_ch._replace(service=response, fav_id=new_fav_id)
2017-12-20 16:46:15 +03:00
bq_services.pop(index)
bq_services.insert(index, new_fav_id)
2017-12-24 01:40:30 +03:00
# ***************** Movement *******************#
2017-12-23 22:25:29 +03:00
def move_items(key, view):
""" Move items in tree view """
selection = view.get_selection()
model, paths = selection.get_selected_rows()
if paths:
# for correct down move!
if key in (Gdk.KEY_Down, Gdk.KEY_Page_Down, Gdk.KEY_KP_Page_Down):
paths = reversed(paths)
for path in paths:
itr = model.get_iter(path)
if key == Gdk.KEY_Down:
next_itr = model.iter_next(itr)
if next_itr:
model.move_after(itr, next_itr)
elif key == Gdk.KEY_Up:
prev_itr = model.iter_previous(itr)
if prev_itr:
model.move_before(itr, prev_itr)
elif key == Gdk.KEY_Page_Up or key == Gdk.KEY_KP_Page_Up:
up_itr = model.get_iter(view.get_cursor()[0])
if up_itr:
model.move_before(itr, up_itr)
elif key == Gdk.KEY_Page_Down or key == Gdk.KEY_KP_Page_Down:
down_itr = model.get_iter(view.get_cursor()[0])
if down_itr:
model.move_after(itr, down_itr)
# ***************** Rename *******************#
2017-12-24 01:40:30 +03:00
def rename(view, parent_window, target, fav_view=None, service_view=None, channels=None):
2017-12-24 01:40:30 +03:00
model, paths = view.get_selection().get_selected_rows()
2018-01-25 21:05:24 +03:00
model = get_base_model(model)
2017-12-24 01:40:30 +03:00
if not paths:
return
elif len(paths) > 1:
show_dialog(DialogType.ERROR, parent_window, "Please, select only one item!")
return
itr = model.get_iter(paths)
f_id = None
channel_name = None
if target is ViewTarget.SERVICES:
2018-01-28 23:10:54 +03:00
name, fav_id = model.get(itr, 3, 18)
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
channel_name = response
model.set_value(itr, 3, response)
if fav_view is not None:
for row in fav_view.get_model():
if row[7] == fav_id:
row[2] = response
break
elif target is ViewTarget.FAV:
name, fav_id = model.get(itr, 2, 7)
f_id = fav_id
response = show_dialog(DialogType.INPUT, parent_window, name)
if response == Gtk.ResponseType.CANCEL:
return
channel_name = response
model.set_value(itr, 2, response)
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-01-28 23:10:54 +03:00
if row[18] == fav_id:
2017-12-24 01:40:30 +03:00
row[3] = response
break
old_ch = channels.get(f_id, None)
if old_ch:
2018-03-15 23:10:22 +03:00
channels[f_id] = old_ch._replace(service=channel_name)
2017-12-24 01:40:30 +03:00
2017-12-24 16:43:05 +03:00
# ***************** Flags *******************#
def set_flags(flag, services_view, fav_view, channels, blacklist):
""" 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:
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)
if flag is Flag.HIDE:
2017-12-29 19:49:01 +03:00
if target is ViewTarget.SERVICES:
set_hide(channels, model, paths)
else:
fav_ids = [model.get_value(model.get_iter(path), 7) for path in paths]
2018-01-25 21:05:24 +03:00
srv_model = get_base_model(services_view.get_model())
2018-01-28 23:10:54 +03:00
srv_paths = [row.path for row in srv_model if row[18] in fav_ids]
2017-12-29 19:49:01 +03:00
set_hide(channels, srv_model, srv_paths)
elif flag is Flag.LOCK:
2018-01-25 21:05:24 +03:00
set_lock(blacklist, channels, model, paths, target, services_model=get_base_model(services_view.get_model()))
2017-12-24 16:43:05 +03:00
return True
def set_lock(blacklist, channels, model, paths, target, services_model):
col_num = 4 if target is ViewTarget.SERVICES else 3
2017-12-24 16:43:05 +03:00
locked = has_locked_hide(model, paths, col_num)
ids = []
2017-12-24 16:43:05 +03:00
for path in paths:
itr = model.get_iter(path)
2018-01-28 23:10:54 +03:00
fav_id = model.get_value(itr, 18 if target is ViewTarget.SERVICES else 7)
2017-12-24 16:43:05 +03:00
channel = channels.get(fav_id, None)
if channel:
bq_id = to_bouquet_id(channel)
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)
model.set_value(itr, col_num, None if locked else LOCKED_ICON)
2018-03-15 23:10:22 +03:00
channels[fav_id] = channel._replace(locked=None if locked else LOCKED_ICON)
ids.append(fav_id)
if target is ViewTarget.FAV and ids:
for ch in services_model:
2018-01-28 23:10:54 +03:00
if ch[18] in ids:
ch[4] = None if locked else LOCKED_ICON
2017-12-24 16:43:05 +03:00
2017-12-29 19:49:01 +03:00
def set_hide(channels, model, paths):
2017-12-24 16:43:05 +03:00
col_num = 5
hide = has_locked_hide(model, paths, col_num)
for path in paths:
itr = model.get_iter(path)
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:
if Flag.is_hide(value):
2017-12-24 16:43:05 +03:00
continue # skip if already hidden
value += Flag.HIDE.value
2017-12-24 16:43:05 +03:00
else:
if not Flag.is_hide(value):
2017-12-24 16:43:05 +03:00
continue # skip if already allowed to show
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:
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-01-28 23:10:54 +03:00
fav_id = model.get_value(itr, 18)
2017-12-24 16:43:05 +03:00
channel = channels.get(fav_id, None)
if channel:
2018-03-15 23:10:22 +03:00
channels[fav_id] = channel._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
# ***************** 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
fav_id = model.get_value(model.get_iter(paths[0]), 7)
for index, row in enumerate(services_view.get_model()):
2018-01-28 23:10:54 +03:00
if row[18] == fav_id:
scroll_to(index, services_view)
break
2017-12-25 19:50:35 +03:00
def scroll_to(index, view, paths=None):
""" 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)
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 *********************#
def update_picons(path, picons, model):
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
for r in model:
model.set_value(model.get_iter(r.path), 8, picons.get(r[9], None))
2018-02-01 21:43:44 +03:00
def assign_picon(target, srv_view, fav_view, transient, picons, options, services):
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
2018-01-31 00:13:42 +03:00
response = get_chooser_dialog(transient, options, "*.png", "png files")
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-02-01 21:43:44 +03:00
picon_pos = 8
model = get_base_model(model)
itr = model.get_iter(paths)
fav_id = model.get_value(itr, 18 if target is ViewTarget.SERVICES else 7)
picon_id = services.get(fav_id)[9]
if picon_id:
picon_file = options.get("picons_dir_path") + picon_id
if os.path.isfile(response):
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:
set_picon(fav_id, fav_view.get_model(), picon, 7, picon_pos)
else:
set_picon(fav_id, get_base_model(srv_view.get_model()), picon, 18, picon_pos)
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
2018-02-01 13:10:06 +03:00
def remove_picon(target, srv_view, fav_view, picons, options):
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 = []
picon_pos = 8 # 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:
fav_ids.append(model.get_value(itr, 18))
picon_ids.append(model.get_value(itr, 9))
else:
fav_ids.append(model.get_value(itr, 7))
def remove(md, path, itr):
if md.get_value(itr, 7 if target is ViewTarget.SERVICES else 18) in fav_ids:
md.set_value(itr, picon_pos, None)
if target is ViewTarget.FAV:
picon_ids.append(md.get_value(itr, 9))
fav_view.get_model().foreach(remove) if target is ViewTarget.SERVICES else get_base_model(
srv_view.get_model()).foreach(remove)
2018-02-01 14:02:59 +03:00
pions_path = options.get("picons_dir_path")
backup_path = options.get("data_dir_path") + "backup/picons/"
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
2018-02-01 13:10:06 +03:00
for p_id in picon_ids:
picons[p_id] = None
2018-02-01 14:02:59 +03:00
src = pions_path + p_id
if os.path.isfile(src):
shutil.move(src, backup_path + p_id)
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:
picon_id = model.get_value(model.get_iter(paths), 9)
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:
fav_id = model.get_value(model.get_iter(paths), 7)
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!")
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 *********************#
def gen_bouquets(view, bq_view, transient, gen_type, tv_types, profile, callback):
""" Auto-generate and append list of bouquets """
fav_id_index = 18
2018-04-07 23:49:36 +03:00
index = 6 if gen_type in (BqGenType.PACKAGE, BqGenType.EACH_PACKAGE) else 16 if gen_type in (
BqGenType.SAT, BqGenType.EACH_SAT) else 7
2018-04-03 22:47:29 +03:00
model, paths = view.get_selection().get_selected_rows()
model = get_base_model(model)
bq_type = BqType.BOUQUET.value if profile is Profile.NEUTRINO_MP else BqType.TV.value
2018-04-07 23:49:36 +03:00
if gen_type in (BqGenType.SAT, BqGenType.PACKAGE, BqGenType.TYPE):
if not is_only_one_item_selected(paths, transient):
return
2018-04-03 22:47:29 +03:00
service = Service(*model[paths][:])
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
service.pos if gen_type is BqGenType.SAT else service.service_type])
else:
append_bouquets(bq_type, bq_view, callback, fav_id_index, index, model, {row[index] for row in model})
2018-04-07 23:49:36 +03:00
@run_task
def append_bouquets(bq_type, bq_view, callback, fav_id_index, index, model, names):
bq_view.expand_row(Gtk.TreePath(0), 0)
bqs_model = bq_view.get_model()
bouquets_names = get_bouquets_names(bqs_model)
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]
callback(Bouquet(name=name, type=bq_type, services=services, locked=None, hidden=None),
bqs_model.get_iter(0))
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 *********************#
def update_entry_data(entry, dialog, options):
""" Updates value in text entry from chooser dialog """
response = show_dialog(dialog_type=DialogType.CHOOSER, transient=dialog, options=options)
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
2017-12-20 16:46:15 +03:00
if __name__ == "__main__":
pass