#!/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()