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()
+
+ #_____________________________________________________________________
+
+#=========================================================================