diff --git a/data/setup.xml b/data/setup.xml index 875c035b940..3e5029b448c 100644 --- a/data/setup.xml +++ b/data/setup.xml @@ -75,14 +75,15 @@ config.cimisc.bootDelay - config.channelSelection.style config.misc.use_ci_assignment config.usage.alternative_number_mode config.usage.show_bouquetalways config.usage.quickzap_bouquet_change config.usage.servicelistpreview_mode - config.usage.use_pig - config.usage.servicelist_mode + + config.usage.use_pig + config.usage.servicelist_mode + config.usage.show_servicelist config.usage.servicelist_cursor_behavior config.usage.multibouquet @@ -92,25 +93,34 @@ config.usage.panicchannel config.usage.numzappicon config.usage.show_channel_jump_in_servicelist - config.usage.service_icon_enable - config.usage.servicelist_picon_ratio - config.usage.servicelist_picon_downsize - config.usage.servicetype_icon_mode - config.usage.crypto_icon_mode - config.usage.record_indicator_mode - config.usage.servicelist_twolines - config.usage.servicelist_servicenumber_valign - config.usage.servicelist_eventprogress_valign - config.usage.show_channel_numbers_in_servicelist - config.usage.servicelist_eventprogress_view_mode - config.usage.show_event_progress_in_servicelist - config.usage.servicelist_column - config.usage.serviceitems_per_page_twolines - config.usage.serviceitems_per_page - config.usage.servicenum_fontsize - config.usage.servicename_fontsize - config.usage.serviceinfo_fontsize - config.usage.progressinfo_fontsize + + config.usage.show_channel_numbers_in_servicelist + config.usage.service_icon_enable + config.usage.servicelist_picon_ratio + config.usage.servicelist_picon_downsize + config.usage.servicetype_icon_mode + config.usage.crypto_icon_mode + config.usage.record_indicator_mode + config.usage.servicelist_twolines + config.usage.servicelist_servicenumber_valign + config.usage.servicelist_eventprogress_valign + config.usage.servicelist_eventprogress_view_mode + config.usage.show_event_progress_in_servicelist + config.usage.servicelist_column + config.usage.serviceitems_per_page_twolines + config.usage.serviceitems_per_page + config.usage.servicenum_fontsize + config.usage.servicename_fontsize + config.usage.serviceinfo_fontsize + config.usage.progressinfo_fontsize + + config.channelSelection.showNumber + config.channelSelection.showLCN + config.channelSelection.showPicon + config.channelSelection.showServiceTypeIcon + config.channelSelection.showCryptoIcon + config.channelSelection.recordIndicatorMode + config.misc.zapmode config.usage.numzaptimeoutmode config.usage.numzaptimeout1 @@ -823,6 +833,8 @@ config.skin.guiSkin config.skin.lcdSkin config.skin.FallbackFont + config.channelSelection.screenStyle + config.channelSelection.widgetStyle config.usage.sleepTimer diff --git a/lib/gdi/drawing.cpp b/lib/gdi/drawing.cpp index da3fd1eb5be..0502fce506d 100644 --- a/lib/gdi/drawing.cpp +++ b/lib/gdi/drawing.cpp @@ -1,7 +1,7 @@ /* Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License -Copyright (c) 2023-2024 openATV +Copyright (c) 2023-2024 zKhadiri, jbleyel, openATV Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/lib/gdi/drawing.h b/lib/gdi/drawing.h index 01b5d482012..0cf5b732c4b 100644 --- a/lib/gdi/drawing.h +++ b/lib/gdi/drawing.h @@ -1,7 +1,7 @@ /* Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License -Copyright (c) 2023-2024 openATV +Copyright (c) 2023-2024 zKhadiri, jbleyel, openATV Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp index 821e238db71..32194ff9658 100644 --- a/lib/gui/elistboxcontent.cpp +++ b/lib/gui/elistboxcontent.cpp @@ -1782,14 +1782,14 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c pheight = PyTuple_GET_ITEM(item, 4), pfilled_perc = PyTuple_GET_ITEM(item, 5), ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, - pstartColor, pmidColor, pendColor, pstartColorSelected, pmidColorSelected, pendColorSelected; + pstartColor, pmidColor, pendColor, pstartColorSelected, pmidColorSelected, pendColorSelected, pborderColor, pborderColorSelected; int idx = 6; if (type == TYPE_PROGRESS) { if (!(px && py && pwidth && pheight && pfilled_perc)) { - eDebug("[eListboxPythonMultiContent] tuple too small (must be (TYPE_PROGRESS, x, y, width, height, filled percent [, borderWidth, color, colorSelected, backColor, backColorSelected]))"); + eDebug("[eListboxPythonMultiContent] tuple too small (must be (TYPE_PROGRESS, x, y, width, height, filled percent [, borderWidth, color, colorSelected, backColor, backColorSelected, borderColor, borderColorSelected]))"); goto error_out; } } @@ -1800,7 +1800,7 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c continue; if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap)) { - eDebug("[eListboxPythonMultiContent] tuple too small (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,borderWidth, color, colorSelected, backColor, backColorSelected]))"); + eDebug("[eListboxPythonMultiContent] tuple too small (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,borderWidth, color, colorSelected, backColor, backColorSelected, borderColor, borderColorSelected]))"); goto error_out; } } @@ -1836,6 +1836,12 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c pbackColorSelected = ePyObject(); } + if (size > idx) + pborderColor = lookupColor(PyTuple_GET_ITEM(item, idx++), data); + + if (size > idx) + pborderColorSelected = lookupColor(PyTuple_GET_ITEM(item, idx++), data); + int radius = 0; int edges = 0; @@ -1966,6 +1972,11 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c } else { + if (pborderColor) { + uint32_t color = PyLong_AsUnsignedLongMask((selected && pborderColorSelected) ? pborderColorSelected : pborderColor); + painter.setForegroundColor(gRGB(color)); + } + rect.setRect(x, y, width, bwidth); painter.fill(rect); @@ -1977,6 +1988,23 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c rect.setRect(x + width - bwidth, y + bwidth, bwidth, height - bwidth); painter.fill(rect); + + if (pborderColor) { + if (selected && pforeColorSelected) + { + uint32_t color = PyLong_AsUnsignedLongMask(pforeColorSelected); + painter.setForegroundColor(gRGB(color)); + } + else if (pforeColor) + { + uint32_t color = PyLong_AsUnsignedLongMask(pforeColor); + painter.setForegroundColor(gRGB(color)); + } + else + { + painter.setForegroundColor(defaultForeColor); + } + } } } diff --git a/lib/python/Components/Converter/XmlMultiContent.py b/lib/python/Components/Converter/XmlMultiContent.py index 9f3fa4ed576..634c5eeb049 100644 --- a/lib/python/Components/Converter/XmlMultiContent.py +++ b/lib/python/Components/Converter/XmlMultiContent.py @@ -35,7 +35,7 @@ def parseTemplateModes(template): context = SkinContext(context, "0,0", f"{itemWidth},{itemHeight}") for element in list(mode): processor = self.processors.get(element.tag, self.processNone) - newItems = processor(element, context, excludeItemValues=[], includeItemValues=[]) + newItems = processor(element, context) if newItems: items += newItems newItems = [] @@ -129,8 +129,7 @@ class XmlMultiContent(StringList, MultiContentTemplateParser): def __init__(self, args): StringList.__init__(self, args) - self.debug = True - MultiContentTemplateParser.__init__(self, self.debug) + MultiContentTemplateParser.__init__(self) self.activeStyle = None self.activeTemplate = "Default" # This value string is used in the UI. self.dom = args.get("dom") diff --git a/lib/python/Components/MultiContent.py b/lib/python/Components/MultiContent.py index 244822ba4d1..80abc7f428d 100644 --- a/lib/python/Components/MultiContent.py +++ b/lib/python/Components/MultiContent.py @@ -49,12 +49,12 @@ def MultiContentEntryPixmapAlphaBlend(pos=(0, 0), size=(0, 0), png=None, backcol return eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, int(pos[0]), int(pos[1]), int(size[0]), int(size[1]), __resolvePixmap(png), __resolveColor(backcolor), __resolveColor(backcolor_sel), flags, cornerRadius, cornerEdges -def MultiContentEntryProgress(pos=(0, 0), size=(0, 0), percent=None, borderWidth=None, foreColor=None, foreColorSelected=None, backColor=None, backColorSelected=None, startColor=None, midColor=None, endColor=None, startColorSelected=None, midColorSelected=None, endColorSelected=None, cornerRadius=0, cornerEdges=15): - return eListboxPythonMultiContent.TYPE_PROGRESS, int(pos[0]), int(pos[1]), int(size[0]), int(size[1]), percent, borderWidth, __resolveColor(foreColor), __resolveColor(foreColorSelected), __resolveColor(backColor), __resolveColor(backColorSelected), __resolveColor(startColor), __resolveColor(midColor), __resolveColor(endColor), __resolveColor(startColorSelected), __resolveColor(midColorSelected), __resolveColor(endColorSelected), cornerRadius, cornerEdges +def MultiContentEntryProgress(pos=(0, 0), size=(0, 0), percent=None, borderWidth=None, borderColor=None, borderColorSelected=None, foreColor=None, foreColorSelected=None, backColor=None, backColorSelected=None, startColor=None, midColor=None, endColor=None, startColorSelected=None, midColorSelected=None, endColorSelected=None, cornerRadius=0, cornerEdges=15): + return eListboxPythonMultiContent.TYPE_PROGRESS, int(pos[0]), int(pos[1]), int(size[0]), int(size[1]), percent, borderWidth, __resolveColor(foreColor), __resolveColor(foreColorSelected), __resolveColor(backColor), __resolveColor(backColorSelected), __resolveColor(borderColor), __resolveColor(borderColorSelected), __resolveColor(startColor), __resolveColor(midColor), __resolveColor(endColor), __resolveColor(startColorSelected), __resolveColor(midColorSelected), __resolveColor(endColorSelected), cornerRadius, cornerEdges -def MultiContentEntryProgressPixmap(pos=(0, 0), size=(0, 0), percent=None, pixmap=None, borderWidth=None, foreColor=None, foreColorSelected=None, backColor=None, backColorSelected=None, cornerRadius=0, cornerEdges=15): - return eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, int(pos[0]), int(pos[1]), int(size[0]), int(size[1]), percent, __resolvePixmap(pixmap), borderWidth, __resolveColor(foreColor), __resolveColor(foreColorSelected), __resolveColor(backColor), __resolveColor(backColorSelected), cornerRadius, cornerEdges +def MultiContentEntryProgressPixmap(pos=(0, 0), size=(0, 0), percent=None, pixmap=None, borderWidth=None, borderColor=None, borderColorSelected=None, foreColor=None, foreColorSelected=None, backColor=None, backColorSelected=None, cornerRadius=0, cornerEdges=15): + return eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, int(pos[0]), int(pos[1]), int(size[0]), int(size[1]), percent, __resolvePixmap(pixmap), borderWidth, __resolveColor(foreColor), __resolveColor(foreColorSelected), __resolveColor(backColor), __resolveColor(backColorSelected), __resolveColor(borderColor), __resolveColor(borderColorSelected), cornerRadius, cornerEdges def MultiContentEntryLinearGradient(pos=(0, 0), size=(0, 0), direction=GRADIENT_VERTICAL, startColor=None, midColor=None, endColor=None, startColorSelected=None, midColorSelected=None, endColorSelected=None, cornerRadius=0, cornerEdges=15): diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py index 7bc6a42accf..11beb29feb0 100644 --- a/lib/python/Components/ServiceList.py +++ b/lib/python/Components/ServiceList.py @@ -1,6 +1,6 @@ from enigma import eListboxServiceContent, eListbox, eServiceCenter, eServiceReference, gFont, eRect, eSize -from Components.config import config, ConfigSelection, ConfigSubsection +from Components.config import config, ConfigYesNo, ConfigSelection, ConfigSubsection from Components.GUIComponent import GUIComponent from Components.Renderer.Picon import getPiconName from skin import parseColor, parseFont @@ -11,8 +11,19 @@ def InitServiceListSettings(): config.channelSelection = ConfigSubsection() + config.channelSelection.showNumber = ConfigYesNo(default=True) + config.channelSelection.showLCN = ConfigYesNo(default=False) + config.channelSelection.showPicon = ConfigYesNo(default=False) + config.channelSelection.showServiceTypeIcon = ConfigYesNo(default=False) + config.channelSelection.showCryptoIcon = ConfigYesNo(default=False) + config.channelSelection.recordIndicatorMode = ConfigSelection(default=2, choices=[ + (0, _("None")), + (1, _("Record Icon")), + (2, _("Colored Text")) + ]) choiceList = [("", _("Legacy mode"))] - config.channelSelection.style = ConfigSelection(default="", choices=choiceList) + config.channelSelection.screenStyle = ConfigSelection(default="", choices=choiceList) + config.channelSelection.widgetStyle = ConfigSelection(default="", choices=choiceList) def refreshServiceList(configElement=None): diff --git a/lib/python/Plugins/Extensions/AtileHD/plugin.py b/lib/python/Plugins/Extensions/AtileHD/plugin.py index 6615e69f43b..71d56b1a017 100644 --- a/lib/python/Plugins/Extensions/AtileHD/plugin.py +++ b/lib/python/Plugins/Extensions/AtileHD/plugin.py @@ -115,7 +115,7 @@ def keyCancel(self): self.close(None) -class AtileHD_Config(Screen, ConfigListScreen): +class AtileHD_Config(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py index 643c5b4bb5e..89f2c3903ad 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py +++ b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py @@ -81,7 +81,7 @@ def exit(self): self.close(None, False, None) -class ProjectSettings(Screen, ConfigListScreen): +class ProjectSettings(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py index aa37add3719..951a6ce161d 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py @@ -8,7 +8,7 @@ from . import Title -class TitleProperties(Screen, ConfigListScreen): +class TitleProperties(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index b8935295f45..f87d2b961e4 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -133,7 +133,7 @@ def __init__(self, session, args=None): defaultDir = "" if defaultDir == "": defaultDir = None - self.filelist = FileList(defaultDir, matchingPattern=r"(?i)^.*\.(mp2|mp3|ogg|ts|trp|mts|m2ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|flv|mov|dts|3gp|3g2|asf|wmv|wma|webm)", useServiceRef=True, additionalExtensions="4098:m3u 4098:e2pls 4098:pls") + self.filelist = FileList(defaultDir, matchingPattern=r"(?i)^.*\.(mp2|mp3|ogg|stream|ts|trp|mts|m2ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|flv|mov|dts|3gp|3g2|asf|wmv|wma|webm)", useServiceRef=True, additionalExtensions="4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() diff --git a/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py b/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py index 33c92826b6d..b951dcb7eef 100644 --- a/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py +++ b/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py @@ -571,7 +571,7 @@ def selectionChanged(self): self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1])) -class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen): +class DiseqcTesterTestTypeSelection(ConfigListScreen, Screen): def __init__(self, session, feid): Screen.__init__(self, session) diff --git a/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py b/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py index 63c70d1940d..78019548e79 100644 --- a/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py +++ b/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py @@ -8,7 +8,7 @@ from Components.NimManager import nimmanager as nimmgr -class SecParameterSetup(Screen, ConfigListScreen): +class SecParameterSetup(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py index fcf4346afd0..ed0fc0cf145 100755 --- a/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py @@ -111,7 +111,7 @@ def SettingsEntry(name, checked): return (name, picture, checked) -class BackupScreen(Screen, ConfigListScreen): +class BackupScreen(ConfigListScreen, Screen): skin = """ @@ -429,7 +429,7 @@ def checkSummary(self): self["summary_description"].text = cur -class RestoreScreen(Screen, ConfigListScreen): +class RestoreScreen(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/SystemPlugins/VideoClippingSetup/plugin.py b/lib/python/Plugins/SystemPlugins/VideoClippingSetup/plugin.py index 77d0102f455..fb706019428 100644 --- a/lib/python/Plugins/SystemPlugins/VideoClippingSetup/plugin.py +++ b/lib/python/Plugins/SystemPlugins/VideoClippingSetup/plugin.py @@ -9,7 +9,7 @@ config.plugins.VideoClippingSetup.clip_height = ConfigInteger(default=576) -class VideoClippingCoordinates(Screen, ConfigListScreen): +class VideoClippingCoordinates(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/SystemPlugins/VideoEnhancement/plugin.py b/lib/python/Plugins/SystemPlugins/VideoEnhancement/plugin.py index 1c1891279ea..8d0346e7f71 100644 --- a/lib/python/Plugins/SystemPlugins/VideoEnhancement/plugin.py +++ b/lib/python/Plugins/SystemPlugins/VideoEnhancement/plugin.py @@ -13,7 +13,7 @@ from . import VideoEnhancement -class VideoEnhancementSetup(Screen, ConfigListScreen): +class VideoEnhancementSetup(ConfigListScreen, Screen): def __init__(self, session): Screen.__init__(self, session) self.onChangedEntry = [] @@ -280,7 +280,7 @@ def createSummary(self): return SetupSummary -class VideoEnhancementPreview(Screen, ConfigListScreen): +class VideoEnhancementPreview(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Plugins/SystemPlugins/VideoEnhancementAML/plugin.py b/lib/python/Plugins/SystemPlugins/VideoEnhancementAML/plugin.py index cdaad3c46e3..7e39cecfcd5 100644 --- a/lib/python/Plugins/SystemPlugins/VideoEnhancementAML/plugin.py +++ b/lib/python/Plugins/SystemPlugins/VideoEnhancementAML/plugin.py @@ -11,7 +11,7 @@ from . import VideoEnhancement -class VideoEnhancementSetup(Screen, ConfigListScreen): +class VideoEnhancementSetup(ConfigListScreen, Screen): def __init__(self, session): Screen.__init__(self, session) self.onChangedEntry = [] @@ -196,7 +196,7 @@ def createSummary(self): return SetupSummary -class VideoEnhancementPreview(Screen, ConfigListScreen): +class VideoEnhancementPreview(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py index 2f0138ecb75..9415585e612 100644 --- a/lib/python/Screens/AudioSelection.py +++ b/lib/python/Screens/AudioSelection.py @@ -29,7 +29,7 @@ def getConfigMenuItem(configElementName): return "", None -class AudioSelection(Screen, ConfigListScreen): +class AudioSelection(ConfigListScreen, Screen): def __init__(self, session, infobar=None, page=PAGE_AUDIO): Screen.__init__(self, session) diff --git a/lib/python/Screens/AutoDiseqc.py b/lib/python/Screens/AutoDiseqc.py index 690b537c2f3..fa9aa786452 100644 --- a/lib/python/Screens/AutoDiseqc.py +++ b/lib/python/Screens/AutoDiseqc.py @@ -8,7 +8,7 @@ from enigma import eDVBFrontendParametersSatellite, eDVBResourceManager, eTimer -class AutoDiseqc(Screen, ConfigListScreen): +class AutoDiseqc(ConfigListScreen, Screen): diseqc_ports = [ "A", "B", "C", "D" ] diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index b395876ef6b..290bf757fd6 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -136,7 +136,7 @@ def digitHelp(): self["key_green"] = StaticText(_("Reception Lists")) self["key_yellow"] = StaticText(_("Providers")) self["key_blue"] = StaticText(_("Bouquets")) - self["list"] = ServiceListLegacy(self) if config.channelSelection.style.value == "" else ServiceList(self) + self["list"] = ServiceListLegacy(self) if config.channelSelection.screenStyle.value == "" or config.channelSelection.widgetStyle.value == "" else ServiceList(self) self.servicelist = self["list"] self.numericalTextInput = NumericalTextInput(handleTimeout=False) self.servicePath = [] @@ -2254,7 +2254,9 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect def __init__(self, session): ChannelSelectionBase.__init__(self, session) - if config.usage.use_pig.value: + if config.channelSelection.screenStyle.value: + self.skinName = [config.channelSelection.screenStyle.value] + elif config.usage.use_pig.value: self.skinName = ["ChannelSelection_PIG", "ChannelSelection"] elif config.usage.servicelist_mode.value == "simple": self.skinName = ["SlimChannelSelection", "SimpleChannelSelection", "ChannelSelection"] diff --git a/lib/python/Screens/CronTimer.py b/lib/python/Screens/CronTimer.py index cc83d406976..0a8634d08e6 100755 --- a/lib/python/Screens/CronTimer.py +++ b/lib/python/Screens/CronTimer.py @@ -287,7 +287,7 @@ def info(self): config.crontimers.dayofmonth = NoSave(ConfigInteger(default=1, limits=(1, 31))) -class CronTimersConfig(Screen, ConfigListScreen): +class CronTimersConfig(ConfigListScreen, Screen): def __init__(self, session): Screen.__init__(self, session) Screen.setTitle(self, _("Cron Manager")) diff --git a/lib/python/Screens/EpgSelection.py b/lib/python/Screens/EpgSelection.py index 1320bc87579..b2970c36374 100644 --- a/lib/python/Screens/EpgSelection.py +++ b/lib/python/Screens/EpgSelection.py @@ -764,6 +764,9 @@ def BouquetOK(self): self["list"].instance.moveSelectionTo(0) if self.type == EPG_TYPE_GRAPH or self.type == EPG_TYPE_INFOBARGRAPH: self["list"].fillGraphEPG(None, self.ask_time, True) + serviceref = self.session.nav.getCurrentlyPlayingServiceOrGroup() + if serviceref: + self["list"].moveToService(serviceref) self.setTitle(self["bouquetlist"].getCurrentBouquet()) self.BouquetlistHide(False) diff --git a/lib/python/Screens/InstallWizard.py b/lib/python/Screens/InstallWizard.py index 5b841bc9eba..a906d531375 100644 --- a/lib/python/Screens/InstallWizard.py +++ b/lib/python/Screens/InstallWizard.py @@ -16,7 +16,7 @@ config.misc.installwizard.channellistdownloaded = ConfigBoolean(default=False) -class InstallWizard(Screen, ConfigListScreen): +class InstallWizard(ConfigListScreen, Screen): STATE_UPDATE = 0 STATE_CHANNELLIST = 1 STATE_SOFTCAM = 2 diff --git a/lib/python/Screens/MountManager.py b/lib/python/Screens/MountManager.py index a5da678061f..74af987df34 100644 --- a/lib/python/Screens/MountManager.py +++ b/lib/python/Screens/MountManager.py @@ -293,7 +293,7 @@ def restBo(self, answer): self.selectionChanged() -class DevicePanelConf(Screen, ConfigListScreen): +class DevicePanelConf(ConfigListScreen, Screen): skin = """ diff --git a/lib/python/Screens/NetworkSetup.py b/lib/python/Screens/NetworkSetup.py index ec116bcaafb..00f566f47cd 100644 --- a/lib/python/Screens/NetworkSetup.py +++ b/lib/python/Screens/NetworkSetup.py @@ -382,7 +382,7 @@ def __init__(self, session): DNSSettings.__init__(self, session=session) -class NetworkMacSetup(Screen, ConfigListScreen): +class NetworkMacSetup(ConfigListScreen, Screen): def __init__(self, session): Screen.__init__(self, session, enableHelp=True) self.setTitle(_("MAC Address Settings")) @@ -440,7 +440,7 @@ def restartfinishedCB(self, data): self.session.openWithCallback(self.close, MessageBox, _("Finished configuring your network"), type=MessageBox.TYPE_INFO, timeout=10, default=False) -class AdapterSetup(Screen, ConfigListScreen): +class AdapterSetup(ConfigListScreen, Screen): def __init__(self, session, networkinfo, essid=None): Screen.__init__(self, session, enableHelp=True) self.setTitle(_("Adapter Settings")) diff --git a/lib/python/Screens/TimeDateInput.py b/lib/python/Screens/TimeDateInput.py index 23efcb443fd..b6107f81648 100644 --- a/lib/python/Screens/TimeDateInput.py +++ b/lib/python/Screens/TimeDateInput.py @@ -9,7 +9,7 @@ import datetime -class TimeDateInput(Screen, ConfigListScreen): +class TimeDateInput(ConfigListScreen, Screen): def __init__(self, session, config_time=None, config_date=None): Screen.__init__(self, session) self.setTitle(_("Date/time input")) diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py index a66f81ef5b3..2ad6ee8041b 100644 --- a/lib/python/Screens/VideoMode.py +++ b/lib/python/Screens/VideoMode.py @@ -58,7 +58,7 @@ def setProgressiveRate(vid_rate, new_rate, new_res, config_res, config_rate): return new_rate -class VideoSetup(Screen, ConfigListScreen): +class VideoSetup(ConfigListScreen, Screen): def __init__(self, session): Screen.__init__(self, session) # for the skin: first try VideoSetup, then Setup, this allows individual skinning diff --git a/lib/python/Tools/MultiBoot.py b/lib/python/Tools/MultiBoot.py index 501a77c850c..8c966ea300e 100644 --- a/lib/python/Tools/MultiBoot.py +++ b/lib/python/Tools/MultiBoot.py @@ -245,7 +245,7 @@ def saveKernel(bootSlots, slotCode, kernel): if startupFile: if isinstance(startupFile, dict): if "" in startupFile: - print(f"[MultiBoot] Startup file: '{startupFile['']}'.") + print(f"[MultiBoot] Startup file: '{startupFile[""]}'.") else: print("[MultiBoot] Startup files:") for key in sorted(startupFile.keys()): @@ -256,18 +256,18 @@ def saveKernel(bootSlots, slotCode, kernel): if commandLine: if isinstance(commandLine, dict): if "" in startupFile: - print(f"[MultiBoot] Command line: '{startupFile['']}'.") + print(f"[MultiBoot] Command line: '{startupFile[""]}'.") else: print("[MultiBoot] Command lines:") for key in sorted(commandLine.keys()): print(f"[MultiBoot] Mode '{key}': '{commandLine[key]}'.") else: print(f"[MultiBoot] Command line: '{startupFile}'.") - print(f"[MultiBoot] Kernel device: '{bootSlots[slotCode].get('kernel', 'Unknown')}'.") - print(f"[MultiBoot] Root device: '{bootSlots[slotCode].get('device', 'Unknown')}'.") - print(f"[MultiBoot] Root directory: '{bootSlots[slotCode].get('rootsubdir', 'Unknown')}'.") - print(f"[MultiBoot] UBI device: '{'Yes' if bootSlots[slotCode].get('ubi', False) else 'No'}'.") - print(f"[MultiBoot] UUID device: '{'Yes' if bootSlots[slotCode].get('uuid', False) else 'No'}'.") + print(f"[MultiBoot] Kernel device: '{bootSlots[slotCode].get("kernel", "Unknown")}'.") + print(f"[MultiBoot] Root device: '{bootSlots[slotCode].get("device", "Unknown")}'.") + print(f"[MultiBoot] Root directory: '{bootSlots[slotCode].get("rootsubdir", "Unknown")}'.") + print(f"[MultiBoot] UBI device: '{"Yes" if bootSlots[slotCode].get("ubi", False) else "No"}'.") + print(f"[MultiBoot] UUID device: '{"Yes" if bootSlots[slotCode].get("uuid", False) else "No"}'.") print(f"[MultiBoot] {len(bootSlots)} boot slots detected.") return bootSlots, bootSlotsKeys @@ -400,16 +400,16 @@ def findSlot(self): # Part of getSlotImageList(). if self.debugMode: for slotCode in sorted(self.imageList.keys()): # print(f"[MultiBoot] findSlot DEBUG: Image slot '{slotCode}': {self.imageList[slotCode]}") - print(f"[MultiBoot] Slot '{slotCode}' content: '{self.imageList[slotCode].get('imagelogname', 'Unknown')}'.") - print(f"[MultiBoot] Device: '{self.imageList[slotCode].get('devicelog', 'Unknown')}'.") - print(f"[MultiBoot] Root: '{self.imageList[slotCode].get('rootlog', 'Unknown')}'.") - print(f"[MultiBoot] Detection: '{self.imageList[slotCode].get('detection', 'Unknown')}'.") - print(f"[MultiBoot] Status: '{self.imageList[slotCode].get('status', 'Unknown').capitalize()}'.") + print(f"[MultiBoot] Slot '{slotCode}' content: '{self.imageList[slotCode].get("imagelogname", "Unknown")}'.") + print(f"[MultiBoot] Device: '{self.imageList[slotCode].get("devicelog", "Unknown")}'.") + print(f"[MultiBoot] Root: '{self.imageList[slotCode].get("rootlog", "Unknown")}'.") + print(f"[MultiBoot] Detection: '{self.imageList[slotCode].get("detection", "Unknown")}'.") + print(f"[MultiBoot] Status: '{self.imageList[slotCode].get("status", "Unknown").capitalize()}'.") modes = self.imageList[slotCode].get("bootCodes") if modes and modes != [""]: print(f"[MultiBoot] Boot modes: '{"', '".join(modes)}'.") - print(f"[MultiBoot] UBI device: '{'Yes' if self.imageList[slotCode].get('ubi', False) else 'No'}'.") - print(f"[MultiBoot] UUID device: '{'Yes' if self.imageList[slotCode].get('uuid', False) else 'No'}'.") + print(f"[MultiBoot] UBI device: '{"Yes" if self.imageList[slotCode].get("ubi", False) else "No"}'.") + print(f"[MultiBoot] UUID device: '{"Yes" if self.imageList[slotCode].get("uuid", False) else "No"}'.") print(f"[MultiBoot] {len(self.imageList)} boot slots detected.") self.callback(self.imageList) @@ -432,32 +432,32 @@ def analyzeSlot(self, data, retVal, extraArgs): # Part of getSlotImageList(). revision = "" if revision.strip() == compileDate else revision compileDate = f"{compileDate[0:4]}-{compileDate[4:6]}-{compileDate[6:8]}" self.imageList[self.slotCode]["detection"] = "Found an enigma information file" - self.imageList[self.slotCode]["imagename"] = f"{info.get('displaydistro', info.get('distro'))} {info.get('imgversion')}{revision} ({compileDate})" - self.imageList[self.slotCode]["imagelogname"] = f"{info.get('displaydistro', info.get('distro'))} {info.get('imgversion')}{revision} ({compileDate})" + self.imageList[self.slotCode]["imagename"] = f"{info.get("displaydistro", info.get("distro"))} {info.get("imgversion")}{revision} ({compileDate})" + self.imageList[self.slotCode]["imagelogname"] = f"{info.get("displaydistro", info.get("distro"))} {info.get("imgversion")}{revision} ({compileDate})" self.imageList[self.slotCode]["status"] = "active" elif isfile(infoFile1): info = self.readSlotInfo(infoFile1) compileDate = self.getCompiledate(imageDir) compileDate = f"{compileDate[0:4]}-{compileDate[4:6]}-{compileDate[6:8]}" - imgversion = str(info.get("version")) - if "." not in imgversion and "-" not in imgversion and imgversion.isdigit(): - imgversion = f"{int(imgversion[0:2])}.{int(imgversion[3:5])}" + version = str(info.get("version")) + if "." not in version and "-" not in version and version.isdigit(): + version = f"{int(version[0:2])}.{int(version[3:5])}" self.imageList[self.slotCode]["detection"] = "Found an image version file" - creator = info.get('creator') + creator = info.get("creator") if creator is not None: - self.imageList[self.slotCode]["imagename"] = f"{creator.split()[0]} {imgversion} ({compileDate})" - self.imageList[self.slotCode]["imagelogname"] = f"{creator.split()[0]} {imgversion} ({compileDate})" + self.imageList[self.slotCode]["imagename"] = f"{creator.split()[0]} {version} ({compileDate})" + self.imageList[self.slotCode]["imagelogname"] = f"{creator.split()[0]} {version} ({compileDate})" else: - self.imageList[self.slotCode]["imagename"] = f"Unknown Creator {imgversion} ({compileDate})" - self.imageList[self.slotCode]["imagelogname"] = f"Unknown Creator {imgversion} ({compileDate})" + self.imageList[self.slotCode]["imagename"] = f"Unknown Creator {version} ({compileDate})" + self.imageList[self.slotCode]["imagelogname"] = f"Unknown Creator {version} ({compileDate})" self.imageList[self.slotCode]["status"] = "active" elif isfile(pathjoin(imageDir, "usr/bin/enigma2")): info = self.deriveSlotInfo(imageDir) compileDate = str(info.get("compiledate")) compileDate = f"{compileDate[0:4]}-{compileDate[4:6]}-{compileDate[6:8]}" self.imageList[self.slotCode]["detection"] = "Found an enigma2 binary file" - self.imageList[self.slotCode]["imagename"] = f"{info.get('displaydistro', info.get('distro'))} {info.get('imgversion')} ({compileDate})" - self.imageList[self.slotCode]["imagelogname"] = f"{info.get('displaydistro', info.get('distro'))} {info.get('imgversion')} ({compileDate})" + self.imageList[self.slotCode]["imagename"] = f"{info.get("displaydistro", info.get("distro"))} {info.get("imgversion")} ({compileDate})" + self.imageList[self.slotCode]["imagelogname"] = f"{info.get("displaydistro", info.get("distro"))} {info.get("imgversion")} ({compileDate})" self.imageList[self.slotCode]["status"] = "active" else: self.imageList[self.slotCode]["detection"] = "Found no enigma files" diff --git a/lib/python/skin.py b/lib/python/skin.py index e40fe11d4a0..232fb168c89 100644 --- a/lib/python/skin.py +++ b/lib/python/skin.py @@ -153,9 +153,7 @@ def InitSkins(): getDesktop(GUI_SKIN_ID).resize(eSize(resolution[0], resolution[1])) runCallbacks = True # Load all XML templates. - skinTemplatesFileName = resolveFilename(SCOPE_SKINS, pathjoin(dirname(currentPrimarySkin), "skinTemplates.xml")) - if isfile(skinTemplatesFileName): - loadSkinTemplates(skinTemplatesFileName) + reloadSkinTemplates() # Method to load a skin XML file into the skin data structures. @@ -203,22 +201,39 @@ def loadSkin(filename, scope=SCOPE_SKINS, desktop=getDesktop(GUI_SKIN_ID), scree return False -# Method to load a skinTemplates.xml if one exists. +# Method to load a skinTemplates.xml if one exists or load the templates from the screens. # def loadSkinTemplates(skinTemplatesFileName): - print(f"[Skin] Loading XML templates from '{skinTemplatesFileName}'.") - domStyles = fileReadXML(skinTemplatesFileName, source=MODULE_NAME) - if domStyles is not None: - for template in domStyles.findall("template"): - component = template.get("component") - name = template.get("name") - if component and name: - if component in componentTemplates: - componentTemplates[component][name] = template - else: - componentTemplates[component] = {name: template} - if config.crash.debugScreens.value: - print(f"[Skin] DEBUG: componentTemplates '{componentTemplates}'.") + if isfile(skinTemplatesFileName): + print(f"[Skin] Loading XML templates from '{skinTemplatesFileName}'.") + domStyles = fileReadXML(skinTemplatesFileName, source=MODULE_NAME) + if domStyles is not None: + for template in domStyles.findall("template"): + component = template.get("component") + name = template.get("name") + if component and name: + if component in componentTemplates: + componentTemplates[component][name] = template + else: + componentTemplates[component] = {name: template} + else: + for screen in domScreens: + element, path = domScreens.get(screen, (None, None)) + for template in element.findall(".//widget/templates/template"): + component = template.get("component") + name = template.get("name") + if component and name: + if component in componentTemplates: + componentTemplates[component][name] = template + else: + componentTemplates[component] = {name: template} + if config.crash.debugScreens.value: + print(f"[Skin] DEBUG: componentTemplates '{componentTemplates}'.") + + +def reloadSkinTemplates(): + skinTemplatesFileName = resolveFilename(SCOPE_SKINS, pathjoin(dirname(currentPrimarySkin), "skinTemplates.xml")) + loadSkinTemplates(skinTemplatesFileName) def reloadSkins(): @@ -1817,7 +1832,7 @@ def collectColors(self, attributes): attributes[color] = translatedColor return attributes - def collectAttributes(self, node, context, ignore=(), excludeItemValues=None, includeItemValues=None): + def collectAttributes(self, node, context, ignore=(), excludeItemIndexes=None, includeItemIndexes=None): horizontalAlignments = { "left": 1, "center": 4, @@ -1846,7 +1861,7 @@ def collectAttributes(self, node, context, ignore=(), excludeItemValues=None, in pos = None size = None skinAttributes = [] - itemValue = "" + itemIndex = "" for attrib, value in node.items(): # Walk all attributes. if attrib not in ignore: newValue = value @@ -1855,13 +1870,14 @@ def collectAttributes(self, node, context, ignore=(), excludeItemValues=None, in pos = newValue case "size": size = newValue - case "value": - itemValue = value + case "index": + itemIndex = value + skinAttributes.append((attrib, newValue)) case _: skinAttributes.append((attrib, newValue)) - if itemValue and includeItemValues and itemValue not in includeItemValues: + if itemIndex and includeItemIndexes and itemIndex not in includeItemIndexes: return [] - if itemValue and excludeItemValues and itemValue in excludeItemValues: + if itemIndex and excludeItemIndexes and itemIndex in excludeItemIndexes: return [] if pos is not None: pos, size = context.parse(pos, size, None) @@ -1884,7 +1900,7 @@ def collectAttributes(self, node, context, ignore=(), excludeItemValues=None, in attributes = self.collectColors(attributes) return [attributes] - def processPanel(self, widget, context, excludeItemValues=None, includeItemValues=None): + def processPanel(self, widget, context, excludeItemIndexes=None, includeItemIndexes=None): if self.debug: print(f"[TemplateParser] processPanel DEBUG: Position={widget.attrib.get("position")}, Size={widget.attrib.get("size")}.") print(f"[TemplateParser] processPanel DEBUG: Parent x={context.x}, width={context.w}.") @@ -1909,7 +1925,7 @@ def processPanel(self, widget, context, excludeItemValues=None, includeItemValue items = [] for element in list(widget): processor = self.processors.get(element.tag, self.processNone) - newItems = processor(element, newContext, excludeItemValues=excludeItemValues, includeItemValues=includeItemValues) + newItems = processor(element, newContext, excludeItemIndexes=excludeItemIndexes, includeItemIndexes=includeItemIndexes) if newItems: items += newItems if layout == "horizontal" and newContext.w > 0: @@ -2047,14 +2063,6 @@ def processWidget(widget, context): raise SkinError(f"Component with name '{widgetName}' was not found in skin of screen '{myName}'") # assert screen[widgetName] is not Source collectAttributes(attributes, widget, context, skinPath, ignore=("name",)) - for widgetTemplate in widget.findall("template"): - widgetTemplateComponent = widgetTemplate.get("component") - widgetTemplateName = widgetTemplate.get("name") - if widgetTemplateComponent and widgetTemplateName: - if widgetTemplateComponent in componentTemplates: - componentTemplates[widgetTemplateComponent][widgetTemplateName] = widgetTemplateComponent - else: - componentTemplates[widgetTemplateComponent] = {widgetTemplateName: widgetTemplateComponent} elif widgetSource: # print(f"[Skin] DEBUG: Widget source='{widgetSource}'.") while True: # Get corresponding source until we found a non-obsolete source.