diff --git a/app/connections.py b/app/connections.py
index 715f592a..7f5d3df9 100644
--- a/app/connections.py
+++ b/app/connections.py
@@ -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__":
diff --git a/app/eparser/__init__.py b/app/eparser/__init__.py
index 6062f1c6..fff031a5 100644
--- a/app/eparser/__init__.py
+++ b/app/eparser/__init__.py
@@ -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
diff --git a/app/eparser/iptv.py b/app/eparser/iptv.py
index 2c67a53f..b47a8967 100644
--- a/app/eparser/iptv.py
+++ b/app/eparser/iptv.py
@@ -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
diff --git a/app/properties.py b/app/properties.py
deleted file mode 100644
index 370a9a82..00000000
--- a/app/properties.py
+++ /dev/null
@@ -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
diff --git a/app/settings.py b/app/settings.py
new file mode 100644
index 00000000..a73cd704
--- /dev/null
+++ b/app/settings.py
@@ -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
diff --git a/app/tools/media.py b/app/tools/media.py
index b85d2d43..2df7c3ea 100644
--- a/app/tools/media.py
+++ b/app/tools/media.py
@@ -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))
diff --git a/app/tools/picons.py b/app/tools/picons.py
index 01ad980b..87f3d5a4 100644
--- a/app/tools/picons.py
+++ b/app/tools/picons.py
@@ -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"
diff --git a/app/ui/backup.py b/app/ui/backup.py
index 3e11aadd..7aca7613 100644
--- a/app/ui/backup.py
+++ b/app/ui/backup.py
@@ -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 """
diff --git a/app/ui/dialogs.py b/app/ui/dialogs.py
index e224f929..596b89f6 100644
--- a/app/ui/dialogs.py
+++ b/app/ui/dialogs.py
@@ -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)
diff --git a/app/ui/download_dialog.py b/app/ui/download_dialog.py
index 801ee934..91d0d9c5 100644
--- a/app/ui/download_dialog.py
+++ b/app/ui/download_dialog.py
@@ -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())
diff --git a/app/ui/epg_dialog.py b/app/ui/epg_dialog.py
index 7754cdf2..de6e49c3 100644
--- a/app/ui/epg_dialog.py
+++ b/app/ui/epg_dialog.py
@@ -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__":
diff --git a/app/ui/import_dialog.glade b/app/ui/import_dialog.glade
index b35db491..fe01dbcb 100644
--- a/app/ui/import_dialog.glade
+++ b/app/ui/import_dialog.glade
@@ -89,6 +89,7 @@ Author: Dmitriy Yefremov
True
dialog
center
+