def install_file(self, user_file, font_path, commit=True, clear=True): doc_cache = DocumentCache() #If the file does not exist the following will fail doc_cache.add(user_file) #Install the file into every cached skin font file for skin_file in self.__doc_cache.list_files(): res_folder = self._get_res_folder(skin_file) res_file = self._get_res_filename(res_folder, user_file) #If an specific res file exists... if os.path.isfile(res_file): self._install_file(doc_cache, res_file, skin_file, font_path) #Otherwise use the dafault fallback else: self._install_file(doc_cache, user_file, skin_file, font_path) #If save was requested if commit: self.__doc_cache.write_all() #Clear cached docs after write (if requested) if clear: self.__doc_cache.clear_all()
def install_file(self, user_file, font_path, commit=True, clear=True): doc_cache = DocumentCache() # If the file does not exist the following will fail doc_cache.add(user_file) # Install the file into every cached skin font file for skin_file in self.__doc_cache.list_files(): res_folder = self._get_res_folder(skin_file) res_file = self._get_res_filename(res_folder, user_file) # If an specific res file exists... if os.path.isfile(res_file): self._install_file(doc_cache, res_file, skin_file, font_path) # Otherwise use the dafault fallback else: self._install_file(doc_cache, user_file, skin_file, font_path) # If save was requested if commit: self.__doc_cache.write_all() # Clear cached docs after write (if requested) if clear: self.__doc_cache.clear_all()
def __init__(self): self.__installed_names = [] self.__doc_cache = DocumentCache() # Check if the environment is sane check_skin_writability() # Initialize the doc cache with found files for file in self._list_skin_include_files(): self.__doc_cache.add(file)
def __init__(self): self.__installed_names = [] self.__doc_cache = DocumentCache() #Check if the environment is sane check_skin_writability() #Initialize the doc cache with found files for file in self._list_skin_include_files(): self.__doc_cache.add(file)
class IncludeManager: __installed_names = None __doc_cache = None def _list_skin_include_files(self): include_list = [] skin_path = xbmc.translatePath("special://skin/") #Go into each dir. Could be 720, 1080... for dir_item in os.listdir(skin_path): dir_path = os.path.join(skin_path, dir_item) if os.path.isdir(dir_path): file = os.path.join(dir_path, "includes.xml") if case_file_exists(file): include_list.append(file) file = os.path.join(dir_path, "Includes.xml") if case_file_exists(file): include_list.append(file) return include_list def __init__(self): self.__installed_names = [] self.__doc_cache = DocumentCache() #Check if the environment is sane check_skin_writability() #Initialize the doc cache with found files for file in self._list_skin_include_files(): self.__doc_cache.add(file) def is_name_installed(self, name): return name in self.__installed_names def add_include(self, name, node): for file in self.__doc_cache.list_files(): doc = self.__doc_cache.read(file) doc.getroot().append(node) self.__installed_names.append(name) def install_file(self, file, commit=True, clear=True): get_logger().info('install include: %s' % file) tree = ET.parse(file) #Handle all includes for item in tree.getroot().findall("include"): name = item.get("name") if name is None: get_logger().warning('Only named includes are supported.') elif self.is_name_installed(name): get_logger().warning('Include name "%s" already installed' % name) else: self.add_include(name, item) #If a save was requested if commit: self.__doc_cache.write_all() #If we where requested to clear the cached docs if clear: self.__doc_cache.clear_all() def remove_installed_names(self): self.__doc_cache.rollback_all() def cleanup(self): self.remove_installed_names() def __del__(self): self.cleanup()
def __init__(self, script_path): self.__installed_names = [] self.__installed_fonts = [] self.__doc_cache = DocumentCache() self.script_path = script_path
class FontManager(object, SkinUtilsFontManager): FONTS = { "script.module.iptvlib-font_MainMenu": "script.module.iptvlib-NotoSans-Bold.ttf", "script.module.iptvlib-font30_title": "script.module.iptvlib-NotoSans-Bold.ttf", "script.module.iptvlib-font30": "script.module.iptvlib-NotoSans-Regular.ttf", "script.module.iptvlib-font14": "script.module.iptvlib-NotoSans-Regular.ttf", "script.module.iptvlib-font12": "script.module.iptvlib-NotoSans-Regular.ttf", } script_path = None def __init__(self, script_path): self.__installed_names = [] self.__installed_fonts = [] self.__doc_cache = DocumentCache() self.script_path = script_path def check_fonts(self): if 'skin.estuary' == get_skin_name(): raise FontManagerException(FontManagerException.INSTALL_NOT_NEEDED) if self.is_restart_needed(): raise FontManagerException(FontManagerException.RESTART_NEEDED) if get_current_skin_path() != get_local_skin_path(): if not self.is_writable(): raise FontManagerException( FontManagerException.INSTALL_NOT_NEEDED) raise FontManagerException(FontManagerException.INSTALL_NEEDED) else: if not os.path.isdir(get_local_skin_path()): raise FontManagerException(FontManagerException.INSTALL_NEEDED) for f in self._list_skin_font_files(): self.__doc_cache.add(f) self.install_fonts() def install_fonts(self): xml_path = os.path.join(self.script_path, "resources", "skins", "Default", "720p", "font.xml") font_dir = os.path.join(self.script_path, "resources", "skins", "Default", "fonts") self.install_file(xml_path, font_dir) reload_skin() @staticmethod def install_skin(): copy_skin_to_userdata(ask_user=False) @staticmethod def is_writable(): # type: () -> bool skin_path = get_local_skin_path() return not os.access(skin_path, os.W_OK) or not do_write_test(skin_path) @staticmethod def is_restart_needed(): # type: () -> bool current_skin_path = get_current_skin_path() local_skin_path = get_local_skin_path() if os.path.isdir( local_skin_path) and current_skin_path != local_skin_path: if is_invalid_local_skin(): time_suffix = datetime.now().strftime('%Y%m%d%H%M%S') shutil.move(local_skin_path, local_skin_path + '-skinutils-' + time_suffix) copy_skin_to_userdata(ask_user=False) return True return False
class FontManager: __installed_names = None __installed_fonts = None __doc_cache = None def _list_skin_font_files(self): font_xml_list = [] skin_path = xbmc.translatePath("special://skin/") #Go into each dir. Could be 720, 1080... for dir_item in os.listdir(skin_path): dir_path = os.path.join(skin_path, dir_item) if os.path.isdir(dir_path): #Try with font.xml file = os.path.join(dir_path, "font.xml") if case_file_exists(file): font_xml_list.append(file) #Don't try the next step on windows, wasted time file = os.path.join(dir_path, "Font.xml") if case_file_exists(file): font_xml_list.append(file) return font_xml_list def __init__(self): self.__installed_names = [] self.__installed_fonts = [] self.__doc_cache = DocumentCache() #Check if the environment is sane check_skin_writability() #Initialize the doc cache with the skin's files for file in self._list_skin_font_files(): self.__doc_cache.add(file) def is_name_installed(self, name): return name in self.__installed_names def is_font_installed(self, file): return file in self.__installed_fonts def _get_font_attr(self, node, name): attrnode = node.find(name) if attrnode is not None: return attrnode.text def _copy_font_file(self, file): skin_font_path = xbmc.translatePath("special://skin/fonts/") file_name = os.path.basename(file) dest_file = os.path.join(skin_font_path, file_name) #TODO: Unix systems could use symlinks #Check if it's already there if dest_file not in self.__installed_fonts: self.__installed_fonts.append(dest_file) #Overwrite if file exists shutil.copyfile(file, dest_file) def _add_font_attr(self, fontdef, name, value): attr = ET.SubElement(fontdef, name) attr.text = value attr.tail = "\n\t\t\t" return attr def _install_font_def(self, skin_file, name, filename, size, style="", aspect="", linespacing=""): #Add it to the registry self.__installed_names.append(name) #Get the parsed skin font file font_doc = self.__doc_cache.read(skin_file) #Iterate over all the fontsets on the file for fontset in font_doc.getroot().findall("fontset"): fontset.findall("font")[-1].tail = "\n\t\t" fontdef = ET.SubElement(fontset, "font") fontdef.text, fontdef.tail = "\n\t\t\t", "\n\t" self._add_font_attr(fontdef, "name", name) #We get the full file path to the font, so let's basename self._add_font_attr(fontdef, "filename", os.path.basename(filename)) self._copy_font_file(filename) last = self._add_font_attr(fontdef, "size", size) if style: if style in ["normal", "bold", "italics", "bolditalics"]: last = self._add_font_attr(fontdef, "style", style) else: raise FontXmlError( "Font '%s' has an invalid style definition: %s" % (name, style) ) if aspect: last = self._add_font_attr(fontdef, "aspect", aspect) if linespacing: last = self._add_font_attr(fontdef, "linespacing", linespacing) last.tail = "\n\t\t" def _install_file(self, doc_cache, user_file, skin_file, font_path): user_doc = doc_cache.read(user_file) #Handle only the first fontset fontset = user_doc.getroot().find("fontset") if len(fontset): #Every font definition inside it for item in fontset.findall("font"): name = self._get_font_attr(item, "name") #Basic check for malformed defs. if name is None: raise FontXmlError("Malformed XML: No name for font definition.") #Omit already defined fonts elif not self.is_name_installed(name): font_file_path = os.path.join( font_path, self._get_font_attr(item, "filename") ) self._install_font_def( skin_file, name, font_file_path, self._get_font_attr(item, "size"), self._get_font_attr(item, "style"), self._get_font_attr(item, "aspect"), self._get_font_attr(item, "linespacing") ) def _get_res_folder(self, path): return os.path.basename(os.path.dirname(path)) def _get_res_filename(self, res_folder, user_file): path, ext = os.path.splitext(user_file) return path + '-' + res_folder + ext def install_file(self, user_file, font_path, commit=True, clear=True): doc_cache = DocumentCache() #If the file does not exist the following will fail doc_cache.add(user_file) #Install the file into every cached skin font file for skin_file in self.__doc_cache.list_files(): res_folder = self._get_res_folder(skin_file) res_file = self._get_res_filename(res_folder, user_file) #If an specific res file exists... if os.path.isfile(res_file): self._install_file(doc_cache, res_file, skin_file, font_path) #Otherwise use the dafault fallback else: self._install_file(doc_cache, user_file, skin_file, font_path) #If save was requested if commit: self.__doc_cache.write_all() #Clear cached docs after write (if requested) if clear: self.__doc_cache.clear_all() def remove_font(self, name): pass def remove_installed_names(self): self.__doc_cache.rollback_all() def remove_installed_fonts(self): for item in self.__installed_fonts: if not try_remove_file(item): get_logger().error( 'Failed removing font file "%s". XBMC may still be using it.' % item ) def cleanup(self): self.remove_installed_names() #Reload skin so font files are no longer in use, and then delete them reload_skin() self.remove_installed_fonts() def __del__(self): self.cleanup()
class IncludeManager: __installed_names = None __doc_cache = None def _list_skin_include_files(self): include_list = [] skin_path = xbmc.translatePath("special://skin/") # Go into each dir. Could be 720, 1080... for dir_item in os.listdir(skin_path): dir_path = os.path.join(skin_path, dir_item) if os.path.isdir(dir_path): file = os.path.join(dir_path, "includes.xml") if case_file_exists(file): include_list.append(file) file = os.path.join(dir_path, "Includes.xml") if case_file_exists(file): include_list.append(file) return include_list def __init__(self): self.__installed_names = [] self.__doc_cache = DocumentCache() # Check if the environment is sane check_skin_writability() # Initialize the doc cache with found files for file in self._list_skin_include_files(): self.__doc_cache.add(file) def is_name_installed(self, name): return name in self.__installed_names def add_include(self, name, node): for file in self.__doc_cache.list_files(): doc = self.__doc_cache.read(file) doc.getroot().append(node) self.__installed_names.append(name) def install_file(self, file, commit=True, clear=True): get_logger().info('install include: %s' % file) tree = ET.parse(file) # Handle all includes for item in tree.getroot().findall("include"): name = item.get("name") if name is None: get_logger().warning('Only named includes are supported.') elif self.is_name_installed(name): get_logger().warning('Include name "%s" already installed' % name) else: self.add_include(name, item) # If a save was requested if commit: self.__doc_cache.write_all() # If we where requested to clear the cached docs if clear: self.__doc_cache.clear_all() def remove_installed_names(self): self.__doc_cache.rollback_all() def cleanup(self): self.remove_installed_names() def __del__(self): self.cleanup()
class FontManager: __installed_names = None __installed_fonts = None __doc_cache = None def _list_skin_font_files(self): font_xml_list = [] skin_path = xbmc.translatePath("special://skin/") # Go into each dir. Could be 720, 1080... for dir_item in os.listdir(skin_path): dir_path = os.path.join(skin_path, dir_item) if os.path.isdir(dir_path): # Try with font.xml file = os.path.join(dir_path, "font.xml") if case_file_exists(file): font_xml_list.append(file) # Don't try the next step on windows, wasted time file = os.path.join(dir_path, "Font.xml") if case_file_exists(file): font_xml_list.append(file) return font_xml_list def __init__(self): self.__installed_names = [] self.__installed_fonts = [] self.__doc_cache = DocumentCache() # Check if the environment is sane check_skin_writability() # Initialize the doc cache with the skin's files for file in self._list_skin_font_files(): self.__doc_cache.add(file) def is_name_installed(self, name): return name in self.__installed_names def is_font_installed(self, file): return file in self.__installed_fonts def _get_font_attr(self, node, name): attrnode = node.find(name) if attrnode is not None: return attrnode.text def _copy_font_file(self, file): skin_font_path = xbmc.translatePath("special://skin/fonts/") file_name = os.path.basename(file) dest_file = os.path.join(skin_font_path, file_name) # TODO: Unix systems could use symlinks # Check if it's already there if dest_file not in self.__installed_fonts: self.__installed_fonts.append(dest_file) # Overwrite if file exists shutil.copyfile(file, dest_file) def _add_font_attr(self, fontdef, name, value): attr = ET.SubElement(fontdef, name) attr.text = value attr.tail = "\n\t\t\t" return attr def _install_font_def(self, skin_file, name, filename, size, style="", aspect="", linespacing=""): # Add it to the registry self.__installed_names.append(name) # Get the parsed skin font file font_doc = self.__doc_cache.read(skin_file) # Iterate over all the fontsets on the file for fontset in font_doc.getroot().findall("fontset"): fontset.findall("font")[-1].tail = "\n\t\t" fontdef = ET.SubElement(fontset, "font") fontdef.text, fontdef.tail = "\n\t\t\t", "\n\t" self._add_font_attr(fontdef, "name", name) # We get the full file path to the font, so let's basename self._add_font_attr(fontdef, "filename", os.path.basename(filename)) self._copy_font_file(filename) last = self._add_font_attr(fontdef, "size", size) if style: if style in [ "normal", "bold", "italics", "bolditalics", "lighten" ]: last = self._add_font_attr(fontdef, "style", style) else: raise FontXmlError( "Font '%s' has an invalid style definition: %s" % (name, style)) if aspect: last = self._add_font_attr(fontdef, "aspect", aspect) if linespacing: last = self._add_font_attr(fontdef, "linespacing", linespacing) last.tail = "\n\t\t" def _install_file(self, doc_cache, user_file, skin_file, font_path): user_doc = doc_cache.read(user_file) # Handle only the first fontset fontset = user_doc.getroot().find("fontset") if len(fontset): # Every font definition inside it for item in fontset.findall("font"): name = self._get_font_attr(item, "name") # Basic check for malformed defs. if name is None: raise FontXmlError( "Malformed XML: No name for font definition.") # Omit already defined fonts elif not self.is_name_installed(name): font_file_path = os.path.join( font_path, self._get_font_attr(item, "filename")) self._install_font_def( skin_file, name, font_file_path, self._get_font_attr(item, "size"), self._get_font_attr(item, "style"), self._get_font_attr(item, "aspect"), self._get_font_attr(item, "linespacing")) def _get_res_folder(self, path): return os.path.basename(os.path.dirname(path)) def _get_res_filename(self, res_folder, user_file): path, ext = os.path.splitext(user_file) return path + '-' + res_folder + ext def install_file(self, user_file, font_path, commit=True, clear=True): doc_cache = DocumentCache() # If the file does not exist the following will fail doc_cache.add(user_file) # Install the file into every cached skin font file for skin_file in self.__doc_cache.list_files(): res_folder = self._get_res_folder(skin_file) res_file = self._get_res_filename(res_folder, user_file) # If an specific res file exists... if os.path.isfile(res_file): self._install_file(doc_cache, res_file, skin_file, font_path) # Otherwise use the dafault fallback else: self._install_file(doc_cache, user_file, skin_file, font_path) # If save was requested if commit: self.__doc_cache.write_all() # Clear cached docs after write (if requested) if clear: self.__doc_cache.clear_all() def remove_font(self, name): pass def remove_installed_names(self): self.__doc_cache.rollback_all() def remove_installed_fonts(self): for item in self.__installed_fonts: if not try_remove_file(item): get_logger().error( 'Failed removing font file "%s". XBMC may still be using it.' % item) def cleanup(self): self.remove_installed_names() # Reload skin so font files are no longer in use, and then delete them reload_skin() self.remove_installed_fonts() def __del__(self): self.cleanup()