XSLTools

Annotated XSLForms/Resources/PyQtWebResources.py

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