diff --git a/models/db_database.py b/models/db.py
similarity index 100%
rename from models/db_database.py
rename to models/db.py
diff --git a/models/db_defaults.py b/models/defaults.py
similarity index 100%
rename from models/db_defaults.py
rename to models/defaults.py
diff --git a/models/plugin_dbui.py b/models/plugin_dbui.py
index 8cda8f7d713329c8d711da6176669e1b9e0c0ac9..c3cf7c10b2b7f180ecf51425fd60da220a40e381 100644
--- a/models/plugin_dbui.py
+++ b/models/plugin_dbui.py
@@ -10,7 +10,7 @@ plugins = PluginManager('dbui',
                         field_modifiers={},
                         form_modifiers={},
                         grid_modifiers={},
-                        viewport_modifiers={},
+                        viewport_modifiers=Storage(extjs={}),
                         script_path='static/scripts',
                         user_src_path='static/src',
                         user_libmin=None)
@@ -28,8 +28,9 @@ directSvc.debug = session.debug
 
 # register method available on the client side
 @directSvc.register
-def getConfiguration(tablename, xtype): 
-    return cfgSvc.get_configuration(tablename, xtype)
+def getForm(table): 
+    return cfgSvc.get_form(table)
+
 
 @directSvc.register
 def getTree(node): 
diff --git a/models/db_widgets.py b/models/widgets.py
similarity index 94%
rename from models/db_widgets.py
rename to models/widgets.py
index 66c5f3b5af7d8ab53b98dd61b04fcaccfa0980dc..24b228544cd78d3913df150ae1c7a480fe59ce4c 100755
--- a/models/db_widgets.py
+++ b/models/widgets.py
@@ -8,27 +8,6 @@
 from datetime import datetime
 dbui = local_import('plugin_dbui')
 
-#
-# The navigation tree embedded in the viewport
-# hide some tables depending on the user role
-#
-
-formNode = dbui.NodeDB(T('Forms'),
-                       tables=db.tables,
-                       widget='xform')
-
-gridNode = dbui.NodeDB(T('Tables'),
-                       tables=db.tables,
-                       widget='xgrid')
-
-reportNode = dbui.NodeURL(T('Reports'),
-                       leaves=['report_1'],
-                       urls=[URL(c="reports", f="report_1")],
-                       widget='panel')
-
-viewportModifier = dbui.ViewportModifier()
-viewportModifier.add_node(formNode, gridNode, reportNode)
-
 #
 # add plugin to all grids
 #
@@ -196,3 +175,19 @@ filters = [('year', '==', T('select publication for a given year')),
 
 gridModifier.set_filters(*filters,
                          width=300)
+
+
+#
+# The navigation tree embedded in the viewport
+# hide some tables depending on the user role
+#
+formNode = dbui.Node(T('Forms'), db.tables, cfgSvc.get_form)
+gridNode = dbui.Node(T('Tables'), db.tables, cfgSvc.get_grid)
+
+reportNode = dbui.Node(T('Reports'),
+                       {'report_1': URL(c="reports", f="report_1")},
+                       dbui.cfg_url_panel)
+
+viewportModifier = dbui.ViewportModifier()
+viewportModifier.add_node(formNode, gridNode, reportNode)
+
diff --git a/modules/plugin_dbui/__init__.py b/modules/plugin_dbui/__init__.py
index 51090280d1c76b5f9ed171723b0b61f5495d34ff..79d7762288d154b9c30ae23ac39424d66105c3c5 100755
--- a/modules/plugin_dbui/__init__.py
+++ b/modules/plugin_dbui/__init__.py
@@ -16,5 +16,5 @@ from helper import (get_js_files,
                     get_script_path)
 from mapper import map_default, map_tabpanel
 from modifier import Spacer, Widget
-from navtree import NodeDB, NodeURL
+from navtree import Node, cfg_url_panel
 from viewportmodifier import ViewportModifier
\ No newline at end of file
diff --git a/modules/plugin_dbui/cfgsvc.py b/modules/plugin_dbui/cfgsvc.py
index 952518b4fde1431e3a82794c61ec723de7dae6cd..af6e00384be3b8c5974249ebd79b0cabfa2178f9 100755
--- a/modules/plugin_dbui/cfgsvc.py
+++ b/modules/plugin_dbui/cfgsvc.py
@@ -227,26 +227,6 @@ class CfgSvc(BaseSvc):
         return self._foreign.get_foreign_data(tablename, fieldname)
 
     
-    def _get_form(self, tablename):
-        """Build the configuration options for the App.form.FormPanel
-        associated to the database table tablename.
-        
-        Return a dictionary.
-        
-        """
-        T = self.environment['T']
-        
-        cfg = {'items': self._get_form_items(tablename),
-               'store': STOREID % tablename,
-               'xtype': 'xform'}
-        
-        form_modifiers = self.environment['plugins'].dbui.form_modifiers
-        if tablename in form_modifiers:
-            cfg.update(form_modifiers[tablename].extjs)
-            
-        return cfg 
-
-        
     def _get_form_composite_field(self, tablename, fieldname):
         """Build the configuration dictionary for a composite field.
         
@@ -392,36 +372,6 @@ class CfgSvc(BaseSvc):
         return formitems
 
 
-    def _get_grid(self, tablename):
-        """Build the configuration options for the Ext.grid.GridPanel
-        widget associated to the database table tablename.
-        
-        Return a dictionary
-        
-        """
-        T = self.environment['T']
-
-        cfg = {'columns': self._get_columns_model(tablename),
-               'frame': False,
-               'store': STOREID % tablename,
-               'viewConfig': {'forceFit': True},
-               'xtype': 'xgrid'}
-                
-        # handle the user configuration option for Ext.grid.GridPanel
-        grid_modifiers = self.environment['plugins'].dbui.grid_modifiers
-        if tablename in grid_modifiers:
-            cfg.update(grid_modifiers[tablename].extjs)
-
-        # grid with filter
-        filter = self._get_grid_filter(tablename)
-        if filter:
-            cfg = {'filterCfg': filter,
-                   'gridCfg':  dict(cfg),
-                   'xtype': 'xgridwithfilter'}
-            
-        return cfg
-
-
     def _get_grid_filter(self, tablename):
         """ Generate configuration object for the grid filter
         
@@ -492,23 +442,54 @@ class CfgSvc(BaseSvc):
         return self._set.is_set_field(tablename, fieldname)
 
         
-    def get_configuration(self, tablename, xtype):
-        """Build the configuration for the widget associated to 
-        the database table tablename. 
-        
-        The widget is defined by the ExtJS xtype parameters.
-        (see the Ext.Component documentation for more information).
+    def get_form(self, tablename):
+        """Build the configuration options for the App.form.FormPanel
+        associated to the database table tablename.
         
         Return a dictionary.
         
-        """ 
-        if xtype in ('form', 'xform'):
-            return self._get_form(tablename)
+        """
+        T = self.environment['T']
+        
+        cfg = {'items': self._get_form_items(tablename),
+               'store': STOREID % tablename,
+               'xtype': 'xform'}
         
-        if xtype in ('grid', 'xgrid', 'xgridwithfilter'):
-            return self._get_grid(tablename)
+        form_modifiers = self.environment['plugins'].dbui.form_modifiers
+        if tablename in form_modifiers:
+            cfg.update(form_modifiers[tablename].extjs)
+            
+        return cfg 
+
+        
+    def get_grid(self, tablename):
+        """Build the configuration options for the Ext.grid.GridPanel
+        widget associated to the database table tablename.
+        
+        Return a dictionary
         
-        return None
+        """
+        T = self.environment['T']
+
+        cfg = {'columns': self._get_columns_model(tablename),
+               'frame': False,
+               'store': STOREID % tablename,
+               'viewConfig': {'forceFit': True},
+               'xtype': 'xgrid'}
+                
+        # handle the user configuration option for Ext.grid.GridPanel
+        grid_modifiers = self.environment['plugins'].dbui.grid_modifiers
+        if tablename in grid_modifiers:
+            cfg.update(grid_modifiers[tablename].extjs)
+
+        # grid with filter
+        filter = self._get_grid_filter(tablename)
+        if filter:
+            cfg = {'filterCfg': filter,
+                   'gridCfg':  dict(cfg),
+                   'xtype': 'xgridwithfilter'}
+            
+        return cfg
 
 
     def get_jsonstore(self, tablename):
diff --git a/modules/plugin_dbui/navtree.py b/modules/plugin_dbui/navtree.py
index 1a5bc76c205d113004bf879d32d63ad25ea93489..2421756309e64613acc8ab0b5d7d960bdc8cd520 100644
--- a/modules/plugin_dbui/navtree.py
+++ b/modules/plugin_dbui/navtree.py
@@ -7,134 +7,95 @@ __version__ = "$Revision$"
 import locale
 from gluon import current
 
-MSG_TEXT_WIDGET = 'The argument text and widget have to be defined.'
 
-
-class NodeBase(object):
+def cfg_url_panel(key, url):
+    """Return the configuration object for an Ext.Panel
+    which autolad an url.
     
-    def __init__(self, text):
-        """The argument text defines the name of the node.
-        
-        """
-        self.text = text
-        self.children= []
+    """
+    return {'autoLoad': url, 'preventBodyReset': True, 'xtype': 'panel'}
+
 
+class Node(object):
+    """Node associating a leaf to a widget.
+    
+    Leaves can be a list of database table or dicitonary
+    assoicating a key with an url. In the latter case leave name
+    are the dictionary key.
+    
+    Leaf names are translated and sorted by alphabetic order.
+    Some my be hidden depending on the context.
 
-    def add_children(self, text='', widget='', **kwargs):
-        """ Add a child to the node.
+    We use a configurator to get the confgiration object of the
+    target widget. It is a function getting the leave names, its
+    attributes (dictionary value) and returning a dictionary
+    
+    """
+    def __init__(self, text, leaves, configurator, hidden=[]):
+        """Constructor of the node
         
                 text
-                    the name of the leaf
+                    name of the node appearing in the viewport
                     
-                widget
-                    the ExtJS widget type associate to the leaf
+                leaves
+                    list of leaves names
+                    or dictionary where keys define leave names
                     
-                kwargs
-                    additional attributes of the node
-
-        """
-        if not (text and widget):
-            raise NodeException(MSG_TEXT_WIDGET)
-        
-        di = {'leaf': True,
-              'text': text,
-              'widget': widget}
+                configurator
+                    Reference to a function accepting either a leave name
+                    or a leave name and the dictionary value. The function
+                    return the configuration dictionary for the ExtJS widget. 
+                    The function defines the type of widget.
+                    
+                hidden
+                    List of leaves to be hidden. It contains leaves names
                 
-        di.update(**kwargs)        
-        self.children.append(di)
-
-
-    def get_node(self):
-        """Return the configuration dictionary for the node.
-        
         """
-        return {'text': self.text, 'children': self.children}
-
-
-class NodeException(BaseException): pass
-
-
-class NodeDB(NodeBase):
-    """Navigation node where each leaf is associate to a database table.
-    
-    ExtJS widget can be associated to each table either globally
-    or individually using widget and widgets arguments respectively.
-    The widget identifier is its ExtJS type: xform, xgrid, ...
-    
-    Some tables my be hidden depending on the context using hidden
-    argument.
-    
-    Tables are sorted by alphabetic order.
-    Name of the table appearing in the tree are translated.
-    
-    """
-    
-    def __init__(self, text, tables=[], widget='', hidden=[], widgets={}):
+        self.text = text
+        self.children= []
 
+        # translator
         T = current.T
         
-        NodeBase.__init__(self, text)
-
-        # order table in alphabetic order according to local setting
-        # the local setting is defined in the model as the time as the language
-        tablesCvt = {}
-        for el in tables:
-            tablesCvt[T(el)] = el
+        # converter to order leaves in alphabetic order 
+        # according to local setting
+        cvt = {}
+        for el in leaves:
+            cvt[T(el)] = el
                   
-        translate_tables = tablesCvt.keys()
-        translate_tables.sort(cmp=locale.strcoll)            
-        
+        translate_leaves = cvt.keys()
+        translate_leaves.sort(cmp=locale.strcoll)            
+
         # fill the node with its children        
-        for tr_table in translate_tables:
-            table = tablesCvt[tr_table]        
-            if table in hidden:
+        for tr_leaf in translate_leaves:
+            leaf = cvt[tr_leaf]        
+            if leaf in hidden:
                 continue
             
-            wdg = widget
-            if table in widgets:
-                wdg = widgets[table]
-            
-            self.add_children(refName=table, text=tr_table, widget=wdg)
+            if isinstance(leaves, (list, tuple)):
+                self.add_children(tr_leaf, configurator(leaf))
+                
+            elif isinstance(leaves, dict):
+                self.add_children(tr_leaf, configurator(leaf, leaves[leaf]))
 
 
-class NodeURL(NodeBase):
-    """Navigation node where each leaf is associated to an url.
+    def add_children(self, text, cfg):
+        """ Add a child (leaf) to the node.
+        
+                text
+                    the name of the leaf
+                    
+                cfg
+                    configuration dictionary for the associated
+                    ExtJS widget
 
-    ExtJS widget can be associated to each leaf either globally
-    or individually using widget and widgets arguments respectively.
-    The widget identifier is its ExtJS type: xform, xgrid, ...
-    
-    Some leaf my be hidden depending on the context using hidden
-    argument.
-    
-    Leaves are sorted by alphabetic order.
-    Name of the leaf appearing in the tree are translated.
-    
-    """
-    def __init__(self, text, leaves=[], urls=[], widget='', hidden=[], widgets={}):
+        """
+        di = {'cfg': cfg, 'leaf': True, 'text': text}
+        self.children.append(di)
+                
 
-        T = current.T
-        
-        NodeBase.__init__(self, text)
-        
-        # order leaf in alphabetic order according to local setting
-        # the local setting is defined in the model as the time as the language
-        leavesCvt = {}
-        for el in leaves:
-            leavesCvt[T(el)] = leaves.index(el)
-                  
-        translate_leaves = leavesCvt.keys()
-        translate_leaves.sort(cmp=locale.strcoll)            
+    def get_node(self):
+        """Return the configuration dictionary for the node.
         
-        # fill the node with its children        
-        for tr_leaf in translate_leaves:
-            i = leavesCvt[tr_leaf]
-            leaf = leaves[i]        
-            if leaf in hidden:
-                continue
-            
-            wdg = widget
-            if leaf in widgets:
-                wdg = widgets[leaf]
-            
-            self.add_children(refName=leaf, text=tr_leaf, url=urls[i], widget=wdg)
\ No newline at end of file
+        """
+        return {'text': self.text, 'children': self.children}
diff --git a/modules/plugin_dbui/viewportmodifier.py b/modules/plugin_dbui/viewportmodifier.py
index ed3da7ee9ceb9443cc40366fbe850abb936b0230..0b708dae2bfca4a7fbef03e300581e5e015466ec 100644
--- a/modules/plugin_dbui/viewportmodifier.py
+++ b/modules/plugin_dbui/viewportmodifier.py
@@ -7,7 +7,7 @@ __author__ = "R. Le Gac"
 
 from gluon.storage import Storage
 from modifier import Modifier
-from navtree import NodeBase
+from navtree import Node
 
 
 MSG_INVALID_NODE = 'Node object is not an instance of NodeBase class.'
@@ -34,7 +34,7 @@ class ViewportModifier(Modifier):
         
         """
         for el in args:
-            if not isinstance(el, NodeBase):
+            if not isinstance(el, Node):
                 raise ViewportModifierException(MSG_INVALID_NODE)
         
         self.data.nodes.extend(args)
diff --git a/static/plugin_dbui/src/appgridroweditor.js b/static/plugin_dbui/src/appgridroweditor.js
index 94a579d4eb638e192b3c365fbef63a4707932cd4..8d4c7f72436a3c09a99410f709efb2c043e9dfc0 100644
--- a/static/plugin_dbui/src/appgridroweditor.js
+++ b/static/plugin_dbui/src/appgridroweditor.js
@@ -69,7 +69,7 @@ App.grid.RowEditor = Ext.extend(Ext.Window, {
 
         // get the formPanel configuration and instantiate the object
         table = App.getTableName(this.grid.store);
-        Dbui.getConfiguration(table, 'xform', this.addFormPanel, this);
+        Dbui.getForm(table, this.addFormPanel, this);
     },
 
     /**
diff --git a/static/plugin_dbui/src/appviewport.js b/static/plugin_dbui/src/appviewport.js
index a924b616f66e0cfa8521e3f5475ddcf33010238d..68f8dcc09c4708ea931f17046ac7d4e61baae2fe 100644
--- a/static/plugin_dbui/src/appviewport.js
+++ b/static/plugin_dbui/src/appviewport.js
@@ -100,26 +100,18 @@ App.Viewport = Ext.extend(Ext.Viewport, {
             parent = node.parentNode,
             panel,
             tabId,
-            refName = node.attributes.refName,
             viewport = this,
-            wdg,
-            xtype = node.attributes.widget;
+            wdgcfg = node.attributes.cfg,
+            wdgtype = node.attributes.cfg.xtype;
      
-        function addWidget(cfg, response) {
-            if (cfg === null) {return;}
-            wdg = Ext.ComponentMgr.create(cfg)
-            panel.add(wdg);
-            panel.doLayout();
-        }
-
         // protection
         if(!node.isLeaf()){
             return;
         }   
-        
-        // generate a unique tab identifier
-        tabId = refName + '/' + xtype;
-        
+
+        // unique tab identifier
+        tabId = node.attributes.text + '/' + wdgtype;
+                
         // activate an existing tab
         if (this.tabPanel.getComponent(tabId)) {
             this.tabPanel.setActiveTab(tabId);
@@ -128,26 +120,24 @@ App.Viewport = Ext.extend(Ext.Viewport, {
 
         // tab configuration
         // the title is defined as 'Form tablename', 'Grid tablename', ...
-        // handle the simple case of panel pointing to an url
         cfg = {
-            itemId: tabId,
             closable: true,
+            itemId: tabId,
             title: parent.attributes.text + " " + node.attributes.text
         };
-         
-        if(xtype === 'panel' && node.attributes.url) {
-            cfg.autoLoad = node.attributes.url
+        
+        // embed single panel in the tab panel        
+        // other widget as children
+        if( wdgtype === 'panel') {
+            delete wdgcfg.xtype;
+            Ext.apply(cfg, wdgcfg);
+            
+        } else {
+            cfg.items = [node.attributes.cfg];
         }
         
         // create a new tab and activate it
         panel = this.tabPanel.add(cfg);
         this.tabPanel.setActiveTab(tabId);
-        
-        // for complex object like form and grid request their configuration
-        // to the server and add the corresponding widget in the newly 
-        // created tab
-        if (xtype !== 'panel') {
-            Dbui.getConfiguration(refName, xtype, addWidget);
-        }
     }
 });