#!/usr/bin/env python # -*- coding: UTF-8 -*- # PyClicUser application, Useristration interface import pygtk pygtk.require('2.0') import gtk import cairo import math from xml.dom import minidom import os import sys from pyclic_common import PyClicCommon MAIN_TAG = 0 QUIZ_TAG = 1 CATEGORY_TAG = 2 TITLE_TAG = 3 COLOR_TAG = 4 IMAGE_TAG = 5 AUTHOR_TAG = 6 QUESTIONS_TAG = 7 QUESTION_TAG = 8 COORDINATES_TAG = 9 ENTRY_TAG = 10 FILE_EXT = "pcx" class PyClicUser: def on_file_open(self, widget): self.on_file_new(self.window) xml_file = self.pcc.file_browse(gtk.FILE_CHOOSER_ACTION_OPEN) #If we have a xml_file if (xml_file): if (self.xml_load_from_file(xml_file)): """Allright it all worked! save the current file and set the title.""" self.xml_file = xml_file self.pcc.set_window_title_from_file(self.xml_file,self.window) def xml_load_from_file(self, xml_file): """Load a quiz from an xml file @param xml_file - string - path to file that we will load. @returns boolean - True success. False failure """ #Init return value success = False #Load the xml_file to a document try: xml_document = minidom.parse(xml_file) if (xml_document): success = ((self.xml_load(xml_document))) except IOError, (errno, strerror): self.show_error_dlg( "Error loading quiz file(%s): %s" % (errno, strerror)) return success def xml_load(self, xml_document): """Load the current quiz from an xml document. @param xml_document - xml.dom.minidom.Document object - The xml document that we will load the quiz from. @returns boolean True - success. False - Failure.""" title_loaded = False category_loaded = False question_loaded = False author_loaded = False image_loaded = False coordinates_loaded = False entries_loaded = False questions_loaded = False colors_loaded = False # reset all values before loading document self.on_file_new(self) #Loop through all child nodes of the root. for node in xml_document.documentElement.childNodes: #We are looking for the quiz Node if (node.nodeName == PyClicCommon._xml_tags[QUIZ_TAG]): # Now loop through the quiz nodes children for item_node in node.childNodes: if (item_node.nodeName == PyClicCommon._xml_tags[TITLE_TAG]): """Set the title, the firstChild in this case is the actual title text that we saved.""" #Make sure it's not a blank string if (item_node.firstChild): self.title_label.set_text("Title: " + item_node.firstChild.nodeValue) else: print "nasti" title_loaded = True elif (item_node.nodeName == PyClicCommon._xml_tags[CATEGORY_TAG]): """Set the category, the firstChild in this case is the actual category that we saved.""" #Make sure it's not a blank string if (item_node.firstChild): self.title_category.set_text("Subject: " + item_node.firstChild.nodeValue) else: print "nasti" category_loaded = True elif (item_node.nodeName == PyClicCommon._xml_tags[AUTHOR_TAG]): """Set the author, the firstChild in this case is the actual author that we saved.""" #Make sure it's not a blank string if (item_node.firstChild): self.author_label.set_text("Author: " + item_node.firstChild.nodeValue) else: print "nasti" author_loaded = True #Break out of the topmost for loop elif (item_node.nodeName == PyClicCommon._xml_tags[IMAGE_TAG]): """Set the image, the firstChild in this case is the image that we saved. Then decode from base64""" #Make sure it's not a blank string if (item_node.firstChild): self.image = self.pcc.decode64(item_node.firstChild.nodeValue) self.window.queue_draw() else: print "nasti" image_loaded = True #Break out of the topmost for loop elif (item_node.nodeName == PyClicCommon._xml_tags[COLOR_TAG]): """Set the image, the firstChild in this case is the image that we saved. Then decode from base64""" #Make sure it's not a blank string if (item_node.firstChild): self.colourred,self.colourgreen,self.colourblue = item_node.firstChild.nodeValue.split(",") self.colorred=self.colourred.replace('[', '') self.colorred=float(self.colorred) self.colorgreen=float(self.colourgreen) self.colorblue=self.colourblue.replace(']', '') self.colorblue=float(self.colorblue) self.window.queue_draw() else: print "nasti" colors_loaded = True #Break out of the topmost for loop #We are looking for the quiz Node elif (node.nodeName == PyClicCommon._xml_tags[QUESTIONS_TAG]): # Now loop through the question nodes children for item_node in node.childNodes: self.questions_list=[] if (item_node.nodeName == PyClicCommon._xml_tags[QUESTION_TAG]): """Grab all the questions.""" #Make sure it's not a blank string if (item_node.firstChild): self.questions_list.append(item_node.firstChild.nodeValue) for question in self.questions_list: self.label=gtk.Label("Question: " + question) self.label_list.append(self.label) self.vbox2.pack_start(self.label,False,False,0) self.label.show() else: print "nasti" question_loaded = True self.coordinate=[] if (item_node.nodeName == PyClicCommon._xml_tags[COORDINATES_TAG]): """Grab all the coordinates.""" #Make sure it's not a blank string if (item_node.firstChild): self.coordinate.append(item_node.firstChild.nodeValue) for coordinate in self.coordinate: x,y = coordinate.split(",") self.coordinates.append((float(x),float(y))) self.window.queue_draw() else: print "nasti" coordinates_loaded = True self.entradas=[] if (item_node.nodeName == PyClicCommon._xml_tags[ENTRY_TAG]): """Grab all the entries.""" #Make sure it's not a blank string if (item_node.firstChild): self.entradas.append(item_node.firstChild.nodeValue) for entry in self.entradas: # self.entry=gtk.Entry(max=15) # self.answer=gtk.Label(self.show_answer(item_node.firstChild.nodeValue)) # self.entry.set_text(self.show_answer(item_node.firstChild.nodeValue)) # self.entry_list.append(self.answer) self.word=self.show_answer(item_node.firstChild.nodeValue) self.entry_list.append(self.word) self.vbox2.add(self.word) # self.vbox2.pack_start(self.word,False,False,0) # self.vbox2.pack_start(self.answer,False,False,0) self.word.show() else: print "nasti" entries_loaded = True break return (title_loaded and category_loaded and author_loaded and image_loaded and entries_loaded and question_loaded and colors_loaded and coordinates_loaded) def xml_save(self, xml_document): """Save the current quiz to an xml document. @param xml_document - xml.dom.minidom.Document object - The xml document that we will save the post to.""" #create quiz_element = xml_document.createElement(PyClicCommon._xml_tags[QUIZ_TAG]) #create category_element = xml_document.createElement(PyClicCommon._xml_tags[CATEGORY_TAG]) #Create category category_element.appendChild(xml_document.createTextNode(self.Category)) #Creates image_element = xml_document.createElement(PyClicCommon._xml_tags[IMAGE_TAG]) #Create image image_element.appendChild(xml_document.createTextNode(self.Image)) #Creates title_element = xml_document.createElement(PyClicCommon._xml_tags[TITLE_TAG]) #Creates title title_element.appendChild(xml_document.createTextNode(self.Title)) #Creates author_element = xml_document.createElement(PyClicCommon._xml_tags[AUTHOR_TAG]) #Creates author author_element.appendChild(xml_document.createTextNode(self.Author)) #Creates color_element = xml_document.createElement(PyClicCommon._xml_tags[COLOR_TAG]) #turn color into list colourvalues = [] colourvalues.append(self.colorred) colourvalues.append(self.colorgreen) colourvalues.append(self.colorblue) #Creates author color_element.appendChild(xml_document.createTextNode(str(colourvalues))) quiz_element.appendChild(category_element) quiz_element.appendChild(title_element) quiz_element.appendChild(image_element) quiz_element.appendChild(author_element) quiz_element.appendChild(color_element) #Now add to the xml document xml_document.documentElement.appendChild(quiz_element) #create questions_element = xml_document.createElement(PyClicCommon._xml_tags[QUESTIONS_TAG]) Iterate = 0 question = 1 while Iterate < len(self.coordinates): #Create question_element = xml_document.createElement(PyClicCommon._xml_tags[QUESTION_TAG]) #create question question_element.appendChild(xml_document.createTextNode(str(question))) c = self.coordinates[Iterate] #Create coordinates_element = xml_document.createElement(PyClicCommon._xml_tags[COORDINATES_TAG]) #create x,y coordinates_element.appendChild(xml_document.createTextNode("%d,%d" % (c[0],c[1]))) #Create entry_element = xml_document.createElement(PyClicCommon._xml_tags[ENTRY_TAG]) #create entry entry_element.appendChild(xml_document.createTextNode(self.Entries[Iterate])) #Add above to questions_element.appendChild(question_element) questions_element.appendChild(coordinates_element) questions_element.appendChild(entry_element) Iterate=Iterate+1 question=question+1 #Now add to the xml document xml_document.documentElement.appendChild(questions_element) def xml_save_to_file(self, widget): """Save the current post to xml_file @param xml_file - string - path to file that we will save the xml to. @returns boolean - True success. False failure """ #Init return value success = False #Get the available DOM Implementation impl = minidom.getDOMImplementation() #Create the document, with PyClicUser as to base node xml_document = impl.createDocument(None, PyClicCommon._xml_tags[MAIN_TAG], None) #Save the questions into the xml self.xml_save(xml_document) #Now actually try to save the file try: save_file = open(self.xml_file, 'w') #write the xml document to disc xml_document.documentElement.writexml(save_file) save_file.close() except IOError, (errno, strerror): self.show_error_dlg( "Error saving quiz(%s): %s" % (errno, strerror)) else: #Allright it all worked! Set the return value success = True return success # # open image file self.chooser with filter for just image types # def open_image(self,widget): # self.chooser = gtk.FileChooserDialog(title="Open Image",action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) # filter = gtk.FileFilter() # filter.set_name("Images") # filter.add_mime_type("image/png") # filter.add_pattern("*.png") # self.chooser.add_filter(filter) # # response = self.chooser.run() # if response == gtk.RESPONSE_OK: # self.image=self.image.create_from_png(self.chooser.get_filename()) # self.image_scale(self.image) # self.image_filename=self.chooser.get_filename() # self.image=self.image.create_from_png(self.chooser.get_filename()) # self.darea.queue_draw() # elif response == gtk.RESPONSE_CANCEL: # print 'Closed, no files selected' # self.chooser.destroy() def image_scale(self,image): self.width=self.image.get_width() self.height=self.image.get_height() imgpat = cairo.SurfacePattern(self.image) scaler = cairo.Matrix() #image width/640*100,image height/480 scaler.scale(self.width/640.0,self.height/480.0) imgpat.set_matrix(scaler) #set resampling filter imgpat.set_filter(cairo.FILTER_BEST) canvas = cairo.ImageSurface(cairo.FORMAT_ARGB32,640,480) ctx = cairo.Context(canvas) ctx.set_source(imgpat) ctx.paint() canvas.write_to_png(self.chooser.get_filename()) # def grab_click(self,widget,event): # x, y = event.get_coords() # self.coordinates.append((x,y)) # gc = widget.window.new_gc() # widget.queue_draw() # # self.label=gtk.Label(self.coordinates.index((x,y))+1) # self.label_list.append(self.label) # self.vbox2.pack_start(self.label,False,False,0) # self.label.show() # # self.entry=gtk.Entry(max=30) # self.entry_list.append(self.entry) # # self.vbox2.pack_start(self.entry,False,False,0) # # self.entry.show() def expose(self, widget, event): self.cr = widget.window.cairo_create() self.cr.set_source_surface(self.image) self.cr.paint() self.cr.select_font_face("Arial",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_BOLD) self.cr.set_font_size(16) for x,y in self.coordinates: self.cr.set_source_rgb(self.colorred,self.colorgreen,self.colorblue) self.cr.arc(x,y,14,0,2 * math.pi) self.cr.stroke self.cr.fill() self.string="%s" %(self.coordinates.index((x,y))+1) self.cr.move_to(x-4,y+5) self.cr.set_source_rgb(1, 1, 1) self.cr.show_text(self.string) def get_active_text(combobox): model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][0] def encode64(self,filew): try: response = open(filew) data = response.read() except IOError, (errno, strerror): self.show_error_dlg("Error saving quiz(%s): %s" % (errno, strerror)) return data.encode('base64') def on_file_save_as(self, widget): """This function saves the current Quiz as an XML file using sub functions""" # Let the user browse for the save location and name if (self.xml_file == None): self.xml_file = self.pcc.file_browse(gtk.FILE_CHOOSER_ACTION_SAVE) #If we have a xml_file if (self.xml_file): if (self.xml_save_to_file(self.xml_file)): #Allright it all worked! Set the Title self.pcc.set_window_title_from_file(self.xml_file,self.window) def on_file_save(self, widget): """Let the user save the current file to a new location.""" xml_file = "Untitled" if (self.xml_file != None): xml_file = os.path.basename(self.xml_file) xml_file = self.pcc.file_browse(gtk.FILE_CHOOSER_ACTION_SAVE, xml_file) # xml_file=xml_file + "answer.pcx" print xml_file #If we have a xml_file # if (xml_file): # if (self.xml_save_to_file(xml_file)): # """Allright it all worked! save the current file and # set the title.""" # self.xml_file = xml_file # # self.pcc.set_window_title_from_file(self.xml_file,self.window) def show_answer(self,text): #FUNCION que devuelve las rallitas necesarias para las respuestas# devolver = gtk.Fixed() for i in range(len(text)): self.letra = gtk.Entry(max=1) self.letra.set_size_request(22,22) self.letra.set_sensitive(False) self.letra.show() devolver.put(self.letra, ( i * 19), 0) return(devolver) def save_details(self,widget): self.Title = self.title_label.get_text() self.Author = self.author_label.get_text() self.Category = self.title_category.get_text() # save image to base64 self.Image = self.encode64(self.image_filename) # function to grab entries from entry list self.Entries=[] for entry in self.entry_list: self.Entries.append(entry.get_text()) self.on_file_save(file) def on_file_new(self,widget): for entry in self.entry_list: self.vbox2.remove(entry) for label in self.label_list: self.vbox2.remove(label) self.entry_list=[] self.Entries=[] self.coordinates=[] self.author_label.set_text("Author") self.title_label.set_text("Title") self.question_list=[] self.xml_file = None self.entry="" self.window.queue_draw() def on_clicked(self, widget): cdia = gtk.ColorSelectionDialog("Select color") response = cdia.run() if response == gtk.RESPONSE_OK: colorsel = cdia.colorsel self.colour = colorsel.get_current_color() self.colorred = self.colour.red/65535.0 self.colorgreen = self.colour.green/65535.0 self.colorblue = self.colour.blue/65535.0 cdia.destroy() self.window.queue_draw() def __init__(self): # create the main window, and attach delete_event signal to terminating # the application self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) #set icon for app try: self.window.set_icon_from_file("pyclicicon.png") except Exception, e: print e.message sys.exit(1) self.pcc=PyClicCommon() self.window.connect("delete_event", self.pcc.close_application) self.window.set_size_request(791,544) self.window.set_border_width(0) self.vbox2 = gtk.VBox(False, 2) self.vbox2.set_border_width(8) self.xml_file=None #Insert menubar containing 2 columns mb = gtk.MenuBar() filemenu = gtk.Menu() filem = gtk.MenuItem("File") filem.set_submenu(filemenu) newquiz = gtk.MenuItem("New File / Clear") newquiz.connect("activate",self.on_file_new) filemenu.append(newquiz) openquiz = gtk.MenuItem("Open Quiz") openquiz.connect("activate",self.on_file_open,self.xml_file) filemenu.append(openquiz) save = gtk.MenuItem("Save Quiz") save.connect("activate",self.save_details,self.xml_file) filemenu.append(save) exit = gtk.MenuItem("Exit") exit.connect("activate",gtk.main_quit) filemenu.append(exit) helpmenu = gtk.Menu() help = gtk.MenuItem("Help") help.set_submenu(helpmenu) aboutm = gtk.MenuItem("About PyClicUser") aboutm.connect("activate",self.pcc.about_program) helpmenu.append(aboutm) # open = gtk.MenuItem("Open Image") # open.connect("activate",self.open_image) # viewmenu.append(open) # # stat = gtk.MenuItem("Change Color") # stat.connect("activate", self.on_clicked) # viewmenu.append(stat) mb.append(filem) mb.append(help) self.hbox = gtk.HBox(False, 2) #define and start vertical area vbox = gtk.VBox(False, 2) vbox.pack_start(mb,False,False,0) #Insert Toolbar with open,save and exit toolbar = gtk.Toolbar() toolbar.set_style(gtk.TOOLBAR_ICONS) newtb = gtk.ToolButton(gtk.STOCK_CLEAR) opentb = gtk.ToolButton(gtk.STOCK_OPEN) savetb = gtk.ToolButton(gtk.STOCK_SAVE) # colortb = gtk.ToolButton(gtk.STOCK_SELECT_COLOR) # importtb = gtk.ToolButton(gtk.STOCK_ORIENTATION_PORTRAIT) sep = gtk.SeparatorToolItem() quittb = gtk.ToolButton(gtk.STOCK_QUIT) toolbar.insert(opentb, 0) toolbar.insert(savetb, 1) toolbar.insert(newtb, 2) # toolbar.insert(colortb,3) # toolbar.insert(importtb,4) toolbar.insert(sep, 3) toolbar.insert(quittb, 4) quittb.connect("clicked", gtk.main_quit) newtb.connect("clicked", self.on_file_new) opentb.connect("clicked", self.on_file_open) savetb.connect("clicked", self.save_details) #colortb.connect("clicked", self.on_clicked) # importtb.connect("clicked",self.open_image) vbox.pack_start(toolbar, False, False, 0) # A drawing area inside a fixed() fix = gtk.Fixed() self.darea=gtk.DrawingArea() self.image = cairo.ImageSurface.create_from_png("pyclic.png") self.image_filename="pyclic.png" self.darea.connect("expose_event", self.expose) # self.darea.set_events(gtk.gdk.BUTTON_PRESS_MASK) # self.darea.connect("button_press_event",self.grab_click) self.darea.set_size_request(606,540) fix.put(self.darea,0,0) #define coordinates list self.coordinates=[] #define text entries list self.entry_list=[] self.label_list=[] self.question_list=[] #define color values for question circle self.colorred=0 self.colorblue=0 self.colorgreen=0 # Layout self.window.add(vbox) vbox.add(self.hbox) self.hbox.add(fix) # Title and category entry boxes self.title_label=gtk.Label("Title") self.vbox2.pack_start(self.title_label,False,False,0) #self.title_entry=gtk.Entry(max=50) #self.vbox2.pack_start(self.title_entry,False,False,0) self.author_label=gtk.Label("Author") self.vbox2.pack_start(self.author_label,False,False,0) #self.author_entry=gtk.Entry(max=50) #self.vbox2.pack_start(self.author_entry,False,False,0) self.title_category=gtk.Label("Category") self.vbox2.pack_start(self.title_category,False,False,0) # self.cb_category=gtk.combo_box_new_text() # self.cb_category.connect("changed", self.on_changed) # self.cb_category.append_text("Geography") # self.cb_category.append_text("Science") # self.cb_category.append_text("ICT") # self.cb_category.append_text("Languages") # self.cb_category.append_text("Maths") # self.cb_category.append_text("Music") # self.cb_category.append_text("History") # self.cb_category.append_text("Business") # self.cb_category.append_text("Art") # self.vbox2.pack_start(self.cb_category,False,False,0) clear_button=gtk.Button("Clear") self.vbox2.pack_start(clear_button,False,False,0) clear_button.set_events(gtk.gdk.BUTTON_PRESS_MASK) clear_button.connect("clicked",self.on_file_new) clear_button.set_size_request(150, 25) #submit button for entries submit_button=gtk.Button("Submit") self.vbox2.pack_start(submit_button,False,False,0) submit_button.set_events(gtk.gdk.BUTTON_PRESS_MASK) submit_button.connect("clicked",self.save_details) self.scrollw = gtk.ScrolledWindow() self.scrollw.set_policy(gtk.POLICY_NEVER,gtk.POLICY_AUTOMATIC) self.hbox.pack_start(self.scrollw) self.scrollw.add_with_viewport(self.vbox2) # self.hbox.add(self.vbox2) self.window.show_all() def main(): gtk.main() return 0 if __name__ == "__main__": PyClicUser() main()