Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Van Assche <dvanassche@guadalinex-nubae.(none)>2009-09-09 15:49:27 (GMT)
committer David Van Assche <dvanassche@guadalinex-nubae.(none)>2009-09-09 15:49:27 (GMT)
commitfb0ee90d778c1c5a7bf4fe87c4d030157520ba3d (patch)
treef00c670a9b1c37090cdcf091c9a78d640d384ee4
parent2c661919adfba436189b3b8120762374a3dd012b (diff)
added pyclicuser.py
-rw-r--r--pyclicuser.py798
1 files changed, 798 insertions, 0 deletions
diff --git a/pyclicuser.py b/pyclicuser.py
new file mode 100644
index 0000000..d2ac301
--- /dev/null
+++ b/pyclicuser.py
@@ -0,0 +1,798 @@
+#!/usr/bin/python
+
+# PyqClicAdmin application, Administration interface. User loads an image, then places lables on them with circled
+# numbers in colour of their choice (application has colour changing ability), then user writes meanings of labels on
+# right hand side, and stores all this in an XML file. XML file contains tags as listed in pylic-common.py file,
+# along with base 64 encoded image. This is for transportability reasons, specifically, transporting across xmpp
+# tubes for collaboration. Application uses cairo and pango libraries for drawing and labeling image. It uses the
+# minidom library for xml importing/exporting.
+
+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 *
+
+class PyClicAdmin:
+
+ #function to open xml file, though parsing of file happens in xml_load_from_file() function.
+ def on_file_open(self, widget):
+ # use file_browse function to open file
+ xml_file = self.pcc.file_browse(gtk.FILE_CHOOSER_ACTION_OPEN)
+ # Check to see 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
+ # set window title to the name of loaded quiz
+ self.pcc.set_window_title_from_file(self.xml_file,self.window)
+
+ #Another in between file in the process of opening xml, basically this checks to see its really an xml document
+ #and can be parsed by minidom, if not it will fail and tell user why. If successful sends it through to
+ #xml_load which does the heavy parsing.
+ 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, show error if it fails
+ try:
+ xml_document = minidom.parse(xml_file)
+ if (xml_document):
+ success = ((self.xml_load(xml_document)))
+ except IOError, (errno, strerror):
+ #show error if not xml file or doesnt load.
+ self.show_error_dlg(
+ "Error loading quiz file(%s): %s" % (errno, strerror))
+ return success
+
+ # Heavy duty xml file parser. Stores false or true for all loaded objects, though currently unused in program
+ # for anything. Title, Category, Author, Colours, Coordinates, Questions and Image are pulled in, parsed and placed
+ # in their respective positions
+ 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
+ self.answers_list=[]
+ # reset all values before loading document, make sure data is clean, and drawing area is clean
+ 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, which will contain all the subelements title, author, category
+ #buttons color, and image. Basically this is seperated as such because it needs to do just one
+ #iteration per quiz document.
+ 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_entry.set_text(item_node.firstChild.nodeValue)
+ else:
+ print "Tag not loaded, probably empty"
+ title_loaded = True
+ # Title Tag loaded at this point and placed by self.title_entry.set_text
+ 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):
+ #we make quite a hacky loop through the listbox, since gtk
+ #doesnt have very nice manipulation of listboxes, and uses
+ #just number indexing.
+ if item_node.firstChild.nodeValue=="Geography":
+ catindex=0
+ elif item_node.firstChild.nodeValue=="Science":
+ catindex=1
+ elif item_node.firstChild.nodeValue=="ICT":
+ catindex=2
+ elif item_node.firstChild.nodeValue=="Languages":
+ catindex=3
+ elif item_node.firstChild.nodeValue=="Maths":
+ catindex=4
+ elif item_node.firstChild.nodeValue=="Music":
+ catindex=5
+ elif item_node.firstChild.nodeValue=="History":
+ catindex=6
+ elif item_node.firstChild.nodeValue=="Business":
+ catindex=7
+ elif item_node.firstChild.nodeValue=="Art":
+ catindex=8
+ #we set the active listbox element to category it found
+ self.cb_category.set_active(catindex)
+ else:
+ print "Tag not loaded, probably empty"
+ category_loaded = True
+ #At this point we have found category and title and have placed them in their
+ #their corresponding positions
+ elif (item_node.nodeName == PyClicCommon._xml_tags[AUTHOR_TAG]):
+ """Set the author, the firstChild in this case is
+ the actual author that we saved. This tag is not really that important
+ and in fact was put in as an after though just in case its wanted"""
+ #Make sure it's not a blank string
+ if (item_node.firstChild):
+ self.author_entry.set_text(item_node.firstChild.nodeValue)
+ else:
+ print "Tag not loaded, probably empty"
+ author_loaded = True
+ #At this point category, title and author have been loaded and placed in the document
+ 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):
+ #we set self.image equal to the decoding of the bin64 image, then
+ #issue a queue draw to let X redraw the drawing area.
+ self.image = self.pcc.decode64(item_node.firstChild.nodeValue)
+ self.window.queue_draw()
+ else:
+ print "Tag not loaded, probably empty"
+ image_loaded = True
+ #Weve now loaded the image, the category, the title and the author and placed
+ #them in their corresponding positions.
+ 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):
+ #since weve saved the colors as a string, as its xml, and
+ #all xml elements must be strings, we need to pull out those
+ #values and make them proper floats to get exact colour values
+ #aswell as split into the 3 corresponsding R, G and B. First we
+ #split the values at the ,
+ self.colourred,self.colourgreen,self.colourblue = item_node.firstChild.nodeValue.split(",")
+ #now we replace the [ with nothing as that got pulled in on save on
+ #conversion of list to string
+ self.colorred=self.colourred.replace('[', '')
+ self.colorred=float(self.colorred)
+ self.colorgreen=float(self.colourgreen)
+ #we do the same replacement for the outer bracket, and now have a
+ # proper list again, split into its R, G, B components, as floats
+ self.colorblue=self.colourblue.replace(']', '')
+ self.colorblue=float(self.colorblue)
+ #we send the color values to X to be redrawn.
+ self.window.queue_draw()
+ else:
+ print "Tag not loaded, probably empty"
+ colors_loaded = True
+ #We've now loaded all the QUIZ tag elements, the ones that require just one iteration.
+ #We are looking for the questions Node, which contains all the iterrable values, that is to say
+ #values for each question found.
+ elif (node.nodeName == PyClicCommon._xml_tags[QUESTIONS_TAG]):
+ # Now loop through the question nodes children
+ for item_node in node.childNodes:
+ self.entradas=[]
+ #we look for entry tag
+ 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):
+ #iterate through entries
+ self.entradas.append(item_node.firstChild.nodeValue)
+ # now pull out values and place them in entry boxes, generating
+ # an entry box for each value
+ for entry in self.entradas:
+ self.answers_list.append(item_node.firstChild.nodeValue)
+ self.label=gtk.Label("("+str(len(item_node.firstChild.nodeValue))+" letras)")
+ self.entry=gtk.Entry(max=30)
+ self.entry_list.append(self.entry)
+ # the below adds the text to the entry boxes
+ self.vbox2.pack_start(self.label,False,False,0)
+ self.vbox2.pack_start(self.entry,False,False,0)
+ self.label.show()
+ self.entry.show()
+ else:
+ print "Tag not loaded, probably empty"
+ entries_loaded = True
+ #We create an empty questions list to iterate through and place items in
+ #self.questions_list=[]
+ #we look for the question tag
+ #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):
+ #for each question, append it to the questions_list
+ # self.questions_list.append(item_node.firstChild.nodeValue)
+ #now generate the questions labels show it
+ #for question in self.questions_list:
+ # self.label=self.get_label(answer)
+ # self.label_list.append(self.label)
+ # self.vbox2.pack_start(self.label,False,False,0)
+ # self.label.show()
+ # else:
+ # print "Tag not loaded, probably empty"
+ # question_loaded = True
+ #create empty self.coordinate list to place coordinates into
+ self.coordinate=[]
+ # Look for coordinates tag
+ 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):
+ #add all coordinates to list
+ self.coordinate.append(item_node.firstChild.nodeValue)
+ # but split x and y and turn into proper floats and point to proper
+ # coordinates list, coordinate, is just used for iteration here.
+ for coordinate in self.coordinate:
+ x,y = coordinate.split(",")
+ self.coordinates.append((float(x),float(y)))
+ # Get X to place or coordinates in the drawin area
+ self.window.queue_draw()
+ else:
+ print "Tag not loaded, probably empty"
+ coordinates_loaded = True
+ # At this point all our question labels and coordinates
+ # have been loaded and placed. We create a entries
+ #iterator list called entradas.
+
+ break
+ # break out of topmost loop since we are finished loading items from XML document.
+ # also return all loaded values as true, which is curerntly unused, but might serve some
+ # purpose at some point.
+ return (title_loaded and category_loaded and author_loaded and image_loaded and entries_loaded and question_loaded and colors_loaded and coordinates_loaded)
+
+
+ #function to save quiz to xml document, way simpler than loading the xml file. In this case we simply
+ #generate all the tags, and place the respectve elements inside.
+ 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></quiz>
+ quiz_element = xml_document.createElement(PyClicCommon._xml_tags[QUIZ_TAG])
+ #create <category></category>
+ category_element = xml_document.createElement(PyClicCommon._xml_tags[CATEGORY_TAG])
+ #Create <category>category</category>
+ category_element.appendChild(xml_document.createTextNode(self.Category))
+ #Creates <image></image>
+ image_element = xml_document.createElement(PyClicCommon._xml_tags[IMAGE_TAG])
+ #Create <IMAGE>image<IMAGE>
+ image_element.appendChild(xml_document.createTextNode(self.Image))
+ #Creates <title></title>
+ title_element = xml_document.createElement(PyClicCommon._xml_tags[TITLE_TAG])
+ #Creates <title>title</title>
+ title_element.appendChild(xml_document.createTextNode(self.Title))
+ #Creates <author></author>
+ author_element = xml_document.createElement(PyClicCommon._xml_tags[AUTHOR_TAG])
+ #Creates <author>author</author>
+ author_element.appendChild(xml_document.createTextNode(self.Author))
+ #Creates <color></color>
+ color_element = xml_document.createElement(PyClicCommon._xml_tags[COLOR_TAG])
+ #Create colorvalues list, and add R,G,B values to it (we should really strip the brackets on string
+ #conversion here taking out the []), but we do that on load instead. Reason = this function was created
+ #before the load function
+ colourvalues = []
+ colourvalues.append(self.colorred)
+ colourvalues.append(self.colorgreen)
+ colourvalues.append(self.colorblue)
+ #Creates <color>colorValues</color> and turns into string
+ color_element.appendChild(xml_document.createTextNode(str(colourvalues)))
+ #appends all elements to quiz tagged XML object
+ 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 all quiz subelements to xml document, these are the non recursive elements of the quiz document,
+ # there is only one of each.
+ xml_document.documentElement.appendChild(quiz_element)
+ #create <questions></questions>
+ questions_element = xml_document.createElement(PyClicCommon._xml_tags[QUESTIONS_TAG])
+ #Setup iteration
+ Iterate = 0
+ #Set questions here, no point in saving values before hand, in fact, come to think of it, we dont really even
+ #need to save this, as it is quite clear we have questions going up in number starting at 1. But for
+ #clarity of XML document we do it that way.
+ question = 1
+ # while there are coordinates in the self.coordinates list, iterate through and save stuff
+ while Iterate < len(self.coordinates):
+ #Create <question></question>
+ question_element = xml_document.createElement(PyClicCommon._xml_tags[QUESTION_TAG])
+ #create <question>question<question> and turn to string (XML requires it)
+ question_element.appendChild(xml_document.createTextNode(str(question)))
+ c = self.coordinates[Iterate]
+ #Create <coordinates></coordinates>
+ coordinates_element = xml_document.createElement(PyClicCommon._xml_tags[COORDINATES_TAG])
+ #create <coordinates>x,y<coordinates>, and turn into strings. This method is better than doing a str
+ # as no bracets are saved, just value,value for each set of x,y coordinates.
+ coordinates_element.appendChild(xml_document.createTextNode("%d,%d" % (c[0],c[1])))
+ #Create <entry></entry>
+ entry_element = xml_document.createElement(PyClicCommon._xml_tags[ENTRY_TAG])
+ #create <entry>entry<entry> and append each entry via the iterator
+ entry_element.appendChild(xml_document.createTextNode(self.Entries[Iterate]))
+
+ #Add above to <questions>
+ 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)
+
+ #This is the main xml saver... basically it leads to xml_save, which does the heavy parsing work. Comparatitvaly
+ #its far easier to open a document than save one.
+ 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, in this case, the XML parser
+ impl = minidom.getDOMImplementation()
+ #Create the document, with PyClicAdmin as 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)
+ #Close the file after writing to it
+ save_file.close()
+ #print exception errors
+ 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
+
+ #A relatively simple function to scale an image by getting its height and width, and doing some funky stuff
+ #with a cairo matrix.
+ 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,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())
+
+ #This function does the hardcore Cairo drawing part with the circle and pango and stuff...
+ def expose(self, widget, event):
+
+ self.cr = widget.window.cairo_create()
+ self.cr.set_source_surface(self.image)
+ self.cr.paint()
+ #set pango details for drawing in circle
+ self.cr.select_font_face("Arial",cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_BOLD)
+ self.cr.set_font_size(16)
+
+ #for each entry in self.coordinates, in other words, for every mouse click position stored
+ for x,y in self.coordinates:
+
+ #set the colour split into its R, G, B components
+ self.cr.set_source_rgb(self.colorred,self.colorgreen,self.colorblue)
+ #draw the respective circle
+ self.cr.arc(x,y,14,0,2 * math.pi)
+ #give the circle an edge
+ self.cr.stroke
+ #make it a filled circle
+ self.cr.fill()
+
+ #define whats going in the circle, basically the mouseclick number
+ self.string="%s" %(self.coordinates.index((x,y))+1)
+ #where do we put it
+ self.cr.move_to(x-4,y+5)
+ #what colour do we make the pango object
+ self.cr.set_source_rgb(1, 1, 1)
+ #show the pango object
+ self.cr.show_text(self.string)
+
+ #needed function to get the active text from the combo box, as gtk doesnt have that built in. found on the web
+ #some place
+ def get_active_text(combobox):
+ model = combobox.get_model()
+ active = combobox.get_active()
+ if active < 0:
+ return None
+ return model[active][0]
+
+ #function to encode in base64 the image so we can transport the XML document easily, especially across xmpp tubes.
+ def encode64(self,filew):
+ try:
+ response = open(filew)
+ data = response.read()
+ #give us the exception error if it doesnt work
+ except IOError, (errno, strerror):
+ self.show_error_dlg("Error saving quiz(%s): %s" % (errno, strerror))
+ #return the base64 encoded object
+ return data.encode('base64')
+
+ #File save function that gets called when all elements have been collected and xml file needs to be openned.
+ def on_file_save(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 of XML file
+ 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 we can actually send to the xml_save_to_file function
+ if (self.xml_save_to_file(self.xml_file)):
+ #Allright it all worked! Set the Title of the window
+ self.pcc.set_window_title_from_file(self.xml_file,self.window)
+ #Give a success notice of saving the file
+ self.on_save_notice(self.window)
+
+
+ #success notice for file save
+ def on_save_notice(self,window):
+ dialog = gtk.MessageDialog(self.window,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "File saved successfully")
+ dialog.set_title("Save Successful")
+ dialog.run()
+ dialog.destroy()
+
+ #warning notice that category is missing
+ def on_items_missing(self,window):
+ dialog = gtk.MessageDialog(self.window,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "You must have a category selected to save")
+ dialog.set_title("Too few details")
+ dialog.run()
+ dialog.destroy()
+
+
+ def on_file_save_as(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.file_browse(gtk.FILE_CHOOSER_ACTION_SAVE, 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
+ PyClicCommon.set_window_title_from_file(self.xml_file)
+
+ #simple little function to grab combobox changed value for category
+ def on_changed(self,widget):
+ self.Category = widget.get_active_text()
+
+ #function to collect data and make sure category is selected
+ def save_details(self,widget):
+ self.Cat=self.cb_category.get_active_text()
+ self.Title = self.title_entry.get_text()
+ self.Author = self.author_entry.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())
+ if self.Cat==None:
+ print "Category missing"
+ self.on_items_missing(self.window)
+ else:
+ self.on_file_save(file)
+
+ #function to check answers against entry list.
+ def on_check_answers(self,widget):
+ iterate=1
+ for entry in self.entry_list:
+ self.Entries.append(entry.get_text())
+ while iterate < len(self.Entries):
+ if self.Entries[iterate]==self.answers_list[iterate]:
+ print self.Entries[iterate]+" is the right answer"
+ else:
+ print "wrong!"
+ iterate=iterate+1
+# self.label.set_text(answers)
+# self.window.queue_draw()
+
+ def on_set_label(self,answer):
+ on_check_answers(self,widget)
+ return answer
+
+ #function to clear all data and all elements
+ 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_entry.set_text("")
+ self.title_entry.set_text("")
+ self.question_list=[]
+ self.xml_file = None
+ self.entry=""
+ self.window.queue_draw()
+
+ #function to call color selector and set the individual colours to their respective numbers
+ 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()
+ #assign the colours as values pycairo understands
+ self.colorred = self.colour.red/65535.0
+ self.colorgreen = self.colour.green/65535.0
+ self.colorblue = self.colour.blue/65535.0
+
+ cdia.destroy()
+ #queue the drawing to X
+ self.window.queue_draw()
+
+ #Start the main constructor of our class, where the magic happens, kinda... not really...
+ 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 (set at 48x48 pixels)
+ try:
+ self.window.set_icon_from_file("pyclicicon.png")
+ except Exception, e:
+ print e.message
+ sys.exit(1)
+
+ #instantiate the pycliccomon class which we imported... yay... now I know what instantiate means :-)
+ self.pcc=PyClicCommon()
+ #add the delete_event handler to pyclic common close application method
+ self.window.connect("delete_event", self.pcc.close_application)
+ #set size for window
+ self.window.set_size_request(775,544)
+ #set the window to have no border
+ self.window.set_border_width(0)
+
+
+ #set an empty xml file on program start
+ self.xml_file=None
+
+
+ #Insert menubar containing 2 columns, file and About or help
+ #create menu bar
+ mb = gtk.MenuBar()
+ #create file menu
+ filemenu = gtk.Menu()
+ #add File menu item
+ filem = gtk.MenuItem("File")
+ #add a submenu to the file menu, basically everything that shows up below file
+ filem.set_submenu(filemenu)
+ #An about menu suboption, linked by the activate handler to the about_program function
+ aboutm = gtk.MenuItem("About PyClicAdmin")
+ aboutm.connect("activate",self.pcc.about_program)
+ #add it to the filemenu
+ filemenu.append(aboutm)
+ #Create a new quiz or clear the screen. This basically deletes all the variable contents
+ #so you have a clean page. Connect it via the activate handler to the on_file_new function
+ newquiz = gtk.MenuItem("New File / Clear")
+ newquiz.connect("activate",self.on_file_new)
+ #add it to the filemenu
+ filemenu.append(newquiz)
+ #create open quiz menu item
+ openquiz = gtk.MenuItem("Open Quiz")
+ #connect the openquiz activator to on_file_open
+ openquiz.connect("activate",self.on_file_open)
+ #add openquiz to filemenu
+ filemenu.append(openquiz)
+
+ #create save option
+ save = gtk.MenuItem("Save Quiz")
+ #connect the activate handler to the save_details function
+ save.connect("activate",self.save_details)
+ #add save to the filemenu
+ filemenu.append(save)
+ #create exit option
+ exit = gtk.MenuItem("Exit")
+ #connect handler to integrated gtk.quit function
+ exit.connect("activate",gtk.main_quit)
+ #add exit to the filemenu
+ filemenu.append(exit)
+
+ #create options submenu
+ optionsmenu = gtk.Menu()
+ #create options option
+ options = gtk.MenuItem("Options")
+ #set optionsmenu as a submenu
+ options.set_submenu(optionsmenu)
+ #create open image option
+# openimage = gtk.MenuItem("Open Image")
+ #add activate handler to open_image function
+# openimage.connect("activate",self.open_image)
+ #add open to the optionsmenu
+# optionsmenu.append(openimage)
+ #create change color option
+# colormenu = gtk.MenuItem("Change Color")
+ #add activate handler to on_clicked function
+# colormenu.connect("activate", self.on_clicked)
+ #add color option to optionsmenu
+# optionsmenu.append(colormenu)
+ #add filemenu and options to menubar
+ mb.append(filem)
+ mb.append(options)
+
+ #Insert Toolbar with several options, and icons taken from stock library,
+ #toolbar only contains icons. Add tooltips to iconic toolbar too.
+ toolbar = gtk.Toolbar()
+ toolbar.set_style(gtk.TOOLBAR_ICONS)
+
+ newtb = gtk.ToolButton(gtk.STOCK_CLEAR)
+ newtb.set_tooltip_text("Clear the screan / start new quiz")
+ opentb = gtk.ToolButton(gtk.STOCK_OPEN)
+ opentb.set_tooltip_text("Open a PyQClic quiz")
+ savetb = gtk.ToolButton(gtk.STOCK_SAVE)
+ savetb.set_tooltip_text("Save a PyQClic Quiz with .gpx extension")
+ sep = gtk.SeparatorToolItem()
+ quittb = gtk.ToolButton(gtk.STOCK_QUIT)
+ quittb.set_tooltip_text("Quit the Program, C u l8r")
+
+ #place positions of toolbar options in toolbar
+ toolbar.insert(newtb, 0)
+ toolbar.insert(opentb, 1)
+ toolbar.insert(savetb, 2)
+ toolbar.insert(sep, 3)
+ toolbar.insert(quittb, 4)
+
+ #connect toolbar handlers to their functions on click
+ 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)
+
+ #create a drawing area where we will place the image
+ self.darea=gtk.DrawingArea()
+ #introduce a startup image called pyclic.png which gives usage instructions
+ self.image = cairo.ImageSurface.create_from_png("pyclic.png")
+ #make initial image filename pyclic.png
+ self.image_filename="pyclic.png"
+ #connect the drawing area to the expose_event handler via the expose function.
+ #Expose makes X draw everything, so one needs to call this function whenever
+ #one needs to add something new to the canvas. This is done using the queue_draw
+ #function, found in several places in this program.
+ self.darea.connect("expose_event", self.expose)
+ #create the events mask, in this case a button click
+ self.darea.set_events(gtk.gdk.BUTTON_PRESS_MASK)
+ #add another handler on button_press_event to the grab_click function which takes
+ #care of grabbing x,y coordinates
+# self.darea.connect("button_press_event",self.grab_click)
+ #set the drawing area size
+ self.darea.set_size_request(606,540)
+ #define empty coordinates list
+
+ self.coordinates=[]
+ #define empty text entries list
+ self.entry_list=[]
+ #define empty labels list
+ self.label_list=[]
+ #define empty question list
+ self.question_list=[]
+
+ #define color values for question circle
+ self.colorred=0
+ self.colorblue=0
+ self.colorgreen=0
+
+ # Generate Layout
+ #create vertical box
+ vbox = gtk.VBox(False, 2)
+ #add the menubar to the vertical box
+ vbox.pack_start(mb,False,False,0)
+ #add toolbar to vertical box
+ vbox.pack_start(toolbar, False, False, 0)
+ #add the vertical box to the window
+ self.window.add(vbox)
+ #create a horizontal box under the menu and toolbar
+ self.hbox = gtk.HBox(False, 2)
+ #add the horizontal box to the vertical box
+ vbox.add(self.hbox)
+ #create a fixed area for the drawing area
+ fix = gtk.Fixed()
+ #add the fixed area to the horizontal box
+ self.hbox.add(fix)
+ #add the drawing area to fixed area at position 0,0, that is to say top left
+ #corner
+ fix.put(self.darea,0,0)
+ #add second vertical box
+ self.vbox2 = gtk.VBox(False, 2)
+
+
+ # Add a title label
+ title_label=gtk.Label("Title")
+ self.vbox2.pack_start(title_label,False,False,0)
+ #Add a Title entry box
+ self.title_entry=gtk.Entry(max=50)
+ self.vbox2.pack_start(self.title_entry,False,False,0)
+ #Add an author label
+ author_label=gtk.Label("Author")
+ self.vbox2.pack_start(author_label,False,False,0)
+ #Add an author entry box
+ self.author_entry=gtk.Entry(max=50)
+ self.vbox2.pack_start(self.author_entry,False,False,0)
+ #Add a Category label
+ title_category=gtk.Label("Category")
+ self.vbox2.pack_start(title_category,False,False,0)
+ #Add a combobox called category to the right hand side and connect changed
+ #handler to on_changed, which captures the category selected
+ 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)
+
+ #submit button for entries
+ submit_button=gtk.Button("Submit")
+ self.vbox2.pack_start(submit_button,False,False,0)
+ #add an event handler to submit button via save_details function
+ submit_button.set_events(gtk.gdk.BUTTON_PRESS_MASK)
+ submit_button.connect("clicked",self.on_check_answers)
+ #add event handler to clear button via on_file_new function
+ 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)
+ #make a scrolledwindow and connect to vertical box 2
+ 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)
+
+ #show all the showable items
+ self.window.show_all()
+
+#initiate main loop
+def main():
+ gtk.main()
+ return 0
+
+#instantiate pyclicadmin class
+if __name__ == "__main__":
+ PyClicAdmin()
+ main()
+