All pastes #427705 Raw Edit

Stuff

public text v1 · immutable
·published 2007-04-06 23:18 UTC
rendered paste body
Index: ProjectTemplate.py
===================================================================
--- ProjectTemplate.py	(revision 0)
+++ ProjectTemplate.py	(revision 0)
@@ -0,0 +1,139 @@
+#
+#	THIS FILE IS PART OF THE JOKOSHER PROJECT AND LICENSED UNDER THE GPL. SEE
+#	THE 'COPYING' FILE FOR DETAILS
+#
+#	ProjectTemplate.py
+#	
+#	This module handles the saving and loading of project templates.
+#	
+#
+#-------------------------------------------------------------------------------
+
+import os
+import Globals
+import xml.dom.minidom as xml
+from Utils import LoadListFromXML, StoreListToXML
+from Monitored import Monitored
+import gettext
+_ = gettext.gettext
+
+#=========================================================================
+
+class ProjectTemplate(Monitored):
+	"""
+	This class saves and loads templates and template information to disk.
+	"""
+
+	#_____________________________________________________________________
+
+	def __init__(self):
+		""" 
+		Creates a new instance of ProjectTemplate.
+		"""
+		Monitored.__init__(self)
+
+	#_____________________________________________________________________
+
+	def SaveTemplateFileToDisk(self, name, instrlist):
+		""" 
+		This method will write a template file to ~/.jokosher/templates/.
+		instrlist is a list containing a list of instruments, e.g. [["audiofile", "Audio File", "path_to_image"], 
+		["acousticguitar", "Acoustic Guitar", "path_to_image"]].
+		Note that we do not save the pixbuf image to xml, we insert it at the beginning of the 
+		instrument list instead so that our template instrument model can have nice shiny icons.
+		
+		Parameters:
+			name -- the name of the template file.
+			instrlist -- a list containing a list of instruments
+		"""
+		doc = xml.Document()
+		head = doc.createElement("template")
+		doc.appendChild(head)
+		
+		for items in instrlist:
+			# create instrument tags for every instrument in the list
+			instrtag = doc.createElement("instrument")
+			head.appendChild(instrtag)
+			StoreListToXML(doc, instrtag, items, "item")
+		
+		if not name.endswith(".template"):
+			name += ".template"
+
+		filename = open(Globals.TEMPLATES_PATH + name, "w")
+		filename.write(doc.toprettyxml())
+		filename.close()
+		self.StateChanged("template-update")
+
+	#_____________________________________________________________________
+	
+	def DeleteTemplateFileFromDisk(self, name):
+		"""
+		This method will delete a template file.
+		
+		Parameters:
+			name -- the name of the template file which will be deleted.
+		"""
+		if not name.endswith(".template"):
+			name += ".template"
+		 
+		try:
+			os.remove(Globals.TEMPLATES_PATH + name)
+		except OSError, e:
+			raise _("Cannot remove template %s") % path, e
+			
+		self.StateChanged("template-update")
+
+	#_____________________________________________________________________
+			
+	def __LoadInstrumentsFromTemplateFile(self, name):
+		"""
+		This method will return a list containing a list of instruments which are in the given template filename.
+		
+		Parameters:
+			name -- the name of the template.
+			
+		Returns:
+			instrlist -- a list containing a list of instruments, e.g. [["audiofile", "Audio File", "path_to_image"]].
+		"""
+		if not name.endswith(".template"):
+			name += ".template"
+		
+		if os.path.exists(Globals.TEMPLATES_PATH + name):
+			filename = open(Globals.TEMPLATES_PATH + name, "r")
+			doc = xml.parse(filename)
+			instrlist = []
+			for item in doc.getElementsByTagName("instrument"):
+				instrlist.append(LoadListFromXML(item))
+			return instrlist
+		else:
+			raise OSError, _("The template %s does not exist") % Globals.TEMPLATES_PATH + name
+				
+	#_____________________________________________________________________
+	
+	def __GetTemplateList(self):
+		"""
+		This method will return a list of template files in the template directory (~/.jokosher/templates/")
+		
+		Returns:
+			filenames -- a list containing the names of file in the template directory.
+		"""
+		templist = []
+		for files in os.listdir(Globals.TEMPLATES_PATH):
+			filenames = files.split(".")[0]
+			templist.append(filenames)
+		return templist
+
+	#_____________________________________________________________________
+
+	def LoadTemplateDictionaryInstruments(self):
+		"""
+		This method will return a dictionary containing the the template file name (key) and their
+		associated instruments (value).
+		e.g. {"Rock" : [["electricguitar", "Electric Guitar", "path_to_image"]]}
+		"""
+		instrdict = {}
+		for i in self.__GetTemplateList():
+			instrdict[i] = self.__LoadInstrumentsFromTemplateFile(i)
+		return instrdict
+	
+#=========================================================================	
Index: ProjectTemplateDialog.py
===================================================================
--- ProjectTemplateDialog.py	(revision 0)
+++ ProjectTemplateDialog.py	(revision 0)
@@ -0,0 +1,243 @@
+#
+#	THIS FILE IS PART OF THE JOKOSHER PROJECT AND LICENSED UNDER THE GPL. SEE
+#	THE 'COPYING' FILE FOR DETAILS
+#
+#	ProjectTemplateDialog.py
+#	
+#	This module is used to present a dialog which allows the user to create, modify and
+#	remove project templates.
+#
+#-------------------------------------------------------------------------------
+
+import gtk
+import gtk.glade
+import Globals
+import ProjectTemplate
+import gettext
+_ = gettext.gettext
+
+#=========================================================================
+
+class ProjectTemplateDialog:
+	"""
+	This class allows the user to modify, save and delete project templates.
+	"""
+	
+	#_____________________________________________________________________
+	
+	def __init__(self, newprojectdlg, template):
+		""" 
+		Creates a new instance of ProjectTemplateDialog.
+		
+		Parameters:
+			newprojectdlg -- reference to NewProjectDialog.
+			template -- reference to ProjectTemplate.
+		"""
+		self.newprojectdlg = newprojectdlg
+		self.template = template
+
+		self.wTree = gtk.glade.XML(Globals.GLADE_PATH, "ProjectTemplateDialog")
+		
+
+		signals = {
+			"on_save_button_clicked" : self.OnSaveButtonClicked,
+			"on_delete_button_clicked" : self.OnDeleteButtonClicked,
+			"on_add_button_clicked" : self.OnAddButtonClicked,
+			"on_remove_button_clicked": self.OnRemoveButtonClicked,
+			"on_close_button_clicked" : self.OnCloseButtonClicked,
+		}
+		self.wTree.signal_autoconnect(signals)
+		
+		self.window = self.wTree.get_widget("ProjectTemplateDialog")
+		self.window.set_transient_for(self.newprojectdlg.dlg)
+		self.window.set_icon(self.newprojectdlg.dlg.get_icon())
+		
+		self.tempcombo = self.wTree.get_widget("template_comboentry")
+		self.tempcombo.child.set_activates_default(True)
+		
+		self.instrtree = self.wTree.get_widget("instrument_treeview")
+		self.addinstrbtn = self.wTree.get_widget("add_button")
+		self.removetempinstr = self.wTree.get_widget("remove_button")
+		self.temptree = self.wTree.get_widget("template_treeview")
+		
+		self.savebtn = self.wTree.get_widget("save_button")
+		self.savebtn.set_flags(gtk.CAN_DEFAULT)
+		self.savebtn.grab_default()
+		self.deletebtn = self.wTree.get_widget("delete_button")
+		
+		self.temptreemodel = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str)
+		self.instrtreemodel = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str)
+		
+		# the template combo entry uses the same model as the template combo in new project dialog
+		self.tempcombo.set_model(self.newprojectdlg.templatemodel)
+		self.instrtree.set_model(self.instrtreemodel)		
+		self.temptree.set_model(self.temptreemodel)
+		
+		self.tempcombo.clear()
+		textrend = gtk.CellRendererText()
+		self.tempcombo.pack_start(textrend)
+		self.tempcombo.add_attribute(textrend, "text", 0)
+		
+		self.instrtree.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+		self.instrtree.append_column(gtk.TreeViewColumn(_("Type"), gtk.CellRendererPixbuf(), pixbuf=0))
+		self.instrtree.append_column(gtk.TreeViewColumn(_("Instrument Name"), gtk.CellRendererText(), text=2))
+		
+		self.temptree.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+		self.temptree.append_column(gtk.TreeViewColumn(_("Type"), gtk.CellRendererPixbuf(), pixbuf=0))
+		self.temptree.append_column(gtk.TreeViewColumn(_("Instrument Name"), gtk.CellRendererText(), text=2))
+		
+		self.tempcombo.connect("changed", self.OnTemplateEntryChanged)
+
+		self.PopulateJokosherInstrumentsModel()
+		self.tempcombo.set_active(self.newprojectdlg.templatecombo.get_active())
+		self.template.AddListener(self)
+		self.window.show_all()
+		
+	#_____________________________________________________________________		
+		
+	def OnTemplateEntryChanged(self, widget):
+		"""
+		Called when the template combo entry contents change.
+			
+		Parameters:
+			widget -- reserved for GTK callbacks. Don't use explicitly.
+		"""
+		if self.tempcombo.child.get_text():
+			self.savebtn.set_sensitive(True)
+			self.deletebtn.set_sensitive(True)
+			self.Update()
+		else:
+			self.savebtn.set_sensitive(False)
+			self.deletebtn.set_sensitive(False)
+			
+	#_____________________________________________________________________
+	
+	def Update(self):
+		"""
+		Called when the template combo entry contents change.
+		Loads instruments from a template file and appends them to the template instruments model.
+		"""
+		for i in self.template.LoadTemplateDictionaryInstruments().keys():
+			if i == self.tempcombo.child.get_text():
+				self.temptreemodel.clear()
+				for instr in self.template.LoadTemplateDictionaryInstruments()[i]:
+					items = (gtk.gdk.pixbuf_new_from_file(instr[2]).scale_simple(22, 22, gtk.gdk.INTERP_BILINEAR), instr[0], instr[1], instr[2])
+					self.temptreemodel.append(items)
+				
+	#_____________________________________________________________________
+			
+	def OnAddButtonClicked(self, widget):
+		"""
+		Called when the add button is clicked.
+		Adds selected instruments to the template instruments model.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks. Don't use explicitly.
+		"""
+		selection = self.instrtree.get_selection()
+		if selection:
+			model, selected = selection.get_selected_rows()
+			iters = [model.get_iter(path) for path in selected]
+			for iter in iters:
+				self.temptreemodel.append((model[iter][0], model[iter][1], model[iter][2], model[iter][3]))
+		else:
+			return
+
+	#_____________________________________________________________________
+			
+	def OnRemoveButtonClicked(self, widget):
+		"""
+		Called when the remove button is clicked.
+		Removes any selected instruments from the template instruments model.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks. Don't use explicitly.
+		"""
+		selection = self.temptree.get_selection()
+		if selection:
+			model, selected = selection.get_selected_rows()
+			iters = [model.get_iter(path) for path in selected]
+			for iter in iters:
+				model.remove(iter)
+		else:
+			return
+
+	#_____________________________________________________________________
+	
+	def OnSaveButtonClicked(self, widget):
+		"""
+		Called when the save button is clicked.
+		Saves added template instruments to a template file.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks. Don't use explicitly.
+		"""
+		instruments = []
+		for row in self.temptreemodel:
+			instruments.append([row[1], row[2], row[3]])
+		self.template.SaveTemplateFileToDisk(self.tempcombo.child.get_text(), instruments)
+		
+	#_____________________________________________________________________
+			
+	def OnDeleteButtonClicked(self, widget):
+		"""
+		Called when the delete button is clicked.
+		Removes the selected template file from disk.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks. Don't use explicitly.
+		"""
+		self.template.DeleteTemplateFileFromDisk(self.tempcombo.child.get_text())
+
+	#_____________________________________________________________________
+		
+	def OnCloseButtonClicked(self, widget):
+		"""
+		Called when the close button is clicked.
+		Destroys the project templates window.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks. Don't use explicitly.
+		"""
+		self.window.destroy()
+		
+	#_____________________________________________________________________
+			
+	def OnStateChanged(self, obj, change=None, *extra):
+		"""
+		Called when a change of state is signalled by any of the
+		objects this view is 'listening' to.
+		
+		Parameters:
+			obj -- object changing state. *CHECK*
+			change -- the change which has occured.
+			extra -- extra parameters passed by the caller.
+		"""
+		if change == "template-update":
+			self.UpdateTemplateModel()
+			
+	#_____________________________________________________________________
+			
+	def PopulateJokosherInstrumentsModel(self):
+		"""
+		Called when the jokosher instruments model needs to be populated.
+		"""
+		instrlist = [(x[0], x[1], x[2].copy(), x[3]) for x in Globals.getCachedInstruments()]
+		for instr in instrlist:
+			self.instrtreemodel.append((instr[2].scale_simple(22, 22, gtk.gdk.INTERP_BILINEAR), instr[1], instr[0], instr[3]))	
+		
+	#_____________________________________________________________________
+	
+	def UpdateTemplateModel(self):
+		"""
+		Called when the template model needs updating.
+		"""
+		self.newprojectdlg.templatemodel.clear()
+		for item in self.template.LoadTemplateDictionaryInstruments().keys():
+			self.newprojectdlg.templatemodel.append((item,))
+			self.newprojectdlg.templatecombo.show_all()
+			self.newprojectdlg.templatecombo.set_active(0)
+		
+	#_____________________________________________________________________
+		
+#=========================================================================
Index: NewProjectDialog.py
===================================================================
--- NewProjectDialog.py	(revision 1346)
+++ NewProjectDialog.py	(working copy)
@@ -16,6 +16,8 @@
 import Globals
 import gettext
 _ = gettext.gettext
+import ProjectTemplate
+import ProjectTemplateDialog
 
 class NewProjectDialog:
 	"""
@@ -39,6 +41,9 @@
 		self.signals = {
 			"on_OK_clicked" : self.OnOK,
 			"on_Cancel_clicked" : self.OnCancel,
+			"on_editbutton_clicked" : self.OnEdit,
+			"on_notemp_radio_toggled" : self.NoTempRadioToggled,
+			"on_temp_radio_toggled" : self.TempRadioToggled
 		}
 		
 		self.res.signal_autoconnect(self.signals)
@@ -54,6 +59,26 @@
 		self.author = self.res.get_widget("author")
 		self.author.set_activates_default(True)
 		
+		self.prjtmp = ProjectTemplate.ProjectTemplate()
+		self.notempradio = self.res.get_widget("notemp_radio")
+		self.notempradio.set_active(True)
+		self.tempradio = self.res.get_widget("temp_radio")
+		self.temphbox = self.res.get_widget("temp_hbox")
+		self.temphbox.set_sensitive(False)
+		self.templatecombo = self.res.get_widget("template")
+		self.templatecombo.clear()
+		
+		self.templatemodel = gtk.ListStore(str)
+		for files in self.prjtmp.LoadTemplateDictionaryInstruments().keys():
+			self.templatemodel.append((files,))
+		self.templatecombo.set_model(self.templatemodel)
+		
+		text = gtk.CellRendererText()
+		self.templatecombo.pack_start(text)
+		self.templatecombo.add_attribute(text, "text", 0)
+		
+		self.templatecombo.set_active(0)
+		
 		# Default author to name of currently logged in user
 		try:
 			# Try to get the full name if it exists
@@ -75,7 +100,31 @@
 		self.dlg.resize(350, 300)
 		self.dlg.set_icon(self.parent.icon)
 		self.dlg.set_transient_for(self.parent.window)
+
+	#_____________________________________________________________________
+		
+	def NoTempRadioToggled(self, widget):
+		"""
+		Called when the no template radio button is activated.
+		The template hbox becomes active if the no template radio button is activated.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks, don't use it explicitly. 
+		"""
+		self.temphbox.set_sensitive(False)
+		
+	#_____________________________________________________________________
 	
+	def TempRadioToggled(self, widget):
+		"""
+		Called when the template radio button is activated.
+		The template hbox becomes inactive if the template radio button is activated.
+		
+		Parameters:
+			widget -- reserved for GTK callbacks, don't use it explicitly. 
+		"""
+		self.temphbox.set_sensitive(True)
+		
 	#_____________________________________________________________________	
 		
 	def OnOK(self, button):
@@ -101,9 +150,9 @@
 		Globals.settings.write()
 		if not folder:
 			folder = "~"
-		
+								
 		try:
-			project = ProjectManager.CreateNewProject(folder,name, author)
+			project = ProjectManager.CreateNewProject(folder, name, author)
 		except ProjectManager.CreateProjectError, e:
 			if e.errno == 1:
 				message = _("Could not initialize project.")
@@ -129,6 +178,8 @@
 		else:
 			self.parent.SetProject(project)
 			self.dlg.destroy()
+			
+		self.AddProjectTemplate()
 		
 	#_____________________________________________________________________	
 	
@@ -141,4 +192,48 @@
 		"""
 		self.dlg.destroy()
 
-	#_____________________________________________________________________	
+	#_____________________________________________________________________
+	
+	def OnEdit(self, button):
+		"""
+		Displays the ProjectTemplate dialog, allowing the user to create, delete and modify project
+		templates.
+		
+		Parameters:
+			button -- reserved for GTK callbacks, don't use it explicitly.
+		"""
+		ProjectTemplateDialog.ProjectTemplateDialog(self, self.prjtmp)
+		
+	#_____________________________________________________________________
+	
+	def ReturnProjectInstrumentTuples(self, name):
+		"""
+		Ths method will return a tuple containing the name, type and pixbuf of the instruments in a given template file.
+		
+		Parameters:
+			name -- the name of the template to use.
+		
+		Returns:
+			instruments -- a list of instruments containing tuples required for project.AddInstruments()
+		"""
+		instruments = []
+		for i in self.prjtmp.LoadTemplateDictionaryInstruments()[name]:
+			items = ((i[1], i[0], gtk.gdk.pixbuf_new_from_file(i[2]), i[2]))
+			instruments.append(items)
+		return instruments
+		
+	#_____________________________________________________________________
+	
+	def AddProjectTemplate(self):
+		"""
+		Adds template instruments to the user's project.
+		"""
+		if self.tempradio.get_active():
+			if self.parent.project:
+				active = self.templatecombo.get_model()[self.templatecombo.get_active()][0]
+				self.parent.project.AddInstruments(self.ReturnProjectInstrumentTuples(active))
+				self.parent.UpdateDisplay()
+				
+	#_____________________________________________________________________
+	
+#=========================================================================