root/tags/dabo-0.2/dApp.py

Revision 490, 12.5 kB (checked in by paul, 4 years ago)

Added a version.py file to dabo to track the version, and made it import
into the dabo namespace. Changed the dApp initialization to use that value
instead of the hardcoded 0.1 which has been in there since the beginning.

Added some summary changelog entries for 0.2 which we'll be releasing later
today.

  • Property svn:eol-style set to native
Line 
1 """
2     dApp.py : The application object for Dabo.
3
4     This object gets instantiated from the client app's main.py,
5     and lives through the life of the application.
6
7         -- set up an empty data connections object which holds
8         -- connectInfo objects connected to pretty names. Entries
9         -- can be added programatically, but upon initialiazation
10         -- it will look for a file called 'dbConnectionDefs.py' which
11         -- contains connection definitions.
12
13         -- Set up a DB Connection manager, that is basically a dictionary
14         -- of dConnection objects. This allows connections to be shared
15         -- application-wide.
16
17         -- decide which ui to use (wx) and gets that ball rolling
18
19         -- make a system menu bar, based on a combination
20         -- of dabo defaults and user resource files.
21
22         -- ditto for toolbar(s)
23
24         -- look for a mainFrame ui resource file in an expected
25         -- place, otherwise uses default dabo mainFrame, and
26         -- instantiate that.
27
28         -- maintain a forms collection and provide interfaces for
29         -- opening dForms, closing them, and iterating through them.
30
31         -- start the main app event loop.
32
33         -- clean up and exit gracefully
34 """
35 import sys, os, warnings
36 import dabo, dabo.ui, dabo.db
37 import dabo.common, dSecurityManager
38 from dLocalize import _
39
40 class Collection(list):
41     """
42     Collection : Base class for the various collection
43                     classes used in the app object.
44     """
45
46     def __init__(self):
47         list.__init__(self)
48
49     def add(self, objRef):
50         """
51         Collection.add(objRef)
52             Add the object reference to the collection.
53         """
54         self.append(objRef)
55
56     def remove(self, objRef):
57         """
58         Collection.remove(objRef)
59             Delete the object reference from the collection.
60         """
61         try:
62             index = self.index(objRef)
63         except ValueError:
64             index = None
65         if index is not None:
66             del self[index]
67
68
69 class dApp(dabo.common.dObject):
70     """ dabo.dApp
71
72         The containing object for the entire application.
73         Various UI's will have app objects also, which
74         dabo.App is a wrapper for.
75     """
76     def __init__(self):
77         self._uiAlreadySet = False
78         dabo.dAppRef = self
79         dApp.doDefault()
80         self._initProperties()
81        
82 ### PKM: commented this out as I don't understand the need for it       
83 #       # Params may need to be sent to the main frame. These two
84 #       # props allow that
85 #       self.mainFrameParamList = []
86 #       self.mainFrameKeyParamList = {}
87
88     def setup(self):
89         """ Set up the app - call this before start()."""
90
91         # dabo is going to want to import various things from the homeDir
92         sys.path.append(self.homeDir)
93
94         if not self.getAppInfo("appName"):
95             self.setAppInfo("appName", "Dabo")
96         if not self.getAppInfo("appVersion"):
97             self.setAppInfo("appVersion", dabo.version["version"])
98         if not self.getAppInfo("vendorName"):
99             self.setAppInfo("vendorName", "Dabo")
100
101         self._initDB()
102         self._initUI()
103
104         self.uiApp = dabo.ui.uiApp()
105
106         self.actionList.setAction("FileExit", self.uiApp.onFileExit)
107         self.actionList.setAction("HelpAbout", self.uiApp.onHelpAbout)
108         self.actionList.setAction("EditPreferences", self.uiApp.onEditPreferences)
109         self.actionList.setAction("EditCut", self.uiApp.onEditCut)
110         self.actionList.setAction("EditCopy", self.uiApp.onEditCopy)
111         self.actionList.setAction("EditPaste", self.uiApp.onEditPaste)
112         self.actionList.setAction("EditFind", self.uiApp.onEditFind)
113         self.actionList.setAction("EditFindAgain", self.uiApp.onEditFindAgain)
114         self.actionList.setAction("EditUndo", self.uiApp.onEditUndo)
115         self.actionList.setAction("EditRedo", self.uiApp.onEditRedo)
116
117         self.uiApp.setup(self)
118
119
120     def start(self):
121         """
122         Start the application event loop, which involves
123             wrapping the application object for the ui library
124             being used.
125         """
126         if (not self.SecurityManager or not self.SecurityManager.RequireAppLogin
127             or self.SecurityManager.login()):
128            
129             userName = self.getUserCaption()
130             if userName:
131                 userName = " (%s)" % userName
132             else:
133                 userName = ""
134                
135             self.uiApp.start(self)
136         self.finish()
137
138
139     def finish(self):
140         """
141         The main event loop has exited and the application
142             is about to finish.
143         """
144         self.uiApp.finish()
145         dabo.infoLog.write(_("Application finished."))
146         pass
147
148
149     def getAppInfo(self, item):
150         """ dApp.getAppInfo(self, item) -> value
151
152             Look up the item, and return the value.
153         """
154         try:
155             retVal = self._appInfo[item]
156         except KeyError:
157             retVal = None
158         return retVal
159
160
161     def setAppInfo(self, item, value):
162         """ dApp.getAppInfo(self, item, value) -> None
163
164             Set item to value in the appinfo table.
165         """
166         self._appInfo[item] = value
167
168
169     def getUserSetting(self, item, user="*", system="*"):
170         """ Return the value of the user settings table that
171             corresponds to the item, user, and system id
172             passed. Based on the ctype field in the table,
173             convert the return value into the appropriate
174             type first.
175
176             Types:    I: Int
177                     N: Float
178                     C: String
179                     M: String
180                     D: Date, saved as a string 3-tuple
181                         of integers '(year,month,day)'
182                     T: DateTime, saved as a string
183                         9-tuple of integers '(year,month,
184                         day,hour,minute,second,?,?,?)'
185
186         """
187         import ConfigParser
188
189         configFileName = '%s/.userSettings.ini' % self.homeDir
190
191         cp = ConfigParser.ConfigParser()
192         cp.read(configFileName)
193
194         try:
195             valueType = cp.get("UserSettingsValueTypes", item)
196         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
197             valueType = "C"
198
199         try:
200             if valueType == "I":
201                 value = cp.getint("UserSettings", item)
202             elif valueType == "N":
203                 value = cp.getfloat("UserSettings", item)
204             elif valueType == "L":
205                 value = cp.getboolean("UserSettings", item)
206             else:
207                 value = cp.get("UserSettings", item)
208         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
209             value = None
210
211         return value
212
213
214     def setUserSetting(self, item, valueType, value, user="*", system="*"):
215         """ Set the value of the user settings table that corresponds to the
216             item, user, and systemid passed. If it doesn't exist in the table,
217             add it. See self.getUserSetting() for the type codes.
218         """
219         # For now, save this info in a plain ini file. Eventually, I'd like
220         # to see this get saved in a persistent dabosettings db table.
221         import ConfigParser
222
223         configFileName = '%s/.userSettings.ini' % self.homeDir
224
225         cp = ConfigParser.ConfigParser()
226         cp.read(configFileName)
227
228         # convert value to string type for saving to db:
229         value = str(value)
230
231         if not cp.has_section("UserSettings"):
232             cp.add_section("UserSettings")
233         cp.set("UserSettings", item, value)
234
235         if not cp.has_section("UserSettingsValueTypes"):
236             cp.add_section("UserSettingsValueTypes")
237         cp.set("UserSettingsValueTypes", item, valueType)
238
239         configFile = open(configFileName, 'w')
240         cp.write(configFile)
241         configFile.close()
242        
243        
244     def getUserCaption(self):
245         """ Return the full name of the currently logged-on user.
246         """
247         if self.SecurityManager:
248             return self.SecurityManager.UserCaption
249         else:
250             return None
251            
252
253     def _initProperties(self):
254         """ Initialize the public properties of the app object. """
255
256         # it is useful to know from where we came
257         # Note: sometimes the runtime distros will alter the path so
258         # that the first entry is not a valid directory. Go throught the path
259         # and use the first valid directory.
260         ###self.homeDir = sys.path[0]
261         for pth in sys.path:
262             if os.path.exists(os.path.join(pth, ".")):
263                 self.homeDir = pth
264                 break
265        
266
267         self.uiType   = None    # ('wx', 'qt', 'curses', 'http', etc.)
268         #self.uiModule = None
269
270         # Initialize UI collections
271         self.uiForms = Collection()
272         self.uiMenus = Collection()
273         self.uiToolBars = Collection()
274         self.uiResources = {}
275
276         self.actionList = dabo.ui.dActionList()
277
278         # Initialize DB collections
279         self.dbConnectionDefs = {}
280
281         self._appInfo = {}
282
283     def _initDB(self):
284         """ Set the available connection definitions for use by the app. """
285
286         dbConnectionDefs = None
287         try:
288             import dbConnectionDefs
289             dbConnectionDefs = dbConnectionDefs.getDefs()
290         except (ImportError, NameError, AttributeError):
291             dbConnectionDefs = None
292
293         if dbConnectionDefs and type(dbConnectionDefs) == type(dict()):
294             # For each connection definition, add an entry to
295             # self.dbConnectionDefs that contains a key on the
296             # name, and a value of a dConnectInfo object.
297             for entry in dbConnectionDefs:
298                 try:             dbType   = dbConnectionDefs[entry]['dbType']
299                 except KeyError: dbType   = None
300                 try:             host     = dbConnectionDefs[entry]['host']
301                 except KeyError: host     = None
302                 try:             user     = dbConnectionDefs[entry]['user']
303                 except KeyError: user     = None
304                 try:             password = dbConnectionDefs[entry]['password']
305                 except KeyError: password = None
306                 try:             dbName   = dbConnectionDefs[entry]['dbName']
307                 except KeyError: dbName   = None
308                 try:             port     = dbConnectionDefs[entry]['port']
309                 except KeyError: port     = None
310
311                 self.dbConnectionDefs[entry] = dabo.db.dConnectInfo(backendName=dbType,
312                         host=host,
313                         user=user,
314                         password=password,
315                         dbName=dbName,
316                         port=port)
317
318             dabo.infoLog.write(_("%s database connection definition(s) loaded.") % (
319                                                 len(self.dbConnectionDefs)))
320
321         else:
322             dabo.infoLog.write(_("No database connection definitions loaded (dbConnectionDefs.py)"))
323
324
325     def _initUI(self):
326         """ Set the user-interface library for the application.
327         
328         Ignored if the UI was already explicitly set by user code.
329         """
330         if self.UI is None and not self._uiAlreadySet:
331             # For now, default to wx, but it should be enhanced to read an
332             # application config file. Actually, that may not be necessary, as the
333             # user's main.py can just set the UI directly now: dApp.UI = "qt".
334             self.UI = "wx"
335         else:
336             # Custom app code or the dabo.ui module already set this: don't touch
337             dabo.infoLog.write(_("User interface already set to '%s', so dApp didn't "
338                 " touch it." % (self.UI,)))
339
340
341     def _getAutoNegotiateUniqueNames(self):
342         try:
343             return self._autoNegotiateUniqueNames
344         except AttributeError:
345             return True
346    
347     def _setAutoNegotiateUniqueNames(self, value):
348         self._autoNegotiateUniqueNames = bool(value)
349        
350    
351     def _getMainForm(self):
352         try:
353             f = self._mainForm
354         except AttributeError:
355             f = None
356             self._mainForm = None
357         return f
358            
359     def _setMainForm(self, val):
360         self._mainForm = val
361
362                
363     def _getMainFormClass(self):
364         try:
365             c = self._mainFormClass
366         except AttributeError:
367             c = dabo.ui.dFormMain
368             self._mainFormClass = c
369         return c
370            
371     def _setMainFormClass(self, val):
372         self._mainFormClass = val
373        
374        
375     def _getSecurityManager(self):
376         try:
377             return self._securityManager
378         except AttributeError:
379             return None
380            
381     def _setSecurityManager(self, value):
382         if isinstance(value, dSecurityManager.dSecurityManager):
383             if self.SecurityManager:
384                 warnings.warn(Warning, _('SecurityManager previously set'))
385             self._securityManager = value
386         else:
387             raise TypeError, _('SecurityManager must descend from dSecurityManager.')
388            
389            
390     def _getUI(self):
391         try:
392             return dabo.ui.getUIType()
393         except AttributeError:
394             return None
395            
396     def _setUI(self, uiType):
397         # Load the appropriate ui module. dabo.ui will now contain
398         # the classes of that library, wx for instance.
399         if self.UI is None:
400             if dabo.ui.loadUI(uiType):
401                 self._uiAlreadySet = True
402                 dabo.infoLog.write(_("User interface set to '%s' by dApp.") % (uiType,))
403             else:
404                 dabo.infoLog.write(_("Tried to set UI to '%s', but it failed." % (uiType,)))
405         else:
406             raise RuntimeError, _("The UI cannot be reset once assigned.")
407    
408    
409     AutoNegotiateUniqueNames = property(_getAutoNegotiateUniqueNames,_setAutoNegotiateUniqueNames,
410                         None, _("Specifies whether setting an object\'s name to a non-unique "
411                         "value results in a unique integer being appended, or whether "
412                         "a NameError is raised. Default is True: negotiate the name."))
413
414     MainForm = property(_getMainForm, _setMainForm, None,
415         _("The object reference to the main form of the application, or None. This gets "
416         "set automatically during application setup, based on the MainFormClass."))
417        
418     MainFormClass = property(_getMainFormClass, _setMainFormClass, None,
419         _("Specifies the class to use to instantiate the main form. Defaults to "
420         "the dFormMain base class. Set to None if you don't want a main form."))
421        
422     UI = property(_getUI, _setUI,
423                         None, _("Specifies the user interface to load, or None. "
424                         "Once set, it cannot be reassigned."))
425    
426     SecurityManager = property(_getSecurityManager, _setSecurityManager,
427                         None, _("Specifies the Security Manager, if any. You "
428                         "must subclass dSecurityManager, overriding the appropriate hooks "
429                         "and properties, and then set dApp.SecurityManager to an instance "
430                         "of your subclass. There is no security manager by default - you "
431                         "explicitly set this to use Dabo security."))
Note: See TracBrowser for help on using the browser.