diff --git a/app/settings.py b/app/settings.py index 11c5a110..b1170e10 100644 --- a/app/settings.py +++ b/app/settings.py @@ -48,6 +48,8 @@ IS_DARWIN = sys.platform == "darwin" IS_WIN = sys.platform == "win32" IS_LINUX = sys.platform == "linux" +USE_HEADER_BAR = int(bool(os.environ.get("GNOME_DESKTOP_SESSION_ID"))) + class Defaults(Enum): """ Default program settings """ @@ -702,6 +704,14 @@ class Settings: # *********** Appearance *********** # + @property + def use_header_bar(self): + return self._settings.get("use_header_bar", USE_HEADER_BAR) + + @use_header_bar.setter + def use_header_bar(self, value): + self._settings["use_header_bar"] = value + @property def list_font(self): return self._settings.get("list_font", "") diff --git a/app/ui/backup.py b/app/ui/backup.py index 1de44990..6e5b6b8b 100644 --- a/app/ui/backup.py +++ b/app/ui/backup.py @@ -36,10 +36,10 @@ from enum import Enum from pathlib import Path from app.commons import run_idle, get_size_from_bytes -from app.settings import SettingsType, SEP, IS_DARWIN +from app.settings import SettingsType, SEP from app.ui.dialogs import show_dialog, DialogType, get_builder from app.ui.main_helper import append_text_to_tview -from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, MOD_MASK, IS_GNOME_SESSION, HeaderBar +from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, MOD_MASK, HeaderBar class RestoreType(Enum): @@ -77,7 +77,7 @@ class BackupDialog: self._message_label = builder.get_object("message_label") self._file_count_label = builder.get_object("file_count_label") - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: header_bar = HeaderBar() self._dialog_window.set_titlebar(header_bar) diff --git a/app/ui/dialogs.py b/app/ui/dialogs.py index ef959f0e..4c9728f7 100644 --- a/app/ui/dialogs.py +++ b/app/ui/dialogs.py @@ -2,7 +2,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2018-2022 Dmitriy Yefremov +# Copyright (c) 2018-2023 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 @@ -34,8 +34,8 @@ from functools import lru_cache from pathlib import Path from app.commons import run_idle -from app.settings import SEP, IS_WIN -from .uicommons import Gtk, UI_RESOURCES_PATH, TEXT_DOMAIN, IS_GNOME_SESSION +from app.settings import SEP, IS_WIN, USE_HEADER_BAR +from .uicommons import Gtk, UI_RESOURCES_PATH, TEXT_DOMAIN class Dialog(Enum): @@ -157,7 +157,7 @@ def get_file_chooser_dialog(transient, text, settings, action_type, file_filter, def get_input_dialog(transient, text): - builder, dialog = get_dialog_from_xml(DialogType.INPUT, transient, use_header=IS_GNOME_SESSION) + builder, dialog = get_dialog_from_xml(DialogType.INPUT, transient, use_header=USE_HEADER_BAR) entry = builder.get_object("input_entry") entry.set_text(text if text else "") response = dialog.run() @@ -223,9 +223,9 @@ def get_builder(path, handlers=None, use_str=False, objects=None, tag="property" if use_str: if objects: - builder.add_objects_from_string(get_dialogs_string(path, tag).format(use_header=IS_GNOME_SESSION), objects) + builder.add_objects_from_string(get_dialogs_string(path, tag).format(use_header=USE_HEADER_BAR), objects) else: - builder.add_from_string(get_dialogs_string(path, tag).format(use_header=IS_GNOME_SESSION)) + builder.add_from_string(get_dialogs_string(path, tag).format(use_header=USE_HEADER_BAR)) else: if objects: builder.add_objects_from_string(get_dialogs_string(path, tag), objects) diff --git a/app/ui/epg/epg.py b/app/ui/epg/epg.py index 4d0a2057..37e88e55 100644 --- a/app/ui/epg/epg.py +++ b/app/ui/epg/epg.py @@ -43,13 +43,13 @@ from gi.repository import GLib from app.commons import run_idle, run_task, run_with_delay from app.connections import download_data, DownloadType, HttpAPI from app.eparser.ecommons import BouquetService, BqServiceType -from app.settings import SEP, EpgSource, IS_DARWIN, IS_WIN +from app.settings import SEP, EpgSource, IS_WIN from app.tools.epg import EPG, ChannelsParser, EpgEvent, XmlTvReader from app.ui.dialogs import get_message, show_dialog, DialogType, get_builder from app.ui.tasks import BGTaskWidget from app.ui.timers import TimerTool from ..main_helper import on_popup_menu, update_entry_data, scroll_to, update_toggle_model, update_filter_sat_positions -from ..uicommons import Gtk, Gdk, UI_RESOURCES_PATH, Column, EPG_ICON, KeyboardKey, IS_GNOME_SESSION, Page, HeaderBar +from ..uicommons import Gtk, Gdk, UI_RESOURCES_PATH, Column, EPG_ICON, KeyboardKey, Page, HeaderBar class RefsSource(Enum): @@ -197,8 +197,8 @@ class EpgSettingsPopover(Gtk.Popover): class EpgTool(Gtk.Box): - def __init__(self, app, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, app, **kwargs): + super().__init__(**kwargs) self._current_bq = None self._app = app @@ -477,7 +477,7 @@ class EpgDialog: self._update_on_start_switch = builder.get_object("update_on_start_switch") self._epg_dat_source_box = builder.get_object("epg_dat_source_box") - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: header_bar = HeaderBar(title="EPG", subtitle=get_message("List configuration")) self._dialog.set_titlebar(header_bar) builder.get_object("left_action_box").reparent(header_bar) diff --git a/app/ui/ftp.py b/app/ui/ftp.py index 2fc9f883..1d63149c 100644 --- a/app/ui/ftp.py +++ b/app/ui/ftp.py @@ -2,7 +2,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2018-2022 Dmitriy Yefremov +# Copyright (c) 2018-2023 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 @@ -42,10 +42,10 @@ from gi.repository import GLib from app.commons import log, run_task, run_idle, get_size_from_bytes from app.connections import UtfFTP -from app.settings import IS_LINUX, IS_DARWIN, IS_WIN, SEP +from app.settings import IS_LINUX, IS_DARWIN, IS_WIN, SEP, USE_HEADER_BAR from app.ui.dialogs import show_dialog, DialogType, get_builder, get_message from app.ui.main_helper import on_popup_menu -from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, MOD_MASK, IS_GNOME_SESSION, Page +from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, MOD_MASK, Page File = namedtuple("File", ["icon", "name", "size", "date", "attr", "extra"]) @@ -529,7 +529,7 @@ class FtpClientBox(Gtk.HBox): @run_idle def show_edit_dialog(self, f_path, data): - dialog = TextEditDialog(f_path, IS_GNOME_SESSION) + dialog = TextEditDialog(f_path, USE_HEADER_BAR) dialog.text = data ok = Gtk.ResponseType.OK if dialog.run() == ok and show_dialog(DialogType.QUESTION, self._app.app_window) == ok: @@ -578,7 +578,7 @@ class FtpClientBox(Gtk.HBox): log(f"Init attributes error [{attrs}]. Invalid length!") return - dialog = AttributesDialog(attrs, IS_GNOME_SESSION) + dialog = AttributesDialog(attrs, USE_HEADER_BAR) ok = Gtk.ResponseType.OK if dialog.run() == ok and show_dialog(DialogType.QUESTION, self._app.app_window) == ok: log(self._ftp.sendcmd(f"SITE CHMOD {dialog.permissions} {file}")) diff --git a/app/ui/imports.py b/app/ui/imports.py index 6e5a9fd5..179bc182 100644 --- a/app/ui/imports.py +++ b/app/ui/imports.py @@ -37,7 +37,7 @@ from app.eparser.neutrino.bouquets import parse_webtv, parse_bouquets as get_neu from app.settings import SettingsType, IS_DARWIN, SEP from app.ui.dialogs import show_dialog, DialogType, get_chooser_dialog, get_message, get_builder from app.ui.main_helper import on_popup_menu, get_iptv_data -from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, Column, IS_GNOME_SESSION, Page, HeaderBar +from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, KeyboardKey, Column, Page, HeaderBar def import_bouquet(app, model, path, appender, file_path=None): @@ -159,7 +159,7 @@ class ImportDialog: self._sat_model = builder.get_object("sat_list_store") self._sat_count_label = builder.get_object("sat_count_label") - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: actions_box = builder.get_object("actions_box") builder.get_object("toolbar_box").set_visible(False) header_bar = HeaderBar() diff --git a/app/ui/iptv.py b/app/ui/iptv.py index 58f2ee71..be3635d5 100644 --- a/app/ui/iptv.py +++ b/app/ui/iptv.py @@ -41,12 +41,11 @@ from app.commons import run_idle, run_task, log from app.eparser.ecommons import BqServiceType, Service from app.eparser.iptv import (NEUTRINO_FAV_ID_FORMAT, StreamType, ENIGMA2_FAV_ID_FORMAT, get_fav_id, MARKER_FORMAT, parse_m3u, PICON_FORMAT) -from app.settings import SettingsType, IS_DARWIN +from app.settings import SettingsType from app.tools.yt import YouTubeException, YouTube from app.ui.dialogs import Action, show_dialog, DialogType, get_message, get_builder from app.ui.main_helper import get_iptv_url, on_popup_menu, get_picon_pixbuf -from app.ui.uicommons import (Gtk, Gdk, UI_RESOURCES_PATH, IPTV_ICON, Column, KeyboardKey, get_yt_icon, - IS_GNOME_SESSION, HeaderBar) +from app.ui.uicommons import (Gtk, Gdk, UI_RESOURCES_PATH, IPTV_ICON, Column, KeyboardKey, get_yt_icon, HeaderBar) _DIGIT_ENTRY_NAME = "digit-entry" _ENIGMA2_REFERENCE = "{}:{}:{:X}:{:X}:{:X}:{:X}:{:X}:0:0:0" @@ -892,7 +891,7 @@ class YtListImportDialog: self._import_button.bind_property("sensitive", self._quality_box, "sensitive") self._receive_button.bind_property("sensitive", self._import_button, "sensitive") - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: header_bar = HeaderBar(title="YouTube", subtitle=get_message("Playlist import")) self._dialog.set_titlebar(header_bar) actions_box = builder.get_object("yt_actions_box") diff --git a/app/ui/main.py b/app/ui/main.py index 2cbcd894..8eacc9c1 100644 --- a/app/ui/main.py +++ b/app/ui/main.py @@ -48,7 +48,7 @@ from app.eparser.enigma.bouquets import BqServiceType from app.eparser.iptv import export_to_m3u, StreamType from app.eparser.neutrino.bouquets import BqType from app.settings import (SettingsType, Settings, SettingsException, SettingsReadException, - IS_DARWIN, PlayStreamsMode, IS_LINUX) + IS_DARWIN, PlayStreamsMode, IS_LINUX, USE_HEADER_BAR) from app.tools.media import Recorder from app.ui.control import ControlTool from app.ui.epg.epg import EpgCache, EpgSettingsPopover, EpgDialog, EpgTool @@ -69,7 +69,7 @@ from .search import SearchProvider from .service_details_dialog import ServiceDetailsDialog, Action from .settings_dialog import SettingsDialog from .uicommons import (Gtk, Gdk, UI_RESOURCES_PATH, LOCKED_ICON, HIDE_ICON, IPTV_ICON, MOVE_KEYS, KeyboardKey, Column, - FavClickMode, MOD_MASK, APP_FONT, Page, IS_GNOME_SESSION, HeaderBar) + FavClickMode, MOD_MASK, APP_FONT, Page, HeaderBar) from .xml.dialogs import ServicesUpdateDialog from .xml.edit import SatellitesTool @@ -505,7 +505,7 @@ class Application(Gtk.Application): # Header bar. profile_box = builder.get_object("profile_combo_box") toolbar_box = builder.get_object("toolbar_main_box") - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: header_bar = HeaderBar() if not IS_DARWIN: header_bar.pack_start(builder.get_object("file_header_button")) @@ -647,7 +647,7 @@ class Application(Gtk.Application): def init_app_menu(self): builder = get_builder(UI_RESOURCES_PATH + "app_menu.ui", tag="attribute") - if not IS_GNOME_SESSION: + if not USE_HEADER_BAR: if IS_DARWIN: self.set_app_menu(builder.get_object("mac_app_menu")) self.set_menubar(builder.get_object("mac_menu_bar")) @@ -770,7 +770,7 @@ class Application(Gtk.Application): 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: + if not USE_HEADER_BAR: # We are working with the "hidden-when" submenu attribute. See 'app_menu_.ui' file. hide_bar_action = Gio.SimpleAction.new("hide_menu_bar", None) self._player_box.bind_property("visible", hide_bar_action, "enabled", 4) @@ -3369,7 +3369,7 @@ class Application(Gtk.Application): def on_playback_full_screen(self, box, state): self._data_paned.set_visible(state) self._main_window.unfullscreen() if state else self._main_window.fullscreen() - if not IS_GNOME_SESSION: + if not USE_HEADER_BAR: self._main_window.set_show_menubar(state) def on_playback_show(self, box): diff --git a/app/ui/playback.py b/app/ui/playback.py index 0f3f015d..8b17a1c7 100644 --- a/app/ui/playback.py +++ b/app/ui/playback.py @@ -34,17 +34,17 @@ from gi.repository import GLib, GObject, Gio from app.commons import run_idle, run_with_delay from app.connections import HttpAPI from app.eparser.ecommons import BqServiceType -from app.settings import PlayStreamsMode, IS_DARWIN, SettingsType +from app.settings import PlayStreamsMode, IS_DARWIN, SettingsType, USE_HEADER_BAR from app.tools.media import Player from app.ui.dialogs import get_builder, get_message from app.ui.main_helper import get_iptv_url -from app.ui.uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, Column, IS_GNOME_SESSION, Page +from app.ui.uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, Column, Page class PlayerBox(Gtk.Box): - def __init__(self, app, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, app, **kwargs): + super().__init__(**kwargs) # Signals. GObject.signal_new("playback-full-screen", self, GObject.SIGNAL_RUN_LAST, GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) @@ -191,7 +191,7 @@ class PlayerBox(Gtk.Box): video_menu = builder.get_object("video_menu") subtitle_menu = builder.get_object("subtitle_menu") - if not IS_GNOME_SESSION: + if not USE_HEADER_BAR: menu_bar = self._app.get_menubar() menu_bar.insert_section(1, None, audio_menu) menu_bar.insert_section(2, None, video_menu) diff --git a/app/ui/settings_dialog.py b/app/ui/settings_dialog.py index 1764c96b..61eaf7f7 100644 --- a/app/ui/settings_dialog.py +++ b/app/ui/settings_dialog.py @@ -32,10 +32,10 @@ from collections import Counter from app.commons import run_task, run_idle, log from app.connections import test_telnet, test_ftp, TestException, test_http, HttpApiException -from app.settings import SettingsType, Settings, PlayStreamsMode, IS_LINUX, SEP, IS_WIN, IS_DARWIN +from app.settings import SettingsType, Settings, PlayStreamsMode, IS_LINUX, SEP, IS_WIN 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 .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, DEFAULT_ICON, APP_FONT, IS_GNOME_SESSION, HeaderBar +from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, DEFAULT_ICON, APP_FONT, HeaderBar class SettingsDialog: @@ -208,7 +208,7 @@ class SettingsDialog: [self.init_element_style(el, screen, style_provider) for el in self._digit_elems] self.init_element_style(self._host_field, screen, style_provider) - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: switcher = builder.get_object("main_stack_switcher") switcher.set_margin_top(0) switcher.set_margin_bottom(0) diff --git a/app/ui/timers.py b/app/ui/timers.py index 6017b209..465b79b9 100644 --- a/app/ui/timers.py +++ b/app/ui/timers.py @@ -31,9 +31,10 @@ from datetime import datetime, timedelta from enum import Enum from urllib.parse import quote +from app.settings import USE_HEADER_BAR from app.ui.main_helper import on_popup_menu from .dialogs import get_builder, get_message, show_dialog, DialogType -from .uicommons import Gtk, Gdk, GLib, UI_RESOURCES_PATH, Page, Column, KeyboardKey, IS_GNOME_SESSION, MOD_MASK +from .uicommons import Gtk, Gdk, GLib, UI_RESOURCES_PATH, Page, Column, KeyboardKey, MOD_MASK from ..commons import run_idle, log from ..connections import HttpAPI from ..eparser.ecommons import BqServiceType @@ -56,7 +57,7 @@ class TimerTool(Gtk.Box): class TimerDialog(Gtk.Dialog): def __init__(self, parent, action=None, timer_data=None, *args, **kwargs): - super().__init__(use_header_bar=IS_GNOME_SESSION, *args, **kwargs) + super().__init__(use_header_bar=USE_HEADER_BAR, *args, **kwargs) self._action = action or TimerTool.TimerAction.ADD self._timer_data = timer_data or {} diff --git a/app/ui/uicommons.py b/app/ui/uicommons.py index a1ccca31..f2a47a82 100644 --- a/app/ui/uicommons.py +++ b/app/ui/uicommons.py @@ -2,7 +2,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2018-2022 Dmitriy Yefremov +# Copyright (c) 2018-2023 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 @@ -52,7 +52,6 @@ TEXT_DOMAIN = "demon-editor" NOTIFY_IS_INIT = False APP_FONT = None -IS_GNOME_SESSION = int(bool(os.environ.get("GNOME_DESKTOP_SESSION_ID"))) try: settings = Settings.get_instance() @@ -164,6 +163,7 @@ def show_notification(message, timeout=10000, urgency=1): class HeaderBar(Gtk.HeaderBar): """ Custom header bar widget. """ + def __init__(self, **kwargs): super().__init__(**kwargs) self.set_visible(True) diff --git a/app/ui/xml/dialogs.py b/app/ui/xml/dialogs.py index 70e93be2..09821330 100644 --- a/app/ui/xml/dialogs.py +++ b/app/ui/xml/dialogs.py @@ -39,12 +39,12 @@ from app.eparser import Satellite, Transponder from app.eparser.ecommons import (PLS_MODE, get_key_by_value, POLARIZATION, FEC, SYSTEM, MODULATION, Terrestrial, Cable, T_SYSTEM, BANDWIDTH, CONSTELLATION, T_FEC, GUARD_INTERVAL, TRANSMISSION_MODE, HIERARCHY, Inversion, C_MODULATION, FEC_DEFAULT, TerTransponder, CableTransponder) -from app.settings import IS_DARWIN +from app.settings import USE_HEADER_BAR from app.tools.satellites import SatellitesParser, SatelliteSource, ServicesParser from ..dialogs import show_dialog, DialogType, get_message, get_builder from ..main_helper import append_text_to_tview, get_base_model, on_popup_menu from ..search import SearchProvider -from ..uicommons import Gtk, Gdk, UI_RESOURCES_PATH, IS_GNOME_SESSION, HeaderBar +from ..uicommons import Gtk, Gdk, UI_RESOURCES_PATH, HeaderBar _DIALOGS_UI_PATH = f"{UI_RESOURCES_PATH}xml{os.sep}dialogs.glade" @@ -61,7 +61,7 @@ class DVBDialog(Gtk.Dialog): skip_taskbar_hint=True, skip_pager_hint=True, destroy_with_parent=True, - use_header_bar=IS_GNOME_SESSION, + use_header_bar=USE_HEADER_BAR, window_position=Gtk.WindowPosition.CENTER_ON_PARENT, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK), *args, **kwargs) @@ -457,7 +457,7 @@ class UpdateDialog: builder.get_object("sat_update_search_up_button")) builder.get_object("sat_update_find_button").connect("toggled", search_provider.on_search_toggled) - if IS_GNOME_SESSION or IS_DARWIN: + if self._settings.use_header_bar: header_bar = HeaderBar() builder.get_object("sat_update_header").set_visible(False) header_box = builder.get_object("satellites_update_header_box")