started new way of defining backup directories

This commit is contained in:
Rob Weber 2017-11-08 15:57:44 -06:00
parent 64daaa13e8
commit 20ee7a92ad
4 changed files with 234 additions and 204 deletions

View File

@ -0,0 +1,91 @@
{
"addons":{
"root":"",
"dirs":[
{
"type":"include",
"path":"special://home/addons",
"recurse":true
},
{
"type":"exclude",
"path":"special://home/addons/packages"
}
]
},
"addon_data":{
"root":"special://home/userdata/addon_data",
"dirs":[
{
"type":"include",
"path":"special://home/userdata/addon_data",
"recurse":true
}
]
},
"database":{
"root":"special://home/userdata/Database",
"dirs":[
{
"type":"include",
"path":"special://home/userdata/Database",
"recurse":true
}
]
},
"playlists":{
"root":"special://home/userdata/playlists",
"dirs":[
{
"type":"include",
"path":"special://home/userdata/playlists",
"recurse":true
}
]
},
"profiles":{
"root":"special://home/userdata/profiles",
"dirs":[
{
"type":"include",
"path":"special://home/userdata/profiles",
"recurse":true
}
]
},
"thumbnails":{
"root":"special://home/userdata/Thumbnails",
"dirs":[
{
"type":"include",
"path":"special://home/userdata/Thumbnails",
"recurse":true
}
]
},
"config":{
"root":"special://home/userdata/",
"dirs":[
{
"type":"include",
"path":"special://home/userdata/",
"recurse":false
},
{
"type":"include",
"path":"special://home/userdata/keymaps",
"recurse":true
},
{
"type":"include",
"path":"special://home/userdata/peripheral_data",
"recurse":true
},
{
"type":"include",
"path":"special://home/userdata/library",
"recurse":true
}
]
}
}

View File

@ -129,12 +129,12 @@ msgid "Config Files"
msgstr "Config Files" msgstr "Config Files"
msgctxt "#30036" msgctxt "#30036"
msgid "Custom Directory 1" msgid ""
msgstr "Custom Directory 1" msgstr ""
msgctxt "#30037" msgctxt "#30037"
msgid "Custom Directory 2" msgid ""
msgstr "Custom Directory 2" msgstr ""
msgctxt "#30038" msgctxt "#30038"
msgid "Advanced Settings Detected" msgid "Advanced Settings Detected"

View File

@ -161,8 +161,65 @@ class XbmcBackup:
#make the remote directory #make the remote directory
self.remote_vfs.mkdir(self.remote_vfs.root_path) self.remote_vfs.mkdir(self.remote_vfs.root_path)
#read in a list of the directories to backup
selectedDirs = self._readBackupConfig(utils.addon_dir() + "/resources/data/default_files.json")
utils.log(utils.getString(30051))
allFiles = []
fileManager = FileManager(self.xbmc_vfs)
#go through each of the user selected items and write them to the backup store
if(utils.getSetting('backup_addons') == 'true'):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['addons']['root']))
for aDir in selectedDirs['addons']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"addons","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
if(utils.getSetting('backup_addon_data') == 'true'):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['addon_data']['root']))
for aDir in selectedDirs['addon_data']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"addon_data","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
if(utils.getSetting('backup_database') == 'true'):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['database']['root']))
for aDir in selectedDirs['database']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"database","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
if(utils.getSetting("backup_playlists") == 'true'):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['playlists']['root']))
for aDir in selectedDirs['playlists']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"playlists","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
if(utils.getSetting('backup_profiles') == 'true'):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['profiles']['root']))
for aDir in selectedDirs['profiles']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"profiles","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
if(utils.getSetting("backup_thumbnails") == "true"):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['thumbnails']['root']))
for aDir in selectedDirs['thumbnails']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"thumbnails","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
if(utils.getSetting("backup_config") == "true"):
self.xbmc_vfs.set_root(xbmc.translatePath(selectedDirs['config']['root']))
for aDir in selectedDirs['config']['dirs']:
fileManager.addDir(aDir)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"name":"config","source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
#create a validation file for backup rotation #create a validation file for backup rotation
writeCheck = self._createValidationFile() writeCheck = self._createValidationFile(allFiles)
if(not writeCheck): if(not writeCheck):
#we may not be able to write to this destination for some reason #we may not be able to write to this destination for some reason
@ -171,89 +228,13 @@ class XbmcBackup:
if(not shouldContinue): if(not shouldContinue):
return return
utils.log(utils.getString(30051))
allFiles = []
fileManager = FileManager(self.xbmc_vfs)
#go through each of the user selected items and write them to the backup store
if(utils.getSetting('backup_addons') == 'true'):
fileManager.addFile("-" + xbmc.translatePath('special://home/addons'))
fileManager.excludeFile(xbmc.translatePath('special://home/addons/packages'))
fileManager.walkTree(xbmc.translatePath('special://home/addons'))
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata'))
if(utils.getSetting('backup_addon_data') == 'true'):
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/addon_data'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/addon_data'))
if(utils.getSetting('backup_database') == 'true'):
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/Database'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/Database'))
if(utils.getSetting("backup_playlists") == 'true'):
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/playlists'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/playlists'))
if(utils.getSetting('backup_profiles') == 'true'):
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/profiles'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/profiles'))
if(utils.getSetting("backup_thumbnails") == "true"):
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/Thumbnails'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/Thumbnails'))
if(utils.getSetting("backup_config") == "true"):
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/keymaps'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/keymaps'))
fileManager.addFile("-" + xbmc.translatePath('special://home/userdata/peripheral_data'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/peripheral_data'))
fileManager.addFile('-' + xbmc.translatePath('special://home/userdata/library'))
fileManager.walkTree(xbmc.translatePath('special://home/userdata/library'))
#this part is an oddity
dirs,configFiles = self.xbmc_vfs.listdir(xbmc.translatePath('special://home/userdata/'))
for aFile in configFiles:
if(aFile.endswith(".xml")):
fileManager.addFile(xbmc.translatePath('special://home/userdata/') + aFile)
#add to array
self.filesTotal = fileManager.size()
allFiles.append({"source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()})
orig_base_path = self.remote_vfs.root_path orig_base_path = self.remote_vfs.root_path
#check if there are custom directories
if(utils.getSetting('custom_dir_1_enable') == 'true' and utils.getSetting('backup_custom_dir_1') != ''):
#create a special remote path with hash
self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir_1'))
fileManager.addFile("-custom_" + self._createCRC(self.xbmc_vfs.root_path))
#walk the directory
fileManager.walkTree(self.xbmc_vfs.root_path)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path),"files":fileManager.getFiles()})
if(utils.getSetting('custom_dir_2_enable') == 'true' and utils.getSetting('backup_custom_dir_2') != ''):
#create a special remote path with hash
self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir_2'))
fileManager.addFile("-custom_" + self._createCRC(self.xbmc_vfs.root_path))
#walk the directory
fileManager.walkTree(self.xbmc_vfs.root_path)
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path),"files":fileManager.getFiles()})
#backup all the files #backup all the files
self.filesLeft = self.filesTotal self.filesLeft = self.filesTotal
for fileGroup in allFiles: for fileGroup in allFiles:
self.xbmc_vfs.set_root(fileGroup['source']) self.xbmc_vfs.set_root(fileGroup['source'])
self.remote_vfs.set_root(fileGroup['dest']) self.remote_vfs.set_root(fileGroup['dest'] + fileGroup['name'])
filesCopied = self.backupFiles(fileGroup['files'],self.xbmc_vfs,self.remote_vfs) filesCopied = self.backupFiles(fileGroup['files'],self.xbmc_vfs,self.remote_vfs)
if(not filesCopied): if(not filesCopied):
@ -332,7 +313,8 @@ class XbmcBackup:
xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path) xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path)
return return
if(not self._checkValidationFile(self.remote_vfs.root_path)): valFile = self._checkValidationFile(self.remote_vfs.root_path)
if(valFile == None):
#don't continue #don't continue
return return
@ -340,97 +322,35 @@ class XbmcBackup:
allFiles = [] allFiles = []
fileManager = FileManager(self.remote_vfs) fileManager = FileManager(self.remote_vfs)
#go through each of the user selected items and write them to the backup store
if(utils.getSetting("backup_config") == "true"):
#check for the existance of an advancedsettings file
if(self.remote_vfs.exists(self.remote_vfs.root_path + "userdata/advancedsettings.xml") and not self.skip_advanced):
#let the user know there is an advanced settings file present
restartXbmc = xbmcgui.Dialog().yesno(utils.getString(30038),utils.getString(30039),utils.getString(30040), utils.getString(30041))
if(restartXbmc):
#add only this file to the file list
fileManager.addFile(self.remote_vfs.root_path + "userdata/advancedsettings.xml")
self.backupFiles(fileManager.getFiles(),self.remote_vfs,self.xbmc_vfs)
#let the service know to resume this backup on startup
self._createResumeBackupFile()
#do not continue running
xbmcgui.Dialog().ok(utils.getString(30077),utils.getString(30078))
return
fileManager.addFile('-' + self.remote_vfs.root_path + 'userdata/keymaps')
fileManager.walkTree(self.remote_vfs.root_path + "userdata/keymaps")
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/peripheral_data")
fileManager.walkTree(self.remote_vfs.root_path + "userdata/peripheral_data")
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/library") #check for the existance of an advancedsettings file
fileManager.walkTree(self.remote_vfs.root_path + "userdata/library") if(self.remote_vfs.exists(self.remote_vfs.root_path + "config/advancedsettings.xml") and not self.skip_advanced):
#let the user know there is an advanced settings file present
#this part is an oddity restartXbmc = xbmcgui.Dialog().yesno(utils.getString(30038),utils.getString(30039),utils.getString(30040), utils.getString(30041))
dirs,configFiles = self.remote_vfs.listdir(self.remote_vfs.root_path + "userdata/")
for aFile in configFiles:
if(aFile.endswith(".xml")):
fileManager.addFile(self.remote_vfs.root_path + "userdata/" + aFile)
if(utils.getSetting('backup_addons') == 'true'): if(restartXbmc):
fileManager.addFile('-' + self.remote_vfs.root_path + "addons") #add only this file to the file list
fileManager.walkTree(self.remote_vfs.root_path + "addons") fileManager.addFile(self.remote_vfs.root_path + "config/advancedsettings.xml")
self.backupFiles(fileManager.getFiles(),self.remote_vfs,self.xbmc_vfs)
self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata')) #let the service know to resume this backup on startup
self._createResumeBackupFile()
if(utils.getSetting('backup_addon_data') == 'true'): #do not continue running
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/addon_data") xbmcgui.Dialog().ok(utils.getString(30077),utils.getString(30078))
fileManager.walkTree(self.remote_vfs.root_path + "userdata/addon_data") return
if(utils.getSetting('backup_database') == 'true'): #go through each of the directories in the backup and write them to the correct location
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/Database") for aDir in valFile['directories']:
fileManager.walkTree(self.remote_vfs.root_path + "userdata/Database") self.xbmc_vfs.set_root(aDir['path'])
if(self.remote_vfs.exists(self.remote_vfs.root_path + aDir['name'] + '/')):
if(utils.getSetting("backup_playlists") == 'true'): #walk the directory
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/playlists") fileManager.walkTree(self.remote_vfs.root_path + aDir['name'] + '/')
fileManager.walkTree(self.remote_vfs.root_path + "userdata/playlists")
if(utils.getSetting('backup_profiles') == 'true'):
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/profiles")
fileManager.walkTree(self.remote_vfs.root_path + "userdata/profiles")
if(utils.getSetting("backup_thumbnails") == "true"):
fileManager.addFile('-' + self.remote_vfs.root_path + "userdata/Thumbnails")
fileManager.walkTree(self.remote_vfs.root_path + "userdata/Thumbnails")
#add to array
self.filesTotal = fileManager.size()
allFiles.append({"source":self.remote_vfs.root_path,"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()})
#check if there are custom directories
if(utils.getSetting('custom_dir_1_enable') == 'true' and utils.getSetting('backup_custom_dir_1') != ''):
self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir_1'))
if(self.remote_vfs.exists(self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path) + "/")):
#index files to restore
fileManager.walkTree(self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path))
self.filesTotal = self.filesTotal + fileManager.size() self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"source":self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path),"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()}) allFiles.append({"source":self.remote_vfs.root_path + aDir['name'],"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()})
else: else:
utils.log("error path not found: " + self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path)) utils.log("error path not found: " + self.remote_vfs.root_path + aDir['name'])
xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path + "custom_" + self._createCRC(utils.getSetting('backup_custom_dir_1'))) xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path + aDir['name'])
if(utils.getSetting('custom_dir_2_enable') == 'true' and utils.getSetting('backup_custom_dir_2') != ''):
self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir_2'))
if(self.remote_vfs.exists(self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path) + "/")):
#index files to restore
fileManager.walkTree(self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path))
self.filesTotal = self.filesTotal + fileManager.size()
allFiles.append({"source":self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path),"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()})
else:
utils.log("error path not found: " + self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path))
xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path + "custom_" + self._createCRC(utils.getSetting('backup_custom_dir_2')))
#restore all the files #restore all the files
self.filesLeft = self.filesTotal self.filesLeft = self.filesTotal
@ -534,9 +454,16 @@ class XbmcBackup:
remove_num = remove_num + 1 remove_num = remove_num + 1
def _createValidationFile(self): def _createValidationFile(self,dirList):
valInfo = {"name":"XBMC Backup Validation File","xbmc_version":xbmc.getInfoLabel('System.BuildVersion'),"type":0}
valDirs = []
for aDir in dirList:
valDirs.append({"name":aDir['name'],"path":aDir['source']})
valInfo['directories'] = valDirs
vFile = xbmcvfs.File(xbmc.translatePath(utils.data_dir() + "xbmcbackup.val"),'w') vFile = xbmcvfs.File(xbmc.translatePath(utils.data_dir() + "xbmcbackup.val"),'w')
vFile.write(json.dumps({"name":"XBMC Backup Validation File","xbmc_version":xbmc.getInfoLabel('System.BuildVersion')})) vFile.write(json.dumps(valInfo))
vFile.write("") vFile.write("")
vFile.close() vFile.close()
@ -548,7 +475,7 @@ class XbmcBackup:
return success return success
def _checkValidationFile(self,path): def _checkValidationFile(self,path):
result = False result = None
#copy the file and open it #copy the file and open it
self.xbmc_vfs.put(path + "xbmcbackup.val",xbmc.translatePath(utils.data_dir() + "xbmcbackup_restore.val")) self.xbmc_vfs.put(path + "xbmcbackup.val",xbmc.translatePath(utils.data_dir() + "xbmcbackup_restore.val"))
@ -561,16 +488,17 @@ class XbmcBackup:
xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "xbmcbackup_restore.val")) xbmcvfs.delete(xbmc.translatePath(utils.data_dir() + "xbmcbackup_restore.val"))
try: try:
json_dict = json.loads(jsonString) result = json.loads(jsonString)
if(xbmc.getInfoLabel('System.BuildVersion') == json_dict['xbmc_version']): if(xbmc.getInfoLabel('System.BuildVersion') != result['xbmc_version']):
result = True shouldContinue = xbmcgui.Dialog().yesno(utils.getString(30085),utils.getString(30086),utils.getString(30044))
else:
result = xbmcgui.Dialog().yesno(utils.getString(30085),utils.getString(30086),utils.getString(30044)) if(not shouldContinue):
result = None
except ValueError: except ValueError:
#may fail on older archives #may fail on older archives
result = True result = None
return result return result
@ -579,6 +507,12 @@ class XbmcBackup:
rFile.write(self.restore_point) rFile.write(self.restore_point)
rFile.close() rFile.close()
def _readBackupConfig(self,aFile):
jFile = xbmcvfs.File(xbmc.translatePath(aFile),'r')
jsonString = jFile.read()
jFile.close()
return json.loads(jsonString)
class FileManager: class FileManager:
not_dir = ['.zip','.xsp','.rar'] not_dir = ['.zip','.xsp','.rar']
exclude_dir = [] exclude_dir = []
@ -587,38 +521,46 @@ class FileManager:
self.vfs = vfs self.vfs = vfs
self.fileArray = [] self.fileArray = []
def walkTree(self,directory): def walkTree(self,directory,recurse=True):
if(directory[-1:] == '/'): if(directory[-1:] == '/' or directory[-1:] == '\\'):
directory = directory[:-1] directory = directory[:-1]
if(self.vfs.exists(directory + "/")): if(self.vfs.exists(directory + "/")):
dirs,files = self.vfs.listdir(directory) dirs,files = self.vfs.listdir(directory)
#create all the subdirs first
for aDir in dirs:
dirPath = xbmc.validatePath(xbmc.translatePath(directory + "/" + aDir))
file_ext = aDir.split('.')[-1]
if(not dirPath in self.exclude_dir): if(recurse):
#create all the subdirs first
for aDir in dirs:
dirPath = xbmc.validatePath(xbmc.translatePath(directory + "/" + aDir))
file_ext = aDir.split('.')[-1]
if(not dirPath in self.exclude_dir):
self.addFile("-" + dirPath) self.addFile("-" + dirPath)
#catch for "non directory" type files #catch for "non directory" type files
shouldWalk = True shouldWalk = True
for s in file_ext: for s in file_ext:
if(s in self.not_dir): if(s in self.not_dir):
shouldWalk = False shouldWalk = False
if(shouldWalk): if(shouldWalk):
self.walkTree(dirPath) self.walkTree(dirPath)
#copy all the files #copy all the files
for aFile in files: for aFile in files:
filePath = xbmc.translatePath(directory + "/" + aFile) filePath = xbmc.translatePath(directory + "/" + aFile)
self.addFile(filePath) self.addFile(filePath)
def addDir(self,dirMeta):
if(dirMeta['type'] == 'include'):
self.addFile('-' + xbmc.translatePath(dirMeta['path']))
self.walkTree(xbmc.translatePath(dirMeta['path']),dirMeta['recurse'])
else:
self.excludeFile('-' + xbmc.translatePath(dirMeta['path']))
def addFile(self,filename): def addFile(self,filename):
try: try:
filename = filename.decode('UTF-8') filename = filename.decode('UTF-8')

View File

@ -18,17 +18,14 @@
<setting id="remove_auth_button" type="action" label="30093" action="RunScript(special://home/addons/script.xbmcbackup/remove_auth.py)" visible="gt(-9,1)"/> <setting id="remove_auth_button" type="action" label="30093" action="RunScript(special://home/addons/script.xbmcbackup/remove_auth.py)" visible="gt(-9,1)"/>
</category> </category>
<category id="selection" label="30012"> <category id="selection" label="30012">
<setting id="backup_addons" type="bool" label="30030" default="true" /> <setting id="backup_selection_type" type="enum" lvalues="Simple|Advanced" default="0" label="File Selection Type" />
<setting id="backup_addon_data" type="bool" label="30031" default="false" /> <setting id="backup_addons" type="bool" label="30030" default="true" visible="eq(-1,0)" />
<setting id="backup_database" type="bool" label="30032" default="true" /> <setting id="backup_addon_data" type="bool" label="30031" default="false" visible="eq(-2,0)"/>
<setting id="backup_playlists" type="bool" label="30033" default="true" /> <setting id="backup_database" type="bool" label="30032" default="true" visible="eq(-3,0)"/>
<setting id="backup_profiles" type="bool" label="30080" default="false" /> <setting id="backup_playlists" type="bool" label="30033" default="true" visible="eq(-4,0)"/>
<setting id="backup_thumbnails" type="bool" label="30034" default="true" /> <setting id="backup_profiles" type="bool" label="30080" default="false" visible="eq(-5,0)"/>
<setting id="backup_config" type="bool" label="30035" default="true" /> <setting id="backup_thumbnails" type="bool" label="30034" default="true" visible="eq(-6,0)"/>
<setting id="custom_dir_1_enable" type="bool" label="30036" default="false" /> <setting id="backup_config" type="bool" label="30035" default="true" visible="eq(-7,0)"/>
<setting id="backup_custom_dir_1" type="folder" label="30018" default="" visible="eq(-1,true)"/>
<setting id="custom_dir_2_enable" type="bool" label="30037" default="false" />
<setting id="backup_custom_dir_2" type="folder" label="30018" default="" visible="eq(-1,true)"/>
</category> </category>
<category id="scheduling" label="30013"> <category id="scheduling" label="30013">
<setting id="enable_scheduler" type="bool" label="30060" default="false" /> <setting id="enable_scheduler" type="bool" label="30060" default="false" />