Skip to content

Commit

Permalink
Cancel theme timer on app close
Browse files Browse the repository at this point in the history
Fixes a locking issue when the app was closed from the tray.
  • Loading branch information
chase9 committed Jan 4, 2025
1 parent 5bd1c72 commit 2c4c124
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 63 deletions.
19 changes: 11 additions & 8 deletions yin_yang/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from argparse import ArgumentParser
from logging.handlers import RotatingFileHandler
from pathlib import Path
from threading import Timer

from PySide6 import QtWidgets
from PySide6.QtCore import QLibraryInfo, QLocale, QTranslator
Expand All @@ -17,10 +18,16 @@
from yin_yang.helpers import is_flatpak
from yin_yang.meta import ConfigEvent
from yin_yang.notification_handler import NotificationHandler
from yin_yang.scheduler import Scheduler
from yin_yang.ui import main_window_connector

logger = logging.getLogger()
timer = Timer(45, theme_switcher.set_desired_theme)

if is_flatpak():
timer.daemon = True
timer.interval = 45
timer.name = "Yin-Yang Timer"
timer.start()


def setup_logger(use_systemd_journal: bool):
Expand Down Expand Up @@ -120,7 +127,9 @@ def systray_icon_clicked(reason: QSystemTrayIcon.ActivationReason):

except Exception as e:
logger.warning(str(e))
print('The app has not been translated to your language yet. Using default language.')
print(
'The app has not been translated to your language yet. Using default language.'
)

# show systray icon
if QSystemTrayIcon.isSystemTrayAvailable():
Expand Down Expand Up @@ -154,12 +163,6 @@ def systray_icon_clicked(reason: QSystemTrayIcon.ActivationReason):
else:
logger.debug('System tray is unsupported')

# Start the timer to handle automatic theme switching. We only need this
# currently if running in a flatpak as systemd units are not supported.
if is_flatpak:
timer = Scheduler(45, theme_switcher.set_desired_theme)
timer.start()

if arguments.minimized:
sys.exit(app.exec())
else:
Expand Down
11 changes: 0 additions & 11 deletions yin_yang/scheduler.py

This file was deleted.

141 changes: 97 additions & 44 deletions yin_yang/ui/main_window_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@

from PySide6 import QtWidgets
from PySide6.QtCore import QStandardPaths
from PySide6.QtGui import QScreen, QColor
from PySide6.QtWidgets import QFileDialog, QMessageBox, QDialogButtonBox, QColorDialog, QGroupBox

from .main_window import Ui_main_window
from ..theme_switcher import set_desired_theme, set_mode
from PySide6.QtGui import QColor, QScreen
from PySide6.QtWidgets import (
QColorDialog,
QDialogButtonBox,
QFileDialog,
QGroupBox,
QMessageBox,
)

from ..config import ConfigWatcher, Modes, config, plugins
from ..meta import ConfigEvent, PluginKey
from ..config import config, Modes, plugins, ConfigWatcher
from ..theme_switcher import set_desired_theme, set_mode
from .main_window import Ui_main_window

logger = logging.getLogger(__name__)

Expand All @@ -28,10 +34,7 @@ def notify(self, event: ConfigEvent, values: dict):


def reverse_dict_search(dictionary, value):
return next(
key for key, value_dict in dictionary.items()
if value_dict == value
)
return next(key for key, value_dict in dictionary.items() if value_dict == value)


class MainWindow(QtWidgets.QMainWindow):
Expand Down Expand Up @@ -65,8 +68,9 @@ def load(self):
"""Sets the values from the config to the elements"""

# set current version in statusbar
self.ui.status_bar.showMessage(self.tr('You are using version {}', '')
.format(str(config.version)))
self.ui.status_bar.showMessage(
self.tr('You are using version {}', '').format(str(config.version))
)

# set the correct mode
mode = config.mode
Expand All @@ -81,7 +85,9 @@ def load(self):
self.ui.btn_schedule.setChecked(True)
self.ui.location.setVisible(False)

self.ui.toggle_notification.setChecked(config.get_plugin_key('notification', PluginKey.ENABLED))
self.ui.toggle_notification.setChecked(
config.get_plugin_key('notification', PluginKey.ENABLED)
)
self.ui.bootOffset.setValue(config.boot_offset)

# sets the correct time based on config
Expand Down Expand Up @@ -110,7 +116,10 @@ def load_location(self):

def load_plugins(self):
# First, remove sample plugin
sample_plugin = cast(QGroupBox, self.ui.plugins_scroll_content.findChild(QGroupBox, 'samplePluginGroupBox'))
sample_plugin = cast(
QGroupBox,
self.ui.plugins_scroll_content.findChild(QGroupBox, 'samplePluginGroupBox'),
)
sample_plugin.hide()

widget: QGroupBox
Expand All @@ -119,45 +128,74 @@ def load_plugins(self):
if plugin.name.casefold() == 'notification':
continue

widget = cast(QGroupBox, self.ui.plugins_scroll_content.findChild(QGroupBox, 'group' + plugin.name))
widget = cast(
QGroupBox,
self.ui.plugins_scroll_content.findChild(
QGroupBox, 'group' + plugin.name
),
)
if widget is None:
widget = plugin.get_widget(self.ui.plugins_scroll_content)
self.ui.plugins_scroll_content_layout.addWidget(widget)

assert widget is not None, f'No widget for plugin {plugin.name} found'

widget.toggled.connect(
lambda enabled, p=plugin:
config.update_plugin_key(p.name, PluginKey.ENABLED, enabled))
lambda enabled, p=plugin: config.update_plugin_key(
p.name, PluginKey.ENABLED, enabled
)
)

if plugin.available_themes:
# uses combobox instead of line edit
for child in widget.findChildren(QtWidgets.QComboBox):
is_dark: bool = widget.findChildren(QtWidgets.QComboBox).index(child) == 1
is_dark: bool = (
widget.findChildren(QtWidgets.QComboBox).index(child) == 1
)
child.currentTextChanged.connect(
lambda text, p=plugin, dark=is_dark: config.update_plugin_key(
p.name,
PluginKey.THEME_DARK if dark else PluginKey.THEME_LIGHT,
reverse_dict_search(p.available_themes, text)))
reverse_dict_search(p.available_themes, text),
)
)
else:
children: [QtWidgets.QLineEdit] = widget.findChildren(QtWidgets.QLineEdit)
children: [QtWidgets.QLineEdit] = widget.findChildren(
QtWidgets.QLineEdit
)
children[0].textChanged.connect(
lambda text, p=plugin: config.update_plugin_key(p.name, PluginKey.THEME_LIGHT, text))
lambda text, p=plugin: config.update_plugin_key(
p.name, PluginKey.THEME_LIGHT, text
)
)
children[1].textChanged.connect(
lambda text, p=plugin: config.update_plugin_key(p.name, PluginKey.THEME_DARK, text))
lambda text, p=plugin: config.update_plugin_key(
p.name, PluginKey.THEME_DARK, text
)
)

if plugin.name == 'Wallpaper':
children: [QtWidgets.QPushButton] = widget.findChildren(QtWidgets.QDialogButtonBox)
children: [QtWidgets.QPushButton] = widget.findChildren(
QtWidgets.QDialogButtonBox
)
children[0].clicked.connect(lambda: self.select_wallpaper(False))
children[1].clicked.connect(lambda: self.select_wallpaper(True))
elif plugin.name == 'Brave':
buttons: [QtWidgets.QPushButton] = widget.findChildren(QtWidgets.QPushButton)
buttons: [QtWidgets.QPushButton] = widget.findChildren(
QtWidgets.QPushButton
)
# this could be a loop, but it didn't work somehow
color_str_0 = config.get_plugin_key(plugin.name, PluginKey.THEME_LIGHT)
color_str_0 = config.get_plugin_key(
plugin.name, PluginKey.THEME_LIGHT
)
color_0 = QColor(color_str_0)
buttons[0].clicked.connect(lambda: self.select_color(False, color_0))
buttons[0].clicked.connect(
lambda: self.select_color(False, color_0)
)

color_str_1 = config.get_plugin_key(plugin.name, PluginKey.THEME_DARK)
color_str_1 = config.get_plugin_key(
plugin.name, PluginKey.THEME_DARK
)
color_1 = QColor(color_str_1)
buttons[1].clicked.connect(lambda: self.select_color(True, color_1))
plugin = None
Expand All @@ -166,8 +204,10 @@ def update_label_enabled(self):
time_light = self.ui.inp_time_light.time().toPython()
time_dark = self.ui.inp_time_dark.time().toPython()
self.ui.label_active.setText(
self.tr('Dark mode will be active between {} and {}.')
.format(time_dark.strftime("%H:%M"), time_light.strftime("%H:%M")))
self.tr('Dark mode will be active between {} and {}.').format(
time_dark.strftime("%H:%M"), time_light.strftime("%H:%M")
)
)

def setup_config_sync(self):
# set sunrise and sunset times if mode is set to followSun or coordinates changed
Expand All @@ -186,7 +226,10 @@ def setup_config_sync(self):
self.ui.btn_box.clicked.connect(self.save_config_to_file)

self.ui.toggle_notification.toggled.connect(
lambda enabled: config.update_plugin_key('notification', PluginKey.ENABLED, enabled))
lambda enabled: config.update_plugin_key(
'notification', PluginKey.ENABLED, enabled
)
)

self.ui.bootOffset.valueChanged.connect(self.update_boot_offset)

Expand Down Expand Up @@ -230,10 +273,7 @@ def update_location(self):
elif not config.update_location:
self.ui.location_input.setEnabled(True)

coordinates = [
self.ui.inp_latitude.value(),
self.ui.inp_longitude.value()
]
coordinates = [self.ui.inp_latitude.value(), self.ui.inp_longitude.value()]
config.location = coordinates
# update message and times
self.load_times()
Expand All @@ -242,23 +282,31 @@ def select_wallpaper(self, dark: bool):
message_light = self.tr('Open light wallpaper')
message_dark = self.tr('Open dark wallpaper')
file_name, _ = QFileDialog.getOpenFileName(
self, message_dark if dark else message_light,
self,
message_dark if dark else message_light,
QStandardPaths.standardLocations(QStandardPaths.PicturesLocation)[0],
'Images (*.png *.jpg *.jpeg *.JPG *.JPEG)')
'Images (*.png *.jpg *.jpeg *.JPG *.JPEG)',
)

group_wallpaper = self.ui.plugins_scroll_content.findChild(QtWidgets.QGroupBox, 'groupWallpaper')
group_wallpaper = self.ui.plugins_scroll_content.findChild(
QtWidgets.QGroupBox, 'groupWallpaper'
)
inputs_wallpaper = group_wallpaper.findChildren(QtWidgets.QLineEdit)
i = 1 if dark else 0
inputs_wallpaper[i].setText(file_name)

def select_color(self, dark: bool, initial_color: QColor):
selected_color = QColorDialog.getColor(initial_color)
group_brave = self.ui.plugins_scroll_content.findChild(QtWidgets.QGroupBox, 'groupBrave')
group_brave = self.ui.plugins_scroll_content.findChild(
QtWidgets.QGroupBox, 'groupBrave'
)
inputs_brave = group_brave.findChildren(QtWidgets.QLineEdit)
i = 1 if dark else 0
inputs_brave[i].setText(selected_color.name())
inputs_brave[i].setStyleSheet(f'background-color: {selected_color.name()};'
f' color: {"white" if selected_color.lightness() <= 128 else "black"}')
inputs_brave[i].setStyleSheet(
f'background-color: {selected_color.name()};'
f' color: {"white" if selected_color.lightness() <= 128 else "black"}'
)

def save_config_to_file(self, button):
"""Saves the config to the file or restores values"""
Expand All @@ -284,10 +332,15 @@ def should_close(self) -> bool:

# ask the user if he wants to save changes
if self.config_changed:
message = self.tr('The settings have been modified. Do you want to save them?')
ret = QMessageBox.warning(self, self.tr('Unsaved changes'),
message,
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
message = self.tr(
'The settings have been modified. Do you want to save them?'
)
ret = QMessageBox.warning(
self,
self.tr('Unsaved changes'),
message,
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel,
)
match ret:
case QMessageBox.Save:
# emulate click on apply-button
Expand Down

0 comments on commit 2c4c124

Please sign in to comment.