329 lines
13 KiB
Python
329 lines
13 KiB
Python
from functools import partial
|
|
from itertools import chain
|
|
import os
|
|
import re
|
|
from PyQt5.QtWidgets import QAction, QActionGroup
|
|
from PyQt5.QtCore import pyqtSlot
|
|
from PyQt5.QtGui import QPixmap
|
|
from constants import Constants
|
|
from switchable_label import SwitchableLabelsIterable
|
|
from utilities import pop_up
|
|
|
|
|
|
class ThemeConstants:
|
|
FOLDER = "themes"
|
|
EXTENSION = ".qss"
|
|
ICONS_FOLDER = "icons"
|
|
DEFAULT = "1-system"
|
|
CURRENT = ".current_theme"
|
|
COLORS = "colors.txt"
|
|
COLOR_SEPARATOR = "="
|
|
DEFAULT_ACTIVE_COLOR = "#000000"
|
|
DEFAULT_INACTIVE_COLOR = "#9f9f9f"
|
|
DEFAULT_OFF_COLORS = "#000000", "#434343"
|
|
DEFAULT_ON_COLORS = "#4b79a1", "#283e51"
|
|
DEFAULT_TEXT_COLOR = "#ffffff"
|
|
THEME_NOT_FOUND = "Theme not found"
|
|
MISSING_THEME = "Missing theme in '" + FOLDER + "' folder."
|
|
|
|
class ThemeManager:
|
|
def __init__(self, parent):
|
|
self.__parent = parent
|
|
self.__parent.active_color = ThemeConstants.DEFAULT_ACTIVE_COLOR
|
|
self.__parent.inactive_color = ThemeConstants.DEFAULT_INACTIVE_COLOR
|
|
|
|
self.__theme_path = ""
|
|
self.__current_theme = ""
|
|
|
|
self.__parent.default_images_folder = os.path.join(
|
|
ThemeConstants.FOLDER,
|
|
ThemeConstants.DEFAULT,
|
|
ThemeConstants.ICONS_FOLDER
|
|
)
|
|
|
|
self.__space_weather_labels = SwitchableLabelsIterable(
|
|
*list(
|
|
chain(
|
|
self.__parent.switchable_r_labels,
|
|
self.__parent.switchable_s_labels,
|
|
self.__parent.switchable_g_now_labels,
|
|
self.__parent.switchable_g_today_labels,
|
|
self.__parent.k_storm_labels,
|
|
self.__parent.a_storm_labels,
|
|
[self.__parent.expected_noise_lbl]
|
|
)
|
|
)
|
|
)
|
|
|
|
self.__space_weather_labels.set(
|
|
"switch_on_colors",
|
|
ThemeConstants.DEFAULT_ON_COLORS
|
|
)
|
|
self.__space_weather_labels.set(
|
|
"switch_off_colors", ThemeConstants.DEFAULT_OFF_COLORS
|
|
)
|
|
|
|
self.__theme_names = {}
|
|
self.__detect_themes()
|
|
|
|
def __refresh_range_labels(self):
|
|
self.__parent.set_acf_interval_label()
|
|
self.__parent.set_band_filter_label(
|
|
self.__parent.activate_low_band_filter_btn,
|
|
self.__parent.lower_band_spinbox,
|
|
self.__parent.lower_band_filter_unit,
|
|
self.__parent.lower_band_confidence,
|
|
self.__parent.activate_up_band_filter_btn,
|
|
self.__parent.upper_band_spinbox,
|
|
self.__parent.upper_band_filter_unit,
|
|
self.__parent.upper_band_confidence,
|
|
self.__parent.band_range_lbl
|
|
)
|
|
|
|
self.__parent.set_band_filter_label(
|
|
self.__parent.activate_low_freq_filter_btn,
|
|
self.__parent.lower_freq_spinbox,
|
|
self.__parent.lower_freq_filter_unit,
|
|
self.__parent.lower_freq_confidence,
|
|
self.__parent.activate_up_freq_filter_btn,
|
|
self.__parent.upper_freq_spinbox,
|
|
self.__parent.upper_freq_filter_unit,
|
|
self.__parent.upper_freq_confidence,
|
|
self.__parent.freq_range_lbl
|
|
)
|
|
|
|
@pyqtSlot()
|
|
def __apply(self, theme_path):
|
|
self.__theme_path = theme_path
|
|
if self.__theme_path != self.__current_theme:
|
|
self.__change()
|
|
self.__parent.display_specs(
|
|
item=self.__parent.result_list.currentItem(),
|
|
previous_item=None
|
|
)
|
|
self.__refresh_range_labels()
|
|
self.__parent.audio_widget.refresh_btns_colors(
|
|
self.__parent.active_color,
|
|
self.__parent.inactive_color
|
|
)
|
|
self.__space_weather_labels.refresh()
|
|
|
|
def __pretty_name(self, bad_name):
|
|
return ' '.join(
|
|
map(lambda s: s.capitalize(),
|
|
bad_name.split('-')[1].split('_')
|
|
)
|
|
)
|
|
|
|
def __detect_themes(self):
|
|
themes = []
|
|
ag = QActionGroup(self.__parent, exclusive=True)
|
|
for theme_folder in os.listdir(ThemeConstants.FOLDER):
|
|
relative_folder = os.path.join(ThemeConstants.FOLDER, theme_folder)
|
|
if os.path.isdir(os.path.abspath(relative_folder)):
|
|
relative_folder = os.path.join(ThemeConstants.FOLDER, theme_folder)
|
|
themes.append(relative_folder)
|
|
for theme_path in themes:
|
|
theme_name = '&' + self.__pretty_name(os.path.basename(theme_path))
|
|
new_theme = ag.addAction(
|
|
QAction(
|
|
theme_name,
|
|
self.__parent, checkable=True
|
|
)
|
|
)
|
|
self.__parent.menu_themes.addAction(new_theme)
|
|
self.__theme_names[theme_name.lstrip('&')] = new_theme
|
|
new_theme.triggered.connect(partial(self.__apply, theme_path))
|
|
|
|
def __is_valid_html_color(self, colors):
|
|
pattern = "#([a-zA-Z0-9]){6}"
|
|
match_ok = lambda col: bool(re.match(pattern, col))
|
|
if isinstance(colors, list):
|
|
if len(colors) > 1:
|
|
return all(match_ok(c) for c in colors)
|
|
else:
|
|
return match_ok(colors[0])
|
|
else:
|
|
return match_ok(colors)
|
|
|
|
def __change(self):
|
|
theme_name = os.path.basename(self.__theme_path).split('-')[1] + ThemeConstants.EXTENSION
|
|
try:
|
|
with open(
|
|
os.path.join(self.__theme_path, theme_name), "r"
|
|
) as stylesheet:
|
|
style = stylesheet.read()
|
|
self.__parent.setStyleSheet(style)
|
|
self.__parent.download_window.setStyleSheet(style)
|
|
except FileNotFoundError:
|
|
pop_up(self.__parent, title=ThemeConstants.THEME_NOT_FOUND,
|
|
text=ThemeConstants.MISSING_THEME).show()
|
|
else:
|
|
icons_path = os.path.join(self.__theme_path, ThemeConstants.ICONS_FOLDER)
|
|
default_icons_path = os.path.join(
|
|
ThemeConstants.FOLDER,
|
|
ThemeConstants.DEFAULT,
|
|
ThemeConstants.ICONS_FOLDER
|
|
)
|
|
|
|
if os.path.exists(os.path.join(icons_path, Constants.NOT_SELECTED)) and \
|
|
os.path.exists(os.path.join(icons_path, Constants.NOT_AVAILABLE)):
|
|
self.__parent.default_images_folder = icons_path
|
|
else:
|
|
self.__parent.default_images_folder = default_icons_path
|
|
|
|
path_to_search_label = os.path.join(
|
|
icons_path,
|
|
Constants.SEARCH_LABEL_IMG
|
|
)
|
|
default_search_label = os.path.join(
|
|
default_icons_path,
|
|
Constants.SEARCH_LABEL_IMG
|
|
)
|
|
|
|
if os.path.exists(path_to_search_label):
|
|
self.__parent.search_label.setPixmap(
|
|
QPixmap(path_to_search_label)
|
|
)
|
|
self.__parent.modulation_search_label.setPixmap(
|
|
QPixmap(path_to_search_label)
|
|
)
|
|
self.__parent.location_search_label.setPixmap(
|
|
QPixmap(path_to_search_label)
|
|
)
|
|
else:
|
|
self.__parent.search_label.setPixmap(
|
|
QPixmap(default_search_label)
|
|
)
|
|
self.__parent.modulation_search_label.setPixmap(
|
|
QPixmap(default_search_label)
|
|
)
|
|
self.__parent.location_search_label.setPixmap(
|
|
QPixmap(default_search_label)
|
|
)
|
|
|
|
self.__parent.search_label.setScaledContents(True)
|
|
self.__parent.modulation_search_label.setScaledContents(True)
|
|
self.__parent.location_search_label.setScaledContents(True)
|
|
|
|
path_to_volume_label = os.path.join(
|
|
icons_path,
|
|
Constants.VOLUME_LABEL_IMG
|
|
)
|
|
default_volume_label = os.path.join(
|
|
default_icons_path,
|
|
Constants.VOLUME_LABEL_IMG
|
|
)
|
|
|
|
if os.path.exists(path_to_volume_label):
|
|
self.__parent.volume_label.setPixmap(
|
|
QPixmap(path_to_volume_label)
|
|
)
|
|
else:
|
|
self.__parent.volume_label.setPixmap(
|
|
QPixmap(default_volume_label)
|
|
)
|
|
|
|
self.__parent.volume_label.setScaledContents(True)
|
|
|
|
path_to_colors = os.path.join(
|
|
self.__theme_path,
|
|
ThemeConstants.COLORS
|
|
)
|
|
|
|
active_color_ok = False
|
|
inactive_color_ok = False
|
|
switch_on_color_ok = False
|
|
switch_off_color_ok = False
|
|
text_color_ok = False
|
|
|
|
if os.path.exists(path_to_colors):
|
|
with open(path_to_colors, "r") as colors_file:
|
|
for line in colors_file:
|
|
if ThemeConstants.COLOR_SEPARATOR in line:
|
|
quality, color = line.split(ThemeConstants.COLOR_SEPARATOR)
|
|
color = color.rstrip()
|
|
color_len = 1
|
|
if ',' in color:
|
|
color = [c.strip() for c in color.split(',')]
|
|
color_len = len(color)
|
|
if self.__is_valid_html_color(color):
|
|
if color_len == 1:
|
|
if quality.lower() == Constants.ACTIVE:
|
|
self.__parent.active_color = color
|
|
active_color_ok = True
|
|
if quality.lower() == Constants.INACTIVE:
|
|
self.__parent.inactive_color = color
|
|
inactive_color_ok = True
|
|
if quality.lower() == Constants.TEXT_COLOR:
|
|
text_color_ok = True
|
|
self.__space_weather_labels.set(
|
|
"text_color",
|
|
color
|
|
)
|
|
if color_len == 2:
|
|
if quality.lower() == Constants.LABEL_ON_COLOR:
|
|
switch_on_color_ok = True
|
|
self.__space_weather_labels.set(
|
|
"switch_on_colors",
|
|
color
|
|
)
|
|
if quality.lower() == Constants.LABEL_OFF_COLOR:
|
|
switch_off_color_ok = True
|
|
self.__space_weather_labels.set(
|
|
"switch_off_colors",
|
|
color
|
|
)
|
|
|
|
if not (active_color_ok and inactive_color_ok):
|
|
self.__parent.active_color = ThemeConstants.DEFAULT_ACTIVE_COLOR
|
|
self.__parent.inactive_color = ThemeConstants.DEFAULT_INACTIVE_COLOR
|
|
|
|
if not (switch_on_color_ok and switch_off_color_ok):
|
|
self.__space_weather_labels.set(
|
|
"switch_on_colors",
|
|
ThemeConstants.DEFAULT_ON_COLORS
|
|
)
|
|
self.__space_weather_labels.set(
|
|
"switch_off_colors",
|
|
ThemeConstants.DEFAULT_OFF_COLORS
|
|
)
|
|
|
|
if not text_color_ok:
|
|
self.__space_weather_labels.set(
|
|
"text_color",
|
|
ThemeConstants.DEFAULT_TEXT_COLOR
|
|
)
|
|
self.__current_theme = self.__theme_path
|
|
|
|
try:
|
|
with open(os.path.join(
|
|
ThemeConstants.FOLDER,
|
|
ThemeConstants.CURRENT
|
|
), "w") as current_theme:
|
|
current_theme.write(self.__theme_path)
|
|
except Exception:
|
|
pass
|
|
|
|
def start(self):
|
|
current_theme_file = os.path.join(
|
|
ThemeConstants.FOLDER,
|
|
ThemeConstants.CURRENT
|
|
)
|
|
if os.path.exists(current_theme_file):
|
|
with open(current_theme_file, "r") as current_theme_path:
|
|
theme_path = current_theme_path.read()
|
|
theme_name = self.__pretty_name(os.path.basename(theme_path))
|
|
self.__theme_names[theme_name].setChecked(True)
|
|
self.__apply(theme_path)
|
|
else:
|
|
self.__theme_names[
|
|
self.__pretty_name(ThemeConstants.DEFAULT)
|
|
].setChecked(True)
|
|
self.__apply(
|
|
os.path.join(
|
|
ThemeConstants.FOLDER,
|
|
ThemeConstants.DEFAULT
|
|
)
|
|
)
|