mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2025-12-21 16:09:41 +01:00
paths settings rework
This commit is contained in:
@@ -328,7 +328,7 @@ def download_data(*, settings, download_type=DownloadType.ALL, callback=log, fil
|
|||||||
with UtfFTP(host=settings.host, user=settings.user, passwd=settings.password) as ftp:
|
with UtfFTP(host=settings.host, user=settings.user, passwd=settings.password) as ftp:
|
||||||
ftp.encoding = "utf-8"
|
ftp.encoding = "utf-8"
|
||||||
callback("FTP OK.\n")
|
callback("FTP OK.\n")
|
||||||
save_path = settings.data_local_path
|
save_path = settings.profile_data_path
|
||||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||||
# bouquets
|
# bouquets
|
||||||
if download_type is DownloadType.ALL or download_type is DownloadType.BOUQUETS:
|
if download_type is DownloadType.ALL or download_type is DownloadType.BOUQUETS:
|
||||||
@@ -342,7 +342,7 @@ def download_data(*, settings, download_type=DownloadType.ALL, callback=log, fil
|
|||||||
ftp.download_xml(save_path, settings.satellites_xml_path, WEB_TV_XML_FILE, callback)
|
ftp.download_xml(save_path, settings.satellites_xml_path, WEB_TV_XML_FILE, callback)
|
||||||
|
|
||||||
if download_type is DownloadType.PICONS:
|
if download_type is DownloadType.PICONS:
|
||||||
picons_path = settings.picons_local_path
|
picons_path = settings.profile_picons_path
|
||||||
os.makedirs(os.path.dirname(picons_path), exist_ok=True)
|
os.makedirs(os.path.dirname(picons_path), exist_ok=True)
|
||||||
ftp.download_picons(settings.picons_path, picons_path, callback, files_filter)
|
ftp.download_picons(settings.picons_path, picons_path, callback, files_filter)
|
||||||
# epg.dat
|
# epg.dat
|
||||||
@@ -362,7 +362,7 @@ def download_data(*, settings, download_type=DownloadType.ALL, callback=log, fil
|
|||||||
def upload_data(*, settings, download_type=DownloadType.ALL, remove_unused=False,
|
def upload_data(*, settings, download_type=DownloadType.ALL, remove_unused=False,
|
||||||
callback=log, done_callback=None, use_http=False, files_filter=None):
|
callback=log, done_callback=None, use_http=False, files_filter=None):
|
||||||
s_type = settings.setting_type
|
s_type = settings.setting_type
|
||||||
data_path = settings.data_local_path
|
data_path = settings.profile_data_path
|
||||||
host = settings.host
|
host = settings.host
|
||||||
base_url = "http{}://{}:{}".format("s" if settings.http_use_ssl else "", host, settings.http_port)
|
base_url = "http{}://{}:{}".format("s" if settings.http_use_ssl else "", host, settings.http_port)
|
||||||
url = "{}/web/".format(base_url)
|
url = "{}/web/".format(base_url)
|
||||||
@@ -428,7 +428,7 @@ def upload_data(*, settings, download_type=DownloadType.ALL, remove_unused=False
|
|||||||
ftp.upload_files(data_path, DATA_FILES_LIST, callback)
|
ftp.upload_files(data_path, DATA_FILES_LIST, callback)
|
||||||
|
|
||||||
if download_type is DownloadType.PICONS:
|
if download_type is DownloadType.PICONS:
|
||||||
ftp.upload_picons(settings.picons_local_path, settings.picons_path, callback, files_filter)
|
ftp.upload_picons(settings.profile_picons_path, settings.picons_path, callback, files_filter)
|
||||||
|
|
||||||
if tn and not use_http:
|
if tn and not use_http:
|
||||||
# resume enigma or restart neutrino
|
# resume enigma or restart neutrino
|
||||||
|
|||||||
288
app/settings.py
288
app/settings.py
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import locale
|
import locale
|
||||||
@@ -13,7 +41,7 @@ SEP = os.sep
|
|||||||
HOME_PATH = str(Path.home())
|
HOME_PATH = str(Path.home())
|
||||||
CONFIG_PATH = HOME_PATH + "{}.config{}demon-editor{}".format(SEP, SEP, SEP)
|
CONFIG_PATH = HOME_PATH + "{}.config{}demon-editor{}".format(SEP, SEP, SEP)
|
||||||
CONFIG_FILE = CONFIG_PATH + "config.json"
|
CONFIG_FILE = CONFIG_PATH + "config.json"
|
||||||
DATA_PATH = HOME_PATH + "{}DemonEditor{}data{}".format(SEP, SEP, SEP)
|
DATA_PATH = HOME_PATH + "{}DemonEditor{}".format(SEP, SEP)
|
||||||
GTK_PATH = os.environ.get("GTK_PATH", None)
|
GTK_PATH = os.environ.get("GTK_PATH", None)
|
||||||
|
|
||||||
IS_DARWIN = sys.platform == "darwin"
|
IS_DARWIN = sys.platform == "darwin"
|
||||||
@@ -23,6 +51,31 @@ IS_LINUX = sys.platform == "linux"
|
|||||||
|
|
||||||
class Defaults(Enum):
|
class Defaults(Enum):
|
||||||
""" Default program settings """
|
""" Default program settings """
|
||||||
|
USER = "root"
|
||||||
|
PASSWORD = ""
|
||||||
|
HOST = "127.0.0.1"
|
||||||
|
FTP_PORT = "21"
|
||||||
|
HTTP_PORT = "80"
|
||||||
|
TELNET_PORT = "23"
|
||||||
|
HTTP_USE_SSL = False
|
||||||
|
# Enigma2.
|
||||||
|
BOX_SERVICES_PATH = "/etc/enigma2/"
|
||||||
|
BOX_SATELLITE_PATH = "/etc/tuxbox/"
|
||||||
|
BOX_PICON_PATH = "/usr/share/enigma2/picon/"
|
||||||
|
BOX_PICON_PATHS = ("/usr/share/enigma2/picon/",
|
||||||
|
"/media/hdd/picon/",
|
||||||
|
"/media/usb/picon/",
|
||||||
|
"/media/mmc/picon/",
|
||||||
|
"/media/cf/picon/")
|
||||||
|
# Neutrino.
|
||||||
|
NEUTRINO_BOX_SERVICES_PATH = "/var/tuxbox/config/zapit/"
|
||||||
|
NEUTRINO_BOX_SATELLITE_PATH = "/var/tuxbox/config/"
|
||||||
|
NEUTRINO_BOX_PICON_PATH = "/usr/share/tuxbox/neutrino/icons/logo/"
|
||||||
|
NEUTRINO_BOX_PICON_PATHS = ("/usr/share/tuxbox/neutrino/icons/logo/",)
|
||||||
|
# Paths.
|
||||||
|
BACKUP_PATH = "{}backup{}".format(DATA_PATH, SEP)
|
||||||
|
PICON_PATH = "{}picons{}".format(DATA_PATH, SEP)
|
||||||
|
|
||||||
DEFAULT_PROFILE = "default"
|
DEFAULT_PROFILE = "default"
|
||||||
BACKUP_BEFORE_DOWNLOADING = True
|
BACKUP_BEFORE_DOWNLOADING = True
|
||||||
BACKUP_BEFORE_SAVE = True
|
BACKUP_BEFORE_SAVE = True
|
||||||
@@ -43,64 +96,6 @@ class Defaults(Enum):
|
|||||||
RECORDS_PATH = DATA_PATH + "records{}".format(SEP)
|
RECORDS_PATH = DATA_PATH + "records{}".format(SEP)
|
||||||
ACTIVATE_TRANSCODING = False
|
ACTIVATE_TRANSCODING = False
|
||||||
ACTIVE_TRANSCODING_PRESET = "720p TV{}device".format(SEP)
|
ACTIVE_TRANSCODING_PRESET = "720p TV{}device".format(SEP)
|
||||||
ENIGMA_2_PICONS_PATHS = ("/usr/share/enigma2/picon/",
|
|
||||||
"/media/hdd/picon/",
|
|
||||||
"/media/usb/picon/",
|
|
||||||
"/media/mmc/picon/",
|
|
||||||
"/media/cf/picon/")
|
|
||||||
NEUTRINO_PICONS_PATHS = ("/usr/share/tuxbox/neutrino/icons/logo/",)
|
|
||||||
|
|
||||||
|
|
||||||
def get_settings():
|
|
||||||
if not os.path.isfile(CONFIG_FILE) or os.stat(CONFIG_FILE).st_size == 0:
|
|
||||||
write_settings(get_default_settings())
|
|
||||||
|
|
||||||
with open(CONFIG_FILE, "r", encoding="utf-8") as config_file:
|
|
||||||
return json.load(config_file)
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_settings(profile_name="default"):
|
|
||||||
def_settings = SettingsType.ENIGMA_2.get_default_settings()
|
|
||||||
set_local_paths(def_settings, profile_name)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"version": 1,
|
|
||||||
"default_profile": Defaults.DEFAULT_PROFILE.value,
|
|
||||||
"profiles": {profile_name: def_settings},
|
|
||||||
"v5_support": Defaults.V5_SUPPORT.value,
|
|
||||||
"http_api_support": Defaults.HTTP_API_SUPPORT.value,
|
|
||||||
"enable_yt_dl": Defaults.ENABLE_YT_DL.value,
|
|
||||||
"enable_send_to": Defaults.ENABLE_SEND_TO.value,
|
|
||||||
"use_colors": Defaults.USE_COLORS.value,
|
|
||||||
"new_color": Defaults.NEW_COLOR.value,
|
|
||||||
"extra_color": Defaults.EXTRA_COLOR.value,
|
|
||||||
"fav_click_mode": Defaults.FAV_CLICK_MODE.value,
|
|
||||||
"profile_folder_is_default": Defaults.PROFILE_FOLDER_DEFAULT.value,
|
|
||||||
"records_path": Defaults.RECORDS_PATH.value
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_transcoding_presets():
|
|
||||||
return {"720p TV/device": {"vcodec": "h264", "vb": "1500", "width": "1280", "height": "720", "acodec": "mp3",
|
|
||||||
"ab": "192", "channels": "2", "samplerate": "44100", "scodec": "none"},
|
|
||||||
"1080p TV/device": {"vcodec": "h264", "vb": "3500", "width": "1920", "height": "1080", "acodec": "mp3",
|
|
||||||
"ab": "192", "channels": "2", "samplerate": "44100", "scodec": "none"}}
|
|
||||||
|
|
||||||
|
|
||||||
def write_settings(config):
|
|
||||||
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
|
|
||||||
with open(CONFIG_FILE, "w", encoding="utf-8") as config_file:
|
|
||||||
json.dump(config, config_file, indent=" ")
|
|
||||||
|
|
||||||
|
|
||||||
def set_local_paths(settings, profile_name, data_path=DATA_PATH, use_profile_folder=False):
|
|
||||||
settings["data_local_path"] = "{}{}{}".format(data_path, profile_name, SEP)
|
|
||||||
if use_profile_folder:
|
|
||||||
settings["picons_local_path"] = "{}{}{}{}{}".format(data_path, profile_name, SEP, "picons", SEP)
|
|
||||||
settings["backup_local_path"] = "{}{}{}{}{}".format(data_path, profile_name, SEP, "backup", SEP)
|
|
||||||
else:
|
|
||||||
settings["picons_local_path"] = "{}{}{}{}{}".format(data_path, "picons", SEP, profile_name, SEP)
|
|
||||||
settings["backup_local_path"] = "{}{}{}{}{}".format(data_path, "backup", SEP, profile_name, SEP)
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsType(IntEnum):
|
class SettingsType(IntEnum):
|
||||||
@@ -109,29 +104,35 @@ class SettingsType(IntEnum):
|
|||||||
NEUTRINO_MP = 1
|
NEUTRINO_MP = 1
|
||||||
|
|
||||||
def get_default_settings(self):
|
def get_default_settings(self):
|
||||||
""" Returns default settings for current type """
|
""" Returns default settings for current type. """
|
||||||
if self is self.ENIGMA_2:
|
if self is self.ENIGMA_2:
|
||||||
|
srv_path = Defaults.BOX_SERVICES_PATH.value
|
||||||
|
sat_path = Defaults.BOX_SATELLITE_PATH.value
|
||||||
|
picons_path = Defaults.BOX_PICON_PATH.value
|
||||||
|
http_timeout = 5
|
||||||
|
telnet_timeout = 5
|
||||||
|
else:
|
||||||
|
srv_path = Defaults.NEUTRINO_BOX_SERVICES_PATH.value
|
||||||
|
sat_path = Defaults.NEUTRINO_BOX_SATELLITE_PATH.value
|
||||||
|
picons_path = Defaults.NEUTRINO_BOX_PICON_PATH.value
|
||||||
|
http_timeout = 2
|
||||||
|
telnet_timeout = 1
|
||||||
|
|
||||||
return {"setting_type": self.value,
|
return {"setting_type": self.value,
|
||||||
"host": "127.0.0.1", "port": "21", "timeout": 5,
|
"host": Defaults.HOST.value,
|
||||||
"user": "root", "password": "root",
|
"port": Defaults.FTP_PORT.value,
|
||||||
"http_port": "80", "http_timeout": 5, "http_use_ssl": False,
|
"timeout": 5,
|
||||||
"telnet_port": "23", "telnet_timeout": 5,
|
"user": Defaults.USER.value,
|
||||||
"services_path": "/etc/enigma2/", "user_bouquet_path": "/etc/enigma2/",
|
"password": Defaults.PASSWORD.value,
|
||||||
"satellites_xml_path": "/etc/tuxbox/", "data_local_path": "{}enigma2{}".format(DATA_PATH, SEP),
|
"http_port": Defaults.HTTP_PORT.value,
|
||||||
"picons_path": "/usr/share/enigma2/picon/",
|
"http_timeout": http_timeout,
|
||||||
"picons_local_path": "{}enigma2{}picons{}".format(DATA_PATH, SEP, SEP),
|
"http_use_ssl": Defaults.HTTP_USE_SSL.value,
|
||||||
"backup_local_path": "{}enigma2{}backup{}".format(DATA_PATH, SEP, SEP)}
|
"telnet_port": Defaults.TELNET_PORT.value,
|
||||||
elif self is SettingsType.NEUTRINO_MP:
|
"telnet_timeout": telnet_timeout,
|
||||||
return {"setting_type": self,
|
"services_path": srv_path,
|
||||||
"host": "127.0.0.1", "port": "21", "timeout": 5,
|
"user_bouquet_path": srv_path,
|
||||||
"user": "root", "password": "root",
|
"satellites_xml_path": sat_path,
|
||||||
"http_port": "80", "http_timeout": 2, "http_use_ssl": False,
|
"picons_path": picons_path}
|
||||||
"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_local_path": DATA_PATH + "neutrino/",
|
|
||||||
"picons_path": "/usr/share/tuxbox/neutrino/icons/logo/",
|
|
||||||
"picons_local_path": DATA_PATH + "neutrino/picons/",
|
|
||||||
"backup_local_path": DATA_PATH + "neutrino/backup/"}
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsException(Exception):
|
class SettingsException(Exception):
|
||||||
@@ -151,11 +152,11 @@ class PlayStreamsMode(IntEnum):
|
|||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
__INSTANCE = None
|
__INSTANCE = None
|
||||||
__VERSION = 1
|
__VERSION = 2
|
||||||
|
|
||||||
def __init__(self, ext_settings=None):
|
def __init__(self, ext_settings=None):
|
||||||
try:
|
try:
|
||||||
settings = ext_settings or get_settings()
|
settings = ext_settings or self.get_settings()
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
raise SettingsReadException(e)
|
raise SettingsReadException(e)
|
||||||
|
|
||||||
@@ -186,22 +187,18 @@ class Settings:
|
|||||||
return cls.__INSTANCE
|
return cls.__INSTANCE
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
write_settings(self._settings)
|
self.write_settings(self._settings)
|
||||||
|
|
||||||
def reset(self, force_write=False):
|
def reset(self, force_write=False):
|
||||||
for k, v in self.setting_type.get_default_settings().items():
|
for k, v in self.setting_type.get_default_settings().items():
|
||||||
self._cp_settings[k] = v
|
self._cp_settings[k] = v
|
||||||
|
|
||||||
def_path = DATA_PATH
|
|
||||||
def_path += "enigma2/" if self.setting_type is SettingsType.ENIGMA_2 else "neutrino/"
|
|
||||||
set_local_paths(self._cp_settings, self._current_profile, def_path, self.profile_folder_is_default)
|
|
||||||
|
|
||||||
if force_write:
|
if force_write:
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def reset_to_default():
|
def reset_to_default():
|
||||||
write_settings(get_default_settings())
|
Settings.write_settings(Settings.get_default_settings())
|
||||||
|
|
||||||
def get_default(self, p_name):
|
def get_default(self, p_name):
|
||||||
""" Returns default value for current settings type """
|
""" Returns default value for current settings type """
|
||||||
@@ -242,6 +239,10 @@ class Settings:
|
|||||||
def default_profile(self, value):
|
def default_profile(self, value):
|
||||||
self._settings["default_profile"] = value
|
self._settings["default_profile"] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_profile_settings(self):
|
||||||
|
return self._cp_settings
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def profiles(self):
|
def profiles(self):
|
||||||
return self._profiles
|
return self._profiles
|
||||||
@@ -368,8 +369,8 @@ class Settings:
|
|||||||
@property
|
@property
|
||||||
def picons_paths(self):
|
def picons_paths(self):
|
||||||
if self.setting_type is SettingsType.NEUTRINO_MP:
|
if self.setting_type is SettingsType.NEUTRINO_MP:
|
||||||
return Defaults.NEUTRINO_PICONS_PATHS.value
|
return Defaults.NEUTRINO_BOX_PICON_PATHS.value
|
||||||
return Defaults.ENIGMA_2_PICONS_PATHS.value
|
return Defaults.BOX_PICON_PATHS.value
|
||||||
|
|
||||||
# ***** Local paths ***** #
|
# ***** Local paths ***** #
|
||||||
|
|
||||||
@@ -382,28 +383,56 @@ class Settings:
|
|||||||
self._settings["profile_folder_is_default"] = value
|
self._settings["profile_folder_is_default"] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data_local_path(self):
|
def default_data_path(self):
|
||||||
return self._cp_settings.get("data_local_path", self.get_default("data_local_path"))
|
return self._settings.get("default_data_path", DATA_PATH)
|
||||||
|
|
||||||
@data_local_path.setter
|
@default_data_path.setter
|
||||||
def data_local_path(self, value):
|
def default_data_path(self, value):
|
||||||
self._cp_settings["data_local_path"] = value
|
self._settings["default_data_path"] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def picons_local_path(self):
|
def default_backup_path(self):
|
||||||
return self._cp_settings.get("picons_local_path", self.get_default("picons_local_path"))
|
return self._settings.get("default_backup_path", Defaults.BACKUP_PATH.value)
|
||||||
|
|
||||||
@picons_local_path.setter
|
@default_backup_path.setter
|
||||||
def picons_local_path(self, value):
|
def default_backup_path(self, value):
|
||||||
self._cp_settings["picons_local_path"] = value
|
self._settings["default_backup_path"] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def backup_local_path(self):
|
def default_picon_path(self):
|
||||||
return self._cp_settings.get("backup_local_path", self.get_default("backup_local_path"))
|
return self._settings.get("default_picon_path", Defaults.PICON_PATH.value)
|
||||||
|
|
||||||
@backup_local_path.setter
|
@default_picon_path.setter
|
||||||
def backup_local_path(self, value):
|
def default_picon_path(self, value):
|
||||||
self._cp_settings["backup_local_path"] = value
|
self._settings["default_picon_path"] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def profile_data_path(self):
|
||||||
|
return "{}data{}{}{}".format(self.default_data_path, SEP, self._current_profile, SEP)
|
||||||
|
|
||||||
|
@profile_data_path.setter
|
||||||
|
def profile_data_path(self, value):
|
||||||
|
self._cp_settings["profile_data_path"] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def profile_picons_path(self):
|
||||||
|
if self.profile_folder_is_default:
|
||||||
|
return "{}picons{}".format(self.profile_data_path, SEP)
|
||||||
|
return "{}{}{}".format(self.default_picon_path, self._current_profile, SEP)
|
||||||
|
|
||||||
|
@profile_picons_path.setter
|
||||||
|
def profile_picons_path(self, value):
|
||||||
|
self._cp_settings["profile_picons_path"] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def profile_backup_path(self):
|
||||||
|
if self.profile_folder_is_default:
|
||||||
|
return "{}backup{}".format(self.profile_data_path, SEP)
|
||||||
|
return "{}{}{}".format(self.default_backup_path, self._current_profile, SEP)
|
||||||
|
|
||||||
|
@profile_backup_path.setter
|
||||||
|
def profile_backup_path(self, value):
|
||||||
|
self._cp_settings["profile_backup_path"] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def records_path(self):
|
def records_path(self):
|
||||||
@@ -433,7 +462,7 @@ class Settings:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def transcoding_presets(self):
|
def transcoding_presets(self):
|
||||||
return self._settings.get("transcoding_presets", get_default_transcoding_presets())
|
return self._settings.get("transcoding_presets", self.get_default_transcoding_presets())
|
||||||
|
|
||||||
@transcoding_presets.setter
|
@transcoding_presets.setter
|
||||||
def transcoding_presets(self, value):
|
def transcoding_presets(self, value):
|
||||||
@@ -667,7 +696,7 @@ class Settings:
|
|||||||
@property
|
@property
|
||||||
@lru_cache(1)
|
@lru_cache(1)
|
||||||
def themes_path(self):
|
def themes_path(self):
|
||||||
return "{}/.themes/".format(HOME_PATH)
|
return "{}{}.themes{}".format(HOME_PATH, SEP, SEP)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon_theme(self):
|
def icon_theme(self):
|
||||||
@@ -680,7 +709,7 @@ class Settings:
|
|||||||
@property
|
@property
|
||||||
@lru_cache(1)
|
@lru_cache(1)
|
||||||
def icon_themes_path(self):
|
def icon_themes_path(self):
|
||||||
return "{}/.icons/".format(HOME_PATH)
|
return "{}{}.icons{}".format(HOME_PATH, SEP, SEP)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_darwin(self):
|
def is_darwin(self):
|
||||||
@@ -725,6 +754,49 @@ class Settings:
|
|||||||
def is_enable_experimental(self, value):
|
def is_enable_experimental(self, value):
|
||||||
self._settings["enable_experimental"] = value
|
self._settings["enable_experimental"] = value
|
||||||
|
|
||||||
|
# **************** Get-Set settings **************** #
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_settings():
|
||||||
|
if not os.path.isfile(CONFIG_FILE) or os.stat(CONFIG_FILE).st_size == 0:
|
||||||
|
Settings.write_settings(Settings.get_default_settings())
|
||||||
|
|
||||||
|
with open(CONFIG_FILE, "r", encoding="utf-8") as config_file:
|
||||||
|
return json.load(config_file)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_default_settings(profile_name="default"):
|
||||||
|
def_settings = SettingsType.ENIGMA_2.get_default_settings()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"version": Settings.__VERSION,
|
||||||
|
"default_profile": Defaults.DEFAULT_PROFILE.value,
|
||||||
|
"profiles": {profile_name: def_settings},
|
||||||
|
"v5_support": Defaults.V5_SUPPORT.value,
|
||||||
|
"http_api_support": Defaults.HTTP_API_SUPPORT.value,
|
||||||
|
"enable_yt_dl": Defaults.ENABLE_YT_DL.value,
|
||||||
|
"enable_send_to": Defaults.ENABLE_SEND_TO.value,
|
||||||
|
"use_colors": Defaults.USE_COLORS.value,
|
||||||
|
"new_color": Defaults.NEW_COLOR.value,
|
||||||
|
"extra_color": Defaults.EXTRA_COLOR.value,
|
||||||
|
"fav_click_mode": Defaults.FAV_CLICK_MODE.value,
|
||||||
|
"profile_folder_is_default": Defaults.PROFILE_FOLDER_DEFAULT.value,
|
||||||
|
"records_path": Defaults.RECORDS_PATH.value
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_default_transcoding_presets():
|
||||||
|
return {"720p TV/device": {"vcodec": "h264", "vb": "1500", "width": "1280", "height": "720", "acodec": "mp3",
|
||||||
|
"ab": "192", "channels": "2", "samplerate": "44100", "scodec": "none"},
|
||||||
|
"1080p TV/device": {"vcodec": "h264", "vb": "3500", "width": "1920", "height": "1080", "acodec": "mp3",
|
||||||
|
"ab": "192", "channels": "2", "samplerate": "44100", "scodec": "none"}}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def write_settings(config):
|
||||||
|
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
|
||||||
|
with open(CONFIG_FILE, "w", encoding="utf-8") as config_file:
|
||||||
|
json.dump(config, config_file, indent=" ")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
""" Module for working with YouTube service """
|
""" Module for working with YouTube service """
|
||||||
import gzip
|
import gzip
|
||||||
import json
|
import json
|
||||||
@@ -12,6 +40,7 @@ from urllib.parse import unquote
|
|||||||
from urllib.request import Request, urlopen, urlretrieve
|
from urllib.request import Request, urlopen, urlretrieve
|
||||||
|
|
||||||
from app.commons import log
|
from app.commons import log
|
||||||
|
from app.settings import SEP
|
||||||
from app.ui.uicommons import show_notification
|
from app.ui.uicommons import show_notification
|
||||||
|
|
||||||
_YT_PATTERN = re.compile(r"https://www.youtube.com/.+(?:v=)([\w-]{11}).*")
|
_YT_PATTERN = re.compile(r"https://www.youtube.com/.+(?:v=)([\w-]{11}).*")
|
||||||
@@ -230,7 +259,7 @@ class YouTubeDL:
|
|||||||
"cookiefile": "cookies.txt"} # File name where cookies should be read from and dumped to.
|
"cookiefile": "cookies.txt"} # File name where cookies should be read from and dumped to.
|
||||||
|
|
||||||
def __init__(self, settings, callback):
|
def __init__(self, settings, callback):
|
||||||
self._path = settings.default_data_path + "tools/"
|
self._path = "{}tools{}".format(settings.default_data_path, SEP)
|
||||||
self._update = settings.enable_yt_dl_update
|
self._update = settings.enable_yt_dl_update
|
||||||
self._supported = {"22", "18"}
|
self._supported = {"22", "18"}
|
||||||
self._dl = None
|
self._dl = None
|
||||||
@@ -247,7 +276,7 @@ class YouTubeDL:
|
|||||||
return cls._DL_INSTANCE
|
return cls._DL_INSTANCE
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
if not os.path.isfile(self._path + "youtube_dl/version.py"):
|
if not os.path.isfile("{}youtube_dl{}version.py".format(self._path, SEP)):
|
||||||
self.get_latest_release()
|
self.get_latest_release()
|
||||||
|
|
||||||
if self._path not in sys.path:
|
if self._path not in sys.path:
|
||||||
|
|||||||
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -7,7 +35,7 @@ from datetime import datetime
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from app.commons import run_idle
|
from app.commons import run_idle
|
||||||
from app.settings import SettingsType
|
from app.settings import SettingsType, SEP
|
||||||
from app.ui.dialogs import show_dialog, DialogType, get_builder
|
from app.ui.dialogs import show_dialog, DialogType, get_builder
|
||||||
from app.ui.main_helper import append_text_to_tview
|
from app.ui.main_helper import append_text_to_tview
|
||||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, MOD_MASK
|
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, MOD_MASK
|
||||||
@@ -34,8 +62,8 @@ class BackupDialog:
|
|||||||
|
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._s_type = settings.setting_type
|
self._s_type = settings.setting_type
|
||||||
self._data_path = self._settings.data_local_path
|
self._data_path = self._settings.profile_data_path
|
||||||
self._backup_path = self._settings.backup_local_path or self._data_path + "backup/"
|
self._backup_path = self._settings.profile_backup_path or "{}backup{}".format(self._data_path, os.sep)
|
||||||
self._open_data_callback = callback
|
self._open_data_callback = callback
|
||||||
self._dialog_window = builder.get_object("dialog_window")
|
self._dialog_window = builder.get_object("dialog_window")
|
||||||
self._dialog_window.set_transient_for(transient)
|
self._dialog_window.set_transient_for(transient)
|
||||||
@@ -149,7 +177,7 @@ class BackupDialog:
|
|||||||
clear_data_path(self._data_path)
|
clear_data_path(self._data_path)
|
||||||
shutil.unpack_archive(full_file_name, self._data_path)
|
shutil.unpack_archive(full_file_name, self._data_path)
|
||||||
elif restore_type is RestoreType.BOUQUETS:
|
elif restore_type is RestoreType.BOUQUETS:
|
||||||
tmp_dir = tempfile.gettempdir() + "/" + file_name
|
tmp_dir = tempfile.gettempdir() + SEP + file_name
|
||||||
cond = (".tv", ".radio") if self._s_type is SettingsType.ENIGMA_2 else "bouquets.xml"
|
cond = (".tv", ".radio") if self._s_type is SettingsType.ENIGMA_2 else "bouquets.xml"
|
||||||
shutil.unpack_archive(full_file_name, tmp_dir)
|
shutil.unpack_archive(full_file_name, tmp_dir)
|
||||||
for file in filter(lambda f: f.endswith(cond), os.listdir(self._data_path)):
|
for file in filter(lambda f: f.endswith(cond), os.listdir(self._data_path)):
|
||||||
@@ -188,7 +216,7 @@ def backup_data(path, backup_path, move=True):
|
|||||||
|
|
||||||
Returns full path to the compressed file.
|
Returns full path to the compressed file.
|
||||||
"""
|
"""
|
||||||
backup_path = "{}{}/".format(backup_path, datetime.now().strftime("%Y-%m-%d_%H-%M-%S"))
|
backup_path = "{}{}{}".format(backup_path, datetime.now().strftime("%Y-%m-%d_%H-%M-%S"), SEP)
|
||||||
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
||||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
# backup files in data dir(skipping dirs and satellites.xml)
|
# backup files in data dir(skipping dirs and satellites.xml)
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ def get_file_chooser_dialog(transient, text, settings, action_type, file_filter,
|
|||||||
if file_filter is not None:
|
if file_filter is not None:
|
||||||
dialog.add_filter(file_filter)
|
dialog.add_filter(file_filter)
|
||||||
|
|
||||||
dialog.set_current_folder(settings.data_local_path)
|
dialog.set_current_folder(settings.profile_data_path)
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
|
|
||||||
if response == Gtk.ResponseType.ACCEPT:
|
if response == Gtk.ResponseType.ACCEPT:
|
||||||
|
|||||||
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
@@ -58,7 +86,7 @@ class DownloadDialog:
|
|||||||
|
|
||||||
def init_ui_settings(self):
|
def init_ui_settings(self):
|
||||||
self._host_entry.set_text(self._settings.host)
|
self._host_entry.set_text(self._settings.host)
|
||||||
self._data_path_entry.set_text(self._settings.data_local_path)
|
self._data_path_entry.set_text(self._settings.profile_data_path)
|
||||||
is_enigma = self._s_type is SettingsType.ENIGMA_2
|
is_enigma = self._s_type is SettingsType.ENIGMA_2
|
||||||
self._webtv_radio_button.set_visible(not is_enigma)
|
self._webtv_radio_button.set_visible(not is_enigma)
|
||||||
self._use_http_box.set_visible(is_enigma)
|
self._use_http_box.set_visible(is_enigma)
|
||||||
@@ -128,9 +156,9 @@ class DownloadDialog:
|
|||||||
try:
|
try:
|
||||||
if download:
|
if download:
|
||||||
if backup and d_type is not DownloadType.SATELLITES:
|
if backup and d_type is not DownloadType.SATELLITES:
|
||||||
data_path = self._settings.data_local_path or self._data_path_entry.get_text()
|
data_path = self._settings.profile_data_path or self._data_path_entry.get_text()
|
||||||
os.makedirs(os.path.dirname(data_path), exist_ok=True)
|
os.makedirs(os.path.dirname(data_path), exist_ok=True)
|
||||||
backup_path = self._settings.backup_local_path or data_path + "backup/"
|
backup_path = self._settings.profile_backup_path or self._settings.default_backup_path
|
||||||
backup_src = backup_data(data_path, backup_path, d_type is DownloadType.ALL)
|
backup_src = backup_data(data_path, backup_path, d_type is DownloadType.ALL)
|
||||||
|
|
||||||
download_data(settings=self._settings, download_type=d_type, callback=self.append_output)
|
download_data(settings=self._settings, download_type=d_type, callback=self.append_output)
|
||||||
|
|||||||
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
import gzip
|
import gzip
|
||||||
import locale
|
import locale
|
||||||
import os
|
import os
|
||||||
@@ -12,6 +40,7 @@ from gi.repository import GLib
|
|||||||
from app.commons import run_idle, run_task
|
from app.commons import run_idle, run_task
|
||||||
from app.connections import download_data, DownloadType
|
from app.connections import download_data, DownloadType
|
||||||
from app.eparser.ecommons import BouquetService, BqServiceType
|
from app.eparser.ecommons import BouquetService, BqServiceType
|
||||||
|
from app.settings import SEP
|
||||||
from app.tools.epg import EPG, ChannelsParser
|
from app.tools.epg import EPG, ChannelsParser
|
||||||
from app.ui.dialogs import get_message, show_dialog, DialogType, get_builder
|
from app.ui.dialogs import get_message, show_dialog, DialogType, get_builder
|
||||||
from .main_helper import on_popup_menu, update_entry_data
|
from .main_helper import on_popup_menu, update_entry_data
|
||||||
@@ -480,7 +509,7 @@ class EpgDialog:
|
|||||||
# ***************** Options *********************#
|
# ***************** Options *********************#
|
||||||
|
|
||||||
def init_options(self):
|
def init_options(self):
|
||||||
epg_dat_path = self._settings.data_local_path + "epg/"
|
epg_dat_path = "{}epg{}".format(self._settings.profile_data_path, SEP)
|
||||||
self._epg_dat_path_entry.set_text(epg_dat_path)
|
self._epg_dat_path_entry.set_text(epg_dat_path)
|
||||||
default_epg_data_stb_path = "/etc/enigma2"
|
default_epg_data_stb_path = "/etc/enigma2"
|
||||||
epg_options = self._settings.epg_options
|
epg_options = self._settings.epg_options
|
||||||
|
|||||||
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
""" Simple FTP client module. """
|
""" Simple FTP client module. """
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
@@ -140,7 +168,7 @@ class FtpClientBox(Gtk.HBox):
|
|||||||
|
|
||||||
@run_task
|
@run_task
|
||||||
def init_file_data(self, path=None):
|
def init_file_data(self, path=None):
|
||||||
self.append_file_data(Path(path if path else self._settings.data_local_path))
|
self.append_file_data(Path(path if path else self._settings.profile_data_path))
|
||||||
|
|
||||||
@run_idle
|
@run_idle
|
||||||
def append_file_data(self, path: Path):
|
def append_file_data(self, path: Path):
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ class M3uImportDialog(IptvListDialog):
|
|||||||
|
|
||||||
self._app = app
|
self._app = app
|
||||||
self._picons = app._picons
|
self._picons = app._picons
|
||||||
self._pic_path = app._settings.picons_local_path
|
self._pic_path = app._settings.profile_picons_path
|
||||||
self._services = None
|
self._services = None
|
||||||
self._url_count = 0
|
self._url_count = 0
|
||||||
self._errors_count = 0
|
self._errors_count = 0
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ class Application(Gtk.Application):
|
|||||||
@run_idle
|
@run_idle
|
||||||
def update_picons_size(self):
|
def update_picons_size(self):
|
||||||
self._picons_size = self._settings.list_picon_size
|
self._picons_size = self._settings.list_picon_size
|
||||||
update_picons_data(self._settings.picons_local_path, self._picons, self._picons_size)
|
update_picons_data(self._settings.profile_picons_path, self._picons, self._picons_size)
|
||||||
self._fav_model.foreach(lambda m, p, itr: m.set_value(itr, Column.FAV_PICON, self._picons.get(
|
self._fav_model.foreach(lambda m, p, itr: m.set_value(itr, Column.FAV_PICON, self._picons.get(
|
||||||
self._services.get(m.get_value(itr, Column.FAV_ID)).picon_id, None)))
|
self._services.get(m.get_value(itr, Column.FAV_ID)).picon_id, None)))
|
||||||
self._services_model.foreach(lambda m, p, itr: m.set_value(itr, Column.SRV_PICON, self._picons.get(
|
self._services_model.foreach(lambda m, p, itr: m.set_value(itr, Column.SRV_PICON, self._picons.get(
|
||||||
@@ -1146,7 +1146,7 @@ class Application(Gtk.Application):
|
|||||||
target_column = Column.FAV_ID if target is ViewTarget.FAV else Column.SRV_FAV_ID
|
target_column = Column.FAV_ID if target is ViewTarget.FAV else Column.SRV_FAV_ID
|
||||||
srv = self._services.get(model[path][target_column], None)
|
srv = self._services.get(model[path][target_column], None)
|
||||||
if srv and srv.picon_id:
|
if srv and srv.picon_id:
|
||||||
tooltip.set_icon(get_picon_pixbuf(self._settings.picons_local_path + srv.picon_id,
|
tooltip.set_icon(get_picon_pixbuf(self._settings.profile_picons_path + srv.picon_id,
|
||||||
size=self._settings.tooltip_logo_size))
|
size=self._settings.tooltip_logo_size))
|
||||||
tooltip.set_text(
|
tooltip.set_text(
|
||||||
self.get_hint_for_bq_list(srv) if target is ViewTarget.FAV else self.get_hint_for_srv_list(srv))
|
self.get_hint_for_bq_list(srv) if target is ViewTarget.FAV else self.get_hint_for_srv_list(srv))
|
||||||
@@ -1588,8 +1588,8 @@ class Application(Gtk.Application):
|
|||||||
if current_profile != self._settings.current_profile:
|
if current_profile != self._settings.current_profile:
|
||||||
self.init_profiles(self._settings.current_profile)
|
self.init_profiles(self._settings.current_profile)
|
||||||
|
|
||||||
data_path = self._settings.data_local_path if data_path is None else data_path
|
data_path = self._settings.profile_data_path if data_path is None else data_path
|
||||||
local_path = self._settings.data_local_path
|
local_path = self._settings.profile_data_path
|
||||||
os.makedirs(os.path.dirname(local_path), exist_ok=True)
|
os.makedirs(os.path.dirname(local_path), exist_ok=True)
|
||||||
|
|
||||||
if data_path != local_path:
|
if data_path != local_path:
|
||||||
@@ -1606,7 +1606,7 @@ class Application(Gtk.Application):
|
|||||||
yield True
|
yield True
|
||||||
services = get_services(data_path, prf, self.get_format_version() if prf is SettingsType.ENIGMA_2 else 0)
|
services = get_services(data_path, prf, self.get_format_version() if prf is SettingsType.ENIGMA_2 else 0)
|
||||||
yield True
|
yield True
|
||||||
update_picons_data(self._settings.picons_local_path, self._picons, self._picons_size)
|
update_picons_data(self._settings.profile_picons_path, self._picons, self._picons_size)
|
||||||
yield True
|
yield True
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
msg = get_message("Please, download files from receiver or setup your path for read data!")
|
msg = get_message("Please, download files from receiver or setup your path for read data!")
|
||||||
@@ -1820,8 +1820,8 @@ class Application(Gtk.Application):
|
|||||||
def save_data(self, callback=None, ext_path=None):
|
def save_data(self, callback=None, ext_path=None):
|
||||||
self._save_tool_button.set_sensitive(False)
|
self._save_tool_button.set_sensitive(False)
|
||||||
profile = self._s_type
|
profile = self._s_type
|
||||||
path = ext_path or self._settings.data_local_path
|
path = ext_path or self._settings.profile_data_path
|
||||||
backup_path = self._settings.backup_local_path
|
backup_path = self._settings.profile_backup_path
|
||||||
# Backup data or clearing data path
|
# Backup data or clearing data path
|
||||||
backup_data(path, backup_path) if not ext_path and self._settings.backup_before_save else clear_data_path(path)
|
backup_data(path, backup_path) if not ext_path and self._settings.backup_before_save else clear_data_path(path)
|
||||||
yield True
|
yield True
|
||||||
@@ -3290,7 +3290,7 @@ class Application(Gtk.Application):
|
|||||||
|
|
||||||
@run_task
|
@run_task
|
||||||
def update_picons(self):
|
def update_picons(self):
|
||||||
update_picons_data(self._settings.picons_local_path, self._picons, self._picons_size)
|
update_picons_data(self._settings.profile_picons_path, self._picons, self._picons_size)
|
||||||
append_picons(self._picons, self._services_model)
|
append_picons(self._picons, self._services_model)
|
||||||
|
|
||||||
def on_assign_picon(self, view, src_path=None, dst_path=None):
|
def on_assign_picon(self, view, src_path=None, dst_path=None):
|
||||||
|
|||||||
@@ -1,3 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
""" Helper module for the ui. """
|
""" Helper module for the ui. """
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@@ -9,7 +37,7 @@ from gi.repository import GdkPixbuf, GLib
|
|||||||
from app.eparser import Service
|
from app.eparser import Service
|
||||||
from app.eparser.ecommons import Flag, BouquetService, Bouquet, BqType
|
from app.eparser.ecommons import Flag, BouquetService, Bouquet, BqType
|
||||||
from app.eparser.enigma.bouquets import BqServiceType, to_bouquet_id
|
from app.eparser.enigma.bouquets import BqServiceType, to_bouquet_id
|
||||||
from app.settings import SettingsType
|
from app.settings import SettingsType, SEP
|
||||||
from .dialogs import show_dialog, DialogType, get_chooser_dialog
|
from .dialogs import show_dialog, DialogType, get_chooser_dialog
|
||||||
from .uicommons import ViewTarget, BqGenType, Gtk, Gdk, HIDE_ICON, LOCKED_ICON, KeyboardKey, Column
|
from .uicommons import ViewTarget, BqGenType, Gtk, Gdk, HIDE_ICON, LOCKED_ICON, KeyboardKey, Column
|
||||||
|
|
||||||
@@ -402,7 +430,7 @@ def assign_picons(target, srv_view, fav_view, transient, picons, settings, servi
|
|||||||
picon_id = services.get(fav_id)[Column.SRV_PICON_ID]
|
picon_id = services.get(fav_id)[Column.SRV_PICON_ID]
|
||||||
|
|
||||||
if picon_id:
|
if picon_id:
|
||||||
picons_path = dst_path or settings.picons_local_path
|
picons_path = dst_path or settings.profile_picons_path
|
||||||
os.makedirs(os.path.dirname(picons_path), exist_ok=True)
|
os.makedirs(os.path.dirname(picons_path), exist_ok=True)
|
||||||
picon_file = picons_path + picon_id
|
picon_file = picons_path + picon_id
|
||||||
try:
|
try:
|
||||||
@@ -499,8 +527,8 @@ def remove_all_unused_picons(settings, picons, services):
|
|||||||
|
|
||||||
|
|
||||||
def remove_picons(settings, picon_ids, picons):
|
def remove_picons(settings, picon_ids, picons):
|
||||||
pions_path = settings.picons_local_path
|
pions_path = settings.profile_picons_path
|
||||||
backup_path = settings.backup_local_path + "picons/"
|
backup_path = "{}{}{}".format(settings.profile_backup_path, "picons", SEP)
|
||||||
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
os.makedirs(os.path.dirname(backup_path), exist_ok=True)
|
||||||
for p_id in picon_ids:
|
for p_id in picon_ids:
|
||||||
picons[p_id] = None
|
picons[p_id] = None
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ from gi.repository import GLib, GdkPixbuf, Gio
|
|||||||
|
|
||||||
from app.commons import run_idle, run_task, run_with_delay
|
from app.commons import run_idle, run_task, run_with_delay
|
||||||
from app.connections import upload_data, DownloadType, download_data, remove_picons
|
from app.connections import upload_data, DownloadType, download_data, remove_picons
|
||||||
from app.settings import SettingsType, Settings
|
from app.settings import SettingsType, Settings, SEP
|
||||||
from app.tools.picons import (PiconsParser, parse_providers, Provider, convert_to, download_picon, PiconsCzDownloader,
|
from app.tools.picons import (PiconsParser, parse_providers, Provider, convert_to, download_picon, PiconsCzDownloader,
|
||||||
PiconsError)
|
PiconsError)
|
||||||
from app.tools.satellites import SatellitesParser, SatelliteSource
|
from app.tools.satellites import SatellitesParser, SatelliteSource
|
||||||
@@ -184,7 +184,7 @@ class PiconManager(Gtk.Box):
|
|||||||
# Settings
|
# Settings
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._s_type = settings.setting_type
|
self._s_type = settings.setting_type
|
||||||
self._picons_dir_entry.set_text(self._settings.picons_local_path)
|
self._picons_dir_entry.set_text(self._settings.profile_picons_path)
|
||||||
|
|
||||||
self.pack_start(builder.get_object("picon_manager_frame"), True, True, 0)
|
self.pack_start(builder.get_object("picon_manager_frame"), True, True, 0)
|
||||||
self.show()
|
self.show()
|
||||||
@@ -197,7 +197,7 @@ class PiconManager(Gtk.Box):
|
|||||||
|
|
||||||
def on_picons_dest_view_realize(self, view):
|
def on_picons_dest_view_realize(self, view):
|
||||||
self._services = {s.picon_id: s for s in self._app.current_services.values() if s.picon_id}
|
self._services = {s.picon_id: s for s in self._app.current_services.values() if s.picon_id}
|
||||||
self._explorer_dest_path_button.select_filename(self._settings.picons_local_path)
|
self._explorer_dest_path_button.select_filename(self._settings.profile_picons_path)
|
||||||
|
|
||||||
def on_picons_src_changed(self, button):
|
def on_picons_src_changed(self, button):
|
||||||
self.update_picons_data(self._picons_src_view, button)
|
self.update_picons_data(self._picons_src_view, button)
|
||||||
@@ -234,7 +234,7 @@ class PiconManager(Gtk.Box):
|
|||||||
if self._terminate:
|
if self._terminate:
|
||||||
return
|
return
|
||||||
|
|
||||||
p_path = "{}/{}".format(path, file)
|
p_path = "{}{}{}".format(path, SEP, file)
|
||||||
p = self.get_pixbuf_at_scale(p_path, 72, 48, True)
|
p = self.get_pixbuf_at_scale(p_path, 72, 48, True)
|
||||||
if p:
|
if p:
|
||||||
yield model.append((p, file, p_path))
|
yield model.append((p, file, p_path))
|
||||||
@@ -327,7 +327,7 @@ class PiconManager(Gtk.Box):
|
|||||||
c_id = Column.SRV_FAV_ID
|
c_id = Column.SRV_FAV_ID
|
||||||
|
|
||||||
t_mod = target_view.get_model()
|
t_mod = target_view.get_model()
|
||||||
dest_path = self._explorer_dest_path_button.get_filename() + "/"
|
dest_path = self._explorer_dest_path_button.get_filename() + SEP
|
||||||
self.update_picons_dest_view(self._app.on_assign_picon(target_view, model[path][-1], dest_path))
|
self.update_picons_dest_view(self._app.on_assign_picon(target_view, model[path][-1], dest_path))
|
||||||
self.show_assign_info([t_mod.get_value(t_mod.get_iter_from_string(itr), c_id) for itr in itr_str.split(",")])
|
self.show_assign_info([t_mod.get_value(t_mod.get_iter_from_string(itr), c_id) for itr in itr_str.split(",")])
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ class PiconManager(Gtk.Box):
|
|||||||
if len(uris) == 2:
|
if len(uris) == 2:
|
||||||
name, fav_id = self._current_picon_info
|
name, fav_id = self._current_picon_info
|
||||||
src = urlparse(unquote(uris[0])).path
|
src = urlparse(unquote(uris[0])).path
|
||||||
dst = "{}/{}".format(urlparse(unquote(uris[1])).path, name)
|
dst = "{}{}{}".format(urlparse(unquote(uris[1])).path, SEP, name)
|
||||||
if src != dst:
|
if src != dst:
|
||||||
shutil.copy(src, dst)
|
shutil.copy(src, dst)
|
||||||
for row in get_base_model(self._picons_dest_view.get_model()):
|
for row in get_base_model(self._picons_dest_view.get_model()):
|
||||||
@@ -443,7 +443,7 @@ class PiconManager(Gtk.Box):
|
|||||||
return
|
return
|
||||||
|
|
||||||
settings = Settings(self._settings.settings)
|
settings = Settings(self._settings.settings)
|
||||||
settings.picons_local_path = "{}/".format(dest_path)
|
settings.profile_picons_path = "{}{}".format(dest_path, SEP)
|
||||||
self.show_info_message(get_message("Please, wait..."), Gtk.MessageType.INFO)
|
self.show_info_message(get_message("Please, wait..."), Gtk.MessageType.INFO)
|
||||||
self.run_func(lambda: upload_data(settings=settings,
|
self.run_func(lambda: upload_data(settings=settings,
|
||||||
download_type=DownloadType.PICONS,
|
download_type=DownloadType.PICONS,
|
||||||
@@ -458,7 +458,7 @@ class PiconManager(Gtk.Box):
|
|||||||
return
|
return
|
||||||
|
|
||||||
settings = Settings(self._settings.settings)
|
settings = Settings(self._settings.settings)
|
||||||
settings.picons_local_path = path + "/"
|
settings.profile_picons_path = path + SEP
|
||||||
self.run_func(lambda: download_data(settings=settings,
|
self.run_func(lambda: download_data(settings=settings,
|
||||||
download_type=DownloadType.PICONS,
|
download_type=DownloadType.PICONS,
|
||||||
callback=self.append_output,
|
callback=self.append_output,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class SatellitesTool(Gtk.Box):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
self._app = app
|
self._app = app
|
||||||
self._data_path = settings.data_local_path + "satellites.xml"
|
self._data_path = settings.profile_data_path + "satellites.xml"
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
|
|
||||||
handlers = {"on_remove": self.on_remove,
|
handlers = {"on_remove": self.on_remove,
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ class ServiceDetailsDialog:
|
|||||||
self._dialog.set_transient_for(transient)
|
self._dialog.set_transient_for(transient)
|
||||||
self._s_type = settings.setting_type
|
self._s_type = settings.setting_type
|
||||||
self._tr_type = TrType.Satellite
|
self._tr_type = TrType.Satellite
|
||||||
self._satellites_xml_path = settings.data_local_path + "satellites.xml"
|
self._satellites_xml_path = settings.profile_data_path + "satellites.xml"
|
||||||
self._picons_dir_path = settings.picons_local_path
|
self._picons_path = settings.profile_picons_path
|
||||||
self._services_view = srv_view
|
self._services_view = srv_view
|
||||||
self._fav_view = fav_view
|
self._fav_view = fav_view
|
||||||
self._action = action
|
self._action = action
|
||||||
@@ -504,13 +504,13 @@ class ServiceDetailsDialog:
|
|||||||
Column.FAV_PICON: new_service.picon})
|
Column.FAV_PICON: new_service.picon})
|
||||||
|
|
||||||
def update_picon_name(self, old_name, new_name):
|
def update_picon_name(self, old_name, new_name):
|
||||||
if not os.path.isdir(self._picons_dir_path):
|
if not os.path.isdir(self._picons_path):
|
||||||
return
|
return
|
||||||
|
|
||||||
for file_name in os.listdir(self._picons_dir_path):
|
for file_name in os.listdir(self._picons_path):
|
||||||
if file_name == old_name:
|
if file_name == old_name:
|
||||||
old_file = os.path.join(self._picons_dir_path, old_name)
|
old_file = os.path.join(self._picons_path, old_name)
|
||||||
new_file = os.path.join(self._picons_dir_path, new_name)
|
new_file = os.path.join(self._picons_path, new_name)
|
||||||
os.rename(old_file, new_file)
|
os.rename(old_file, new_file)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
@@ -1199,7 +1199,7 @@ Author: Dmitriy Yefremov
|
|||||||
<property name="row_spacing">5</property>
|
<property name="row_spacing">5</property>
|
||||||
<property name="column_spacing">10</property>
|
<property name="column_spacing">10</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="data_dir_label">
|
<object class="GtkLabel" id="data_path_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">start</property>
|
<property name="halign">start</property>
|
||||||
@@ -1212,7 +1212,7 @@ Author: Dmitriy Yefremov
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="picons_dir_label">
|
<object class="GtkLabel" id="picons_path_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">start</property>
|
<property name="halign">start</property>
|
||||||
@@ -1224,7 +1224,7 @@ Author: Dmitriy Yefremov
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="backup_dir_label">
|
<object class="GtkLabel" id="backup_path_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">start</property>
|
<property name="halign">start</property>
|
||||||
@@ -1236,7 +1236,7 @@ Author: Dmitriy Yefremov
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="data_dir_field">
|
<object class="GtkEntry" id="data_path_field">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="hexpand">True</property>
|
||||||
@@ -1253,7 +1253,7 @@ Author: Dmitriy Yefremov
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="picons_dir_field">
|
<object class="GtkEntry" id="picons_path_field">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="hexpand">True</property>
|
||||||
@@ -1270,7 +1270,7 @@ Author: Dmitriy Yefremov
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="backup_dir_field">
|
<object class="GtkEntry" id="backup_path_field">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="hexpand">True</property>
|
||||||
@@ -1327,7 +1327,7 @@ Author: Dmitriy Yefremov
|
|||||||
<property name="margin_bottom">5</property>
|
<property name="margin_bottom">5</property>
|
||||||
<property name="column_spacing">10</property>
|
<property name="column_spacing">10</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="record_dir_label">
|
<object class="GtkLabel" id="record_path_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">Streams record path:</property>
|
<property name="label" translatable="yes">Streams record path:</property>
|
||||||
@@ -1339,7 +1339,7 @@ Author: Dmitriy Yefremov
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="record_data_dir_field">
|
<object class="GtkEntry" id="record_data_path_field">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="hexpand">True</property>
|
||||||
|
|||||||
@@ -1,9 +1,37 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Author: Dmitriy Yefremov
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from app.commons import run_task, run_idle, log
|
from app.commons import run_task, run_idle, log
|
||||||
from app.connections import test_telnet, test_ftp, TestException, test_http, HttpApiException
|
from app.connections import test_telnet, test_ftp, TestException, test_http, HttpApiException
|
||||||
from app.settings import SettingsType, Settings, PlayStreamsMode, IS_LINUX
|
from app.settings import SettingsType, Settings, PlayStreamsMode, IS_LINUX, SEP
|
||||||
from app.ui.dialogs import show_dialog, DialogType, get_message, get_chooser_dialog, get_builder
|
from app.ui.dialogs import show_dialog, DialogType, get_message, get_chooser_dialog, get_builder
|
||||||
from .main_helper import update_entry_data, scroll_to, get_picon_pixbuf
|
from .main_helper import update_entry_data, scroll_to, get_picon_pixbuf
|
||||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, DEFAULT_ICON, APP_FONT
|
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, DEFAULT_ICON, APP_FONT
|
||||||
@@ -78,6 +106,7 @@ class SettingsDialog:
|
|||||||
self._http_use_ssl_check_button = builder.get_object("http_use_ssl_check_button")
|
self._http_use_ssl_check_button = builder.get_object("http_use_ssl_check_button")
|
||||||
self._telnet_port_field = builder.get_object("telnet_port_field")
|
self._telnet_port_field = builder.get_object("telnet_port_field")
|
||||||
self._telnet_timeout_spin_button = builder.get_object("telnet_timeout_spin_button")
|
self._telnet_timeout_spin_button = builder.get_object("telnet_timeout_spin_button")
|
||||||
|
self._reset_button = builder.get_object("reset_button")
|
||||||
# Test.
|
# Test.
|
||||||
self._ftp_radio_button = builder.get_object("ftp_radio_button")
|
self._ftp_radio_button = builder.get_object("ftp_radio_button")
|
||||||
self._http_radio_button = builder.get_object("http_radio_button")
|
self._http_radio_button = builder.get_object("http_radio_button")
|
||||||
@@ -87,12 +116,13 @@ class SettingsDialog:
|
|||||||
self._satellites_xml_field = builder.get_object("satellites_xml_field")
|
self._satellites_xml_field = builder.get_object("satellites_xml_field")
|
||||||
self._picons_paths_box = builder.get_object("picons_paths_box")
|
self._picons_paths_box = builder.get_object("picons_paths_box")
|
||||||
# Paths.
|
# Paths.
|
||||||
self._picons_dir_field = builder.get_object("picons_dir_field")
|
self._picons_path_field = builder.get_object("picons_path_field")
|
||||||
self._data_dir_field = builder.get_object("data_dir_field")
|
self._data_path_field = builder.get_object("data_path_field")
|
||||||
self._backup_dir_field = builder.get_object("backup_dir_field")
|
self._backup_path_field = builder.get_object("backup_path_field")
|
||||||
self._default_data_dir_field = builder.get_object("default_data_dir_field")
|
self._record_data_path_field = builder.get_object("record_data_path_field")
|
||||||
self._record_data_dir_field = builder.get_object("record_data_dir_field")
|
|
||||||
self._default_data_paths_switch = builder.get_object("default_data_paths_switch")
|
self._default_data_paths_switch = builder.get_object("default_data_paths_switch")
|
||||||
|
self._default_data_paths_switch.bind_property("active", self._backup_path_field, "sensitive", 4)
|
||||||
|
self._default_data_paths_switch.bind_property("active", self._picons_path_field, "sensitive", 4)
|
||||||
# Info bar.
|
# Info bar.
|
||||||
self._info_bar = builder.get_object("info_bar")
|
self._info_bar = builder.get_object("info_bar")
|
||||||
self._message_label = builder.get_object("info_bar_message_label")
|
self._message_label = builder.get_object("info_bar_message_label")
|
||||||
@@ -268,10 +298,10 @@ class SettingsDialog:
|
|||||||
self._user_bouquet_field.set_text(self._settings.user_bouquet_path)
|
self._user_bouquet_field.set_text(self._settings.user_bouquet_path)
|
||||||
self._satellites_xml_field.set_text(self._settings.satellites_xml_path)
|
self._satellites_xml_field.set_text(self._settings.satellites_xml_path)
|
||||||
self._picons_paths_box.set_active_id(self._settings.picons_path)
|
self._picons_paths_box.set_active_id(self._settings.picons_path)
|
||||||
self._data_dir_field.set_text(self._settings.data_local_path)
|
self._data_path_field.set_text(self._settings.default_data_path)
|
||||||
self._picons_dir_field.set_text(self._settings.picons_local_path)
|
self._picons_path_field.set_text(self._settings.default_picon_path)
|
||||||
self._backup_dir_field.set_text(self._settings.backup_local_path)
|
self._backup_path_field.set_text(self._settings.default_backup_path)
|
||||||
self._record_data_dir_field.set_text(self._settings.records_path)
|
self._record_data_path_field.set_text(self._settings.records_path)
|
||||||
self._before_save_switch.set_active(self._settings.backup_before_save)
|
self._before_save_switch.set_active(self._settings.backup_before_save)
|
||||||
self._before_downloading_switch.set_active(self._settings.backup_before_downloading)
|
self._before_downloading_switch.set_active(self._settings.backup_before_downloading)
|
||||||
self.set_fav_click_mode(self._settings.fav_click_mode)
|
self.set_fav_click_mode(self._settings.fav_click_mode)
|
||||||
@@ -328,9 +358,6 @@ class SettingsDialog:
|
|||||||
self._settings.user_bouquet_path = self._user_bouquet_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.satellites_xml_path = self._satellites_xml_field.get_text()
|
||||||
self._settings.picons_path = self._picons_paths_box.get_active_id()
|
self._settings.picons_path = self._picons_paths_box.get_active_id()
|
||||||
self._settings.data_local_path = self._data_dir_field.get_text()
|
|
||||||
self._settings.picons_local_path = self._picons_dir_field.get_text()
|
|
||||||
self._settings.backup_local_path = self._backup_dir_field.get_text()
|
|
||||||
|
|
||||||
def apply_settings(self, item=None):
|
def apply_settings(self, item=None):
|
||||||
if show_dialog(DialogType.QUESTION, self._dialog) != Gtk.ResponseType.OK:
|
if show_dialog(DialogType.QUESTION, self._dialog) != Gtk.ResponseType.OK:
|
||||||
@@ -348,7 +375,10 @@ class SettingsDialog:
|
|||||||
self._ext_settings.show_bq_hints = self._bouquet_hints_switch.get_active()
|
self._ext_settings.show_bq_hints = self._bouquet_hints_switch.get_active()
|
||||||
self._ext_settings.show_srv_hints = self._services_hints_switch.get_active()
|
self._ext_settings.show_srv_hints = self._services_hints_switch.get_active()
|
||||||
self._ext_settings.profile_folder_is_default = self._default_data_paths_switch.get_active()
|
self._ext_settings.profile_folder_is_default = self._default_data_paths_switch.get_active()
|
||||||
self._ext_settings.records_path = self._record_data_dir_field.get_text()
|
self._ext_settings.default_data_path = self._data_path_field.get_text()
|
||||||
|
self._ext_settings.default_backup_path = self._backup_path_field.get_text()
|
||||||
|
self._ext_settings.default_picon_path = self._picons_path_field.get_text()
|
||||||
|
self._ext_settings.records_path = self._record_data_path_field.get_text()
|
||||||
self._ext_settings.activate_transcoding = self._transcoding_switch.get_active()
|
self._ext_settings.activate_transcoding = self._transcoding_switch.get_active()
|
||||||
self._ext_settings.active_preset = self._presets_combo_box.get_active_id()
|
self._ext_settings.active_preset = self._presets_combo_box.get_active_id()
|
||||||
self._ext_settings.list_picon_size = int(self._picons_size_button.get_active_id())
|
self._ext_settings.list_picon_size = int(self._picons_size_button.get_active_id())
|
||||||
@@ -515,29 +545,8 @@ class SettingsDialog:
|
|||||||
if p_settings:
|
if p_settings:
|
||||||
row[0] = new_value
|
row[0] = new_value
|
||||||
self._profiles[new_value] = p_settings
|
self._profiles[new_value] = p_settings
|
||||||
self.update_local_paths(new_value, old_name)
|
|
||||||
self.on_profile_selected(self._profile_view, False)
|
self.on_profile_selected(self._profile_view, False)
|
||||||
|
|
||||||
def update_local_paths(self, p_name, old_name, force_rename=False):
|
|
||||||
data_path = self._settings.data_local_path
|
|
||||||
picons_path = self._settings.picons_local_path
|
|
||||||
backup_path = self._settings.backup_local_path
|
|
||||||
|
|
||||||
self._settings.data_local_path = p_name.join(data_path.rsplit(old_name, 1))
|
|
||||||
self._settings.picons_local_path = p_name.join(picons_path.rsplit(old_name, 1))
|
|
||||||
self._settings.backup_local_path = p_name.join(backup_path.rsplit(old_name, 1))
|
|
||||||
|
|
||||||
if force_rename:
|
|
||||||
try:
|
|
||||||
if os.path.isdir(picons_path):
|
|
||||||
os.rename(picons_path, self._settings.picons_local_path)
|
|
||||||
if os.path.isdir(data_path):
|
|
||||||
os.rename(data_path, self._settings.data_local_path)
|
|
||||||
if os.path.isdir(backup_path):
|
|
||||||
os.rename(backup_path, self._settings.backup_local_path)
|
|
||||||
except OSError as e:
|
|
||||||
self.show_info_message(str(e), Gtk.MessageType.ERROR)
|
|
||||||
|
|
||||||
def on_profile_selected(self, view, force=True):
|
def on_profile_selected(self, view, force=True):
|
||||||
if force:
|
if force:
|
||||||
self.on_apply_profile_settings()
|
self.on_apply_profile_settings()
|
||||||
@@ -566,6 +575,7 @@ class SettingsDialog:
|
|||||||
def on_main_settings_visible(self, stack, param):
|
def on_main_settings_visible(self, stack, param):
|
||||||
name = stack.get_visible_child_name()
|
name = stack.get_visible_child_name()
|
||||||
self._apply_presets_button.set_visible(name == "streaming")
|
self._apply_presets_button.set_visible(name == "streaming")
|
||||||
|
self._reset_button.set_visible(name == "profiles")
|
||||||
|
|
||||||
def on_http_use_ssl_toggled(self, button):
|
def on_http_use_ssl_toggled(self, button):
|
||||||
active = button.get_active()
|
active = button.get_active()
|
||||||
@@ -706,7 +716,7 @@ class SettingsDialog:
|
|||||||
|
|
||||||
@run_idle
|
@run_idle
|
||||||
def set_theme_thumbnail_image(self, theme_name):
|
def set_theme_thumbnail_image(self, theme_name):
|
||||||
img_path = "{}{}/gtk-3.0/thumbnail.png".format(self._ext_settings.themes_path, theme_name)
|
img_path = "{}{}{}gtk-3.0{}thumbnail.png".format(self._ext_settings.themes_path, theme_name, SEP, SEP)
|
||||||
self._theme_thumbnail_image.set_from_pixbuf(get_picon_pixbuf(img_path, 96))
|
self._theme_thumbnail_image.set_from_pixbuf(get_picon_pixbuf(img_path, 96))
|
||||||
|
|
||||||
def on_theme_add(self, button):
|
def on_theme_add(self, button):
|
||||||
|
|||||||
Reference in New Issue
Block a user