# HG changeset patch # User Paul Boddie # Date 1223833629 -7200 # Node ID 4626e4174edfef423209b5b5cbf00c0f7fcfac57 # Parent 54380c79216ee5315ad9d5f4cd0ab2aa860193f6 Removed PyQt support. Tidied and updated the overview. Updated dependencies and release notes. diff -r 54380c79216e -r 4626e4174edf README.txt --- a/README.txt Sun Oct 12 19:28:30 2008 +0200 +++ b/README.txt Sun Oct 12 19:47:09 2008 +0200 @@ -51,7 +51,6 @@ libxslt 1.1.17 should be avoided The example Web applications require WebStack (release 1.3 or later). -The example PyQt applications have been tested with PyQt 3.15. New in XSLTools 0.6 (Changes since XSLTools 0.5) ------------------------------------------------ @@ -64,13 +63,15 @@ template design document, linking to the housekeeping annotations section of the template attribute reference guide. * Observed changes in WebStack 1.3 and introduced default_charset usage in - the WebResources and PyQtWebResources modules. + the WebResources module. * Added experimental OpenID support; improved the authentication resources and mechanisms. * Fixed the LoginResource to work correctly when detecting the protected application's location. * NOTE: Need to add persistence for OpenID associations. * Added XInclude support in templates (requires libxml2dom 0.4.6 or later). + * Removed PyQt support since the advantages of designing user interfaces for + the Web using Qt Designer are questionable. New in XSLTools 0.5 (Changes since XSLTools 0.4.6) -------------------------------------------------- diff -r 54380c79216e -r 4626e4174edf XSLForms/Resources/PyQtCommon.py --- a/XSLForms/Resources/PyQtCommon.py Sun Oct 12 19:28:30 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -#!/usr/bin/env python - -""" -Common resource class functionality for PyQt-related applications. - -Copyright (C) 2005 Paul Boddie - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the Free -Software Foundation; either version 3 of the License, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. - -You should have received a copy of the GNU Lesser General Public License along -with this program. If not, see . -""" - -import os -from XSLForms.Resources.Common import CommonResource - -class PyQtCommonResource(CommonResource): - - "Common PyQt-compatible resource methods." - - design_resources = {} - - def get_document(self, document_identifier): - - """ - Return a DOM-style document retrieved using the given - 'document_identifier'. - - Each implementation is free to choose its own DOM library. - """ - - raise NotImplementedError, "get_document" - - def get_elements(self, document_identifier): - doc = self.get_document(document_identifier) - - # NOTE: Using special suffix. - - return doc.getElementsByTagName(document_identifier + "-enum") - - def prepare_design(self, design_identifier): - filename = self.design_resources[design_identifier] - return os.path.abspath(os.path.join(self.resource_dir, filename)) - - def populate_list(self, field, elements): - - "Populate the given 'field' using a list of DOM 'elements'." - - current_text = field.currentText() - while field.count() > 0: - field.removeItem(0) - item = 0 - set = 0 - for element in elements: - text = element.getAttribute("value") - field.insertItem(text) - if text == current_text: - field.setCurrentItem(item) - set = 1 - item += 1 - if not set: - field.setCurrentItem(0) - - def reset_collection(self, field): - - "Empty the given collection 'field'." - - layout = field.layout() - for child in field.children(): - if child is not layout: - layout.remove(child) - child.deleteLater() - -# vim: tabstop=4 expandtab shiftwidth=4 diff -r 54380c79216e -r 4626e4174edf XSLForms/Resources/PyQtResources.py --- a/XSLForms/Resources/PyQtResources.py Sun Oct 12 19:28:30 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -#!/usr/bin/env python - -""" -Resources for use with PyQt. - -Copyright (C) 2005 Paul Boddie - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the Free -Software Foundation; either version 3 of the License, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. - -You should have received a copy of the GNU Lesser General Public License along -with this program. If not, see . -""" - -import XSLForms.Prepare -import XSLForms.Resources.PyQtCommon -import qt, qtui, qtxmldom -import os - -class XSLFormsResource(XSLForms.Resources.PyQtCommon.PyQtCommonResource): - - "An XSLForms resource for use with PyQt." - - widget_resources = {} - - def __init__(self, design_identifier): - self.factory = Factory(self.prepare_design(design_identifier)) - - def get_document(self, document_identifier): - return qtxmldom.parse(self.prepare_document(document_identifier)) - - def prepare_widget(self, design_identifier, widget_identifier, parent=None): - design_path = self.prepare_design(design_identifier) - fragment_name, widget_name = self.widget_resources[widget_identifier] - fragment_path = os.path.abspath(os.path.join(self.resource_dir, fragment_name)) - XSLForms.Prepare.ensure_qt_fragment(design_path, fragment_path, widget_name) - return qtui.QWidgetFactory.create(fragment_path, None, parent) - - def request_refresh(self, *kw, **args): - self.form_refresh(*kw, **args) - -class Factory: - - "A widget factory helper class." - - def __init__(self, ui_filename): - self.ui_filename = ui_filename - self.ui_doc = qtxmldom.parse(ui_filename) - - def connect(self, widget, obj): - - for connection in self.ui_doc.getElementsByTagName("connection"): - sender_name = self.get_text(connection.getElementsByTagName("sender")[0]).encode("utf-8") - signal_name = self.get_text(connection.getElementsByTagName("signal")[0]).encode("utf-8") - slot_name = self.get_text(connection.getElementsByTagName("slot")[0]).encode("utf-8") - - if widget.name() == sender_name: - senders = [widget] - else: - senders = self.find_widgets(widget, sender_name) - - slot = slot_name.split("(")[0] - if hasattr(obj, slot): - signal = qt.SIGNAL(signal_name) - for sender in senders: - qt.QObject.connect(sender, signal, getattr(obj, slot)) - - def get_text(self, node): - node.normalize() - return node.childNodes[0].nodeValue - - def find_widgets(self, widget, name): - widgets = [] - found = widget.child(name) - if found: - widgets.append(found) - for child in widget.children() or []: - widgets += self.find_widgets(child, name) - return widgets - -# vim: tabstop=4 expandtab shiftwidth=4 diff -r 54380c79216e -r 4626e4174edf XSLForms/Resources/PyQtWebResources.py --- a/XSLForms/Resources/PyQtWebResources.py Sun Oct 12 19:28:30 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -#!/usr/bin/env python - -""" -PyQt-compatible resources for use with WebStack. - -Copyright (C) 2005, 2007 Paul Boddie - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser General Public License as published by the Free -Software Foundation; either version 3 of the License, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. - -You should have received a copy of the GNU Lesser General Public License along -with this program. If not, see . -""" - -import XSLForms.Prepare -import XSLForms.Resources.PyQtCommon -import XSLForms.Resources.WebResources -import WebStack.Generic -import os -import libxml2dom - -class XSLFormsResource(XSLForms.Resources.WebResources.XSLFormsResource, - XSLForms.Resources.PyQtCommon.PyQtCommonResource): - - """ - An XSLForms resource supporting PyQt-compatible Web applications for use - with WebStack. - """ - - encoding = "utf-8" - widget_resources = {} - - def __init__(self, design_identifier): - self.factory = Factory() - self.default_design = design_identifier - - # NOTE: Filenames extended by string concatenation. - - self.template_resources = {} - self.init_resources = {} - for design_identifier, design_name in self.design_resources.items(): - self.template_resources[design_identifier] = (design_name + "_template.xhtml", design_name + "_output.xsl") - self.init_resources[design_identifier] = (design_name + "_template.xhtml", design_name + "_input.xsl") - - # Initialisation of connections - just a mapping from field names to - # methods in the Web version. - - self.method_resources = {} - for design_identifier, design_name in self.design_resources.items(): - design_path = self.prepare_design(design_identifier) - design_doc = libxml2dom.parse(design_path) - connections = {} - for connection in design_doc.xpath("UI/connections/connection"): - receiver = "".join([n.nodeValue for n in connection.xpath("receiver/text()")]) - if receiver == design_identifier: - sender = "".join([n.nodeValue for n in connection.xpath("sender/text()")]) - slot = "".join([n.nodeValue for n in connection.xpath("slot/text()")]) - slot = slot.split("(")[0] - connections[sender] = slot - self.method_resources[design_identifier] = connections - - # Initialisation of template fragments. - - self.in_page_resources = {} - for widget_identifier, (design_name, fragment_id) in self.widget_resources.items(): - self.in_page_resources[widget_identifier] = (design_name + "_output.xsl", fragment_id) - - # Refresh status - avoiding multiple refresh calls. - - self._refreshed = 0 - - # Resource methods. - - def prepare_output(self, design_identifier): - - """ - Prepare the output stylesheets using the given 'design_identifier' to - indicate which templates and stylesheets are to be employed in the - production of output from the resource. - - The 'design_identifier' is used as a key to the 'design_resources' and - 'template_resources' dictionary attributes. - - Return the full path to the output stylesheet for use with 'send_output' - or 'get_result'. - """ - - design_path = self.prepare_design(design_identifier) - template_filename, output_filename = self.template_resources[design_identifier] - output_path = os.path.abspath(os.path.join(self.resource_dir, output_filename)) - template_path = os.path.abspath(os.path.join(self.resource_dir, template_filename)) - XSLForms.Prepare.ensure_qt_template(design_path, template_path) - XSLForms.Prepare.ensure_stylesheet(template_path, output_path) - return output_path - - # PyQt compatibility methods. - - def get_document(self, document_identifier): - return libxml2dom.parse(self.prepare_document(document_identifier)) - - def prepare_widget(self, design_identifier, widget_identifier, parent=None): - fragment_name, widget_name = self.widget_resources[widget_identifier] - element = UINode(self.doc._node.ownerDocument.createElement(widget_name)) - - # NOTE: Creating an element which may not be appropriate. - - element._node.appendChild(self.doc._node.ownerDocument.createElement(widget_name + "_value")) - return element - - def child(self, name): - return self.doc.child(name) - - def sender(self): - return self._sender - - # PyQt structural methods. - - def form_init(self): - - "Initialise a newly-created form." - - raise NotImplementedError, "form_init" - - def form_populate(self): - - "Populate the values in a form." - - raise NotImplementedError, "form_populate" - - def form_refresh(self): - - "Refresh the form." - - raise NotImplementedError, "form_refresh" - - def request_refresh(self, *args, **kw): - - "Request a refresh of the form." - - if not self._refreshed: - self._refreshed = 1 - self.form_refresh(*args, **kw) - - # Standard XSLFormsResource method, overridden to handle presentation. - - def respond_to_form(self, trans, form): - - """ - Respond to the request described by the given transaction 'trans', using - the given 'form' object to conveniently retrieve field (request - parameter) information and structured form information (as DOM-style XML - documents). - """ - - self._refreshed = 0 - - # Ensure the presence of the template. - - self.prepare_output(self.default_design) - - # Remember the document since it is accessed independently elsewhere. - - doc = form.get_document(self.default_design) - if doc is None: - doc = form.new_document(self.default_design) - doc = self._get_initialised_form(doc) - self.doc = UINode(doc.xpath("*")[0]) - self.form_init() - else: - doc = self._get_initialised_form(doc) - self.doc = UINode(doc.xpath("*")[0]) - - self.form_populate() - - # Updates happen here. - - form.set_document(self.default_design, doc) - selectors = form.get_selectors() - connections = self.method_resources[self.default_design] - for selector_name, selector_values in selectors.items(): - if connections.has_key(selector_name): - slot = connections[selector_name] - if hasattr(self, slot): - - # Initialise the sender. - - for selector_value in selector_values: - # NOTE: Fake a special element to simulate the Qt widget hierarchy. - # NOTE: We could instead have set the underlying annotations for - # NOTE: selector-field differently, but that would be more work. - # NOTE: An alternative which works in certain cases is a new - # NOTE: attribute whose node is retained. - _sender = self.doc._node.ownerDocument.createElement("_sender") - self._sender = UINode(selector_value.appendChild(_sender)) - getattr(self, slot)() - - # Consistency is ensured and filtering enforced. - - self.request_refresh() - #print self.doc._node.toString("iso-8859-1") - - # Output is produced. - - attributes = trans.get_attributes() - encoding = attributes.get("encoding") or self.encoding or trans.default_charset - - trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", encoding)) - design_xsl = self.prepare_output(self.default_design) - self.send_output(trans, [design_xsl], doc._node) - - def _get_initialised_form(self, doc): - input_xsl = self.prepare_initialiser(self.default_design, init_enumerations=0) - return self.get_result([input_xsl], doc) - -class UINode: - - "A PyQt widget tree emulation node." - - def __init__(self, node): - self._node = node - - def add(self, node): - self._node.appendChild(node._node) - - def child(self, name): - nodes = self._node.xpath(name) - if len(nodes) > 0: - return UINode(nodes[0]) - else: - return None - - def children(self): - return [UINode(node) for node in self._node.childNodes] - - def count(self): - return len(self._node.childNodes) - - def currentText(self): - return self._node.getAttribute("value") - - def currentItem(self): - found = self._node.xpath("*[@value=current()/@value]") - if found: - return int(found.xpath("count(preceding-sibling::*)")) - else: - return 0 - - def deleteLater(self): - pass - - def insertItem(self, item, position=-1): - # NOTE: Names invented rather than being extracted from the schema. - new_element = self._node.ownerDocument.createElement(self._node.localName + "_enum") - new_element.setAttribute("value", item) - if position == -1: - self._node.appendChild(new_element) - else: - elements = self._node.xpath("*") - if position < len(elements) - 1: - self._node.insertBefore(new_element, elements[position]) - else: - self._node.appendChild(new_element) - - def layout(self): - return self - - def parent(self): - return UINode(self._node.parentNode) - - def removeItem(self, item): - elements = self._node.xpath("*") - if item < len(elements): - self._node.removeChild(elements[item]) - - def remove(self, item): - self._node.removeChild(item._node) - - def setCurrentItem(self, index): - pass # NOTE: Not implemented yet! - - def show(self): - pass - -class Factory: - - "A widget factory helper class." - - def connect(self, widget, obj): - - """ - Connection is done all at once by mapping field names to method names in - the resource object. - """ - - pass - - def find_widgets(self, widget, name): - - """ - Find within the given 'widget' (a DOM node) the widget with the given - 'name'. - """ - - return [UINode(node) for node in widget.doc._node.getElementsByTagName(name)] - -# vim: tabstop=4 expandtab shiftwidth=4 diff -r 54380c79216e -r 4626e4174edf docs/overview.html --- a/docs/overview.html Sun Oct 12 19:28:30 2008 +0200 +++ b/docs/overview.html Sun Oct 12 19:47:09 2008 +0200 @@ -1,15 +1,23 @@ - + + Creating Applications: An Overview - + +

Creating Applications: An Overview

+

This document contains an overview of the process of developing an XSLForms application. Since the only currently supported way of -deploying such an application is through the use of WebStack, it is necessary to install that package first before following the tutorial below.

The following steps briefly describe how to make a new application:
-

+deploying such an application is through the use of +WebStack, +it is necessary to install that package first before following the +tutorial below.

+ +

The following steps briefly describe how to make a new application:

+
  1. Create a directory to hold your files
  2. Design the structure of the form data
  3. @@ -22,5 +30,24 @@
  4. Adding multivalued fields
  5. Labelling multiple-choice values
  6. Recommendations and advice
  7. Adding in-page updates
  8. -

A topic-by-topic guide to XSLTools:

Some other resources:

- + + +

A topic-by-topic guide to XSLTools:

+ + + +

Some other resources:

+ + + + + diff -r 54380c79216e -r 4626e4174edf packages/ubuntu-feisty/python-xsltools/debian/control --- a/packages/ubuntu-feisty/python-xsltools/debian/control Sun Oct 12 19:28:30 2008 +0200 +++ b/packages/ubuntu-feisty/python-xsltools/debian/control Sun Oct 12 19:47:09 2008 +0200 @@ -11,7 +11,6 @@ Depends: ${python:Depends}, python-libxml2dom (>= 0.4.3), python-libxslt1 (>= 1.1.20-0ubuntu2), python-webstack (>= 1.2.5) Conflicts: python2.4-xsltools (<< 0.5-0ubuntu1) Replaces: python2.4-xsltools (<< 0.5-0ubuntu1) -Suggests: python-qtxmldom, python-qt3 (>= 3.17-0ubuntu3), qt3-designer XB-Python-Version: ${python:Versions} Description: Modules and packages for the development of XML/XSL-based applications XSLTools is a distribution providing modules and packages for the development diff -r 54380c79216e -r 4626e4174edf packages/ubuntu-hoary/python2.4-xsltools/debian/control --- a/packages/ubuntu-hoary/python2.4-xsltools/debian/control Sun Oct 12 19:28:30 2008 +0200 +++ b/packages/ubuntu-hoary/python2.4-xsltools/debian/control Sun Oct 12 19:47:09 2008 +0200 @@ -10,7 +10,6 @@ Architecture: all Depends: python2.4-libxml2dom (>= 0.4.3), python2.4-libxslt1 (>= 1.1.12), python2.4-webstack (>= 1.2.3), python2.4 Conflicts: python2.4-libxslt1 (1.1.17) -Suggests: python2.4-qtxmldom, python2.4-qt3 (>= 3.15), qt3-designer Description: Modules and packages for the development of XML/XSL-based applications XSLTools is a distribution providing modules and packages for the development of XML/XSL-based applications in Python, including Web-based applications,