From 1b750343172af40eb847e50dc614f774a22832dc Mon Sep 17 00:00:00 2001 From: DYefremov Date: Sun, 19 Dec 2021 13:15:58 +0300 Subject: [PATCH] basic alternate layout support --- app/ui/app_menu.ui | 12 +++++ app/ui/control.py | 81 ++++++++++++++++++++-------------- app/ui/main.glade | 16 +------ app/ui/main.py | 107 ++++++++++++++++++++++++++++++++++----------- 4 files changed, 144 insertions(+), 72 deletions(-) diff --git a/app/ui/app_menu.ui b/app/ui/app_menu.ui index 357b29d7..3f9d12f8 100644 --- a/app/ui/app_menu.ui +++ b/app/ui/app_menu.ui @@ -133,6 +133,12 @@ action-disabled +
+ + Alternate layout + app.set_alternate_layout + +
Tools @@ -323,6 +329,12 @@ action-disabled +
+ + Alternate layout + app.set_alternate_layout + +
Tools diff --git a/app/ui/control.py b/app/ui/control.py index 49e1bbdd..edce1072 100644 --- a/app/ui/control.py +++ b/app/ui/control.py @@ -126,7 +126,7 @@ class EpgTool(Gtk.Box): start = int(event.get("e2eventstart", "0")) start_time = datetime.fromtimestamp(start) end_time = datetime.fromtimestamp(start + int(event.get("e2eventduration", "0"))) - time = "{} - {}".format(start_time.strftime("%A, %H:%M"), end_time.strftime("%H:%M")) + time = f"{start_time.strftime('%A, %H:%M')} - {end_time.strftime('%H:%M')}" return title, time, desc, event @@ -223,7 +223,7 @@ class TimerTool(Gtk.Box): elif self._action is TimerTool.TimerAction.EVENT: self.set_timer_from_event_data() else: - log("{} error: No action set for timer!".format(__class__.__name__)) + log(f"{__class__.__name__} error: No action set for timer!") @property def request(self): @@ -242,34 +242,34 @@ class TimerTool(Gtk.Box): s_ref = quote(t_data.get("sRef", "")) if self._action is TimerTool.TimerAction.EVENT: - args.append("timeraddbyeventid?sRef={}".format(s_ref)) - args.append("eventid={}".format(t_data.get("eit", "0"))) - args.append("justplay={}".format(t_data.get("justplay", ""))) - args.append("tags={}".format("")) + args.append(f"timeraddbyeventid?sRef={s_ref}") + args.append(f"eventid={t_data.get('eit', '0')}") + args.append(f"justplay={t_data.get('justplay', '')}") + args.append(f"tags={''}") else: if self._action is TimerTool.TimerAction.ADD: - args.append("timeradd?sRef={}".format(s_ref)) - args.append("deleteOldOnSave={}".format(0)) + args.append(f"timeradd?sRef={s_ref}") + args.append(f"deleteOldOnSave={0}") elif self._action is TimerTool.TimerAction.CHANGE: - args.append("timerchange?sRef={}".format(s_ref)) - args.append("channelOld={}".format(s_ref)) - args.append("beginOld={}".format(self._timer_data.get("e2timebegin", "0"))) - args.append("endOld={}".format(self._timer_data.get("e2timeend", "0"))) - args.append("deleteOldOnSave={}".format(1)) + args.append(f"timerchange?sRef={s_ref}") + args.append(f"channelOld={s_ref}") + args.append(f"beginOld={self._timer_data.get('e2timebegin', '0')}") + args.append(f"endOld={self._timer_data.get('e2timeend', '0')}") + args.append(f"deleteOldOnSave={1}") - args.append("begin={}".format(t_data.get("begin", ""))) - args.append("end={}".format(t_data.get("end", ""))) - args.append("name={}".format(quote(t_data.get("name", "")))) - args.append("description={}".format(quote(t_data.get("description", "")))) - args.append("tags={}".format("")) - args.append("eit={}".format("0")) - args.append("disabled={}".format(t_data.get("disabled", "1"))) - args.append("justplay={}".format(t_data.get("justplay", "1"))) - args.append("afterevent={}".format(t_data.get("afterevent", "0"))) - args.append("repeated={}".format(TimerTool.get_repetition_flags(self._days_buttons))) + args.append(f"begin={t_data.get('begin', '')}") + args.append(f"end={t_data.get('end', '')}") + args.append(f"name={quote(t_data.get('name', ''))}") + args.append(f"description={quote(t_data.get('description', ''))}") + args.append(f"tags={''}") + args.append(f"eit={'0'}") + args.append(f"disabled={t_data.get('disabled', '1')}") + args.append(f"justplay={t_data.get('justplay', '1')}") + args.append(f"afterevent={t_data.get('afterevent', '0')}") + args.append(f"repeated={TimerTool.get_repetition_flags(self._days_buttons)}") if self._timer_location_switch.get_active(): - args.append("dirname={}".format(self._timer_location_entry.get_text())) + args.append(f"dirname={self._timer_location_entry.get_text()}") return "&".join(args) @@ -292,8 +292,7 @@ class TimerTool(Gtk.Box): self._timer_begins_min_button.set_value(minute) self._timer_begins_calendar.select_day(date.day) self._timer_begins_calendar.select_month(date.month - 1, date.year) - self._timer_begins_entry.set_text( - "{}-{}-{} {}:{:02d}".format(date.year, date.month, date.day, hour, minute)) + self._timer_begins_entry.set_text(f"{date.year}-{date.month}-{date.day} {hour}:{minute:02d}") def get_ends_date(self): date = self._timer_ends_calendar.get_date() @@ -308,7 +307,7 @@ class TimerTool(Gtk.Box): self._timer_ends_min_button.set_value(minute) self._timer_ends_calendar.select_day(date.day) self._timer_ends_calendar.select_month(date.month - 1, date.year) - self._timer_ends_entry.set_text("{}-{}-{} {}:{:02d}".format(date.year, date.month, date.day, hour, minute)) + self._timer_ends_entry.set_text(f"{date.year}-{date.month}-{date.day} {hour}:{minute:02d}") def set_timer_for_add(self): self._timer_service_entry.set_text(self._timer_data.get("e2servicename", "")) @@ -446,7 +445,7 @@ class TimerTool(Gtk.Box): service = timer.get("e2servicename", "") or "" start_time = datetime.fromtimestamp(int(timer.get("e2timebegin", "0"))) end_time = datetime.fromtimestamp(int(timer.get("e2timeend", "0"))) - time = "{} - {}".format(start_time.strftime("%A, %H:%M"), end_time.strftime("%H:%M")) + time = f"{start_time.strftime('%A, %H:%M')} - {end_time.strftime('%H:%M')}" return disabled, name, service, time, description, timer @@ -486,7 +485,7 @@ class TimerTool(Gtk.Box): @run_idle def timer_add_edit_callback(self, resp): if "error_code" in resp: - msg = "Error getting timer status.\n{}".format(resp.get("error_code")) + msg = f"Error getting timer status.\n{resp.get('error_code')}" self._app.show_error_message(msg) log(msg) return @@ -628,7 +627,7 @@ class TimerTool(Gtk.Box): service = self._app.current_services.get(fav_id, None) if service: if service.service_type == BqServiceType.ALT.name: - msg = "Alternative service.\n\n {}".format(get_message("Not implemented yet!")) + msg = "Alternative service.\n\n {get_message('Not implemented yet!')}" show_dialog(DialogType.ERROR, transient=self._app._main_window, text=msg) context.finish(False, False, time) return @@ -647,6 +646,7 @@ class RecordingsTool(Gtk.Box): super().__init__(*args, **kwargs) self._app = app + self._app.connect("layout-changed", self.on_layout_changed) self._app.connect("profile-changed", self.init) self._settings = settings self._ftp = None @@ -666,6 +666,8 @@ class RecordingsTool(Gtk.Box): self._paths_view = builder.get_object("recordings_paths_view") self._paned = builder.get_object("recordings_paned") self.pack_start(builder.get_object("recordings_frame"), True, True, 0) + if settings.alternate_layout: + self.on_layout_changed(app, True) self.init() self.show() @@ -674,6 +676,14 @@ class RecordingsTool(Gtk.Box): self._rec_view.get_model().clear() self._paths_view.get_model().clear() + def on_layout_changed(self, app, alt_layout): + ch1 = self._paned.get_child1() + ch2 = self._paned.get_child2() + self._paned.remove(ch1) + self._paned.remove(ch2) + self._paned.add1(ch2) + self._paned.add(ch1) + @run_task def init(self, app=None, arg=None): GLib.idle_add(self.clear_data) @@ -801,6 +811,7 @@ class ControlTool(Gtk.Box): self._settings = settings self._app = app + self._app.connect("layout-changed", self.on_layout_changed) self._pix = None handlers = {"on_volume_changed": self.on_volume_changed, @@ -810,7 +821,7 @@ class ControlTool(Gtk.Box): objects=("control_box", "volume_adjustment")) self.pack_start(builder.get_object("control_box"), True, True, 0) - self._stack = builder.get_object("stack") + self._remote_box = builder.get_object("remote_box") self._screenshot_area = builder.get_object("screenshot_area") self._screenshot_button_box = builder.get_object("screenshot_button_box") self._screenshot_check_button = builder.get_object("screenshot_check_button") @@ -823,6 +834,9 @@ class ControlTool(Gtk.Box): self._agc_level_bar = builder.get_object("agc_level_bar") self._volume_button = builder.get_object("volume_button") self.init_actions(app) + if settings.alternate_layout: + self.on_layout_changed(app, True) + self.show() def init_actions(self, app): @@ -856,6 +870,9 @@ class ControlTool(Gtk.Box): app.set_action("on_screenshot_video", self.on_screenshot_video) app.set_action("on_screenshot_osd", self.on_screenshot_osd) + def on_layout_changed(self, app, alt_layout): + self._remote_box.reorder_child(self._remote_box.get_children()[0], 1) + # ***************** Remote controller ********************* # def on_remote(self, action, state=False): @@ -875,7 +892,7 @@ class ControlTool(Gtk.Box): @run_with_delay(0.5) def on_volume_changed(self, button, value): - self._app.send_http_request(HttpAPI.Request.VOL, "{:.0f}".format(value), self.on_response) + self._app.send_http_request(HttpAPI.Request.VOL, f"{value:.0f}", self.on_response) def update_volume(self, vol): if "error_code" in vol: diff --git a/app/ui/main.glade b/app/ui/main.glade index 458b7004..6ab004ed 100644 --- a/app/ui/main.glade +++ b/app/ui/main.glade @@ -1311,6 +1311,8 @@ Author: Dmitriy Yefremov True False + 5 + 5 True True @@ -1382,7 +1384,6 @@ Author: Dmitriy Yefremov True False - 5 0.49000000953674316 in @@ -2262,8 +2263,6 @@ Author: Dmitriy Yefremov True False - 5 - 5 2 vertical @@ -2281,7 +2280,6 @@ Author: Dmitriy Yefremov True False - 5 2 vertical @@ -2299,7 +2297,6 @@ Author: Dmitriy Yefremov True False - 5 2 vertical @@ -2317,7 +2314,6 @@ Author: Dmitriy Yefremov True False - 5 2 vertical @@ -2335,8 +2331,6 @@ Author: Dmitriy Yefremov True False - 5 - 5 2 vertical @@ -2354,8 +2348,6 @@ Author: Dmitriy Yefremov True False - 5 - 5 2 vertical @@ -2373,9 +2365,6 @@ Author: Dmitriy Yefremov True False - 5 - 5 - 2 @@ -2397,7 +2386,6 @@ Author: Dmitriy Yefremov 350 False - 5 True True diff --git a/app/ui/main.py b/app/ui/main.py index a0d5877e..2b5fca77 100644 --- a/app/ui/main.py +++ b/app/ui/main.py @@ -265,6 +265,8 @@ class Application(Gtk.Application): GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.signal_new("change-page", self, GObject.SIGNAL_RUN_LAST, GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) + GObject.signal_new("layout-changed", self, GObject.SIGNAL_RUN_LAST, + GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.signal_new("play-recording", self, GObject.SIGNAL_RUN_LAST, GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) GObject.signal_new("play-current", self, GObject.SIGNAL_RUN_LAST, @@ -280,6 +282,8 @@ class Application(Gtk.Application): self._main_window = builder.get_object("main_window") self._stack = builder.get_object("stack") self._fav_paned = builder.get_object("fav_paned") + self._bq_frame = builder.get_object("bq_frame") + self._fav_frame = builder.get_object("fav_frame") self._services_view = builder.get_object("services_tree_view") self._fav_view = builder.get_object("fav_tree_view") self._bouquets_view = builder.get_object("bouquets_tree_view") @@ -363,17 +367,13 @@ class Application(Gtk.Application): self._fav_search_button.connect("toggled", fav_search_provider.on_search_toggled) # Playback. self._player_box = PlayerBox(self) - paned = builder.get_object("main_paned") - data_paned = paned.get_child1() - paned.remove(data_paned) self._player_box.bind_property("visible", self._profile_combo_box, "visible", 4) - paned.pack1(self._player_box, True, False) - paned.pack2(data_paned, True, False) self._player_box.connect("show", self.on_playback_show) self._player_box.connect("playback-close", self.on_playback_close) self._player_box.connect("playback-full-screen", self.on_playback_full_screen) self._data_paned = builder.get_object("data_paned") self._data_paned.bind_property("visible", self._status_bar_box, "visible") + self._main_paned = builder.get_object("main_paned") # Record. self._record_image = builder.get_object("record_button_image") # Dynamically active elements depending on the selected view. @@ -469,6 +469,7 @@ class Application(Gtk.Application): self.init_actions() self.set_accels() + self.init_layout() self.init_drag_and_drop() self.init_appearance() @@ -530,6 +531,9 @@ class Application(Gtk.Application): sa = self.set_state_action("show_control", self.on_page_show, self._settings.get("show_control", True)) sa.connect("change-state", lambda a, v: self._stack_control_box.set_visible(v)) self.bind_property("is-enigma", sa, "enabled") + # Alternate layout. + sa = self.set_state_action("set_alternate_layout", self.set_use_alt_layout, self._settings.alternate_layout) + sa.connect("change-state", self.on_layout_change) # Menu bar and playback. self.set_action("on_playback_close", self._player_box.on_close) if not IS_GNOME_SESSION: @@ -701,6 +705,27 @@ class Application(Gtk.Application): self._NEW_COLOR = new_rgb self._EXTRA_COLOR = extra_rgb + def init_layout(self): + """ Initializes an alternate layout, if enabled. """ + if self._settings.alternate_layout: + self._main_paned.pack2(self._player_box, True, False) + self.reverse_main_elements(True) + else: + self._main_paned.remove(self._data_paned) + self._main_paned.pack1(self._player_box, True, False) + self._main_paned.pack2(self._data_paned, True, False) + + def init_bq_position(self): + self._fav_paned.remove(self._fav_frame) + self._fav_paned.remove(self._bq_frame) + + if self._settings.alternate_layout: + self._fav_paned.pack1(self._bq_frame, True, False) + self._fav_paned.pack2(self._fav_frame, True, False) + else: + self._fav_paned.pack1(self._fav_frame, True, False) + self._fav_paned.pack2(self._bq_frame, True, False) + def init_main_paned_position(self, paned): """ Initializes starting positions of main paned widgets. """ width = paned.get_allocated_width() @@ -791,40 +816,47 @@ class Application(Gtk.Application): # ************** Pages initialization *************** # def on_satellites_realize(self, box): - self._satellite_tool = SatellitesTool(self, self._settings) - box.pack_start(self._satellite_tool, True, True, 0) + if not self._satellite_tool: + self._satellite_tool = SatellitesTool(self, self._settings) + box.pack_start(self._satellite_tool, True, True, 0) def on_picons_realize(self, box): - ids = {} - if self._s_type is SettingsType.ENIGMA_2: - for r in self._services_model: - data = r[Column.SRV_PICON_ID].split("_") - ids[f"{data[3]}:{data[5]}:{data[6]}"] = r[Column.SRV_PICON_ID] + if not self._picon_manager: + ids = {} + if self._s_type is SettingsType.ENIGMA_2: + for r in self._services_model: + data = r[Column.SRV_PICON_ID].split("_") + ids[f"{data[3]}:{data[5]}:{data[6]}"] = r[Column.SRV_PICON_ID] - self._picon_manager = PiconManager(self, self._settings, ids, self._sat_positions) - box.pack_start(self._picon_manager, True, True, 0) + self._picon_manager = PiconManager(self, self._settings, ids, self._sat_positions) + box.pack_start(self._picon_manager, True, True, 0) def on_epg_realize(self, box): - self._epg_tool = EpgTool(self) - box.pack_start(self._epg_tool, True, True, 0) + if not self._epg_tool: + self._epg_tool = EpgTool(self) + box.pack_start(self._epg_tool, True, True, 0) def on_timers_realize(self, box): - self._timers_tool = TimerTool(self, self._http_api) - box.pack_start(self._timers_tool, True, True, 0) + if not self._timers_tool: + self._timers_tool = TimerTool(self, self._http_api) + box.pack_start(self._timers_tool, True, True, 0) def on_recordings_realize(self, box): - self._recordings_tool = RecordingsTool(self, self._settings) - box.pack_start(self._recordings_tool, True, True, 0) - self._player_box.connect("play", self._recordings_tool.on_playback) - self._player_box.connect("playback-close", self._recordings_tool.on_playback_close) + if not self._recordings_tool: + self._recordings_tool = RecordingsTool(self, self._settings) + box.pack_start(self._recordings_tool, True, True, 0) + self._player_box.connect("play", self._recordings_tool.on_playback) + self._player_box.connect("playback-close", self._recordings_tool.on_playback_close) def on_ftp_realize(self, box): - self._ftp_client = FtpClientBox(self, self._settings) - box.pack_start(self._ftp_client, True, True, 0) + if not self._ftp_client: + self._ftp_client = FtpClientBox(self, self._settings) + box.pack_start(self._ftp_client, True, True, 0) def on_control_realize(self, box): - self._control_tool = ControlTool(self, self._http_api, self._settings) - box.pack_start(self._control_tool, True, True, 0) + if not self._control_tool: + self._control_tool = ControlTool(self, self._settings) + box.pack_start(self._control_tool, True, True, 0) def on_telnet_realize(self, box): box.pack_start(TelnetClient(self), True, True, 0) @@ -845,6 +877,29 @@ class Application(Gtk.Application): def on_page_change(self, app, page_name): self._stack.set_visible_child_name(page_name) + def set_use_alt_layout(self, action, value): + action.set_state(value) + self._settings.alternate_layout = bool(value) + + @run_idle + def on_layout_change(self, action, value): + is_alt = bool(value) + self.reverse_main_elements(is_alt) + if self._settings.play_streams_mode is PlayStreamsMode.BUILT_IN: + msg = get_message("Layout of elements has been changed!") + msg = f"{msg} {get_message('Restart the program to apply all changes.')}" + self.show_info_message(msg, Gtk.MessageType.WARNING) + + self.emit("layout-changed", is_alt) + + def reverse_main_elements(self, alt_layout): + self._data_paned.remove(self._stack) + self._data_paned.remove(self._fav_paned) + self._data_paned.pack1(self._fav_paned if alt_layout else self._stack, True, False) + self._data_paned.pack2(self._stack if alt_layout else self._fav_paned, True, False) + + self.init_bq_position() + # ***************** Copy - Cut - Paste ********************* # def on_services_copy(self, view):