Updated kodi settings on Lenovo
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
# coding=utf-8
|
||||
import os, sys, shutil
|
||||
import xbmc, xbmcaddon, xbmcplugin, xbmcgui, xbmcvfs
|
||||
import xml.etree.ElementTree as xmltree
|
||||
import json
|
||||
from traceback import print_exc
|
||||
from urllib.parse import quote, unquote
|
||||
|
||||
from resources.lib.common import *
|
||||
|
||||
class PathRuleFunctions():
|
||||
def __init__(self, ltype):
|
||||
self.nodeRules = None
|
||||
self.ATTRIB = None
|
||||
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 translateComponent( self, component, splitPath ):
|
||||
if component[ 0 ] is None:
|
||||
return splitPath[ 0 ]
|
||||
if component[0].isdigit():
|
||||
string = LANGUAGE( int( component[ 0 ] ) )
|
||||
if string != "": return string
|
||||
return xbmc.getLocalizedString( int( component[ 0 ] ) )
|
||||
else:
|
||||
return component[ 0 ]
|
||||
|
||||
def translateValue( self, rule, splitPath, ruleNum ):
|
||||
if splitPath[ ruleNum ][ 1 ] == "":
|
||||
return "<No value>"
|
||||
|
||||
if rule[ 1 ] == "year" or rule[ 2 ] != "integer" or rule[ 3 ] is None:
|
||||
return splitPath[ ruleNum ][ 1 ]
|
||||
|
||||
try:
|
||||
value = int( splitPath[ ruleNum ][ 1 ] )
|
||||
except:
|
||||
return splitPath[ ruleNum ][ 1 ]
|
||||
|
||||
json_query = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method": "Files.GetDirectory", "params": { "properties": ["title"], "directory": "%s", "media": "files" } }' % rule[ 3 ] )
|
||||
json_response = json.loads(json_query)
|
||||
listings = []
|
||||
values = []
|
||||
# Add all directories returned by the json query
|
||||
if json_response.get('result') and json_response['result'].get('files') and json_response['result']['files'] is not None:
|
||||
for item in json_response['result']['files']:
|
||||
if "id" in item and item[ "id" ] == value:
|
||||
return "(%d) %s" %( value, item[ "label" ] )
|
||||
|
||||
# Didn't find a match
|
||||
return "%s (%s)" %( splitPath[ ruleNum ][ 1 ], xbmc.getLocalizedString(13205) )
|
||||
|
||||
def displayRule( self, actionPath, ruleNum ):
|
||||
try:
|
||||
# Load the xml file
|
||||
tree = xmltree.parse( unquote(actionPath) )
|
||||
root = tree.getroot()
|
||||
# Get the path
|
||||
path = root.find( "path" ).text
|
||||
# Split the path element
|
||||
splitPath = self.ATTRIB.splitPath( path )
|
||||
# Get the rules
|
||||
rules = self.getRulesForPath( splitPath[ 0 ] )
|
||||
if len( splitPath ) == int( ruleNum ):
|
||||
# This rule doesn't exist - create it
|
||||
self.ATTRIB.writeUpdatedPath( actionPath, ( ruleNum, rules[ 0 ][ 1 ], "" ) )
|
||||
rule = rules[ 0 ]
|
||||
translatedValue = "<No value>"
|
||||
else:
|
||||
# Find the matching rule
|
||||
rule = self.getMatchingRule( splitPath[ ruleNum ], rules )
|
||||
translatedValue = self.translateValue( rule, splitPath, ruleNum )
|
||||
|
||||
#Component
|
||||
listitem = xbmcgui.ListItem( label="%s" % ( self.translateComponent( rule, splitPath[ruleNum] ) ) )
|
||||
action = "plugin://plugin.library.node.editor?ltype=%s&type=editPathMatch&actionPath=%s&rule=%d" %( self.ltype, actionPath, ruleNum )
|
||||
xbmcplugin.addDirectoryItem( int(sys.argv[ 1 ]), action, listitem, isFolder=False )
|
||||
|
||||
# Value
|
||||
listitem = xbmcgui.ListItem( label="%s" % ( translatedValue ) )
|
||||
action = "plugin://plugin.library.node.editor?ltype=%s&type=editPathValue&actionPath=%s&rule=%s" %( self.ltype, actionPath, ruleNum )
|
||||
xbmcplugin.addDirectoryItem( int(sys.argv[ 1 ]), action, listitem, isFolder=False )
|
||||
# Browse
|
||||
if rule[ 3 ] is not None:
|
||||
listitem = xbmcgui.ListItem( label=LANGUAGE(30107) )
|
||||
action = "plugin://plugin.library.node.editor?ltype=%s&type=browsePathValue&actionPath=%s&rule=%s" %( self.ltype, actionPath, ruleNum )
|
||||
xbmcplugin.addDirectoryItem( int(sys.argv[ 1 ]), action, listitem, isFolder=False )
|
||||
|
||||
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
||||
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
|
||||
return
|
||||
except:
|
||||
log( "Failed" )
|
||||
print_exc()
|
||||
|
||||
def getRulesForPath( self, path ):
|
||||
# This function gets all valid rules for a given path
|
||||
# Load the rules
|
||||
tree = self._load_rules()
|
||||
subSearch = None
|
||||
content = []
|
||||
elems = tree.getroot().find( "paths" ).findall( "type" )
|
||||
for elem in elems:
|
||||
if elem.attrib.get( "name" ) == path[ 0 ]:
|
||||
for contentType in elem.findall( "content" ):
|
||||
content.append( contentType.text )
|
||||
subSearch = elem
|
||||
break
|
||||
|
||||
if path[ 1 ] and subSearch is not None:
|
||||
for elem in subSearch.findall( "type" ):
|
||||
if elem.attrib.get( "name" ) == path[ 1 ]:
|
||||
if elem.find( "content" ):
|
||||
content = []
|
||||
for contentType in elem.findall( "content" ):
|
||||
content.append( contentType.text )
|
||||
break
|
||||
|
||||
rules = []
|
||||
for rule in tree.getroot().find( "pathRules" ).findall( "rule" ):
|
||||
# Can it be browsed
|
||||
if rule.find( "browse" ) is not None:
|
||||
browse = rule.find( "browse" ).text
|
||||
else:
|
||||
browse = None
|
||||
if len( content ) == 0:
|
||||
rules.append( ( rule.attrib.get( "label" ), rule.attrib.get( "name" ), rule.find( "value" ).text, browse ) )
|
||||
else:
|
||||
for contentType in rule.findall( "content" ):
|
||||
if contentType.text in content:
|
||||
# If the root of the browse is changed dependant on what we're looking at, replace
|
||||
# it now with the correct content
|
||||
if browse is not None and "::root::" in browse:
|
||||
browse = browse.replace( "::root::", content[ 0 ] )
|
||||
rules.append( ( rule.attrib.get( "label" ), rule.attrib.get( "name" ), rule.find( "value" ).text, browse ) )
|
||||
|
||||
if len( rules ) == 0:
|
||||
return [ ( None, "property", "string", None ) ]
|
||||
return rules
|
||||
|
||||
def getMatchingRule( self, component, rules ):
|
||||
# This function matches a component to its rule
|
||||
for rule in rules:
|
||||
if rule[ 1 ] == component[ 0 ]:
|
||||
return rule
|
||||
|
||||
# No rule matched, return an empty one
|
||||
return ( None, "property", "string", None )
|
||||
|
||||
def editMatch( self, actionPath, ruleNum ):
|
||||
# Change the match element of a path component
|
||||
|
||||
# Load the xml file
|
||||
tree = xmltree.parse( unquote(actionPath) )
|
||||
root = tree.getroot()
|
||||
# Get the path
|
||||
path = root.find( "path" ).text
|
||||
# Split the path element
|
||||
splitPath = self.ATTRIB.splitPath( path )
|
||||
# Get the rules and current value
|
||||
rules = self.getRulesForPath( splitPath[ 0 ] )
|
||||
currentValue = splitPath[ ruleNum ][ 1 ]
|
||||
|
||||
if rules[ 0 ][ 0 ] is None:
|
||||
# There are no available choices
|
||||
self.manuallyEditMatch( actionPath, ruleNum, splitPath[ ruleNum ][ 0 ], currentValue )
|
||||
return
|
||||
|
||||
# Build list of rules to choose from
|
||||
selectName = []
|
||||
for rule in rules:
|
||||
selectName.append( self.translateComponent( rule, None ) )
|
||||
|
||||
# Add a manual option
|
||||
selectName.append( LANGUAGE( 30408 ) )
|
||||
|
||||
# Let the user select an operator
|
||||
selectedOperator = xbmcgui.Dialog().select( LANGUAGE( 30305 ), selectName )
|
||||
# If the user selected no operator...
|
||||
if selectedOperator == -1:
|
||||
return
|
||||
elif selectedOperator == len( rules ):
|
||||
# User choose custom property
|
||||
self.manuallyEditMatch( actionPath, ruleNum, splitPath[ ruleNum ][ 0 ], currentValue )
|
||||
return
|
||||
else:
|
||||
self.ATTRIB.writeUpdatedPath( actionPath, ( ruleNum, rules[ selectedOperator ][ 1 ], currentValue ) )
|
||||
|
||||
def manuallyEditMatch( self, actionPath, ruleNum, currentName, currentValue ):
|
||||
type = xbmcgui.INPUT_ALPHANUM
|
||||
returnVal = xbmcgui.Dialog().input( LANGUAGE( 30318 ), currentName, type=type )
|
||||
if returnVal != "":
|
||||
self.ATTRIB.writeUpdatedPath( actionPath, ( ruleNum, returnVal.decode( "utf-8" ), currentValue ) )
|
||||
|
||||
def editValue( self, actionPath, ruleNum ):
|
||||
# Let the user edit the value of a path component
|
||||
|
||||
# Load the xml file
|
||||
tree = xmltree.parse( unquote(actionPath) )
|
||||
root = tree.getroot()
|
||||
# Get the path
|
||||
path = root.find( "path" ).text
|
||||
# Split the path element
|
||||
splitPath = self.ATTRIB.splitPath( path )
|
||||
# Get the rules and current value
|
||||
rules = self.getRulesForPath( splitPath[ 0 ] )
|
||||
rule = self.getMatchingRule( splitPath[ ruleNum ], rules )
|
||||
|
||||
if rule[ 2 ] == "boolean":
|
||||
# Let the user select a boolean
|
||||
selectedBool = xbmcgui.Dialog().select( LANGUAGE( 30307 ), [ xbmc.getLocalizedString(20122), xbmc.getLocalizedString(20424) ] )
|
||||
# If the user selected nothing...
|
||||
if selectedBool == -1:
|
||||
return
|
||||
value = "true"
|
||||
if selectedBool == 1:
|
||||
value = "false"
|
||||
self.ATTRIB.writeUpdatedPath( actionPath, ( ruleNum, splitPath[ ruleNum][ 0 ], value ) )
|
||||
else:
|
||||
type = xbmcgui.INPUT_ALPHANUM
|
||||
if rule[ 2 ] == "integer":
|
||||
type = xbmcgui.INPUT_NUMERIC
|
||||
returnVal = xbmcgui.Dialog().input( LANGUAGE( 30307 ), splitPath[ ruleNum ][ 1 ], type=type )
|
||||
if returnVal != "":
|
||||
self.ATTRIB.writeUpdatedPath( actionPath, ( ruleNum, splitPath[ ruleNum ][ 0 ], returnVal ) )
|
||||
|
||||
|
||||
def browse( self, actionPath, ruleNum ):
|
||||
# This function launches the browser for the given property type
|
||||
|
||||
pDialog = xbmcgui.DialogProgress()
|
||||
pDialog.create( ADDONNAME, LANGUAGE( 30317 ) )
|
||||
|
||||
# Load the xml file
|
||||
tree = xmltree.parse( unquote(actionPath) )
|
||||
root = tree.getroot()
|
||||
# Get the path
|
||||
path = root.find( "path" ).text
|
||||
# Split the path element
|
||||
splitPath = self.ATTRIB.splitPath( path )
|
||||
# Get the rules and current value
|
||||
rules = self.getRulesForPath( splitPath[ 0 ] )
|
||||
rule = self.getMatchingRule( splitPath[ ruleNum ], rules )
|
||||
title = self.translateComponent( rule, splitPath[ ruleNum ] )
|
||||
|
||||
# Get the path we'll be browsing
|
||||
browsePath = self.getBrowsePath( splitPath, rule[ 3 ], ruleNum )
|
||||
|
||||
json_query = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method": "Files.GetDirectory", "params": { "properties": ["title", "file", "thumbnail"], "directory": "%s", "media": "files" } }' % browsePath )
|
||||
json_response = json.loads(json_query)
|
||||
listings = []
|
||||
values = []
|
||||
# Add all directories returned by the json query
|
||||
if json_response.get('result') and json_response['result'].get('files') and json_response['result']['files'] is not None:
|
||||
total = len( json_response[ 'result' ][ 'files' ] )
|
||||
for item in json_response['result']['files']:
|
||||
if item[ "label" ] == "..":
|
||||
continue
|
||||
thumb = None
|
||||
if item[ "thumbnail" ] is not "":
|
||||
thumb = item[ "thumbnail" ]
|
||||
listitem = xbmcgui.ListItem(label=item[ "label" ] )
|
||||
listitem.setArt({'icon': thumb})
|
||||
listitem.setProperty( "thumbnail", thumb )
|
||||
listings.append( listitem )
|
||||
if rule[ 2 ] == "integer" and "id" in item:
|
||||
values.append( str( item[ "id" ] ) )
|
||||
else:
|
||||
values.append( item[ "label" ] )
|
||||
|
||||
pDialog.close()
|
||||
|
||||
if len( listings ) == 0:
|
||||
# No browsable options found
|
||||
xbmcgui.Dialog().ok( ADDONNAME, LANGUAGE( 30409 ) )
|
||||
return
|
||||
|
||||
# Show dialog
|
||||
w = ShowDialog( "DialogSelect.xml", CWD, listing=listings, windowtitle=title )
|
||||
w.doModal()
|
||||
selectedItem = w.result
|
||||
del w
|
||||
if selectedItem == "" or selectedItem == -1:
|
||||
return None
|
||||
|
||||
self.ATTRIB.writeUpdatedPath( actionPath, ( ruleNum, splitPath[ ruleNum ][ 0 ], values[ selectedItem ] ) )
|
||||
|
||||
def getBrowsePath( self, splitPath, newBase, rule ):
|
||||
# This function replaces the base path with the browse path, and removes the current
|
||||
# component
|
||||
|
||||
returnText = ""
|
||||
|
||||
if "::root::" in newBase:
|
||||
newBase = newBase.replace( "::root::", splitPath[ 0 ][ 0 ] )
|
||||
|
||||
# Enumarate through everything in the existing path
|
||||
addedQ = False
|
||||
for x, component in enumerate( splitPath ):
|
||||
if x != rule:
|
||||
# Transfer this component to the new path
|
||||
if x == 0:
|
||||
returnText = newBase
|
||||
elif not addedQ:
|
||||
returnText += "?%s=%s" %( component[ 0 ], quote(component[1]) )
|
||||
addedQ = True
|
||||
else:
|
||||
returnText += "&%s=%s" %( component[ 0 ], quote(component[1]) )
|
||||
return returnText
|
||||
|
||||
# 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
|
||||
|
||||
# ============================
|
||||
# === PRETTY SELECT DIALOG ===
|
||||
# ============================
|
||||
class ShowDialog( xbmcgui.WindowXMLDialog ):
|
||||
def __init__( self, *args, **kwargs ):
|
||||
xbmcgui.WindowXMLDialog.__init__( self )
|
||||
self.listing = kwargs.get( "listing" )
|
||||
self.windowtitle = kwargs.get( "windowtitle" )
|
||||
self.result = -1
|
||||
|
||||
def onInit(self):
|
||||
try:
|
||||
self.fav_list = self.getControl(6)
|
||||
self.getControl(3).setVisible(False)
|
||||
except:
|
||||
print_exc()
|
||||
self.fav_list = self.getControl(3)
|
||||
self.getControl(5).setVisible(False)
|
||||
self.getControl(1).setLabel(self.windowtitle)
|
||||
for item in self.listing :
|
||||
listitem = xbmcgui.ListItem(label=item.getLabel(), label2=item.getLabel2())
|
||||
listitem.setArt({'icon': item.getProperty( "icon" ), 'thumb': item.getProperty( "thumbnail" )})
|
||||
listitem.setProperty( "Addon.Summary", item.getLabel2() )
|
||||
self.fav_list.addItem( listitem )
|
||||
self.setFocus(self.fav_list)
|
||||
|
||||
def onAction(self, action):
|
||||
if action.getId() in ( 9, 10, 92, 216, 247, 257, 275, 61467, 61448, ):
|
||||
self.result = -1
|
||||
self.close()
|
||||
|
||||
def onClick(self, controlID):
|
||||
if controlID == 6 or controlID == 3:
|
||||
num = self.fav_list.getSelectedPosition()
|
||||
self.result = num
|
||||
else:
|
||||
self.result = -1
|
||||
self.close()
|
||||
|
||||
def onFocus(self, controlID):
|
||||
pass
|
||||
Reference in New Issue
Block a user