Example #1
0
    def _from_etree(cls, el: ElementTree, base_href: str) -> LessonSection:
        title_el = el.find('./h2')
        if title_el is None or not title_el.text:
            raise LessonParseError(
                'Lesson <section> needs a non-empty <h2> title')
        title = title_el.text

        steps_el = el.find('./ol[@class="steps"]')
        if steps_el is None or not steps_el:
            steps = list()
        else:
            steps = [
                LessonSectionStep._from_etree(el, base_href) for el in steps_el
            ]

        # Now get the rest of the HTML, minus the <h1> and <ol>
        el.remove(title_el)  # hacky mutation
        if steps_el is not None:
            el.remove(steps_el)  # hacky mutation
        html = _build_inner_html(el, base_href)

        # Look for "fullscreen" class on section, set fullscreen flag if so
        is_full_screen = el.find('[@class="fullscreen"]') is not None

        return cls(title, html, steps, is_full_screen)
 def newSubChapterTitle(self, parent_tag, tag, title):
     if tag in self.report_elements:
         ET.remove(self.report_elements[tag])
         #del self.report_elements[tag] # will be overwritten anyway
     
     div =  ET.SubElement(self.report_elements[parent_tag], "div" )
     h3 =   ET.SubElement(div, "h3" )
     h3.text = title
     
     self.report_elements[tag] = div
     self.textAdded.emit()
    def newSubChapterTitle(self, parent_tag, tag, title):
        if tag in self.report_elements:
            ET.remove(self.report_elements[tag])
            #del self.report_elements[tag] # will be overwritten anyway

        div = ET.SubElement(self.report_elements[parent_tag], "div")
        h3 = ET.SubElement(div, "h3")
        h3.text = title

        self.report_elements[tag] = div
        self.textAdded.emit()
Example #4
0
    def _from_etree(cls, el: ElementTree, base_href: str) -> LessonHeader:
        title_el = el.find('./h1')
        if title_el is None or not title_el.text:
            raise LessonParseError(
                'Lesson <header> needs a non-empty <h1> title')
        title = title_el.text

        # Now get the rest of the HTML, minus the <h1>
        el.remove(title_el)  # hacky mutation
        html = _build_inner_html(el, base_href)

        return cls(title, html)
Example #5
0
    def _from_etree(cls, el: ElementTree, base_href: str) -> LessonFooter:
        title_el = el.find('./h2')
        if title_el is None or not title_el.text:
            raise LessonParseError(
                'Lesson <footer> needs a non-empty <h2> title')
        title = title_el.text
        is_full_screen = el.find('[@class="fullscreen"]') is not None

        # Now get the rest of the HTML, minus the <h2>
        el.remove(title_el)  # hacky mutation
        html = _build_inner_html(el, base_href)

        return cls(title, html, is_full_screen)
 def newReportTitle(self, parent_tag, tag, title, authors, date):
     if tag in self.report_elements:
         ET.remove(self.report_elements[tag])
         #del self.report_elements[tag] # will be overwritten anyway
         
     div =  ET.SubElement(self.report_elements[parent_tag], "div" )
     h1 =   ET.SubElement(div, "h1" )
     h1.text = title
     
     par_date =  ET.SubElement(div, "p" )
     par_date.text = "Creation date:  " + date
     par_authors = ET.SubElement(div, "p" )
     par_authors.text = "Experimenter:  " + authors 
     
     self.report_elements[tag] = h1
     self.textAdded.emit()
    def newReportTitle(self, parent_tag, tag, title, authors, date):
        if tag in self.report_elements:
            ET.remove(self.report_elements[tag])
            #del self.report_elements[tag] # will be overwritten anyway

        div = ET.SubElement(self.report_elements[parent_tag], "div")
        h1 = ET.SubElement(div, "h1")
        h1.text = title

        par_date = ET.SubElement(div, "p")
        par_date.text = "Creation date:  " + date
        par_authors = ET.SubElement(div, "p")
        par_authors.text = "Experimenter:  " + authors

        self.report_elements[tag] = h1
        self.textAdded.emit()
class ConfigXmlWriter(RcbXmlReaderWriter):

	def __init__(self, createNew):

		Logutil.log('init ConfigXmlWriter', util.LOG_LEVEL_INFO)

		self.createNew = createNew

		if(createNew):
			configFile = os.path.join(util.getAddonInstallPath(), 'resources', 'database', 'config_template.xml')
		else:
			configFile = util.getConfigXmlPath()

		if(not os.path.isfile(configFile)):
			Logutil.log('File config.xml does not exist. Place a valid config file here: ' + str(configFile), util.LOG_LEVEL_ERROR)
		else:
			self.tree = ElementTree().parse(configFile)

	""" Functions for generating XML objects from objects """
	def getXmlAttributesForRomCollection(self, rc):
		return {'id': str(rc.id), 'name': rc.name}

	def getXmlElementsForRomCollection(self, rc):
		elements = []
		# String attributes
		for e in ['gameclient', 'emulatorCmd', 'emulatorParams', 'preCmd', 'postCmd',
				  'saveStatePath', 'saveStateParams']:
			try:
				el = Element(e, {})
				el.text = getattr(rc, e)
				elements.append(el)
			except AttributeError as exc:
				# Skip any errors
				pass

		# Non-string attributes
		for e in ['useBuiltinEmulator', 'useEmuSolo', 'usePopen', 'ignoreOnScan', 'allowUpdate', 'autoplayVideoMain',
				  'autoplayVideoInfo', 'useFoldernameAsGamename', 'maxFolderDepth', 'doNotExtractZipFiles',
				  'makeLocalCopy', 'diskPrefix']:
			try:
				el = Element(e, {})
				el.text = str(getattr(rc, e))
				elements.append(el)
			except AttributeError as exc:
				# Skip any errors
				pass

		for romPath in rc.romPaths:
			el = Element('romPath', {})
			el.text = romPath
			elements.append(el)

		return elements

	def getXmlAttributesForSite(self, site):
		attrs = {'name': site.name, 'path': site.path}
		return attrs

	def getXmlElementsForSite(self, site):
		""" Not needed """
		pass

	def writeRomCollections(self, romCollections, isEdit):

		Logutil.log('write Rom Collections', util.LOG_LEVEL_INFO)

		romCollectionsXml = self.tree.find('RomCollections')

		#HACK: remove all Rom Collections and create new
		if(isEdit):
			for romCollectionXml in romCollectionsXml.findall('RomCollection'):
				romCollectionsXml.remove(romCollectionXml)


		for romCollection in romCollections.values():

			Logutil.log('write Rom Collection: ' + str(romCollection.name), util.LOG_LEVEL_INFO)

			romCollectionXml = SubElement(romCollectionsXml, 'RomCollection', self.getXmlAttributesForRomCollection(romCollection))

			for subel in self.getXmlElementsForRomCollection(romCollection):
				romCollectionXml.append(subel)


			for mediaPath in romCollection.mediaPaths:

				success, message = self.searchConfigObjects('FileTypes/FileType', mediaPath.fileType.name, 'FileType')
				if(not success):
					return False, message

				SubElement(romCollectionXml, 'mediaPath', {'type': mediaPath.fileType.name}).text = mediaPath.path

			#image placing
			if(not self.createNew):
				#in case of an update we have to create new options
				if(romCollection.name == 'MAME' and not self.createNew):
					self.addFileTypesForMame()
					self.addImagePlacingForMame()

			if(romCollection.imagePlacingMain != None and romCollection.imagePlacingMain.name != ''):
				success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor', romCollection.imagePlacingMain.name, 'ImagePlacing')
				if(not success):
					return False, message
				SubElement(romCollectionXml, 'imagePlacingMain').text = romCollection.imagePlacingMain.name
			else:
				SubElement(romCollectionXml, 'imagePlacingMain').text = 'gameinfobig'

			if(romCollection.imagePlacingInfo != None and romCollection.imagePlacingInfo.name != ''):
				success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor', romCollection.imagePlacingInfo.name, 'ImagePlacing')
				if(not success):
					return False, message
				SubElement(romCollectionXml, 'imagePlacingInfo').text = romCollection.imagePlacingInfo.name
			else:
				SubElement(romCollectionXml, 'imagePlacingInfo').text = 'gameinfosmall'

			if (romCollection.scraperSites == None or len(romCollection.scraperSites) == 0):
				#use thegamesdb.net as default scraper in online scraping scenario
				SubElement(romCollectionXml, 'scraper', {'name': 'thegamesdb.net'})
			else:
				for scraperSite in romCollection.scraperSites:
					if(scraperSite == None):
						continue
					SubElement(romCollectionXml, 'scraper', {'name' : scraperSite.name, 'path' : scraperSite.path})

		success, message = self.writeFile()
		return success, message


	def writeMissingFilter(self, showHideOption, artworkOrGroup, artworkAndGroup, infoOrGroup, infoAndGroup):

		Logutil.log('write Missing Info Filter', util.LOG_LEVEL_INFO)

		missingFilterXml = self.tree.find('MissingFilter')

		#HACK: remove MissingFilter-element
		if(missingFilterXml != None):
			self.tree.remove(missingFilterXml)

		missingFilterXml = SubElement(self.tree, 'MissingFilter')
		SubElement(missingFilterXml, 'showHideOption').text = showHideOption

		if(len(artworkOrGroup) > 0 or len(artworkAndGroup) > 0):
			missingArtworkXml = SubElement(missingFilterXml, 'missingArtworkFilter')
			self.addMissingFilterItems(missingArtworkXml, artworkOrGroup, 'orGroup')
			self.addMissingFilterItems(missingArtworkXml, artworkAndGroup, 'andGroup')
		if(len(infoOrGroup) > 0 or len(infoAndGroup) > 0):
			missingInfoXml = SubElement(missingFilterXml, 'missingInfoFilter')
			self.addMissingFilterItems(missingInfoXml, infoOrGroup, 'orGroup')
			self.addMissingFilterItems(missingInfoXml, infoAndGroup, 'andGroup')

		success, message = self.writeFile()
		return success, message


	def addMissingFilterItems(self, missingXml, group, groupName):
		if(len(group) > 0):
			groupXml = SubElement(missingXml, groupName)
			for item in group:
				SubElement(groupXml, 'item').text = item


	def searchConfigObjects(self, xPath, nameToCompare, objectType):
		objects = self.tree.findall(xPath)
		objectFound = False
		for obj in objects:
			objectName = obj.attrib.get('name')
			if(objectName == nameToCompare):
				objectFound = True
				break

		if(not objectFound):
			return False, util.localize(32009) % (objectType, nameToCompare)

		return True, ''


	def removeRomCollection(self, RCName):

		Logutil.log('removeRomCollection', util.LOG_LEVEL_INFO)

		configFile = util.getConfigXmlPath()
		self.tree = ElementTree().parse(configFile)
		romCollectionsXml = self.tree.find('RomCollections')
		for romCollectionXml in romCollectionsXml.findall('RomCollection'):
			name = romCollectionXml.attrib.get('name')
			if(name == RCName):
				romCollectionsXml.remove(romCollectionXml)

		success, message = self.writeFile()
		return success, message

	def addFileTypesForMame(self):
		Logutil.log('addFileTypesForMame', util.LOG_LEVEL_INFO)

		fileTypesXml = self.tree.find('FileTypes')

		#check if the MAME FileTypes already exist
		cabinetExists = False
		marqueeExists = False
		actionExists = False
		titleExists = False
		highestId = 0
		fileTypeXml = fileTypesXml.findall('FileType')
		for fileType in fileTypeXml:
			name = fileType.attrib.get('name')
			if name == 'cabinet':
				cabinetExists = True
			elif name == 'marquee':
				marqueeExists = True
			elif name == 'action':
				actionExists = True
			elif name == 'title':
				titleExists = True

			id = fileType.attrib.get('id')
			if int(id) > highestId:
				highestId = int(id)

		if not cabinetExists:
			self.createFileType(fileTypesXml, str(highestId + 1), 'cabinet', 'image', 'game')
		if not marqueeExists:
			self.createFileType(fileTypesXml, str(highestId + 2), 'marquee', 'image', 'game')
		if not actionExists:
			self.createFileType(fileTypesXml, str(highestId + 3), 'action', 'image', 'game')
		if not titleExists:
			self.createFileType(fileTypesXml, str(highestId + 4), 'title', 'image', 'game')


	def createFileType(self, fileTypesXml, id, name, type, parent):
		fileType = SubElement(fileTypesXml, 'FileType', {'id' : str(id), 'name' : name})
		SubElement(fileType, 'type').text = type
		SubElement(fileType, 'parent').text = parent


	def addImagePlacingForMame(self):
		Logutil.log('addImagePlacingForMame', util.LOG_LEVEL_INFO)

		imagePlacingXml = self.tree.find('ImagePlacing')

		#check if the MAME ImagePlacing options already exist
		cabinetExists = False
		marqueeExists = False
		fileTypeForXml = imagePlacingXml.findall('fileTypeFor')
		for fileTypeFor in fileTypeForXml:
			name = fileTypeFor.attrib.get('name')
			if name == 'gameinfomamecabinet':
				cabinetExists = True
			elif name == 'gameinfomamemarquee':
				marqueeExists = True

		if not cabinetExists:
			fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name' : 'gameinfomamecabinet'})
			for imgtype in ['cabinet', 'boxfront', 'title']:
				SubElement(fileTypeFor, 'fileTypeForGameList').text = imgtype
				SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = imgtype

			for imgtype in ['boxfront', 'title', 'action']:
				SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = imgtype

			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperLeft').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLower').text = 'marquee'

		if not marqueeExists:
			fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name' : 'gameinfomamemarquee'})
			for imgtype in ['marquee', 'boxfront', 'title']:
				SubElement(fileTypeFor, 'fileTypeForGameList').text = imgtype
				SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = imgtype

			for imgtype in ['boxfront', 'title', 'action']:
				SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = imgtype

			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLeft').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLowerRight').text = 'title'

	# FIXME TODO This function is only called within this class - raise exception rather than return tuple
	def writeFile(self):
		Logutil.log('writeFile', util.LOG_LEVEL_INFO)
		#write file
		try:
			configFile = util.getConfigXmlPath()

			self.indentXml(self.tree)
			treeToWrite = ElementTree(self.tree)
			treeToWrite.write(configFile)

			return True, ""

		except Exception, (exc):
			print("Error: Cannot write config.xml: " + str(exc))
			return False, util.localize(32008) + ": " + str(exc)
class ConfigXmlWriter:
	
	def __init__(self, createNew):
		
		Logutil.log('init ConfigXmlWriter', util.LOG_LEVEL_INFO)
		
		self.createNew = createNew
		
		if(createNew):
			configFile = os.path.join(util.getAddonInstallPath(), 'resources', 'database', 'config_template.xml')
		else:
			configFile = util.getConfigXmlPath()
		
		if(not os.path.isfile(configFile)):
			Logutil.log('File config.xml does not exist. Place a valid config file here: ' +str(configFile), util.LOG_LEVEL_ERROR)
			return False, util.localize(32003)
		
		self.tree = ElementTree().parse(configFile)
	
	
	def writeRomCollections(self, romCollections, isEdit):
				
		Logutil.log('write Rom Collections', util.LOG_LEVEL_INFO)
				
		romCollectionsXml = self.tree.find('RomCollections')
		
		#HACK: remove all Rom Collections and create new
		if(isEdit):
			for romCollectionXml in romCollectionsXml.findall('RomCollection'):				
				romCollectionsXml.remove(romCollectionXml)
				
		
		for romCollection in romCollections.values():
			
			Logutil.log('write Rom Collection: ' +str(romCollection.name), util.LOG_LEVEL_INFO)
			
			romCollectionXml = SubElement(romCollectionsXml, 'RomCollection', {'id' : str(romCollection.id), 'name' : romCollection.name})
			SubElement(romCollectionXml, 'useBuiltinEmulator').text = str(romCollection.useBuiltinEmulator)
			SubElement(romCollectionXml, 'gameclient').text = romCollection.gameclient
			SubElement(romCollectionXml, 'emulatorCmd').text = romCollection.emulatorCmd
			SubElement(romCollectionXml, 'emulatorParams').text = romCollection.emulatorParams
			
			for romPath in romCollection.romPaths:
				SubElement(romCollectionXml, 'romPath').text = romPath
							
			SubElement(romCollectionXml, 'saveStatePath').text = romCollection.saveStatePath
			SubElement(romCollectionXml, 'saveStateParams').text = romCollection.saveStateParams
				
			for mediaPath in romCollection.mediaPaths:
				
				success, message = self.searchConfigObjects('FileTypes/FileType', mediaPath.fileType.name, 'FileType')
				if(not success):
					return False, message								
												
				SubElement(romCollectionXml, 'mediaPath', {'type' : mediaPath.fileType.name}).text = mediaPath.path
				
			SubElement(romCollectionXml, 'preCmd').text = romCollection.preCmd
			SubElement(romCollectionXml, 'postCmd').text = romCollection.postCmd
			SubElement(romCollectionXml, 'useEmuSolo').text = str(romCollection.useEmuSolo)
			SubElement(romCollectionXml, 'usePopen').text = str(romCollection.usePopen)
			SubElement(romCollectionXml, 'ignoreOnScan').text = str(romCollection.ignoreOnScan)
			SubElement(romCollectionXml, 'allowUpdate').text = str(romCollection.allowUpdate)
			SubElement(romCollectionXml, 'autoplayVideoMain').text = str(romCollection.autoplayVideoMain)
			SubElement(romCollectionXml, 'autoplayVideoInfo').text = str(romCollection.autoplayVideoInfo)
			SubElement(romCollectionXml, 'useFoldernameAsGamename').text = str(romCollection.useFoldernameAsGamename)
			SubElement(romCollectionXml, 'maxFolderDepth').text = str(romCollection.maxFolderDepth)
			SubElement(romCollectionXml, 'doNotExtractZipFiles').text = str(romCollection.doNotExtractZipFiles)
			SubElement(romCollectionXml, 'diskPrefix').text = str(romCollection.diskPrefix)
			
			if (os.environ.get( "OS", "xbox" ) == "xbox"):
				SubElement(romCollectionXml, 'xboxCreateShortcut').text = str(romCollection.xboxCreateShortcut)
				SubElement(romCollectionXml, 'xboxCreateShortcutAddRomfile').text = str(romCollection.xboxCreateShortcutAddRomfile)
				SubElement(romCollectionXml, 'xboxCreateShortcutUseShortGamename').text = str(romCollection.xboxCreateShortcutUseShortGamename)
				
			#image placing
			if(not self.createNew):
				#in case of an update we have to create new options
				if(romCollection.name == 'MAME' and not self.createNew):
					self.addFileTypesForMame()
					self.addImagePlacingForMame()
					
			if(romCollection.imagePlacingMain != None and romCollection.imagePlacingMain.name != ''):
				success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor', romCollection.imagePlacingMain.name, 'ImagePlacing')
				if(not success):
					return False, message
				SubElement(romCollectionXml, 'imagePlacingMain').text = romCollection.imagePlacingMain.name 
			else:
				SubElement(romCollectionXml, 'imagePlacingMain').text = 'gameinfobig'
				
			if(romCollection.imagePlacingInfo != None and romCollection.imagePlacingInfo.name != ''):
				success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor', romCollection.imagePlacingInfo.name, 'ImagePlacing')
				if(not success):
					return False, message
				SubElement(romCollectionXml, 'imagePlacingInfo').text = romCollection.imagePlacingInfo.name 
			else:
				SubElement(romCollectionXml, 'imagePlacingInfo').text = 'gameinfosmall'
			
			if(romCollection.scraperSites == None or len(romCollection.scraperSites) == 0):
				SubElement(romCollectionXml, 'scraper', {'name' : 'thegamesdb.net', 'replaceKeyString' : '', 'replaceValueString' : ''})
				SubElement(romCollectionXml, 'scraper', {'name' : 'archive.vg', 'replaceKeyString' : '', 'replaceValueString' : ''})
				SubElement(romCollectionXml, 'scraper', {'name' : 'mobygames.com', 'replaceKeyString' : '', 'replaceValueString' : ''})
			else:
				for scraperSite in romCollection.scraperSites:
				
					if(scraperSite == None):
						continue
						
					#HACK: use replaceKey and -Value only from first scraper
					firstScraper = scraperSite.scrapers[0]
					SubElement(romCollectionXml, 'scraper', {'name' : scraperSite.name, 'replaceKeyString' : firstScraper.replaceKeyString, 'replaceValueString' : firstScraper.replaceValueString})
					
					#create Scraper element
					scrapersXml = self.tree.find('Scrapers')
					
					#check if the current scraper already exists
					siteExists = False
					sitesXml = scrapersXml.findall('Site')
					for site in sitesXml:
						name = site.attrib.get('name')
						if name == scraperSite.name:
							siteExists = True
							break
						
					if not siteExists:
						#HACK: this only covers the first scraper (for offline scrapers)
						site = SubElement(scrapersXml, 'Site', 
							{ 
							'name' : scraperSite.name,
							'descFilePerGame' : str(scraperSite.descFilePerGame),
							'searchGameByCRC' : str(scraperSite.searchGameByCRC),
							'useFoldernameAsCRC' : str(scraperSite.useFoldernameAsCRC),
							'useFilenameAsCRC' : str(scraperSite.useFilenameAsCRC)
							})
																		
						scraper = scraperSite.scrapers[0]
						
						SubElement(site, 'Scraper', 
							{ 
							'parseInstruction' : scraper.parseInstruction,
							'source' : scraper.source,
							'encoding' : scraper.encoding
							})
				
		success, message = self.writeFile()
		return success, message
	
	
	def writeScrapers(self, scrapers):
		
		Logutil.log('write scraper sites', util.LOG_LEVEL_INFO)
				
		scraperSitesXml = self.tree.find('Scrapers')
				
		#HACK: remove all scrapers and create new
		for scraperSiteXml in scraperSitesXml.findall('Site'):				
			scraperSitesXml.remove(scraperSiteXml)
			
		for scraperSite in scrapers.values():
			
			Logutil.log('write scraper site: ' +str(scraperSite.name), util.LOG_LEVEL_INFO)
			
			#Don't write None-Scraper
			if(scraperSite.name == util.localize(32854)):
				Logutil.log('None scraper will be skipped', util.LOG_LEVEL_INFO)
				continue
			
			scraperSiteXml = SubElement(scraperSitesXml, 'Site', 
					{ 
					'name' : scraperSite.name,
					'descFilePerGame' : str(scraperSite.descFilePerGame),
					'searchGameByCRC' : str(scraperSite.searchGameByCRC),
					'useFoldernameAsCRC' : str(scraperSite.useFoldernameAsCRC),
					'useFilenameAsCRC' : str(scraperSite.useFilenameAsCRC)
					})
			
			for scraper in scraperSite.scrapers:
				
				#check if we can use a relative path to parseInstructions
				rcbScraperPath = os.path.join(util.RCBHOME, 'resources', 'scraper')
				pathParts = os.path.split(scraper.parseInstruction)
				if(pathParts[0].upper() == rcbScraperPath.upper()):
					scraper.parseInstruction = pathParts[1]
				
				scraperXml = SubElement(scraperSiteXml, 'Scraper', 
					{ 
					'parseInstruction' : scraper.parseInstruction,
					'source' : scraper.source,
					'encoding' : scraper.encoding,
					'returnUrl' : str(scraper.returnUrl)
					})
		
		success, message = self.writeFile()
		return success, message
	
	
	def writeMissingFilter(self, showHideOption, artworkOrGroup, artworkAndGroup, infoOrGroup, infoAndGroup):
		
		Logutil.log('write Missing Info Filter', util.LOG_LEVEL_INFO)
		
		missingFilterXml = self.tree.find('MissingFilter')
		
		#HACK: remove MissingFilter-element
		if(missingFilterXml != None):				
			self.tree.remove(missingFilterXml)
		
		missingFilterXml = SubElement(self.tree, 'MissingFilter')
		SubElement(missingFilterXml, 'showHideOption').text = showHideOption
		
		if(len(artworkOrGroup) > 0 or len(artworkAndGroup) > 0):
			missingArtworkXml = SubElement(missingFilterXml, 'missingArtworkFilter')
			self.addMissingFilterItems(missingArtworkXml, artworkOrGroup, 'orGroup')
			self.addMissingFilterItems(missingArtworkXml, artworkAndGroup, 'andGroup')
		if(len(infoOrGroup) > 0 or len(infoAndGroup) > 0):
			missingInfoXml = SubElement(missingFilterXml, 'missingInfoFilter')
			self.addMissingFilterItems(missingInfoXml, infoOrGroup, 'orGroup')
			self.addMissingFilterItems(missingInfoXml, infoAndGroup, 'andGroup')
				
		success, message = self.writeFile()
		return success, message
		
		
	def addMissingFilterItems(self, missingXml, group, groupName):		
		if(len(group) > 0):
			groupXml = SubElement(missingXml, groupName)
			for item in group:
				SubElement(groupXml, 'item').text = item
		
	
	def searchConfigObjects(self, xPath, nameToCompare, objectType):		
		objects = self.tree.findall(xPath)
		objectFound = False
		for obj in objects:
			objectName = obj.attrib.get('name')
			if(objectName == nameToCompare):
				objectFound = True
				break
		
		if(not objectFound):
			return False,  util.localize(32009) %(objectType, nameToCompare)
		
		return True, ''
	
		
	def removeRomCollection(self, RCName):
		
		Logutil.log('removeRomCollection', util.LOG_LEVEL_INFO)
		
		configFile = util.getConfigXmlPath()
		self.tree = ElementTree().parse(configFile)
		romCollectionsXml = self.tree.find('RomCollections')
		for romCollectionXml in romCollectionsXml.findall('RomCollection'):
			name = romCollectionXml.attrib.get('name')
			if(name == RCName):
				romCollectionsXml.remove(romCollectionXml)	
				
		success, message = self.writeFile()
		return success, message
		
	def addFileTypesForMame(self):
		Logutil.log('addFileTypesForMame', util.LOG_LEVEL_INFO)
		
		fileTypesXml = self.tree.find('FileTypes')
				
		#check if the MAME FileTypes already exist
		cabinetExists = False
		marqueeExists = False
		actionExists = False
		titleExists = False
		highestId = 0
		fileTypeXml = fileTypesXml.findall('FileType')
		for fileType in fileTypeXml:
			name = fileType.attrib.get('name')
			if name == 'cabinet':
				cabinetExists = True
			elif name == 'marquee':
				marqueeExists = True
			elif name == 'action':
				actionExists = True
			elif name == 'title':
				titleExists = True
			
			id = fileType.attrib.get('id')
			if int(id) > highestId:
				highestId = int(id)
		
		if not cabinetExists:
			self.createFileType(fileTypesXml, str(highestId +1), 'cabinet', 'image', 'game')
		if not marqueeExists:
			self.createFileType(fileTypesXml, str(highestId +2), 'marquee', 'image', 'game')			
		if not actionExists:
			self.createFileType(fileTypesXml, str(highestId +3), 'action', 'image', 'game')
		if not titleExists:
			self.createFileType(fileTypesXml, str(highestId +4), 'title', 'image', 'game')			
			
		
	def createFileType(self, fileTypesXml, id, name, type, parent):
		fileType = SubElement(fileTypesXml, 'FileType', {'id' : str(id), 'name' : name})
		SubElement(fileType, 'type').text = type
		SubElement(fileType, 'parent').text = parent
		
		
	def addImagePlacingForMame(self):
		Logutil.log('addImagePlacingForMame', util.LOG_LEVEL_INFO)
		
		imagePlacingXml = self.tree.find('ImagePlacing')
		
		#check if the MAME ImagePlacing options already exist
		cabinetExists = False
		marqueeExists = False		
		fileTypeForXml = imagePlacingXml.findall('fileTypeFor')
		for fileTypeFor in fileTypeForXml:
			name = fileTypeFor.attrib.get('name')
			if name == 'gameinfomamecabinet':
				cabinetExists = True
			elif name == 'gameinfomamemarquee':
				marqueeExists = True
				
		if not cabinetExists:
			fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name' : 'gameinfomamecabinet'})
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'title'			
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperLeft').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLower').text = 'marquee'
			
		if not marqueeExists:
			fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name' : 'gameinfomamemarquee'})
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'marquee'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'marquee'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'title'			
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLeft').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLowerRight').text = 'title'
		
						
	def writeFile(self):
		Logutil.log('writeFile', util.LOG_LEVEL_INFO)
		#write file
		try:
			configFile = util.getConfigXmlPath()
			
			util.indentXml(self.tree)
			treeToWrite = ElementTree(self.tree)			
			treeToWrite.write(configFile)
			
			return True, ""
			
		except Exception, (exc):
			print("Error: Cannot write config.xml: " +str(exc))
			return False, util.localize(32008) +": " +str(exc)
Example #10
0
class ConfigXmlWriter(RcbXmlReaderWriter):

    def __init__(self, createNew):

        Logutil.log('init ConfigXmlWriter', util.LOG_LEVEL_INFO)

        self.createNew = createNew

        if createNew:
            configFile = os.path.join(util.getAddonInstallPath(), 'resources', 'database', 'config_template.xml')
        else:
            configFile = util.getConfigXmlPath()

        if not os.path.isfile(configFile):
            Logutil.log('File config.xml does not exist. Place a valid config file here: ' + str(configFile),
                        util.LOG_LEVEL_ERROR)
        else:
            self.tree = ElementTree().parse(configFile)

    #Functions for generating XML objects from objects

    def getXmlAttributesForRomCollection(self, rc):
        return {'id': str(rc.id), 'name': rc.name}

    def getXmlElementsForRomCollection(self, rc):
        elements = []
        # String attributes
        for e in ['gameclient', 'emulatorCmd', 'emulatorParams', 'preCmd', 'postCmd',
                  'saveStatePath', 'saveStateParams']:
            try:
                el = Element(e, {})
                el.text = getattr(rc, e)
                elements.append(el)
            except AttributeError:
                # Skip any errors
                pass

        # Non-string attributes
        for e in ['useBuiltinEmulator', 'useEmuSolo', 'usePopen', 'ignoreOnScan', 'allowUpdate', 'autoplayVideoMain',
                  'autoplayVideoInfo', 'useFoldernameAsGamename', 'maxFolderDepth', 'doNotExtractZipFiles',
                  'makeLocalCopy', 'diskPrefix']:
            try:
                el = Element(e, {})
                el.text = str(getattr(rc, e))
                elements.append(el)
            except AttributeError:
                # Skip any errors
                pass

        for romPath in rc.romPaths:
            el = Element('romPath', {})
            el.text = romPath
            elements.append(el)

        return elements

    def getXmlAttributesForSite(self, site):
        attrs = {'name': site.name, 'path': site.path}
        return attrs

    def getXmlElementsForSite(self, site):
        """ Not needed """
        pass

    def writeRomCollections(self, romCollections, isEdit):

        Logutil.log('write Rom Collections', util.LOG_LEVEL_INFO)

        romCollectionsXml = self.tree.find('RomCollections')

        #HACK: remove all Rom Collections and create new
        if isEdit:
            for romCollectionXml in romCollectionsXml.findall('RomCollection'):
                romCollectionsXml.remove(romCollectionXml)

        for romCollection in list(romCollections.values()):

            Logutil.log('write Rom Collection: ' + str(romCollection.name), util.LOG_LEVEL_INFO)

            romCollectionXml = SubElement(romCollectionsXml, 'RomCollection',
                                          self.getXmlAttributesForRomCollection(romCollection))

            for subel in self.getXmlElementsForRomCollection(romCollection):
                romCollectionXml.append(subel)

            for mediaPath in romCollection.mediaPaths:

                success, message = self.searchConfigObjects('FileTypes/FileType', mediaPath.fileType.name, 'FileType')
                if not success:
                    return False, message

                SubElement(romCollectionXml, 'mediaPath', {'type': mediaPath.fileType.name}).text = mediaPath.path

            #image placing
            if not self.createNew:
                #in case of an update we have to create new options
                if romCollection.name == 'MAME' and not self.createNew:
                    self.addFileTypesForMame()
                    self.addImagePlacingForMame()

            if romCollection.imagePlacingMain != None and romCollection.imagePlacingMain.name != '':
                success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor',
                                                            romCollection.imagePlacingMain.name, 'ImagePlacing')
                if not success:
                    return False, message
                SubElement(romCollectionXml, 'imagePlacingMain').text = romCollection.imagePlacingMain.name
            else:
                SubElement(romCollectionXml, 'imagePlacingMain').text = 'gameinfobig'

            if romCollection.imagePlacingInfo != None and romCollection.imagePlacingInfo.name != '':
                success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor',
                                                            romCollection.imagePlacingInfo.name, 'ImagePlacing')
                if not success:
                    return False, message
                SubElement(romCollectionXml, 'imagePlacingInfo').text = romCollection.imagePlacingInfo.name
            else:
                SubElement(romCollectionXml, 'imagePlacingInfo').text = 'gameinfosmall'

            if romCollection.scraperSites == None or len(romCollection.scraperSites) == 0:
                #use thegamesdb.net as default scraper in online scraping scenario
                SubElement(romCollectionXml, 'scraper', {'name': 'thegamesdb.net', 'default': 'True'})
            else:
                for scraperSite in romCollection.scraperSites:
                    if scraperSite == None:
                        continue
                    attributes = {'name': scraperSite.name}
                    if scraperSite.path:
                        attributes['path'] = scraperSite.path
                    if scraperSite.default:
                        attributes['default'] = str(scraperSite.default)

                    SubElement(romCollectionXml, 'scraper', attributes)

        success, message = self.writeFile()
        return success, message

    def writeMissingFilter(self, showHideOption, artworkOrGroup, artworkAndGroup, infoOrGroup, infoAndGroup):

        Logutil.log('write Missing Info Filter', util.LOG_LEVEL_INFO)

        missingFilterXml = self.tree.find('MissingFilter')

        #HACK: remove MissingFilter-element
        if missingFilterXml != None:
            self.tree.remove(missingFilterXml)

        missingFilterXml = SubElement(self.tree, 'MissingFilter')
        SubElement(missingFilterXml, 'showHideOption').text = showHideOption

        if len(artworkOrGroup) > 0 or len(artworkAndGroup) > 0:
            missingArtworkXml = SubElement(missingFilterXml, 'missingArtworkFilter')
            self.addMissingFilterItems(missingArtworkXml, artworkOrGroup, 'orGroup')
            self.addMissingFilterItems(missingArtworkXml, artworkAndGroup, 'andGroup')
        if len(infoOrGroup) > 0 or len(infoAndGroup) > 0:
            missingInfoXml = SubElement(missingFilterXml, 'missingInfoFilter')
            self.addMissingFilterItems(missingInfoXml, infoOrGroup, 'orGroup')
            self.addMissingFilterItems(missingInfoXml, infoAndGroup, 'andGroup')

        success, message = self.writeFile()
        return success, message

    def addMissingFilterItems(self, missingXml, group, groupName):
        if len(group) > 0:
            groupXml = SubElement(missingXml, groupName)
            for item in group:
                SubElement(groupXml, 'item').text = item

    def searchConfigObjects(self, xPath, nameToCompare, objectType):
        objects = self.tree.findall(xPath)
        objectFound = False
        for obj in objects:
            objectName = obj.attrib.get('name')
            if objectName == nameToCompare:
                objectFound = True
                break

        if not objectFound:
            return False, util.localize(32009) % (objectType, nameToCompare)

        return True, ''

    def removeRomCollection(self, RCName):

        Logutil.log('removeRomCollection', util.LOG_LEVEL_INFO)

        configFile = util.getConfigXmlPath()
        self.tree = ElementTree().parse(configFile)
        romCollectionsXml = self.tree.find('RomCollections')
        for romCollectionXml in romCollectionsXml.findall('RomCollection'):
            name = romCollectionXml.attrib.get('name')
            if name == RCName:
                romCollectionsXml.remove(romCollectionXml)

        success, message = self.writeFile()
        return success, message

    def addFileTypesForMame(self):
        Logutil.log('addFileTypesForMame', util.LOG_LEVEL_INFO)

        fileTypesXml = self.tree.find('FileTypes')

        #check if the MAME FileTypes already exist
        cabinetExists = False
        marqueeExists = False
        actionExists = False
        titleExists = False
        highestId = 0
        fileTypeXml = fileTypesXml.findall('FileType')
        for fileType in fileTypeXml:
            name = fileType.attrib.get('name')
            if name == 'cabinet':
                cabinetExists = True
            elif name == 'marquee':
                marqueeExists = True
            elif name == 'action':
                actionExists = True
            elif name == 'title':
                titleExists = True

            ftid = fileType.attrib.get('id')
            if int(ftid) > highestId:
                highestId = int(ftid)

        if not cabinetExists:
            self.createFileType(fileTypesXml, str(highestId + 1), 'cabinet', 'image', 'game')
        if not marqueeExists:
            self.createFileType(fileTypesXml, str(highestId + 2), 'marquee', 'image', 'game')
        if not actionExists:
            self.createFileType(fileTypesXml, str(highestId + 3), 'action', 'image', 'game')
        if not titleExists:
            self.createFileType(fileTypesXml, str(highestId + 4), 'title', 'image', 'game')

    def createFileType(self, fileTypesXml, ftid, name, filetype, parent):
        fileType = SubElement(fileTypesXml, 'FileType', {'id': str(ftid), 'name': name})
        SubElement(fileType, 'type').text = filetype
        SubElement(fileType, 'parent').text = parent

    def addImagePlacingForMame(self):
        Logutil.log('addImagePlacingForMame', util.LOG_LEVEL_INFO)

        imagePlacingXml = self.tree.find('ImagePlacing')

        #check if the MAME ImagePlacing options already exist
        cabinetExists = False
        marqueeExists = False
        fileTypeForXml = imagePlacingXml.findall('fileTypeFor')
        for fileTypeFor in fileTypeForXml:
            name = fileTypeFor.attrib.get('name')
            if name == 'gameinfomamecabinet':
                cabinetExists = True
            elif name == 'gameinfomamemarquee':
                marqueeExists = True

        if not cabinetExists:
            fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name': 'gameinfomamecabinet'})
            for imgtype in ['cabinet', 'boxfront', 'title']:
                SubElement(fileTypeFor, 'fileTypeForGameList').text = imgtype
                SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = imgtype

            for imgtype in ['boxfront', 'title', 'action']:
                SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = imgtype

            SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperLeft').text = 'title'
            SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
            SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLower').text = 'marquee'

        if not marqueeExists:
            fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name': 'gameinfomamemarquee'})
            for imgtype in ['marquee', 'boxfront', 'title']:
                SubElement(fileTypeFor, 'fileTypeForGameList').text = imgtype
                SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = imgtype

            for imgtype in ['boxfront', 'title', 'action']:
                SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = imgtype

            SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLeft').text = 'cabinet'
            SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
            SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLowerRight').text = 'title'

    # FIXME TODO This function is only called within this class - raise exception rather than return tuple
    def writeFile(self):
        Logutil.log('writeFile', util.LOG_LEVEL_INFO)
        #write file
        try:
            configFile = util.getConfigXmlPath()

            self.indentXml(self.tree)
            treeToWrite = ElementTree(self.tree)
            treeToWrite.write(configFile)

            return True, ""

        except Exception as exc:
            print("Error: Cannot write config.xml: " + str(exc))
            return False, util.localize(32008) + ": " + str(exc)
class ConfigXmlWriter:
	
	def __init__(self, createNew):
		
		Logutil.log('init ConfigXmlWriter', util.LOG_LEVEL_INFO)
		
		self.createNew = createNew
		
		if(createNew):
			configFile = os.path.join(util.getAddonInstallPath(), 'resources', 'database', 'config_template.xml')
		else:
			configFile = util.getConfigXmlPath()
		
		if(not os.path.isfile(configFile)):
			Logutil.log('File config.xml does not exist. Place a valid config file here: ' +str(configFile), util.LOG_LEVEL_ERROR)
			return False, util.localize(32003)
		
		self.tree = ElementTree().parse(configFile)
	
	
	def writeRomCollections(self, romCollections, isEdit):
				
		Logutil.log('write Rom Collections', util.LOG_LEVEL_INFO)
				
		romCollectionsXml = self.tree.find('RomCollections')
		
		#HACK: remove all Rom Collections and create new
		if(isEdit):
			for romCollectionXml in romCollectionsXml.findall('RomCollection'):				
				romCollectionsXml.remove(romCollectionXml)
				
		
		for romCollection in romCollections.values():
			
			Logutil.log('write Rom Collection: ' +str(romCollection.name), util.LOG_LEVEL_INFO)
			
			romCollectionXml = SubElement(romCollectionsXml, 'RomCollection', {'id' : str(romCollection.id), 'name' : romCollection.name})
			SubElement(romCollectionXml, 'useBuiltinEmulator').text = str(romCollection.useBuiltinEmulator)
			SubElement(romCollectionXml, 'gameclient').text = romCollection.gameclient
			SubElement(romCollectionXml, 'emulatorCmd').text = romCollection.emulatorCmd
			SubElement(romCollectionXml, 'emulatorParams').text = romCollection.emulatorParams
			
			for romPath in romCollection.romPaths:
				SubElement(romCollectionXml, 'romPath').text = romPath
							
			SubElement(romCollectionXml, 'saveStatePath').text = romCollection.saveStatePath
			SubElement(romCollectionXml, 'saveStateParams').text = romCollection.saveStateParams
				
			for mediaPath in romCollection.mediaPaths:
				
				success, message = self.searchConfigObjects('FileTypes/FileType', mediaPath.fileType.name, 'FileType')
				if(not success):
					return False, message								
												
				SubElement(romCollectionXml, 'mediaPath', {'type' : mediaPath.fileType.name}).text = mediaPath.path
				
			SubElement(romCollectionXml, 'preCmd').text = romCollection.preCmd
			SubElement(romCollectionXml, 'postCmd').text = romCollection.postCmd
			SubElement(romCollectionXml, 'useEmuSolo').text = str(romCollection.useEmuSolo)
			SubElement(romCollectionXml, 'usePopen').text = str(romCollection.usePopen)
			SubElement(romCollectionXml, 'ignoreOnScan').text = str(romCollection.ignoreOnScan)
			SubElement(romCollectionXml, 'allowUpdate').text = str(romCollection.allowUpdate)
			SubElement(romCollectionXml, 'autoplayVideoMain').text = str(romCollection.autoplayVideoMain)
			SubElement(romCollectionXml, 'autoplayVideoInfo').text = str(romCollection.autoplayVideoInfo)
			SubElement(romCollectionXml, 'useFoldernameAsGamename').text = str(romCollection.useFoldernameAsGamename)
			SubElement(romCollectionXml, 'maxFolderDepth').text = str(romCollection.maxFolderDepth)
			SubElement(romCollectionXml, 'doNotExtractZipFiles').text = str(romCollection.doNotExtractZipFiles)
			SubElement(romCollectionXml, 'makeLocalCopy').text = str(romCollection.makeLocalCopy)
			SubElement(romCollectionXml, 'diskPrefix').text = str(romCollection.diskPrefix)
			
			if (os.environ.get( "OS", "xbox" ) == "xbox"):
				SubElement(romCollectionXml, 'xboxCreateShortcut').text = str(romCollection.xboxCreateShortcut)
				SubElement(romCollectionXml, 'xboxCreateShortcutAddRomfile').text = str(romCollection.xboxCreateShortcutAddRomfile)
				SubElement(romCollectionXml, 'xboxCreateShortcutUseShortGamename').text = str(romCollection.xboxCreateShortcutUseShortGamename)
				
			#image placing
			if(not self.createNew):
				#in case of an update we have to create new options
				if(romCollection.name == 'MAME' and not self.createNew):
					self.addFileTypesForMame()
					self.addImagePlacingForMame()
					
			if(romCollection.imagePlacingMain != None and romCollection.imagePlacingMain.name != ''):
				success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor', romCollection.imagePlacingMain.name, 'ImagePlacing')
				if(not success):
					return False, message
				SubElement(romCollectionXml, 'imagePlacingMain').text = romCollection.imagePlacingMain.name 
			else:
				SubElement(romCollectionXml, 'imagePlacingMain').text = 'gameinfobig'
				
			if(romCollection.imagePlacingInfo != None and romCollection.imagePlacingInfo.name != ''):
				success, message = self.searchConfigObjects('ImagePlacing/fileTypeFor', romCollection.imagePlacingInfo.name, 'ImagePlacing')
				if(not success):
					return False, message
				SubElement(romCollectionXml, 'imagePlacingInfo').text = romCollection.imagePlacingInfo.name 
			else:
				SubElement(romCollectionXml, 'imagePlacingInfo').text = 'gameinfosmall'
			
			if(romCollection.scraperSites == None or len(romCollection.scraperSites) == 0):
				SubElement(romCollectionXml, 'scraper', {'name' : 'thegamesdb.net', 'replaceKeyString' : '', 'replaceValueString' : ''})
				SubElement(romCollectionXml, 'scraper', {'name' : 'archive.vg', 'replaceKeyString' : '', 'replaceValueString' : ''})
				SubElement(romCollectionXml, 'scraper', {'name' : 'mobygames.com', 'replaceKeyString' : '', 'replaceValueString' : ''})
			else:
				for scraperSite in romCollection.scraperSites:
				
					if(scraperSite == None):
						continue
						
					#HACK: use replaceKey and -Value only from first scraper
					firstScraper = scraperSite.scrapers[0]
					SubElement(romCollectionXml, 'scraper', {'name' : scraperSite.name, 'replaceKeyString' : firstScraper.replaceKeyString, 'replaceValueString' : firstScraper.replaceValueString})
					
					#create Scraper element
					scrapersXml = self.tree.find('Scrapers')
					
					#check if the current scraper already exists
					siteExists = False
					sitesXml = scrapersXml.findall('Site')
					for site in sitesXml:
						name = site.attrib.get('name')
						if name == scraperSite.name:
							siteExists = True
							break
						
					if not siteExists:
						#HACK: this only covers the first scraper (for offline scrapers)
						site = SubElement(scrapersXml, 'Site', 
							{ 
							'name' : scraperSite.name,
							'descFilePerGame' : str(scraperSite.descFilePerGame),
							'searchGameByCRC' : str(scraperSite.searchGameByCRC),
							'useFoldernameAsCRC' : str(scraperSite.useFoldernameAsCRC),
							'useFilenameAsCRC' : str(scraperSite.useFilenameAsCRC)
							})
																		
						scraper = scraperSite.scrapers[0]
						
						SubElement(site, 'Scraper', 
							{ 
							'parseInstruction' : scraper.parseInstruction,
							'source' : scraper.source,
							'encoding' : scraper.encoding
							})
				
		success, message = self.writeFile()
		return success, message
	
	
	def writeScrapers(self, scrapers):
		
		Logutil.log('write scraper sites', util.LOG_LEVEL_INFO)
				
		scraperSitesXml = self.tree.find('Scrapers')
				
		#HACK: remove all scrapers and create new
		for scraperSiteXml in scraperSitesXml.findall('Site'):				
			scraperSitesXml.remove(scraperSiteXml)
			
		for scraperSite in scrapers.values():
			
			Logutil.log('write scraper site: ' +str(scraperSite.name), util.LOG_LEVEL_INFO)
			
			#Don't write None-Scraper
			if(scraperSite.name == util.localize(32854)):
				Logutil.log('None scraper will be skipped', util.LOG_LEVEL_INFO)
				continue
			
			scraperSiteXml = SubElement(scraperSitesXml, 'Site', 
					{ 
					'name' : scraperSite.name,
					'descFilePerGame' : str(scraperSite.descFilePerGame),
					'searchGameByCRC' : str(scraperSite.searchGameByCRC),
					'useFoldernameAsCRC' : str(scraperSite.useFoldernameAsCRC),
					'useFilenameAsCRC' : str(scraperSite.useFilenameAsCRC)
					})
			
			for scraper in scraperSite.scrapers:
				
				#check if we can use a relative path to parseInstructions
				rcbScraperPath = os.path.join(util.RCBHOME, 'resources', 'scraper')
				pathParts = os.path.split(scraper.parseInstruction)
				if(pathParts[0].upper() == rcbScraperPath.upper()):
					scraper.parseInstruction = pathParts[1]
				
				scraperXml = SubElement(scraperSiteXml, 'Scraper', 
					{ 
					'parseInstruction' : scraper.parseInstruction,
					'source' : scraper.source,
					'encoding' : scraper.encoding,
					'returnUrl' : str(scraper.returnUrl)
					})
		
		success, message = self.writeFile()
		return success, message
	
	
	def writeMissingFilter(self, showHideOption, artworkOrGroup, artworkAndGroup, infoOrGroup, infoAndGroup):
		
		Logutil.log('write Missing Info Filter', util.LOG_LEVEL_INFO)
		
		missingFilterXml = self.tree.find('MissingFilter')
		
		#HACK: remove MissingFilter-element
		if(missingFilterXml != None):				
			self.tree.remove(missingFilterXml)
		
		missingFilterXml = SubElement(self.tree, 'MissingFilter')
		SubElement(missingFilterXml, 'showHideOption').text = showHideOption
		
		if(len(artworkOrGroup) > 0 or len(artworkAndGroup) > 0):
			missingArtworkXml = SubElement(missingFilterXml, 'missingArtworkFilter')
			self.addMissingFilterItems(missingArtworkXml, artworkOrGroup, 'orGroup')
			self.addMissingFilterItems(missingArtworkXml, artworkAndGroup, 'andGroup')
		if(len(infoOrGroup) > 0 or len(infoAndGroup) > 0):
			missingInfoXml = SubElement(missingFilterXml, 'missingInfoFilter')
			self.addMissingFilterItems(missingInfoXml, infoOrGroup, 'orGroup')
			self.addMissingFilterItems(missingInfoXml, infoAndGroup, 'andGroup')
				
		success, message = self.writeFile()
		return success, message
		
		
	def addMissingFilterItems(self, missingXml, group, groupName):		
		if(len(group) > 0):
			groupXml = SubElement(missingXml, groupName)
			for item in group:
				SubElement(groupXml, 'item').text = item
		
	
	def searchConfigObjects(self, xPath, nameToCompare, objectType):		
		objects = self.tree.findall(xPath)
		objectFound = False
		for obj in objects:
			objectName = obj.attrib.get('name')
			if(objectName == nameToCompare):
				objectFound = True
				break
		
		if(not objectFound):
			return False,  util.localize(32009) %(objectType, nameToCompare)
		
		return True, ''
	
		
	def removeRomCollection(self, RCName):
		
		Logutil.log('removeRomCollection', util.LOG_LEVEL_INFO)
		
		configFile = util.getConfigXmlPath()
		self.tree = ElementTree().parse(configFile)
		romCollectionsXml = self.tree.find('RomCollections')
		for romCollectionXml in romCollectionsXml.findall('RomCollection'):
			name = romCollectionXml.attrib.get('name')
			if(name == RCName):
				romCollectionsXml.remove(romCollectionXml)	
				
		success, message = self.writeFile()
		return success, message
		
	def addFileTypesForMame(self):
		Logutil.log('addFileTypesForMame', util.LOG_LEVEL_INFO)
		
		fileTypesXml = self.tree.find('FileTypes')
				
		#check if the MAME FileTypes already exist
		cabinetExists = False
		marqueeExists = False
		actionExists = False
		titleExists = False
		highestId = 0
		fileTypeXml = fileTypesXml.findall('FileType')
		for fileType in fileTypeXml:
			name = fileType.attrib.get('name')
			if name == 'cabinet':
				cabinetExists = True
			elif name == 'marquee':
				marqueeExists = True
			elif name == 'action':
				actionExists = True
			elif name == 'title':
				titleExists = True
			
			id = fileType.attrib.get('id')
			if int(id) > highestId:
				highestId = int(id)
		
		if not cabinetExists:
			self.createFileType(fileTypesXml, str(highestId +1), 'cabinet', 'image', 'game')
		if not marqueeExists:
			self.createFileType(fileTypesXml, str(highestId +2), 'marquee', 'image', 'game')			
		if not actionExists:
			self.createFileType(fileTypesXml, str(highestId +3), 'action', 'image', 'game')
		if not titleExists:
			self.createFileType(fileTypesXml, str(highestId +4), 'title', 'image', 'game')			
			
		
	def createFileType(self, fileTypesXml, id, name, type, parent):
		fileType = SubElement(fileTypesXml, 'FileType', {'id' : str(id), 'name' : name})
		SubElement(fileType, 'type').text = type
		SubElement(fileType, 'parent').text = parent
		
		
	def addImagePlacingForMame(self):
		Logutil.log('addImagePlacingForMame', util.LOG_LEVEL_INFO)
		
		imagePlacingXml = self.tree.find('ImagePlacing')
		
		#check if the MAME ImagePlacing options already exist
		cabinetExists = False
		marqueeExists = False		
		fileTypeForXml = imagePlacingXml.findall('fileTypeFor')
		for fileTypeFor in fileTypeForXml:
			name = fileTypeFor.attrib.get('name')
			if name == 'gameinfomamecabinet':
				cabinetExists = True
			elif name == 'gameinfomamemarquee':
				marqueeExists = True
				
		if not cabinetExists:
			fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name' : 'gameinfomamecabinet'})
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'title'			
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperLeft').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLower').text = 'marquee'
			
		if not marqueeExists:
			fileTypeFor = SubElement(imagePlacingXml, 'fileTypeFor', {'name' : 'gameinfomamemarquee'})
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'marquee'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameList').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'marquee'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForGameListSelected').text = 'title'			
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'boxfront'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'title'
			SubElement(fileTypeFor, 'fileTypeForMainViewBackground').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLeft').text = 'cabinet'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoUpperRight').text = 'action'
			SubElement(fileTypeFor, 'fileTypeForMainViewGameInfoLowerRight').text = 'title'
		
						
	def writeFile(self):
		Logutil.log('writeFile', util.LOG_LEVEL_INFO)
		#write file
		try:
			configFile = util.getConfigXmlPath()
			
			util.indentXml(self.tree)
			treeToWrite = ElementTree(self.tree)			
			treeToWrite.write(configFile)
			
			return True, ""
			
		except Exception, (exc):
			print("Error: Cannot write config.xml: " +str(exc))
			return False, util.localize(32008) +": " +str(exc)