2018-04-16 18:50:48 +03:00
|
|
|
import locale
|
|
|
|
|
import os
|
2018-12-17 18:31:57 +03:00
|
|
|
from enum import Enum, IntEnum
|
2020-02-07 16:56:01 +03:00
|
|
|
from functools import lru_cache
|
2020-04-19 13:23:18 +03:00
|
|
|
from app.settings import Settings, SettingsException, IS_DARWIN
|
2018-04-16 18:50:48 +03:00
|
|
|
|
2020-01-02 15:47:48 +03:00
|
|
|
import gi
|
2020-01-14 18:26:05 +03:00
|
|
|
|
2020-02-07 16:56:01 +03:00
|
|
|
gi.require_version("Gtk", "3.0")
|
|
|
|
|
gi.require_version("Gdk", "3.0")
|
2020-07-15 11:16:09 +03:00
|
|
|
gi.require_version("Notify", "0.7")
|
|
|
|
|
from gi.repository import Gtk, Gdk, Notify
|
2018-04-16 18:50:48 +03:00
|
|
|
|
2020-07-15 11:16:09 +03:00
|
|
|
# Init notify
|
|
|
|
|
Notify.init("DemonEditor")
|
2020-04-19 13:23:18 +03:00
|
|
|
# Setting mod mask for the keyboard depending on the platform.
|
|
|
|
|
MOD_MASK = Gdk.ModifierType.MOD2_MASK if IS_DARWIN else Gdk.ModifierType.CONTROL_MASK
|
|
|
|
|
# Path to *.glade files.
|
2018-04-16 18:50:48 +03:00
|
|
|
UI_RESOURCES_PATH = "app/ui/" if os.path.exists("app/ui/") else "/usr/share/demoneditor/app/ui/"
|
2019-05-09 14:48:29 +03:00
|
|
|
IS_GNOME_SESSION = int(bool(os.environ.get("GNOME_DESKTOP_SESSION_ID")))
|
2020-04-19 13:23:18 +03:00
|
|
|
# Translation.
|
2018-04-16 18:50:48 +03:00
|
|
|
TEXT_DOMAIN = "demon-editor"
|
2020-04-19 13:23:18 +03:00
|
|
|
|
2020-01-02 15:47:48 +03:00
|
|
|
try:
|
|
|
|
|
settings = Settings.get_instance()
|
|
|
|
|
except SettingsException:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
os.environ["LANGUAGE"] = settings.language
|
|
|
|
|
if UI_RESOURCES_PATH == "app/ui/":
|
|
|
|
|
locale.bindtextdomain(TEXT_DOMAIN, UI_RESOURCES_PATH + "lang")
|
2018-04-16 18:50:48 +03:00
|
|
|
|
2020-04-13 13:46:02 +03:00
|
|
|
if settings.is_themes_support:
|
|
|
|
|
st = Gtk.Settings().get_default()
|
|
|
|
|
st.set_property("gtk-theme-name", settings.theme)
|
|
|
|
|
st.set_property("gtk-icon-theme-name", settings.icon_theme)
|
|
|
|
|
|
2018-04-16 18:50:48 +03:00
|
|
|
theme = Gtk.IconTheme.get_default()
|
2020-01-15 07:24:16 +03:00
|
|
|
theme.append_search_path(UI_RESOURCES_PATH + "icons")
|
|
|
|
|
|
2018-04-16 18:50:48 +03:00
|
|
|
_IMAGE_MISSING = theme.load_icon("image-missing", 16, 0) if theme.lookup_icon("image-missing", 16, 0) else None
|
|
|
|
|
CODED_ICON = theme.load_icon("emblem-readonly", 16, 0) if theme.lookup_icon(
|
|
|
|
|
"emblem-readonly", 16, 0) else _IMAGE_MISSING
|
2018-07-08 14:58:41 +03:00
|
|
|
LOCKED_ICON = theme.load_icon("changes-prevent-symbolic", 16, 0) if theme.lookup_icon(
|
2018-04-16 18:50:48 +03:00
|
|
|
"system-lock-screen", 16, 0) else _IMAGE_MISSING
|
|
|
|
|
HIDE_ICON = theme.load_icon("go-jump", 16, 0) if theme.lookup_icon("go-jump", 16, 0) else _IMAGE_MISSING
|
|
|
|
|
TV_ICON = theme.load_icon("tv-symbolic", 16, 0) if theme.lookup_icon("tv-symbolic", 16, 0) else _IMAGE_MISSING
|
2019-04-20 20:44:56 +03:00
|
|
|
IPTV_ICON = theme.load_icon("emblem-shared", 16, 0) if theme.lookup_icon("emblem-shared", 16, 0) else None
|
|
|
|
|
EPG_ICON = theme.load_icon("gtk-index", 16, 0) if theme.lookup_icon("gtk-index", 16, 0) else None
|
2019-12-22 20:42:29 +03:00
|
|
|
DEFAULT_ICON = theme.load_icon("emblem-default", 16, 0) if theme.lookup_icon("emblem-default", 16, 0) else None
|
2018-04-16 18:50:48 +03:00
|
|
|
|
2018-11-05 00:31:44 +03:00
|
|
|
|
2020-02-07 16:56:01 +03:00
|
|
|
@lru_cache(maxsize=1)
|
|
|
|
|
def get_yt_icon(icon_name, size=24):
|
2020-07-15 11:16:09 +03:00
|
|
|
""" Getting YouTube icon.
|
|
|
|
|
|
|
|
|
|
If the icon is not found in the icon themes, the "Info" icon is returned by default!
|
|
|
|
|
"""
|
2020-02-07 16:56:01 +03:00
|
|
|
default_theme = Gtk.IconTheme.get_default()
|
|
|
|
|
if default_theme.has_icon(icon_name):
|
|
|
|
|
return default_theme.load_icon(icon_name, size, 0)
|
|
|
|
|
|
2020-02-11 13:18:14 +03:00
|
|
|
n_theme = Gtk.IconTheme.new()
|
2020-02-07 16:56:01 +03:00
|
|
|
import glob
|
|
|
|
|
|
|
|
|
|
for theme_name in map(os.path.basename, filter(os.path.isdir, glob.glob("/usr/share/icons/*"))):
|
2020-02-11 13:18:14 +03:00
|
|
|
n_theme.set_custom_theme(theme_name)
|
|
|
|
|
if n_theme.has_icon(icon_name):
|
|
|
|
|
return n_theme.load_icon(icon_name, size, 0)
|
2020-02-07 16:56:01 +03:00
|
|
|
|
|
|
|
|
return default_theme.load_icon("info", size, 0)
|
|
|
|
|
|
|
|
|
|
|
2020-07-15 11:16:09 +03:00
|
|
|
def show_notification(message, timeout=10000, urgency=1):
|
|
|
|
|
""" Shows notification.
|
|
|
|
|
|
|
|
|
|
@param message: text to display
|
|
|
|
|
@param timeout: milliseconds
|
|
|
|
|
@param urgency: 0 - low, 1 - normal, 2 - critical
|
|
|
|
|
"""
|
|
|
|
|
notify = Notify.Notification.new("DemonEditor", message, "demon-editor")
|
|
|
|
|
notify.set_urgency(urgency)
|
|
|
|
|
notify.set_timeout(timeout)
|
|
|
|
|
notify.show()
|
|
|
|
|
|
|
|
|
|
|
2018-11-05 00:31:44 +03:00
|
|
|
class KeyboardKey(Enum):
|
2019-03-10 15:33:28 +03:00
|
|
|
""" The raw(hardware) codes of the keyboard keys. """
|
2020-02-13 20:15:18 +03:00
|
|
|
E = 26
|
2018-11-05 00:31:44 +03:00
|
|
|
R = 27
|
|
|
|
|
T = 28
|
|
|
|
|
P = 33
|
|
|
|
|
S = 39
|
2020-02-11 13:18:14 +03:00
|
|
|
F = 41
|
2018-11-05 00:31:44 +03:00
|
|
|
X = 53
|
|
|
|
|
C = 54
|
|
|
|
|
V = 55
|
2018-12-02 00:45:55 +03:00
|
|
|
W = 25
|
2018-11-23 15:03:10 +03:00
|
|
|
Z = 52
|
2018-11-05 00:31:44 +03:00
|
|
|
INSERT = 118
|
|
|
|
|
HOME = 110
|
|
|
|
|
END = 115
|
|
|
|
|
UP = 111
|
|
|
|
|
DOWN = 116
|
|
|
|
|
PAGE_UP = 112
|
|
|
|
|
PAGE_DOWN = 117
|
|
|
|
|
LEFT = 113
|
|
|
|
|
RIGHT = 114
|
2018-11-12 11:26:11 +03:00
|
|
|
F2 = 68
|
2020-12-16 00:32:32 +03:00
|
|
|
F7 = 73
|
2019-02-09 15:16:03 +03:00
|
|
|
SPACE = 65
|
2018-11-05 00:31:44 +03:00
|
|
|
DELETE = 119
|
|
|
|
|
BACK_SPACE = 22
|
|
|
|
|
CTRL_L = 37
|
|
|
|
|
CTRL_R = 105
|
2018-11-05 11:09:15 +03:00
|
|
|
# Laptop codes
|
|
|
|
|
HOME_KP = 79
|
|
|
|
|
END_KP = 87
|
|
|
|
|
PAGE_UP_KP = 81
|
|
|
|
|
PAGE_DOWN_KP = 89
|
2018-11-05 00:31:44 +03:00
|
|
|
|
|
|
|
|
@classmethod
|
2018-11-09 14:14:24 +03:00
|
|
|
def value_exist(cls, value):
|
|
|
|
|
return value in (val.value for val in cls.__members__.values())
|
2018-11-05 00:31:44 +03:00
|
|
|
|
|
|
|
|
|
2018-11-02 21:58:10 +03:00
|
|
|
# Keys for move in lists. KEY_KP_(NAME) for laptop!!!
|
2018-11-05 00:31:44 +03:00
|
|
|
MOVE_KEYS = (KeyboardKey.UP, KeyboardKey.PAGE_UP, KeyboardKey.DOWN, KeyboardKey.PAGE_DOWN, KeyboardKey.HOME,
|
2018-11-05 11:09:15 +03:00
|
|
|
KeyboardKey.END, KeyboardKey.HOME_KP, KeyboardKey.END_KP, KeyboardKey.PAGE_UP_KP, KeyboardKey.PAGE_DOWN_KP)
|
2018-11-02 23:13:51 +03:00
|
|
|
|
|
|
|
|
|
2019-03-10 15:33:28 +03:00
|
|
|
class FavClickMode(IntEnum):
|
|
|
|
|
""" Double click mode on the service in the bouquet(FAV) list. """
|
|
|
|
|
DISABLED = 0
|
|
|
|
|
STREAM = 1
|
|
|
|
|
PLAY = 2
|
|
|
|
|
ZAP = 3
|
2020-01-14 18:26:05 +03:00
|
|
|
ZAP_PLAY = 4
|
2019-03-10 15:33:28 +03:00
|
|
|
|
|
|
|
|
|
2018-04-16 18:50:48 +03:00
|
|
|
class ViewTarget(Enum):
|
2019-03-10 15:33:28 +03:00
|
|
|
""" Used for set target view. """
|
2018-04-16 18:50:48 +03:00
|
|
|
BOUQUET = 0
|
|
|
|
|
FAV = 1
|
|
|
|
|
SERVICES = 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BqGenType(Enum):
|
2019-03-10 15:33:28 +03:00
|
|
|
""" Bouquet generation type. """
|
2018-04-16 18:50:48 +03:00
|
|
|
SAT = 0
|
|
|
|
|
EACH_SAT = 1
|
|
|
|
|
PACKAGE = 2
|
|
|
|
|
EACH_PACKAGE = 3
|
|
|
|
|
TYPE = 4
|
|
|
|
|
EACH_TYPE = 5
|
|
|
|
|
|
|
|
|
|
|
2018-12-17 18:31:57 +03:00
|
|
|
class Column(IntEnum):
|
2018-12-16 17:28:07 +03:00
|
|
|
""" Column nums in the views """
|
|
|
|
|
# main view
|
|
|
|
|
SRV_CAS_FLAGS = 0
|
|
|
|
|
SRV_STANDARD = 1
|
|
|
|
|
SRV_CODED = 2
|
|
|
|
|
SRV_SERVICE = 3
|
|
|
|
|
SRV_LOCKED = 4
|
|
|
|
|
SRV_HIDE = 5
|
|
|
|
|
SRV_PACKAGE = 6
|
|
|
|
|
SRV_TYPE = 7
|
|
|
|
|
SRV_PICON = 8
|
|
|
|
|
SRV_PICON_ID = 9
|
|
|
|
|
SRV_SSID = 10
|
|
|
|
|
SRV_FREQ = 11
|
|
|
|
|
SRV_RATE = 12
|
|
|
|
|
SRV_POL = 13
|
|
|
|
|
SRV_FEC = 14
|
|
|
|
|
SRV_SYSTEM = 15
|
|
|
|
|
SRV_POS = 16
|
|
|
|
|
SRV_DATA_ID = 17
|
|
|
|
|
SRV_FAV_ID = 18
|
|
|
|
|
SRV_TRANSPONDER = 19
|
|
|
|
|
SRV_TOOLTIP = 20
|
|
|
|
|
SRV_BACKGROUND = 21
|
|
|
|
|
# fav view
|
|
|
|
|
FAV_NUM = 0
|
|
|
|
|
FAV_CODED = 1
|
|
|
|
|
FAV_SERVICE = 2
|
|
|
|
|
FAV_LOCKED = 3
|
|
|
|
|
FAV_HIDE = 4
|
|
|
|
|
FAV_TYPE = 5
|
|
|
|
|
FAV_POS = 6
|
|
|
|
|
FAV_ID = 7
|
|
|
|
|
FAV_PICON = 8
|
2018-12-16 22:44:45 +03:00
|
|
|
FAV_TOOLTIP = 9
|
|
|
|
|
FAV_BACKGROUND = 10
|
2019-02-09 12:43:27 +03:00
|
|
|
# bouquets view
|
|
|
|
|
BQ_NAME = 0
|
|
|
|
|
BQ_LOCKED = 1
|
|
|
|
|
BQ_HIDDEN = 2
|
|
|
|
|
BQ_TYPE = 3
|
2018-12-16 17:28:07 +03:00
|
|
|
|
|
|
|
|
def __index__(self):
|
|
|
|
|
""" Overridden to get the index in slices directly """
|
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
|
|
|
2018-04-16 18:50:48 +03:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
pass
|