xbmcbackup/resources/lib/advanced_editor.py
2019-11-25 15:48:42 -06:00

228 lines
8.9 KiB
Python

import json
import xbmc
import xbmcgui
import xbmcvfs
from . import utils as utils
class BackupSetManager:
jsonFile = xbmc.translatePath(utils.data_dir() + "custom_paths.json")
paths = None
def __init__(self):
self.paths = {}
# try and read in the custom file
self._readFile()
def addSet(self, aSet):
self.paths[aSet['name']] = {'root':aSet['root'], 'dirs':[{"type":"include", "path":aSet['root'], 'recurse':True}]}
# save the file
self._writeFile()
def updateSet(self, name, aSet):
self.paths[name] = aSet
# save the file
self._writeFile()
def deleteSet(self, index):
# match the index to a key
keys = self.getSets()
# delete this set
del self.paths[keys[index]]
#save the file
self._writeFile()
def getSets(self):
# list all current sets by name
keys = list(self.paths.keys())
keys.sort()
return keys
def getSet(self, index):
keys = self.getSets();
# return the set at this index
return {'name':keys[index], 'set':self.paths[keys[index]]}
def validateSetName(self, name):
return (name not in self.getSets())
def _writeFile(self):
# create the custom file
aFile = xbmcvfs.File(self.jsonFile, 'w')
aFile.write(json.dumps(self.paths))
aFile.close()
def _readFile(self):
if(xbmcvfs.exists(self.jsonFile)):
# read in the custom file
aFile = xbmcvfs.File(self.jsonFile)
# load custom dirs
self.paths = json.loads(aFile.read())
aFile.close()
else:
# write a blank file
self._writeFile()
class AdvancedBackupEditor:
dialog = None
def __init__(self):
self.dialog = xbmcgui.Dialog()
def _cleanPath(self, root, path):
return path[len(root)-1:]
def _validatePath(self, root, path):
return path.startswith(root)
def createSet(self):
backupSet = None
name = self.dialog.input(utils.getString(30110), defaultt='Backup Set')
if(name != None):
# give a choice to start in home or enter a root path
enterHome = self.dialog.yesno(utils.getString(30111), line1=utils.getString(30112) + " - " + utils.getString(30114), line2=utils.getString(30113) + " - " + utils.getString(30115), nolabel=utils.getString(30112), yeslabel=utils.getString(30113))
rootFolder = 'special://home'
if(enterHome):
rootFolder = self.dialog.input(utils.getString(30116), defaultt=rootFolder)
# direcotry has to end in slash
if(rootFolder[:-1] != '/'):
rootFolder = rootFolder + '/'
# check that this path even exists
if(not xbmcvfs.exists(xbmc.translatePath(rootFolder))):
self.dialog.ok(utils.getString(30117), utils.getString(30118), rootFolder)
return None
else:
# select path to start set
rootFolder = self.dialog.browse(type=0, heading=utils.getString(30119), shares='files', defaultt=rootFolder)
backupSet = {'name':name, 'root':rootFolder}
return backupSet
def editSet(self ,name, backupSet):
optionSelected = ''
rootPath = backupSet['root']
utils.log(rootPath)
while(optionSelected != -1):
options = [xbmcgui.ListItem(utils.getString(30120), "Exclude a specific folder from this backup set"), xbmcgui.ListItem(utils.getString(30135), "Include a specific folder to this backup set"), xbmcgui.ListItem(rootPath, utils.getString(30121))]
for aDir in backupSet['dirs']:
if(aDir['type'] == 'exclude'):
options.append(xbmcgui.ListItem(self._cleanPath(rootPath, aDir['path']),"%s: %s" % ("Type", utils.getString(30129))))
elif(aDir['type'] == 'include'):
options.append(xbmcgui.ListItem(self._cleanPath(rootPath, aDir['path']),"%s: %s | %s: %s" % ("Type", utils.getString(30134), "Include Sub Folders", str(aDir['recurse']))))
optionSelected = self.dialog.select(utils.getString(30122) + ' ' + name, options, useDetails=True)
if(optionSelected == 0 or optionSelected == 1):
# add a folder, will equal root if cancel is hit
addFolder = self.dialog.browse(type=0, heading=utils.getString(30120), shares='files', defaultt=backupSet['root'])
if(addFolder.startswith(rootPath)):
if(not any(addFolder == aDir['path'] for aDir in backupSet['dirs'])):
# cannot add root as an exclusion
if(optionSelected == 0 and addFolder != backupSet['root']):
backupSet['dirs'].append({"path":addFolder, "type":"exclude"})
elif(optionSelected == 1):
# can add root as inclusion
backupSet['dirs'].append({"path":addFolder, "type":"include", "recurse":True})
else:
# this path is already part of another include/exclude rule
self.dialog.ok(utils.getString(30117), utils.getString(30137), addFolder)
else:
# folder must be under root folder
self.dialog.ok(utils.getString(30117), utils.getString(30136), rootPath)
elif(optionSelected == 2):
self.dialog.ok(utils.getString(30121), utils.getString(30130), backupSet['root'])
elif(optionSelected > 2):
cOptions = ['Delete']
if(backupSet['dirs'][optionSelected - 3]['type'] == 'include'):
cOptions.append('Toggle Sub Folders')
contextOption = self.dialog.contextmenu(cOptions)
if(contextOption == 0):
if(self.dialog.yesno(heading=utils.getString(30123), line1=utils.getString(30128))):
# remove folder
del backupSet['dirs'][optionSelected - 3]
elif(contextOption == 1 and backupSet['dirs'][optionSelected - 3]['type'] == 'include'):
# toggle if this folder should be recursive
backupSet['dirs'][optionSelected - 3]['recurse'] = not backupSet['dirs'][optionSelected - 3]['recurse']
return backupSet
def showMainScreen(self):
exitCondition = ""
customPaths = BackupSetManager()
# show this every time
self.dialog.ok(utils.getString(30036), utils.getString(30037))
while(exitCondition != -1):
# load the custom paths
options = [xbmcgui.ListItem(utils.getString(30126), '', utils.addon_dir() + '/resources/images/plus-icon.png')]
for index in range(0, len(customPaths.getSets())):
aSet = customPaths.getSet(index)
options.append(xbmcgui.ListItem(aSet['name'], utils.getString(30121) + ': ' + aSet['set']['root'], utils.addon_dir() + '/resources/images/folder-icon.png'))
# show the gui
exitCondition = self.dialog.select(utils.getString(30125), options, useDetails=True)
if(exitCondition >= 0):
if(exitCondition == 0):
newSet = self.createSet()
# check that the name is unique
if(customPaths.validateSetName(newSet['name'])):
customPaths.addSet(newSet)
else:
self.dialog.ok(utils.getString(30117), utils.getString(30138), newSet['name'])
else:
# bring up a context menu
menuOption = self.dialog.contextmenu([utils.getString(30122), utils.getString(30123)])
if(menuOption == 0):
# get the set
aSet = customPaths.getSet(exitCondition -1)
# edit the set
updatedSet = self.editSet(aSet['name'], aSet['set'])
# save it
customPaths.updateSet(aSet['name'], updatedSet)
elif(menuOption == 1):
if(self.dialog.yesno(heading=utils.getString(30127), line1=utils.getString(30128))):
# delete this path - subtract one because of "add" item
customPaths.deleteSet(exitCondition -1)
def copySimpleConfig(self):
# disclaimer in case the user hit this on accident
shouldContinue = self.dialog.yesno(utils.getString(30139), utils.getString(30140), utils.getString(30141))
if(shouldContinue):
source = xbmc.translatePath(utils.addon_dir() + "/resources/data/default_files.json")
dest = xbmc.translatePath(utils.data_dir() + "/custom_paths.json")
xbmcvfs.copy(source, dest)