[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r6542 - trunk/gnue-navigator/src
From: |
johannes |
Subject: |
r6542 - trunk/gnue-navigator/src |
Date: |
Thu, 21 Oct 2004 13:55:45 -0500 (CDT) |
Author: johannes
Date: 2004-10-21 13:55:45 -0500 (Thu, 21 Oct 2004)
New Revision: 6542
Modified:
trunk/gnue-navigator/src/GNClient.py
trunk/gnue-navigator/src/UIgtk2.py
Log:
Fixed gtk2 frontend for navigator
Modified: trunk/gnue-navigator/src/GNClient.py
===================================================================
--- trunk/gnue-navigator/src/GNClient.py 2004-10-21 16:37:59 UTC (rev
6541)
+++ trunk/gnue-navigator/src/GNClient.py 2004-10-21 18:55:45 UTC (rev
6542)
@@ -1,6 +1,9 @@
+# GNU Enterprise Navigator - Client
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-2004 Free Software Foundation
#
+# 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
@@ -16,168 +19,197 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2002-2004 Free Software Foundation
-#
-# FILE:
-# GNClient.py
-#
-# DESCRIPTION:
-# Client startup file that creates a navigation menu from a file
-#
-# NOTES:
-#
+# $Id$
import pstats
import os
-import os.path
import sys
import urllib
-import string
from gnue.navigator.GNParser import loadProcesses
from gnue.navigator import Actions
-from gnue.common.apps import GDebug
+from gnue.common.apps import errors
from gnue.common.utils.FileUtils import openResource, dyn_import
from gnue.common.datasources import GDataObjects, GConnections
from gnue.common.apps.GClientApp import *
from gnue import paths
from gnue.navigator import VERSION
+from gnue.forms.GFInstance import GFInstance
from GNConfig import ConfigOptions as NavigatorConfigOptions
# TODO: Please go away!!!!!
-try:
+try:
from gnue.forms.GFConfig import ConfigOptions
-except:
- FORMS_SUPPORT=0
+ FORMS_SUPPORT = True
+
+except:
+ FORMS_SUPPORT = False
-try:
+try:
from gnue.reports.base.GRConfig import ConfigOptions as ReportsConfigOptions
- REPORTS_SUPPORT=1
-except:
- REPORTS_SUPPORT=0
+
+ REPORTS_SUPPORT = True
+
+except:
+ REPORTS_SUPPORT = False
-class GNClient(GClientApp):
+# =============================================================================
+# This class implements the navigator client
+# =============================================================================
+
+class GNClient (GClientApp):
#
# GClientApp() overrides
#
VERSION = VERSION
COMMAND = "gnue-navigator"
- NAME = "GNUe Navigator"
- USAGE = "[options] file"
- COMMAND_OPTIONS = [
- [ 'user_interface', 'u', 'user_interface', 1, None, 'type',
- 'The currently supported values for <type> are ' \
- + 'wx, gtk2, win32, web (a themable web-like interface), and text' ],
- [ 'splash_screen','s','no-splash', 0, None, None,
- 'Disables the splash screen'],
- [ 'gnome_menu',None,'install-gnome-menu', 0, None, None,
- 'Installs a menu structure into your local GNOME session'],
- [ 'kde_menu',None,'install-kde-menu', 0, None, None,
- 'Installs a menu structure into your local KDE session']
- ]
- SUMMARY = \
- "GNUe Navigator is the primary menuing interface to the GNU Enterprise
system."
+ NAME = "GNUe Navigator"
+ USAGE = "[options] file"
+ SUMMARY = _("GNUe Navigator is the primary menuing interface to the GNU "
+ "Enterprise system.")
- #
+ # ---------------------------------------------------------------------------
# Initialize the class
- #
- def __init__(self, connections=None):
- GClientApp.__init__(self, connections,'forms', ConfigOptions)
-
self.configurationManager.loadApplicationConfig(section="navigator",defaults=NavigatorConfigOptions)
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, connections = None):
+
+ self.addCommandOption ('user_interface', 'u', 'interface', argument = "ui",
+ category = "ui",
+ help = _("The name of the user interface to use to display the "
+ "navigator. Currently supported interfaces are: wx, gtk2, "
+ "win32, web and text"))
+
+ self.addCommandOption ('no-splash', 's', category = "ui",
+ help = _("Disables the splash screen"))
+
+ self.addCommandOption ('gnome_menu', None, 'install-gnome-menu',
+ help = _('Installs a menu structure into your local GNOME session'))
+
+ self.addCommandOption ('kde_menu', None, 'install-kde-menu',
+ help = _('Installs a menu structure into your local KDE session'))
+
+
+ GClientApp.__init__ (self, connections, 'forms', ConfigOptions)
+
+ self.configurationManager.loadApplicationConfig (section = "navigator",
+ defaults = NavigatorConfigOptions)
- if REPORTS_SUPPORT:
-
self.configurationManager.loadApplicationConfig(section="reports",defaults=ReportsConfigOptions)
- self.configurationManager.registerAlias('gConfigReports', 'reports')
+ if REPORTS_SUPPORT:
+ self.configurationManager.loadApplicationConfig (section = "reports",
+ defaults = ReportsConfigOptions)
+ self.configurationManager.registerAlias ('gConfigReports', 'reports')
- self.configurationManager.registerAlias('gConfigNav', 'navigator')
- self.configurationManager.registerAlias('gConfigForms', 'forms')
+ self.configurationManager.registerAlias ('gConfigNav' , 'navigator')
+ self.configurationManager.registerAlias ('gConfigForms', 'forms')
- self._formInstances = {}
+ self._formInstances = {}
self._lastSerialNumber = 0
- #
+ # ---------------------------------------------------------------------------
# Run the client application
- #
- # GClientApp().run() override
- #
- def run(self):
+ # ---------------------------------------------------------------------------
+ def run (self):
+
#
# Initialize user interface
#
- self.ui_type = self.OPTIONS['user_interface']
+ self.ui_type = self.OPTIONS ['user_interface']
if self.ui_type:
- SPECIFIC_UI = 1
+ SPECIFIC_UI = True
else:
- SPECIFIC_UI = 0
- self.ui_type = gConfigForms('DefaultUI')
+ SPECIFIC_UI = False
+ self.ui_type = gConfigForms ('DefaultUI')
- while 1:
+ while True:
try:
- self._ui = dyn_import("gnue.navigator.UI%s" % (self.ui_type))
+ self._ui = dyn_import ("gnue.navigator.UI%s" % self.ui_type)
break
- except ImportError, err:
- GDebug.printMesg(1,_("Unable to load UI driver")+" %s" % self.ui_type)
- GDebug.printMesg(1,err)
+ except ImportError:
+ gDebug (1, "Unable to load UI driver %s" % self.ui_type)
+ gDebug (1, "Error: %s" % errors.getException () [2])
+
# If user specified a specific UI, don't cycle...
if SPECIFIC_UI:
- raise # TODO: TEMPORARY
- self.handleStartupError(_("Unable to load any valid UI drivers.
Aborting.\n\nTraceback\n%s") % err)
+ raise StartupError, \
+ u_("Unable to load any valid UI drivers: %s") \
+ % errors.getException () [2]
if self.ui_type != 'text':
self.ui_type = 'text'
+
else:
- self.handleStartupError(_("Unable to load any valid UI drivers.
Aborting."))
+ raise StartupError, u_("Unable to load any valid UI driver.")
+ # if we have a forms-uidriver available take over it's exception handling
+ # and set the login handler for the connection manager.
+ if hasattr (self._ui, 'ui'):
+ instance = GFInstance (self, self.connections, self._ui.ui, False)
+ self._showException = instance._uiinstance.showException
+ loginHandler = self._ui.ui.UILoginHandler ()
+ loginHandler.uiDriver = instance._uiinstance
+ self.connections.setLoginHandler (loginHandler)
+
#
# assign menu file from 1st free argument
#
+ if len (self.ARGUMENTS):
+ processFile = self.ARGUMENTS [0]
+
+ else:
+ basename = os.path.basename (sys.argv [0]).lower ().split ('.') [0]
+ if basename not in ['gnue-navigator','gncvs']:
+ processFile = os.path.join (paths.data, gConfigNav ('ProcessDir'),
+ os.path.basename (sys.argv [0])) + ".gpd"
+ else:
+ raise StartupError, u_("No process definition file specified")
+
+
+ fileHandle = openResource (processFile)
try:
- processFile = self.ARGUMENTS[0]
- except:
- try:
- if string.split(string.lower(os.path.basename(sys.argv[0])),'.')[0]
not in ('gnue-navigator','gncvs'):
- processFile =
paths.data+'/'+gConfigNav('ProcessDir')+"/"+os.path.basename(sys.argv[0])+".gpd"
- else:
- raise IndexError
- except IndexError:
- self.handleStartupError ("No Process Definition File Specified.")
+ nav = loadProcesses (fileHandle)
+ finally:
+ fileHandle.close ()
- fileHandle = openResource(processFile)
- nav = loadProcesses (fileHandle)
- fileHandle.close()
-
# Handle any action commands
- if self.OPTIONS['kde_menu']:
+ if self.OPTIONS ['kde_menu']:
from gnue.navigator.Actions import kde_menu
- kde_menu.run(nav, self.ARGUMENTS[1:])
- sys.exit()
- if self.OPTIONS['gnome_menu']:
+ kde_menu.run (nav, self.ARGUMENTS [1:])
+ sys.exit ()
+
+ if self.OPTIONS ['gnome_menu']:
from gnue.navigator.Actions import gnome_menu
- gnome_menu.run(nav, self.ARGUMENTS[1:])
- sys.exit()
+ gnome_menu.run (nav, self.ARGUMENTS [1:])
+ sys.exit ()
- if gConfigNav('disableSplash') == True:
- self.disableSplash = 1
+
+ if gConfigNav ('disableSplash'):
+ self.disableSplash = True
else:
- self.disableSplash = self.OPTIONS['splash_screen']
+ self.disableSplash = self.OPTIONS ['splash_screen']
# add connections object to top object
- nav._connections=self.connections
+ nav._connections = self.connections
- self._ui.Instance(nav).run(self.connections)
+ self._ui.Instance (nav).run (self.connections)
+
+# =============================================================================
+# Main program
+# =============================================================================
+
if __name__ == '__main__':
- GNClient().run()
+ GNClient ().run ()
Property changes on: trunk/gnue-navigator/src/GNClient.py
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: trunk/gnue-navigator/src/UIgtk2.py
===================================================================
--- trunk/gnue-navigator/src/UIgtk2.py 2004-10-21 16:37:59 UTC (rev 6541)
+++ trunk/gnue-navigator/src/UIgtk2.py 2004-10-21 18:55:45 UTC (rev 6542)
@@ -1,7 +1,8 @@
+# GNU Enterprise Navigator - GTK Frontent
#
-# Copyright 2002-2004 Free Software Foundation
+# Copyright 2001-2004 Free Software Foundation
#
-# This file is part of GNU Enterprise.
+# 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
@@ -18,436 +19,700 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# FILE:
-# UIgtk2.py
-#
-# DESCRIPTION:
-# Set of classes that provide a menuing interface via wxPython
-#
-# NOTES:
-# This file is nothing but a temporary hack. Navigator should
-# reuse GNUe Form's UI* classes if at all possible.
+# $Id$
-
import pygtk
pygtk.require('2.0')
import gtk
-import pango
import gtkhtml2
-import gobject
+import urllib
+import urlparse
+import os
-__gtk_mainloop = None
-
-from time import sleep
-import os, sys, string
-from gnue.common.datasources import GDataObjects, GConnections
-from gnue.common.utils.FileUtils import dyn_import, openResource
from gnue.common.apps import GConfig
+from gnue.common.utils.FileUtils import openResource
from gnue.navigator import VERSION
+from gnue.navigator import GNParser
try:
from gnue.forms.GFInstance import GFInstance
- from gnue.forms import GFParser
from gnue.forms.uidrivers import gtk2 as ui
- FORMS_SUPPORT=0
+
except ImportError:
- FORMS_SUPPORT=1
+ FORMS_SUPPORT = False
print 'GNUe Forms is not installed on your system'
-images_dir = GConfig.getInstalledBase('forms_images','common_images') + '/'
+images_dir = GConfig.getInstalledBase ('forms_images','common_images') + '/'
-import urllib
+# =============================================================================
+# This class implements the GTK-UI of the navigator client
+# =============================================================================
-class ProcessTree(gtk.TreeView):
- def __init__(self, processes, on_selected, on_activated):
- self._callbacks={}
- self._callbacks['on_selected']=on_selected
- self._callbacks['on_activated']=on_activated
-
- # a) the model
- self._treeStore = gtk.TreeStore(gobject.TYPE_STRING)
- self._mapping = {}
- processes.walk(self.__buildTreeStore)
- processes.walk(self.__removeNodes)
+class Instance:
- # b) the widget (i.e. "my-self")
- gtk.TreeView.__init__(self, self._treeStore)
- cell = gtk.CellRendererText()
- column = gtk.TreeViewColumn("tuples", cell, text=0)
- self.append_column(column)
- self.connect("row-activated",self._row_activated)
- self.connect("cursor-changed",self._row_selected)
- self.set_headers_visible(gtk.FALSE)
- self.expand_row((0,),gtk.FALSE)
- self._oldpath=(0,)
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
- def __buildTreeStore(self, object):
+ def __init__ (self, processes):
+ """
+ @param processes: GNObjects tree describing the current loaded gpd
+ """
- if object._type == 'GNProcesses':
- # add parent (top) object
- node=self._treeStore.append(None)
- self._treeStore.set(node, 0, object.title)
-
- elif object._type in ('GNStep','GNProcess'):
- # add child
- node=self._treeStore.append(object._parent.__node)
- self._treeStore.set(node, 0, object.title)
- else:
- return
+ self.processes = processes
+ self._formInstances = {}
+ self._lastSerialNumber = 0
+ self._treeModel = None
- object.__node = node
- self._mapping[self._treeStore.get_path(node)] = object
+ self.__currentURL = None
+ self.__opener = urllib.FancyURLopener ()
- ## TODO: Is this necessary?
- def __removeNodes(self, object):
- if hasattr(object,"__node"):
- del object.__node
+ self.app = ui.getApp ()
- def _row_selected(self, tree):
- (path,column)=self.get_cursor()
-# print 'selected:', path
- if path != self._oldpath:
- self._callbacks['on_selected'](self._mapping[path])
- self._oldpath=path
+
+ # ---------------------------------------------------------------------------
+ # Build the UI and start the navigator client
+ # ---------------------------------------------------------------------------
- def _row_activated(self, view, path, column):
-# print 'activated:', path
-
- # 1. try to expand
- self.expand_row(path,gtk.FALSE)
- # 2. pass event further
- self._callbacks['on_activated'](self._mapping[path])
+ def run (self, connections):
+ """
+ This function creates the user interface and starts the main loop
+ """
- def reload_definitions(self, processes):
- # remove elements from tree
- self.treeStore.clear()
- self._mapping = {}
- processes.walk(self.__buildTreeStore)
- processes.walk(self.__removeNodes)
- self.expand_row((0,),gtk.FALSE)
+ self.connections = connections
-class Instance:
- def __init__(self, processes):
- self.processes = processes
- self._formInstances = {}
- self._lastSerialNumber = 0
+ self.__buildInterface ()
- self.titlePage = _("""
- <html>
- <body>
- <center>
- <B>GNUe Navigator</B>
- <p><img src="%s"></p>
- <p>A part of the <a href="http://www.gnuenteprise.org/">GNU
Enterprise Project</a></p>
- </center>
- </body>
- </html>
- """) % (images_dir+"/ship2.png")
+ # Transform the GNObjects tree into a tree store and activate it
+ self.__treeStore = self.__buildTreeModel (self.processes)
+ self.treeView.set_model (self.__treeStore)
+ self.treeView.expand_row ((0,), False)
+ self.__lastItem = None
- self.app = ui.getApp()
-
- def run(self, connections):
- #
- # Assign the proper login handler based upon the user interface choice
- #
- self.connections = connections
- self.connections.setLoginHandler(ui.UILoginHandler())
+ self.processes.setClientHandlers ({'form': self.runForm})
- self.mainWindow = gtk.Window()
- self.mainWindow.set_resizable(gtk.TRUE)
- self.content_table = gtk.Table(4, 1, gtk.FALSE)
- self.mainWindow.add(self.content_table)
- self.mainWindow.set_title('GNUe Navigator')
- self.mainWindow.set_default_size(600,400)
- self.mainWindow.connect('delete_event', self.OnClose)
+ self.treeView.set_cursor ((0,))
- #
+ self.mainWindow.show_all ()
+ self.app.mainLoop ()
+
+
+ # ---------------------------------------------------------------------------
+ # display a message in the status bar
+ # ---------------------------------------------------------------------------
+
+ def setStatus (self, message = None):
+ """
+ This function removes the last message from the status bar and adds a new
+ one if specified.
+
+ @param message: message to put into the status bar or None
+ """
+
+ self.statusbar.pop (0)
+ if message is not None:
+ self.statusbar.push (0, message)
+
+
+ # ---------------------------------------------------------------------------
+ # Build up the user interface
+ # ---------------------------------------------------------------------------
+
+ def __buildInterface (self):
+ """
+ This function creates the user interface and connects all signal handlers
+ """
+
+ self.mainWindow = gtk.Window ()
+ self.mainWindow.set_resizable (True)
+ self.content_table = gtk.Table (3, 1, False)
+
+ self.mainWindow.add (self.content_table)
+ self.mainWindow.set_title ('GNUe Navigator')
+ self.mainWindow.set_default_size (600, 400)
+ self.mainWindow.connect ('delete_event', self.__windowExit)
+
# StatusBar
- #
- self.statusbar = gtk.Statusbar();
- self.content_table.attach(self.statusbar,
+ self.statusbar = gtk.Statusbar ()
+ self.content_table.attach (self.statusbar,
# X direction Y direction
- 0, 1, 3, 4,
+ 0, 1, 2, 3,
gtk.EXPAND | gtk.FILL, 0,
0, 0)
- #
- # MenuBar
- #
- self.menu = self.createMenuBar()
- self.content_table.attach(self.menu,
+ # Menu-Bar
+ self.handleBox = gtk.HandleBox ()
+ self.menu = self.__createMenuBar ()
+ self.handleBox.add (self.menu)
+ self.menu.show ()
+
+ self.content_table.attach (self.handleBox,
# X direction Y direction
- 0, 1, 0, 1,
- gtk.EXPAND | gtk.FILL, 0,
- 0, 0)
+ 0, 1, 0, 1,
+ gtk.EXPAND | gtk.FILL, 0,
+ 0, 0)
-
- #
# main part of window
- #
- self.splitter= gtk.HPaned()
- self.content_table.attach(self.splitter,
+ self.splitter = gtk.HPaned ()
+ self.content_table.attach (self.splitter,
# X direction Y direction
- 0, 1, 2, 3,
+ 0, 1, 1, 2,
gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL,
0, 0)
- self.panel1 = gtk.ScrolledWindow()
- self.panel1.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
- #self.panel1.set_border_width(2)
- self.panel1.set_shadow_type(gtk.SHADOW_IN)
+ self.treePane = gtk.ScrolledWindow ()
+ self.treePane.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.treePane.set_shadow_type (gtk.SHADOW_IN)
- self.splitter.add1(self.panel1)
+ self.treeView = gtk.TreeView ()
+ self.treeView.set_headers_visible (False)
- self.panel2 = gtk.ScrolledWindow()
- self.panel2.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
-# self.panel2.set_border_width(2)
- self.panel2.set_shadow_type(gtk.SHADOW_IN)
- self.splitter.add2(self.panel2)
+ col = gtk.TreeViewColumn ('Title', gtk.CellRendererText (), text = 0)
+ self.treeView.append_column (col)
+ self.treeView.connect ('row_activated', self.__row_activated)
+ self.treeView.connect ('cursor_changed', self.__row_selected)
- self.splitter.set_position(200)
-
- # Panel 1 contents
- self.tree = ProcessTree(self.processes,
- self.loadDescription,
- self.executeStep)
- self.panel1.add(self.tree)
+ self.treePane.add (self.treeView)
- # Panel 2 contents
- self.document = gtkhtml2.Document()
- self.document.connect('request_url', self.request_url)
- self.document.connect('link_clicked', self.link_clicked)
-
- self.document.clear()
- self.document.open_stream('text/html')
- self.document.write_stream(self.titlePage)
- self.document.close_stream()
-
- view = gtkhtml2.View()
- view.set_document(self.document)
- self.panel2.add(view)
+ self.splitter.add1 (self.treePane)
+
+ self.viewPane = gtk.ScrolledWindow ()
+ self.viewPane.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.viewPane.set_shadow_type (gtk.SHADOW_IN)
+ self.splitter.add2 (self.viewPane)
+
+ self.view = gtkhtml2.View ()
+ self.view.connect ('on_url', self.__onURL)
+ self.viewPane.add (self.view)
+
+ self.__startNewDocument ()
+
+ self.splitter.set_position (200)
+
+
+ # ---------------------------------------------------------------------------
+ # Create the menu bar
+ # ---------------------------------------------------------------------------
+
+ def __createMenuBar (self):
+ """
+ This function creates the menu bar for the navigator.
+ """
+
+ menu_items = ( \
+ (u_('/_File'), None, None, 0, '<Branch>'),
+ (u_('/_File/_Open'), '<control>O', self.__openFile, 0, '<StockItem>',
+ gtk.STOCK_OPEN),
+ (u_('/_File/_Quit'), '<control>Q', self.__windowExit, 0, '<StockItem>',
+ gtk.STOCK_QUIT),
+
+ (u_('/_Favorites'), None, None, 0, '<Branch>'),
+ (u_('/_Favorites/_Add Favorite'), None, None, 0, ''),
+ (u_('/_Favorites/_Organize Favorites'), None, None, 0, ''),
+
+ (u_('/_Help'), None, None, 0, '<Branch>'),
+ (u_('/Help/_About'), None, self.__about, 0, ''),
+ )
+
+ self.accel_group = gtk.AccelGroup ()
+ self.mainWindow.add_accel_group (self.accel_group)
- self.processes.setClientHandlers({'form':self.runForm})
+ self.item_factory = gtk.ItemFactory (gtk.MenuBar, '<main>',
+ self.accel_group)
+
+ self.item_factory.create_items (menu_items, self.mainWindow)
+
+ return self.item_factory.get_widget ('<main>')
- self.mainWindow.show_all()
- self.app.mainLoop()
+ # ---------------------------------------------------------------------------
+ # Close the navigator
+ # ---------------------------------------------------------------------------
- def request_url(self,obj,url,stream):
-# print "request url",url
- opener = urllib.FancyURLopener()
- f = opener.open(url)
- stream.write(f.read())
+ def __windowExit (self, widget, event, data = None):
+ """
+ This function quits the main loop
+ """
- def link_clicked(self,obj,link):
-# print "Link clicked",link
- opener = urllib.FancyURLopener()
- try:
- f = opener.open(link)
- except OSError:
- print "failed to open", link
- return
- currentUrl = resolve_uri(link)
- document.clear()
- headers = f.info()
- mime = headers.getheader('Content-type')
- # TODO: test content type for gnue/process, if yes, load process file into
tree widget
- if mime:
- document.open_stream(mime)
- else:
- document.open_stream('text/plain')
- document.write_stream(f.read())
- document.close_stream()
+ # TODO: can we keep track of all windows opened ?
+ self.app.quit ()
- def setStatus(self,mesg):
- self.statusbar.pop(0)
- self.statusbar.push(0,mesg)
- def OnClose(self, obj, more, muchmore=1):
- # close down
- # TODO: use GFgtkAPP instead, so open form widgets wouldn't get closed by
accident.
- self.app.quit()
+ # ---------------------------------------------------------------------------
+ # Create a new tree model
+ # ---------------------------------------------------------------------------
- def OnAbout(self, obj, more, muchmore):
- # TODO: Create a more beautiful about box
- text = _("GNUE Navigator")+"\n"+ \
- _(" Version : ")+"%s\n"+ \
- _(" Driver : UIgtk2")+"\n"+ \
- _("-= Process Info =- ")+"\n"+ \
- _(" Name : ")+"%s\n"+ \
- _(" Version: ")+"%s\n"+ \
- _(" Author : ")+"%s\n"+ \
- _(" Description: ")+"%s\n"
- dlg = gtk.MessageDialog(self.mainWindow,
- gtk.DIALOG_DESTROY_WITH_PARENT + gtk.DIALOG_MODAL,
- gtk.MESSAGE_INFO,
- gtk.BUTTONS_CLOSE,
- text % (VERSION,'-','-','-','-'))
- dlg.connect('response', lambda dlg, response: dlg.destroy())
- dlg.show()
+ def __buildTreeModel (self, GNTree):
+ """
+ This function creates a new tree store and populates the given GNObjects
+ tree into that store
- def OnOpen(self, obj, more, muchmore):
- # TODO: Implement for other uidrivers
- self.fs=fs=gtk.FileSelection()
- fs.complete('*.gpd') # todo: make this work
- fs.hide_fileop_buttons()
- fs.ok_button.connect('clicked',lambda obj, self:
self.reloadProcesses(self.fs.get_filename()),self)
- fs.cancel_button.connect('clicked',lambda obj, self:
self.fs.destroy(),self)
- fs.ok_button.connect_after('clicked',lambda obj, self:
self.fs.destroy(),self)
- fs.show()
+ @param GNTree: GNObjects tree to be added to the gtk.TreeStore
+ @return: gtk.TreeStore holding the given GNObjects tree. The tree store has
+ two columns: Title of the element, the element instance itself.
+ """
- def reloadProcesses(self,filename):
- # TODO: 1. finish 2. move this part into ui independent part
- print filename
- return
- self.processes=loadDefinition(filename)
- self.tree.reload_definitions(self.processes)
+ result = gtk.TreeStore (str, object)
+ GNTree.walk (self.__addToTreeModel, store = result)
- def loadDescription(self,obj):
- # a) get description
- newDescr="<HTML><HEAD></HEAD><BODY></BODY></HTML>"
- for item in obj._children:
- if item._type == 'GNDescription':
- newDescr=item.getChildrenAsContent()
- break
-
- # b) write to document
- self.document.clear()
- self.document.open_stream('text/html')
- self.document.write_stream(newDescr)
- self.document.close_stream()
+ return result
- def executeStep(self,step):
- print "executing step:", step
- if step._type != 'GNStep':
- pass
+ # ---------------------------------------------------------------------------
+ # Add an item of a GNObjects tree to the TreeStore
+ # ---------------------------------------------------------------------------
+
+ def __addToTreeModel (self, gnObject, store):
+ """
+ This function adds an item of a GNObjects tree to the given tree store
+
+ @param gnObject: GNObject instance to be added
+ @param store: gtk.TreeStore the gnObject should be added to
+ """
+
+ if gnObject._type == 'GNProcesses':
+ node = store.append (None, [gnObject.title, gnObject])
+
+ elif gnObject._type in ['GNStep', 'GNProcess']:
+ node = store.append (gnObject._parent.__node, [gnObject.title, gnObject])
+
else:
- step.run()
+ return
- # Called whenever forms goes into a "wait" state in which user cannot
- # interact with interface (e.g., while waiting for a query or a commit)
+ # Remember the iterator of the current node
+ gnObject.__node = node
+
+
+ # ---------------------------------------------------------------------------
+ # Activate a row in the tree view
+ # ---------------------------------------------------------------------------
+
+ def __row_activated (self, tree, path, column):
+ """
+ This function is called on the 'row-activated' signal of the tree view,
+ which happens if an element of the tree get's selected by the enter-key or
+ a double-click.
+
+ @param tree: the tree view widget which emitted the signal
+ @param path: the path tuple of the selected item
+ @param column: the tree view column instance which has been activated
+ """
+
+ try:
+ self.beginWait ()
+
+ tree.expand_row (path, False)
+ item = self.__treeStore.get_iter (path)
+
+ # Fetch the associated GN* instance, which is hold in the first column
+ gnObject = self.__treeStore.get_value (item, 1)
+ if gnObject._type == 'GNStep':
+ gnObject.run ()
+
+ finally:
+ self.endWait ()
+
+
+ # ---------------------------------------------------------------------------
+ # A row has been selected in the tree
+ # ---------------------------------------------------------------------------
+
+ def __row_selected (self, tree):
+ """
+ This function get's called when the focus in the tree view widget has
+ changed.
+
+ @param tree: the tree view widget which emitted the signal
+ """
+
+ try:
+ self.beginWait ()
+
+ (path, column) = tree.get_cursor ()
+ if path != self.__lastItem:
+ self.__lastItem = path
+
+ item = self.__treeStore.get_iter (path)
+ gnObject = self.__treeStore.get_value (item, 1)
+ descr = gnObject.findChildOfType ('GNDescription')
+
+ if descr is not None:
+ stream = descr.getChildrenAsContent ()
+ else:
+ stream = self.__getTitlePage ()
+
+ self.__startNewDocument ()
+ self.__loadDocument ('text/html', stream)
+
+ finally:
+ self.endWait ()
+
+
+ # ---------------------------------------------------------------------------
+ # Create a HTML stream with the title page
+ # ---------------------------------------------------------------------------
+
+ def __getTitlePage (self):
+ """
+ This function creates a HTML string containing the title page
+
+ @return: stream with the HTML code for the titlepage
+ """
+
+ return '<HTML><BODY><CENTER><B>GNUe Navigator</B>' \
+ '<p><img src="%s"></p>' \
+ '<p>A part of the <a href="http://www.gnuenterprise.org/">' \
+ 'GNU Enterprise Project</a></p>' \
+ '</center></body></html>' % (images_dir + "/ship2.png")
+
+
+ # --------------------------------------------------------------------------
+ # Change the mouse pointer in an hour-glass
+ # --------------------------------------------------------------------------
+
def beginWait (self):
- pass #wxBeginBusyCursor()
+ """
+ This function changes the mouse pointer to an hour glass.
+ """
- # Called whenever forms leaves a "wait" state
+ if self.mainWindow.window is not None:
+ self.mainWindow.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.WATCH))
+
+
+ # --------------------------------------------------------------------------
+ # Change the mouse pointer back to it's normal apperance
+ # --------------------------------------------------------------------------
+
def endWait (self):
- pass #wxEndBusyCursor()
+ """
+ This function changes the mouse pointer back to the normal state.
+ """
+ if self.mainWindow.window is not None:
+ self.mainWindow.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.LEFT_PTR))
- def getNextSerialNumber (self):
- self._lastSerialNumber = self._lastSerialNumber + 1
- return self._lastSerialNumber
- # forms compatibility
- def handleStartupError(self, mesg):
- self.handleError(mesg)
-
- def handleError(self, mesg):
- dlg = gtk.MessageDialog(self.mainWindow,
- gtk.DIALOG_DESTROY_WITH_PARENT + gtk.DIALOG_MODAL,
- gtk.MESSAGE_ERROR,
- gtk.BUTTONS_CLOSE,
- "Error: %s!" % mesg)
- dlg.connect('response', lambda dlg, response: dlg.destroy())
- dlg.show()
+ # ===========================================================================
+ # gtkhtml stuff
+ # ===========================================================================
- def runFormFromTrigger(self, form, parameters = {}):
- self.setStatus('running form %s from trigger' % formfile)
- self._runForm(form, self._params)
- def runForm(self, step, parameters = {}):
- # This is the code executing in the new thread. Simulation of
- # a long process (well, 10s here) as a simple loop - you will
- # need to structure your processing so that you periodically
- # peek at the abort variable
+ # ---------------------------------------------------------------------------
+ # Start a fresh document
+ # ---------------------------------------------------------------------------
- # TODO: Pass parameters
+ def __startNewDocument (self):
+ """
+ This function creates a new instance of a fresh document, connects the
+ signal handlers and resets the global URL.
+ """
- if os.path.basename(step.location) == step.location:
+ self.__currentURL = None
+ self.document = gtkhtml2.Document ()
+ self.document.connect ('request_url' , self.__requestURL)
+ self.document.connect ('link_clicked', self.__linkClicked)
+
+ self.view.set_document (self.document)
+
+
+ # ---------------------------------------------------------------------------
+ # Load a given stream into the current document
+ # ---------------------------------------------------------------------------
+
+ def __loadDocument (self, contenttype, stream):
+ """
+ This function loads a stream of a given type into the current document
+ which get's cleared first.
+
+ @param contenttype: type of the contents, e.g. 'text/html'
+ @param stream: string with the actual data
+ """
+
+ self.document.clear ()
+ self.document.open_stream (contenttype)
+ self.document.write_stream (stream)
+ self.document.close_stream ()
+
+
+ # ---------------------------------------------------------------------------
+ # Check if a given URL is relative or absolute
+ # ---------------------------------------------------------------------------
+
+ def __isRelativeToServer (self, url):
+ """
+ This function determines wether the given URL is absolute or relative
+
+ @param url: URL to be checked
+ @return: True if URL is relative, False if it is absolute
+ """
+
+ parts = urlparse.urlparse (url)
+ if parts [0] or parts [1]:
+ return False
+
+ return True
+
+
+ # ---------------------------------------------------------------------------
+ # Resolve a URI so we have an absolute one afterwards
+ # ---------------------------------------------------------------------------
+
+ def __resolveURI (self, uri):
+ """
+ This function returns a resolved URI. If it is a relative URL it will be
+ joined with the current 'global' URL.
+
+ @param uri: URI to be resolved
+ @return: complete URI
+ """
+
+ if self.__isRelativeToServer (uri):
+ return urlparse.urljoin (self.__currentURL, uri)
+
+ return uri
+
+
+ # ---------------------------------------------------------------------------
+ # Resolve a given URL and open it
+ # ---------------------------------------------------------------------------
+
+ def __openURL (self, url):
+ """
+ This function opens a given URL and returns a file-like object.
+ @param url: URL to be opened. This URL will be resolved.
+
+ @return: file object for the url.
+ """
+
+ uri = self.__resolveURI (url)
+ return self.__opener.open (uri)
+
+
+ # ---------------------------------------------------------------------------
+ # download a given url into a stream
+ # ---------------------------------------------------------------------------
+
+ def __requestURL (self, document, url, stream):
+ """
+ This function get's called when the given document needs data from an URL.
+ It opens the given URL and writes it's contents into the given stream.
+
+ @param document: the document which requested the resource
+ @param url: the URL from where we can get the resource
+ @param stream: the stream where the result get's written to
+ """
+
+ try:
+ self.beginWait ()
+
+ self.setStatus (u_("Requesting %s" % url))
+ stream.write (self.__openURL (url).read ())
+
+ finally:
+ self.setStatus ()
+ self.endWait ()
+
+
+ # ---------------------------------------------------------------------------
+ # Process the click to a link in the current document
+ # ---------------------------------------------------------------------------
+
+ def __linkClicked (self, document, link):
+ """
+ This function get's called when the user clicks a link in the given
+ document. The specified URL will then be loaded and displayed in the
+ current document.
+
+ @param document: the document where the link should be displayed in
+ @param link: URL of the link which has been selected
+ """
+
+ try:
+ self.beginWait ()
+
+ fhd = self.__openURL (link)
+ self.__currentURL = self.__resolveURI (link)
+
+ headers = fhd.info ()
+ document.clear ()
+
+ ctype = headers.getheader ('Content-type') or 'text/plain'
+ document.open_stream (ctype)
+ document.write_stream (fhd.read ())
+ document.close_stream ()
+
+ finally:
+ self.endWait ()
+
+
+ # ---------------------------------------------------------------------------
+ # On URL
+ # ---------------------------------------------------------------------------
+
+ def __onURL (self, view, url):
+ """
+ This function get's called when the mouse is over an url. This url get's
+ displayed in the status bar. If the mouse has left the url this function
+ will be called with an url value of None.
+ """
+
+ self.setStatus (url)
+
+ # ---------------------------------------------------------------------------
+ # Run a form
+ # ---------------------------------------------------------------------------
+
+ def runForm (self, step, parameters = {}):
+ """
+ This function runs a GNStep with a GNUe Form definition.
+
+ @param step: the GNStep instance describing the form
+ @param paramters: dictionary with user parameters for the form
+ """
+
+ # TODO: this code *should* be executed in a new thread.
+ if os.path.basename (step.location) == step.location:
try:
- formdir = gConfigNav('FormDir')
+ formdir = gConfigNav ('FormDir')
+
except KeyError:
formdir = ""
- formfile = formdir+"/"+step.location
+
+ formfile = os.path.join (formdir, step.location)
+
else:
formfile = step.location
- self.setStatus('running form %s' % formfile)
- self._runForm(formfile, parameters)
+ try:
+ self.beginWait ()
+ self.setStatus ('running form %s' % formfile)
+ self._runForm (formfile, parameters)
+ finally:
+ self.endWait ()
+ self.setStatus ()
- def _runForm(self, formfile, parameters):
+
+ # ---------------------------------------------------------------------------
+ # Run a form from a trigger
+ # ---------------------------------------------------------------------------
+
+ def runFormFromTrigger (self, form, parameters = {}):
+ """
+ This function runs a form from trigger code.
+
+ @param form: URL of the form
+ @param parameters: dictionary with user parameters for the form
+ """
+
try:
- #
- # Create the instance
- #
- #instance = GFInstance(id(self),
- # connections=self.connections,
- # ui=ui, disableSplash=1)
- instance = GFInstance(self,connections=self.connections,
- ui=ui,disableSplash=1, parameters=parameters)
- self._formInstances[id(self)] = instance
+ self.beginWait ()
+ self.setStatus ('running form %s from trigger' % formfile)
+
+ self._runForm (form, self._params)
+
+ finally:
+ self.endWait ()
+ self.setStatus ()
+
+
+ # ---------------------------------------------------------------------------
+ # Do the dirty work of running a form
+ # ---------------------------------------------------------------------------
+
+ def _runForm (self, formfile, parameters):
+ """
+ This function starts a new form.
+
+ @param formfile: URL of the form to be started
+ @param parameters: dictionary with user parameters for the form
+ """
+
+ instance = GFInstance (self, self.connections, ui, True, parameters)
+ self._formInstances [id (self)] = instance
- #
- # Build the form tree
- #
- instance.addFormFromFile(formfile)
+ instance.addFormFromFile (formfile)
+ instance.addDialogs ()
+ instance.activate ()
- #
- # Start the instance
- #
- instance.addDialogs()
-
- #instance.buildForm(form)
- instance.activate()
- except GConnections.Error, mesg:
- self.handleError(mesg)
+ # ---------------------------------------------------------------------------
+ # Open another process definition file
+ # ---------------------------------------------------------------------------
- except IOError, mesg:
- self.handleError(_("Unable to open file\n\n %s")%mesg)
+ def __openFile (self, obj, more, muchmore):
+ """
+ This function displays a 'FileSelection' dialog to select other GPD files.
+ If a file was selected it will be loaded into a new process tree.
+ """
- except GDataObjects.ConnectError, mesg:
- self.handleError(\
- _("Unable to login to datasource.\n\n %s") %mesg)
+ self.filesel = gtk.FileSelection ( \
+ u_("Select another process definition file"))
+ self.filesel.ok_button.connect ('clicked', \
+ lambda w, self: self.__reload (self.filesel.get_filename ()), self)
+ self.filesel.cancel_button.connect ('clicked', \
+ lambda obj, self: self.filesel.destroy (), self)
+ self.filesel.hide_fileop_buttons ()
+ self.filesel.complete ('*.gpd')
- except GDataObjects.ConnectionError, mesg:
- self.handleError(\
- _("Error while communicating with datasource.\n\n %s") %mesg)
+ self.filesel.show ()
- except GDataObjects.Error, mesg:
- self.handleError(mesg)
- print 'closed'
+ # ---------------------------------------------------------------------------
+ # Load another process definition file
+ # ---------------------------------------------------------------------------
- def createMenuBar(self):
+ def __reload (self, filename):
+ """
+ This function loads a new process tree from the given filename and replaces
+ the current tree view with the new process tree.
- menu_items = (
- ('/_File', None, None, 0, '<Branch>' ),
-# ('/File/_New', '<control>N', menuitem_cb, 0, '<StockItem>',
gtk.STOCK_NEW),
- ('/File/_Open', '<control>O', self.OnOpen, 0, '<StockItem>',
gtk.STOCK_OPEN),
-# ('/File/_Save', '<control>S', menuitem_cb, 0, '<StockItem>',
gtk.STOCK_SAVE),
-# ('/File/Save _As...', None, menuitem_cb, 0, '<StockItem>',
gtk.STOCK_SAVE),
- ('/File/_Quit', '<control>Q', self.OnClose, 0, '<StockItem>',
gtk.STOCK_QUIT),
-
- ('/_Favorites', None, None, 0, '<Branch>'),
- ('/_Favorites/_Add Favorite', None, None, 0, ''),
- ('/_Favorites/_Organize Favorites', None, None, 0, ''),
-
- ('/_Help', None, None, 0, '<Branch>'),
- ('/Help/_About', None, self.OnAbout, 0,''),
- )
+ @param filename: name of the GPD file to be loaded
+ """
- self.accel_group = gtk.AccelGroup()
- self.mainWindow.add_accel_group(self.accel_group)
-
- self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>',
self.accel_group)
-
- self.item_factory.create_items(menu_items, self.mainWindow)
-
- return self.item_factory.get_widget('<main>')
+ if self.filesel is not None:
+ self.filesel.destroy ()
+ fhd = openResource (filename)
+
+ try:
+ processes = GNParser.loadProcesses (fhd)
+ newModel = self.__buildTreeModel (processes)
+ self.processes = processes
+ self.__treeStore = newModel
+ self.treeView.set_model (newModel)
+ self.treeView.expand_row ((0,), False)
+ self.treeView.set_cursor ((0,))
+ self.treeView.grab_focus ()
+
+ finally:
+ fhd.close ()
+
+
+ # ---------------------------------------------------------------------------
+ # Display a nice about message
+ # ---------------------------------------------------------------------------
+
+ def __about (self, obj, more, muchmore):
+ """
+ This function displays an about box.
+ """
+
+ text = _("GNUE Navigator")+"\n"+ \
+ _(" Version : ")+"%s\n"+ \
+ _(" Driver : UIgtk2")+"\n"+ \
+ _("-= Process Info =- ")+"\n"+ \
+ _(" Name : ")+"%s\n"+ \
+ _(" Version: ")+"%s\n"+ \
+ _(" Author : ")+"%s\n"+ \
+ _(" Description: ")+"%s\n"
+ dlg = gtk.MessageDialog(self.mainWindow,
+ gtk.DIALOG_DESTROY_WITH_PARENT + gtk.DIALOG_MODAL,
+ gtk.MESSAGE_INFO,
+ gtk.BUTTONS_CLOSE,
+ text % (VERSION,'-','-','-','-'))
+ dlg.connect ('response', lambda dlg, response: dlg.destroy ())
+ dlg.show ()
Property changes on: trunk/gnue-navigator/src/UIgtk2.py
___________________________________________________________________
Name: svn:keywords
+ Id
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r6542 - trunk/gnue-navigator/src,
johannes <=