1 #!/usr/bin/env python 2 3 "A WebStack questionnaire application." 4 5 import WebStack.Generic 6 from XSLForms.Resources.WebResources import \ 7 XSLFormsResource, input, output, resources, prepare_resources as xslforms_prepare_resources 8 import os 9 import libxml2dom 10 import xml.dom 11 12 # Site map imports. 13 14 from WebStack.Resources.ResourceMap import MapResource 15 from WebStack.Resources.Selectors import EncodingSelector 16 from WebStack.Resources.Static import DirectoryResource 17 18 # Configuration settings. 19 20 encoding = "utf-8" 21 22 # Resource classes. 23 24 class QuestionnaireEditorResource(XSLFormsResource): 25 26 "A resource providing a questionnaire editor." 27 28 resource_dir = resources(__file__) 29 template_resources = { 30 "questionnaire" : output("question_template.xhtml") 31 } 32 init_resources = { 33 "questionnaire" : input("question_template.xhtml") 34 } 35 document_resources = { 36 "response-types" : "question_response_types.xml" 37 } 38 39 def select_activity(self, trans, form): 40 form.set_activity("questionnaire") 41 42 def respond_to_input(self, trans, form): 43 44 parameters = form.get_parameters() 45 selectors = form.get_selectors() 46 questionnaire = form.get_document() 47 48 self.remove_elements(selectors.get("remove-question")) 49 self.add_elements(selectors.get("add-choice"), "choice") 50 self.remove_elements(selectors.get("remove-choice")) 51 52 # Move questions. 53 # NOTE: Potentially a DOM convenience method here. 54 55 for question in selectors.get("move-question", []): 56 destination = int(question.getAttribute("destination")) 57 if destination > 1: 58 destination += 1 59 root = questionnaire.documentElement 60 target = (root.xpath("question[position() = %d]" % destination) or [None])[0] 61 root.removeChild(question) 62 if target is not None: 63 try: 64 root.insertBefore(question, target) 65 except xml.dom.NotFoundErr: 66 target = (root.xpath("question[position() = %d]" % destination) or [None])[0] 67 root.insertBefore(question, target) 68 else: 69 root.appendChild(question) 70 71 # Add questions using the normal request parameter. 72 73 if parameters.has_key("add-question"): 74 new_question = questionnaire.ownerDocument.createElementNS(None, "question") 75 questionnaire.xpath("questionnaire")[0].appendChild(new_question) 76 77 # Send a response according to certain parameters. 78 # When exported, an XML version of the data is returned. 79 80 if parameters.has_key("export"): 81 trans.set_content_type(WebStack.Generic.ContentType("text/xml", encoding)) 82 questionnaire.toStream(trans.get_response_stream(), trans.get_response_stream_encoding()) 83 raise WebStack.Generic.EndOfResponse 84 85 # Support uploading of files. 86 87 if parameters.has_key("import"): 88 importfile = parameters["importfile"][0] 89 try: 90 doc = libxml2dom.parse(importfile.stream) 91 form.set_document(doc) 92 except libxml2dom.LSException: 93 pass 94 95 def init_document(self, trans, form): 96 97 # Transform, adding enumerations/ranges. 98 99 response_types_xml = self.prepare_document("response-types") 100 XSLFormsResource.init_document(self, trans, form, references={"response-type" : response_types_xml}) 101 102 # Site map initialisation. 103 104 def get_site(): 105 106 "Return a simple Web site resource." 107 108 # Get the main resource and the directory used by the application. 109 110 questionnaire_resource = QuestionnaireEditorResource() 111 directory = questionnaire_resource.resource_dir 112 113 # Make a simple Web site. 114 115 resource = MapResource({ 116 # Static resources: 117 "styles" : DirectoryResource(os.path.join(directory, "styles"), {"css" : "text/css"}), 118 # Main page: 119 "" : questionnaire_resource 120 }) 121 122 return EncodingSelector(resource, encoding) 123 124 # Resource preparation ahead of time - useful for making installations. 125 126 def prepare_resources(): 127 for cls in [QuestionnaireEditorResource]: 128 xslforms_prepare_resources(cls) 129 130 # vim: tabstop=4 expandtab shiftwidth=4