Commit d540da37 authored by Roman Alifanov's avatar Roman Alifanov

CustomSetting: Can now create a notification (Toast) as well as callbacks:

NOTIFY:some message:seconds
parent 8e32b9d5
...@@ -131,21 +131,50 @@ class CustomSetting: ...@@ -131,21 +131,50 @@ class CustomSetting:
def _get_default_row_index(self): def _get_default_row_index(self):
return list(self.map.values()).index(self.default) if self.default in self.map.values() else None return list(self.map.values()).index(self.default) if self.default in self.map.values() else None
def _execute_command(self, cmd, capture_output=True):
with subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
shell=True,
bufsize=1
) as p:
output = []
def process_line(line):
line = line.strip()
if not line:
return
if line.startswith('CALLBACK:'):
self._handle_callback(line)
elif line.startswith('NOTIFY:'):
self._handle_notify(line)
elif capture_output:
output.append(line)
while p.poll() is None:
line = p.stdout.readline()
process_line(line)
for line in p.stdout.read().splitlines():
process_line(line)
stderr = p.stderr.read().strip()
if p.returncode != 0:
raise subprocess.CalledProcessError(p.returncode, cmd, stderr=stderr)
return '\n'.join(output) if capture_output else ''
def _execute_get_command(self): def _execute_get_command(self):
if not self.get_command: if not self.get_command:
return self.default return self.default
try: try:
cmd = self._format_command(self.get_command) cmd = self._format_command(self.get_command)
result = subprocess.run( output = self._execute_command(cmd)
cmd, return output
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
shell=True
)
return self._process_output(result.stdout)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
self.logger.error(f"Get command failed: {e.stderr}") self.logger.error(f"Get command failed: {e.stderr}")
return self.default return self.default
...@@ -156,16 +185,7 @@ class CustomSetting: ...@@ -156,16 +185,7 @@ class CustomSetting:
try: try:
cmd = self._format_command(self.set_command, value) cmd = self._format_command(self.set_command, value)
result = subprocess.run( self._execute_command(cmd, capture_output=False)
cmd,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
shell=True
)
self._process_output(result.stdout)
return True return True
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
self.logger.error(f"Set command failed: {e.stderr}") self.logger.error(f"Set command failed: {e.stderr}")
...@@ -177,15 +197,8 @@ class CustomSetting: ...@@ -177,15 +197,8 @@ class CustomSetting:
try: try:
cmd = self._format_command(self.get_range_command) cmd = self._format_command(self.get_range_command)
result = subprocess.run( output = self._execute_command(cmd)
cmd, return ast.literal_eval(output)
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
shell=True
)
return ast.literal_eval(self._process_output(result.stdout))
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
self.logger.error(f"Get range command failed: {e.stderr}") self.logger.error(f"Get range command failed: {e.stderr}")
return None return None
...@@ -198,16 +211,6 @@ class CustomSetting: ...@@ -198,16 +211,6 @@ class CustomSetting:
} }
return template.format(**variables) return template.format(**variables)
def _process_output(self, output):
lines = []
for line in output.split('\n'):
line = line.strip()
if line.startswith('CALLBACK:'):
self._handle_callback(line)
else:
lines.append(line)
return '\n'.join(lines).strip()
def _handle_callback(self, line): def _handle_callback(self, line):
try: try:
_, action, target, value = line.split(':', 3) _, action, target, value = line.split(':', 3)
...@@ -219,6 +222,23 @@ class CustomSetting: ...@@ -219,6 +222,23 @@ class CustomSetting:
except ValueError: except ValueError:
self.logger.error(f"Invalid callback format: {line}") self.logger.error(f"Invalid callback format: {line}")
def _handle_notify(self, line):
self.logger.debug("handled notify")
try:
parts = line.split(':', 2)
parts += [None] * (3 - len(parts))
_, notification, seconds = parts
from ...main import get_main_window
get_main_window().setting_notify(
self.module.name,
self._(notification),
int(seconds) if seconds else None
)
except ValueError:
self.logger.error(f"Invalid notify format: {line}")
def _update_widget(self): def _update_widget(self):
if self.widget: if self.widget:
self.widget.update_display() self.widget.update_display()
......
...@@ -47,7 +47,7 @@ template $TuneitWindow: Adw.ApplicationWindow { ...@@ -47,7 +47,7 @@ template $TuneitWindow: Adw.ApplicationWindow {
name: "settings"; name: "settings";
title: _("Settings"); title: _("Settings");
child: Adw.NavigationSplitView settings_split_view { child: Adw.ToastOverlay settings_toast_overlay { child: Adw.NavigationSplitView settings_split_view {
hexpand: true; hexpand: true;
content: Adw.NavigationPage { content: Adw.NavigationPage {
...@@ -104,7 +104,7 @@ template $TuneitWindow: Adw.ApplicationWindow { ...@@ -104,7 +104,7 @@ template $TuneitWindow: Adw.ApplicationWindow {
} }
} }
}; };
}; }; };
} }
Adw.ViewStackPage { Adw.ViewStackPage {
...@@ -112,7 +112,7 @@ template $TuneitWindow: Adw.ApplicationWindow { ...@@ -112,7 +112,7 @@ template $TuneitWindow: Adw.ApplicationWindow {
name: "shop"; name: "shop";
title: _("Shop"); title: _("Shop");
child: Box {}; child: Box {};
} }
} }
......
...@@ -28,6 +28,9 @@ from .settings.widgets.error_dialog import TuneItErrorDialog ...@@ -28,6 +28,9 @@ from .settings.widgets.error_dialog import TuneItErrorDialog
class TuneitWindow(Adw.ApplicationWindow): class TuneitWindow(Adw.ApplicationWindow):
__gtype_name__ = 'TuneitWindow' __gtype_name__ = 'TuneitWindow'
settings_toast_overlay = Gtk.Template.Child()
settings_pagestack = Gtk.Template.Child() settings_pagestack = Gtk.Template.Child()
settings_listbox = Gtk.Template.Child() settings_listbox = Gtk.Template.Child()
settings_split_view = Gtk.Template.Child() settings_split_view = Gtk.Template.Child()
...@@ -58,12 +61,15 @@ class TuneitWindow(Adw.ApplicationWindow): ...@@ -58,12 +61,15 @@ class TuneitWindow(Adw.ApplicationWindow):
Можно вызвать вот так, благодаря сигналу: Можно вызвать вот так, благодаря сигналу:
self.settings_pagestack.get_root().emit("settings_page_update") self.settings_pagestack.get_root().emit("settings_page_update")
""" """
self.setting_notify("Tune It", "Init settings...")
try: try:
init_settings_stack( init_settings_stack(
self.settings_pagestack, self.settings_pagestack,
self.settings_listbox, self.settings_listbox,
self.settings_split_view, self.settings_split_view,
) )
self.setting_notify("Tune It", "Settings are initialized!")
except Exception as e: except Exception as e:
self.error(traceback.format_exc()) self.error(traceback.format_exc())
...@@ -72,3 +78,14 @@ class TuneitWindow(Adw.ApplicationWindow): ...@@ -72,3 +78,14 @@ class TuneitWindow(Adw.ApplicationWindow):
self.error_dialog.textbuffer.set_text(str(error)) self.error_dialog.textbuffer.set_text(str(error))
GLib.idle_add(self.error_dialog.present, self) GLib.idle_add(self.error_dialog.present, self)
def setting_notify(self, module_name: str, notify: str, seconds: int = 5) -> None:
seconds = 5 if seconds is None else seconds
GLib.idle_add(self.settings_toast_overlay.dismiss_all)
toast = Adw.Toast(
title=f"{module_name}: {notify}",
timeout=seconds,
)
GLib.idle_add(self.settings_toast_overlay.add_toast, toast)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment