mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2026-07-06 07:19:36 +02:00
write bouquets impl
This commit is contained in:
17
main/commons.py
Normal file
17
main/commons.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from functools import wraps
|
||||
from threading import Thread
|
||||
|
||||
|
||||
def run_task(func):
|
||||
""" Runs function in separate thread """
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
task = Thread(target=func(*args, **kwargs))
|
||||
task.start()
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
@@ -1,11 +1,6 @@
|
||||
""" This module only for common constants """
|
||||
from collections import namedtuple
|
||||
from enum import Enum
|
||||
|
||||
Channel = namedtuple("Channel", ["service", "package", "service_type",
|
||||
"ssid", "freq", "rate", "pol", "fec",
|
||||
"system", "pos", "data_id", "fav_id"])
|
||||
|
||||
|
||||
class Type(Enum):
|
||||
""" Types of DVB transponders """
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from .lamedb import get_channels, write_channels
|
||||
from .bouquets import get_bouquets, get_bouquet, write_bouquet
|
||||
from .bouquets import get_bouquets, write_bouquets, Bouquet, Bouquets
|
||||
from .satxml import get_satellites, write_satellites, Satellite, Transponder
|
||||
|
||||
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
""" Module for parsing bouquets """
|
||||
from collections import namedtuple
|
||||
|
||||
__BOUQUETS_PATH = "../data/"
|
||||
_BOUQUETS_PATH = "../data/"
|
||||
_TV_ROOT_FILE_NAME = "bouquets.tv"
|
||||
_RADIO_ROOT_FILE_NAME = "bouquets.radio"
|
||||
|
||||
Bouquet = namedtuple("Bouquet", ["name", "type", "services"])
|
||||
Bouquets = namedtuple("Bouquets", ["name", "bouquets"])
|
||||
Bouquets = namedtuple("Bouquets", ["name", "type", "bouquets"])
|
||||
|
||||
|
||||
def get_bouquets(path):
|
||||
return parse_bouquets(path, "bouquets.tv", "tv"), parse_bouquets(path, "bouquets.radio", "radio")
|
||||
|
||||
|
||||
def write_bouquets(path, bouquets, bouquets_services):
|
||||
srv_line = '#SERVICE 1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "userbouquet.{}.{}" ORDER BY bouquet\n'
|
||||
line = []
|
||||
|
||||
for bqs in bouquets:
|
||||
line.clear()
|
||||
line.append("#NAME {}\n".format(bqs.name))
|
||||
|
||||
for bq in bqs.bouquets:
|
||||
line.append(srv_line.format(bq.name, bq.type))
|
||||
write_bouquet(path, bq.name, bq.services)
|
||||
|
||||
with open(path + "bouquets.{}".format(bqs.type), "w") as file:
|
||||
file.writelines(line)
|
||||
|
||||
|
||||
def write_bouquet(path, name, channels):
|
||||
bouquet = ["#NAME {}\n".format(name)]
|
||||
|
||||
for ch in channels:
|
||||
data_type = int(ch.data_id.split(":")[-2])
|
||||
if data_type == 22:
|
||||
@@ -20,6 +39,7 @@ def write_bouquet(path, name, channels):
|
||||
elif data_type == 25:
|
||||
data_type = 19
|
||||
bouquet.append("#SERVICE {}:0:{}:{}:0:0:0:\n".format(1, data_type, ch.fav_id))
|
||||
|
||||
with open(path + "_userbouquet.{}.tv".format(name), "w") as file:
|
||||
file.writelines(bouquet)
|
||||
|
||||
@@ -32,6 +52,7 @@ def get_bouquet(path, name, bq_type):
|
||||
for ch in chs_list.split("#SERVICE")[1:]:
|
||||
ch_data = ch.strip().split(":")
|
||||
ids.append("{}:{}:{}:{}".format(ch_data[3], ch_data[4], ch_data[5], ch_data[6]))
|
||||
|
||||
return ids
|
||||
|
||||
|
||||
@@ -40,13 +61,15 @@ def parse_bouquets(path, bq_name, bq_type):
|
||||
lines = file.readlines()
|
||||
bouquets = None
|
||||
nm_sep = "#NAME"
|
||||
|
||||
for line in lines:
|
||||
if nm_sep in line:
|
||||
_, _, name = line.partition(nm_sep)
|
||||
bouquets = Bouquets(name.strip(), [])
|
||||
bouquets = Bouquets(name.strip(), bq_type, [])
|
||||
if bouquets and "#SERVICE" in line:
|
||||
name = line.split(".")[1]
|
||||
bouquets[1].append(Bouquet(name=name, type=bq_type, services=get_bouquet(path, name, bq_type)))
|
||||
bouquets[2].append(Bouquet(name=name, type=bq_type, services=get_bouquet(path, name, bq_type)))
|
||||
|
||||
return bouquets
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,18 @@
|
||||
Currently implemented only for satellite channels!!!
|
||||
Description of format taken from here: http://www.satsupreme.com/showthread.php/194074-Lamedb-format-explained
|
||||
"""
|
||||
from main.eparser.__constants import POLARIZATION, SYSTEM, FEC, Channel, SERVICE_TYPE
|
||||
from collections import namedtuple
|
||||
|
||||
from main.eparser.__constants import POLARIZATION, SYSTEM, FEC, SERVICE_TYPE
|
||||
|
||||
_HEADER = "eDVB services /4/"
|
||||
_FILE_PATH = "../data/lamedb"
|
||||
_SEP = ":" # separator
|
||||
|
||||
Channel = namedtuple("Channel", ["service", "package", "service_type",
|
||||
"ssid", "freq", "rate", "pol", "fec",
|
||||
"system", "pos", "data_id", "fav_id"])
|
||||
|
||||
|
||||
def get_channels(path):
|
||||
return parse(path)
|
||||
@@ -25,6 +31,7 @@ def parse(path):
|
||||
transponders, sep, services = data.partition("transponders") # 1 step
|
||||
transponders, sep, services = services.partition("services") # 2 step
|
||||
services, sep, _ = services.partition("end") # 3 step
|
||||
|
||||
return parse_channels(services.split("\n"), transponders.split("/"))
|
||||
|
||||
|
||||
@@ -35,18 +42,19 @@ def parse_transponders(arg):
|
||||
tr = ar.replace("\n", "").split("\t")
|
||||
if len(tr) == 2:
|
||||
transponders[tr[0]] = tr[1]
|
||||
|
||||
return transponders
|
||||
|
||||
|
||||
def parse_channels(*args):
|
||||
""" Parsing channels """
|
||||
channels = []
|
||||
transponders = parse_transponders(args[1])
|
||||
|
||||
srv = split(args[0], 3)
|
||||
if srv[0][0] == "": # remove first empty element
|
||||
srv.remove(srv[0])
|
||||
|
||||
channels = []
|
||||
for ch in srv:
|
||||
data = str(ch[0]).split(_SEP)
|
||||
sp = "0"
|
||||
@@ -73,6 +81,7 @@ def split(itr, size):
|
||||
if i % size == 0:
|
||||
srv.append(tuple(tmp))
|
||||
tmp.clear()
|
||||
|
||||
return srv
|
||||
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ from collections import namedtuple
|
||||
from xml.dom.minidom import parse, Document
|
||||
from main.eparser.__constants import POLARIZATION, FEC, SYSTEM, MODULATION, PLS_MODE
|
||||
|
||||
# temporary
|
||||
__XML_PATH = "../data/"
|
||||
__FILE_NAME = "satellites.xml"
|
||||
|
||||
Satellite = namedtuple("Satellite", ["name", "flags", "position", "transponders"])
|
||||
|
||||
@@ -59,12 +58,14 @@ def write_satellites(satellites, data_path):
|
||||
doc.appendChild(comment)
|
||||
root = doc.createElement("satellites")
|
||||
doc.appendChild(root)
|
||||
|
||||
for sat in satellites:
|
||||
# Create Element
|
||||
sat_child = doc.createElement("sat")
|
||||
sat_child.setAttribute("name", sat.name)
|
||||
sat_child.setAttribute("flags", sat.flags)
|
||||
sat_child.setAttribute("position", sat.position)
|
||||
|
||||
for tr in sat.transponders:
|
||||
transponder_child = doc.createElement("transponder")
|
||||
transponder_child.setAttribute("frequency", tr.frequency)
|
||||
@@ -81,7 +82,7 @@ def write_satellites(satellites, data_path):
|
||||
transponder_child.setAttribute("is_id", tr.is_id)
|
||||
sat_child.appendChild(transponder_child)
|
||||
root.appendChild(sat_child)
|
||||
doc.writexml(open(data_path + "new_satellites.xml", "w"),
|
||||
doc.writexml(open(data_path + __FILE_NAME, "w"),
|
||||
# indent="",
|
||||
addindent=" ",
|
||||
newl='\n',
|
||||
@@ -120,9 +121,11 @@ def parse_satellites(path):
|
||||
""" Parsing satellites from xml"""
|
||||
dom = parse(path)
|
||||
satellites = []
|
||||
|
||||
for elem in dom.getElementsByTagName("sat"):
|
||||
if elem.hasAttributes():
|
||||
satellites.append(parse_sat(elem))
|
||||
|
||||
return satellites
|
||||
|
||||
|
||||
@@ -133,9 +136,4 @@ def get_key_by_value(dictionary, value):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sats = get_satellites(__XML_PATH)
|
||||
for sat in sats:
|
||||
trnsp = sat.transponders
|
||||
for tr in trnsp:
|
||||
if tr.pls_mode or tr.pls_code or tr.is_id:
|
||||
print(tr, sat.name)
|
||||
pass
|
||||
|
||||
@@ -13,6 +13,7 @@ def download_data(*, properties):
|
||||
ftp.cwd(properties["services_path"])
|
||||
files = []
|
||||
ftp.dir(files.append)
|
||||
|
||||
for file in files:
|
||||
name = str(file).strip()
|
||||
if name.endswith(__DATA_FILES_LIST):
|
||||
@@ -23,19 +24,23 @@ def download_data(*, properties):
|
||||
ftp.cwd(properties["satellites_xml_path"])
|
||||
files.clear()
|
||||
ftp.dir(files.append)
|
||||
|
||||
for file in files:
|
||||
name = str(file).strip()
|
||||
xml_file = "satellites.xml"
|
||||
if name.endswith(xml_file):
|
||||
with open(save_path + xml_file, 'wb') as f:
|
||||
ftp.retrbinary('RETR ' + xml_file, f.write)
|
||||
|
||||
for name in os.listdir(save_path):
|
||||
print(name)
|
||||
|
||||
return ftp.voidcmd("NOOP")
|
||||
|
||||
|
||||
def upload_data(*, properties):
|
||||
load_path = properties["data_dir_path"]
|
||||
|
||||
for file_name in os.listdir(load_path):
|
||||
print(file_name)
|
||||
# Open the file for transfer in binary mode
|
||||
|
||||
@@ -11,6 +11,7 @@ DATA_PATH = "data/"
|
||||
def get_config():
|
||||
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True) # create dir if not exist
|
||||
os.makedirs(os.path.dirname(DATA_PATH), exist_ok=True)
|
||||
|
||||
if not os.path.isfile(CONFIG_FILE) or os.stat(CONFIG_FILE).st_size == 0:
|
||||
with open(CONFIG_FILE, "w") as default_config_file:
|
||||
json.dump(get_default_settings(), default_config_file)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from contextlib import suppress
|
||||
from threading import Thread
|
||||
|
||||
from main.eparser import get_channels, get_bouquets, write_bouquet, write_channels
|
||||
from main.commons import run_task
|
||||
from main.eparser import get_channels, get_bouquets, write_bouquets, write_channels, Bouquets, Bouquet
|
||||
from main.ftp import download_data, upload_data
|
||||
from main.properties import get_config, write_config
|
||||
from . import Gtk, Gdk
|
||||
@@ -98,17 +98,24 @@ def on_paste(view):
|
||||
selection = view.get_selection()
|
||||
dest_index = 0
|
||||
bq_selected = is_bouquet_selected()
|
||||
if bq_selected:
|
||||
fav_bouquet = __bouquets[bq_selected]
|
||||
|
||||
if not bq_selected:
|
||||
return
|
||||
|
||||
fav_bouquet = __bouquets[bq_selected]
|
||||
model, paths = selection.get_selected_rows()
|
||||
|
||||
if paths:
|
||||
dest_index = int(paths[0][0])
|
||||
|
||||
for row in __rows_buffer:
|
||||
dest_index += 1
|
||||
model.insert(dest_index, row)
|
||||
fav_bouquet.insert(dest_index, row[-1])
|
||||
|
||||
if model.get_name() == FAV_LIST_NAME:
|
||||
update_fav_num_column(model)
|
||||
|
||||
__rows_buffer.clear()
|
||||
|
||||
|
||||
@@ -126,11 +133,14 @@ def on_delete(item):
|
||||
rows = [model.get(in_itr, *[x for x in range(view.get_n_columns())]) for in_itr in itrs]
|
||||
bq_selected = is_bouquet_selected()
|
||||
fav_bouquet = None
|
||||
|
||||
if bq_selected:
|
||||
fav_bouquet = __bouquets[bq_selected]
|
||||
|
||||
for itr in itrs:
|
||||
if fav_bouquet and model_name == FAV_LIST_NAME:
|
||||
del fav_bouquet[int(model.get_path(itr)[0])]
|
||||
|
||||
if model_name == BOUQUETS_LIST_NAME:
|
||||
if model.iter_has_child(itr):
|
||||
show_message_dialog("This item is not allowed to be removed!")
|
||||
@@ -138,9 +148,10 @@ def on_delete(item):
|
||||
else:
|
||||
__bouquets.pop(bq_selected)
|
||||
model.remove(itr)
|
||||
|
||||
if model_name == FAV_LIST_NAME:
|
||||
update_fav_num_column(model)
|
||||
if model_name == SERVICE_LIST_NAME:
|
||||
elif model_name == SERVICE_LIST_NAME:
|
||||
for row in rows:
|
||||
# There are channels with the same parameters except for the name.
|
||||
# None because it can have duplicates! Need fix
|
||||
@@ -153,12 +164,14 @@ def on_delete(item):
|
||||
__fav_model.clear()
|
||||
if bq_selected:
|
||||
update_bouquet_channels(__fav_model, None, bq_selected)
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
def on_to_fav_move(view):
|
||||
""" Move items from main to fav list """
|
||||
selection = get_selection(view)
|
||||
|
||||
if selection:
|
||||
receive_selection(view=__fav_view, drop_info=None, data=selection)
|
||||
|
||||
@@ -167,6 +180,7 @@ def get_selection(view):
|
||||
""" Creates a string from the iterators of the selected rows """
|
||||
selection = view.get_selection()
|
||||
model, paths = selection.get_selected_rows()
|
||||
|
||||
if len(paths) > 0:
|
||||
itrs = [model.get_iter(path) for path in paths]
|
||||
return "{}:{}".format(",".join([model.get_string_from_iter(itr) for itr in itrs]), model.get_name())
|
||||
@@ -175,20 +189,26 @@ def get_selection(view):
|
||||
def receive_selection(*, view, drop_info, data):
|
||||
""" Update fav view after data received """
|
||||
bq_selected = is_bouquet_selected()
|
||||
|
||||
if not bq_selected:
|
||||
show_message_dialog("Error. No bouquet is selected!")
|
||||
return
|
||||
|
||||
model = view.get_model()
|
||||
dest_index = 0
|
||||
|
||||
if drop_info:
|
||||
path, position = drop_info
|
||||
dest_iter = model.get_iter(path)
|
||||
if dest_iter:
|
||||
dest_index = model.get_value(dest_iter, 0)
|
||||
|
||||
itr_str, sep, source = data.partition(":")
|
||||
itrs = itr_str.split(",")
|
||||
|
||||
try:
|
||||
fav_bouquet = __bouquets[bq_selected]
|
||||
|
||||
if source == SERVICE_LIST_NAME:
|
||||
ext_model = __services_view.get_model()
|
||||
ext_itrs = [ext_model.get_iter_from_string(itr) for itr in itrs]
|
||||
@@ -246,21 +266,24 @@ def on_satellite_editor_show(model):
|
||||
show_satellites_dialog(__main_window, __options["data_dir_path"])
|
||||
|
||||
|
||||
def data_open(model):
|
||||
@run_task
|
||||
def on_data_open(model):
|
||||
try:
|
||||
model.clear()
|
||||
__fav_model.clear()
|
||||
model_name = model.get_name()
|
||||
data_path = get_config()["data_dir_path"]
|
||||
|
||||
if model_name == SERVICE_LIST_NAME:
|
||||
for ch in get_channels(data_path + "lamedb"):
|
||||
# adding channels to dict with fav_id as keys
|
||||
__channels[ch.fav_id] = ch
|
||||
model.append(ch)
|
||||
|
||||
if model_name == BOUQUETS_LIST_NAME:
|
||||
bouquets = get_bouquets(data_path)
|
||||
for bouquet in bouquets:
|
||||
parent = model.append(None, [bouquet.name, None])
|
||||
parent = model.append(None, [bouquet.name, bouquet.type])
|
||||
for bt in bouquet.bouquets:
|
||||
name, bt_type = bt.name, bt.type
|
||||
model.append(parent, [name, bt_type])
|
||||
@@ -269,23 +292,36 @@ def data_open(model):
|
||||
__status_bar.push(1, getattr(e, "message", repr(e)))
|
||||
|
||||
|
||||
def on_data_open(model):
|
||||
# Maybe is not necessary? Need testing.
|
||||
task = Thread(target=data_open(model))
|
||||
task.start()
|
||||
|
||||
|
||||
@run_task
|
||||
def on_data_save(*args):
|
||||
# Perhaps needs a dialog to choose what we need to save!!!
|
||||
bouquet_selected = is_bouquet_selected()
|
||||
path = __options["data_dir_path"]
|
||||
if bouquet_selected and __fav_view.is_focus(): # bouquets
|
||||
fav_ids = []
|
||||
__fav_model.foreach(lambda model, p, itr: fav_ids.append(model.get(model.get_iter(p), 4)))
|
||||
channels = [__channels[fav_id[0]] for fav_id in fav_ids]
|
||||
write_bouquet(path, bouquet_selected, channels)
|
||||
elif __services_view.is_focus():
|
||||
write_channels(path, __channels.values())
|
||||
bouquets = []
|
||||
services = []
|
||||
services_model = __services_view.get_model()
|
||||
s_n_columns = services_model.get_n_columns()
|
||||
|
||||
def parse_bouquets(model, b_path, itr):
|
||||
if model.iter_has_child(itr):
|
||||
num_of_children = model.iter_n_children(itr)
|
||||
bqs = []
|
||||
|
||||
for num in range(num_of_children):
|
||||
bq_itr = model.iter_nth_child(itr, num)
|
||||
bq_name, bq_type = model.get(bq_itr, 0, 1)
|
||||
favs = __bouquets["{}:{}".format(bq_name, bq_type)]
|
||||
bq = Bouquet(bq_name, bq_type, [__channels[f_id] for f_id in favs])
|
||||
bqs.append(bq)
|
||||
bqs = Bouquets(*model.get(itr, 0, 1), bqs)
|
||||
bouquets.append(bqs)
|
||||
|
||||
# Getting bouquets
|
||||
__bouquets_view.get_model().foreach(parse_bouquets)
|
||||
write_bouquets(path + "tmp/", bouquets, __bouquets)
|
||||
# Getting services
|
||||
services_model.foreach(lambda model, s_path, itr:
|
||||
services.append(model.get(itr, *[item for item in range(s_n_columns)])))
|
||||
write_channels(path + "tmp/", services)
|
||||
|
||||
|
||||
def on_services_selection(model, path, column):
|
||||
@@ -298,6 +334,7 @@ def on_fav_selection(model, path, column):
|
||||
|
||||
def on_bouquets_selection(model, path, column):
|
||||
__fav_model.clear()
|
||||
|
||||
if len(path) > 1:
|
||||
delete_selection(__services_view)
|
||||
update_bouquet_channels(model, path)
|
||||
@@ -308,8 +345,10 @@ def update_bouquet_channels(model, path, bq_key=None):
|
||||
tree_iter = None
|
||||
if path:
|
||||
tree_iter = model.get_iter(path)
|
||||
|
||||
key = bq_key if bq_key else "{}:{}".format(*model.get(tree_iter, 0, 1))
|
||||
services = __bouquets[key]
|
||||
|
||||
for num, ch_id in enumerate(services):
|
||||
channel = __channels.get(ch_id, None)
|
||||
if channel:
|
||||
@@ -323,8 +362,10 @@ def is_bouquet_selected():
|
||||
"""
|
||||
selection = __bouquets_view.get_selection()
|
||||
model, path = selection.get_selected_rows()
|
||||
|
||||
if len(path) < 1 or model.iter_has_child(model.get_iter(path)):
|
||||
return False
|
||||
|
||||
return "{}:{}".format(*model.get(model.get_iter(path), 0, 1))
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from main.commons import run_task
|
||||
from main.eparser import get_satellites, write_satellites, Satellite, Transponder
|
||||
from . import Gtk, Gdk
|
||||
|
||||
@@ -19,11 +20,13 @@ def show_satellites_dialog(transient, data_path):
|
||||
dialog.destroy()
|
||||
|
||||
|
||||
@run_task
|
||||
def on_satellites_list_load(model):
|
||||
""" Load satellites data into model """
|
||||
satellites = get_satellites(__data_path)
|
||||
model.clear()
|
||||
aggr = [None for x in range(9)]
|
||||
|
||||
for name, flags, pos, transponders in satellites:
|
||||
parent = model.append(None, [name, *aggr, flags, pos])
|
||||
for transponder in transponders:
|
||||
@@ -38,22 +41,26 @@ def on_remove(view):
|
||||
model.remove(itr)
|
||||
|
||||
|
||||
@run_task
|
||||
def on_save(view):
|
||||
model = view.get_model()
|
||||
satellites = []
|
||||
model.foreach(parse_data, satellites)
|
||||
write_satellites(satellites, __data_path)
|
||||
write_satellites(satellites, __data_path + "tmp/")
|
||||
|
||||
|
||||
def parse_data(model, path, itr, sats):
|
||||
if model.iter_has_child(itr):
|
||||
num_of_children = model.iter_n_children(itr)
|
||||
transponders = []
|
||||
num_columns = model.get_n_columns()
|
||||
|
||||
for num in range(num_of_children):
|
||||
transponder_itr = model.iter_nth_child(itr, num)
|
||||
transponder = model.get(transponder_itr, *[item for item in range(model.get_n_columns())])
|
||||
transponder = model.get(transponder_itr, *[item for item in range(num_columns)])
|
||||
transponders.append(Transponder(*transponder[1:-2]))
|
||||
sat = model.get(itr, *[item for item in range(model.get_n_columns())])
|
||||
|
||||
sat = model.get(itr, *[item for item in range(num_columns)])
|
||||
satellite = Satellite(sat[0], sat[-2], sat[-1], transponders)
|
||||
sats.append(satellite)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user