1 #!/usr/bin/env python 2 3 """ 4 PyQt-compatible resources for use with WebStack. 5 6 Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk> 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2.1 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 """ 22 23 import XSLForms.Prepare 24 import XSLForms.Resources.Common 25 import XSLForms.Resources.WebResources 26 import WebStack.Generic 27 import os 28 import libxml2dom 29 30 class XSLFormsResource(XSLForms.Resources.WebResources.XSLFormsResource): 31 32 """ 33 An XSLForms resource supporting PyQt-compatible Web applications for use 34 with WebStack. 35 """ 36 37 widget_resources = {} 38 39 def __init__(self, design_identifier): 40 self.factory = Factory() 41 self.default_design = design_identifier 42 43 # NOTE: Filename extended by string concatenation. 44 45 self.template_resources = {} 46 for design_identifier, design_name in self.design_resources.items(): 47 self.template_resources[design_identifier] = (design_name + ".xhtml", design_name + ".xsl") 48 49 # Resource methods. 50 51 def prepare_output(self, design_identifier): 52 53 """ 54 Prepare the output stylesheets using the given 'design_identifier' to 55 indicate which templates and stylesheets are to be employed in the 56 production of output from the resource. 57 58 The 'design_identifier' is used as a key to the 'design_resources' and 59 'template_resources' dictionary attributes. 60 61 Return the full path to the output stylesheet for use with 'send_output' 62 or 'get_result'. 63 """ 64 65 design_path = self.prepare_design(design_identifier) 66 template_filename, output_filename = self.template_resources[output_identifier] 67 output_path = os.path.abspath(os.path.join(self.resource_dir, output_filename)) 68 template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename)) 69 XSLForms.Prepare.ensure_qt_template(design_path, template_path) 70 XSLForms.Prepare.ensure_stylesheet(template_path, output_path) 71 return output_path 72 73 # PyQt compatibility methods. 74 75 def get_document(self, document_identifier): 76 return libxml2dom.parse(self.prepare_document(document_identifier)) 77 78 def prepare_widget(self, design_identifier, widget_identifier, parent=None): 79 design_path = self.prepare_design(design_identifier) 80 fragment_name, widget_name = self.widget_resources[widget_identifier] 81 fragment_path = os.path.abspath(os.path.join(self.resource_dir, fragment_name)) 82 XSLForms.Prepare.ensure_qt_fragment(design_path, fragment_path, widget_name) 83 # NOTE: Implement the equivalent here! 84 return qtui.QWidgetFactory.create(fragment_path, None, parent) 85 86 def child(self, name): 87 return self.doc.child(name) 88 89 # PyQt structural methods. 90 91 def form_init(self): 92 raise NotImplementedError, "form_init" 93 94 def form_refresh(self): 95 raise NotImplementedError, "form_refresh" 96 97 # Standard XSLFormsResource method, overridden to handle presentation. 98 99 def respond_to_form(self, trans, form): 100 101 """ 102 Respond to the request described by the given transaction 'trans', using 103 the given 'form' object to conveniently retrieve field (request 104 parameter) information and structured form information (as DOM-style XML 105 documents). 106 """ 107 108 # Remember the document since it is accessed independently elsewhere. 109 110 doc = form.get_document(self.default_design) 111 if doc is None: 112 self.doc = UINode(form.new_document(self.default_design)) 113 else: 114 self.doc = UINode(doc) 115 116 self.form_init() 117 118 # NOTE: Updates happen here. 119 120 self.form_refresh() 121 122 trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding)) 123 design_xsl = self.prepare_output(self.default_design) 124 self.send_output(trans, [design_xsl], doc._node) 125 126 class UINode: 127 128 "A PyQt widget tree emulation node." 129 130 def __init__(self, node): 131 self._node = node 132 133 def child(self, name): 134 nodes = self._node.xpath(name) 135 if len(nodes) > 0: 136 return UINode(nodes[0]) 137 else: 138 return None 139 140 def children(self): 141 return [UINode(node) for node in self._node.childNodes] 142 143 def count(self): 144 return len(self._node.childNodes) 145 146 def currentText(self): 147 return self.getAttribute("value") 148 149 def currentItem(self): 150 found = self._node.xpath("*[@value=current()/@value]") 151 if found: 152 return int(found.xpath("count(preceding-sibling::*)")) 153 else: 154 return 0 155 156 def insertItem(self, item, position=-1): 157 158 def parent(self): 159 return UINode(self._node.parentNode) 160 161 def removeItem(self, item): 162 163 def remove(self, item): 164 165 def layout(self): 166 return self 167 168 def setCurrentItem(self): 169 170 def deleteLater(self): 171 self._node.parentNode.removeChild(self._node) 172 173 class Factory: 174 175 "A widget factory helper class." 176 177 def connect(self, widget, obj): 178 pass 179 180 def find_widgets(self, widget, name): 181 182 """ 183 Find within the given 'widget' (a DOM node) the widget with the given 184 'name'. 185 """ 186 187 return widget.getElementsByTagName(name) 188 189 # vim: tabstop=4 expandtab shiftwidth=4