mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2026-01-24 16:30:14 +01:00
Merge branch 'development' into experimental-mac
# Conflicts: # app/properties.py # app/tools/media.py # app/ui/dialogs.py # app/ui/main_app_window.py # app/ui/transmitter.py # deb/usr/share/locale/es/LC_MESSAGES/demon-editor.mo
This commit is contained in:
@@ -11,7 +11,7 @@ from urllib.parse import urlencode
|
||||
from urllib.request import urlopen, HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener, install_opener
|
||||
|
||||
from app.commons import log
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
|
||||
_BQ_FILES_LIST = ("tv", "radio", # enigma 2
|
||||
"myservices.xml", "bouquets.xml", "ubouquets.xml") # neutrino
|
||||
@@ -44,16 +44,16 @@ class TestException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def download_data(*, properties, download_type=DownloadType.ALL, callback=print):
|
||||
with FTP(host=properties["host"], user=properties["user"], passwd=properties["password"]) as ftp:
|
||||
def download_data(*, settings, download_type=DownloadType.ALL, callback=print):
|
||||
with FTP(host=settings.host, user=settings.user, passwd=settings.password) as ftp:
|
||||
ftp.encoding = "utf-8"
|
||||
callback("FTP OK.\n")
|
||||
save_path = properties["data_dir_path"]
|
||||
save_path = settings.data_dir_path
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
files = []
|
||||
# bouquets
|
||||
if download_type is DownloadType.ALL or download_type is DownloadType.BOUQUETS:
|
||||
ftp.cwd(properties["services_path"])
|
||||
ftp.cwd(settings.services_path)
|
||||
ftp.dir(files.append)
|
||||
file_list = _BQ_FILES_LIST + _DATA_FILES_LIST if download_type is DownloadType.ALL else _BQ_FILES_LIST
|
||||
for file in files:
|
||||
@@ -63,7 +63,7 @@ def download_data(*, properties, download_type=DownloadType.ALL, callback=print)
|
||||
download_file(ftp, name, save_path, callback)
|
||||
# satellites.xml and webtv
|
||||
if download_type in (DownloadType.ALL, DownloadType.SATELLITES, DownloadType.WEBTV):
|
||||
ftp.cwd(properties["satellites_xml_path"])
|
||||
ftp.cwd(settings.satellites_xml_path)
|
||||
files.clear()
|
||||
ftp.dir(files.append)
|
||||
|
||||
@@ -75,11 +75,11 @@ def download_data(*, properties, download_type=DownloadType.ALL, callback=print)
|
||||
download_file(ftp, _WEBTV_XML_FILE, save_path, callback)
|
||||
# epg.dat
|
||||
if download_type is DownloadType.EPG:
|
||||
stb_path = properties["services_path"]
|
||||
epg_options = properties.get("epg_options", None)
|
||||
stb_path = settings.services_path
|
||||
epg_options = settings.epg_options
|
||||
if epg_options:
|
||||
stb_path = epg_options.get("epg_dat_stb_path", stb_path)
|
||||
save_path = epg_options.get("epg_dat_path", save_path)
|
||||
stb_path = epg_options.epg_dat_stb_path or stb_path
|
||||
save_path = epg_options.epg_dat_path or save_path
|
||||
ftp.cwd(stb_path)
|
||||
ftp.dir(files.append)
|
||||
for file in files:
|
||||
@@ -91,16 +91,17 @@ def download_data(*, properties, download_type=DownloadType.ALL, callback=print)
|
||||
callback("\nDone.\n")
|
||||
|
||||
|
||||
def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=False, profile=Profile.ENIGMA_2,
|
||||
def upload_data(*, settings, download_type=DownloadType.ALL, remove_unused=False,
|
||||
callback=print, done_callback=None, use_http=False):
|
||||
data_path = properties["data_dir_path"]
|
||||
host = properties["host"]
|
||||
base_url = "http://{}:{}/api/".format(host, properties.get("http_port", "80"))
|
||||
profile = settings.profile
|
||||
data_path = settings.data_dir_path
|
||||
host = settings.host
|
||||
base_url = "http://{}:{}/api/".format(host, settings.http_port)
|
||||
tn, ht = None, None # telnet, http
|
||||
|
||||
try:
|
||||
if profile is Profile.ENIGMA_2 and use_http:
|
||||
ht = http(properties.get("http_user", ""), properties.get("http_password", ""), base_url, callback)
|
||||
ht = http(settings.http_user, settings.http_password, base_url, callback)
|
||||
next(ht)
|
||||
message = ""
|
||||
if download_type is DownloadType.BOUQUETS:
|
||||
@@ -120,18 +121,19 @@ def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=Fal
|
||||
time.sleep(2)
|
||||
else:
|
||||
# telnet
|
||||
tn = telnet(host=host, user=properties.get("telnet_user", "root"),
|
||||
password=properties.get("telnet_password", ""),
|
||||
timeout=properties.get("telnet_timeout", 5))
|
||||
tn = telnet(host=host,
|
||||
user=settings.telnet_user,
|
||||
password=settings.telnet_password,
|
||||
timeout=settings.telnet_timeout)
|
||||
next(tn)
|
||||
# terminate enigma or neutrino
|
||||
tn.send("init 4")
|
||||
|
||||
with FTP(host=host, user=properties["user"], passwd=properties["password"]) as ftp:
|
||||
with FTP(host=host, user=settings.user, passwd=settings.password) as ftp:
|
||||
ftp.encoding = "utf-8"
|
||||
callback("FTP OK.\n")
|
||||
sat_xml_path = properties["satellites_xml_path"]
|
||||
services_path = properties["services_path"]
|
||||
sat_xml_path = settings.satellites_xml_path
|
||||
services_path = settings.services_path
|
||||
|
||||
if download_type is DownloadType.SATELLITES:
|
||||
upload_xml(ftp, data_path, sat_xml_path, _SAT_XML_FILE, callback)
|
||||
@@ -153,7 +155,7 @@ def upload_data(*, properties, download_type=DownloadType.ALL, remove_unused=Fal
|
||||
upload_files(ftp, data_path, _DATA_FILES_LIST, callback)
|
||||
|
||||
if download_type is DownloadType.PICONS:
|
||||
upload_picons(ftp, properties.get("picons_dir_path"), properties.get("picons_path"), callback)
|
||||
upload_picons(ftp, settings.picons_dir_path, settings.picons_path, callback)
|
||||
|
||||
if tn and not use_http:
|
||||
# resume enigma or restart neutrino
|
||||
@@ -362,7 +364,7 @@ def telnet_test(host, port, user, password, timeout):
|
||||
time.sleep(timeout)
|
||||
yield tn.read_very_eager()
|
||||
tn.close()
|
||||
yield "Done"
|
||||
yield "Done!"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from app.commons import run_task
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from .ecommons import Service, Satellite, Transponder, Bouquet, Bouquets, is_transponder_valid
|
||||
from .enigma.blacklist import get_blacklist, write_blacklist
|
||||
from .enigma.bouquets import get_bouquets as get_enigma_bouquets, write_bouquets as write_enigma_bouquets, to_bouquet_id
|
||||
|
||||
@@ -3,7 +3,7 @@ import re
|
||||
import urllib.request
|
||||
from enum import Enum
|
||||
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from app.ui.uicommons import IPTV_ICON
|
||||
from .ecommons import BqServiceType, Service
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
|
||||
CONFIG_PATH = str(Path.home()) + "/.config/demon-editor/"
|
||||
CONFIG_FILE = CONFIG_PATH + "config.json"
|
||||
DATA_PATH = os.path.expanduser("~") + "/data/"
|
||||
|
||||
|
||||
class Profile(Enum):
|
||||
""" Profiles for settings """
|
||||
ENIGMA_2 = "0"
|
||||
NEUTRINO_MP = "1"
|
||||
|
||||
|
||||
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:
|
||||
reset_config()
|
||||
|
||||
with open(CONFIG_FILE, "r") as config_file:
|
||||
return json.load(config_file)
|
||||
|
||||
|
||||
def reset_config():
|
||||
with open(CONFIG_FILE, "w") as default_config_file:
|
||||
json.dump(get_default_settings(), default_config_file)
|
||||
|
||||
|
||||
def write_config(config):
|
||||
assert isinstance(config, dict)
|
||||
with open(CONFIG_FILE, "w") as config_file:
|
||||
json.dump(config, config_file)
|
||||
|
||||
|
||||
def get_default_settings():
|
||||
return {
|
||||
Profile.ENIGMA_2.value: {
|
||||
"host": "127.0.0.1", "port": "21", "user": "root", "password": "root",
|
||||
"http_user": "root", "http_password": "", "http_port": "80", "http_timeout": 5,
|
||||
"telnet_user": "root", "telnet_password": "", "telnet_port": "23", "telnet_timeout": 5,
|
||||
"services_path": "/etc/enigma2/", "user_bouquet_path": "/etc/enigma2/",
|
||||
"satellites_xml_path": "/etc/tuxbox/", "data_dir_path": DATA_PATH + "enigma2/",
|
||||
"picons_path": "/usr/share/enigma2/picon", "picons_dir_path": DATA_PATH + "enigma2/picons/",
|
||||
"backup_dir_path": DATA_PATH + "enigma2/backup/",
|
||||
"backup_before_save": True, "backup_before_downloading": True,
|
||||
"v5_support": False, "http_api_support": False, "enable_yt_dl": False, "enable_send_to": False,
|
||||
"use_colors": True, "new_color": "rgb(255,230,204)", "extra_color": "rgb(179,230,204)",
|
||||
"fav_click_mode": 0},
|
||||
Profile.NEUTRINO_MP.value: {
|
||||
"host": "127.0.0.1", "port": "21", "user": "root", "password": "root",
|
||||
"http_user": "", "http_password": "", "http_port": "80", "http_timeout": 2,
|
||||
"telnet_user": "root", "telnet_password": "", "telnet_port": "23", "telnet_timeout": 1,
|
||||
"services_path": "/var/tuxbox/config/zapit/", "user_bouquet_path": "/var/tuxbox/config/zapit/",
|
||||
"satellites_xml_path": "/var/tuxbox/config/", "data_dir_path": DATA_PATH + "neutrino/",
|
||||
"picons_path": "/usr/share/tuxbox/neutrino/icons/logo/", "picons_dir_path": DATA_PATH + "neutrino/picons/",
|
||||
"backup_dir_path": DATA_PATH + "neutrino/backup/",
|
||||
"backup_before_save": True, "backup_before_downloading": True,
|
||||
"fav_click_mode": 0},
|
||||
"profile": Profile.ENIGMA_2.value}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
365
app/settings.py
Normal file
365
app/settings.py
Normal file
@@ -0,0 +1,365 @@
|
||||
import json
|
||||
import os
|
||||
from pprint import pformat
|
||||
from textwrap import dedent
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
|
||||
CONFIG_PATH = str(Path.home()) + "/.config/demon-editor/"
|
||||
CONFIG_FILE = CONFIG_PATH + "config.json"
|
||||
DATA_PATH = "data/"
|
||||
|
||||
|
||||
class Profile(Enum):
|
||||
""" Profiles for settings """
|
||||
ENIGMA_2 = "0"
|
||||
NEUTRINO_MP = "1"
|
||||
|
||||
|
||||
class Settings:
|
||||
__INSTANCE = None
|
||||
|
||||
def __init__(self):
|
||||
self._config = get_config()
|
||||
self._current_profile = Profile(self._config.get("profile"))
|
||||
self._current_profile_options = self._config.get(self._current_profile.value)
|
||||
|
||||
def __str__(self):
|
||||
return dedent(""" Current profile: {}
|
||||
Current profile options:
|
||||
{}
|
||||
Full config:
|
||||
{}
|
||||
""").format(self._current_profile,
|
||||
pformat(self._current_profile_options),
|
||||
pformat(self._config))
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls):
|
||||
if not cls.__INSTANCE:
|
||||
cls.__INSTANCE = Settings()
|
||||
return cls.__INSTANCE
|
||||
|
||||
def save(self):
|
||||
write_config(self._config)
|
||||
|
||||
def reset(self, force_write=False):
|
||||
def_settings = get_default_settings()
|
||||
for p in Profile:
|
||||
current = self._config.get(p.value)
|
||||
default = def_settings.get(p.value)
|
||||
for k in default:
|
||||
current[k] = default.get(k)
|
||||
|
||||
if force_write:
|
||||
write_config(get_default_settings())
|
||||
|
||||
def add(self, name, value):
|
||||
""" Adds extra options """
|
||||
self._config[name] = value
|
||||
|
||||
def get(self, name):
|
||||
""" Returns extra options """
|
||||
return self._config.get(name, None)
|
||||
|
||||
def get_default(self, name):
|
||||
""" Returns default value of the option """
|
||||
return get_default_settings().get(self._current_profile.value).get(name)
|
||||
|
||||
@property
|
||||
def presets(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@presets.setter
|
||||
def presets(self, name):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def profile(self):
|
||||
return self._current_profile
|
||||
|
||||
@profile.setter
|
||||
def profile(self, prf):
|
||||
self._current_profile = prf
|
||||
self._config["profile"] = prf.value
|
||||
self._current_profile_options = self._config.get(prf.value)
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
return self._current_profile_options.get("host", self.get_default("host"))
|
||||
|
||||
@host.setter
|
||||
def host(self, value):
|
||||
self._current_profile_options["host"] = value
|
||||
|
||||
@property
|
||||
def port(self):
|
||||
return self._current_profile_options.get("port", self.get_default("port"))
|
||||
|
||||
@port.setter
|
||||
def port(self, value):
|
||||
self._current_profile_options["port"] = value
|
||||
|
||||
@property
|
||||
def user(self):
|
||||
return self._current_profile_options.get("user", self.get_default("user"))
|
||||
|
||||
@user.setter
|
||||
def user(self, value):
|
||||
self._current_profile_options["user"] = value
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
return self._current_profile_options.get("password", self.get_default("password"))
|
||||
|
||||
@password.setter
|
||||
def password(self, value):
|
||||
self._current_profile_options["password"] = value
|
||||
|
||||
@property
|
||||
def http_user(self):
|
||||
return self._current_profile_options.get("http_user", self.get_default("http_user"))
|
||||
|
||||
@http_user.setter
|
||||
def http_user(self, value):
|
||||
self._current_profile_options["http_user"] = value
|
||||
|
||||
@property
|
||||
def http_password(self):
|
||||
return self._current_profile_options.get("http_password", self.get_default("http_password"))
|
||||
|
||||
@http_password.setter
|
||||
def http_password(self, value):
|
||||
self._current_profile_options["http_password"] = value
|
||||
|
||||
@property
|
||||
def http_port(self):
|
||||
return self._current_profile_options.get("http_port", self.get_default("http_port"))
|
||||
|
||||
@http_port.setter
|
||||
def http_port(self, value):
|
||||
self._current_profile_options["http_port"] = value
|
||||
|
||||
@property
|
||||
def http_timeout(self):
|
||||
return self._current_profile_options.get("http_timeout", self.get_default("http_timeout"))
|
||||
|
||||
@http_timeout.setter
|
||||
def http_timeout(self, value):
|
||||
self._current_profile_options["http_timeout"] = value
|
||||
|
||||
@property
|
||||
def telnet_user(self):
|
||||
return self._current_profile_options.get("telnet_user", self.get_default("telnet_user"))
|
||||
|
||||
@telnet_user.setter
|
||||
def telnet_user(self, value):
|
||||
self._current_profile_options["telnet_user"] = value
|
||||
|
||||
@property
|
||||
def telnet_password(self):
|
||||
return self._current_profile_options.get("telnet_password", self.get_default("telnet_password"))
|
||||
|
||||
@telnet_password.setter
|
||||
def telnet_password(self, value):
|
||||
self._current_profile_options["telnet_password"] = value
|
||||
|
||||
@property
|
||||
def telnet_port(self):
|
||||
return self._current_profile_options.get("telnet_port", self.get_default("telnet_port"))
|
||||
|
||||
@telnet_port.setter
|
||||
def telnet_port(self, value):
|
||||
self._current_profile_options["telnet_port"] = value
|
||||
|
||||
@property
|
||||
def telnet_timeout(self):
|
||||
return self._current_profile_options.get("telnet_timeout", self.get_default("telnet_timeout"))
|
||||
|
||||
@telnet_timeout.setter
|
||||
def telnet_timeout(self, value):
|
||||
self._current_profile_options["telnet_timeout"] = value
|
||||
|
||||
@property
|
||||
def services_path(self):
|
||||
return self._current_profile_options.get("services_path", self.get_default("services_path"))
|
||||
|
||||
@services_path.setter
|
||||
def services_path(self, value):
|
||||
self._current_profile_options["services_path"] = value
|
||||
|
||||
@property
|
||||
def user_bouquet_path(self):
|
||||
return self._current_profile_options.get("user_bouquet_path", self.get_default("user_bouquet_path"))
|
||||
|
||||
@user_bouquet_path.setter
|
||||
def user_bouquet_path(self, value):
|
||||
self._current_profile_options["user_bouquet_path"] = value
|
||||
|
||||
@property
|
||||
def satellites_xml_path(self):
|
||||
return self._current_profile_options.get("satellites_xml_path", self.get_default("satellites_xml_path"))
|
||||
|
||||
@satellites_xml_path.setter
|
||||
def satellites_xml_path(self, value):
|
||||
self._current_profile_options["satellites_xml_path"] = value
|
||||
|
||||
@property
|
||||
def data_dir_path(self):
|
||||
return self._current_profile_options.get("data_dir_path", self.get_default("data_dir_path"))
|
||||
|
||||
@data_dir_path.setter
|
||||
def data_dir_path(self, value):
|
||||
self._current_profile_options["data_dir_path"] = value
|
||||
|
||||
@property
|
||||
def picons_path(self):
|
||||
return self._current_profile_options.get("picons_path", self.get_default("picons_path"))
|
||||
|
||||
@picons_path.setter
|
||||
def picons_path(self, value):
|
||||
self._current_profile_options["picons_path"] = value
|
||||
|
||||
@property
|
||||
def picons_dir_path(self):
|
||||
return self._current_profile_options.get("picons_dir_path", self.get_default("picons_dir_path"))
|
||||
|
||||
@picons_dir_path.setter
|
||||
def picons_dir_path(self, value):
|
||||
self._current_profile_options["picons_dir_path"] = value
|
||||
|
||||
@property
|
||||
def backup_dir_path(self):
|
||||
return self._current_profile_options.get("backup_dir_path", self.get_default("backup_dir_path"))
|
||||
|
||||
@backup_dir_path.setter
|
||||
def backup_dir_path(self, value):
|
||||
self._current_profile_options["backup_dir_path"] = value
|
||||
|
||||
@property
|
||||
def backup_before_save(self):
|
||||
return self._current_profile_options.get("backup_before_save", self.get_default("backup_before_save"))
|
||||
|
||||
@backup_before_save.setter
|
||||
def backup_before_save(self, value):
|
||||
self._current_profile_options["backup_before_save"] = value
|
||||
|
||||
@property
|
||||
def backup_before_downloading(self):
|
||||
return self._current_profile_options.get("backup_before_downloading",
|
||||
self.get_default("backup_before_downloading"))
|
||||
|
||||
@backup_before_downloading.setter
|
||||
def backup_before_downloading(self, value):
|
||||
self._current_profile_options["backup_before_downloading"] = value
|
||||
|
||||
@property
|
||||
def v5_support(self):
|
||||
return self._current_profile_options.get("v5_support", self.get_default("v5_support"))
|
||||
|
||||
@v5_support.setter
|
||||
def v5_support(self, value):
|
||||
self._current_profile_options["v5_support"] = value
|
||||
|
||||
@property
|
||||
def http_api_support(self):
|
||||
return self._current_profile_options.get("http_api_support", self.get_default("http_api_support"))
|
||||
|
||||
@http_api_support.setter
|
||||
def http_api_support(self, value):
|
||||
self._current_profile_options["http_api_support"] = value
|
||||
|
||||
@property
|
||||
def enable_yt_dl(self):
|
||||
return self._current_profile_options.get("enable_yt_dl", self.get_default("enable_yt_dl"))
|
||||
|
||||
@enable_yt_dl.setter
|
||||
def enable_yt_dl(self, value):
|
||||
self._current_profile_options["enable_yt_dl"] = value
|
||||
|
||||
@property
|
||||
def enable_send_to(self):
|
||||
return self._current_profile_options.get("enable_send_to", self.get_default("enable_send_to"))
|
||||
|
||||
@enable_send_to.setter
|
||||
def enable_send_to(self, value):
|
||||
self._current_profile_options["enable_send_to"] = value
|
||||
|
||||
@property
|
||||
def use_colors(self):
|
||||
return self._current_profile_options.get("use_colors", self.get_default("use_colors"))
|
||||
|
||||
@use_colors.setter
|
||||
def use_colors(self, value):
|
||||
self._current_profile_options["use_colors"] = value
|
||||
|
||||
@property
|
||||
def new_color(self):
|
||||
return self._current_profile_options.get("new_color", self.get_default("new_color"))
|
||||
|
||||
@new_color.setter
|
||||
def new_color(self, value):
|
||||
self._current_profile_options["new_color"] = value
|
||||
|
||||
@property
|
||||
def extra_color(self):
|
||||
return self._current_profile_options.get("extra_color", self.get_default("extra_color"))
|
||||
|
||||
@extra_color.setter
|
||||
def extra_color(self, value):
|
||||
self._current_profile_options["extra_color"] = value
|
||||
|
||||
@property
|
||||
def fav_click_mode(self):
|
||||
return self._current_profile_options.get("fav_click_mode", self.get_default("fav_click_mode"))
|
||||
|
||||
@fav_click_mode.setter
|
||||
def fav_click_mode(self, value):
|
||||
self._current_profile_options["fav_click_mode"] = value
|
||||
|
||||
|
||||
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:
|
||||
write_config(get_default_settings())
|
||||
|
||||
with open(CONFIG_FILE, "r") as config_file:
|
||||
return json.load(config_file)
|
||||
|
||||
|
||||
def write_config(config):
|
||||
with open(CONFIG_FILE, "w") as config_file:
|
||||
json.dump(config, config_file, indent=" ")
|
||||
|
||||
|
||||
def get_default_settings():
|
||||
return {
|
||||
Profile.ENIGMA_2.value: {
|
||||
"host": "127.0.0.1", "port": "21", "user": "root", "password": "root",
|
||||
"http_user": "root", "http_password": "", "http_port": "80", "http_timeout": 5,
|
||||
"telnet_user": "root", "telnet_password": "", "telnet_port": "23", "telnet_timeout": 5,
|
||||
"services_path": "/etc/enigma2/", "user_bouquet_path": "/etc/enigma2/",
|
||||
"satellites_xml_path": "/etc/tuxbox/", "data_dir_path": DATA_PATH + "enigma2/",
|
||||
"picons_path": "/usr/share/enigma2/picon", "picons_dir_path": DATA_PATH + "enigma2/picons/",
|
||||
"backup_dir_path": DATA_PATH + "enigma2/backup/",
|
||||
"backup_before_save": True, "backup_before_downloading": True,
|
||||
"v5_support": False, "http_api_support": False, "enable_yt_dl": False, "enable_send_to": False,
|
||||
"use_colors": True, "new_color": "rgb(255,230,204)", "extra_color": "rgb(179,230,204)",
|
||||
"fav_click_mode": 0},
|
||||
Profile.NEUTRINO_MP.value: {
|
||||
"host": "127.0.0.1", "port": "21", "user": "root", "password": "root",
|
||||
"http_user": "", "http_password": "", "http_port": "80", "http_timeout": 2,
|
||||
"telnet_user": "root", "telnet_password": "", "telnet_port": "23", "telnet_timeout": 1,
|
||||
"services_path": "/var/tuxbox/config/zapit/", "user_bouquet_path": "/var/tuxbox/config/zapit/",
|
||||
"satellites_xml_path": "/var/tuxbox/config/", "data_dir_path": DATA_PATH + "neutrino/",
|
||||
"picons_path": "/usr/share/tuxbox/neutrino/icons/logo/", "picons_dir_path": DATA_PATH + "neutrino/picons/",
|
||||
"backup_dir_path": DATA_PATH + "neutrino/backup/",
|
||||
"backup_before_save": True, "backup_before_downloading": True,
|
||||
"fav_click_mode": 0},
|
||||
"profile": Profile.ENIGMA_2.value}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
@@ -1,36 +1,37 @@
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
from app.commons import run_task, log
|
||||
from app.tools import vlc
|
||||
from app.tools.vlc import EventType
|
||||
|
||||
|
||||
class Player:
|
||||
_VLC_INSTANCE = None
|
||||
__VLC_INSTANCE = None
|
||||
|
||||
def __init__(self, rewind_callback=None, position_callback=None):
|
||||
self._is_playing = False
|
||||
self._player = self.get_vlc_instance()
|
||||
ev_mgr = self._player.event_manager()
|
||||
def __init__(self, rewind_callback, position_callback):
|
||||
try:
|
||||
from app.tools import vlc
|
||||
from app.tools.vlc import EventType
|
||||
except OSError as e:
|
||||
log("{}: Load library error: {}".format(__class__.__name__, e))
|
||||
else:
|
||||
self._is_playing = False
|
||||
args = "--quiet {}".format("" if sys.platform == "darwin" else "--no-xlib")
|
||||
self._player = vlc.Instance(args).media_player_new()
|
||||
ev_mgr = self._player.event_manager()
|
||||
|
||||
if rewind_callback:
|
||||
# TODO look other EventType options
|
||||
ev_mgr.event_attach(EventType.MediaPlayerBuffering,
|
||||
lambda e, p: rewind_callback(p.get_media().get_duration()),
|
||||
self._player)
|
||||
if position_callback:
|
||||
ev_mgr.event_attach(EventType.MediaPlayerTimeChanged,
|
||||
lambda e, p: position_callback(p.get_time()),
|
||||
self._player)
|
||||
if rewind_callback:
|
||||
# TODO look other EventType options
|
||||
ev_mgr.event_attach(EventType.MediaPlayerBuffering,
|
||||
lambda et, p: rewind_callback(p.get_media().get_duration()),
|
||||
self._player)
|
||||
if position_callback:
|
||||
ev_mgr.event_attach(EventType.MediaPlayerTimeChanged,
|
||||
lambda et, p: position_callback(p.get_time()),
|
||||
self._player)
|
||||
|
||||
@staticmethod
|
||||
def get_vlc_instance():
|
||||
if Player._VLC_INSTANCE:
|
||||
return Player._VLC_INSTANCE
|
||||
args = "--quiet {}".format("" if sys.platform == "darwin" else "--no-xlib")
|
||||
_VLC_INSTANCE = vlc.Instance(args).media_player_new()
|
||||
return _VLC_INSTANCE
|
||||
@classmethod
|
||||
def get_instance(cls, rewind_callback=None, position_callback=None):
|
||||
if not cls.__VLC_INSTANCE:
|
||||
cls.__VLC_INSTANCE = Player(rewind_callback, position_callback)
|
||||
return cls.__VLC_INSTANCE
|
||||
|
||||
@run_task
|
||||
def play(self, mrl=None):
|
||||
@@ -68,6 +69,7 @@ class Player:
|
||||
https://github.com/oaubert/python-vlc/tree/master/examples
|
||||
"""
|
||||
try:
|
||||
import ctypes
|
||||
g_dll = ctypes.CDLL("libgdk-3.0.dylib")
|
||||
except OSError as e:
|
||||
log("{}: Load library error: {}".format(__class__.__name__, e))
|
||||
|
||||
@@ -7,7 +7,7 @@ from collections import namedtuple
|
||||
from html.parser import HTMLParser
|
||||
|
||||
from app.commons import run_task
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
|
||||
_ENIGMA2_PICON_KEY = "{:X}:{:X}:{}"
|
||||
_NEUTRINO_PICON_KEY = "{:x}{:04x}{:04x}.png"
|
||||
|
||||
@@ -7,7 +7,7 @@ from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from app.commons import run_idle
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from app.ui.dialogs import show_dialog, DialogType
|
||||
from app.ui.main_helper import append_text_to_tview
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey
|
||||
@@ -19,7 +19,7 @@ class RestoreType(Enum):
|
||||
|
||||
|
||||
class BackupDialog:
|
||||
def __init__(self, transient, options, profile, callback):
|
||||
def __init__(self, transient, settings, callback):
|
||||
handlers = {"on_restore_bouquets": self.on_restore_bouquets,
|
||||
"on_restore_all": self.on_restore_all,
|
||||
"on_remove": self.on_remove,
|
||||
@@ -35,10 +35,10 @@ class BackupDialog:
|
||||
builder.add_from_file(UI_RESOURCES_PATH + "backup_dialog.glade")
|
||||
builder.connect_signals(handlers)
|
||||
|
||||
self._options = options.get(profile.value)
|
||||
self._data_path = self._options.get("data_dir_path", "")
|
||||
self._backup_path = self._options.get("backup_dir_path", self._data_path + "backup/")
|
||||
self._profile = profile
|
||||
self._settings = settings
|
||||
self._profile = settings.profile
|
||||
self._data_path = self._settings.data_dir_path
|
||||
self._backup_path = self._settings.backup_dir_path or self._data_path + "backup/"
|
||||
self._open_data_callback = callback
|
||||
self._dialog_window = builder.get_object("dialog_window")
|
||||
self._dialog_window.set_transient_for(transient)
|
||||
@@ -50,7 +50,7 @@ class BackupDialog:
|
||||
self._info_bar = builder.get_object("info_bar")
|
||||
self._message_label = builder.get_object("message_label")
|
||||
# Setting the last size of the dialog window if it was saved
|
||||
window_size = self._options.get("backup_tool_window_size", None)
|
||||
window_size = self._settings.get("backup_tool_window_size")
|
||||
if window_size:
|
||||
self._dialog_window.resize(*window_size)
|
||||
|
||||
@@ -166,8 +166,8 @@ class BackupDialog:
|
||||
self._open_data_callback(self._data_path)
|
||||
|
||||
def on_resize(self, window):
|
||||
if self._options:
|
||||
self._options["backup_tool_window_size"] = window.get_size()
|
||||
if self._settings:
|
||||
self._settings.add("backup_tool_window_size", window.get_size())
|
||||
|
||||
def on_key_release(self, view, event):
|
||||
""" Handling keystrokes """
|
||||
|
||||
@@ -67,12 +67,12 @@ class WaitDialog:
|
||||
self._dialog.destroy()
|
||||
|
||||
|
||||
def show_dialog(dialog_type: DialogType, transient, text=None, options=None, action_type=None, file_filter=None):
|
||||
def show_dialog(dialog_type: DialogType, transient, text=None, settings=None, action_type=None, file_filter=None):
|
||||
""" Shows dialogs by name """
|
||||
if dialog_type in (DialogType.INFO, DialogType.ERROR):
|
||||
return get_message_dialog(transient, dialog_type, Gtk.ButtonsType.OK, text)
|
||||
elif dialog_type is DialogType.CHOOSER and options:
|
||||
return get_file_chooser_dialog(transient, text, options, action_type, file_filter)
|
||||
elif dialog_type is DialogType.CHOOSER and settings:
|
||||
return get_file_chooser_dialog(transient, text, settings, action_type, file_filter)
|
||||
elif dialog_type is DialogType.INPUT:
|
||||
return get_input_dialog(transient, text)
|
||||
elif dialog_type is DialogType.QUESTION:
|
||||
@@ -81,34 +81,30 @@ def show_dialog(dialog_type: DialogType, transient, text=None, options=None, act
|
||||
return get_about_dialog(transient)
|
||||
|
||||
|
||||
def get_chooser_dialog(transient, options, pattern, name):
|
||||
def get_chooser_dialog(transient, settings, pattern, name):
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.add_pattern(pattern)
|
||||
file_filter.set_name(name)
|
||||
|
||||
return show_dialog(dialog_type=DialogType.CHOOSER,
|
||||
transient=transient,
|
||||
options=options,
|
||||
settings=settings,
|
||||
action_type=Gtk.FileChooserAction.OPEN,
|
||||
file_filter=file_filter)
|
||||
|
||||
|
||||
def get_file_chooser_dialog(transient, text, options, action_type, file_filter):
|
||||
dialog = Gtk.FileChooserNative()
|
||||
dialog.set_title(get_message(text) if text else "")
|
||||
dialog.set_transient_for(transient)
|
||||
dialog.set_action(action_type if action_type is not None else Gtk.FileChooserAction.SELECT_FOLDER)
|
||||
dialog.set_create_folders(False)
|
||||
dialog.set_modal(True)
|
||||
|
||||
def get_file_chooser_dialog(transient, text, settings, action_type, file_filter):
|
||||
dialog = Gtk.FileChooserDialog(get_message(text) if text else "", transient,
|
||||
action_type if action_type is not None else Gtk.FileChooserAction.SELECT_FOLDER,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK),
|
||||
use_header_bar=IS_GNOME_SESSION)
|
||||
if file_filter is not None:
|
||||
dialog.add_filter(file_filter)
|
||||
|
||||
path = options.get("data_dir_path")
|
||||
path = settings.data_dir_path
|
||||
dialog.set_current_folder(path)
|
||||
response = dialog.run()
|
||||
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
if response == Gtk.ResponseType.OK:
|
||||
if dialog.get_filename():
|
||||
path = dialog.get_filename()
|
||||
if action_type is not Gtk.FileChooserAction.OPEN:
|
||||
@@ -167,8 +163,7 @@ def get_dialog_from_xml(dialog_type, transient, use_header=0, title=""):
|
||||
|
||||
def get_message(message):
|
||||
""" returns translated message """
|
||||
# return locale.dgettext(TEXT_DOMAIN, message)
|
||||
return message
|
||||
return locale.dgettext(TEXT_DOMAIN, message)
|
||||
|
||||
|
||||
@lru_cache(maxsize=5)
|
||||
|
||||
@@ -2,7 +2,7 @@ from gi.repository import GLib
|
||||
|
||||
from app.commons import run_idle, run_task
|
||||
from app.connections import download_data, DownloadType, upload_data
|
||||
from app.properties import Profile, get_config
|
||||
from app.settings import Profile
|
||||
from app.ui.backup import backup_data, restore_data
|
||||
from app.ui.main_helper import append_text_to_tview
|
||||
from app.ui.settings_dialog import show_settings_dialog
|
||||
@@ -11,12 +11,11 @@ from .dialogs import show_dialog, DialogType, get_message
|
||||
|
||||
|
||||
class DownloadDialog:
|
||||
def __init__(self, transient, properties, open_data_callback, update_settings_callback, profile=Profile.ENIGMA_2):
|
||||
self._profile_properties = properties.get(profile.value)
|
||||
self._properties = properties
|
||||
def __init__(self, transient, settings, open_data_callback, update_settings_callback):
|
||||
self._profile = settings.profile
|
||||
self._settings = settings
|
||||
self._open_data_callback = open_data_callback
|
||||
self._update_settings_callback = update_settings_callback
|
||||
self._profile = profile
|
||||
|
||||
handlers = {"on_receive": self.on_receive,
|
||||
"on_send": self.on_send,
|
||||
@@ -53,14 +52,14 @@ class DownloadDialog:
|
||||
self._use_http_switch = builder.get_object("use_http_switch")
|
||||
self._http_radio_button = builder.get_object("http_radio_button")
|
||||
self._use_http_box = builder.get_object("use_http_box")
|
||||
self.init_properties()
|
||||
self.init_settings()
|
||||
|
||||
def show(self):
|
||||
self._dialog_window.show()
|
||||
|
||||
def init_properties(self):
|
||||
self._host_entry.set_text(self._profile_properties["host"])
|
||||
self._data_path_entry.set_text(self._profile_properties["data_dir_path"])
|
||||
def init_settings(self):
|
||||
self._host_entry.set_text(self._settings.host)
|
||||
self._data_path_entry.set_text(self._settings.data_dir_path)
|
||||
is_enigma = self._profile is Profile.ENIGMA_2
|
||||
self._webtv_radio_button.set_visible(not is_enigma)
|
||||
self._http_radio_button.set_visible(is_enigma)
|
||||
@@ -93,33 +92,34 @@ class DownloadDialog:
|
||||
if button.get_active():
|
||||
label = button.get_label()
|
||||
if label == "Telnet":
|
||||
self._login_entry.set_text(self._profile_properties.get("telnet_user", ""))
|
||||
self._password_entry.set_text(self._profile_properties.get("telnet_password", ""))
|
||||
self._port_entry.set_text(self._profile_properties.get("telnet_port", ""))
|
||||
self._timeout_entry.set_text(str(self._profile_properties.get("telnet_timeout", 0)))
|
||||
self._login_entry.set_text(self._settings.telnet_user)
|
||||
self._password_entry.set_text(self._settings.telnet_password)
|
||||
self._port_entry.set_text(self._settings.telnet_port)
|
||||
self._timeout_entry.set_text(str(self._settings.telnet_timeout))
|
||||
elif label == "HTTP":
|
||||
self._login_entry.set_text(self._profile_properties.get("http_user", "root"))
|
||||
self._password_entry.set_text(self._profile_properties.get("http_password", ""))
|
||||
self._port_entry.set_text(self._profile_properties.get("http_port", ""))
|
||||
self._timeout_entry.set_text(str(self._profile_properties.get("http_timeout", 0)))
|
||||
self._login_entry.set_text(self._settings.http_user)
|
||||
self._password_entry.set_text(self._settings.http_password)
|
||||
self._port_entry.set_text(self._settings.http_port)
|
||||
self._timeout_entry.set_text(str(self._settings.http_timeout))
|
||||
elif label == "FTP":
|
||||
self._login_entry.set_text(self._profile_properties.get("user", ""))
|
||||
self._password_entry.set_text(self._profile_properties.get("password", ""))
|
||||
self._port_entry.set_text(self._profile_properties.get("port", ""))
|
||||
self._login_entry.set_text(self._settings.user)
|
||||
self._password_entry.set_text(self._settings.password)
|
||||
self._port_entry.set_text(self._settings.port)
|
||||
self._timeout_entry.set_text("")
|
||||
self._current_property = label
|
||||
|
||||
def on_preferences(self, item):
|
||||
show_settings_dialog(self._dialog_window, self._properties)
|
||||
self._profile = Profile(self._properties.get("profile", Profile.ENIGMA_2.value))
|
||||
self._profile_properties = get_config().get(self._profile.value)
|
||||
self.init_properties()
|
||||
self._update_settings_callback()
|
||||
response = show_settings_dialog(self._dialog_window, self._settings)
|
||||
if response != Gtk.ResponseType.CANCEL:
|
||||
self._profile = self._settings.profile
|
||||
self.init_settings()
|
||||
gen = self._update_settings_callback()
|
||||
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
||||
|
||||
for button in self._settings_buttons_box.get_children():
|
||||
if button.get_active():
|
||||
self.on_settings_button(button)
|
||||
break
|
||||
for button in self._settings_buttons_box.get_children():
|
||||
if button.get_active():
|
||||
self.on_settings_button(button)
|
||||
break
|
||||
|
||||
def on_info_bar_close(self, bar=None, resp=None):
|
||||
self._info_bar.set_visible(False)
|
||||
@@ -129,21 +129,20 @@ class DownloadDialog:
|
||||
""" Download/upload data from/to receiver """
|
||||
self._expander.set_expanded(True)
|
||||
self.clear_output()
|
||||
backup, backup_src, data_path = self._profile_properties.get("backup_before_downloading", True), None, None
|
||||
backup, backup_src, data_path = self._settings.backup_before_downloading, None, None
|
||||
|
||||
try:
|
||||
if download:
|
||||
if backup and d_type is not DownloadType.SATELLITES:
|
||||
data_path = self._profile_properties.get("data_dir_path", self._data_path_entry.get_text())
|
||||
backup_path = self._profile_properties.get("backup_dir_path", data_path + "backup/")
|
||||
data_path = self._settings.data_dir_path or self._data_path_entry.get_text()
|
||||
backup_path = self._settings.backup_dir_path or data_path + "backup/"
|
||||
backup_src = backup_data(data_path, backup_path, d_type is DownloadType.ALL)
|
||||
download_data(properties=self._profile_properties, download_type=d_type, callback=self.append_output)
|
||||
download_data(settings=self._settings, download_type=d_type, callback=self.append_output)
|
||||
else:
|
||||
self.show_info_message(get_message("Please, wait..."), Gtk.MessageType.INFO)
|
||||
upload_data(properties=self._profile_properties,
|
||||
upload_data(settings=self._settings,
|
||||
download_type=d_type,
|
||||
remove_unused=self._remove_unused_check_button.get_active(),
|
||||
profile=self._profile,
|
||||
callback=self.append_output,
|
||||
done_callback=lambda: self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO),
|
||||
use_http=self._use_http_switch.get_active())
|
||||
|
||||
@@ -25,7 +25,7 @@ class RefsSource(Enum):
|
||||
|
||||
class EpgDialog:
|
||||
|
||||
def __init__(self, transient, options, services, bouquet, fav_model, bouquet_name):
|
||||
def __init__(self, transient, settings, services, bouquet, fav_model, bouquet_name):
|
||||
|
||||
handlers = {"on_close_dialog": self.on_close_dialog,
|
||||
"on_apply": self.on_apply,
|
||||
@@ -56,7 +56,7 @@ class EpgDialog:
|
||||
self._services = {}
|
||||
self._ex_services = services
|
||||
self._ex_fav_model = fav_model
|
||||
self._options = options
|
||||
self._settings = settings
|
||||
self._bouquet = bouquet
|
||||
self._bouquet_name = bouquet_name
|
||||
self._current_ref = []
|
||||
@@ -106,7 +106,7 @@ class EpgDialog:
|
||||
self._update_on_start_switch = builder.get_object("update_on_start_switch")
|
||||
self._epg_dat_source_box = builder.get_object("epg_dat_source_box")
|
||||
# Setting the last size of the dialog window
|
||||
window_size = self._options.get("epg_tool_window_size", None)
|
||||
window_size = self._settings.get("epg_tool_window_size")
|
||||
if window_size:
|
||||
self._dialog.resize(*window_size)
|
||||
|
||||
@@ -288,7 +288,7 @@ class EpgDialog:
|
||||
|
||||
@run_idle
|
||||
def on_save_to_xml(self, item):
|
||||
response = show_dialog(DialogType.CHOOSER, self._dialog, options=self._options)
|
||||
response = show_dialog(DialogType.CHOOSER, self._dialog, settings=self._settings)
|
||||
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
return
|
||||
|
||||
@@ -483,10 +483,10 @@ class EpgDialog:
|
||||
# ***************** Options *********************#
|
||||
|
||||
def init_options(self):
|
||||
epg_dat_path = self._options.get("data_dir_path", "") + "epg/"
|
||||
epg_dat_path = self._settings.data_dir_path + "epg/"
|
||||
self._epg_dat_path_entry.set_text(epg_dat_path)
|
||||
default_epg_data_stb_path = "/etc/enigma2"
|
||||
epg_options = self._options.get("epg_options", None)
|
||||
epg_options = self._settings.get("epg_options")
|
||||
if epg_options:
|
||||
self._refs_source = RefsSource.XML if epg_options.get("xml_source", False) else RefsSource.SERVICES
|
||||
self._xml_radiobutton.set_active(self._refs_source is RefsSource.XML)
|
||||
@@ -514,11 +514,11 @@ class EpgDialog:
|
||||
"epg_dat_path": self._epg_dat_path_entry.get_text(),
|
||||
"epg_dat_stb_path": self._epg_dat_stb_path_entry.get_text(),
|
||||
"epg_data_update_on_start": self._update_on_start_switch.get_active()}
|
||||
self._options["epg_options"] = epg_options
|
||||
self._settings.add("epg_options", epg_options)
|
||||
|
||||
def on_resize(self, window):
|
||||
if self._options:
|
||||
self._options["epg_tool_window_size"] = window.get_size()
|
||||
if self._settings:
|
||||
self._settings.add("epg_tool_window_size", window.get_size())
|
||||
|
||||
def on_names_source_changed(self, button):
|
||||
self._refs_source = RefsSource.XML if button.get_active() else RefsSource.SERVICES
|
||||
@@ -536,13 +536,13 @@ class EpgDialog:
|
||||
self._xml_chooser_button.set_sensitive(not state)
|
||||
|
||||
def on_field_icon_press(self, entry, icon, event_button):
|
||||
update_entry_data(entry, self._dialog, self._options)
|
||||
update_entry_data(entry, self._dialog, self._settings)
|
||||
|
||||
# ***************** Downloads *********************#
|
||||
|
||||
def download_epg_from_stb(self):
|
||||
""" Download the epg.dat file via ftp from the receiver. """
|
||||
download_data(properties=self._options, download_type=DownloadType.EPG, callback=print)
|
||||
download_data(settings=self._settings, download_type=DownloadType.EPG, callback=print)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -89,6 +89,7 @@ Author: Dmitriy Yefremov
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="gravity">center</property>
|
||||
<signal name="check-resize" handler="on_resize" swapped="no"/>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header_bar">
|
||||
<property name="visible">True</property>
|
||||
|
||||
@@ -6,17 +6,18 @@ from app.eparser import get_bouquets, get_services
|
||||
from app.eparser.ecommons import BqType, BqServiceType, Bouquet
|
||||
from app.eparser.enigma.bouquets import get_bouquet
|
||||
from app.eparser.neutrino.bouquets import parse_webtv, parse_bouquets as get_neutrino_bouquets
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from app.ui.dialogs import show_dialog, DialogType, get_chooser_dialog, get_message
|
||||
from app.ui.main_helper import on_popup_menu
|
||||
from .uicommons import Gtk, UI_RESOURCES_PATH, KeyboardKey, Column
|
||||
|
||||
|
||||
def import_bouquet(transient, profile, model, path, options, services, appender):
|
||||
def import_bouquet(transient, model, path, settings, services, appender):
|
||||
""" Import of single bouquet """
|
||||
itr = model.get_iter(path)
|
||||
bq_type = BqType(model.get(itr, Column.BQ_TYPE)[0])
|
||||
pattern, f_pattern = None, None
|
||||
profile = settings.profile
|
||||
|
||||
if profile is Profile.ENIGMA_2:
|
||||
pattern = ".{}".format(bq_type.value)
|
||||
@@ -29,7 +30,7 @@ def import_bouquet(transient, profile, model, path, options, services, appender)
|
||||
elif bq_type is BqType.WEBTV:
|
||||
f_pattern = "webtv.xml"
|
||||
|
||||
file_path = get_chooser_dialog(transient, options, f_pattern, "bouquet files")
|
||||
file_path = get_chooser_dialog(transient, settings, f_pattern, "bouquet files")
|
||||
if file_path == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
@@ -56,7 +57,7 @@ def import_bouquet(transient, profile, model, path, options, services, appender)
|
||||
else:
|
||||
bqs = get_neutrino_bouquets(file_path, "", bq_type.value)
|
||||
file_path = "{}/".format(Path(file_path).parent)
|
||||
ImportDialog(transient, file_path, profile, services.keys(), lambda b, s: appender(b), (bqs,)).show()
|
||||
ImportDialog(transient, file_path, settings, services.keys(), lambda b, s: appender(b), (bqs,)).show()
|
||||
|
||||
|
||||
def get_enigma2_bouquet(path):
|
||||
@@ -68,7 +69,7 @@ def get_enigma2_bouquet(path):
|
||||
|
||||
|
||||
class ImportDialog:
|
||||
def __init__(self, transient, path, profile, service_ids, appender, bouquets=None):
|
||||
def __init__(self, transient, path, settings, service_ids, appender, bouquets=None):
|
||||
handlers = {"on_import": self.on_import,
|
||||
"on_cursor_changed": self.on_cursor_changed,
|
||||
"on_info_button_toggled": self.on_info_button_toggled,
|
||||
@@ -77,6 +78,7 @@ class ImportDialog:
|
||||
"on_select_all": self.on_select_all,
|
||||
"on_unselect_all": self.on_unselect_all,
|
||||
"on_popup_menu": on_popup_menu,
|
||||
"on_resize": self.on_resize,
|
||||
"on_key_press": self.on_key_press}
|
||||
|
||||
builder = Gtk.Builder()
|
||||
@@ -88,7 +90,8 @@ class ImportDialog:
|
||||
self._services = {}
|
||||
self._service_ids = service_ids
|
||||
self._append = appender
|
||||
self._profile = profile
|
||||
self._profile = settings.profile
|
||||
self._settings = settings
|
||||
self._bouquets = bouquets
|
||||
|
||||
self._dialog_window = builder.get_object("dialog_window")
|
||||
@@ -101,6 +104,9 @@ class ImportDialog:
|
||||
self._info_check_button = builder.get_object("info_check_button")
|
||||
self._info_bar = builder.get_object("info_bar")
|
||||
self._message_label = builder.get_object("message_label")
|
||||
window_size = self._settings.get("import_dialog_window_size")
|
||||
if window_size:
|
||||
self._dialog_window.resize(*window_size)
|
||||
|
||||
self.init_data(path)
|
||||
|
||||
@@ -206,6 +212,10 @@ class ImportDialog:
|
||||
def update_selection(self, view, select):
|
||||
view.get_model().foreach(lambda mod, path, itr: mod.set_value(itr, 2, select))
|
||||
|
||||
def on_resize(self, window):
|
||||
if self._settings:
|
||||
self._settings.add("import_dialog_window_size", window.get_size())
|
||||
|
||||
def on_key_press(self, view, event):
|
||||
""" Handling keystrokes """
|
||||
key_code = event.hardware_keycode
|
||||
|
||||
@@ -10,7 +10,7 @@ from gi.repository import GLib
|
||||
from app.commons import run_idle, run_task, log
|
||||
from app.eparser.ecommons import BqServiceType, Service
|
||||
from app.eparser.iptv import NEUTRINO_FAV_ID_FORMAT, StreamType, ENIGMA2_FAV_ID_FORMAT, get_fav_id, MARKER_FORMAT
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from app.tools.yt import YouTube, PlayListParser
|
||||
from .dialogs import Action, show_dialog, DialogType, get_dialogs_string, get_message
|
||||
from .main_helper import get_base_model, get_iptv_url, on_popup_menu
|
||||
|
||||
@@ -16,7 +16,7 @@ from app.eparser.ecommons import CAS, Flag, BouquetService
|
||||
from app.eparser.enigma.bouquets import BqServiceType
|
||||
from app.eparser.iptv import export_to_m3u
|
||||
from app.eparser.neutrino.bouquets import BqType
|
||||
from app.properties import get_config, write_config, Profile
|
||||
from app.settings import Profile, Settings
|
||||
from app.tools.media import Player
|
||||
from app.ui.epg_dialog import EpgDialog
|
||||
from app.ui.transmitter import LinksTransmitter
|
||||
@@ -26,7 +26,7 @@ from .download_dialog import DownloadDialog
|
||||
from .iptv import IptvDialog, SearchUnavailableDialog, IptvListConfigurationDialog, YtListImportDialog
|
||||
from .search import SearchProvider
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, LOCKED_ICON, HIDE_ICON, IPTV_ICON, MOVE_KEYS, KeyboardKey, Column, \
|
||||
EXTRA_COLOR, NEW_COLOR, FavClickMode
|
||||
FavClickMode
|
||||
from .dialogs import show_dialog, DialogType, get_chooser_dialog, WaitDialog, get_message
|
||||
from .main_helper import insert_marker, move_items, rename, ViewTarget, set_flags, locate_in_services, \
|
||||
scroll_to, get_base_model, update_picons_data, copy_picon_reference, assign_picon, remove_picon, \
|
||||
@@ -151,9 +151,9 @@ class Application(Gtk.Application):
|
||||
"on_create_bouquet_for_current_type": self.on_create_bouquet_for_current_type,
|
||||
"on_create_bouquet_for_each_type": self.on_create_bouquet_for_each_type}
|
||||
|
||||
self._options = get_config()
|
||||
self._profile = self._options.get("profile")
|
||||
os.makedirs(os.path.dirname(self._options.get(self._profile).get("data_dir_path")), exist_ok=True)
|
||||
self._settings = Settings.get_instance()
|
||||
self._profile = self._settings.profile
|
||||
os.makedirs(os.path.dirname(self._settings.data_dir_path), exist_ok=True)
|
||||
# Used for copy/paste. When adding the previous data will not be deleted.
|
||||
# Clearing only after the insertion!
|
||||
self._rows_buffer = []
|
||||
@@ -184,12 +184,12 @@ class Application(Gtk.Application):
|
||||
builder = Gtk.Builder()
|
||||
builder.set_translation_domain("demon-editor")
|
||||
builder.add_from_file(UI_RESOURCES_PATH + "main_window.glade")
|
||||
builder.connect_signals(self._handlers)
|
||||
builder.connect_signals(handlers)
|
||||
self._main_window = builder.get_object("main_window")
|
||||
self._main_window_size = self._options.get("window_size", None)
|
||||
main_window_size = self._settings.get("window_size")
|
||||
# Setting the last size of the window if it was saved
|
||||
if self._main_window_size:
|
||||
self._main_window.resize(*self._main_window_size)
|
||||
if main_window_size:
|
||||
self._main_window.resize(*main_window_size)
|
||||
self._services_view = builder.get_object("services_tree_view")
|
||||
self._fav_view = builder.get_object("fav_tree_view")
|
||||
self._bouquets_view = builder.get_object("bouquets_tree_view")
|
||||
@@ -211,7 +211,7 @@ class Application(Gtk.Application):
|
||||
self._app_info_box.bind_property("visible", builder.get_object("toolbar_extra_item"), "visible", 4)
|
||||
# Status bar
|
||||
self._ip_label = builder.get_object("ip_label")
|
||||
self._ip_label.set_text(self._options.get(self._profile).get("host"))
|
||||
self._ip_label.set_text(self._settings.host)
|
||||
self._receiver_info_box = builder.get_object("receiver_info_box")
|
||||
self._receiver_info_label = builder.get_object("receiver_info_label")
|
||||
self._signal_box = builder.get_object("signal_box")
|
||||
@@ -332,7 +332,7 @@ class Application(Gtk.Application):
|
||||
|
||||
def do_shutdown(self):
|
||||
""" Performs shutdown tasks """
|
||||
write_config(self._options) # storing current config
|
||||
self._settings.save() # storing current config
|
||||
if self._player:
|
||||
self._player.release()
|
||||
Gtk.Application.do_shutdown(self)
|
||||
@@ -374,15 +374,12 @@ class Application(Gtk.Application):
|
||||
|
||||
If update=False - first call on program start, else - after options changes!
|
||||
"""
|
||||
profile = Profile(self._profile)
|
||||
if profile is Profile.ENIGMA_2:
|
||||
opts = self._options.get(self._profile)
|
||||
self._use_colors = opts.get("use_colors", False)
|
||||
if self._use_colors:
|
||||
if self._profile is Profile.ENIGMA_2:
|
||||
if self._settings.use_colors:
|
||||
new_rgb = Gdk.RGBA()
|
||||
extra_rgb = Gdk.RGBA()
|
||||
new_rgb = new_rgb if new_rgb.parse(opts.get("new_color", NEW_COLOR)) else None
|
||||
extra_rgb = extra_rgb if extra_rgb.parse(opts.get("extra_color", EXTRA_COLOR)) else None
|
||||
new_rgb = new_rgb if new_rgb.parse(self._settings.new_color) else None
|
||||
extra_rgb = extra_rgb if extra_rgb.parse(self._settings.extra_color) else None
|
||||
if update:
|
||||
gen = self.update_background_colors(new_rgb, extra_rgb)
|
||||
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
||||
@@ -419,7 +416,7 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_resize(self, window):
|
||||
""" Stores new size properties for app window after resize """
|
||||
self._options["window_size"] = window.get_size()
|
||||
self._settings.add("window_size", window.get_size())
|
||||
|
||||
@run_idle
|
||||
def on_about_app(self, action, value=None):
|
||||
@@ -608,7 +605,7 @@ class Application(Gtk.Application):
|
||||
# ***************** ####### *********************#
|
||||
|
||||
def get_bouquet_file_name(self, bouquet):
|
||||
bouquet_file_name = "{}userbouquet.{}.{}".format(self._options.get(self._profile).get("data_dir_path"),
|
||||
bouquet_file_name = "{}userbouquet.{}.{}".format(self._settings.get(self._profile).get("data_dir_path"),
|
||||
*bouquet.split(":"))
|
||||
return bouquet_file_name
|
||||
|
||||
@@ -836,19 +833,18 @@ class Application(Gtk.Application):
|
||||
@run_idle
|
||||
def on_satellite_editor_show(self, action, value):
|
||||
""" Shows satellites editor dialog """
|
||||
show_satellites_dialog(self._main_window, self._options.get(self._profile))
|
||||
show_satellites_dialog(self._main_window, self._settings)
|
||||
|
||||
def on_download(self, action, value):
|
||||
DownloadDialog(transient=self._main_window,
|
||||
properties=self._options,
|
||||
settings=self._settings,
|
||||
open_data_callback=self.open_data,
|
||||
update_settings_callback=self.update_options,
|
||||
profile=Profile(self._profile)).show()
|
||||
update_settings_callback=self.update_options).show()
|
||||
|
||||
@run_task
|
||||
def on_download_data(self):
|
||||
try:
|
||||
download_data(properties=self._options.get(self._profile),
|
||||
download_data(settings=self._settings,
|
||||
download_type=DownloadType.ALL,
|
||||
callback=lambda x: print(x, end=""))
|
||||
except Exception as e:
|
||||
@@ -859,22 +855,20 @@ class Application(Gtk.Application):
|
||||
@run_task
|
||||
def on_upload_data(self, download_type):
|
||||
try:
|
||||
profile = Profile(self._profile)
|
||||
opts = self._options.get(self._profile)
|
||||
profile = self._profile
|
||||
opts = self._settings
|
||||
use_http = profile is Profile.ENIGMA_2
|
||||
|
||||
if profile is Profile.ENIGMA_2:
|
||||
host, port = opts.get("host", "127.0.0.1"), opts.get("http_port")
|
||||
user, password = opts.get("http_user", "root"), opts.get("http_password", "")
|
||||
host, port, user, password = opts.host, opts.http_port, opts.http_user, opts.http_password
|
||||
try:
|
||||
test_http(host, port, user, password, skip_message=True)
|
||||
except TestException:
|
||||
use_http = False
|
||||
|
||||
upload_data(properties=opts,
|
||||
upload_data(settings=opts,
|
||||
download_type=download_type,
|
||||
remove_unused=True,
|
||||
profile=profile,
|
||||
callback=lambda x: print(x, end=""),
|
||||
use_http=use_http)
|
||||
except Exception as e:
|
||||
@@ -895,18 +889,17 @@ class Application(Gtk.Application):
|
||||
self._wait_dialog.show()
|
||||
yield True
|
||||
|
||||
profile = Profile(self._profile)
|
||||
data_path = self._options.get(self._profile).get("data_dir_path") if data_path is None else data_path
|
||||
|
||||
data_path = self._settings.data_dir_path if data_path is None else data_path
|
||||
yield from self.clear_current_data()
|
||||
|
||||
try:
|
||||
prf = self._profile
|
||||
black_list = get_blacklist(data_path)
|
||||
bouquets = get_bouquets(data_path, Profile(self._profile))
|
||||
bouquets = get_bouquets(data_path, prf)
|
||||
yield True
|
||||
services = get_services(data_path, profile, self.get_format_version() if profile is Profile.ENIGMA_2 else 0)
|
||||
services = get_services(data_path, prf, self.get_format_version() if prf is Profile.ENIGMA_2 else 0)
|
||||
yield True
|
||||
update_picons_data(self._options.get(self._profile).get("picons_dir_path"), self._picons)
|
||||
update_picons_data(self._settings.picons_dir_path, self._picons)
|
||||
yield True
|
||||
except FileNotFoundError as e:
|
||||
msg = get_message("Please, download files from receiver or setup your path for read data!")
|
||||
@@ -1046,12 +1039,12 @@ class Application(Gtk.Application):
|
||||
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
||||
|
||||
def save_data(self):
|
||||
profile = Profile(self._profile)
|
||||
options = self._options.get(self._profile)
|
||||
path = options.get("data_dir_path")
|
||||
backup_path = options.get("backup_dir_path", path + "backup/")
|
||||
self._save_header_button.set_sensitive(False)
|
||||
profile = self._profile
|
||||
path = self._settings.data_dir_path
|
||||
backup_path = self._settings.backup_dir_path
|
||||
# Backup data or clearing data path
|
||||
backup_data(path, backup_path) if options.get("backup_before_save", True) else clear_data_path(path)
|
||||
backup_data(path, backup_path) if self._settings.backup_before_save else clear_data_path(path)
|
||||
yield True
|
||||
|
||||
bouquets = []
|
||||
@@ -1096,7 +1089,7 @@ class Application(Gtk.Application):
|
||||
if show_dialog(DialogType.QUESTION, self._main_window) == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
gen = self.create_new_configuration(Profile(self._profile))
|
||||
gen = self.create_new_configuration(self._profile)
|
||||
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
||||
|
||||
def create_new_configuration(self, profile):
|
||||
@@ -1179,7 +1172,7 @@ class Application(Gtk.Application):
|
||||
self.show_error_dialog("Error. No bouquet is selected!")
|
||||
return
|
||||
|
||||
if Profile(self._profile) is Profile.NEUTRINO_MP and self._bq_selected.endswith(BqType.WEBTV.value):
|
||||
if self._profile is Profile.NEUTRINO_MP and self._bq_selected.endswith(BqType.WEBTV.value):
|
||||
self.show_error_dialog("Operation not allowed in this context!")
|
||||
return
|
||||
|
||||
@@ -1205,14 +1198,14 @@ class Application(Gtk.Application):
|
||||
v.get_selection().unselect_all()
|
||||
|
||||
def on_preferences(self, action, value):
|
||||
response = show_settings_dialog(self._main_window, self._options)
|
||||
response = show_settings_dialog(self._main_window, self._settings)
|
||||
if response != Gtk.ResponseType.CANCEL:
|
||||
gen = self.update_options()
|
||||
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
||||
|
||||
def update_options(self):
|
||||
profile = self._options.get("profile")
|
||||
self._ip_label.set_text(self._options.get(profile).get("host"))
|
||||
profile = self._settings.profile
|
||||
self._ip_label.set_text(self._settings.host)
|
||||
if profile != self._profile:
|
||||
yield from self.show_app_info(True)
|
||||
self._profile = profile
|
||||
@@ -1309,7 +1302,6 @@ class Application(Gtk.Application):
|
||||
self.update_bouquet_list()
|
||||
|
||||
def on_view_focus(self, view, focus_event=None):
|
||||
profile = Profile(self._profile)
|
||||
model_name, model = get_model_data(view)
|
||||
not_empty = len(model) > 0 # if > 0 model has items
|
||||
is_service = model_name == self._SERVICE_LIST_NAME
|
||||
@@ -1321,7 +1313,7 @@ class Application(Gtk.Application):
|
||||
self._tool_elements[elem].set_sensitive(not_empty)
|
||||
if elem == "bouquets_paste_popup_item":
|
||||
self._tool_elements[elem].set_sensitive(not_empty and self._bouquets_buffer)
|
||||
if profile is Profile.NEUTRINO_MP:
|
||||
if self._profile is Profile.NEUTRINO_MP:
|
||||
for elem in self._LOCK_HIDE_ELEMENTS:
|
||||
self._tool_elements[elem].set_sensitive(not_empty)
|
||||
else:
|
||||
@@ -1337,17 +1329,17 @@ class Application(Gtk.Application):
|
||||
for elem in self._BOUQUET_ELEMENTS:
|
||||
self._tool_elements[elem].set_sensitive(False)
|
||||
for elem in self._LOCK_HIDE_ELEMENTS:
|
||||
self._tool_elements[elem].set_sensitive(not_empty and profile is Profile.ENIGMA_2)
|
||||
self._tool_elements[elem].set_sensitive(not_empty and self._profile is Profile.ENIGMA_2)
|
||||
|
||||
for elem in self._FAV_IPTV_ELEMENTS:
|
||||
is_iptv = self._bq_selected and not is_service
|
||||
if profile is Profile.NEUTRINO_MP:
|
||||
if self._profile is Profile.NEUTRINO_MP:
|
||||
is_iptv = is_iptv and BqType(self._bq_selected.split(":")[1]) is BqType.WEBTV
|
||||
self._tool_elements[elem].set_sensitive(is_iptv)
|
||||
for elem in self._COMMONS_ELEMENTS:
|
||||
self._tool_elements[elem].set_sensitive(not_empty)
|
||||
|
||||
if profile is not Profile.ENIGMA_2:
|
||||
if self._profile is not Profile.ENIGMA_2:
|
||||
for elem in self._FAV_ENIGMA_ELEMENTS:
|
||||
self._tool_elements[elem].set_sensitive(False)
|
||||
|
||||
@@ -1358,11 +1350,9 @@ class Application(Gtk.Application):
|
||||
self.set_service_flags(Flag.LOCK)
|
||||
|
||||
def set_service_flags(self, flag):
|
||||
profile = Profile(self._profile)
|
||||
|
||||
if profile is Profile.ENIGMA_2:
|
||||
if self._profile is Profile.ENIGMA_2:
|
||||
set_flags(flag, self._services_view, self._fav_view, self._services, self._blacklist)
|
||||
elif profile is Profile.NEUTRINO_MP and self._bq_selected:
|
||||
elif self._profile is Profile.NEUTRINO_MP and self._bq_selected:
|
||||
model, paths = self._bouquets_view.get_selection().get_selected_rows()
|
||||
itr = model.get_iter(paths[0])
|
||||
value = model.get_value(itr, 1 if flag is Flag.LOCK else 2)
|
||||
@@ -1425,15 +1415,14 @@ class Application(Gtk.Application):
|
||||
self._fav_view,
|
||||
self._services,
|
||||
self._bouquets.get(self._bq_selected, None),
|
||||
Profile(self._profile),
|
||||
self._profile,
|
||||
Action.ADD).show()
|
||||
if response != Gtk.ResponseType.CANCEL:
|
||||
self.update_fav_num_column(self._fav_model)
|
||||
|
||||
@run_idle
|
||||
def on_iptv_list_configuration(self, action, value=None):
|
||||
profile = Profile(self._profile)
|
||||
if profile is Profile.NEUTRINO_MP:
|
||||
def on_iptv_list_configuration(self, action, value):
|
||||
if self._profile is Profile.NEUTRINO_MP:
|
||||
self.show_error_dialog("Neutrino at the moment not supported!")
|
||||
return
|
||||
|
||||
@@ -1446,7 +1435,8 @@ class Application(Gtk.Application):
|
||||
return
|
||||
|
||||
bq = self._bouquets.get(self._bq_selected, [])
|
||||
IptvListConfigurationDialog(self._main_window, self._services, iptv_rows, bq, self._fav_model, profile).show()
|
||||
IptvListConfigurationDialog(self._main_window, self._services, iptv_rows, bq,
|
||||
self._fav_model, self._profile).show()
|
||||
|
||||
@run_idle
|
||||
def on_remove_all_unavailable(self, action, value=None):
|
||||
@@ -1462,8 +1452,7 @@ class Application(Gtk.Application):
|
||||
return
|
||||
|
||||
fav_bqt = self._bouquets.get(self._bq_selected, None)
|
||||
prf = Profile(self._profile)
|
||||
response = SearchUnavailableDialog(self._main_window, self._fav_model, fav_bqt, iptv_rows, prf).show()
|
||||
response = SearchUnavailableDialog(self._main_window, self._fav_model, fav_bqt, iptv_rows, self._profile).show()
|
||||
if response:
|
||||
next(self.remove_favs(response, self._fav_model), False)
|
||||
|
||||
@@ -1471,7 +1460,7 @@ class Application(Gtk.Application):
|
||||
|
||||
@run_idle
|
||||
def on_epg_list_configuration(self, action, value=None):
|
||||
if Profile(self._profile) is not Profile.ENIGMA_2:
|
||||
if self._profile is not Profile.ENIGMA_2:
|
||||
self.show_error_dialog("Only Enigma2 is supported!")
|
||||
return
|
||||
|
||||
@@ -1480,8 +1469,7 @@ class Application(Gtk.Application):
|
||||
return
|
||||
|
||||
bq = self._bouquets.get(self._bq_selected)
|
||||
profile = self._options.get(self._profile)
|
||||
EpgDialog(self._main_window, profile, self._services, bq, self._fav_model, self._current_bq_name).show()
|
||||
EpgDialog(self._main_window, self._settings, self._services, bq, self._fav_model, self._current_bq_name).show()
|
||||
|
||||
# ***************** Import ********************#
|
||||
|
||||
@@ -1490,11 +1478,11 @@ class Application(Gtk.Application):
|
||||
if not self._bq_selected:
|
||||
return
|
||||
|
||||
YtListImportDialog(self._main_window, Profile(self._profile), self.append_imported_services).show()
|
||||
YtListImportDialog(self._main_window, self._profile, self.append_imported_services).show()
|
||||
|
||||
def on_import_m3u(self, action, value=None):
|
||||
""" Imports iptv from m3u files. """
|
||||
response = get_chooser_dialog(self._main_window, self._options.get(self._profile), "*.m3u", "m3u files")
|
||||
response = get_chooser_dialog(self._main_window, self._settings, "*.m3u", "m3u files")
|
||||
if response == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
@@ -1502,7 +1490,7 @@ class Application(Gtk.Application):
|
||||
self.show_error_dialog("No m3u file is selected!")
|
||||
return
|
||||
|
||||
channels = parse_m3u(response, Profile(self._profile))
|
||||
channels = parse_m3u(response, self._profile)
|
||||
|
||||
if channels and self._bq_selected:
|
||||
self.append_imported_services(channels)
|
||||
@@ -1527,31 +1515,29 @@ class Application(Gtk.Application):
|
||||
self.show_error_dialog("This list does not contains IPTV streams!")
|
||||
return
|
||||
|
||||
response = show_dialog(DialogType.CHOOSER, self._main_window, options=self._options.get(self._profile))
|
||||
response = show_dialog(DialogType.CHOOSER, self._main_window, settings=self._settings)
|
||||
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
return
|
||||
|
||||
try:
|
||||
bq = Bouquet(self._current_bq_name, None, bq_services, None, None)
|
||||
export_to_m3u(response, bq, Profile(self._profile))
|
||||
export_to_m3u(response, bq, self._profile)
|
||||
except Exception as e:
|
||||
self.show_error_dialog(str(e))
|
||||
else:
|
||||
show_dialog(DialogType.INFO, self._main_window, "Done!")
|
||||
|
||||
def on_import_bouquet(self, action, value=None):
|
||||
profile = Profile(self._profile)
|
||||
model, paths = self._bouquets_view.get_selection().get_selected_rows()
|
||||
if not paths:
|
||||
self.show_error_dialog("No selected item!")
|
||||
return
|
||||
|
||||
opts = self._options.get(self._profile)
|
||||
appender = self.append_bouquet if profile is Profile.ENIGMA_2 else self.append_bouquets
|
||||
import_bouquet(self._main_window, profile, model, paths[0], opts, self._services, appender)
|
||||
appender = self.append_bouquet if self._profile is Profile.ENIGMA_2 else self.append_bouquets
|
||||
import_bouquet(self._main_window, model, paths[0], self._settings, self._services, appender)
|
||||
|
||||
def on_import_bouquets(self, action, value=None):
|
||||
response = show_dialog(DialogType.CHOOSER, self._main_window, options=self._options.get(self._profile))
|
||||
response = show_dialog(DialogType.CHOOSER, self._main_window, settings=self._settings)
|
||||
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
return
|
||||
|
||||
@@ -1559,7 +1545,7 @@ class Application(Gtk.Application):
|
||||
gen = self.append_imported_data(b, s)
|
||||
GLib.idle_add(lambda: next(gen, False))
|
||||
|
||||
ImportDialog(self._main_window, response, Profile(self._profile), self._services.keys(), append).show()
|
||||
ImportDialog(self._main_window, response, self._settings, self._services.keys(), append).show()
|
||||
|
||||
def append_imported_data(self, bouquets, services):
|
||||
try:
|
||||
@@ -1570,12 +1556,9 @@ class Application(Gtk.Application):
|
||||
|
||||
# ***************** Backup ********************#
|
||||
|
||||
def on_backup_tool_show(self, action, value=None):
|
||||
def on_backup_tool_show(self, item):
|
||||
""" Shows backup tool dialog """
|
||||
BackupDialog(self._main_window,
|
||||
self._options,
|
||||
Profile(self._profile),
|
||||
self.open_data).show()
|
||||
BackupDialog(self._main_window, self._settings, self.open_data).show()
|
||||
|
||||
# ***************** Player *********************#
|
||||
|
||||
@@ -1591,7 +1574,7 @@ class Application(Gtk.Application):
|
||||
self.show_error_dialog("Not allowed in this context!")
|
||||
return
|
||||
|
||||
url = get_iptv_url(row, Profile(self._profile))
|
||||
url = get_iptv_url(row, self._profile)
|
||||
self.update_player_buttons()
|
||||
if not url:
|
||||
return
|
||||
@@ -1600,8 +1583,8 @@ class Application(Gtk.Application):
|
||||
def play(self, url):
|
||||
if not self._player:
|
||||
try:
|
||||
self._player = Player(rewind_callback=self.on_player_duration_changed,
|
||||
position_callback=self.on_player_time_changed)
|
||||
self._player = Player.get_instance(rewind_callback=self.on_player_duration_changed,
|
||||
position_callback=self.on_player_time_changed)
|
||||
except (NameError, AttributeError):
|
||||
self.show_error_dialog("No VLC is found. Check that it is installed!")
|
||||
return
|
||||
@@ -1638,8 +1621,7 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_player_close(self, item=None):
|
||||
if self._player:
|
||||
self._player.release()
|
||||
self._player = None
|
||||
self._player.stop()
|
||||
GLib.idle_add(self._player_box.set_visible, False, priority=GLib.PRIORITY_LOW)
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
@@ -1670,6 +1652,7 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_player_drawing_area_draw(self, widget, cr):
|
||||
""" Used for black background drawing in the player drawing area.
|
||||
|
||||
Required for Gtk >= 3.20.
|
||||
More info: https://developer.gnome.org/gtk3/stable/ch32s10.html,
|
||||
https://developer.gnome.org/gtk3/stable/GtkStyleContext.html#gtk-render-background
|
||||
@@ -1706,14 +1689,12 @@ class Application(Gtk.Application):
|
||||
|
||||
@run_task
|
||||
def init_http_api(self):
|
||||
prp = self._options.get(self._profile)
|
||||
profile = Profile(self._profile)
|
||||
self._fav_click_mode = FavClickMode(prp.get("fav_click_mode", FavClickMode.DISABLED))
|
||||
http_api_enable = prp.get("http_api_support", False)
|
||||
status = all((http_api_enable, profile is Profile.ENIGMA_2, not self._receiver_info_box.get_visible()))
|
||||
self._fav_click_mode = FavClickMode(self._settings.fav_click_mode)
|
||||
http_api_enable = self._settings.http_api_support
|
||||
status = all((http_api_enable, self._profile is Profile.ENIGMA_2, not self._receiver_info_box.get_visible()))
|
||||
GLib.idle_add(self._http_status_image.set_visible, status)
|
||||
|
||||
if profile is Profile.NEUTRINO_MP or not http_api_enable:
|
||||
if self._profile is Profile.NEUTRINO_MP or not http_api_enable:
|
||||
self.update_info_boxes_visible(False)
|
||||
if self._http_api:
|
||||
self._http_api.close()
|
||||
@@ -1722,12 +1703,12 @@ class Application(Gtk.Application):
|
||||
return
|
||||
|
||||
if not self._http_api:
|
||||
self._http_api = HttpAPI(prp.get("host", "127.0.0.1"), prp.get("http_port", "80"),
|
||||
prp.get("http_user", ""), prp.get("http_password", ""))
|
||||
self._http_api = HttpAPI(self._settings.host, self._settings.http_port,
|
||||
self._settings.http_user, self._settings.http_password)
|
||||
|
||||
GLib.timeout_add_seconds(3, self.update_info, priority=GLib.PRIORITY_LOW)
|
||||
|
||||
self.init_send_to(http_api_enable and prp.get("enable_send_to", False))
|
||||
self.init_send_to(http_api_enable and self._settings.enable_send_to)
|
||||
|
||||
@run_idle
|
||||
def init_send_to(self, enable):
|
||||
@@ -1836,22 +1817,26 @@ class Application(Gtk.Application):
|
||||
""" Updates positions values for the filtering function """
|
||||
self._sat_positions.clear()
|
||||
sat_positions = set()
|
||||
terrestrial = False
|
||||
cable = False
|
||||
|
||||
for srv in self._services.values():
|
||||
tr_type = srv.transponder_type
|
||||
if tr_type == "s" and srv.pos:
|
||||
sat_positions.add(float(srv.pos))
|
||||
elif tr_type == "t":
|
||||
terrestrial = True
|
||||
elif tr_type == "c":
|
||||
cable = True
|
||||
if self._profile is Profile.ENIGMA_2:
|
||||
terrestrial = False
|
||||
cable = False
|
||||
|
||||
if terrestrial:
|
||||
self._sat_positions.append("T")
|
||||
if cable:
|
||||
self._sat_positions.append("C")
|
||||
for srv in self._services.values():
|
||||
tr_type = srv.transponder_type
|
||||
if tr_type == "s" and srv.pos:
|
||||
sat_positions.add(float(srv.pos))
|
||||
elif tr_type == "t":
|
||||
terrestrial = True
|
||||
elif tr_type == "c":
|
||||
cable = True
|
||||
|
||||
if terrestrial:
|
||||
self._sat_positions.append("T")
|
||||
if cable:
|
||||
self._sat_positions.append("C")
|
||||
elif self._profile is Profile.NEUTRINO_MP:
|
||||
list(map(lambda s: sat_positions.add(float(s.pos)), filter(lambda s: s.pos, self._services.values())))
|
||||
|
||||
self._sat_positions.extend(map(str, sorted(sat_positions)))
|
||||
if self._filter_bar.is_visible():
|
||||
@@ -1929,12 +1914,12 @@ class Application(Gtk.Application):
|
||||
self._fav_view,
|
||||
self._services,
|
||||
self._bouquets.get(self._bq_selected, None),
|
||||
Profile(self._profile),
|
||||
self._profile,
|
||||
Action.EDIT).show()
|
||||
self.on_locate_in_services(view)
|
||||
|
||||
dialog = ServiceDetailsDialog(self._main_window,
|
||||
self._options,
|
||||
self._settings,
|
||||
self._services_view,
|
||||
self._fav_view,
|
||||
self._services,
|
||||
@@ -1944,7 +1929,7 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_services_add_new(self, item):
|
||||
dialog = ServiceDetailsDialog(self._main_window,
|
||||
self._options,
|
||||
self._settings,
|
||||
self._services_view,
|
||||
self._fav_view,
|
||||
self._services,
|
||||
@@ -2047,18 +2032,17 @@ class Application(Gtk.Application):
|
||||
@run_idle
|
||||
def on_picons_loader_show(self, action, value):
|
||||
ids = {}
|
||||
if Profile(self._profile) is Profile.ENIGMA_2:
|
||||
if self._profile is Profile.ENIGMA_2:
|
||||
for r in self._services_model:
|
||||
data = r[Column.SRV_PICON_ID].split("_")
|
||||
ids["{}:{}:{}".format(data[3], data[5], data[6])] = r[Column.SRV_PICON_ID]
|
||||
|
||||
dialog = PiconsDialog(self._main_window, self._options, ids, self._sat_positions, Profile(self._profile))
|
||||
dialog.show()
|
||||
PiconsDialog(self._main_window, self._settings, ids, self._sat_positions).show()
|
||||
self.update_picons()
|
||||
|
||||
@run_task
|
||||
def update_picons(self):
|
||||
update_picons_data(self._options.get(self._profile).get("picons_dir_path"), self._picons)
|
||||
update_picons_data(self._settings.picons_dir_path, self._picons)
|
||||
append_picons(self._picons, self._services_model)
|
||||
|
||||
def on_assign_picon(self, view):
|
||||
@@ -2067,14 +2051,14 @@ class Application(Gtk.Application):
|
||||
self._fav_view,
|
||||
self._main_window,
|
||||
self._picons,
|
||||
self._options.get(self._profile),
|
||||
self._settings,
|
||||
self._services)
|
||||
|
||||
def on_remove_picon(self, view):
|
||||
remove_picon(self.get_target_view(view),
|
||||
self._services_view,
|
||||
self._fav_view, self._picons,
|
||||
self._options.get(self._profile))
|
||||
self._settings)
|
||||
|
||||
def on_reference_picon(self, view):
|
||||
""" Copying picon id to clipboard """
|
||||
@@ -2084,7 +2068,7 @@ class Application(Gtk.Application):
|
||||
if show_dialog(DialogType.QUESTION, self._main_window) == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
remove_all_unused_picons(self._options.get(self._profile), self._picons, self._services.values())
|
||||
remove_all_unused_picons(self._settings, self._picons, self._services.values())
|
||||
|
||||
def get_target_view(self, view):
|
||||
return ViewTarget.SERVICES if Gtk.Buildable.get_name(view) == "services_tree_view" else ViewTarget.FAV
|
||||
@@ -2111,20 +2095,18 @@ class Application(Gtk.Application):
|
||||
|
||||
def create_bouquets(self, g_type):
|
||||
gen_bouquets(self._services_view, self._bouquets_view, self._main_window, g_type, self._TV_TYPES,
|
||||
Profile(self._profile), self.append_bouquet)
|
||||
self._profile, self.append_bouquet)
|
||||
|
||||
# ***************** Profile label *********************#
|
||||
|
||||
def update_profile_label(self):
|
||||
profile = Profile(self._profile)
|
||||
if profile is Profile.ENIGMA_2:
|
||||
ver = self.get_format_version()
|
||||
self._main_window.set_title("DemonEditor [{} Enigma2 v.{}]".format(get_message("Profile:"), ver))
|
||||
elif profile is Profile.NEUTRINO_MP:
|
||||
self._main_window.set_title("DemonEditor [{} Neutrino-MP]".format(get_message("Profile:")))
|
||||
if self._profile is Profile.ENIGMA_2:
|
||||
self._header_bar.set_subtitle("{} Enigma2 v.{}".format(get_message("Profile:"), self.get_format_version()))
|
||||
elif self._profile is Profile.NEUTRINO_MP:
|
||||
self._header_bar.set_subtitle("{} Neutrino-MP".format(get_message("Profile:")))
|
||||
|
||||
def get_format_version(self):
|
||||
return 5 if self._options.get(self._profile).get("v5_support", False) else 4
|
||||
return 5 if self._settings.v5_support else 4
|
||||
|
||||
@run_idle
|
||||
def update_info_boxes_visible(self, visible):
|
||||
|
||||
@@ -9,7 +9,7 @@ from app.commons import run_task
|
||||
from app.eparser import Service
|
||||
from app.eparser.ecommons import Flag, BouquetService, Bouquet, BqType
|
||||
from app.eparser.enigma.bouquets import BqServiceType, to_bouquet_id
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from .uicommons import ViewTarget, BqGenType, Gtk, Gdk, HIDE_ICON, LOCKED_ICON, KeyboardKey, Column
|
||||
from .dialogs import show_dialog, DialogType, get_chooser_dialog, WaitDialog
|
||||
|
||||
@@ -360,13 +360,13 @@ def append_picons(picons, model):
|
||||
GLib.idle_add(lambda: next(app, False), priority=GLib.PRIORITY_LOW)
|
||||
|
||||
|
||||
def assign_picon(target, srv_view, fav_view, transient, picons, options, services):
|
||||
def assign_picon(target, srv_view, fav_view, transient, picons, settings, 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
|
||||
|
||||
response = get_chooser_dialog(transient, options, "*.png", "png files")
|
||||
response = get_chooser_dialog(transient, settings, "*.png", "png files")
|
||||
if response == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
@@ -381,8 +381,10 @@ def assign_picon(target, srv_view, fav_view, transient, picons, options, service
|
||||
picon_id = services.get(fav_id)[Column.SRV_PICON_ID]
|
||||
|
||||
if picon_id:
|
||||
picon_file = options.get("picons_dir_path") + picon_id
|
||||
if os.path.isfile(response):
|
||||
picons_path = settings.picons_dir_path
|
||||
os.makedirs(os.path.dirname(picons_path), exist_ok=True)
|
||||
picon_file = picons_path + picon_id
|
||||
shutil.copy(response, picon_file)
|
||||
picon = get_picon_pixbuf(picon_file)
|
||||
picons[picon_id] = picon
|
||||
@@ -400,7 +402,7 @@ def set_picon(fav_id, model, picon, fav_id_pos, picon_pos):
|
||||
break
|
||||
|
||||
|
||||
def remove_picon(target, srv_view, fav_view, picons, options):
|
||||
def remove_picon(target, srv_view, fav_view, picons, settings):
|
||||
view = srv_view if target is ViewTarget.SERVICES else fav_view
|
||||
model, paths = view.get_selection().get_selected_rows()
|
||||
model = get_base_model(model)
|
||||
@@ -431,7 +433,7 @@ def remove_picon(target, srv_view, fav_view, picons, options):
|
||||
fav_view.get_model().foreach(remove) if target is ViewTarget.SERVICES else get_base_model(
|
||||
srv_view.get_model()).foreach(remove)
|
||||
|
||||
remove_picons(options, picon_ids, picons)
|
||||
remove_picons(settings, picon_ids, picons)
|
||||
|
||||
|
||||
def copy_picon_reference(target, view, services, clipboard, transient):
|
||||
@@ -455,15 +457,15 @@ def copy_picon_reference(target, view, services, clipboard, transient):
|
||||
show_dialog(DialogType.ERROR, transient, "No reference is present!")
|
||||
|
||||
|
||||
def remove_all_unused_picons(options, picons, services):
|
||||
def remove_all_unused_picons(settings, picons, services):
|
||||
ids = {s.picon_id for s in services}
|
||||
pcs = list(filter(lambda x: x not in ids, picons))
|
||||
remove_picons(options, pcs, picons)
|
||||
remove_picons(settings, pcs, picons)
|
||||
|
||||
|
||||
def remove_picons(options, picon_ids, picons):
|
||||
pions_path = options.get("picons_dir_path")
|
||||
backup_path = options.get("backup_dir_path") + "picons/"
|
||||
def remove_picons(settings, picon_ids, picons):
|
||||
pions_path = settings.picons_dir_path
|
||||
backup_path = settings.backup_dir_path + "picons/"
|
||||
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
||||
for p_id in picon_ids:
|
||||
picons[p_id] = None
|
||||
@@ -550,9 +552,9 @@ def get_bouquets_names(model):
|
||||
|
||||
# ***************** Others *********************#
|
||||
|
||||
def update_entry_data(entry, dialog, options):
|
||||
def update_entry_data(entry, dialog, settings):
|
||||
""" Updates value in text entry from chooser dialog """
|
||||
response = show_dialog(dialog_type=DialogType.CHOOSER, transient=dialog, options=options)
|
||||
response = show_dialog(dialog_type=DialogType.CHOOSER, transient=dialog, settings=settings)
|
||||
if response not in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
entry.set_text(response)
|
||||
return response
|
||||
|
||||
@@ -9,7 +9,7 @@ from gi.repository import GLib, GdkPixbuf
|
||||
from app.commons import run_idle, run_task
|
||||
from app.connections import upload_data, DownloadType
|
||||
from app.tools.picons import PiconsParser, parse_providers, Provider, convert_to
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from app.tools.satellites import SatellitesParser, SatelliteSource
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TEXT_DOMAIN, TV_ICON
|
||||
from .dialogs import show_dialog, DialogType, get_message
|
||||
@@ -17,7 +17,7 @@ from .main_helper import update_entry_data, append_text_to_tview, scroll_to, on_
|
||||
|
||||
|
||||
class PiconsDialog:
|
||||
def __init__(self, transient, options, picon_ids, sat_positions, profile=Profile.ENIGMA_2):
|
||||
def __init__(self, transient, settings, picon_ids, sat_positions):
|
||||
self._picon_ids = picon_ids
|
||||
self._sat_positions = sat_positions
|
||||
self._TMP_DIR = tempfile.gettempdir() + "/"
|
||||
@@ -85,16 +85,13 @@ class PiconsDialog:
|
||||
self._style_provider.load_from_path(UI_RESOURCES_PATH + "style.css")
|
||||
self._url_entry.get_style_context().add_provider_for_screen(Gdk.Screen.get_default(), self._style_provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
self._properties = options.get(profile.value)
|
||||
self._profile = profile
|
||||
self._ip_entry.set_text(self._properties.get("host", ""))
|
||||
self._picons_entry.set_text(self._properties.get("picons_path", ""))
|
||||
self._picons_path = self._properties.get("picons_dir_path", "")
|
||||
self._settings = settings
|
||||
self._profile = settings.profile
|
||||
self._ip_entry.set_text(self._settings.host)
|
||||
self._picons_entry.set_text(self._settings.picons_path)
|
||||
self._picons_path = self._settings.picons_dir_path
|
||||
self._picons_dir_entry.set_text(self._picons_path)
|
||||
self._enigma2_picons_path = self._picons_path
|
||||
|
||||
if profile is Profile.NEUTRINO_MP:
|
||||
self._enigma2_picons_path = options.get(Profile.ENIGMA_2.value).get("picons_dir_path", "")
|
||||
if not len(self._picon_ids) and self._profile is Profile.ENIGMA_2:
|
||||
message = get_message("To automatically set the identifiers for picons,\n"
|
||||
"first load the required services list into the main application window.")
|
||||
@@ -280,9 +277,8 @@ class PiconsDialog:
|
||||
|
||||
try:
|
||||
GLib.idle_add(self._expander.set_expanded, True)
|
||||
upload_data(properties=self._properties,
|
||||
upload_data(settings=self._settings,
|
||||
download_type=DownloadType.PICONS,
|
||||
profile=self._profile,
|
||||
callback=self.append_output,
|
||||
done_callback=lambda: self.show_info_message(get_message("Done!"), Gtk.MessageType.INFO))
|
||||
except OSError as e:
|
||||
@@ -298,7 +294,7 @@ class PiconsDialog:
|
||||
self._message_label.set_text(text)
|
||||
|
||||
def on_picons_dir_open(self, entry, icon, event_button):
|
||||
update_entry_data(entry, self._dialog, options={"data_dir_path": self._picons_path})
|
||||
update_entry_data(entry, self._dialog, settings=self._settings)
|
||||
|
||||
@run_idle
|
||||
def on_selected_toggled(self, toggle, path):
|
||||
@@ -332,9 +328,6 @@ class PiconsDialog:
|
||||
self._convert_button.set_visible(tab_num)
|
||||
self._send_button.set_visible(not tab_num)
|
||||
|
||||
if self._enigma2_path_button.get_filename() is None:
|
||||
self._enigma2_path_button.set_current_folder(self._enigma2_picons_path)
|
||||
|
||||
@run_idle
|
||||
def on_convert(self, item):
|
||||
if show_dialog(DialogType.QUESTION, self._dialog) == Gtk.ResponseType.CANCEL:
|
||||
|
||||
@@ -24,9 +24,9 @@ def show_satellites_dialog(transient, options):
|
||||
class SatellitesDialog:
|
||||
_aggr = [None for x in range(9)] # aggregate
|
||||
|
||||
def __init__(self, transient, options):
|
||||
self._data_path = options.get("data_dir_path") + "satellites.xml"
|
||||
self._options = options
|
||||
def __init__(self, transient, settings):
|
||||
self._data_path = settings.data_dir_path + "satellites.xml"
|
||||
self._settings = settings
|
||||
|
||||
handlers = {"on_open": self.on_open,
|
||||
"on_remove": self.on_remove,
|
||||
@@ -55,7 +55,7 @@ class SatellitesDialog:
|
||||
self._window.set_transient_for(transient)
|
||||
self._sat_view = builder.get_object("satellites_editor_tree_view")
|
||||
# Setting the last size of the dialog window if it was saved
|
||||
window_size = self._options.get("sat_editor_window_size", None)
|
||||
window_size = self._settings.get("sat_editor_window_size")
|
||||
if window_size:
|
||||
self._window.resize(*window_size)
|
||||
|
||||
@@ -75,8 +75,8 @@ class SatellitesDialog:
|
||||
|
||||
def on_resize(self, window):
|
||||
""" Stores new size properties for dialog window after resize """
|
||||
if self._options:
|
||||
self._options["sat_editor_window_size"] = window.get_size()
|
||||
if self._settings:
|
||||
self._settings.add("sat_editor_window_size", window.get_size())
|
||||
|
||||
@run_idle
|
||||
def on_quit(self, *args):
|
||||
@@ -100,7 +100,7 @@ class SatellitesDialog:
|
||||
file_filter.set_name("satellites.xml")
|
||||
response = show_dialog(dialog_type=DialogType.CHOOSER,
|
||||
transient=self._window,
|
||||
options=self._options,
|
||||
settings=self._settings,
|
||||
action_type=action,
|
||||
file_filter=file_filter)
|
||||
return response
|
||||
|
||||
@@ -6,7 +6,7 @@ from app.eparser import Service
|
||||
from app.eparser.ecommons import MODULATION, Inversion, ROLL_OFF, Pilot, Flag, Pids, POLARIZATION, \
|
||||
get_key_by_value, get_value_by_name, FEC_DEFAULT, PLS_MODE, SERVICE_TYPE, T_MODULATION, C_MODULATION, TrType, \
|
||||
SystemCable, T_SYSTEM, BANDWIDTH, TRANSMISSION_MODE, GUARD_INTERVAL, HIERARCHY, T_FEC
|
||||
from app.properties import Profile
|
||||
from app.settings import Profile
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, HIDE_ICON, TEXT_DOMAIN, CODED_ICON, Column, IS_GNOME_SESSION
|
||||
from .dialogs import show_dialog, DialogType, Action, get_dialogs_string
|
||||
from .main_helper import get_base_model
|
||||
@@ -34,7 +34,7 @@ class ServiceDetailsDialog:
|
||||
|
||||
_DIGIT_ENTRY_NAME = "digit-entry"
|
||||
|
||||
def __init__(self, transient, options, srv_view, fav_view, services, bouquets, new_color, action=Action.EDIT):
|
||||
def __init__(self, transient, settings, srv_view, fav_view, services, bouquets, new_color, action=Action.EDIT):
|
||||
handlers = {"on_system_changed": self.on_system_changed,
|
||||
"on_save": self.on_save,
|
||||
"on_create_new": self.on_create_new,
|
||||
@@ -52,10 +52,10 @@ class ServiceDetailsDialog:
|
||||
|
||||
self._dialog = builder.get_object("service_details_dialog")
|
||||
self._dialog.set_transient_for(transient)
|
||||
self._profile = Profile(options["profile"])
|
||||
self._profile = settings.profile
|
||||
self._tr_type = None
|
||||
self._satellites_xml_path = options.get(self._profile.value)["data_dir_path"] + "satellites.xml"
|
||||
self._picons_dir_path = options.get(self._profile.value)["picons_dir_path"]
|
||||
self._satellites_xml_path = settings.data_dir_path + "satellites.xml"
|
||||
self._picons_dir_path = settings.picons_dir_path
|
||||
self._services_view = srv_view
|
||||
self._fav_view = fav_view
|
||||
self._action = action
|
||||
|
||||
@@ -2,8 +2,8 @@ from enum import Enum
|
||||
|
||||
from app.commons import run_task, run_idle
|
||||
from app.connections import test_telnet, test_ftp, TestException, test_http
|
||||
from app.properties import write_config, Profile, get_default_settings
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TEXT_DOMAIN, NEW_COLOR, EXTRA_COLOR, FavClickMode
|
||||
from app.settings import Profile
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TEXT_DOMAIN, FavClickMode
|
||||
from .main_helper import update_entry_data
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class Property(Enum):
|
||||
|
||||
class SettingsDialog:
|
||||
|
||||
def __init__(self, transient, options):
|
||||
def __init__(self, transient, settings):
|
||||
handlers = {"on_field_icon_press": self.on_field_icon_press,
|
||||
"on_profile_changed": self.on_profile_changed,
|
||||
"on_reset": self.on_reset,
|
||||
@@ -89,11 +89,11 @@ class SettingsDialog:
|
||||
self._click_mode_zap_button.bind_property("sensitive", self._enable_send_to_switch, "sensitive")
|
||||
self._enable_send_to_switch.bind_property("sensitive", builder.get_object("enable_send_to_label"), "sensitive")
|
||||
self._extra_support_grid.bind_property("sensitive", builder.get_object("v5_support_grid"), "sensitive")
|
||||
# Options
|
||||
self._options = options
|
||||
self._active_profile = options.get("profile")
|
||||
# Settings
|
||||
self._settings = settings
|
||||
self._active_profile = settings.profile
|
||||
self.set_settings()
|
||||
self.init_ui_elements(Profile(self._active_profile))
|
||||
self.init_ui_elements(self._active_profile)
|
||||
|
||||
def init_ui_elements(self, profile):
|
||||
is_enigma_profile = profile is Profile.ENIGMA_2
|
||||
@@ -115,106 +115,90 @@ class SettingsDialog:
|
||||
return response
|
||||
|
||||
def on_field_icon_press(self, entry, icon, event_button):
|
||||
update_entry_data(entry, self._dialog, self._options.get(self._options.get("profile")))
|
||||
update_entry_data(entry, self._dialog, self._settings)
|
||||
|
||||
def on_profile_changed(self, item):
|
||||
profile = Profile.ENIGMA_2 if self._enigma_radio_button.get_active() else Profile.NEUTRINO_MP
|
||||
self._active_profile = profile.value
|
||||
self._active_profile = profile
|
||||
self._settings.profile = profile
|
||||
self.set_settings()
|
||||
self.init_ui_elements(profile)
|
||||
|
||||
def set_profile(self, profile):
|
||||
self._active_profile = profile.value
|
||||
self.set_settings()
|
||||
|
||||
def on_reset(self, item):
|
||||
def_settings = get_default_settings()
|
||||
for key in def_settings:
|
||||
current = self._options.get(key)
|
||||
if type(current) is str:
|
||||
continue
|
||||
default = def_settings.get(key)
|
||||
for k in default:
|
||||
current[k] = default.get(k)
|
||||
self._settings.reset()
|
||||
self.set_settings()
|
||||
|
||||
def set_settings(self):
|
||||
def_settings = get_default_settings().get(self._active_profile)
|
||||
options = self._options.get(self._active_profile)
|
||||
self._host_field.set_text(self._settings.host)
|
||||
self._port_field.set_text(self._settings.port)
|
||||
self._login_field.set_text(self._settings.user)
|
||||
self._password_field.set_text(self._settings.password)
|
||||
self._http_login_field.set_text(self._settings.http_user)
|
||||
self._http_password_field.set_text(self._settings.http_password)
|
||||
self._http_port_field.set_text(self._settings.http_port)
|
||||
self._telnet_login_field.set_text(self._settings.telnet_user)
|
||||
self._telnet_password_field.set_text(self._settings.telnet_password)
|
||||
self._telnet_port_field.set_text(self._settings.telnet_port)
|
||||
self._telnet_timeout_spin_button.set_value(self._settings.telnet_timeout)
|
||||
self._services_field.set_text(self._settings.services_path)
|
||||
self._user_bouquet_field.set_text(self._settings.user_bouquet_path)
|
||||
self._satellites_xml_field.set_text(self._settings.satellites_xml_path)
|
||||
self._picons_field.set_text(self._settings.picons_path)
|
||||
self._data_dir_field.set_text(self._settings.data_dir_path)
|
||||
self._picons_dir_field.set_text(self._settings.picons_dir_path)
|
||||
self._backup_dir_field.set_text(self._settings.backup_dir_path)
|
||||
self._before_save_switch.set_active(self._settings.backup_before_save)
|
||||
self._before_downloading_switch.set_active(self._settings.backup_before_downloading)
|
||||
self.set_fav_click_mode(self._settings.fav_click_mode)
|
||||
|
||||
self._host_field.set_text(options.get("host", def_settings["host"]))
|
||||
self._port_field.set_text(options.get("port", def_settings["port"]))
|
||||
self._login_field.set_text(options.get("user", def_settings["user"]))
|
||||
self._password_field.set_text(options.get("password", def_settings["password"]))
|
||||
self._http_login_field.set_text(options.get("http_user", def_settings["http_user"]))
|
||||
self._http_password_field.set_text(options.get("http_password", def_settings["http_password"]))
|
||||
self._http_port_field.set_text(options.get("http_port", def_settings["http_port"]))
|
||||
self._telnet_login_field.set_text(options.get("telnet_user", def_settings["telnet_user"]))
|
||||
self._telnet_password_field.set_text(options.get("telnet_password", def_settings["telnet_password"]))
|
||||
self._telnet_port_field.set_text(options.get("telnet_port", def_settings["telnet_port"]))
|
||||
self._telnet_timeout_spin_button.set_value(options.get("telnet_timeout", def_settings["telnet_timeout"]))
|
||||
self._services_field.set_text(options.get("services_path", def_settings["services_path"]))
|
||||
self._user_bouquet_field.set_text(options.get("user_bouquet_path", def_settings["user_bouquet_path"]))
|
||||
self._satellites_xml_field.set_text(options.get("satellites_xml_path", def_settings["satellites_xml_path"]))
|
||||
self._picons_field.set_text(options.get("picons_path", def_settings["picons_path"]))
|
||||
self._data_dir_field.set_text(options.get("data_dir_path", def_settings["data_dir_path"]))
|
||||
self._picons_dir_field.set_text(options.get("picons_dir_path", def_settings["picons_dir_path"]))
|
||||
self._backup_dir_field.set_text(options.get("backup_dir_path", def_settings["backup_dir_path"]))
|
||||
self._before_save_switch.set_active(options.get("backup_before_save", def_settings["backup_before_save"]))
|
||||
self._before_downloading_switch.set_active(options.get("backup_before_downloading",
|
||||
def_settings["backup_before_downloading"]))
|
||||
self.set_fav_click_mode(options.get("fav_click_mode", def_settings["fav_click_mode"]))
|
||||
|
||||
if Profile(self._active_profile) is Profile.ENIGMA_2:
|
||||
self._support_ver5_switch.set_active(options.get("v5_support", False))
|
||||
self._support_http_api_switch.set_active(options.get("http_api_support", False))
|
||||
self._enable_y_dl_switch.set_active(options.get("enable_yt_dl", False))
|
||||
self._enable_send_to_switch.set_active(options.get("enable_send_to", False))
|
||||
self._set_color_switch.set_active(options.get("use_colors", False))
|
||||
if self._active_profile is Profile.ENIGMA_2:
|
||||
self._support_ver5_switch.set_active(self._settings.v5_support)
|
||||
self._support_http_api_switch.set_active(self._settings.http_api_support)
|
||||
self._enable_y_dl_switch.set_active(self._settings.enable_yt_dl)
|
||||
self._enable_send_to_switch.set_active(self._settings.enable_send_to)
|
||||
self._set_color_switch.set_active(self._settings.use_colors)
|
||||
new_rgb = Gdk.RGBA()
|
||||
new_rgb.parse(options.get("new_color", NEW_COLOR))
|
||||
new_rgb.parse(self._settings.new_color)
|
||||
extra_rgb = Gdk.RGBA()
|
||||
extra_rgb.parse(options.get("extra_color", EXTRA_COLOR))
|
||||
extra_rgb.parse(self._settings.extra_color)
|
||||
self._new_color_button.set_rgba(new_rgb)
|
||||
self._extra_color_button.set_rgba(extra_rgb)
|
||||
|
||||
def apply_settings(self, item=None):
|
||||
profile = Profile.ENIGMA_2 if self._enigma_radio_button.get_active() else Profile.NEUTRINO_MP
|
||||
self._active_profile = profile.value
|
||||
self._options["profile"] = self._active_profile
|
||||
options = self._options.get(self._active_profile)
|
||||
options["host"] = self._host_field.get_text()
|
||||
options["port"] = self._port_field.get_text()
|
||||
options["user"] = self._login_field.get_text()
|
||||
options["password"] = self._password_field.get_text()
|
||||
options["http_user"] = self._http_login_field.get_text()
|
||||
options["http_password"] = self._http_password_field.get_text()
|
||||
options["http_port"] = self._http_port_field.get_text()
|
||||
options["telnet_user"] = self._telnet_login_field.get_text()
|
||||
options["telnet_password"] = self._telnet_password_field.get_text()
|
||||
options["telnet_port"] = self._telnet_port_field.get_text()
|
||||
options["telnet_timeout"] = int(self._telnet_timeout_spin_button.get_value())
|
||||
options["services_path"] = self._services_field.get_text()
|
||||
options["user_bouquet_path"] = self._user_bouquet_field.get_text()
|
||||
options["satellites_xml_path"] = self._satellites_xml_field.get_text()
|
||||
options["picons_path"] = self._picons_field.get_text()
|
||||
options["data_dir_path"] = self._data_dir_field.get_text()
|
||||
options["picons_dir_path"] = self._picons_dir_field.get_text()
|
||||
options["backup_dir_path"] = self._backup_dir_field.get_text()
|
||||
options["backup_before_save"] = self._before_save_switch.get_active()
|
||||
options["backup_before_downloading"] = self._before_downloading_switch.get_active()
|
||||
options["fav_click_mode"] = self.get_fav_click_mode()
|
||||
self._active_profile = Profile.ENIGMA_2 if self._enigma_radio_button.get_active() else Profile.NEUTRINO_MP
|
||||
self._settings.profile = self._active_profile
|
||||
self._settings.host = self._host_field.get_text()
|
||||
self._settings.port = self._port_field.get_text()
|
||||
self._settings.user = self._login_field.get_text()
|
||||
self._settings.password = self._password_field.get_text()
|
||||
self._settings.http_user = self._http_login_field.get_text()
|
||||
self._settings.http_password = self._http_password_field.get_text()
|
||||
self._settings.http_port = self._http_port_field.get_text()
|
||||
self._settings.telnet_user = self._telnet_login_field.get_text()
|
||||
self._settings.telnet_password = self._telnet_password_field.get_text()
|
||||
self._settings.telnet_port = self._telnet_port_field.get_text()
|
||||
self._settings.telnet_timeout = int(self._telnet_timeout_spin_button.get_value())
|
||||
self._settings.services_path = self._services_field.get_text()
|
||||
self._settings.user_bouquet_path = self._user_bouquet_field.get_text()
|
||||
self._settings.satellites_xml_path = self._satellites_xml_field.get_text()
|
||||
self._settings.picons_path = self._picons_field.get_text()
|
||||
self._settings.data_dir_path = self._data_dir_field.get_text()
|
||||
self._settings.picons_dir_path = self._picons_dir_field.get_text()
|
||||
self._settings.backup_dir_path = self._backup_dir_field.get_text()
|
||||
self._settings.backup_before_save = self._before_save_switch.get_active()
|
||||
self._settings.backup_before_downloading = self._before_downloading_switch.get_active()
|
||||
self._settings.fav_click_mode = self.get_fav_click_mode()
|
||||
|
||||
if profile is Profile.ENIGMA_2:
|
||||
options["use_colors"] = self._set_color_switch.get_active()
|
||||
options["new_color"] = self._new_color_button.get_rgba().to_string()
|
||||
options["extra_color"] = self._extra_color_button.get_rgba().to_string()
|
||||
options["v5_support"] = self._support_ver5_switch.get_active()
|
||||
options["http_api_support"] = self._support_http_api_switch.get_active()
|
||||
options["enable_yt_dl"] = self._enable_y_dl_switch.get_active()
|
||||
options["enable_send_to"] = self._enable_send_to_switch.get_active()
|
||||
if self._active_profile is Profile.ENIGMA_2:
|
||||
self._settings.use_colors = self._set_color_switch.get_active()
|
||||
self._settings.new_color = self._new_color_button.get_rgba().to_string()
|
||||
self._settings.extra_color = self._extra_color_button.get_rgba().to_string()
|
||||
self._settings.v5_support = self._support_ver5_switch.get_active()
|
||||
self._settings.http_api_support = self._support_http_api_switch.get_active()
|
||||
self._settings.enable_yt_dl = self._enable_y_dl_switch.get_active()
|
||||
self._settings.enable_send_to = self._enable_send_to_switch.get_active()
|
||||
|
||||
write_config(self._options)
|
||||
self._settings.save()
|
||||
|
||||
@run_task
|
||||
def on_connection_test(self, item):
|
||||
|
||||
@@ -2,6 +2,7 @@ from urllib.parse import urlparse
|
||||
from gi.repository import GLib
|
||||
from app.connections import HttpRequestType
|
||||
from app.tools.yt import YouTube
|
||||
from app.ui.iptv import get_yt_icon
|
||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, TEXT_DOMAIN
|
||||
|
||||
|
||||
@@ -70,7 +71,7 @@ class LinksTransmitter:
|
||||
yield True
|
||||
|
||||
if yt_id:
|
||||
self._url_entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, Gtk.STOCK_INFO)
|
||||
self._url_entry.set_icon_from_pixbuf(Gtk.EntryIconPosition.SECONDARY, get_yt_icon("youtube", 32))
|
||||
links, title = YouTube.get_yt_link(yt_id)
|
||||
yield True
|
||||
if links:
|
||||
|
||||
@@ -27,10 +27,6 @@ TV_ICON = theme.load_icon("tv-symbolic", 16, 0) if theme.lookup_icon("tv-symboli
|
||||
IPTV_ICON = theme.load_icon("emblem-shared", 16, 0) if theme.lookup_icon("emblem-shared", 16, 0) else None
|
||||
EPG_ICON = theme.load_icon("gtk-index", 16, 0) if theme.lookup_icon("gtk-index", 16, 0) else None
|
||||
|
||||
# Colors
|
||||
NEW_COLOR = "rgb(255,230,204)" # Color for new services in the main list
|
||||
EXTRA_COLOR = "rgb(179,230,204)" # Color for services with a extra name for the bouquet
|
||||
|
||||
|
||||
class KeyboardKey(Enum):
|
||||
""" The raw(hardware) codes of the keyboard keys. """
|
||||
|
||||
BIN
deb/usr/share/locale/es/LC_MESSAGES/demon-editor.mo
Normal file
BIN
deb/usr/share/locale/es/LC_MESSAGES/demon-editor.mo
Normal file
Binary file not shown.
@@ -57,16 +57,16 @@ msgid "Assign"
|
||||
msgstr "Assignar"
|
||||
|
||||
msgid "Bouquet details"
|
||||
msgstr "Detalles Ramo"
|
||||
msgstr "Detalles bouquet"
|
||||
|
||||
msgid "Bouquets"
|
||||
msgstr "Ramos"
|
||||
msgstr "Bouquets"
|
||||
|
||||
msgid "Copy"
|
||||
msgstr "Copiar"
|
||||
|
||||
msgid "Copy reference"
|
||||
msgstr "Copia de Referencia"
|
||||
msgstr "Copia de referencia"
|
||||
|
||||
msgid "Download"
|
||||
msgstr "Descargar"
|
||||
@@ -78,7 +78,7 @@ msgid "Edit mаrker text"
|
||||
msgstr "Editar texto del mаrcador"
|
||||
|
||||
msgid "FTP-transfer"
|
||||
msgstr "Transferencia-FTP"
|
||||
msgstr "Transferencia FTP"
|
||||
|
||||
msgid "Global search"
|
||||
msgstr "Búsqueda Global"
|
||||
@@ -99,10 +99,10 @@ msgid "Import m3u file"
|
||||
msgstr "Importar fichero m3u"
|
||||
|
||||
msgid "List configuration"
|
||||
msgstr "Lista configuración"
|
||||
msgstr "Listar configuración"
|
||||
|
||||
msgid "Rename for this bouquet"
|
||||
msgstr "Renombrar para este ramo"
|
||||
msgstr "Renombrar para este bouquet"
|
||||
|
||||
msgid "Set default name"
|
||||
msgstr "Establecer nombre predeterminado"
|
||||
@@ -114,7 +114,7 @@ msgid "Locate in services"
|
||||
msgstr "Buscar en servicios"
|
||||
|
||||
msgid "Locked"
|
||||
msgstr "Cerrado"
|
||||
msgstr "Bloqueado"
|
||||
|
||||
msgid "Move"
|
||||
msgstr "Mover"
|
||||
@@ -123,13 +123,13 @@ msgid "New"
|
||||
msgstr "Nuevo"
|
||||
|
||||
msgid "New bouquet"
|
||||
msgstr "Ramo nuevo"
|
||||
msgstr "Bouquet nuevo"
|
||||
|
||||
msgid "Create bouquet"
|
||||
msgstr "Crear ramo"
|
||||
msgstr "Crear bouquet"
|
||||
|
||||
msgid "For current satellite"
|
||||
msgstr "Para el Satélite actual"
|
||||
msgstr "Para el satélite actual"
|
||||
|
||||
msgid "For current package"
|
||||
msgstr "Para el paquete actual"
|
||||
@@ -138,7 +138,7 @@ msgid "For current type"
|
||||
msgstr "Para el tipo actual"
|
||||
|
||||
msgid "For each satellite"
|
||||
msgstr "Para cada Satélite"
|
||||
msgstr "Para cada satélite"
|
||||
|
||||
msgid "For each package"
|
||||
msgstr "Para cada paquete"
|
||||
@@ -150,25 +150,25 @@ msgid "Open"
|
||||
msgstr "Abrir"
|
||||
|
||||
msgid "Parent lock On/Off Ctrl + L"
|
||||
msgstr "Bloqueo parentesco Encender/Apagar Ctrl + L"
|
||||
msgstr "Bloqueo parental Encender/Apagar Ctrl + L"
|
||||
|
||||
msgid "Picons"
|
||||
msgstr "Picons"
|
||||
|
||||
msgid "Picons downloader"
|
||||
msgstr "Picons descargar"
|
||||
msgstr "Descargar picons"
|
||||
|
||||
msgid "Satellites downloader"
|
||||
msgstr "Satélites descargar"
|
||||
msgstr "Descargar satélites"
|
||||
|
||||
msgid "Remove"
|
||||
msgstr "Remover"
|
||||
msgstr "Quitar"
|
||||
|
||||
msgid "Remove all unavailable"
|
||||
msgstr "Remover todo lo indisponible"
|
||||
msgstr "Quitar todo lo indisponible"
|
||||
|
||||
msgid "Satellites editor"
|
||||
msgstr "Editor Satélites"
|
||||
msgstr "Editor de satélites"
|
||||
|
||||
msgid "Save"
|
||||
msgstr "Guardar"
|
||||
@@ -183,7 +183,7 @@ msgid "Services filter"
|
||||
msgstr "Filtro servicios"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Configuraciones"
|
||||
msgstr "Configuración"
|
||||
|
||||
msgid "Up"
|
||||
msgstr "Arriba"
|
||||
@@ -198,7 +198,7 @@ msgid "All"
|
||||
msgstr "Todo"
|
||||
|
||||
msgid "Are you sure?"
|
||||
msgstr "Estás seguro?"
|
||||
msgstr "¿Estás seguro?"
|
||||
|
||||
msgid "Current data path:"
|
||||
msgstr "Ruta de datos actual:"
|
||||
@@ -207,13 +207,13 @@ msgid "Data:"
|
||||
msgstr "Datos:"
|
||||
|
||||
msgid "Enigma2 channel and satellites list editor for GNU/Linux"
|
||||
msgstr "Editor de Canales y Satélites Enigma2 para GNU/Linux"
|
||||
msgstr "Editor de canales y satélites Enigma2 para GNU/Linux"
|
||||
|
||||
msgid "Host:"
|
||||
msgstr "Anfitrión:"
|
||||
|
||||
msgid "Loading data..."
|
||||
msgstr "Cargar datos..."
|
||||
msgstr "Cargando datos..."
|
||||
|
||||
msgid "Receive"
|
||||
msgstr "Recibir"
|
||||
@@ -222,10 +222,10 @@ msgid "Receive files from receiver"
|
||||
msgstr "Recibir ficheros de su receptor"
|
||||
|
||||
msgid "Receiver IP:"
|
||||
msgstr "Receptor IP:"
|
||||
msgstr "IP del receptor:"
|
||||
|
||||
msgid "Remove unused bouquets"
|
||||
msgstr "Remover ramos sin usar"
|
||||
msgstr "Quitar bouquets sin usar"
|
||||
|
||||
msgid "Reset profile"
|
||||
msgstr "Restablecer perfil"
|
||||
@@ -234,7 +234,7 @@ msgid "Satellites"
|
||||
msgstr "Satélites"
|
||||
|
||||
msgid "Satellites.xml file:"
|
||||
msgstr "Fichero Satellites.xml:"
|
||||
msgstr "Fichero satellites.xml:"
|
||||
|
||||
msgid "Selected"
|
||||
msgstr "Seleccionado"
|
||||
@@ -246,10 +246,10 @@ msgid "Send files to receiver"
|
||||
msgstr "Enviar ficheros al receptor"
|
||||
|
||||
msgid "Services and Bouquets files:"
|
||||
msgstr "Ficheros de Servicios y ramos:"
|
||||
msgstr "Ficheros de servicios y bouquets:"
|
||||
|
||||
msgid "User bouquet files:"
|
||||
msgstr "Importar ficheros de ramos:"
|
||||
msgstr "Importar ficheros de bouquets:"
|
||||
|
||||
msgid "Extra:"
|
||||
msgstr "Extra:"
|
||||
@@ -266,16 +266,16 @@ msgstr "Todos los tipos"
|
||||
|
||||
# Streams player
|
||||
msgid "Play"
|
||||
msgstr "Play"
|
||||
msgstr "Reproducir"
|
||||
|
||||
msgid "Stop playback"
|
||||
msgstr "Detener la reproducción"
|
||||
|
||||
msgid "Previous stream in the list"
|
||||
msgstr "Secuencia anterior en la lista"
|
||||
msgstr "Anterior flujo en la lista"
|
||||
|
||||
msgid "Next stream in the list"
|
||||
msgstr "Secuencia siguiente en la lista"
|
||||
msgstr "Siguiente flujo en la lista"
|
||||
|
||||
msgid "Toggle in fullscreen"
|
||||
msgstr "Cambiar a pantalla completa"
|
||||
@@ -285,7 +285,7 @@ msgstr "Cerrar"
|
||||
|
||||
# Picons dialog
|
||||
msgid "Load providers"
|
||||
msgstr "Cargar Proveedores"
|
||||
msgstr "Cargar proveedores"
|
||||
|
||||
msgid "Providers"
|
||||
msgstr "Proveedores"
|
||||
@@ -300,19 +300,19 @@ msgid "Resize:"
|
||||
msgstr "Redimensionar:"
|
||||
|
||||
msgid "Current picons path:"
|
||||
msgstr "Ruta actual Picons:"
|
||||
msgstr "Ruta actual picons:"
|
||||
|
||||
msgid "Receiver picons path:"
|
||||
msgstr "Ruta picons receptor:"
|
||||
|
||||
msgid "Picons download tool"
|
||||
msgstr "Picons herramiento de descarga"
|
||||
msgstr "Herramienta de descarga de picons"
|
||||
|
||||
msgid "Transfer to receiver"
|
||||
msgstr "Transferir al receptor"
|
||||
|
||||
msgid "Downloader"
|
||||
msgstr "Descargador"
|
||||
msgstr "Programa de descarga"
|
||||
|
||||
msgid "Converter"
|
||||
msgstr "Convertidor"
|
||||
@@ -324,31 +324,31 @@ msgid "Path to save:"
|
||||
msgstr "Ruta para guardar:"
|
||||
|
||||
msgid "Path to Enigma2 picons:"
|
||||
msgstr "Ruta a picons Enigma2:"
|
||||
msgstr "Ruta a picons de Enigma2:"
|
||||
|
||||
msgid "Specify the correct position value for the provider!"
|
||||
msgstr "Especifique la posición correcta para el proveedor!"
|
||||
msgstr "¡Especifique el valor correcto de la posición del proveedor!"
|
||||
|
||||
msgid "Converter between name formats"
|
||||
msgstr "Conversor entre formatos de nombre"
|
||||
|
||||
msgid "Receive picons for providers"
|
||||
msgstr "Recibir picons para proovedor"
|
||||
msgstr "Recibir picons de proveedores"
|
||||
|
||||
msgid "Load satellite providers."
|
||||
msgstr "Cargar proovedores Satélite."
|
||||
msgstr "Cargar proveedores de satélite."
|
||||
|
||||
msgid ""
|
||||
"To automatically set the identifiers for picons,\n"
|
||||
"first load the required services list into the main application window."
|
||||
|
||||
msgstr ""
|
||||
"Para configurar automáticamente los identificadores para picons, \n"
|
||||
"primero cargue la lista de serviços requeridos en la ventana principal."
|
||||
"Para configurar automáticamente los identificadores para picons,\n"
|
||||
"cargue primero la lista de servicios requeridos en la ventana principal."
|
||||
|
||||
# Satellites editor
|
||||
msgid "Satellites edit tool"
|
||||
msgstr "Editor de Satélites"
|
||||
msgstr "Editor de satélites"
|
||||
|
||||
msgid "Add"
|
||||
msgstr "Añadir"
|
||||
@@ -360,10 +360,10 @@ msgid "Transponder"
|
||||
msgstr "Transpondedor"
|
||||
|
||||
msgid "Satellite properties:"
|
||||
msgstr "Propiedades del Satélite:"
|
||||
msgstr "Propiedades del satélite:"
|
||||
|
||||
msgid "Transponder properties:"
|
||||
msgstr "Propiedades del Transpondedor:"
|
||||
msgstr "Propiedades del transpondedor:"
|
||||
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
@@ -373,30 +373,30 @@ msgstr "Posición"
|
||||
|
||||
# Satellites update dialog
|
||||
msgid "Satellites update"
|
||||
msgstr "Actualisar Satélite"
|
||||
msgstr "Actualizar satélites"
|
||||
|
||||
msgid "Remove selection"
|
||||
msgstr "Remover selección"
|
||||
msgstr "Quitar selección"
|
||||
|
||||
# Service details dialog
|
||||
msgid "Service data:"
|
||||
msgstr "Datos servicio:"
|
||||
|
||||
msgid "Transponder data:"
|
||||
msgstr "Datos Transpondedor:"
|
||||
msgstr "Datos transpondedor:"
|
||||
|
||||
msgid "Service data"
|
||||
msgstr "Datos servicio"
|
||||
|
||||
msgid "Transponder details"
|
||||
msgstr "Detalles Transpondedor"
|
||||
msgstr "Detalles transpondedor"
|
||||
|
||||
msgid ""
|
||||
"Changes will be applied to all services of this transponder!\n"
|
||||
"Continue?"
|
||||
msgstr ""
|
||||
"Los cambios se aplicarán a todos los servicios de este transpondedor!\n"
|
||||
"Continuar?"
|
||||
"¿Continuar?"
|
||||
|
||||
msgid "Reference"
|
||||
msgstr "Referencia"
|
||||
@@ -408,10 +408,10 @@ msgid "Flags:"
|
||||
msgstr "Flags:"
|
||||
|
||||
msgid "Delays (ms):"
|
||||
msgstr "Retraso (mc)"
|
||||
msgstr "Retraso (ms)"
|
||||
|
||||
msgid "Bitstream"
|
||||
msgstr "Secuencia de Bits"
|
||||
msgstr "Secuencia de bits"
|
||||
|
||||
msgid "Description"
|
||||
msgstr "Descripción"
|
||||
@@ -420,10 +420,10 @@ msgid "Source:"
|
||||
msgstr "Fuente:"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "Annular"
|
||||
msgstr "Cancelar"
|
||||
|
||||
msgid "Update"
|
||||
msgstr "Actualisar"
|
||||
msgstr "Actualizar"
|
||||
|
||||
msgid "Filter"
|
||||
msgstr "Filtrar"
|
||||
@@ -433,7 +433,7 @@ msgstr "Buscar"
|
||||
|
||||
# IPTV dialog
|
||||
msgid "Stream data"
|
||||
msgstr "Datos de la Secuencia"
|
||||
msgstr "Transmitir flujo"
|
||||
|
||||
# IPTV list configuration dialog
|
||||
msgid "Starting values"
|
||||
@@ -443,7 +443,7 @@ msgid "Reset to default"
|
||||
msgstr "Restablecer a predeterminado"
|
||||
|
||||
msgid "IPTV streams list configuration"
|
||||
msgstr "Configurar lista de Secuencias IPTV"
|
||||
msgstr "Configurar lista de flujos IPTV"
|
||||
|
||||
# Settings dialog
|
||||
msgid "Preferences"
|
||||
@@ -456,7 +456,7 @@ msgid "Timeout between commands in seconds"
|
||||
msgstr "Tiempo de espera entre comandos en segundos"
|
||||
|
||||
msgid "Timeout:"
|
||||
msgstr "Time-out:"
|
||||
msgstr "Tiempo de espera:"
|
||||
|
||||
msgid "Login:"
|
||||
msgstr "Usuario:"
|
||||
@@ -471,68 +471,68 @@ msgid "Picons:"
|
||||
msgstr "Picons:"
|
||||
|
||||
msgid "Port:"
|
||||
msgstr "Puerta:"
|
||||
msgstr "Puerto:"
|
||||
|
||||
msgid "Data path:"
|
||||
msgstr "Ruta de datos:"
|
||||
|
||||
msgid "Picons path:"
|
||||
msgstr "Ruta de Picons:"
|
||||
msgstr "Ruta de picons:"
|
||||
|
||||
msgid "Network settings:"
|
||||
msgstr "Configuración de red:"
|
||||
|
||||
msgid "STB file paths:"
|
||||
msgstr "Ruta de ficherors STB:"
|
||||
msgstr "Rutas de ficheros del receptor:"
|
||||
|
||||
msgid "Local file paths:"
|
||||
msgstr "Ruta de ficheros local:"
|
||||
msgstr "Rutas de ficheros local:"
|
||||
|
||||
# Dialogs messages
|
||||
msgid "Error. No bouquet is selected!"
|
||||
msgstr "Error. Ningún ramo está seleccionado!"
|
||||
msgstr "Error. ¡Ningún bouquet seleccionado!"
|
||||
|
||||
msgid "This item is not allowed to be removed!"
|
||||
msgstr "Este artículo no puede ser eliminado!"
|
||||
msgstr "¡Este elemento no puede ser quitado!"
|
||||
|
||||
msgid "This item is not allowed to edit!"
|
||||
msgstr "Este artículo no puede ser editado!"
|
||||
msgstr "¡Este elemento no puede ser editado!"
|
||||
|
||||
msgid "Not allowed in this context!"
|
||||
msgstr "No permitido en este contexto!"
|
||||
msgstr "¡No permitido en este contexto!"
|
||||
|
||||
msgid "Please, download files from receiver or setup your path for read data!"
|
||||
msgstr "Por favor, descargue archivos desde el receptor o configure su ruta para leer los datos!"
|
||||
msgstr "Por favor, descargue ficheros desde el receptor o configure la ruta para leer los datos!"
|
||||
|
||||
msgid "Reading data error!"
|
||||
msgstr "Error de lectura de datos!"
|
||||
msgstr "¡Error de lectura de datos!"
|
||||
|
||||
msgid "No m3u file is selected!"
|
||||
msgstr "Ningún archivo m3u ha sido seleccionado!"
|
||||
msgstr "¡No se ha seleccionado ningún fichero m3u!"
|
||||
|
||||
msgid "Not implemented yet!"
|
||||
msgstr "Aun no implementado!"
|
||||
msgstr "¡Aún sin implementar!"
|
||||
|
||||
msgid "The text of marker is empty, please try again!"
|
||||
msgstr "El texto del marcador está vacío, inténtalo de nuevo!"
|
||||
msgstr "¡El texto del marcador está vacío, inténtalo de nuevo!"
|
||||
|
||||
msgid "Please, select only one item!"
|
||||
msgstr "Por favor, seleccione solo un elemento!"
|
||||
msgstr "¡Por favor, seleccione sólo un elemento!"
|
||||
|
||||
msgid "No png file is selected!"
|
||||
msgstr "Ningún fichero png seleccionado!"
|
||||
msgstr "¡No se ha seleccionado ningún fichero png!"
|
||||
|
||||
msgid "No reference is present!"
|
||||
msgstr "Ninguna referencia presente!"
|
||||
msgstr "¡Ninguna referencia presente!"
|
||||
|
||||
msgid "No selected item!"
|
||||
msgstr "Ningún elemento seleccionado!"
|
||||
msgstr "¡Ningún elemento seleccionado!"
|
||||
|
||||
msgid "The task is already running!"
|
||||
msgstr "La tarea ya se está ejecutando!"
|
||||
msgstr "¡La tarea ya se está ejecutando!"
|
||||
|
||||
msgid "Done!"
|
||||
msgstr "Hecho!"
|
||||
msgstr "¡Hecho!"
|
||||
|
||||
msgid "Please, wait..."
|
||||
msgstr "Por favor, espere..."
|
||||
@@ -541,50 +541,50 @@ msgid "Resizing..."
|
||||
msgstr "Redimensionando..."
|
||||
|
||||
msgid "Select paths!"
|
||||
msgstr "Seleccione rutas!"
|
||||
msgstr "¡Seleccione rutas!"
|
||||
|
||||
msgid "No satellite is selected!"
|
||||
msgstr "Ningún Satélite seleccionado!"
|
||||
msgstr "¡Ningún satélite seleccionado!"
|
||||
|
||||
msgid "Please, select only one satellite!"
|
||||
msgstr "Seleccione solo un Satélite!"
|
||||
msgstr "¡Seleccione sólo un Satélite!"
|
||||
|
||||
msgid "Please check your parameters and try again."
|
||||
msgstr "Por favor revise sus parámetros y vuelva a intentar!"
|
||||
msgstr "¡Por favor revise sus parámetros y vuelva a intentarlo!"
|
||||
|
||||
msgid "No satellites.xml file is selected!"
|
||||
msgstr "Ningún satellites.xml seleccionado!"
|
||||
msgstr "¡Ningún satellites.xml seleccionado!"
|
||||
|
||||
msgid "Error. Verify the data!"
|
||||
msgstr "Error. Revise sus datos!"
|
||||
msgstr "Error. ¡Revise los datos!"
|
||||
|
||||
msgid "Operation not allowed in this context!"
|
||||
msgstr "Operación no permitida en este contexto!"
|
||||
msgstr "¡Operación no permitida en este contexto!"
|
||||
|
||||
msgid "No VLC is found. Check that it is installed!"
|
||||
msgstr "VLC no encontrado. Verifica si está instalado!"
|
||||
msgstr "VLC no encontrado. ¡Verifique que está instalado!"
|
||||
|
||||
# Search unavailable streams dialog
|
||||
msgid "Please wait, streams testing in progress..."
|
||||
msgstr "Por favor espera una prueba de las secuencias..."
|
||||
msgstr "Por favor espere, hay una prueba de flujo en progreso..."
|
||||
|
||||
msgid "Found"
|
||||
msgstr "Encontrado"
|
||||
|
||||
msgid "unavailable streams."
|
||||
msgstr "Secuencias no presentes"
|
||||
msgstr "Flujos no presentes."
|
||||
|
||||
msgid "No changes required!"
|
||||
msgstr "ningún cambio requerido!"
|
||||
msgstr "¡Ningún cambio requerido!"
|
||||
|
||||
msgid "This list does not contains IPTV streams!"
|
||||
msgstr "La lista no contiene secuencias IPTV!"
|
||||
msgstr "¡La lista no contiene flujos IPTV!"
|
||||
|
||||
msgid "New empty configuration"
|
||||
msgstr "Nueva configuración vacía"
|
||||
|
||||
msgid "No data to save!"
|
||||
msgstr "No hay datos para guardar!"
|
||||
msgstr "¡No hay datos que guardar!"
|
||||
|
||||
msgid "Network"
|
||||
msgstr "Red"
|
||||
@@ -596,19 +596,19 @@ msgid "Program"
|
||||
msgstr "Programa"
|
||||
|
||||
msgid "Backup:"
|
||||
msgstr "Backup:"
|
||||
msgstr "Copia de seguridad:"
|
||||
|
||||
msgid "Backup"
|
||||
msgstr "Backup"
|
||||
msgstr "Copia de seguridad"
|
||||
|
||||
msgid "Backups"
|
||||
msgstr "Backups"
|
||||
msgstr "Copias de seguridad"
|
||||
|
||||
msgid "Backup path:"
|
||||
msgstr "Ruta del backup:"
|
||||
msgstr "Ruta de la copia de seguridad:"
|
||||
|
||||
msgid "Restore bouquets"
|
||||
msgstr "Restaurar ramos"
|
||||
msgstr "Restaurar bouquets"
|
||||
|
||||
msgid "Restore all"
|
||||
msgstr "Restaurar todo"
|
||||
@@ -620,19 +620,19 @@ msgid "Before downloading from the receiver"
|
||||
msgstr "Antes de recibir del receptor"
|
||||
|
||||
msgid "Set background color for the services"
|
||||
msgstr "Determinar color de fondo para servicios"
|
||||
msgstr "Determinar color de fondo de los servicios"
|
||||
|
||||
msgid "Marked as new:"
|
||||
msgstr "Marcado como nuevo:"
|
||||
|
||||
msgid "With an extra name in the bouquet:"
|
||||
msgstr "Con nombre adicional en ramo:"
|
||||
msgstr "Con nombre adicional en bouquet:"
|
||||
|
||||
msgid "Select"
|
||||
msgstr "Seleccione"
|
||||
|
||||
msgid "About"
|
||||
msgstr "Sobre"
|
||||
msgstr "Acerca de"
|
||||
|
||||
msgid "Exit"
|
||||
msgstr "Salir"
|
||||
@@ -645,19 +645,19 @@ msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
msgid "Bouquet"
|
||||
msgstr "Ramo"
|
||||
msgstr "Bouquet"
|
||||
|
||||
msgid "Bouquets and services"
|
||||
msgstr "Ramos y servicios"
|
||||
msgstr "Bouquets y servicios"
|
||||
|
||||
msgid "The main list does not contain services for this bouquet!"
|
||||
msgstr "La lista principal no contiene servicios para este ramo!"
|
||||
msgstr "¡La lista principal no contiene servicios para este bouquet!"
|
||||
|
||||
msgid "No bouquet file is selected!"
|
||||
msgstr "Nigún fichero de ramo ha sido seleccionado!"
|
||||
msgstr "¡No se ha seleccionado nigún fichero de bouquet!"
|
||||
|
||||
msgid "Remove all unused"
|
||||
msgstr "Quite todos los"
|
||||
msgstr "Quitar todos sin usar"
|
||||
|
||||
msgid "Test"
|
||||
msgstr "Prueba"
|
||||
@@ -672,7 +672,7 @@ msgid "Zap"
|
||||
msgstr "Zapear"
|
||||
|
||||
msgid "Play stream"
|
||||
msgstr "Reproducir secuencia"
|
||||
msgstr "Reproducir flujo"
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr "Desactivado"
|
||||
@@ -684,16 +684,16 @@ msgid "Enable HTTP API (experimental)"
|
||||
msgstr "Habilitar API HTTP (experimental)"
|
||||
|
||||
msgid "Switch(zap) the channel(Ctrl + Z)"
|
||||
msgstr "Cambiar (ZAP) el canal (Ctrl + Z)"
|
||||
msgstr "Poner el canal (Ctrl + Z)"
|
||||
|
||||
msgid "Switch the channel and watch in the program(Ctrl + W)"
|
||||
msgstr "Cambiar el canal y ver en el programa (Ctrl + W)"
|
||||
msgstr "Poner el canal y ver en el programa (Ctrl + W)"
|
||||
|
||||
msgid "Play IPTV or other stream in the program(Ctrl + P)"
|
||||
msgstr "Reproducir IPTV u otro flujo en el programa (Ctrl + P)"
|
||||
|
||||
msgid "Export to m3u"
|
||||
msgstr "Exportar hacia m3u"
|
||||
msgstr "Exportar a m3u"
|
||||
|
||||
msgid "EPG configuration"
|
||||
msgstr "Configuración EPG"
|
||||
@@ -705,61 +705,61 @@ msgid "EPG source"
|
||||
msgstr "Fuente EPG"
|
||||
|
||||
msgid "Service names source:"
|
||||
msgstr "Nombre de servicio fuente:"
|
||||
msgstr "Origen nombres de servicio:"
|
||||
|
||||
msgid "Main service list"
|
||||
msgstr "Lista principal de servicios:"
|
||||
|
||||
msgid "XML file"
|
||||
msgstr "Archivo XML"
|
||||
msgstr "Fichero XML"
|
||||
|
||||
msgid "Use web source"
|
||||
msgstr "Usar fuente web"
|
||||
|
||||
msgid "Url to *.xml.gz file:"
|
||||
msgstr "URL del archivo *.xml.gz:"
|
||||
msgstr "URL del fichero *.xml.gz:"
|
||||
|
||||
msgid "Enable filtering"
|
||||
msgstr "Habilitar filtrar"
|
||||
msgstr "Habilitar filtrado"
|
||||
|
||||
msgid "Filter by presence in the epg.dat file."
|
||||
msgstr "Filtrar por presencia del archivo epg.dat."
|
||||
msgstr "Filtrar según presencia del fichero epg.dat."
|
||||
|
||||
msgid "Paths to the epg.dat file:"
|
||||
msgstr "Ruta al archivo epg.dat:"
|
||||
msgstr "Ruta al fichero epg.dat:"
|
||||
|
||||
msgid "Local path:"
|
||||
msgstr "Ruta local:"
|
||||
|
||||
msgid "STB path:"
|
||||
msgstr "Ruta STB:"
|
||||
msgstr "Ruta receptor:"
|
||||
|
||||
msgid "Update on start"
|
||||
msgstr "Actualisar al iniciar"
|
||||
msgstr "Actualizar al inicio"
|
||||
|
||||
msgid "Auto configuration by service names."
|
||||
msgstr "Auto configuración por nombres de servicios."
|
||||
msgstr "Auto configuración según nombres de servicios."
|
||||
|
||||
msgid "Save list to xml."
|
||||
msgstr "Guardar como XML."
|
||||
|
||||
msgid "Download XML file error."
|
||||
msgstr "Error bajando archivo XML."
|
||||
msgstr "Error bajando fichero XML."
|
||||
|
||||
msgid "Unsupported file type:"
|
||||
msgstr "Archivo no supportado:"
|
||||
msgstr "Fichero no soportado:"
|
||||
|
||||
msgid "Unpacking data error."
|
||||
msgstr "Error abriende datos."
|
||||
msgstr "Error abriendo datos."
|
||||
|
||||
msgid "XML parsing error:"
|
||||
msgstr "Error analisando XML:"
|
||||
msgstr "Error analizando XML:"
|
||||
|
||||
msgid "Count of successfully configured services:"
|
||||
msgstr "Número de servicios configurados con éxito:"
|
||||
|
||||
msgid "Current epg.dat file does not contains references for the services of this bouquet!"
|
||||
msgstr "Archivo epg.dat actual no tiene referencias a servicios de este ramo!"
|
||||
msgstr "¡El fichero epg.dat actual no tiene referencias a servicios de este bouquet!"
|
||||
|
||||
msgid "Use HTTP"
|
||||
msgstr "Utilizar HTTP"
|
||||
@@ -771,10 +771,10 @@ msgid "Import YouTube playlist"
|
||||
msgstr "Importar lista de reproducción de YouTube"
|
||||
|
||||
msgid "Found a link to the YouTube resource!\nTry to get a direct link to the video?"
|
||||
msgstr "Encontré un enlace al recurso de YouTube!\nIntentar obtener un enlace directo al video?"
|
||||
msgstr "¡Encontrado enlace al recurso de YouTube!\n¿Intentar obtener un enlace directo al vídeo?"
|
||||
|
||||
msgid "Playlist import"
|
||||
msgstr "Importar lista de reproducción"
|
||||
|
||||
msgid "Getting link error:"
|
||||
msgstr "Recibido Link error:"
|
||||
msgstr "Error en el enlace:"
|
||||
|
||||
Reference in New Issue
Block a user