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(), prettyprint=1) 83 raise WebStack.Generic.EndOfResponse 84 85 # Support uploading of files. 86 87 if parameters.has_key("import"): 88 importfile = parameters["importfile"][0] 89 90 if hasattr(importfile, "stream"): 91 try: 92 doc = libxml2dom.parse(importfile.stream) 93 form.set_document(doc) 94 return # success 95 except libxml2dom.LSException: 96 pass 97 98 questionnaire.documentElement.setAttribute("error", "true") 99 100 def init_document(self, trans, form): 101 102 # Transform, adding enumerations/ranges. 103 104 response_types_xml = self.prepare_document("response-types") 105 XSLFormsResource.init_document(self, trans, form, references={"response-type" : response_types_xml}) 106 107 # Site map initialisation. 108 109 def get_site(): 110 111 "Return a simple Web site resource." 112 113 # Get the main resource and the directory used by the application. 114 115 questionnaire_resource = QuestionnaireEditorResource() 116 directory = questionnaire_resource.resource_dir 117 118 # Make a simple Web site. 119 120 resource = MapResource({ 121 # Static resources: 122 "styles" : DirectoryResource(os.path.join(directory, "styles"), {"css" : "text/css"}), 123 # Main page: 124 "" : questionnaire_resource 125 }) 126 127 return EncodingSelector(resource, encoding) 128 129 # Resource preparation ahead of time - useful for making installations. 130 131 def prepare_resources(): 132 for cls in [QuestionnaireEditorResource]: 133 xslforms_prepare_resources(cls) 134 135 # vim: tabstop=4 expandtab shiftwidth=4