[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r5757 - in trunk/gnue-forms: samples samples/tree src src/GFObjects src/
From: |
florin |
Subject: |
r5757 - in trunk/gnue-forms: samples samples/tree src src/GFObjects src/uidrivers/wx/widgets |
Date: |
Sat, 24 Apr 2004 16:49:58 -0500 (CDT) |
Author: florin
Date: 2004-04-24 16:49:57 -0500 (Sat, 24 Apr 2004)
New Revision: 5757
Added:
trunk/gnue-forms/samples/tree/
trunk/gnue-forms/samples/tree/README
trunk/gnue-forms/samples/tree/tree.gfd
trunk/gnue-forms/src/GFObjects/GFColsrc.py
trunk/gnue-forms/src/GFObjects/GFColumn.py
trunk/gnue-forms/src/GFObjects/GFLeaf.py
trunk/gnue-forms/src/GFObjects/GFTree.py
trunk/gnue-forms/src/uidrivers/wx/widgets/tree.py
Modified:
trunk/gnue-forms/src/GFObjects/__init__.py
trunk/gnue-forms/src/GFParser.py
Log:
added tree widget support (wx only for now...)
Added: trunk/gnue-forms/samples/tree/README
===================================================================
--- trunk/gnue-forms/samples/tree/README 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/samples/tree/README 2004-04-24 21:49:57 UTC (rev
5757)
@@ -0,0 +1,5 @@
+This is a GFD for testing the gnue tree widget.
+You might need to change it to match your DB design.
+Sorry, that's all I can do for you now... :-(
+
+Florin Boariu <address@hidden>
\ No newline at end of file
Added: trunk/gnue-forms/samples/tree/tree.gfd
===================================================================
--- trunk/gnue-forms/samples/tree/tree.gfd 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/samples/tree/tree.gfd 2004-04-24 21:49:57 UTC (rev
5757)
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="iso8859-1"?>
+
+<!-- GNUe-Designer (0.5.3.99)
+ Saved on: 2004-03-17 22:07:45 -->
+
+<form>
+ <options/>
+
+ <datasource name="dtsProdtype" connection="borg_test" primarykey="id"
table="prodtype"/>
+ <datasource name="dtsPerson" connection="borg_test" primarykey="id"
table="person"/>
+ <datasource name="dtsCurrency" connection="borg_test" primarykey="id"
table="currency"/>
+
+ <logic>
+ <block name="blkProdtype" datasource="dtsprodtype" rows="1">
+ <field name="fldId" field="id" required="Y" typecast="number"/>
+ <field name="fldDescription" field="description"/>
+ <field name="fldParent_id" field="parent_id" typecast="number"/>
+ <field name="fldInfo_table" field="info_table"/>
+ <field name="fldInfo_id" field="info_id" typecast="number"/>
+ </block>
+
+ <block name="blkPerson" datasource="dtsperson" rows="1">
+ <field name="fldId" field="id"/>
+ <field name="fldName" field="name"/>
+ </block>
+
+ <block name="blkCurrency" datasource="dtscurrency" rows="1">
+ <field name="fldId" field="id"/>
+ <field name="fldShort_name" field="short_name"/>
+ <field name="fldLong_name" field="long_name"/>
+ </block>
+
+ </logic>
+ <layout xmlns:Char="GNUe:Layout:Char" Char:height="12" Char:width="45">
+ <page name="Page">
+ <entry name="ntryDescription" block="blkProdtype" field="fldId"
+ Char:x="0" Char:y="1" Char:width="2" Char:height="1"/>
+
+ <entry name="ntryName" block="blkPerson" field="fldName"
+ Char:x="3" Char:y="0" Char:width="20" Char:height="1"
style="label"
+ hidden="false"/>
+
+ <entry name="ntryLong_name" block="blkCurrency" field="fldLong_name"
+ Char:x="3" Char:y="1" Char:width="20" Char:height="1"
style="label"
+ hidden="false"/>
+
+ <tree name="treeProd" block="blkProdtype"
+ fld_tblhint="fldInfo_table" fld_desc="fldDescription"
+ fld_id="fldId" fld_parentid="fldParent_id"
+ Char:height="11" Char:width="40" Char:x="3" Char:y="2">
+
+ <trigger type="POST-KIDSCHANGED" name="trigChanged"><![CDATA[
+#
+# composing first column entry for tree-nodes: ID sum of leaf-entries
+#
+node = treeProd.getIncompleteNode()
+sum = 0
+print "parent: ", node.desc
+for item in node.children:
+ print " child: ", item.desc
+ sum = sum + item.columns[0]
+node.columns[0] = sum
+treeProd.popIncompleteNode()
+
+]]></trigger>
+
+ <column name="id" align="right" field="fldId"/>
+ <column name="desc" align="left" field="fldDescription"/>
+
+ <leaf name="lfPerson" block="blkPerson" tblhint="person"
+ fld_desc="fldName" fld_id="fldId">
+ <colsrc covers="id" field="fldId"/>
+ <colsrc covers="desc" field="fldName"/>
+ </leaf>
+
+ <leaf name="lfCurrency" block="blkCurrency" tblhint="currency"
+ fld_desc="fldLong_name" fld_id="fldId">
+ <colsrc covers="id" field="fldId"/>
+ <colsrc covers="desc" field="fldShort_name"/>
+ </leaf>
+
+ </tree>
+ </page>
+ </layout>
+</form>
Added: trunk/gnue-forms/src/GFObjects/GFColsrc.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/GFColsrc.py 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/src/GFObjects/GFColsrc.py 2004-04-24 21:49:57 UTC (rev
5757)
@@ -0,0 +1,59 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2000-2004 Free Software Foundation
+#
+#
+# FILE:
+# GFColumn.py
+#
+# DESCRIPTION:
+"""
+Column data source information for GFLeaf
+"""
+# NOTES:
+#
+
+from GFValue import GFValue
+from GFObj import GFObj
+import string
+
+#
+# GFColsrc
+#
+class GFColsrc (GFObj):
+ def __init__(self, parent=None):
+ GFObj.__init__(self, parent, 'GFColsrc')
+
+ # Runtime Variables
+ self._inits = [self.initialize]
+
+ def _buildObject(self):
+ return GFObj._buildObject(self)
+
+ #
+ # Routines called during a phaseInit
+ #
+ def initialize(self):
+ self._form = self.findParentOfType ('GFForm')
+ self._leaf = self.findParentOfType ('GFLeaf')
+
+ self._leaf._colsrcList.append (self)
+ self._leaf._colsrcMap[self.covers] = self
+ print "added colsrc for: ", self.covers
+
Added: trunk/gnue-forms/src/GFObjects/GFColumn.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/GFColumn.py 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/src/GFObjects/GFColumn.py 2004-04-24 21:49:57 UTC (rev
5757)
@@ -0,0 +1,59 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2000-2004 Free Software Foundation
+#
+#
+# FILE:
+# GFColumn.py
+#
+# DESCRIPTION:
+"""
+Column information for GFTree
+"""
+# NOTES:
+#
+
+from GFValue import GFValue
+from GFObj import GFObj
+import string
+
+#
+# GFColumn
+#
+class GFColumn (GFObj):
+ def __init__(self, parent=None):
+ GFObj.__init__(self, parent, 'GFColumn')
+
+ # Runtime Variables
+ self._inits = [self.initialize]
+
+ def _buildObject(self):
+ return GFObj._buildObject(self)
+
+ #
+ # Routines called during a phaseInit
+ #
+ def initialize(self):
+ self._form = self.findParentOfType ('GFForm')
+ self._tree = self.findParentOfType ('GFTree')
+
+ self._tree._colList.append (self)
+ #self._tree._colMap[self.name] = self
+ print "added column: ", self.name
+
Added: trunk/gnue-forms/src/GFObjects/GFLeaf.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/GFLeaf.py 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/src/GFObjects/GFLeaf.py 2004-04-24 21:49:57 UTC (rev
5757)
@@ -0,0 +1,66 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2000-2004 Free Software Foundation
+#
+#
+# FILE:
+# GFTree.py
+#
+# DESCRIPTION:
+"""
+Leaf support (sub-tree pointing to another table)
+"""
+# NOTES:
+#
+
+from GFValue import GFValue
+from GFObj import GFObj
+import string
+
+#
+# GFLeaf
+#
+class GFLeaf (GFObj):
+ def __init__(self, parent=None):
+ GFObj.__init__(self, parent, 'GFLeaf')
+
+ # Runtime Variables
+ self._inits = [self.initialize]
+
+ self._colsrcMap = {} # column source information
+ self._colsrcList = [] # column source information
+
+ def _buildObject(self):
+ if not hasattr(self, 'rows') and hasattr(self,'visibleCount'):
+ self.rows = self.visibleCount
+ del self.visibleCount
+ return GFObj._buildObject(self)
+
+ #
+ # Routines called during a phaseInit
+ #
+ def initialize(self):
+ if hasattr (self, 'block'):
+ self._form = form = self.findParentOfType ('GFForm')
+ self._tree = self.findParentOfType ('GFTree')
+ self._blk = form._logic._blockMap[self.block]
+
+ if hasattr (self, 'tblhint'):
+ self._tree._leafMap[self.tblhint] = self
+
Added: trunk/gnue-forms/src/GFObjects/GFTree.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/GFTree.py 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/src/GFObjects/GFTree.py 2004-04-24 21:49:57 UTC (rev
5757)
@@ -0,0 +1,453 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2000-2004 Free Software Foundation
+#
+#
+# FILE:
+# GFTree.py
+#
+# DESCRIPTION:
+"""
+Logical tree support
+"""
+# NOTES:
+#
+
+from GFValue import GFValue
+from GFObj import GFObj
+from gnue.common import events
+from gnue.forms import GFDisplayHandler
+from GFBlock import GFBlock
+import string
+import copy
+
+#
+# internal tree node representation
+#
+class TreeNode:
+ def __init__(self, parent=None):
+ self.desc = "n/a" # description -- will appear in the tree view
+ self.id = 0 # database ID -- may be used to find the selected
value in the DB
+ self.parent = parent # parent node
+ self.children = [] # children list (to spawn a subtree)
+ self.columns = [] # values of the columns
+ self.leaf = None # GFLeaf reference
+ self.srcinfo = None # reference to info struct in GFTree._infoMap
+ self.recno = 0 # record number in the block
+ self._ui_obj = None # this one will be set to the TreeItem obj by the
UI
+
+ def getUiObj (self):
+ return self._ui_obj
+
+ def setUiObj (self, obj=None):
+ self._ui_obj = obj
+
+#
+# will hold information on the various sources (GFBlocks)
+# and column namings.
+#
+class NodeInfo:
+ def __init__(self):
+ self.block = None # the block we represent
+ self.fld_id = "" # ID field (primary key)
+ self.fld_desc = "" # Description field (Human readable)
+ self.fld_query = "" # Query field
+ self.pat_query = None # Query pattern
+
+#
+# GFTree
+#
+class GFTree (GFObj):
+ def __init__(self, parent=None):
+ GFObj.__init__(self, parent, 'GFTree')
+
+ # Default attributes (these may be replaced by parser)
+ self.Char__height = int(gConfigForms('widgetHeight'))
+
+ # Runtime Variables
+ self._inits = [self.initialize]
+
+ self._treeRoot = TreeNode() # here's our internal tree representation
+ self._leafMap = {} # block information for other tables (leaves)
+ self._colList = [] # column information for main tree
+
+ self._infoMap = {} # saves information on tree/leaves
sources/fields/blocks
+
+ self._incompleteNodes = [] # nodes that don't have columns yet set (but
their kids have)
+
+ self._loadList = [] # root items we have to load kids for (i.e. on
IdleEvent)
+
+ # note on columns:
+ # the ListView right next to the tree will hold
+ # be updated OnSelect to contain all children of
+ # the current selection. (alternative: update it
+ # to give the feel of an Qt-ListView
+ # (multi-column tree-view)
+
+ # note on leaves:
+ # leaves should have an attribute "big" or "don't show in tree"
+ # or whatever. it should prevent the items of a leafnode
+ # from being loaded into the tree and instead only be shown
+ # in the ListView (which might be implemented to have a decent
+ # caching). 'normal' tree items (no leafnodes) are assumed to be
+ # "small" (loadable in one single step, no caching needed...)
+
+ # operations on big leaves (like computation/loading of several
+ # columns) should be done in idleEvents.
+
+ # still need to specify decent column info
+
+ # trigger stuff
+ self._validTriggers = {
+ 'ON-SELECTED': 'On-Selected',
+ 'POST-KIDSCHANGED': 'Post-KidsChanged'
+ }
+
+ self._triggerGlobal = 1
+ self._triggerFunctions = {
+ 'setNodeCol': { 'function': self._trigSetNodeCol
},
+ 'getIncompleteNode': { 'function':
self._trigGetIncompleteNode },
+ 'popIncompleteNode': { 'function':
self._trigPopIncompleteNode }
+ }
+
+ #self._triggerProperties = {'name': {'get': self.getName} }
+
+ #
+ # builds _infoMap structure
+ #
+ def _buildInfoMap (self):
+ ## tree nodes info
+ i = NodeInfo()
+ i.block = self._blk
+ i.fld_id = self.fld_id
+ i.fld_desc = self.fld_desc
+ i.fld_query = self.fld_parentid
+ i.pat_query = '' # this only goes for the root node! FIXME!
+ self._infoMap[self.name] = i
+
+ ## leaf nodes info
+ for leaf in self._leafMap.values():
+ info = NodeInfo()
+ info.block = leaf._blk
+ info.fld_id = leaf.fld_id
+ info.fld_desc = leaf.fld_desc
+ info.fld_query = leaf.fld_id
+ info.pat_query = '*'
+ self._infoMap[leaf.name] = info
+
+ #
+ # returns the currently changing (i.e. no-column-values-set-yet) node
+ #
+ def _trigGetIncompleteNode (self):
+ if not self._incompleteNodes:
+ return None
+ else:
+ return self._incompleteNodes[0]
+
+ #
+ # pops the next incomplete node from the incomplete-list (-> node is
"complete" now)
+ #
+ def _trigPopIncompleteNode (self):
+ self._incompleteNodes.pop (0)
+
+ #
+ # sets the column text for the current node
+ #
+ def _trigSetNodeCol (self, col, val):
+ pass
+
+ def _buildObject(self):
+ if not hasattr(self, 'rows') and hasattr(self,'visibleCount'):
+ self.rows = self.visibleCount
+ del self.visibleCount
+ return GFObj._buildObject(self)
+
+ #
+ # Routines called during a phaseInit
+ #
+ def initialize(self):
+ if hasattr (self, 'block'):
+ self._form = form = self.findParentOfType ('GFForm')
+ self._orig_blk = form._logic._blockMap[self.block]
+ self._blk = self._orig_blk
+
+ # bad attempt to make a copy of a block... :-(
+ #self._blk = copy.copy (self._orig_blk)
+ #self._blk.initialize()
+
+ self.evtCtrl = self._form._instance.eventController
+ self.evtCtrl.registerEventListeners ({
+ 'uitreeItemSelected': self._onItemSelected,
+ 'uitreeItemExpanded': self._onItemExpanded,
+ 'uitreeItemCollapsed': self._onItemCollapsed
+ })
+
+ #
+ # OnExpand handler. params: node
+ #
+ def _onItemExpanded (self, event):
+ pass
+
+ #
+ # OnCollapse handler. params: node (surprise :-)
+ #
+ def _onItemCollapsed (self, event):
+ pass
+
+ #
+ # OnSelect handler. params: cursel, lastsel
+ #
+ def _onItemSelected (self, event):
+ try:
+ blk = event.cursel.parent.leaf._blk
+ blk.jumpRecord (event.cursel.recno)
+ blk = event.lastsel.parent.leaf._blk
+ except AttributeError:
+ pass
+
+ self.processTrigger ('ON-SELECTED')
+
+ #
+ # build tree from DB
+ #
+ def buildTree (self):
+
+ self._buildInfoMap()
+
+ self._treeRoot.id = 0
+ self._treeRoot.desc = "kick me!"
+ self._treeRoot.srcinfo = self._infoMap[self.name]
+
+ #self.__populate_tree (self._treeRoot)
+
+ self.__pop_query (self._treeRoot, 0)
+ self.__pop_load_init (self._treeRoot)
+ self.__pop_load_part (self._treeRoot, -1)
+ self.__pop_load_finish (self._treeRoot)
+
+ return self._treeRoot
+
+ #
+ # wrapper function for __populate_base
+ # to populate tree nodes
+ #
+ def __populate_tree (self, rootnode):
+ self.__populate_base (rootnode, self._blk,
+ self.fld_id, self.fld_desc,
+ self.fld_parentid, rootnode.id)
+
+ # wrapper function for __populate_base
+ # to populate leaf nodes
+ def __populate_leaf (self, rootnode):
+ leaf = rootnode.leaf
+ self.__populate_base (rootnode, leaf._blk,
+ leaf.fld_id, leaf.fld_desc,
+ leaf.fld_id, '*')
+
+ #
+ # starts query for items to populate a (sub)tree with.
+ # parameters:
+ # rootnode: the root node
+ # pat_query: select pattern
+ #
+ def __pop_query (self, rootnode, val_query):
+ blk = rootnode.srcinfo.block
+ fld_query = blk._fieldMap[rootnode.srcinfo.fld_query]
+ #print "query for ", rootnode.srcinfo.fld_query, "=", val_query
+ blk.initQuery()
+ fld_query.setValue (val_query)
+ blk.processQuery()
+
+ #
+ # initializes load phase for tree items
+ # parameters:
+ # rootnode: root node to add items to
+ #
+ def __pop_load_init (self, rootnode):
+ rootnode.srcinfo.block.firstRecord()
+ self._loadList.append (rootnode)
+
+ #
+ # loads given number of tree items (call __pop_load_init first!)
+ # nr: maximum number of items to read
+ # returns the number of items actually loaded
+ #
+ def __pop_load_part (self, rootnode, nr):
+ blk = rootnode.srcinfo.block
+ fld_id = blk._fieldMap[rootnode.srcinfo.fld_id]
+ fld_desc = blk._fieldMap[rootnode.srcinfo.fld_desc]
+
+ total = nr
+ do_loop = not blk._resultSet.isLastRecord()
+
+ while nr != 0 and do_loop:
+ ## main item stuff
+ node_data = TreeNode (rootnode)
+ node_data.id = fld_id.getValue()
+ node_data.desc = fld_desc.getValue()
+ node_data.children = []
+ node_data.recno = blk._currentRecord
+ node_data.columns = []
+ node_data.leaf = None
+ node_data.srcinfo = self._infoMap[self.name] # goes for tree nodes
+
+ ## column stuff (pretty clumsy... still waiting for enlightenment)
+ if blk == self._blk: # if this is tree-node (!= leaf-node)...
+ leaf_tbl = blk._fieldMap[self.fld_tblhint].getValue()
+ if leaf_tbl:
+ node_data.leaf = self._leafMap[leaf_tbl]
+ node_data.srcinfo = self._infoMap[node_data.leaf.name]
+ for ci in self._colList: # add columns to the tree item
+ node_data.columns.append (blk._fieldMap[ci.field].getValue())
+ else:
+ #node_data.srcinfo = self._infoMap[node_data.leaf.name]
+ for ci in self._colList: # add column to a leaf
+ colsrc = rootnode.leaf._colsrcMap[ci.name]
+ node_data.columns.append (blk._fieldMap[colsrc.field].getValue())
+
+ rootnode.children.append (node_data)
+
+ ## while-loop stuff
+ nr = nr - 1
+ do_loop = not blk._resultSet.isLastRecord()
+ blk.nextRecord()
+
+ # while-loop ends.
+
+ self.evtCtrl.dispatchEvent (events.Event ('gftreeAppendKids',
+ root=rootnode, kids=rootnode.children,
+ _form=self._form))
+
+ return total-nr
+
+ #
+ # ends load phase for tree items
+ #
+ def __pop_load_finish (self, rootnode):
+ self._loadList.remove (rootnode)
+
+ ## populate sub-trees/leaves
+ if rootnode.srcinfo.block == self._blk: # if this is _not_ a leaf-list
+ for n in rootnode.children:
+ pat = '*'
+ if n.leaf == None: pat = n.id
+ self.__pop_query (n, pat)
+ self.__pop_load_init (n)
+ self.__pop_load_part (n, -1)
+
+ # trigger KidsChanged -- that should fill in column values for tree nodes
+ if rootnode != self._treeRoot:
+ self._incompleteNodes.append (rootnode)
+ self.processTrigger ('POST-KIDSCHANGED')
+
+ #
+ # aborts load phase for tree items
+ #
+ def __pop_load_cancel (self, rootnode, blk):
+ pass
+
+ #
+ # functions populates list subnode 'rootnode' with
+ # items from DB with items in the DB that have parent id 'rootid'
+ #
+ # (or populates with items from another table that match the
+ # val_query in fld_query => leafnodes)
+ #
+ # fld_id: ID field (primary key). will be used to jump to records (??)
+ # fld_desc: human readable information field
+ # fld_query: "use it or not"-decision information field
+ # val_query: "use it or nor"-decision query string
+ # blk: block to use
+ # rootnode: root node to insert items into (see above for type)
+ #
+ def __populate_base (self, rootnode, blk, fld_id, fld_desc, fld_query,
val_query):
+
+ blk.initQuery()
+ blk._fieldMap[fld_query].setValue (val_query)
+ blk.processQuery()
+
+ blk.firstRecord()
+ go = not blk._resultSet.isLastRecord()
+ while go == True:
+ item = blk
+ node_data = TreeNode (rootnode)
+ node_data.desc = item._fieldMap[fld_desc].getValue()
+ node_data.id = item._fieldMap[fld_id].getValue()
+ node_data.parent = rootnode
+ node_data.children = []
+ node_data.columns = []
+ node_data.recno = blk._currentRecord
+ node_data.leaf = None
+
+ # if this is a leafnode (main tree item which
+ # spawns a sub-tree from another table)
+ if blk == self._blk:
+ leaf_tbl = item._fieldMap[self.fld_tblhint].getValue()
+ if leaf_tbl:
+ node_data.leaf = self._leafMap[leaf_tbl]
+
+ # load column information for tree-nodes and leaf-nodes
+ for ci in self._colList:
+ node_data.columns.append (item._fieldMap[ci.field].getValue())
+
+ else:
+
+ # load columns for leaf-ends
+ #for ci in rootnode.leaf._colsrcList:
+ # node_data.columns.append (item._fieldMap[ci.field].getValue())
+ for ci in self._colList:
+ colsrc = rootnode.leaf._colsrcMap[ci.name]
+ node_data.columns.append (item._fieldMap[colsrc.field].getValue())
+
+ rootnode.children.append (node_data)
+
+ go = not blk._resultSet.isLastRecord()
+ if go:
+ blk.nextRecord()
+
+ # end 'while'
+
+ self.evtCtrl.dispatchEvent (events.Event ('gftreeAppendKids',
+ root=rootnode, kids=rootnode.children,
+ _form=self._form))
+
+ ## populate sub-trees/leaves
+ if blk == self._blk:
+ for n in rootnode.children:
+ if n.leaf == None:
+ self.__populate_tree (n)
+ else:
+ self.__populate_leaf (n)
+
+ # trigger KidsChanged -- that should fill in column values for tree nodes
+ if rootnode != self._treeRoot:
+ self._incompleteNodes.append (rootnode)
+ self.processTrigger ('POST-KIDSCHANGED')
+
+ #
+ # removes the children of a node (and sends rm event to ui)
+ #
+ def __remove_kids (self, rootnode):
+ for item in rootnode.children:
+ if item.children:
+ self.__remove_kids (item)
+ self.evtCtrl.dispatchEvent (events.Event ('gftreeRemoveKids',
+ root=rootnode, _form=self._form))
+ for item in rootnode.children:
+ rootnode.children.remove (item)
Modified: trunk/gnue-forms/src/GFObjects/__init__.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/__init__.py 2004-04-21 14:42:03 UTC (rev
5756)
+++ trunk/gnue-forms/src/GFObjects/__init__.py 2004-04-24 21:49:57 UTC (rev
5757)
@@ -31,6 +31,10 @@
"GFOption",
"GFScrollBar",
"GFBox",
+ "GFTree",
+ "GFLeaf",
+ "GFColumn",
+ "GFColsrc",
"GFOptions",
"GFValue",
"GFButton",
Modified: trunk/gnue-forms/src/GFParser.py
===================================================================
--- trunk/gnue-forms/src/GFParser.py 2004-04-21 14:42:03 UTC (rev 5756)
+++ trunk/gnue-forms/src/GFParser.py 2004-04-24 21:49:57 UTC (rev 5757)
@@ -688,6 +688,111 @@
'ParentTags': ('page',),
'Description': 'TODO' },
+ 'tree': {
+ 'BaseClass': GFObjects.GFTree,
+ 'Attributes': {
+ 'name': {
+ 'Unique': True,
+ 'Typecast': GTypecast.name,
+ 'Description': 'Tree Widget.' },
+ 'rows': {
+ 'Typecast': GTypecast.whole,
+ 'Description': 'Overrides the rows setting defined at the block
level. ' },
+ 'rowSpacer': {
+ 'Typecast': GTypecast.whole,
+ 'Label': _('Row Spacing'),
+ 'Description': 'Overriders the rowSpace setting defined at the
block level.' },
+ 'block': {
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'References': 'block.name',
+ 'Description': 'The name of the block the tree ties to.' },
+ 'fld_desc': {
+ 'Label': _('Description field'),
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'Description': 'The visible text of the TreeViewItem' },
+ 'fld_id': {
+ 'Label': _('Own ID field'),
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'Description': 'The field containing the TreeViewItem ID' },
+ 'fld_parentid': {
+ 'Label': _('Parent ID field'),
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'Description': 'The field containing the TreeViewItem parent' },
+ 'fld_tblhint': {
+ 'Label': _('Table hint for leaf tables'),
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'Description': 'The field containing the table-hint for leaves'
} },
+ 'Positionable': True,
+ 'ParentTags': ('page',),
+ 'Description': 'Tree/List-View of a table' },
+
+ 'leaf': {
+ 'BaseClass': GFObjects.GFLeaf,
+ 'Attributes': {
+ 'name': {
+ 'Unique': True,
+ 'Typecast': GTypecast.name,
+ 'Description': 'Leaf of the Tree Widget' },
+ 'block': {
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'References': 'block.name',
+ 'Description': 'Block used for db operations' },
+ 'fld_id': {
+ 'Label': _('ID of a field'), # TODO: we need some kind of
restriction
+ 'Typecast': GTypecast.name, # TODO: on which entries we
pick...
+ 'Required': True },
+ 'fld_desc': {
+ 'Label': _('Description field'),
+ 'Typecast': GTypecast.name,
+ 'Required': True },
+ 'tblhint': {
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'Description': 'Table of this leaf' } },
+ 'Positionable': True,
+ 'ParentTags': ('tree',),
+ 'Description': 'Leaf information of a tree view' },
+
+ 'column': {
+ 'BaseClass': GFObjects.GFColumn,
+ 'Attributes': {
+ 'name': {
+ 'Unique': True,
+ 'Required': True,
+ 'Typecast': GTypecast.name,
+ 'Description': 'Column info for leaves/trees' },
+ 'align': {
+ 'Typecast': GTypecast.name,
+ 'Required': True,
+ 'Description': 'Contents alignment: left/right/center' },
+ 'field': { # we'll have to remove this, or replace it with some
more general source
+ 'Typecast': GTypecast.name,
+ 'Description': 'Field to get column text from' } },
+ 'Positionable': False,
+ 'ParentTags': ('tree',),
+ 'Descrpition': 'Column information for trees' },
+
+ 'colsrc': {
+ 'BaseClass': GFObjects.GFColsrc,
+ 'Attributes': {
+ 'covers': {
+ 'Unique': True,
+ 'Required': True,
+ 'Typecast': GTypecast.name,
+ 'Description': 'Specifies the column this belongs to' },
+ 'field': {
+ 'Typecast': GTypecast.name,
+ 'Description': 'Field to get column text from' } },
+ 'Positionable': False,
+ 'ParentTags': ('leaf',),
+ 'Descrpition': 'Column information for trees' },
+
'options': {
'BaseClass': GFObjects.GFOptions,
'UsableBySiblings': True,
Added: trunk/gnue-forms/src/uidrivers/wx/widgets/tree.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/wx/widgets/tree.py 2004-04-21 14:42:03 UTC
(rev 5756)
+++ trunk/gnue-forms/src/uidrivers/wx/widgets/tree.py 2004-04-24 21:49:57 UTC
(rev 5757)
@@ -0,0 +1,227 @@
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2000-2004 Free Software Foundation
+#
+# FILE:
+# UIwxpython.py
+#
+# DESCRIPTION:
+# A wxPython based user interface driver for GNUe forms.
+#
+# NOTES:
+#
+from wxPython.wx import *
+
+from gnue.forms.uidrivers.wx.widgets._base import UIHelper
+from gnue.forms.uidrivers.wx.common import wxEncode
+from gnue.common import events
+from gnue.forms.uidrivers.wx.common import _eventObjTowxWindow, wxEncode,
wxDecode
+from types import *
+
+import thread
+
+import string
+
+#
+# UITree
+#
+# Widget set specific function that creates a single instance of a tree
+#
+class UITree(UIHelper):
+
+ def _createWidget(self, event, spacer):
+ self._gftree = object = event.object
+ app = wx.wxGetApp()
+ self._eventHandler = self._sendEvt = event.eventHandler
+ self.evtCtrl = object._form._instance.eventController
+
+ self.splitter = wxSplitterWindow (event.container, -1,
+ wxPoint (object.Char__x *
event.widgetWidth,
+ (object.Char__y + spacer +
(spacer*object._gap)) * event.widgetHeight),
+ wxSize (self.itemWidth, self.itemHeight))
+
+ self.treeWg = wxTreeCtrl (self.splitter, -1)
+ self.listWg = wxListCtrl (self.splitter, -1, wxPoint (0, 0), wxSize (0, 0),
+ wxLC_REPORT | wxLC_SINGLE_SEL)
+ self.listWg_root = None # root TreeNode of the current GFTree selection
+
+ self.splitter.SplitVertically (self.treeWg, self.listWg)
+ self.splitter.SetMinimumPaneSize (20)
+
+ EVT_TREE_SEL_CHANGED (app, self.treeWg.GetId(), self._onTreeSelected)
+ EVT_TREE_ITEM_ACTIVATED (app, self.treeWg.GetId(), self._onTreeActivated)
+ EVT_TREE_ITEM_EXPANDED (app, self.treeWg.GetId(), self._onTreeExpanded)
+ EVT_TREE_ITEM_COLLAPSED (app, self.treeWg.GetId(), self._onTreeCollapsed)
+
+ EVT_LIST_ITEM_SELECTED (app, self.listWg.GetId(), self._onListSelected)
+
+ #EVT_IDLE (self.treeWg, self.__onIdle)
+
+ self.evtCtrl.registerEventListeners ({
+ 'gftreeItemSelected': self._gfItemSelected,
+ 'gftreeAppendKids': self._gfAppendKids,
+ 'gftreeRemoveKids': self._gfRemoveKids
+ #'gftreeDetailView': self._gfDetailView
+ })
+
+ object.buildTree()
+
+ wx_align = {'left': wxLIST_FORMAT_LEFT,
+ 'center': wxLIST_FORMAT_CENTER,
+ 'right': wxLIST_FORMAT_RIGHT }
+
+ # insert description column -- this col is actually not part of
+ # the XML widget description. it is a work-around for missing
+ # column support in wx-treeviews (as is this whole treeview/listview
+ # thingy)
+ self.listWg.InsertColumn (0, _("Node"))
+ cnr = 1
+ for col in object._colList:
+ self.listWg.InsertColumn (cnr, col.name, wx_align[col.align])
+ cnr = cnr + 1
+
+ return self.treeWg
+
+ #
+ # shows the kids of the selected node in TreeView in the ListView
+ #
+ def showDetail (self, node):
+ self.listWg.DeleteAllItems()
+ nr = 0
+ self.listWg_root = node
+
+ # go though the children
+ for item in node.children:
+ self.listWg.InsertStringItem (nr, item.desc)
+
+ # add default column -- we always have this one as first column :-)
+ self.listWg.SetStringItem (nr, 0, item.desc)
+
+ # add column labels for current item
+ cnr = 1
+ for col in item.columns:
+ label = "n/a"
+ if isinstance(col, UnicodeType):
+ label = wxEncode (col)
+ else:
+ label = str (col)
+ self.listWg.SetStringItem (nr, cnr, label)
+ cnr = cnr + 1
+
+ nr = nr + 1
+
+ #
+ # called by gfobj after (sub)tree items are added and need to be displayed
+ #
+ def _gfAppendKids (self, event):
+ if not event.root.getUiObj(): # we don't have a root node... adding it.
+ wxroot = self.treeWg.AddRoot (event.root.desc)
+ self.treeWg.SetPyData (wxroot, event.root)
+ event.root.setUiObj (ui_info (wxroot))
+
+ root = event.root.getUiObj().tree_item
+ old = self.treeWg.GetChildrenCount (root, False)
+
+ for gfi in event.kids[old:]:
+ wxi = self.treeWg.AppendItem (root, gfi.desc)
+ self.treeWg.SetPyData (wxi, gfi)
+ gfi.setUiObj (ui_info(wxi))
+
+ #
+ # called by gfobj before (sub)tree items are deleted and need to be erased
+ #
+ def _gfRemoveKids (self, event):
+ for gfi in event.root.children:
+ self.treeWg.SetPyData (gfi.getUiObj().tree_item, None)
+
+ self.treeWg.DeleteChildren (event.root.getUiObj().tree_item)
+
+ def _gfItemSelected (selv, event):
+ print "gf item selected!"
+
+ def _onIdle(self, event):
+ pass
+
+ #
+ # list selected -- select same item in TreeView
+ #
+ def _onListSelected (self, event):
+ node = self.listWg_root.children[event.GetIndex()]
+ tsel = self.treeWg.GetSelection()
+ if tsel and self.treeWg.GetPyData(tsel) != node:
+ self.treeWg.SelectItem (node.getUiObj().tree_item)
+
+ #
+ # called when user selects an item -- passes event to gfobj
+ #
+ def _onTreeSelected (self, event):
+
+ csel = self.treeWg.GetPyData (event.GetItem())
+
+ if csel.children: # build detail list
+ self.showDetail (csel)
+ else: # select item in already built
detail list
+ if csel.parent != self.listWg_root: # user switched to another leafnode
+ self.showDetail (csel.parent) # => rebuild detail list
+ pass # wxListCtrl won't give me any function to change selection :-(
+
+ self._sendEvt (events.Event ('uitreeItemSelected',
+ cursel = self.treeWg.GetPyData (event.GetItem()),
+ lastsel = self.treeWg.GetPyData (event.GetOldItem()),
+ _form = self._gftree._form))
+
+ #event.Skip() -- don't skip, it actually comes in handy :-)
+
+ #
+ # the new, digitally remastered, thx enhanced _onTreeActivated handler :-)
+ #
+ def _onTreeActivated (self, event):
+ #print "activated: ", self.treeWg.GetPyData (event.GetItem()).desc
+ thread.start_new_thread (thread_proc, ())
+ pass
+
+ #
+ # on item expanded/collapsed we need to update the list view
+ #
+ def _onTreeExpanded (self, event):
+ self._sendEvt ('uitreeItemExpanded',
+ node=self.treeWg.GetPyData(event.GetItem()),
+ _form=self._gftree._form)
+
+ def _onTreeCollapsed (self, event):
+ self._sendEvt ('uitreeItemCollapsed',
+ node=self.treeWg.GetPyData(event.GetItem()),
+ _form=self._gftree._form)
+
+#
+# stores ui specific information about tree nodes
+#
+class ui_info:
+ def __init__ (self, t=None, l=-1):
+ self.tree_item = t
+ self.list_index = l
+
+def thread_proc():
+ print "foo"
+
+configuration = {
+ 'baseClass' : UITree,
+ 'provides' : 'GFTree',
+ 'container' : 0,
+ }
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r5757 - in trunk/gnue-forms: samples samples/tree src src/GFObjects src/uidrivers/wx/widgets,
florin <=