Example #1
0
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()
Example #2
0
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()
Example #3
0
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()
Example #4
0
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()