# coding=utf-8 import os, sys import xbmc, xbmcaddon, xbmcplugin, xbmcgui, xbmcvfs import xml.etree.ElementTree as xmltree from traceback import print_exc from urllib.parse import unquote from resources.lib.common import * class OrderByFunctions(): def __init__(self, ltype): self.ltype = ltype def _load_rules( self ): if self.ltype.startswith('video'): overridepath = os.path.join( DEFAULTPATH , "videorules.xml" ) else: overridepath = os.path.join( DEFAULTPATH , "musicrules.xml" ) try: tree = xmltree.parse( overridepath ) return tree except: return None def translateOrderBy( self, rule ): # Load the rules tree = self._load_rules() hasValue = True if rule[ 0 ] == "sorttitle": rule[ 0 ] = "title" if rule[ 0 ] != "random": # Get the field we're ordering by elems = tree.getroot().find( "matches" ).findall( "match" ) for elem in elems: if elem.attrib.get( "name" ) == rule[ 0 ]: match = xbmc.getLocalizedString( int( elem.find( "label" ).text ) ) else: # We'll manually set for random match = xbmc.getLocalizedString( 590 ) # Get localization of direction direction = None elems = tree.getroot().find( "orderby" ).findall( "type" ) for elem in elems: if elem.text == rule[ 1 ]: direction = xbmc.getLocalizedString( int( elem.attrib.get( "label" ) ) ) directionVal = rule[ 1 ] if direction is None: direction = xbmc.getLocalizedString( int( tree.getroot().find( "orderby" ).find( "type" ).attrib.get( "label" ) ) ) directionVal = tree.getroot().find( "orderby" ).find( "type" ).text return [ [ match, rule[ 0 ] ], [ direction, directionVal ] ] def displayOrderBy( self, actionPath): try: # Load the xml file tree = xmltree.parse( unquote(actionPath) ) root = tree.getroot() # Get the content type content = root.find( "content" ).text # Get the order node orderby = root.find( "order" ) if orderby is None: # There is no orderby element, so add one self.newOrderBy( tree, actionPath ) orderby = root.find( "order" ) match = orderby.text if "direction" in orderby.attrib: direction = orderby.attrib.get( "direction" ) else: direction = "" translated = self.translateOrderBy( [match, direction ] ) listitem = xbmcgui.ListItem( label="%s" % ( translated[ 0 ][ 0 ] ) ) action = "plugin://plugin.library.node.editor?ltype=%s&type=editOrderBy&actionPath=" % self.ltype + actionPath + "&content=" + content + "&default=" + translated[0][1] xbmcplugin.addDirectoryItem( int(sys.argv[ 1 ]), action, listitem, isFolder=False ) listitem = xbmcgui.ListItem( label="%s" % ( translated[ 1 ][ 0 ] ) ) action = "plugin://plugin.library.node.editor?ltype=%s&type=editOrderByDirection&actionPath=" % self.ltype + actionPath + "&default=" + translated[1][1] xbmcplugin.addDirectoryItem( int(sys.argv[ 1 ]), action, listitem, isFolder=False ) xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.endOfDirectory(int(sys.argv[1])) except: print_exc() def editOrderBy( self, actionPath, content, default ): # Load all operator groups tree = self._load_rules().getroot() elems = tree.find( "matches" ).findall( "match" ) selectName = [] selectValue = [] # Find the matches for the content we've been passed for elem in elems: contentMatch = elem.find( content ) if contentMatch is not None: selectName.append( xbmc.getLocalizedString( int( elem.find( "label" ).text ) ) ) selectValue.append( elem.attrib.get( "name" ) ) # Add a random element selectName.append( xbmc.getLocalizedString( 590 ) ) selectValue.append( "random" ) # Let the user select an operator selectedOperator = xbmcgui.Dialog().select( LANGUAGE( 30314 ), selectName ) # If the user selected no operator... if selectedOperator == -1: return returnVal = selectValue[ selectedOperator ] if returnVal == "title": returnVal = "sorttitle" self.writeUpdatedOrderBy( actionPath, field = returnVal ) def editDirection( self, actionPath, direction ): # Load all directions tree = self._load_rules().getroot() elems = tree.find( "orderby" ).findall( "type" ) selectName = [] selectValue = [] # Find the group we've been passed and load its operators for elem in elems: selectName.append( xbmc.getLocalizedString( int( elem.attrib.get( "label" ) ) ) ) selectValue.append( elem.text ) # Let the user select an operator selectedOperator = xbmcgui.Dialog().select( LANGUAGE( 30315 ), selectName ) # If the user selected no operator... if selectedOperator == -1: return self.writeUpdatedOrderBy( actionPath, direction = selectValue[ selectedOperator ] ) def writeUpdatedOrderBy( self, actionPath, field = None, direction = None ): # This function writes an updated orderby rule try: # Load the xml file tree = xmltree.parse( unquote(unquote(actionPath)) ) root = tree.getroot() # Get all the rules orderby = root.find( "order" ) if field is not None: orderby.text = field if direction is not None: orderby.set( "direction", direction ) # Save the file self.indent( root ) tree.write( unquote(actionPath), encoding="UTF-8" ) except: print_exc() def newOrderBy( self, tree, actionPath ): # This function adds a new OrderBy, with default match and direction try: # Load the xml file #tree = xmltree.parse( actionPath ) root = tree.getroot() # Get the content type content = root.find( "content" ) if content is None: xbmcgui.Dialog().ok( ADDONNAME, LANGUAGE( 30406 ) ) return else: content = content.text # Find the default match for this content type ruleTree = self._load_rules().getroot() elems = ruleTree.find( "matches" ).findall( "match" ) match = "title" for elem in elems: contentCheck = elem.find( content ) if contentCheck is not None: # We've found the first match for this type match = elem.attrib.get( "name" ) break if match == "title": match = "sorttitle" # Find the default direction elem = ruleTree.find( "orderby" ).find( "type" ) direction = elem.text # Write the new rule newRule = xmltree.SubElement( root, "order" ) newRule.text = match newRule.set( "direction", direction ) # Save the file self.indent( root ) tree.write( unquote( actionPath ), encoding="UTF-8" ) except: print_exc() # in-place prettyprint formatter def indent( self, elem, level=0 ): i = "\n" + level*"\t" if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + "\t" if not elem.tail or not elem.tail.strip(): elem.tail = i for elem in elem: self.indent(elem, level+1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i