changeset 499:3dff106b945b

Combined the settings extension with the editor settings module. It is now a little more robust. Note that the settings file format has changed. All demos and tools now use the new settings extension.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Fri, 14 May 2010 17:37:42 +0000
parents 5ff83f209333
children 5e6ff32a46fb
files demos/rio_de_hola/run.py demos/rio_de_hola/scripts/agents/agent.py demos/rio_de_hola/scripts/agents/beekeeper.py demos/rio_de_hola/scripts/agents/cloud.py demos/rio_de_hola/scripts/agents/girl.py demos/rio_de_hola/scripts/agents/hero.py demos/rio_de_hola/scripts/world.py demos/rio_de_hola/settings-dist.xml demos/shooter/run.py demos/shooter/settings-dist.xml engine/python/fife/extensions/fife_settings.py tools/editor/scripts/editor.py tools/editor/scripts/settings.py
diffstat 13 files changed, 387 insertions(+), 476 deletions(-) [+]
line wrap: on
line diff
--- a/demos/rio_de_hola/run.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/run.py	Fri May 14 17:37:42 2010 +0000
@@ -118,47 +118,53 @@
 class IslandDemo(ApplicationBase):
 	def __init__(self):
 		super(IslandDemo,self).__init__()
-		pychan.init(self.engine, debug=TDS.readSetting("PychanDebug", type='bool'))
+		pychan.init(self.engine, debug=TDS.get("FIFE", "PychanDebug"))
 		self.world = world.World(self.engine)
 		self.listener = ApplicationListener(self.engine, self.world)
-		self.world.load(str(TDS.readSetting("MapFile")))
+		self.world.load(str(TDS.get("rio", "MapFile")))
 
 	def loadSettings(self):
 		"""
 		Load the settings from a python file and load them into the engine.
-		Called in the ApplicationBase constructor.
+		Called in the ApplicationBase constructor. 
 		"""
+		
+		self._setting = TDS
 
+		glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\\\""
 		engineSetting = self.engine.getSettings()
-		engineSetting.setDefaultFontGlyphs(str(TDS.readSetting("FontGlyphs", strip=False)))
-		engineSetting.setDefaultFontPath(str(TDS.readSetting("Font")))
-		engineSetting.setDefaultFontSize(12)
-		engineSetting.setBitsPerPixel(int(TDS.readSetting("BitsPerPixel")))
-		engineSetting.setInitialVolume(float(TDS.readSetting("InitialVolume")))
-		engineSetting.setSDLRemoveFakeAlpha(int(TDS.readSetting("SDLRemoveFakeAlpha")))
-		engineSetting.setScreenWidth(int(TDS.readSetting("ScreenWidth")))
-		engineSetting.setScreenHeight(int(TDS.readSetting("ScreenHeight")))
-		engineSetting.setRenderBackend(str(TDS.readSetting("RenderBackend")))
-		engineSetting.setFullScreen(int(TDS.readSetting("FullScreen")))
+		engineSetting.setDefaultFontGlyphs(self._setting.get("FIFE", "FontGlyphs", glyphDft))
+		engineSetting.setDefaultFontPath(self._setting.get("FIFE", "Font", "fonts/FreeSans.ttf"))
+		engineSetting.setDefaultFontSize(self._setting.get("FIFE", "DefaultFontSize", 12))
+		engineSetting.setBitsPerPixel(self._setting.get("FIFE", "BitsPerPixel", 0))
+		engineSetting.setInitialVolume(self._setting.get("FIFE", "InitialVolume", 5.0))
+		engineSetting.setSDLRemoveFakeAlpha(self._setting.get("FIFE", "SDLRemoveFakeAlpha", 1))
+		engineSetting.setScreenWidth(self._setting.get("FIFE", "ScreenWidth", 1024))
+		engineSetting.setScreenHeight(self._setting.get("FIFE", "ScreenHeight", 768))
+		engineSetting.setRenderBackend(self._setting.get("FIFE", "RenderBackend", "OpenGL"))
+		engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", 0))
 
-		try:
-			engineSetting.setWindowTitle(str(TDS.readSetting("WindowTitle")))
-			engineSetting.setWindowIcon(str(TDS.readSetting("WindowIcon")))
-		except:
-			pass			
-		try:
-			engineSetting.setImageChunkingSize(int(TDS.readSetting("ImageChunkSize")))
-		except:
-			pass
+		engineSetting.setWindowTitle(self._setting.get("FIFE", "WindowTitle", "No window title set"))
+		engineSetting.setWindowIcon(self._setting.get("FIFE", "WindowIcon", ""))
+		engineSetting.setImageChunkingSize(self._setting.get("FIFE", "ImageChunkSize", 256))
 
 	def initLogging(self):
 		"""
 		Initialize the LogManager.
 		"""
-		LogModules = TDS.readSetting("LogModules", type='list')
-		self.log = fifelog.LogManager(self.engine, int(TDS.readSetting("LogToPrompt")), int(TDS.readSetting("LogToFile")))
-		if LogModules:
-			self.log.setVisibleModules(*LogModules)
+		
+		engineSetting = self.engine.getSettings()
+		logmodules = self._setting.get("FIFE", "LogModules", "controller")
+
+		#log to both the console and log file
+		self._log = fifelog.LogManager(self.engine, 
+									   self._setting.get("FIFE", "LogToPrompt", "0"), 
+									   self._setting.get("FIFE", "LogToFile", "0"))
+
+		self._log.setLevelFilter(fife.LogManager.LEVEL_DEBUG)
+		
+		if logmodules:
+			self._log.setVisibleModules(*logmodules)
 
 	def createListener(self):
 		pass # already created in constructor
@@ -185,7 +191,7 @@
 
 
 if __name__ == '__main__':
-	if TDS.readSetting("ProfilingOn", type='bool'):
+	if TDS.get("FIFE", "ProfilingOn"):
 		import hotshot, hotshot.stats
 		print "Starting profiler"
 		prof = hotshot.Profile("fife.prof")
@@ -197,7 +203,7 @@
 		stats.sort_stats('time', 'calls')
 		stats.print_stats(20)
 	else:
-		if TDS.readSetting("UsePsyco", type='bool'):
+		if TDS.get("FIFE", "UsePsyco"):
 			# Import Psyco if available
 			try:
 				import psyco
--- a/demos/rio_de_hola/scripts/agents/agent.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/scripts/agents/agent.py	Fri May 14 17:37:42 2010 +0000
@@ -25,8 +25,9 @@
 from scripts.common.common import ProgrammingError
 
 class Agent(fife.InstanceActionListener):
-	def __init__(self, model, agentName, layer, uniqInMap=True):
+	def __init__(self, settings, model, agentName, layer, uniqInMap=True):
 		fife.InstanceActionListener.__init__(self)
+		self.settings = settings
 		self.model = model
 		self.agentName = agentName
 		self.layer = layer
@@ -41,14 +42,14 @@
 		raise ProgrammingError('No start defined for Agent')
 
 
-def create_anonymous_agents(model, objectName, layer, agentClass):
+def create_anonymous_agents(settings, model, objectName, layer, agentClass):
 	agents = []
 	instances = [a for a in layer.getInstances() if a.getObject().getId() == objectName]
 	i = 0
 	for a in instances:
 		agentName = '%s:i:%d' % (objectName, i)
 		i += 1
-		agent = agentClass(model, agentName, layer, False)
+		agent = agentClass(settings, model, agentName, layer, False)
 		agent.agent = a
 		a.addActionListener(agent)
 		agents.append(agent)
--- a/demos/rio_de_hola/scripts/agents/beekeeper.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/scripts/agents/beekeeper.py	Fri May 14 17:37:42 2010 +0000
@@ -28,8 +28,8 @@
 _STATE_NONE, _STATE_TALK = 0, 1
 
 class Beekeeper(Agent):
-	def __init__(self, model, agentName, layer, uniqInMap=True):
-		super(Beekeeper, self).__init__(model, agentName, layer, uniqInMap)
+	def __init__(self, settings, model, agentName, layer, uniqInMap=True):
+		super(Beekeeper, self).__init__(settings, model, agentName, layer, uniqInMap)
 		self.state = _STATE_NONE
 
 	def onInstanceActionFinished(self, instance, action):
--- a/demos/rio_de_hola/scripts/agents/cloud.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/scripts/agents/cloud.py	Fri May 14 17:37:42 2010 +0000
@@ -28,8 +28,8 @@
 _STATE_NONE, _STATE_FLOATING, _STATE_DISAPPEAR, _STATE_APPEAR = 0, 1, 2, 3
 
 class Cloud(Agent):
-	def __init__(self, model, agentName, layer, uniqInMap=False):
-		super(Cloud, self).__init__(model, agentName, layer, uniqInMap)
+	def __init__(self, settings, model, agentName, layer, uniqInMap=False):
+		super(Cloud, self).__init__(settings, model, agentName, layer, uniqInMap)
 		self.state = _STATE_NONE
 
 	def isOutOfBounds(self, c):
--- a/demos/rio_de_hola/scripts/agents/girl.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/scripts/agents/girl.py	Fri May 14 17:37:42 2010 +0000
@@ -25,18 +25,19 @@
 from fife import fife
 from fife.extensions.fife_settings import Setting
 
-TDS = Setting(app_name="rio_de_hola")
+#TDS = Setting(app_name="rio_de_hola")
 
 _STATE_NONE, _STATE_IDLE, _STATE_RUN, _STATE_FOLLOW = 0, 1, 2, 3
 
-GIRL_SPEED = 3 * float(TDS.readSetting("TestAgentSpeed"))
 class Girl(Agent):
-	def __init__(self, model, agentName, layer, uniqInMap=True):
-		super(Girl, self).__init__(model, agentName, layer, uniqInMap)
+	def __init__(self, settings, model, agentName, layer, uniqInMap=True):
+		super(Girl, self).__init__(settings, model, agentName, layer, uniqInMap)
 		self.state = _STATE_NONE
 		self.waypoints = ((67, 80), (75, 44))
 		self.waypoint_counter = 0
 		self.hero = self.layer.getInstance('PC')
+		
+		self.GIRL_SPEED = 3 * float(self.settings.get("rio", "TestAgentSpeed"))
 
 	def onInstanceActionFinished(self, instance, action):
 		if self.state in (_STATE_RUN, _STATE_FOLLOW):
@@ -63,8 +64,8 @@
 
 	def follow_hero(self):
 		self.state = _STATE_FOLLOW
-		self.agent.follow('run', self.hero, GIRL_SPEED)
+		self.agent.follow('run', self.hero, self.GIRL_SPEED)
 
 	def run(self, location):
 		self.state = _STATE_RUN
-		self.agent.move('run', location, GIRL_SPEED)
+		self.agent.move('run', location, self.GIRL_SPEED)
--- a/demos/rio_de_hola/scripts/agents/hero.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/scripts/agents/hero.py	Fri May 14 17:37:42 2010 +0000
@@ -25,13 +25,13 @@
 from agent import Agent
 from fife.extensions.fife_settings import Setting
 
-TDS = Setting(app_name="rio_de_hola")
+#TDS = Setting(app_name="rio_de_hola")
 
 _STATE_NONE, _STATE_IDLE, _STATE_RUN, _STATE_KICK, _STATE_TALK = xrange(5)
 
 class Hero(Agent):
-	def __init__(self, model, agentName, layer, uniqInMap=True):
-		super(Hero, self).__init__(model, agentName, layer, uniqInMap)
+	def __init__(self, settings, model, agentName, layer, uniqInMap=True):
+		super(Hero, self).__init__(settings, model, agentName, layer, uniqInMap)
 		self.state = _STATE_NONE
 		self.idlecounter = 1
 
@@ -42,7 +42,7 @@
 		else:
 			self.idlecounter += 1
 		if self.idlecounter % 7 == 0:
-			heroTexts = TDS.readSetting("heroTexts", type='list', text=True)
+			heroTexts = self.settings.get("rio", "heroTexts")
 			txtindex = random.randint(0, len(heroTexts) - 1)
 			instance.say(heroTexts[txtindex], 2500)
 
@@ -55,7 +55,7 @@
 
 	def run(self, location):
 		self.state = _STATE_RUN
-		self.agent.move('run', location, 4 * float(TDS.readSetting("TestAgentSpeed")))
+		self.agent.move('run', location, 4 * self.settings.get("rio", "TestAgentSpeed"))
 
 	def kick(self, target):
 		self.state = _STATE_KICK
--- a/demos/rio_de_hola/scripts/world.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/scripts/world.py	Fri May 14 17:37:42 2010 +0000
@@ -163,7 +163,7 @@
 		self.initAgents()
 		self.initCameras()
 
-		if int(TDS.readSetting("PlaySounds")):
+		if int(TDS.get("FIFE", "PlaySounds")):
 			# play track as background music
 			self.music = self.soundmanager.createSoundEmitter('music/rio_de_hola.ogg')
 			self.music.looping = True
@@ -186,22 +186,22 @@
 		to the python agents for later reference.
 		"""
 		self.agentlayer = self.map.getLayer('TechdemoMapGroundObjectLayer')
-		self.hero = Hero(self.model, 'PC', self.agentlayer)
+		self.hero = Hero(TDS, self.model, 'PC', self.agentlayer)
 		self.instance_to_agent[self.hero.agent.getFifeId()] = self.hero
 		self.hero.start()
 
-		self.girl = Girl(self.model, 'NPC:girl', self.agentlayer)
+		self.girl = Girl(TDS, self.model, 'NPC:girl', self.agentlayer)
 		self.instance_to_agent[self.girl.agent.getFifeId()] = self.girl
 		self.girl.start()
 
-		self.beekeepers = create_anonymous_agents(self.model, 'beekeeper', self.agentlayer, Beekeeper)
+		self.beekeepers = create_anonymous_agents(TDS, self.model, 'beekeeper', self.agentlayer, Beekeeper)
 		for beekeeper in self.beekeepers:
 			self.instance_to_agent[beekeeper.agent.getFifeId()] = beekeeper
 			beekeeper.start()
 
 		# Clouds are currently defunct.
 		cloudlayer = self.map.getLayer('TechdemoMapTileLayer')
-		self.clouds = create_anonymous_agents(self.model, 'Cloud', cloudlayer, Cloud)
+		self.clouds = create_anonymous_agents(TDS, self.model, 'Cloud', cloudlayer, Cloud)
 		for cloud in self.clouds:
 			cloud.start(0.1, 0.05)
 
@@ -230,7 +230,7 @@
 		# You'll se that for our demo we use a image font, so we have to specify the font glyphs
 		# for that one.
 		renderer = fife.FloatingTextRenderer.getInstance(self.cameras['main'])
-		textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.readSetting("FontGlyphs", strip=False)));
+		textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.get("FIFE", "FontGlyphs")));
 		renderer.changeDefaultFont(textfont)
 		renderer.activateAllLayers(self.map)
 		
@@ -242,20 +242,19 @@
 		# So we disable the renderer simply by setting its font to None.
 		renderer = fife.FloatingTextRenderer.getInstance(self.cameras['small'])
 		renderer.changeDefaultFont(None)
-		
 
 		# The following renderers are used for debugging.
 		# Note that by default ( that is after calling View.resetRenderers or Camera.resetRenderers )
 		# renderers will be handed all layers. That's handled here.
 		renderer = self.cameras['main'].getRenderer('CoordinateRenderer')
 		renderer.clearActiveLayers()
-		renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("CoordinateLayerName"))))
+		renderer.addActiveLayer(self.map.getLayer(str(TDS.get("rio", "CoordinateLayerName"))))
 
 		renderer = self.cameras['main'].getRenderer('QuadTreeRenderer')
 		renderer.setEnabled(True)
 		renderer.clearActiveLayers()
-		if str(TDS.readSetting("QuadTreeLayerName")):
-			renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("QuadTreeLayerName"))))
+		if str(TDS.get("rio", "QuadTreeLayerName")):
+			renderer.addActiveLayer(self.map.getLayer(str(TDS.get("rio", "QuadTreeLayerName"))))
 
 		# Set up the second camera
 		# NOTE: We need to explicitly call setLocation, there's a bit of a messup in the Camera code.
@@ -370,10 +369,10 @@
 		instance = self.instancemenu.instance
 		self.hero.talk(instance.getLocationRef())
 		if instance.getObject().getId() == 'beekeeper':
-			beekeeperTexts = TDS.readSetting("beekeeperTexts", type='list', text=True)
+			beekeeperTexts = TDS.get("rio", "beekeeperTexts")
 			instance.say(random.choice(beekeeperTexts), 5000)
 		if instance.getObject().getId() == 'girl':
-			girlTexts = TDS.readSetting("girlTexts", type='list', text=True)
+			girlTexts = TDS.get("rio", "girlTexts")
 			instance.say(random.choice(girlTexts), 5000)
 
 	def onKickButtonPress(self):
--- a/demos/rio_de_hola/settings-dist.xml	Fri May 14 16:23:52 2010 +0000
+++ b/demos/rio_de_hola/settings-dist.xml	Fri May 14 17:37:42 2010 +0000
@@ -1,35 +1,39 @@
+<?xml version='1.0' encoding='UTF-8'?>
 <Settings>
-	<FullScreen> 0 </FullScreen>
-	<PlaySounds> 1 </PlaySounds>
-	<RenderBackend> OpenGL </RenderBackend>
-	<ScreenWidth> 1024 </ScreenWidth>
-	<ScreenHeight> 768 </ScreenHeight>
-	<BitsPerPixel> 0 </BitsPerPixel>
-	<InitialVolume> 5.0 </InitialVolume>
-	<SDLRemoveFakeAlpha> 1 </SDLRemoveFakeAlpha>
-	<WindowTitle> FIFE - Rio de hola </WindowTitle>
-	<WindowIcon>gui/icons/boy.png</WindowIcon>
+	<Module name="FIFE">
+		<Setting name="FullScreen" type="int"> 0 </Setting>
+		<Setting name="PlaySounds" type="int"> 1 </Setting>
+		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
+		<Setting name="ScreenWidth" type="int"> 1024 </Setting>
+		<Setting name="ScreenHeight" type="int"> 768 </Setting>
+		<Setting name="BitsPerPixel" type="int"> 0 </Setting>
+		<Setting name="InitialVolume" type="float"> 5.0 </Setting>
+		<Setting name="SDLRemoveFakeAlpha" type="int"> 1 </Setting>
+		<Setting name="WindowTitle" type="str"> FIFE - Rio de hola </Setting>
+		<Setting name="WindowIcon" type="str"> gui/icons/boy.png </Setting>
+		<Setting name="Font" type="str"> fonts/FreeSans.ttf </Setting>
+		<Setting name="FontGlyphs" strip="0" type="str"> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&amp;`'*#=[]\"</Setting>
+		<Setting name="DefaultFontSize" type="int"> 16 </Setting>
+		<Setting name="LogModules" type="list"> controller </Setting>
+		<Setting name="PychanDebug" type="bool"> False </Setting>
+		<Setting name="LogToPrompt" type="int"> 1 </Setting>
+ 		<Setting name="UsePsyco" type="bool"> False </Setting>
+		<Setting name="ProfilingOn" type="bool"> False </Setting>
+		<Setting name="LogToFile" type="int"> 0 </Setting>
+	</Module>
 
-	<MapFile> maps/shrine.xml </MapFile>
-	<Font> fonts/FreeSans.ttf </Font>
-	<FontGlyphs> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&amp;`'*#=[]\"</FontGlyphs>
-	<LogModules> controller </LogModules>
-	<PychanDebug> False </PychanDebug>
-	<LogToPrompt> 1 </LogToPrompt>
-	<LogToFile> 0 </LogToFile>
-	<UsePsyco> False </UsePsyco>
-	<ProfilingOn> False </ProfilingOn>
-	<ImageChunkSize> 256 </ImageChunkSize>
+	<Module name="rio">
+		<Setting name="MapFile" type="str"> maps/shrine.xml </Setting>
+
+		<Setting name="CoordinateLayerName" type="str"> TechdemoMapTileLayer </Setting>
+		<Setting name="QuadTreeLayerName" type="str"> </Setting>
 
-	<CoordinateLayerName> TechdemoMapTileLayer </CoordinateLayerName>
-	<QuadTreeLayerName> <!--TechdemoMapObjectLayer--> </QuadTreeLayerName>
+		<Setting name="heroTexts" type="list"> I wonder when the guys will get this world ready for me ; Bring it on baby, I'm ready for action! ; humm di dum.... </Setting>
+		<Setting name="girlTexts" type="list"> Why I am running? Haven't you heard that the bees are coming?! ; Heeelp!!! The bees are going to get us! </Setting>
+		<Setting name="beekeeperTexts" type="list"> Some idiot has grown mutated bees around here ; Want to take a look at my farm? ; Did you know that I actually cannot do anything else than stand still and greet everybody? </Setting>
 
-	<heroTexts> I wonder when the guys will \n get this world ready for me ; Bring it on baby, \n I'm ready for action! ; humm di dum.... </heroTexts>
-	<girlTexts> Why I am running? Haven't you heard \n that the bees are coming?! ; Heeelp!!! The bees are going to get us! </girlTexts>
-	<beekeeperTexts> Some idiot has grown mutated bees around here ; Want to take a look at my farm? ; Did you know that I actually cannot do anything \n else than stand still and greet everybody? </beekeeperTexts>
-
-<!-- Test Settings -->
-	<TestCameraPlacement> 0 </TestCameraPlacement>
-	<TestRotationLayerName> TechdemoMapObjectLayer <!-- TechdemoMapTileLayer --> </TestRotationLayerName>
-	<TestAgentSpeed> 0.5 </TestAgentSpeed>
+		<Setting name="TestCameraPlacement" type="int"> 0 </Setting>
+		<Setting name="TestRotationLayerName" type="str"> TechdemoMapTileLayer  </Setting>
+		<Setting name="TestAgentSpeed" type="float"> 0.5 </Setting>
+	</Module>
 </Settings>
--- a/demos/shooter/run.py	Fri May 14 16:23:52 2010 +0000
+++ b/demos/shooter/run.py	Fri May 14 17:37:42 2010 +0000
@@ -93,60 +93,39 @@
 		"""
 		
 		self._setting = TDS
-		
+
+		glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&amp;`'*#=[]\\\""
 		engineSetting = self.engine.getSettings()
-		engineSetting.setDefaultFontGlyphs(str(self._setting.readSetting("FontGlyphs", strip=False)))
-		engineSetting.setDefaultFontPath(str(self._setting.readSetting("Font")))
-		engineSetting.setDefaultFontSize(int(self._setting.readSetting("DefaultFontSize")))
-		engineSetting.setBitsPerPixel(int(self._setting.readSetting("BitsPerPixel")))
-		engineSetting.setInitialVolume(float(self._setting.readSetting("InitialVolume")))
-		engineSetting.setSDLRemoveFakeAlpha(int(self._setting.readSetting("SDLRemoveFakeAlpha")))
-		engineSetting.setScreenWidth(int(self._setting.readSetting("ScreenWidth")))
-		engineSetting.setScreenHeight(int(self._setting.readSetting("ScreenHeight")))
-		engineSetting.setRenderBackend(str(self._setting.readSetting("RenderBackend")))
-		engineSetting.setFullScreen(int(self._setting.readSetting("FullScreen")))
+		engineSetting.setDefaultFontGlyphs(self._setting.get("FIFE", "FontGlyphs", glyphDft))
+		engineSetting.setDefaultFontPath(self._setting.get("FIFE", "Font", "fonts/FreeSans.ttf"))
+		engineSetting.setDefaultFontSize(self._setting.get("FIFE", "DefaultFontSize", 12))
+		engineSetting.setBitsPerPixel(self._setting.get("FIFE", "BitsPerPixel", 0))
+		engineSetting.setInitialVolume(self._setting.get("FIFE", "InitialVolume", 5.0))
+		engineSetting.setSDLRemoveFakeAlpha(self._setting.get("FIFE", "SDLRemoveFakeAlpha", 1))
+		engineSetting.setScreenWidth(self._setting.get("FIFE", "ScreenWidth", 1024))
+		engineSetting.setScreenHeight(self._setting.get("FIFE", "ScreenHeight", 768))
+		engineSetting.setRenderBackend(self._setting.get("FIFE", "RenderBackend", "OpenGL"))
+		engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", 0))
 
-		try:
-			engineSetting.setWindowTitle(str(self._setting.readSetting("WindowTitle")))
-			engineSetting.setWindowIcon(str(self._setting.readSetting("WindowIcon")))
-		except:
-			pass			
-
-		try:
-			engineSetting.setImageChunkingSize(int(self._setting.readSetting("ImageChunkSize")))
-		except:
-			pass
+		engineSetting.setWindowTitle(self._setting.get("FIFE", "WindowTitle", "No window title set"))
+		engineSetting.setWindowIcon(self._setting.get("FIFE", "WindowIcon", ""))
+		engineSetting.setImageChunkingSize(self._setting.get("FIFE", "ImageChunkSize", 256))
 
 	def initLogging(self):
 		"""
 		Initialize the LogManager.
 		"""
+		
+		engineSetting = self.engine.getSettings()
+		logmodules = self._setting.get("FIFE", "LogModules", "controller")
 
-		#@todo: load this from settings
-		logmodules = ["controller",
-		              "event channel", 
-		              "audio",
-		              "model",
-		              "metamodel",
-		              "pool",
-		              "vfs",
-		              "video",
-		              "view",
-		              "camera",
-		              "util",
-		              "pool",
-		              "xml",
-		              "exception",
-		              "structures",
-		              "location",
-		              "native loaders",
-		              "loaders",
-		              "gui",
-		              "script"]
+		#log to both the console and log file
+		self._log = fifelog.LogManager(self.engine, 
+									   self._setting.get("FIFE", "LogToPrompt", "0"), 
+									   self._setting.get("FIFE", "LogToFile", "0"))
+
+		self._log.setLevelFilter(fife.LogManager.LEVEL_DEBUG)
 		
-		#log to both the console and log file
-		self._log = fifelog.LogManager(self.engine, 1, 1)
-		self._log.setLevelFilter(fife.LogManager.LEVEL_DEBUG)
 		if logmodules:
 			self._log.setVisibleModules(*logmodules)
 			
--- a/demos/shooter/settings-dist.xml	Fri May 14 16:23:52 2010 +0000
+++ b/demos/shooter/settings-dist.xml	Fri May 14 17:37:42 2010 +0000
@@ -1,24 +1,25 @@
+<?xml version='1.0' encoding='UTF-8'?>
 <Settings>
-	<FullScreen> 0 </FullScreen>
-	<PlaySounds> 1 </PlaySounds>
-	<RenderBackend> OpenGL </RenderBackend>
-	<ScreenWidth> 1024 </ScreenWidth>
-	<ScreenHeight> 768 </ScreenHeight>
-	<BitsPerPixel> 0 </BitsPerPixel>
-	<InitialVolume> 5.0 </InitialVolume>
-	<SDLRemoveFakeAlpha> 1 </SDLRemoveFakeAlpha>
-	<WindowTitle> FIFE - Shooter Demo </WindowTitle>
-	<WindowIcon> </WindowIcon>
-
-	<MapFile> maps/shrine.xml </MapFile>
-	<Font> fonts/FreeSans.ttf </Font>
-	<FontGlyphs> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&amp;`'*#=[]\"</FontGlyphs>
-	<DefaultFontSize> 16 </DefaultFontSize>
-	<LogModules> controller </LogModules>
-	<PychanDebug> False </PychanDebug>
-	<LogToPrompt> 1 </LogToPrompt>
-	<LogToFile> 0 </LogToFile>
-	<UsePsyco> False </UsePsyco>
-	<ProfilingOn> False </ProfilingOn>
-	<ImageChunkSize> 256 </ImageChunkSize>
+	<Module name="FIFE">
+		<Setting name="FullScreen" type="int"> 0 </Setting>
+		<Setting name="PlaySounds" type="int"> 1 </Setting>
+		<Setting name="RenderBackend" type="str"> OpenGL </Setting>
+		<Setting name="ScreenWidth" type="int"> 1024 </Setting>
+		<Setting name="ScreenHeight" type="int"> 768 </Setting>
+		<Setting name="BitsPerPixel" type="int"> 0 </Setting>
+		<Setting name="InitialVolume" type="float"> 5.0 </Setting>
+		<Setting name="SDLRemoveFakeAlpha" type="int"> 1 </Setting>
+		<Setting name="WindowTitle" type="str"> FIFE - Shooter Demo </Setting>
+		<Setting name="WindowIcon" type="str"></Setting>
+		<Setting name="Font" type="str"> fonts/FreeSans.ttf </Setting>
+		<Setting name="FontGlyphs" strip="0" type="str"> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&amp;`'*#=[]\"</Setting>
+		<Setting name="DefaultFontSize" type="int"> 16 </Setting>
+		<Setting name="LogModules" type="list"> controller ; audio ; vfs ; script ; loaders ; pool ; view ; video ; model ; metamodel ; event_channel ; xml </Setting>
+		<Setting name="PychanDebug" type="bool"> False </Setting>
+		<Setting name="LogToPrompt" type="int"> 1 </Setting>
+		<Setting name="LogToFile" type="int"> 0 </Setting>
+	</Module>
+	<Module name="shooter">
+		<Setting name="MaxSounds" type="int">100</Setting>
+	</Module>
 </Settings>
--- a/engine/python/fife/extensions/fife_settings.py	Fri May 14 16:23:52 2010 +0000
+++ b/engine/python/fife/extensions/fife_settings.py	Fri May 14 17:37:42 2010 +0000
@@ -87,6 +87,7 @@
 		settings = Setting(app_name="myapp")
 		screen_width = settings.readSetting("ScreenWidth")
 	"""
+	
 	def __init__(self, app_name="", settings_file="", settings_gui_xml=""):
 		"""
 		Initializes the Setting object.
@@ -124,10 +125,212 @@
 		if not os.path.exists(os.path.join(self._appdata, self._settings_file)):
 			shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file))
 		
+		self._tree = ET.parse(os.path.join(self._appdata, self._settings_file))
+		self._root_element = self._tree.getroot()
+		self.validateTree()
+
+	def validateTree(self):
+		""" Iterates the settings tree and prints warning when an invalid tag is found """
+		for c in self._root_element.getchildren():
+			if c.tag != "Module":
+				print "Invalid tag in settings.xml. Expected Module, got: ", c.tag
+			elif c.get("name", "") == "":
+				print "Invalid tag in settings.xml. Module name is empty."
+			else:
+				for e in c.getchildren():
+					if e.tag != "Setting":
+						print "Invalid tag in settings.xml in module: ",c.tag,
+						print ". Expected Setting, got: ", e.tag
+					elif c.get("name", "") == "":
+						print "Invalid tag in settings.xml in module: ",c.tag,
+						print ". Setting name is empty", e.tag
+		
+	def getModuleTree(self, module):
+		""" 
+		Returns a module element from the settings tree. If no module with the specified
+		name exists, a new element will be created. 
+		
+		@param module: The module to get from the settings tree
+		@type module: C{string}
+		"""
+		if not isinstance(module, str) and not isinstance(module, unicode):
+			raise AttributeError("Settings:getModuleTree: Invalid type for module argument.")
+			
+		for c in self._root_element.getchildren():
+			if c.tag == "Module" and c.get("name", "") == module:
+				return c
+	
+		# Create module
+		return ET.SubElement(self._root_element, "Module", {"name":module})
+
+	def get(self, module, name, defaultValue=None):
+		""" Gets the value of a specified setting
+		
+		@param module: Name of the module to get the setting from
+		@param name: Setting name
+		@param defaultValue: Specifies the default value to return if the setting is not found
+		@type defaultValue: C{str} or C{unicode} or C{int} or C{float} or C{bool} or C{list} or C{dict}
+		"""
+		if not isinstance(name, str) and not isinstance(name, unicode):
+			raise AttributeError("Settings:get: Invalid type for name argument.")
+		
+		moduleTree = self.getModuleTree(module)
+		element = None
+		for e in moduleTree.getchildren():
+			if e.tag == "Setting" and e.get("name", "") == name:
+				element = e
+				break
+		else: 
+			return defaultValue
+		
+		e_value = element.text
+		e_strip = element.get("strip", "1").strip().lower()
+		e_type	= str(element.get("type", "str")).strip()
+		
+		if e_value is None: 
+			return defaultValue
+		
+		# Strip value
+		if e_strip == "" or e_strip == "false" or e_strip == "no" or e_strip == "0":
+			e_strip = False
+		else: e_strip = True
+		
+		if e_type == "str" or e_type == "unicode":
+			if e_strip: e_value = e_value.strip()
+		else:
+			e_value = e_value.strip()
+		
+		# Return value
+		if e_type == 'int':
+			return int(e_value)
+		elif e_type == 'float':
+			return float(e_value)
+		elif e_type == 'bool':
+			e_value = e_value.lower()
+			if e_value == "" or e_value == "false" or e_value == "no" or e_value == "0":
+				return False
+			else:
+				return True
+		elif e_type == 'str':
+			return str(e_value)
+		elif e_type == 'unicode':
+			return unicode(e_value)
+		elif e_type == 'list':
+			return self._deserializeList(e_value)
+		elif e_type == 'dict':
+			return self._deserializeDict(e_value)
+
+	def set(self, module, name, value, extra_attrs={}):
+		"""
+		Sets a setting to specified value.
+		
+		@param module: Module where the setting should be set
+		@param name: Name of setting
+		@param value: Value to assign to setting
+		@type value: C{str} or C{unicode} or C{int} or C{float} or C{bool} or C{list} or C{dict}
+		@param extra_attrs: Extra attributes to be stored in the XML-file
+		@type extra_attrs: C{dict}
+		"""
+		if not isinstance(name, str) and not isinstance(name, unicode):
+			raise AttributeError("Settings:set: Invalid type for name argument.")
+			
+		moduleTree = self.getModuleTree(module)
+		e_type = "str"
+		
+		if isinstance(value, bool): # This must be before int
+			e_type = "bool"
+			value = str(value)
+		elif isinstance(value, int):
+			e_type = "int"
+			value = str(value)
+		elif isinstance(value, float):
+			e_type = "float"
+			value = str(value)
+		elif isinstance(value, unicode):
+			e_type = "unicode"
+			value = unicode(value)
+		elif isinstance(value, list):
+			e_type = "list"
+			value = self._serializeList(value)
+		elif isinstance(value, dict):
+			e_type = "dict"
+			value = self._serializeDict(value)
+		else:
+			e_type = "str"
+			value = str(value)
+		
+		for e in moduleTree.getchildren():
+			if e.tag != "Setting": continue
+			if e.get("name", "") == name:
+				e.text = value
+				break
+		else:
+			attrs = {"name":name, "type":e_type}
+			for k in extra_attrs:
+				if k not in attrs:
+					attrs[k] = extra_args[k]
+			elm = ET.SubElement(moduleTree, "Setting", attrs)
+			elm.text = value
+
+	def saveSettings(self):
+		""" Writes the settings to the settings file """
+		self._indent(self._root_element)
+		self._tree.write(os.path.join(self._appdata, self._settings_file), 'UTF-8')
+		
+	def _indent(self, elem, level=0):
+		""" 
+		Adds whitespace, so the resulting XML-file is properly indented.
+		Shamelessly stolen from http://effbot.org/zone/element-lib.htm 
+		"""
+		i = "\n" + level*"  "
+		if len(elem):
+			if not elem.text or not elem.text.strip():
+				elem.text = i + "  "
+			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
+		
+	# FIXME:
+	# These serialization functions are not reliable at all
+	# This will only serialize the first level of a dict or list
+	# It will not check the types nor the content for conflicts.
+	# Perhaps we should add a small serialization library?
+	def _serializeList(self, list):
+		""" Serializes a list, so it can be stored in a text file """
+		return " ; ".join(list)
+		
+	def _deserializeList(self, string):
+		""" Deserializes a list back into a list object """
+		return string.split(" ; ")
+
+	def _serializeDict(self, dict):
+		""" Serializes a list, so it can be stored in a text file """
+		serial = ""
+		for key in dict:
+			value = dict[key]
+			if serial != "": serial += " ; "
+			serial += str(key)+" : "+str(value)
+			
+		return serial
+	
+	def _deserializeDict(self, serial):
+		""" Deserializes a list back into a dict object """
+		dict = {}
+		items = serial.split(" ; ")
+		for i in items:
+			kv_pair = i.split(" : ")
+			dict[kv_pair[0]] = kv_pair[1]
+		return dict
 
 	def onOptionsPress(self):
 		"""
-		Opends the options dialog box.  Usually you would bind this to a button.
+		Opens the options dialog box.  Usually you would bind this to a button.
 		"""
 		self.changesRequireRestart = False
 		self.isSetToDefault = False
@@ -141,18 +344,48 @@
 				'render_backend' : ['OpenGL', 'SDL']
 			})
 			self.OptionsDlg.distributeData({
-				'screen_resolution' : self.Resolutions.index(str(self.readSetting("ScreenWidth")) + 'x' + str(self.readSetting("ScreenHeight"))),
-				'render_backend' : 0 if str(self.readSetting("RenderBackend")) == "OpenGL" else 1,
-				'enable_fullscreen' : int(self.readSetting("FullScreen")),
-				'enable_sound' : int(self.readSetting("PlaySounds"))
+				'screen_resolution' : self.Resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))),
+				'render_backend' : 0 if self.get("FIFE", "RenderBackend") == "OpenGL" else 1,
+				'enable_fullscreen' : self.get("FIFE", "FullScreen"),
+				'enable_sound' : self.get("FIFE", "PlaySounds")
 			})
 			self.OptionsDlg.mapEvents({
-				'okButton' : self.saveSettings,
+				'okButton' : self.applySettings,
 				'cancelButton' : self.OptionsDlg.hide,
 				'defaultButton' : self.setDefaults
 			})
 		self.OptionsDlg.show()
 
+	def applySettings(self):
+		"""
+		Writes the settings file.  If a change requires a restart of the engine
+		it notifies you with a small dialog box.
+		"""
+		screen_resolution, render_backend, enable_fullscreen, enable_sound = self.OptionsDlg.collectData('screen_resolution', 'render_backend', 'enable_fullscreen', 'enable_sound')
+		render_backend = 'OpenGL' if render_backend is 0 else 'SDL'
+		if render_backend != self.get("FIFE", "RenderBackend"):
+			self.set("FIFE", 'RenderBackend', render_backend)
+			self.changesRequireRestart = True
+		if int(enable_fullscreen) != int(self.get("FIFE", "FullScreen")):
+			self.set("FIFE", 'FullScreen', int(enable_fullscreen))
+			self.changesRequireRestart = True
+		if int(enable_sound) != int(self.get("FIFE", "PlaySounds")):
+			self.set("FIFE", 'PlaySounds', int(enable_sound))
+			self.changesRequireRestart = True
+		if screen_resolution != self.Resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))):
+			self.set("FIFE", 'ScreenWidth', int(self.Resolutions[screen_resolution].partition('x')[0]))
+			self.set("FIFE", 'ScreenHeight', int(self.Resolutions[screen_resolution].partition('x')[2]))
+			self.changesRequireRestart = True
+
+		if not self.isSetToDefault:
+			self.saveSettings()
+			
+		self.OptionsDlg.hide()
+		if self.changesRequireRestart:
+			RestartDlg = pychan.loadXML(StringIO(CHANGES_REQUIRE_RESTART))
+			RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide })
+			RestartDlg.show()
+
 	def setDefaults(self):
 		"""
 		Overwrites the setting file with the default settings-dist.xml file.
@@ -160,71 +393,3 @@
 		shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file))
 		self.isSetToDefault = True
 		self.changesRequireRestart = True
-
-	def readSetting(self, name, type='int', strip=True, text=False):
-		if not hasattr(self, 'tree'):
-			self.tree = ET.parse(os.path.join(self._appdata, self._settings_file))
-			self.root_element = self.tree.getroot()
-		element = self.root_element.find(name)
-		if element is not None:
-			element_value = element.text
-			if element_value is None:
-				if type == 'int':
-					return 0
-				elif type == 'list':
-					list = []
-					return list
-			else:
-				if type == 'int':
-					return element_value.strip() if strip else element_value
-				elif type == 'list':
-					list = []
-					list_s = []
-					list = str(element_value.strip()).split(";")
-					for item in list:
-						item = item.strip()
-						if text:
-							item = item.replace('\\n', '\n')
-						list_s.append(item)
-					return list_s
-				elif type == 'bool':
-					return False if element_value.strip() == 'False' else True
-		else:
-			print 'Setting,', name, 'does not exist!'
-
-	def setSetting(self, name, value):
-		element = self.root_element.find(name)
-		if element is not None:
-			if value is not element.text:
-				element.text = str(value)
-		else:
-			print 'Setting,', name, 'does not exist!'
-
-	def saveSettings(self):
-		"""
-		Writes the settings file.  If a change requires a restart of the engine
-		it notifies you with a small dialog box.
-		"""
-		screen_resolution, render_backend, enable_fullscreen, enable_sound = self.OptionsDlg.collectData('screen_resolution', 'render_backend', 'enable_fullscreen', 'enable_sound')
-		render_backend = 'OpenGL' if render_backend is 0 else 'SDL'
-		if render_backend != str(self.readSetting("RenderBackend")):
-			self.setSetting('RenderBackend', render_backend)
-			self.changesRequireRestart = True
-		if int(enable_fullscreen) != int(self.readSetting("FullScreen")):
-			self.setSetting('FullScreen', int(enable_fullscreen))
-			self.changesRequireRestart = True
-		if int(enable_sound) != int(self.readSetting("PlaySounds")):
-			self.setSetting('PlaySounds', int(enable_sound))
-			self.changesRequireRestart = True
-		if screen_resolution != self.Resolutions.index(str(self.readSetting("ScreenWidth")) + 'x' + str(self.readSetting("ScreenHeight"))):
-			self.setSetting('ScreenWidth', int(self.Resolutions[screen_resolution].partition('x')[0]))
-			self.setSetting('ScreenHeight', int(self.Resolutions[screen_resolution].partition('x')[2]))
-			self.changesRequireRestart = True
-
-		if not self.isSetToDefault:
-			self.tree.write(os.path.join(self._appdata, self._settings_file))
-		self.OptionsDlg.hide()
-		if self.changesRequireRestart:
-			RestartDlg = pychan.loadXML(StringIO(CHANGES_REQUIRE_RESTART))
-			RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide })
-			RestartDlg.show()
--- a/tools/editor/scripts/editor.py	Fri May 14 16:23:52 2010 +0000
+++ b/tools/editor/scripts/editor.py	Fri May 14 17:37:42 2010 +0000
@@ -57,7 +57,7 @@
 from gui.menubar import Menu, MenuBar
 from gui.error import ErrorDialog
 from mapview import MapView
-from settings import Settings
+from fife.extensions.fife_settings import Setting
 
 def getEditor():
 	""" Returns the Global editor instance """
@@ -109,7 +109,7 @@
 		Load the settings from a python file and load them into the engine.
 		Called in the ApplicationBase constructor.
 		"""
-		self._settings = Settings()
+		self._settings = Setting(app_name="editor")
 		TDS = self._settings
 		
 		glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&amp;`'*#=[]\\\""
--- a/tools/editor/scripts/settings.py	Fri May 14 16:23:52 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ####################################################################
-#  Copyright (C) 2005-2009 by the FIFE team
-#  http://www.fifengine.de
-#  This file is part of FIFE.
-#
-#  FIFE is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the
-#  Free Software Foundation, Inc.,
-#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-# ####################################################################
-
-import shutil
-import os
-from fife.extensions.fife_utils import getUserDataDirectory
-try:
-	import xml.etree.cElementTree as ET
-except:
-	import xml.etree.ElementTree as ET
-
-class Settings(object):
-	""" This class provides an interface for retrieving and putting settings
-	to an XML-file. 
-	
-	Only one instance of this class may exist, or a RuntimeWarning exception
-	will be raised. Use Settings.instance or Editor.getSettings() to retrieve
-	an instance of this class.
-	"""
-	instance = None # Points to the first initialized instance of this class
-	def __init__(self, *args, **kwargs):
-		if Settings.instance is not None:
-			raise RuntimeWarning("Settings instance has already been initialized! Use Editor.getSettings instead")
-			
-		Settings.instance = self
-		
-		self._appdata = getUserDataDirectory("fife", "editor")
-	
-		if os.path.exists(self._appdata+'/settings.xml') is False:
-			shutil.copyfile('settings-dist.xml', self._appdata+'/settings.xml')
-			
-		self.tree = ET.parse(self._appdata+'/settings.xml')
-		self.root_element = self.tree.getroot()
-		self.validateTree()
-		
-	def validateTree(self):
-		""" Iterates the settings tree and prints warning when an invalid tag is found """
-		for c in self.root_element.getchildren():
-			if c.tag != "Module":
-				print "Invalid tag in settings.xml. Expected Module, got: ", c.tag
-			elif c.get("name", "") == "":
-				print "Invalid tag in settings.xml. Module name is empty."
-			else:
-				for e in c.getchildren():
-					if e.tag != "Setting":
-						print "Invalid tag in settings.xml in module: ",c.tag,
-						print ". Expected Setting, got: ", e.tag
-					elif c.get("name", "") == "":
-						print "Invalid tag in settings.xml in module: ",c.tag,
-						print ". Setting name is empty", e.tag
-		
-	def getModuleTree(self, module):
-		""" Returns a module element from the settings tree. If no module with the specified
-		name exists, a new element will be created. """
-		if not isinstance(module, str) and not isinstance(module, unicode):
-			raise AttributeError("Settings:getModuleTree: Invalid type for module argument.")
-			
-		for c in self.root_element.getchildren():
-			if c.tag == "Module" and c.get("name", "") == module:
-				return c
-	
-		# Create module
-		return ET.SubElement(self.root_element, "Module", {"name":module})
-
-	def get(self, module, name, defaultValue=None):
-		""" Gets the value of a specified setting
-		
-		defaultValue is returned if the setting does not exist
-		"""
-		if not isinstance(name, str) and not isinstance(name, unicode):
-			raise AttributeError("Settings:get: Invalid type for name argument.")
-		
-		moduleTree = self.getModuleTree(module)
-		element = None
-		for e in moduleTree.getchildren():
-			if e.tag == "Setting" and e.get("name", "") == name:
-				element = e
-				break
-		else: 
-			return defaultValue
-		
-		e_value = element.text
-		e_strip = element.get("strip", "1").strip().lower()
-		e_type	= str(element.get("type", "str")).strip()
-		
-		if e_value is None: 
-			return defaultValue
-		
-		# Strip value
-		if e_strip == "" or e_strip == "false" or e_strip == "no" or e_strip == "0":
-			e_strip = False
-		else: e_strip = True
-		
-		if e_type == "str" or e_type == "unicode":
-			if e_strip: e_value = e_value.strip()
-		else:
-			e_value = e_value.strip()
-		
-		# Return value
-		if e_type == 'int':
-			return int(e_value)
-		elif e_type == 'float':
-			return float(e_value)
-		elif e_type == 'bool':
-			e_value = e_value.lower()
-			if e_value == "" or e_value == "false" or e_value == "no" or e_value == "0":
-				return False
-			else:
-				return True
-		elif e_type == 'str':
-			return str(e_value)
-		elif e_type == 'unicode':
-			return unicode(e_value)
-		elif e_type == 'list':
-			return self._deserializeList(e_value)
-		elif e_type == 'dict':
-			return self._deserializeDict(e_value)
-
-	def set(self, module, name, value, extra_attrs={}):
-		"""
-		Sets a setting to specified value.
-		
-		Parameters:
-		module (str|unicode): Module where the setting should be set
-		name (str|unicode): Name of setting
-		value: Value to assign to setting
-		extra_attrs (dict): Extra attributes to be stored in the XML-file
-		"""
-		if not isinstance(name, str) and not isinstance(name, unicode):
-			raise AttributeError("Settings:set: Invalid type for name argument.")
-			
-		moduleTree = self.getModuleTree(module)
-		e_type = "str"
-		
-		if isinstance(value, bool): # This must be before int
-			e_type = "bool"
-			value = str(value)
-		elif isinstance(value, int):
-			e_type = "int"
-			value = str(value)
-		elif isinstance(value, float):
-			e_type = "float"
-			value = str(value)
-		elif isinstance(value, unicode):
-			e_type = "unicode"
-			value = unicode(value)
-		elif isinstance(value, list):
-			e_type = "list"
-			value = self._serializeList(value)
-		elif isinstance(value, dict):
-			e_type = "dict"
-			value = self._serializeDict(value)
-		else:
-			e_type = "str"
-			value = str(value)
-		
-		for e in moduleTree.getchildren():
-			if e.tag != "Setting": continue
-			if e.get("name", "") == name:
-				e.text = value
-				break
-		else:
-			attrs = {"name":name, "type":e_type}
-			for k in extra_attrs:
-				if k not in attrs:
-					attrs[k] = extra_args[k]
-			elm = ET.SubElement(moduleTree, "Setting", attrs)
-			elm.text = value
-
-	def saveSettings(self):
-		""" Save settings into settings.xml """
-		self._indent(self.root_element)
-		self.tree.write(self._appdata+'/settings.xml', 'UTF-8')
-		
-	def _indent(self, elem, level=0):
-		""" 
-		Adds whitespace, so the resulting XML-file is properly indented.
-		Shamelessly stolen from http://effbot.org/zone/element-lib.htm 
-		"""
-		i = "\n" + level*"  "
-		if len(elem):
-			if not elem.text or not elem.text.strip():
-				elem.text = i + "  "
-			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
-		
-	# FIXME:
-	# These serialization functions are not reliable at all
-	# This will only serialize the first level of a dict or list
-	# It will not check the types nor the content for conflicts.
-	# Perhaps we should add a small serialization library?
-	def _serializeList(self, list):
-		""" Serializes a list, so it can be stored in a text file """
-		return " ; ".join(list)
-		
-	def _deserializeList(self, string):
-		""" Deserializes a list back into a list object """
-		return string.split(" ; ")
-
-	def _serializeDict(self, dict):
-		""" Serializes a list, so it can be stored in a text file """
-		serial = ""
-		for key in dict:
-			value = dict[key]
-			if serial != "": serial += " ; "
-			serial += str(key)+" : "+str(value)
-			
-		return serial
-	
-	def _deserializeDict(self, serial):
-		""" Deserializes a list back into a dict object """
-		dict = {}
-		items = serial.split(" ; ")
-		for i in items:
-			kv_pair = i.split(" : ")
-			dict[kv_pair[0]] = kv_pair[1]
-		return dict
-