DocView and ActiveGrid IDE updates from Morgan Hua:
New Features: In Tab-View mode, Ctrl-number will take the user to
    the numbered tab view.  Modified files now show an '*' astrisk in
    the view title.  Debugger framework can now support PHP debugging.
    Not important for python development, but at least that means the
    debugger framework is more generalized.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38852 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
			
			
This commit is contained in:
		
							
								
								
									
										20
									
								
								wxPython/samples/ide/activegrid/model/projectmodel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								wxPython/samples/ide/activegrid/model/projectmodel.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| #---------------------------------------------------------------------------- | ||||
| # Name:         projectmodel.py | ||||
| # Purpose:      This file contains project model information | ||||
| # | ||||
| # Author:       Morgan Hua | ||||
| # | ||||
| # Created:      4/18/06 | ||||
| # CVS-ID:       $Id$ | ||||
| # Copyright:    (c) 2006 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
| # Constants | ||||
| #---------------------------------------------------------------------------- | ||||
| LANGUAGE_PYTHON = "python" | ||||
| LANGUAGE_PHP = "php" | ||||
| LANGUAGE_DEFAULT = LANGUAGE_PYTHON | ||||
| LANGUAGE_LIST = [LANGUAGE_PHP, LANGUAGE_PYTHON] | ||||
| @@ -5,7 +5,7 @@ | ||||
| # Author:       Morgan Hua | ||||
| # | ||||
| # Created:      3/22/05 | ||||
| # Copyright:    (c) 2005 ActiveGrid, Inc. | ||||
| # Copyright:    (c) 2005-2006 ActiveGrid, Inc. | ||||
| # CVS-ID:       $Id$ | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
| @@ -30,23 +30,25 @@ licenseData = [  # add licenses for base IDE features | ||||
|     ("Python 2.4", "Python Software Foundation License", "http://www.python.org/2.4/license.html"), | ||||
|     ("wxPython 2.6", "wxWidgets 2 - LGPL", "http://wxwidgets.org/newlicen.htm"), | ||||
|     ("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.6.1/wx_wxlicense.html"), | ||||
|     ("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"),  | ||||
|     ("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"), | ||||
|     ("process.py", "See file", "http://starship.python.net/~tmick/"), | ||||
|     ("pysvn", "Apache License, Version 2.0", "http://pysvn.tigris.org/"), | ||||
| ] | ||||
|  | ||||
| if not ACTIVEGRID_BASE_IDE:    # add licenses for non-base IDE features such as database connections | ||||
|     licenseData += [ | ||||
|         ("pydb2", "LGPL", "http://sourceforge.net/projects/pydb2"),  | ||||
|         ("pydb2", "LGPL", "http://sourceforge.net/projects/pydb2"), | ||||
|         ("pysqlite", "Python License (CNRI)", "http://sourceforge.net/projects/pysqlite"), | ||||
|         ("mysql-python", "GPL, Python License (CNRI), Zope Public License", "http://sourceforge.net/projects/mysql-python"),  | ||||
|         ("cx_Oracle", "Computronix", "http://www.computronix.com/download/License(cxOracle).txt"),  | ||||
|         ("mysql-python", "GPL, Python License (CNRI), Zope Public License", "http://sourceforge.net/projects/mysql-python"), | ||||
|         ("cx_Oracle", "Computronix", "http://www.computronix.com/download/License(cxOracle).txt"), | ||||
|         ("SQLite", "Public Domain", "http://www.sqlite.org/copyright.html"), | ||||
|         ("PyGreSQL", "BSD", "http://www.pygresql.org"), | ||||
|         ("pyXML", "CNRI Python License", "http://sourceforge.net/softwaremap/trove_list.php?form_cat=194"), | ||||
|         ("Zolera Soap Infrastructure", "Zope Public License 2.0", "http://www.zope.org/Resources/License/"), | ||||
|         ("python-ldap", "Python Software Foundation License", "http://python-ldap.sourceforge.net"), | ||||
|         ("Sarissa", "LGPL", "http://sourceforge.net/projects/sarissa/"), | ||||
|         ("Dynarch DHTML Calendar", "LGPL", "http://www.dynarch.com/projects/calendar/"), | ||||
|         ("python-dateutil", "Python Software Foundation License", "http://labix.org/python-dateutil"),         | ||||
|     ] | ||||
|  | ||||
| if wx.Platform == '__WXMSW__':  # add Windows only licenses | ||||
| @@ -70,7 +72,7 @@ class AboutDialog(wx.Dialog): | ||||
|         else: | ||||
|             splash_bmp = getIDESplashBitmap() | ||||
|  | ||||
|         # find version number from  | ||||
|         # find version number from | ||||
|         versionFilepath = os.path.join(sysutilslib.mainModuleDir, "version.txt") | ||||
|         if os.path.exists(versionFilepath): | ||||
|             versionfile = open(versionFilepath, 'r') | ||||
| @@ -82,7 +84,7 @@ class AboutDialog(wx.Dialog): | ||||
|  | ||||
|         image = wx.StaticBitmap(aboutPage, -1, splash_bmp, (0,0), (splash_bmp.GetWidth(), splash_bmp.GetHeight())) | ||||
|         sizer.Add(image, 0, wx.ALIGN_CENTER|wx.ALL, 0) | ||||
|         sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\n%s\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors.  All rights reserved.") % version), 0, wx.ALIGN_LEFT|wx.ALL, 10) | ||||
|         sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\n%s\n\nCopyright (c) 2003-2006 ActiveGrid Incorporated and Contributors.  All rights reserved.") % version), 0, wx.ALIGN_LEFT|wx.ALL, 10) | ||||
|         sizer.Add(wx.StaticText(aboutPage, -1, _("http://www.activegrid.com")), 0, wx.ALIGN_LEFT|wx.LEFT|wx.BOTTOM, 10) | ||||
|         aboutPage.SetSizer(sizer) | ||||
|         nb.AddPage(aboutPage, _("Copyright")) | ||||
| @@ -90,15 +92,14 @@ class AboutDialog(wx.Dialog): | ||||
|         licensePage = wx.Panel(nb, -1) | ||||
|         grid = wx.grid.Grid(licensePage, -1) | ||||
|         grid.CreateGrid(len(licenseData), 2) | ||||
|          | ||||
|  | ||||
|         dc = wx.ClientDC(grid) | ||||
|         dc.SetFont(grid.GetLabelFont()) | ||||
|         grid.SetColLabelValue(0, _("License")) | ||||
|         grid.SetColLabelValue(1, _("URL")) | ||||
|         w, maxHeight = dc.GetTextExtent(_("License")) | ||||
|         w, h = dc.GetTextExtent(_("URL")) | ||||
|         if h > maxHeight: | ||||
|             maxHeight = h | ||||
|         w, h1 = dc.GetTextExtent(_("License")) | ||||
|         w, h2 = dc.GetTextExtent(_("URL")) | ||||
|         maxHeight = max(h1, h2) | ||||
|         grid.SetColLabelSize(maxHeight + 6)  # add a 6 pixel margin | ||||
|  | ||||
|         maxW = 0 | ||||
| @@ -115,7 +116,7 @@ class AboutDialog(wx.Dialog): | ||||
|                 grid.SetCellValue(row, 0, license) | ||||
|             if url: | ||||
|                 grid.SetCellValue(row, 1, url) | ||||
|          | ||||
|  | ||||
|         grid.EnableEditing(False) | ||||
|         grid.EnableDragGridSize(False) | ||||
|         grid.EnableDragColSize(False) | ||||
| @@ -132,10 +133,10 @@ class AboutDialog(wx.Dialog): | ||||
|  | ||||
|         creditsPage = wx.Panel(nb, -1) | ||||
|         sizer = wx.BoxSizer(wx.VERTICAL) | ||||
|         sizer.Add(wx.StaticText(creditsPage, -1, _("ActiveGrid Development Team:\n\nLarry Abrahams\nLawrence Bruhmuller\nEric Chu\nBeth Fryer\nMatt Fryer\nJoel Hare\nMorgan Hua\nMatt McNulty\nPratik Mehta\nAlan Mullendore\nJeff Norton\nSimon Toens\nKevin Wang\nPeter Yared")), 0, wx.ALIGN_LEFT|wx.ALL, 10) | ||||
|         sizer.Add(wx.StaticText(creditsPage, -1, _("ActiveGrid Development Team:\n\nLarry Abrahams\nLawrence Bruhmuller\nEric Chu\nBeth Fryer\nMatt Fryer\nFrankie Fu\nJoel Hare\nMorgan Hua\nMatt McNulty\nPratik Mehta\nAlan Mullendore\nJeff Norton\nKevin Ollivier\nMatt Small\nSimon Toens\nKevin Wang\nPeter Yared\nJeremy Yun")), 0, wx.ALIGN_LEFT|wx.ALL, 10) | ||||
|         creditsPage.SetSizer(sizer) | ||||
|         nb.AddPage(creditsPage, _("Credits")) | ||||
|              | ||||
|  | ||||
|         sizer = wx.BoxSizer(wx.VERTICAL) | ||||
|         sizer.Add(nb, 0, wx.ALIGN_CENTRE|wx.ALL, 5) | ||||
|         btn = wx.Button(self, wx.ID_OK) | ||||
| @@ -145,5 +146,5 @@ class AboutDialog(wx.Dialog): | ||||
|         self.Layout() | ||||
|         self.Fit() | ||||
|         grid.ForceRefresh()  # wxBug: Get rid of unnecessary scrollbars | ||||
|          | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,7 @@ PARKING_VERTICAL = 1 | ||||
| PARKING_HORIZONTAL = 2 | ||||
| PARKING_OFFSET = 30    # space between shapes | ||||
|  | ||||
| FORCE_REDRAW_METHOD = "ForceRedraw" | ||||
|  | ||||
| def GetRawModel(model): | ||||
|     if hasattr(model, "GetRawModel"): | ||||
| @@ -85,6 +86,7 @@ class CanvasView(wx.lib.docview.View): | ||||
|         self._propShape = None | ||||
|         self._maxWidth = 2000 | ||||
|         self._maxHeight = 16000 | ||||
|         self._valetParking = False | ||||
|  | ||||
|  | ||||
|     def OnDraw(self, dc): | ||||
| @@ -195,6 +197,16 @@ class CanvasView(wx.lib.docview.View): | ||||
|         self.SetPropertyModel(None) | ||||
|                    | ||||
|  | ||||
|     def SetLastRightClick(self, x, y): | ||||
|         self._lastRightClick = (x,y) | ||||
|          | ||||
|  | ||||
|     def GetLastRightClick(self): | ||||
|         if hasattr(self, "_lastRightClick"): | ||||
|             return self._lastRightClick | ||||
|         return (-1,-1) | ||||
|          | ||||
|  | ||||
|     def OnKeyPressed(self, event): | ||||
|         key = event.KeyCode() | ||||
|         if key == wx.WXK_DELETE: | ||||
| @@ -211,6 +223,7 @@ class CanvasView(wx.lib.docview.View): | ||||
|         dc = wx.ClientDC(self._canvas) | ||||
|         self._canvas.PrepareDC(dc) | ||||
|         x, y = event.GetLogicalPosition(dc)  # this takes into account scrollbar offset | ||||
|         self.SetLastRightClick(x, y) | ||||
|         shape = self._canvas.FindShape(x, y)[0] | ||||
|          | ||||
|         model = None | ||||
| @@ -260,12 +273,15 @@ class CanvasView(wx.lib.docview.View): | ||||
|             pass | ||||
|         else: | ||||
|             # click on empty part of canvas, deselect everything | ||||
|             forceRedrawShapes = [] | ||||
|             needRefresh = False | ||||
|             for shape in self._diagram.GetShapeList(): | ||||
|                 if hasattr(shape, "GetModel"): | ||||
|                     if shape.Selected(): | ||||
|                         needRefresh = True | ||||
|                         shape.Select(False, dc) | ||||
|                         if hasattr(shape, FORCE_REDRAW_METHOD): | ||||
|                             forceRedrawShapes.append(shape) | ||||
|             if needRefresh: | ||||
|                 self._canvas.Redraw(dc) | ||||
|  | ||||
| @@ -274,7 +290,8 @@ class CanvasView(wx.lib.docview.View): | ||||
|         if len(self.GetSelection()) == 0: | ||||
|             self.SetPropertyShape(None) | ||||
|  | ||||
|  | ||||
|         for shape in forceRedrawShapes: | ||||
|             shape.ForceRedraw() | ||||
|  | ||||
|     def OnLeftDoubleClick(self, event): | ||||
|         propertyService = wx.GetApp().GetService(PropertyService.PropertyService) | ||||
| @@ -401,8 +418,20 @@ class CanvasView(wx.lib.docview.View): | ||||
|         dc.EndDrawing() | ||||
|  | ||||
|  | ||||
|     def SetValetParking(self, enable=True): | ||||
|         """ If valet parking is enabled, remember last parking spot and try for a spot near it """ | ||||
|         self._valetParking = enable | ||||
|         if enable: | ||||
|             self._valetPosition = None | ||||
|          | ||||
|  | ||||
|     def FindParkingSpot(self, width, height, parking=PARKING_HORIZONTAL, x=PARKING_OFFSET, y=PARKING_OFFSET): | ||||
|         """ given a width and height, find a upper left corner where shape can be parked without overlapping other shape """ | ||||
|         """ | ||||
|             Given a width and height, find a upper left corner where shape can be parked without overlapping other shape | ||||
|         """ | ||||
|         if self._valetParking and self._valetPosition: | ||||
|             x, y = self._valetPosition | ||||
|          | ||||
|         max = 700  # max distance to the right where we'll place tables | ||||
|         noParkingSpot = True | ||||
|  | ||||
| @@ -422,6 +451,9 @@ class CanvasView(wx.lib.docview.View): | ||||
|             else: | ||||
|                 noParkingSpot = False | ||||
|  | ||||
|         if self._valetParking: | ||||
|             self._valetPosition = (x, y) | ||||
|              | ||||
|         return x, y | ||||
|  | ||||
|  | ||||
| @@ -518,7 +550,8 @@ class CanvasView(wx.lib.docview.View): | ||||
|                         self._diagram.RemoveShape(line) | ||||
|                         line.Delete() | ||||
|                      | ||||
|             shape.RemoveFromCanvas(self._canvas) | ||||
|             if self._canvas: | ||||
|                 shape.RemoveFromCanvas(self._canvas) | ||||
|             self._diagram.RemoveShape(shape) | ||||
|             shape.Delete() | ||||
|  | ||||
| @@ -698,6 +731,9 @@ class CanvasView(wx.lib.docview.View): | ||||
|                 self._propShape.SetTextColour("WHITE", 0) | ||||
|             self._propShape.Draw(dc) | ||||
|  | ||||
|             if hasattr(self._propShape, FORCE_REDRAW_METHOD): | ||||
|                 self._propShape.ForceRedraw() | ||||
|  | ||||
|         dc.EndDrawing() | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -19,7 +19,6 @@ import os | ||||
| import re | ||||
| import string | ||||
| import sys | ||||
| import DebuggerService | ||||
| import MarkerService | ||||
| from UICommon import CaseInsensitiveCompare | ||||
| _ = wx.GetTranslation | ||||
| @@ -120,16 +119,27 @@ class CodeView(STCTextEditor.TextView): | ||||
|             return False | ||||
|         id = event.GetId() | ||||
|         if id == EXPAND_TEXT_ID: | ||||
|             event.Enable(self.GetCtrl().CanLineExpand(self.GetCtrl().GetCurrentLine())) | ||||
|             if self.GetCtrl().GetViewFolding(): | ||||
|                 event.Enable(self.GetCtrl().CanLineExpand(self.GetCtrl().GetCurrentLine())) | ||||
|             else: | ||||
|                 event.Enable(False) | ||||
|             return True | ||||
|         elif id == COLLAPSE_TEXT_ID: | ||||
|             event.Enable(self.GetCtrl().CanLineCollapse(self.GetCtrl().GetCurrentLine())) | ||||
|             if self.GetCtrl().GetViewFolding(): | ||||
|                 event.Enable(self.GetCtrl().CanLineCollapse(self.GetCtrl().GetCurrentLine())) | ||||
|             else: | ||||
|                 event.Enable(False) | ||||
|             return True | ||||
|         elif (id == EXPAND_TOP_ID | ||||
|         or id == COLLAPSE_TOP_ID | ||||
|         or id == EXPAND_ALL_ID | ||||
|         or id == COLLAPSE_ALL_ID | ||||
|         or id == AUTO_COMPLETE_ID | ||||
|         or id == COLLAPSE_ALL_ID): | ||||
|             if self.GetCtrl().GetViewFolding(): | ||||
|                 event.Enable(self.GetCtrl().GetTextLength() > 0) | ||||
|             else: | ||||
|                 event.Enable(False) | ||||
|             return True             | ||||
|         elif (id == AUTO_COMPLETE_ID | ||||
|         or id == CLEAN_WHITESPACE | ||||
|         or id == INDENT_LINES_ID | ||||
|         or id == DEDENT_LINES_ID | ||||
| @@ -140,10 +150,12 @@ class CodeView(STCTextEditor.TextView): | ||||
|         elif id == CHECK_CODE_ID: | ||||
|             event.Enable(False) | ||||
|             return True | ||||
|         elif (id == SET_INDENT_WIDTH_ID | ||||
|         or id == FOLDING_ID): | ||||
|         elif id == SET_INDENT_WIDTH_ID: | ||||
|             event.Enable(True) | ||||
|             return True | ||||
|         elif id == FOLDING_ID: | ||||
|             event.Enable(self.GetCtrl().GetViewFolding()) | ||||
|             return True | ||||
|         elif id == USE_TABS_ID: | ||||
|             event.Enable(True) | ||||
|             event.Check(self.GetCtrl().GetUseTabs()) | ||||
| @@ -210,7 +222,7 @@ class CodeView(STCTextEditor.TextView): | ||||
|         filename = document.GetFilename() | ||||
|         if filename: | ||||
|             rootItem = treeCtrl.AddRoot(os.path.basename(filename)) | ||||
|             treeCtrl.SetDoSelectCallback(rootItem, self, None) | ||||
|             treeCtrl.SetDoSelectCallback(rootItem, self, (0,0)) | ||||
|         else: | ||||
|             return True | ||||
|  | ||||
| @@ -232,11 +244,13 @@ class CodeView(STCTextEditor.TextView): | ||||
|             if classLine: | ||||
|                 indent = classLine.start(0) | ||||
|                 itemStr = classLine.string[classLine.start(0):classLine.end(0)-1]  # don't take the closing ':' | ||||
|                 itemStr = itemStr.replace("\n", "").replace("\r", "").replace(",\\", ",").replace("  ", "")  # remove line continuations and spaces from outline view | ||||
|             else: | ||||
|                 defLine = defPat.search(line) | ||||
|                 if defLine: | ||||
|                     indent = defLine.start(0) | ||||
|                     itemStr = defLine.string[defLine.start(0):defLine.end(0)] | ||||
|                     itemStr = itemStr.replace("\n", "").replace("\r", "").replace(",\\", ",").replace("  ", "")  # remove line continuations and spaces from outline view | ||||
|  | ||||
|             if indent == 0: | ||||
|                 parentItem = rootItem | ||||
| @@ -467,6 +481,9 @@ class CodeView(STCTextEditor.TextView): | ||||
|  | ||||
|  | ||||
|     def OnUpdate(self, sender = None, hint = None): | ||||
|         if wx.lib.docview.View.OnUpdate(self, sender, hint): | ||||
|             return | ||||
|  | ||||
|         if hint == "ViewStuff": | ||||
|             self.GetCtrl().SetViewDefaults() | ||||
|         elif hint == "Font": | ||||
| @@ -474,6 +491,7 @@ class CodeView(STCTextEditor.TextView): | ||||
|             self.GetCtrl().SetFont(font) | ||||
|             self.GetCtrl().SetFontColor(color) | ||||
|         else: | ||||
|             import DebuggerService | ||||
|             dbg_service = wx.GetApp().GetService(DebuggerService.DebuggerService) | ||||
|             if dbg_service: | ||||
|                 dbg_service.SetCurrentBreakpointMarkers(self) | ||||
| @@ -623,7 +641,7 @@ class CodeCtrl(STCTextEditor.TextCtrl): | ||||
|     BREAKPOINT_MARKER_MASK = 0x2 | ||||
|      | ||||
|              | ||||
|     def __init__(self, parent, id=-1, style = wx.NO_FULL_REPAINT_ON_RESIZE): | ||||
|     def __init__(self, parent, id=-1, style = wx.NO_FULL_REPAINT_ON_RESIZE, clearTab=True): | ||||
|         STCTextEditor.TextCtrl.__init__(self, parent, id, style) | ||||
|          | ||||
|         self.UsePopUp(False) | ||||
| @@ -635,7 +653,6 @@ class CodeCtrl(STCTextEditor.TextCtrl): | ||||
|         self.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL) | ||||
|         self.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS) | ||||
|         self.SetMarginSensitive(2, True) | ||||
|         self.SetMarginWidth(2, 12) | ||||
|          | ||||
|         self.SetMarginSensitive(1, False) | ||||
|         self.SetMarginMask(1, 0x4) | ||||
| @@ -657,7 +674,7 @@ class CodeCtrl(STCTextEditor.TextCtrl): | ||||
|         # Define the breakpoint marker | ||||
|         self.MarkerDefine(CodeCtrl.BREAKPOINT_MARKER_NUM, wx.stc.STC_MARK_CIRCLE, wx.BLACK, (255,0,0)) | ||||
|          | ||||
|         if _WINDOWS:  # should test to see if menu item exists, if it does, add this workaround | ||||
|         if _WINDOWS and clearTab:  # should test to see if menu item exists, if it does, add this workaround | ||||
|             self.CmdKeyClear(wx.stc.STC_KEY_TAB, 0)  # menu item "Indent Lines" from CodeService.InstallControls() generates another INDENT_LINES_ID event, so we'll explicitly disable the tab processing in the editor | ||||
|  | ||||
|         wx.stc.EVT_STC_MARGINCLICK(self, self.GetId(), self.OnMarginClick) | ||||
| @@ -693,7 +710,7 @@ class CodeCtrl(STCTextEditor.TextCtrl): | ||||
|         item = wx.MenuItem(menu, TOGGLEBREAKPOINT_ID, _("Toggle Breakpoint")) | ||||
|         menu.AppendItem(item) | ||||
|         self.Bind(wx.EVT_MENU, self.OnPopToggleMarker, id=TOGGLEMARKER_ID) | ||||
|         item = wx.MenuItem(menu, TOGGLEMARKER_ID, _("Toggle Marker")) | ||||
|         item = wx.MenuItem(menu, TOGGLEMARKER_ID, _("Toggle Bookmark")) | ||||
|         menu.AppendItem(item) | ||||
|         menu.AppendSeparator() | ||||
|                  | ||||
| @@ -715,6 +732,7 @@ class CodeCtrl(STCTextEditor.TextCtrl): | ||||
|  | ||||
|     def OnPopToggleBP(self, event): | ||||
|         """ Toggle break point on right click line, not current line """ | ||||
|         import DebuggerService | ||||
|         wx.GetApp().GetService(DebuggerService.DebuggerService).OnToggleBreakpoint(event, line=self._rightClickLine) | ||||
|        | ||||
|    | ||||
| @@ -859,6 +877,7 @@ class CodeCtrl(STCTextEditor.TextCtrl): | ||||
|  | ||||
|         elif evt.GetMargin() == 0: | ||||
|             #This is used to toggle breakpoints via the debugger service. | ||||
|             import DebuggerService | ||||
|             db_service = wx.GetApp().GetService(DebuggerService.DebuggerService) | ||||
|             if db_service: | ||||
|                 db_service.OnToggleBreakpoint(evt, line=self.LineFromPosition(evt.GetPosition())) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -6,7 +6,7 @@ | ||||
| # | ||||
| # Created:      5/23/05 | ||||
| # CVS-ID:       $ID:$ | ||||
| # Copyright:    (c) 2005 ActiveGrid, Inc. | ||||
| # Copyright:    (c) 2005-2006 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| @@ -17,27 +17,22 @@ import ProjectEditor | ||||
| import os | ||||
| import os.path | ||||
| import activegrid.util.xmlutils as xmlutils | ||||
|  | ||||
| _ = wx.GetTranslation | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
| # Constants | ||||
| #---------------------------------------------------------------------------- | ||||
| SPACE = 10 | ||||
| HALF_SPACE = 5 | ||||
|  | ||||
|  | ||||
| EXTENSIONS_CONFIG_STRING = "Extensions" | ||||
|  | ||||
|  | ||||
|  | ||||
| # TODO: Redo extensions menu on OK, or provide alert that it won't happen until restart | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
| # Classes | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| class Extension: | ||||
|      | ||||
|  | ||||
|  | ||||
|     def __init__(self, menuItemName=None): | ||||
|         self.menuItemName = menuItemName | ||||
| @@ -48,7 +43,7 @@ class Extension: | ||||
|         self.commandPostArgs = '' | ||||
|         self.fileExt = None | ||||
|         self.opOnSelectedFile = True | ||||
|          | ||||
|  | ||||
|  | ||||
| class ExtensionService(wx.lib.pydocview.DocService): | ||||
|  | ||||
| @@ -60,8 +55,8 @@ class ExtensionService(wx.lib.pydocview.DocService): | ||||
|  | ||||
|     def __getExtensionKeyName(extensionName): | ||||
|         return "%s/%s" % (ExtensionService.EXTENSIONS_KEY, extensionName) | ||||
|        | ||||
|    | ||||
|  | ||||
|  | ||||
|     __getExtensionKeyName = staticmethod(__getExtensionKeyName) | ||||
|  | ||||
|  | ||||
| @@ -79,7 +74,7 @@ class ExtensionService(wx.lib.pydocview.DocService): | ||||
|                 cont, value, index = config.GetNextEntry(index) | ||||
|         finally: | ||||
|             config.SetPath(path) | ||||
|                      | ||||
|  | ||||
|         for extensionName in extensionNames: | ||||
|             extensionData = config.Read(self.__getExtensionKeyName(extensionName)) | ||||
|             if extensionData: | ||||
| @@ -112,10 +107,10 @@ class ExtensionService(wx.lib.pydocview.DocService): | ||||
|             toolsMenu = menuBar.GetMenu(toolsMenuIndex) | ||||
|         else: | ||||
|             toolsMenu = wx.Menu() | ||||
|          | ||||
|  | ||||
|         if self._extensions: | ||||
|             if toolsMenu.GetMenuItems(): | ||||
|                 toolsMenu.AppendSeparator()             | ||||
|                 toolsMenu.AppendSeparator() | ||||
|             for ext in self._extensions: | ||||
|                 # Append a tool menu item for each extension | ||||
|                 ext.id = wx.NewId() | ||||
| @@ -192,7 +187,7 @@ class ExtensionService(wx.lib.pydocview.DocService): | ||||
|             if extension.commandPostArgs: | ||||
|                 cmds.append(extension.commandPostArgs) | ||||
|             os.spawnv(os.P_NOWAIT, extension.command, cmds) | ||||
|                        | ||||
|  | ||||
|         else: | ||||
|             cmd = extension.command | ||||
|             if extension.commandPreArgs: | ||||
| @@ -207,24 +202,24 @@ class ExtensionService(wx.lib.pydocview.DocService): | ||||
|                 view.AddLines(line) | ||||
|             view.GetControl().EnsureCaretVisible() | ||||
|             f.close() | ||||
|              | ||||
|  | ||||
|  | ||||
| class ExtensionOptionsPanel(wx.Panel): | ||||
|  | ||||
|  | ||||
|     def __init__(self, parent, id): | ||||
|         wx.Panel.__init__(self, parent, id) | ||||
|          | ||||
|  | ||||
|         extOptionsPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) | ||||
|          | ||||
|  | ||||
|         extOptionsPanelSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|          | ||||
|  | ||||
|         extCtrlSizer = wx.BoxSizer(wx.VERTICAL) | ||||
|         extCtrlSizer.Add(wx.StaticText(self, -1, _("External Tools:")), 0, wx.BOTTOM, HALF_SPACE) | ||||
|         self._extListBox = wx.ListBox(self, -1, size=(-1,160), style=wx.LB_SINGLE) | ||||
|         self._extListBox = wx.ListBox(self, -1, style=wx.LB_SINGLE) | ||||
|         self.Bind(wx.EVT_LISTBOX, self.OnListBoxSelect, self._extListBox) | ||||
|         extCtrlSizer.Add(self._extListBox, 1, wx.BOTTOM | wx.EXPAND, SPACE)         | ||||
|         buttonSizer = wx.GridSizer(cols=2, vgap=5, hgap=10) | ||||
|         extCtrlSizer.Add(self._extListBox, 1, wx.BOTTOM | wx.EXPAND, SPACE) | ||||
|         buttonSizer = wx.GridSizer(cols=2, vgap=HALF_SPACE, hgap=HALF_SPACE) | ||||
|         self._moveUpButton = wx.Button(self, -1, _("Move Up")) | ||||
|         self.Bind(wx.EVT_BUTTON, self.OnMoveUp, self._moveUpButton) | ||||
|         buttonSizer.Add(self._moveUpButton, 1, wx.EXPAND) | ||||
| @@ -243,21 +238,21 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|         self._extDetailPanel = wx.Panel(self) | ||||
|         staticBox = wx.StaticBox(self, label=_("Selected External Tool")) | ||||
|         staticBoxSizer = wx.StaticBoxSizer(staticBox, wx.VERTICAL) | ||||
|          | ||||
|         extDetailSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=3) | ||||
|  | ||||
|         extDetailSizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5) | ||||
|         extDetailSizer.AddGrowableCol(1,1) | ||||
|  | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:"))) | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:")), flag=wx.ALIGN_CENTER_VERTICAL) | ||||
|         self._menuItemNameTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) | ||||
|         extDetailSizer.Add(self._menuItemNameTextCtrl, 0, wx.EXPAND) | ||||
|         self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl)         | ||||
|         self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl) | ||||
|  | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:"))) | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:")), flag=wx.ALIGN_CENTER_VERTICAL) | ||||
|         self._menuItemDescTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) | ||||
|         extDetailSizer.Add(self._menuItemDescTextCtrl, 0, wx.EXPAND) | ||||
|  | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:"))) | ||||
|         self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))         | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:")), flag=wx.ALIGN_CENTER_VERTICAL) | ||||
|         self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) | ||||
|         findFileButton = wx.Button(self._extDetailPanel, -1, _("Browse...")) | ||||
|         def OnBrowseButton(event): | ||||
|             fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY|wx.CHANGE_DIR) | ||||
| @@ -276,26 +271,26 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|         hsizer.Add(findFileButton, 0, wx.LEFT, HALF_SPACE) | ||||
|         extDetailSizer.Add(hsizer, 0, wx.EXPAND) | ||||
|  | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Args:"))) | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Args:")), flag=wx.ALIGN_CENTER_VERTICAL) | ||||
|         self._commandPreArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) | ||||
|         extDetailSizer.Add(self._commandPreArgsTextCtrl, 0, wx.EXPAND) | ||||
|  | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Args:"))) | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Args:")), flag=wx.ALIGN_CENTER_VERTICAL) | ||||
|         self._commandPostArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) | ||||
|         extDetailSizer.Add(self._commandPostArgsTextCtrl, 0, wx.EXPAND) | ||||
|  | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions:"))) | ||||
|         extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions:")), flag=wx.ALIGN_CENTER_VERTICAL) | ||||
|         self._fileExtTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) | ||||
|         self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" (comma separated) or "*" for all files""")) | ||||
|         extDetailSizer.Add(self._fileExtTextCtrl, 0, wx.EXPAND) | ||||
|  | ||||
|         self._selFileCtrl = wx.CheckBox(self._extDetailPanel, -1, _("Operate on Selected File")) | ||||
|         extDetailSizer.Add(self._selFileCtrl) | ||||
|         extDetailSizer.Add(self._selFileCtrl, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, SPACE) | ||||
|         self._selFileCtrl.SetToolTipString(_("If focus is in the project, instead of operating on the project file, operate on the selected file.")) | ||||
|  | ||||
|         self._extDetailPanel.SetSizer(extDetailSizer) | ||||
|         staticBoxSizer.Add(self._extDetailPanel, 1, wx.ALL|wx.EXPAND, SPACE) | ||||
|          | ||||
|  | ||||
|         extOptionsPanelSizer.Add(staticBoxSizer, 1, wx.LEFT|wx.EXPAND, SPACE) | ||||
|  | ||||
|         extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 1, wx.ALL|wx.EXPAND, SPACE) | ||||
| @@ -306,8 +301,8 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|         self.OnListBoxSelect() | ||||
|  | ||||
|         self.Layout() | ||||
|          | ||||
|         parent.AddPage(self, _("External Tools"))         | ||||
|  | ||||
|         parent.AddPage(self, _("External Tools")) | ||||
|  | ||||
|  | ||||
|     def OnOK(self, optionsDialog): | ||||
| @@ -323,7 +318,7 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|                           msgTitle, | ||||
|                           wx.OK | wx.ICON_INFORMATION, | ||||
|                           self.GetParent()) | ||||
|          | ||||
|  | ||||
|  | ||||
|     def PopulateItems(self): | ||||
|         extensionsService = wx.GetApp().GetService(ExtensionService) | ||||
| @@ -335,7 +330,7 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|         self._currentItem = None | ||||
|         self._currentItemIndex = -1 | ||||
|         return len(self._extensions) | ||||
|        | ||||
|  | ||||
|  | ||||
|     def OnListBoxSelect(self, event=None): | ||||
|         self.SaveCurrentItem() | ||||
| @@ -370,7 +365,7 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|             else: | ||||
|                 extension.fileExt = fileExt.split(',') | ||||
|             extension.opOnSelectedFile = self._selFileCtrl.GetValue() | ||||
|              | ||||
|  | ||||
|  | ||||
|     def LoadItem(self, extension): | ||||
|         if extension: | ||||
| @@ -401,8 +396,8 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|             self._fileExtTextCtrl.SetValue('') | ||||
|             self._selFileCtrl.SetValue(True) | ||||
|             self._extDetailPanel.Enable(False) | ||||
|              | ||||
|        | ||||
|  | ||||
|  | ||||
|     def OnAdd(self, event): | ||||
|         self.SaveCurrentItem() | ||||
|         name = _("Untitled") | ||||
| @@ -417,11 +412,11 @@ class ExtensionOptionsPanel(wx.Panel): | ||||
|         self.OnListBoxSelect() | ||||
|         self._menuItemNameTextCtrl.SetFocus() | ||||
|         self._menuItemNameTextCtrl.SetSelection(-1, -1) | ||||
|          | ||||
|  | ||||
|  | ||||
|     def OnDelete(self, event): | ||||
|         self._extListBox.Delete(self._currentItemIndex) | ||||
|         self._extensions.remove(self._currentItem)     | ||||
|         self._extensions.remove(self._currentItem) | ||||
|         self._currentItemIndex = min(self._currentItemIndex, self._extListBox.GetCount() - 1) | ||||
|         if self._currentItemIndex > -1: | ||||
|             self._extListBox.SetSelection(self._currentItemIndex) | ||||
|   | ||||
| @@ -27,6 +27,7 @@ _ = wx.GetTranslation | ||||
| #---------------------------------------------------------------------------- | ||||
| FILENAME_MARKER = _("Found in file: ") | ||||
| PROJECT_MARKER = _("Searching project: ") | ||||
| FILE_MARKER = _("Searching file: ") | ||||
| FIND_MATCHDIR = "FindMatchDir" | ||||
| FIND_MATCHDIRSUBFOLDERS = "FindMatchDirSubfolders" | ||||
|  | ||||
| @@ -39,6 +40,7 @@ class FindInDirService(FindService.FindService): | ||||
|     #---------------------------------------------------------------------------- | ||||
|     # Constants | ||||
|     #---------------------------------------------------------------------------- | ||||
|     FINDFILE_ID = wx.NewId()        # for bringing up Find in File dialog box | ||||
|     FINDALL_ID = wx.NewId()         # for bringing up Find All dialog box | ||||
|     FINDDIR_ID = wx.NewId()         # for bringing up Find Dir dialog box | ||||
|  | ||||
| @@ -47,29 +49,39 @@ class FindInDirService(FindService.FindService): | ||||
|         FindService.FindService.InstallControls(self, frame, menuBar, toolBar, statusBar, document) | ||||
|  | ||||
|         editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit"))) | ||||
|         wx.EVT_MENU(frame, FindInDirService.FINDFILE_ID, self.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, FindInDirService.FINDFILE_ID, self.ProcessUpdateUIEvent) | ||||
|         editMenu.Append(FindInDirService.FINDFILE_ID, _("Find in File...\tCtrl+Shift+F"), _("Searches for the specified text in the current file")) | ||||
|         wx.EVT_MENU(frame, FindInDirService.FINDALL_ID, self.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, FindInDirService.FINDALL_ID, self.ProcessUpdateUIEvent) | ||||
|         editMenu.Append(FindInDirService.FINDALL_ID, _("Find in Project...\tCtrl+Shift+F"), _("Searches for the specified text in all the files in the project")) | ||||
|         editMenu.Append(FindInDirService.FINDALL_ID, _("Find in Project...\tCtrl+Shift+P"), _("Searches for the specified text in all the files in the project")) | ||||
|         wx.EVT_MENU(frame, FindInDirService.FINDDIR_ID, self.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, FindInDirService.FINDDIR_ID, self.ProcessUpdateUIEvent) | ||||
|         editMenu.Append(FindInDirService.FINDDIR_ID, _("Find in Directory..."), _("Searches for the specified text in all the files in the directory")) | ||||
|         editMenu.Append(FindInDirService.FINDDIR_ID, _("Find in Directory...\tCtrl+Shift+D"), _("Searches for the specified text in all the files in the directory")) | ||||
|  | ||||
|  | ||||
|     def ProcessEvent(self, event): | ||||
|         id = event.GetId() | ||||
|         if id == FindInDirService.FINDALL_ID: | ||||
|         if id == FindInDirService.FINDFILE_ID: | ||||
|             view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|             if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|                 self.ShowFindAllDialog(view.GetCtrl().GetSelectedText()) | ||||
|                 self.ShowFindInFileDialog(view.GetCtrl().GetSelectedText()) | ||||
|             else: | ||||
|                 self.ShowFindAllDialog() | ||||
|                 self.ShowFindInFileDialog() | ||||
|             return True | ||||
|         elif id == FindInDirService.FINDALL_ID: | ||||
|             view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|             if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|                 self.ShowFindInProjectDialog(view.GetCtrl().GetSelectedText()) | ||||
|             else: | ||||
|                 self.ShowFindInProjectDialog() | ||||
|             return True | ||||
|         elif id == FindInDirService.FINDDIR_ID: | ||||
|             view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|             if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|                 self.ShowFindDirDialog(view.GetCtrl().GetSelectedText()) | ||||
|                 self.ShowFindInDirDialog(view.GetCtrl().GetSelectedText()) | ||||
|             else: | ||||
|                 self.ShowFindDirDialog() | ||||
|                 self.ShowFindInDirDialog() | ||||
|             return True | ||||
|         else: | ||||
|             return FindService.FindService.ProcessEvent(self, event) | ||||
| @@ -77,7 +89,14 @@ class FindInDirService(FindService.FindService): | ||||
|  | ||||
|     def ProcessUpdateUIEvent(self, event): | ||||
|         id = event.GetId() | ||||
|         if id == FindInDirService.FINDALL_ID: | ||||
|         if id == FindInDirService.FINDFILE_ID: | ||||
|             view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|             if view and view.GetDocument() and not isinstance(view.GetDocument(), ProjectEditor.ProjectDocument):  # don't search project model | ||||
|                 event.Enable(True) | ||||
|             else: | ||||
|                 event.Enable(False) | ||||
|             return True | ||||
|         elif id == FindInDirService.FINDALL_ID: | ||||
|             projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | ||||
|             if projectService.GetFilesFromCurrentProject(): | ||||
|                 event.Enable(True) | ||||
| @@ -90,7 +109,7 @@ class FindInDirService(FindService.FindService): | ||||
|             return FindService.FindService.ProcessUpdateUIEvent(self, event) | ||||
|  | ||||
|  | ||||
|     def ShowFindDirDialog(self, findString=None): | ||||
|     def ShowFindInDirDialog(self, findString=None): | ||||
|         config = wx.ConfigBase_Get() | ||||
|  | ||||
|         frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in Directory"), size= (320,200)) | ||||
| @@ -105,7 +124,7 @@ class FindInDirService(FindService.FindService): | ||||
|         findDirButton = wx.Button(frame, -1, _("Browse...")) | ||||
|         lineSizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) | ||||
|         contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) | ||||
|          | ||||
|  | ||||
|         def OnBrowseButton(event): | ||||
|             dlg = wx.DirDialog(frame, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE) | ||||
|             dir = dirCtrl.GetValue() | ||||
| @@ -126,10 +145,10 @@ class FindInDirService(FindService.FindService): | ||||
|         lineSizer = wx.BoxSizer(wx.VERTICAL)    # let the line expand horizontally without vertical expansion | ||||
|         lineSizer.Add(wx.StaticLine(frame, -1, size = (10,-1)), 0, flag=wx.EXPAND) | ||||
|         contentSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM, border=HALF_SPACE) | ||||
|          | ||||
|  | ||||
|         if wx.Platform == "__WXMAC__": | ||||
|             contentSizer.Add((-1, 10), 0, wx.EXPAND) | ||||
|          | ||||
|  | ||||
|         lineSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|         lineSizer.Add(wx.StaticText(frame, -1, _("Find what:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) | ||||
|         if not findString: | ||||
| @@ -192,13 +211,13 @@ class FindInDirService(FindService.FindService): | ||||
|                 status = frame.ShowModal() | ||||
|             else: | ||||
|                 passedCheck = True | ||||
|      | ||||
|  | ||||
|  | ||||
|         # save user choice state for this and other Find Dialog Boxes | ||||
|         dirString = dirCtrl.GetValue() | ||||
|         searchSubfolders = subfolderCtrl.IsChecked() | ||||
|         self.SaveFindDirConfig(dirString, searchSubfolders) | ||||
|          | ||||
|         self.SaveFindInDirConfig(dirString, searchSubfolders) | ||||
|  | ||||
|         findString = findCtrl.GetValue() | ||||
|         matchCase = matchCaseCtrl.IsChecked() | ||||
|         wholeWord = wholeWordCtrl.IsChecked() | ||||
| @@ -206,52 +225,23 @@ class FindInDirService(FindService.FindService): | ||||
|         self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) | ||||
|  | ||||
|         frame.Destroy() | ||||
|         if status == wx.ID_OK:             | ||||
|         if status == wx.ID_OK: | ||||
|             messageService = wx.GetApp().GetService(MessageService.MessageService) | ||||
|             messageService.ShowWindow() | ||||
|  | ||||
|             view = messageService.GetView() | ||||
|             if view: | ||||
|                 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | ||||
|                 view.ClearLines() | ||||
|                 view.SetCallback(self.OnJumpToFoundLine) | ||||
|  | ||||
|                 view.AddLines(_("Searching for '%s' in '%s'\n\n") % (findString, dirString)) | ||||
|                  | ||||
|                 if os.path.isfile(dirString): | ||||
|                     try: | ||||
|                         docFile = file(dirString, 'r') | ||||
|                         lineNum = 1 | ||||
|                         needToDisplayFilename = True | ||||
|                         line = docFile.readline() | ||||
|                         while line: | ||||
|                             count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) | ||||
|                             if count != -1: | ||||
|                                 if needToDisplayFilename: | ||||
|                                     view.AddLines(FILENAME_MARKER + dirString + "\n") | ||||
|                                     needToDisplayFilename = False | ||||
|                                 line = repr(lineNum).zfill(4) + ":" + line | ||||
|                                 view.AddLines(line) | ||||
|                             line = docFile.readline() | ||||
|                             lineNum += 1 | ||||
|                         if not needToDisplayFilename: | ||||
|                             view.AddLines("\n") | ||||
|                     except IOError, (code, message): | ||||
|                         print _("Warning, unable to read file: '%s'.  %s") % (dirString, message) | ||||
|                 else: | ||||
|                     # do search in files on disk | ||||
|                     for root, dirs, files in os.walk(dirString): | ||||
|                         if not searchSubfolders and root != dirString: | ||||
|                             break | ||||
|                              | ||||
|                         for name in files: | ||||
|                             filename = os.path.join(root, name) | ||||
|                             try: | ||||
|                                 docFile = file(filename, 'r') | ||||
|                             except IOError, (code, message): | ||||
|                                 print _("Warning, unable to read file: '%s'.  %s") % (filename, message) | ||||
|                                 continue | ||||
|          | ||||
|                 try: | ||||
|                     view.ClearLines() | ||||
|                     view.SetCallback(self.OnJumpToFoundLine) | ||||
|      | ||||
|                     view.AddLines(_("Searching for '%s' in '%s'\n\n") % (findString, dirString)) | ||||
|      | ||||
|                     if os.path.isfile(dirString): | ||||
|                         try: | ||||
|                             docFile = file(dirString, 'r') | ||||
|                             lineNum = 1 | ||||
|                             needToDisplayFilename = True | ||||
|                             line = docFile.readline() | ||||
| @@ -259,7 +249,7 @@ class FindInDirService(FindService.FindService): | ||||
|                                 count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) | ||||
|                                 if count != -1: | ||||
|                                     if needToDisplayFilename: | ||||
|                                         view.AddLines(FILENAME_MARKER + filename + "\n") | ||||
|                                         view.AddLines(FILENAME_MARKER + dirString + "\n") | ||||
|                                         needToDisplayFilename = False | ||||
|                                     line = repr(lineNum).zfill(4) + ":" + line | ||||
|                                     view.AddLines(line) | ||||
| @@ -267,27 +257,186 @@ class FindInDirService(FindService.FindService): | ||||
|                                 lineNum += 1 | ||||
|                             if not needToDisplayFilename: | ||||
|                                 view.AddLines("\n") | ||||
|  | ||||
|                 view.AddLines(_("Search completed.")) | ||||
|                 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||||
|                         except IOError, (code, message): | ||||
|                             print _("Warning, unable to read file: '%s'.  %s") % (dirString, message) | ||||
|                     else: | ||||
|                         # do search in files on disk | ||||
|                         for root, dirs, files in os.walk(dirString): | ||||
|                             if not searchSubfolders and root != dirString: | ||||
|                                 break | ||||
|      | ||||
|                             for name in files: | ||||
|                                 filename = os.path.join(root, name) | ||||
|                                 try: | ||||
|                                     docFile = file(filename, 'r') | ||||
|                                 except IOError, (code, message): | ||||
|                                     print _("Warning, unable to read file: '%s'.  %s") % (filename, message) | ||||
|                                     continue | ||||
|      | ||||
|                                 lineNum = 1 | ||||
|                                 needToDisplayFilename = True | ||||
|                                 line = docFile.readline() | ||||
|                                 while line: | ||||
|                                     count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) | ||||
|                                     if count != -1: | ||||
|                                         if needToDisplayFilename: | ||||
|                                             view.AddLines(FILENAME_MARKER + filename + "\n") | ||||
|                                             needToDisplayFilename = False | ||||
|                                         line = repr(lineNum).zfill(4) + ":" + line | ||||
|                                         view.AddLines(line) | ||||
|                                     line = docFile.readline() | ||||
|                                     lineNum += 1 | ||||
|                                 if not needToDisplayFilename: | ||||
|                                     view.AddLines("\n") | ||||
|      | ||||
|                     view.AddLines(_("Search completed.")) | ||||
|                  | ||||
|                 finally: | ||||
|                     wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||||
|  | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|              | ||||
|  | ||||
|     def SaveFindDirConfig(self, dirString, searchSubfolders): | ||||
|  | ||||
|     def SaveFindInDirConfig(self, dirString, searchSubfolders): | ||||
|         """ Save search dir patterns and flags to registry. | ||||
|          | ||||
|  | ||||
|             dirString = search directory | ||||
|             searchSubfolders = Search subfolders | ||||
|         """ | ||||
|         config = wx.ConfigBase_Get() | ||||
|         config.Write(FIND_MATCHDIR, dirString) | ||||
|         config.WriteInt(FIND_MATCHDIRSUBFOLDERS, searchSubfolders) | ||||
|      | ||||
|  | ||||
|     def ShowFindAllDialog(self, findString=None): | ||||
|  | ||||
|     def DoFindIn(self, findString, matchCase, wholeWord, regExpr, currFileOnly=False, jumpToFound=False): | ||||
|         messageService = wx.GetApp().GetService(MessageService.MessageService) | ||||
|         if not messageService: | ||||
|             return | ||||
|  | ||||
|         messageService.ShowWindow() | ||||
|  | ||||
|         view = messageService.GetView() | ||||
|         if not view: | ||||
|             return | ||||
|  | ||||
|         wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | ||||
|          | ||||
|         try: | ||||
|             #Switch to messages tab. | ||||
|             view.GetControl().GetParent().SetSelection(0)  | ||||
|             view.ClearLines() | ||||
|             view.SetCallback(self.OnJumpToFoundLine) | ||||
|      | ||||
|             projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | ||||
|      | ||||
|             if wx.GetApp().GetDocumentManager().GetCurrentView(): | ||||
|                 currDoc = wx.GetApp().GetDocumentManager().GetCurrentView().GetDocument() | ||||
|             else: | ||||
|                 currDoc = None | ||||
|             if currFileOnly: | ||||
|                 if currDoc: | ||||
|                     projectFilenames = [currDoc.GetFilename()] | ||||
|                     view.AddLines(FILE_MARKER + currDoc.GetFilename() + "\n\n") | ||||
|                 else: | ||||
|                     projectFilenames = [] | ||||
|             else: | ||||
|                 projectFilenames = projectService.GetFilesFromCurrentProject() | ||||
|      | ||||
|                 projView = projectService.GetView() | ||||
|                 if projView: | ||||
|                     projName = wx.lib.docview.FileNameFromPath(projView.GetDocument().GetFilename()) | ||||
|                     view.AddLines(PROJECT_MARKER + projName + "\n\n") | ||||
|      | ||||
|             firstDef = -1 | ||||
|      | ||||
|             # do search in open files first, open files may have been modified and different from disk because it hasn't been saved | ||||
|             openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | ||||
|             openDocsInProject = filter(lambda openDoc: openDoc.GetFilename() in projectFilenames, openDocs) | ||||
|             if currDoc and currDoc in openDocsInProject: | ||||
|                 # make sure current document is searched first. | ||||
|                 openDocsInProject.remove(currDoc) | ||||
|                 openDocsInProject.insert(0, currDoc) | ||||
|             for openDoc in openDocsInProject: | ||||
|                 if isinstance(openDoc, ProjectEditor.ProjectDocument):  # don't search project model | ||||
|                     continue | ||||
|      | ||||
|                 openDocView = openDoc.GetFirstView() | ||||
|                 # some views don't have a in memory text object to search through such as the PM and the DM | ||||
|                 # even if they do have a non-text searchable object, how do we display it in the message window? | ||||
|                 if not hasattr(openDocView, "GetValue"): | ||||
|                     continue | ||||
|                 text = openDocView.GetValue() | ||||
|      | ||||
|                 lineNum = 1 | ||||
|                 needToDisplayFilename = True | ||||
|                 start = 0 | ||||
|                 end = 0 | ||||
|                 count = 0 | ||||
|                 while count != -1: | ||||
|                     count, foundStart, foundEnd, newText = self.DoFind(findString, None, text, start, end, True, matchCase, wholeWord, regExpr) | ||||
|                     if count != -1: | ||||
|                         if needToDisplayFilename: | ||||
|                             view.AddLines(FILENAME_MARKER + openDoc.GetFilename() + "\n") | ||||
|                             needToDisplayFilename = False | ||||
|      | ||||
|                         lineNum = openDocView.LineFromPosition(foundStart) | ||||
|                         line = repr(lineNum).zfill(4) + ":" + openDocView.GetLine(lineNum) | ||||
|                         view.AddLines(line) | ||||
|                         if firstDef == -1: | ||||
|                             firstDef = view.GetControl().GetCurrentLine() - 1 | ||||
|      | ||||
|                         start = text.find("\n", foundStart) | ||||
|                         if start == -1: | ||||
|                             break | ||||
|                         end = start | ||||
|                 if not needToDisplayFilename: | ||||
|                     view.AddLines("\n") | ||||
|                 wx.GetApp().Yield(True) | ||||
|             openDocNames = map(lambda openDoc: openDoc.GetFilename(), openDocs) | ||||
|      | ||||
|             # do search in closed files, skipping the open ones we already searched | ||||
|             filenames = filter(lambda filename: filename not in openDocNames, projectFilenames) | ||||
|             for filename in filenames: | ||||
|                 try: | ||||
|                     docFile = file(filename, 'r') | ||||
|                 except IOError, (code, message): | ||||
|                     print _("Warning, unable to read file: '%s'.  %s") % (filename, message) | ||||
|                     continue | ||||
|      | ||||
|                 lineNum = 1 | ||||
|                 needToDisplayFilename = True | ||||
|                 line = docFile.readline() | ||||
|                 while line: | ||||
|                     count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) | ||||
|                     if count != -1: | ||||
|                         if needToDisplayFilename: | ||||
|                             view.AddLines(FILENAME_MARKER + filename + "\n") | ||||
|                             needToDisplayFilename = False | ||||
|                         line = repr(lineNum).zfill(4) + ":" + line | ||||
|                         view.AddLines(line) | ||||
|                         if firstDef == -1: | ||||
|                             firstDef = view.GetControl().GetCurrentLine() - 1 | ||||
|                     line = docFile.readline() | ||||
|                     lineNum += 1 | ||||
|                 if not needToDisplayFilename: | ||||
|                     view.AddLines("\n") | ||||
|                 wx.GetApp().Yield(True) | ||||
|      | ||||
|             view.AddLines(_("Search for '%s' completed.") % findString) | ||||
|      | ||||
|             if jumpToFound: | ||||
|                 self.OnJumpToFoundLine(event=None, defLineNum=firstDef) | ||||
|  | ||||
|         finally: | ||||
|             wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||||
|  | ||||
|     def FindInProject(self, findString): | ||||
|         self.DoFindIn(findString, matchCase=True, wholeWord=True, regExpr=True, jumpToFound=True) | ||||
|  | ||||
|  | ||||
|     def ShowFindInProjectDialog(self, findString=None): | ||||
|         config = wx.ConfigBase_Get() | ||||
|  | ||||
|         frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in Project"), size= (320,200)) | ||||
| @@ -336,97 +485,80 @@ class FindInDirService(FindService.FindService): | ||||
|         self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) | ||||
|  | ||||
|         frame.Destroy() | ||||
|  | ||||
|         if status == wx.ID_OK: | ||||
|             messageService = wx.GetApp().GetService(MessageService.MessageService) | ||||
|             messageService.ShowWindow() | ||||
|  | ||||
|             view = messageService.GetView() | ||||
|             if view: | ||||
|                 view.ClearLines() | ||||
|                 view.SetCallback(self.OnJumpToFoundLine) | ||||
|  | ||||
|                 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | ||||
|                 projectFilenames = projectService.GetFilesFromCurrentProject() | ||||
|  | ||||
|                 projView = projectService.GetView() | ||||
|                 if projView: | ||||
|                     projName = wx.lib.docview.FileNameFromPath(projView.GetDocument().GetFilename()) | ||||
|                     view.AddLines(PROJECT_MARKER + projName + "\n\n") | ||||
|  | ||||
|                 # do search in open files first, open files may have been modified and different from disk because it hasn't been saved | ||||
|                 openDocs = wx.GetApp().GetDocumentManager().GetDocuments() | ||||
|                 openDocsInProject = filter(lambda openDoc: openDoc.GetFilename() in projectFilenames, openDocs) | ||||
|                 for openDoc in openDocsInProject: | ||||
|                     if isinstance(openDoc, ProjectEditor.ProjectDocument):  # don't search project model | ||||
|                         continue | ||||
|  | ||||
|                     openDocView = openDoc.GetFirstView() | ||||
|                     # some views don't have a in memory text object to search through such as the PM and the DM | ||||
|                     # even if they do have a non-text searchable object, how do we display it in the message window? | ||||
|                     if not hasattr(openDocView, "GetValue"): | ||||
|                         continue | ||||
|                     text = openDocView.GetValue() | ||||
|  | ||||
|                     lineNum = 1 | ||||
|                     needToDisplayFilename = True | ||||
|                     start = 0 | ||||
|                     end = 0 | ||||
|                     count = 0 | ||||
|                     while count != -1: | ||||
|                         count, foundStart, foundEnd, newText = self.DoFind(findString, None, text, start, end, True, matchCase, wholeWord, regExpr) | ||||
|                         if count != -1: | ||||
|                             if needToDisplayFilename: | ||||
|                                 view.AddLines(FILENAME_MARKER + openDoc.GetFilename() + "\n") | ||||
|                                 needToDisplayFilename = False | ||||
|  | ||||
|                             lineNum = openDocView.LineFromPosition(foundStart) | ||||
|                             line = repr(lineNum).zfill(4) + ":" + openDocView.GetLine(lineNum) | ||||
|                             view.AddLines(line) | ||||
|  | ||||
|                             start = text.find("\n", foundStart) | ||||
|                             if start == -1: | ||||
|                                 break | ||||
|                             end = start | ||||
|                     if not needToDisplayFilename: | ||||
|                         view.AddLines("\n") | ||||
|                 openDocNames = map(lambda openDoc: openDoc.GetFilename(), openDocs) | ||||
|  | ||||
|                 # do search in closed files, skipping the open ones we already searched | ||||
|                 filenames = filter(lambda filename: filename not in openDocNames, projectFilenames) | ||||
|                 for filename in filenames: | ||||
|                     try: | ||||
|                         docFile = file(filename, 'r') | ||||
|                     except IOError, (code, message): | ||||
|                         print _("Warning, unable to read file: '%s'.  %s") % (filename, message) | ||||
|                         continue | ||||
|  | ||||
|                     lineNum = 1 | ||||
|                     needToDisplayFilename = True | ||||
|                     line = docFile.readline() | ||||
|                     while line: | ||||
|                         count, foundStart, foundEnd, newText = self.DoFind(findString, None, line, 0, 0, True, matchCase, wholeWord, regExpr) | ||||
|                         if count != -1: | ||||
|                             if needToDisplayFilename: | ||||
|                                 view.AddLines(FILENAME_MARKER + filename + "\n") | ||||
|                                 needToDisplayFilename = False | ||||
|                             line = repr(lineNum).zfill(4) + ":" + line | ||||
|                             view.AddLines(line) | ||||
|                         line = docFile.readline() | ||||
|                         lineNum += 1 | ||||
|                     if not needToDisplayFilename: | ||||
|                         view.AddLines("\n") | ||||
|  | ||||
|                 view.AddLines(_("Search for '%s' completed.") % findString) | ||||
|  | ||||
|             self.DoFindIn(findString, matchCase, wholeWord, regExpr) | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|  | ||||
|     def OnJumpToFoundLine(self, event): | ||||
|     def ShowFindInFileDialog(self, findString=None): | ||||
|         config = wx.ConfigBase_Get() | ||||
|  | ||||
|         frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in File"), size= (320,200)) | ||||
|         borderSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|  | ||||
|         contentSizer = wx.BoxSizer(wx.VERTICAL) | ||||
|         lineSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|         lineSizer.Add(wx.StaticText(frame, -1, _("Find what:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) | ||||
|         if not findString: | ||||
|             findString = config.Read(FindService.FIND_MATCHPATTERN, "") | ||||
|         findCtrl = wx.TextCtrl(frame, -1, findString, size=(200,-1)) | ||||
|         lineSizer.Add(findCtrl, 0, wx.LEFT, HALF_SPACE) | ||||
|         contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) | ||||
|         wholeWordCtrl = wx.CheckBox(frame, -1, _("Match whole word only")) | ||||
|         wholeWordCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHWHOLEWORD, False)) | ||||
|         matchCaseCtrl = wx.CheckBox(frame, -1, _("Match case")) | ||||
|         matchCaseCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHCASE, False)) | ||||
|         regExprCtrl = wx.CheckBox(frame, -1, _("Regular expression")) | ||||
|         regExprCtrl.SetValue(config.ReadInt(FindService.FIND_MATCHREGEXPR, False)) | ||||
|         contentSizer.Add(wholeWordCtrl, 0, wx.BOTTOM, SPACE) | ||||
|         contentSizer.Add(matchCaseCtrl, 0, wx.BOTTOM, SPACE) | ||||
|         contentSizer.Add(regExprCtrl, 0, wx.BOTTOM, SPACE) | ||||
|         borderSizer.Add(contentSizer, 0, wx.TOP | wx.BOTTOM | wx.LEFT, SPACE) | ||||
|  | ||||
|         buttonSizer = wx.BoxSizer(wx.VERTICAL) | ||||
|         findBtn = wx.Button(frame, wx.ID_OK, _("Find")) | ||||
|         findBtn.SetDefault() | ||||
|         BTM_SPACE = HALF_SPACE | ||||
|         if wx.Platform == "__WXMAC__": | ||||
|             BTM_SPACE = SPACE | ||||
|         buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) | ||||
|         buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0) | ||||
|         borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) | ||||
|  | ||||
|         frame.SetSizer(borderSizer) | ||||
|         frame.Fit() | ||||
|  | ||||
|         frame.CenterOnParent() | ||||
|         status = frame.ShowModal() | ||||
|  | ||||
|         # save user choice state for this and other Find Dialog Boxes | ||||
|         findString = findCtrl.GetValue() | ||||
|         matchCase = matchCaseCtrl.IsChecked() | ||||
|         wholeWord = wholeWordCtrl.IsChecked() | ||||
|         regExpr = regExprCtrl.IsChecked() | ||||
|         self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) | ||||
|  | ||||
|         frame.Destroy() | ||||
|  | ||||
|         if status == wx.ID_OK: | ||||
|             self.DoFindIn(findString, matchCase, wholeWord, regExpr, currFileOnly=True) | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|  | ||||
|     def OnJumpToFoundLine(self, event=None, defLineNum=-1): | ||||
|         messageService = wx.GetApp().GetService(MessageService.MessageService) | ||||
|         lineText, pos = messageService.GetView().GetCurrLine() | ||||
|         if lineText == "\n" or lineText.find(FILENAME_MARKER) != -1 or lineText.find(PROJECT_MARKER) != -1: | ||||
|         if defLineNum == -1: | ||||
|             lineText, pos = messageService.GetView().GetCurrLine() | ||||
|         else: | ||||
|             lineText = messageService.GetView().GetControl().GetLine(defLineNum) | ||||
|             pos = 0 | ||||
|  | ||||
|         if lineText == "\n" or lineText.find(FILENAME_MARKER) != -1 or lineText.find(PROJECT_MARKER) != -1 or lineText.find(FILE_MARKER) != -1: | ||||
|             return | ||||
|         lineEnd = lineText.find(":") | ||||
|         if lineEnd == -1: | ||||
| @@ -435,7 +567,10 @@ class FindInDirService(FindService.FindService): | ||||
|             lineNum = int(lineText[0:lineEnd]) | ||||
|  | ||||
|         text = messageService.GetView().GetText() | ||||
|         curPos = messageService.GetView().GetCurrentPos() | ||||
|         if defLineNum == -1: | ||||
|             curPos = messageService.GetView().GetCurrentPos() | ||||
|         else: | ||||
|             curPos = messageService.GetView().GetControl().GetLineEndPosition(defLineNum) | ||||
|  | ||||
|         startPos = text.rfind(FILENAME_MARKER, 0, curPos) | ||||
|         endPos = text.find("\n", startPos) | ||||
| @@ -464,5 +599,3 @@ class FindInDirService(FindService.FindService): | ||||
|                 #         time, we don't see the selection, it is scrolled off screen | ||||
|                 foundView.SetSelection(startPos - 1 + len(lineText[lineEnd:].rstrip("\n")), startPos) | ||||
|                 wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -119,7 +119,7 @@ class HtmlCtrl(CodeEditor.CodeCtrl): | ||||
|  | ||||
|  | ||||
|     def SetViewDefaults(self): | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Html", hasWordWrap = True, hasTabs = True) | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Html", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetFontAndColorFromConfig(self): | ||||
| @@ -156,7 +156,7 @@ class HtmlCtrl(CodeEditor.CodeCtrl): | ||||
| class HtmlOptionsPanel(STCTextEditor.TextOptionsPanel): | ||||
|  | ||||
|     def __init__(self, parent, id): | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Html", label = "HTML", hasWordWrap = True, hasTabs = True) | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Html", label = "HTML", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetIcon(self): | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -36,16 +36,16 @@ class MarkerService(wx.lib.pydocview.DocService): | ||||
|  | ||||
|         editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit"))) | ||||
|         editMenu.AppendSeparator() | ||||
|         editMenu.Append(MarkerService.MARKERTOGGLE_ID, _("Toggle &Marker\tCtrl+M"), _("Toggles a jump marker to text line")) | ||||
|         editMenu.Append(MarkerService.MARKERTOGGLE_ID, _("Toggle &Bookmark\tCtrl+M"), _("Toggles a bookmark at text line")) | ||||
|         wx.EVT_MENU(frame, MarkerService.MARKERTOGGLE_ID, frame.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, MarkerService.MARKERTOGGLE_ID, frame.ProcessUpdateUIEvent) | ||||
|         editMenu.Append(MarkerService.MARKERDELALL_ID, _("Clear Markers"), _("Removes all jump markers from selected file")) | ||||
|         editMenu.Append(MarkerService.MARKERDELALL_ID, _("Clear Bookmarks"), _("Removes all jump bookmarks from selected file")) | ||||
|         wx.EVT_MENU(frame, MarkerService.MARKERDELALL_ID, frame.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, MarkerService.MARKERDELALL_ID, frame.ProcessUpdateUIEvent) | ||||
|         editMenu.Append(MarkerService.MARKERNEXT_ID, _("Marker Next\tF4"), _("Moves to next marker in selected file")) | ||||
|         editMenu.Append(MarkerService.MARKERNEXT_ID, _("Bookmark Next\tF4"), _("Moves to next bookmark in selected file")) | ||||
|         wx.EVT_MENU(frame, MarkerService.MARKERNEXT_ID, frame.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, MarkerService.MARKERNEXT_ID, frame.ProcessUpdateUIEvent) | ||||
|         editMenu.Append(MarkerService.MARKERPREV_ID, _("Marker Previous\tShift+F4"), _("Moves to previous marker in selected file")) | ||||
|         editMenu.Append(MarkerService.MARKERPREV_ID, _("Bookmark Previous\tShift+F4"), _("Moves to previous bookmark in selected file")) | ||||
|         wx.EVT_MENU(frame, MarkerService.MARKERPREV_ID, frame.ProcessEvent) | ||||
|         wx.EVT_UPDATE_UI(frame, MarkerService.MARKERPREV_ID, frame.ProcessUpdateUIEvent) | ||||
|  | ||||
|   | ||||
| @@ -124,6 +124,7 @@ class MessageView(Service.ServiceView): | ||||
|  | ||||
|  | ||||
|     def AddLines(self, text): | ||||
|         self.GetControl().SetCurrentPos(self.GetControl().GetTextLength()) | ||||
|         self.GetControl().SetReadOnly(False) | ||||
|         self.GetControl().AddText(text) | ||||
|         self.GetControl().SetReadOnly(True) | ||||
|   | ||||
| @@ -147,7 +147,11 @@ class OutlineView(Service.ServiceView): | ||||
|             return | ||||
|  | ||||
|         treeCtrl = self.GetControl() | ||||
|          | ||||
|         parentItem = treeCtrl.GetRootItem() | ||||
|         if not parentItem: | ||||
|             return | ||||
|              | ||||
|         if expanded[0] != treeCtrl.GetItemText(parentItem): | ||||
|             return | ||||
|  | ||||
| @@ -157,8 +161,7 @@ class OutlineView(Service.ServiceView): | ||||
|                 treeCtrl.Expand(child) | ||||
|             (child, cookie) = treeCtrl.GetNextChild(parentItem, cookie) | ||||
|  | ||||
|         if parentItem: | ||||
|             treeCtrl.EnsureVisible(parentItem) | ||||
|         treeCtrl.EnsureVisible(parentItem) | ||||
|  | ||||
|  | ||||
| class OutlineTreeCtrl(wx.TreeCtrl): | ||||
| @@ -267,7 +270,7 @@ class OutlineTreeCtrl(wx.TreeCtrl): | ||||
|  | ||||
|         if self.ItemHasChildren(item): | ||||
|             child, cookie = self.GetFirstChild(item) | ||||
|             while child and child.IsOk(): | ||||
|             while child.IsOk(): | ||||
|                 self.FindDistanceToTreeItems(child, position, distances, items) | ||||
|                 child, cookie = self.GetNextChild(item, cookie) | ||||
|         return False | ||||
|   | ||||
							
								
								
									
										2105
									
								
								wxPython/samples/ide/activegrid/tool/PHPDebugger.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2105
									
								
								wxPython/samples/ide/activegrid/tool/PHPDebugger.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -17,6 +17,10 @@ import CodeEditor | ||||
| import OutlineService | ||||
| import os | ||||
| import re | ||||
| import FindInDirService | ||||
| import activegrid.util.appdirs as appdirs | ||||
| import activegrid.util.sysutils as sysutils | ||||
| _ = wx.GetTranslation | ||||
|  | ||||
|  | ||||
| class PHPDocument(CodeEditor.CodeDocument): | ||||
| @@ -153,18 +157,52 @@ class PHPCtrl(CodeEditor.CodeCtrl): | ||||
|  | ||||
|     def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE): | ||||
|         CodeEditor.CodeCtrl.__init__(self, parent, id, style) | ||||
|         self.SetLexer(wx.stc.STC_LEX_PHP) | ||||
|         self.SetLexer(wx.stc.STC_LEX_HTML) | ||||
|         self.SetStyleBits(7) | ||||
|         self.SetKeyWords(4, string.join(PHPKEYWORDS)) | ||||
|         self.SetProperty("fold.html", "1") | ||||
|  | ||||
|  | ||||
|     def CreatePopupMenu(self): | ||||
|         FINDCLASS_ID = wx.NewId() | ||||
|         FINDDEF_ID = wx.NewId() | ||||
|          | ||||
|         menu = CodeEditor.CodeCtrl.CreatePopupMenu(self) | ||||
|  | ||||
|         self.Bind(wx.EVT_MENU, self.OnPopFindDefinition, id=FINDDEF_ID) | ||||
|         menu.Insert(1, FINDDEF_ID, _("Find 'function'")) | ||||
|  | ||||
|         self.Bind(wx.EVT_MENU, self.OnPopFindClass, id=FINDCLASS_ID) | ||||
|         menu.Insert(2, FINDCLASS_ID, _("Find 'class'")) | ||||
|  | ||||
|         return menu | ||||
|          | ||||
|  | ||||
|     def OnPopFindDefinition(self, event): | ||||
|         view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|         if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|             pattern = view.GetCtrl().GetSelectedText().strip() | ||||
|             if pattern: | ||||
|                 searchPattern = "function\s+%s" % pattern | ||||
|                 wx.GetApp().GetService(FindInDirService.FindInDirService).FindInProject(searchPattern) | ||||
|  | ||||
|  | ||||
|     def OnPopFindClass(self, event): | ||||
|         view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|         if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|             definition = "class\s+%s" | ||||
|             pattern = view.GetCtrl().GetSelectedText().strip() | ||||
|             if pattern: | ||||
|                 searchPattern = definition % pattern | ||||
|                 wx.GetApp().GetService(FindInDirService.FindInDirService).FindInProject(searchPattern) | ||||
|  | ||||
|  | ||||
|     def CanWordWrap(self): | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def SetViewDefaults(self): | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "PHP", hasWordWrap = True, hasTabs = True) | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "PHP", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetFontAndColorFromConfig(self): | ||||
| @@ -216,8 +254,110 @@ class PHPCtrl(CodeEditor.CodeCtrl): | ||||
| class PHPOptionsPanel(STCTextEditor.TextOptionsPanel): | ||||
|  | ||||
|     def __init__(self, parent, id): | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "PHP", label = "PHP", hasWordWrap = True, hasTabs = True) | ||||
|         wx.Panel.__init__(self, parent, id) | ||||
|         mainSizer = wx.BoxSizer(wx.VERTICAL)                 | ||||
|  | ||||
|         config = wx.ConfigBase_Get() | ||||
|  | ||||
|         pathLabel = wx.StaticText(self, -1, _("PHP Executable Path:")) | ||||
|         path = config.Read("ActiveGridPHPLocation") | ||||
|         self._pathTextCtrl = wx.TextCtrl(self, -1, path, size = (150, -1)) | ||||
|         self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue()) | ||||
|         self._pathTextCtrl.SetInsertionPointEnd() | ||||
|         choosePathButton = wx.Button(self, -1, _("Browse...")) | ||||
|         pathSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|         HALF_SPACE = 5 | ||||
|         SPACE = 10 | ||||
|         pathSizer.Add(pathLabel, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.TOP, HALF_SPACE) | ||||
|         pathSizer.Add(self._pathTextCtrl, 1, wx.EXPAND|wx.LEFT|wx.TOP, HALF_SPACE) | ||||
|         pathSizer.Add(choosePathButton, 0, wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT|wx.TOP, HALF_SPACE) | ||||
|         wx.EVT_BUTTON(self, choosePathButton.GetId(), self.OnChoosePath) | ||||
|         mainSizer.Add(pathSizer, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, SPACE) | ||||
|  | ||||
|         iniLabel = wx.StaticText(self, -1, _("php.ini Path:")) | ||||
|         ini = config.Read("ActiveGridPHPINILocation") | ||||
|         if not ini: | ||||
|             if sysutils.isRelease(): | ||||
|                 ini = os.path.normpath(os.path.join(appdirs.getSystemDir(), "php.ini")) | ||||
|             else: | ||||
|                 tmp = self._pathTextCtrl.GetValue().strip() | ||||
|                 if tmp and len(tmp) > 0: | ||||
|                     ini = os.path.normpath(os.path.join(os.path.dirname(tmp), "php.ini")) | ||||
|  | ||||
|         self._iniTextCtrl = wx.TextCtrl(self, -1, ini, size = (150, -1)) | ||||
|         self._iniTextCtrl.SetToolTipString(self._iniTextCtrl.GetValue()) | ||||
|         self._iniTextCtrl.SetInsertionPointEnd() | ||||
|         chooseIniButton = wx.Button(self, -1, _("Browse...")) | ||||
|         iniSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|         HALF_SPACE = 5 | ||||
|         SPACE = 10 | ||||
|         iniSizer.Add(iniLabel, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.TOP, HALF_SPACE) | ||||
|         iniSizer.Add(self._iniTextCtrl, 1, wx.EXPAND|wx.LEFT|wx.TOP, HALF_SPACE) | ||||
|         iniSizer.Add(chooseIniButton, 0, wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT|wx.TOP, HALF_SPACE) | ||||
|         wx.EVT_BUTTON(self, chooseIniButton.GetId(), self.OnChooseIni) | ||||
|         mainSizer.Add(iniSizer, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, SPACE) | ||||
|  | ||||
|         self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "PHP", label = "PHP", hasWordWrap = True, hasTabs = True, addPage=False, hasFolding=False) | ||||
|         #STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "PHP", label = "PHP", hasWordWrap = True, hasTabs = True) | ||||
|         mainSizer.Add(self._otherOptions, 0, wx.EXPAND|wx.BOTTOM, SPACE) | ||||
|  | ||||
|         self.SetSizer(mainSizer) | ||||
|         parent.AddPage(self, _("PHP")) | ||||
|  | ||||
|     def OnChoosePath(self, event): | ||||
|         defaultDir = os.path.dirname(self._pathTextCtrl.GetValue().strip()) | ||||
|         defaultFile = os.path.basename(self._pathTextCtrl.GetValue().strip()) | ||||
|         if wx.Platform == '__WXMSW__': | ||||
|             wildcard = _("Executable (*.exe)|*.exe|All|*.*") | ||||
|             if not defaultFile: | ||||
|                 defaultFile = "php-cgi.exe" | ||||
|         else: | ||||
|             wildcard = _("*") | ||||
|         dlg = wx.FileDialog(wx.GetApp().GetTopWindow(), | ||||
|                                _("Select a File"), | ||||
|                                defaultDir=defaultDir, | ||||
|                                defaultFile=defaultFile, | ||||
|                                wildcard=wildcard, | ||||
|                                style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY) | ||||
|         # dlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog | ||||
|         if dlg.ShowModal() == wx.ID_OK: | ||||
|             path = dlg.GetPath() | ||||
|             if path:   | ||||
|                 self._pathTextCtrl.SetValue(path) | ||||
|                 self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue()) | ||||
|                 self._pathTextCtrl.SetInsertionPointEnd() | ||||
|         dlg.Destroy()             | ||||
|  | ||||
|     def OnChooseIni(self, event): | ||||
|         defaultDir = os.path.dirname(self._iniTextCtrl.GetValue().strip()) | ||||
|         defaultFile = os.path.basename(self._iniTextCtrl.GetValue().strip()) | ||||
|         if wx.Platform == '__WXMSW__': | ||||
|             wildcard = _("Ini (*.ini)|*.ini|All|*.*") | ||||
|             if not defaultFile: | ||||
|                 defaultFile = "php.ini" | ||||
|         else: | ||||
|             wildcard = _("*") | ||||
|         dlg = wx.FileDialog(wx.GetApp().GetTopWindow(), | ||||
|                                _("Select a File"), | ||||
|                                defaultDir=defaultDir, | ||||
|                                defaultFile=defaultFile, | ||||
|                                wildcard=wildcard, | ||||
|                                style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY) | ||||
|         # dlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog | ||||
|         if dlg.ShowModal() == wx.ID_OK: | ||||
|             ini = dlg.GetPath() | ||||
|             if ini:   | ||||
|                 self._iniTextCtrl.SetValue(ini) | ||||
|                 self._iniTextCtrl.SetToolTipString(self._iniTextCtrl.GetValue()) | ||||
|                 self._iniTextCtrl.SetInsertionPointEnd() | ||||
|         dlg.Destroy()             | ||||
|  | ||||
|     def OnOK(self, optionsDialog): | ||||
|         config = wx.ConfigBase_Get() | ||||
|         config.Write("ActiveGridPHPLocation", self._pathTextCtrl.GetValue().strip()) | ||||
|         config.Write("ActiveGridPHPINILocation", self._iniTextCtrl.GetValue().strip()) | ||||
|  | ||||
|         self._otherOptions.OnOK(optionsDialog) | ||||
|  | ||||
|     def GetIcon(self): | ||||
|         return getPHPIcon() | ||||
|   | ||||
| @@ -73,7 +73,7 @@ class PerlCtrl(CodeEditor.CodeCtrl): | ||||
|  | ||||
|  | ||||
|     def SetViewDefaults(self): | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Perl", hasWordWrap = True, hasTabs = True) | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Perl", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetFontAndColorFromConfig(self): | ||||
| @@ -130,7 +130,7 @@ class PerlCtrl(CodeEditor.CodeCtrl): | ||||
| class PerlOptionsPanel(STCTextEditor.TextOptionsPanel): | ||||
|  | ||||
|     def __init__(self, parent, id): | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Perl", label = "Perl", hasWordWrap = True, hasTabs = True) | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Perl", label = "Perl", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetIcon(self): | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -25,6 +25,7 @@ import keyword # for GetAutoCompleteKeywordList | ||||
| import sys # for GetAutoCompleteKeywordList | ||||
| import MessageService # for OnCheckCode | ||||
| import OutlineService | ||||
| import FindInDirService | ||||
| from UICommon import CaseInsensitiveCompare | ||||
| try: | ||||
|     import checker # for pychecker | ||||
| @@ -143,11 +144,13 @@ class PythonView(CodeEditor.CodeView): | ||||
|         # Set cursor to Wait cursor | ||||
|         wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) | ||||
|  | ||||
|         # This takes a while for involved code | ||||
|         checker.checkSyntax(self.GetDocument().GetFilename(), view) | ||||
|         try: | ||||
|             # This takes a while for involved code | ||||
|             checker.checkSyntax(self.GetDocument().GetFilename(), view) | ||||
|  | ||||
|         # Set cursor to Default cursor | ||||
|         wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||||
|         finally: | ||||
|             # Set cursor to Default cursor | ||||
|             wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) | ||||
|  | ||||
|  | ||||
|     def OnJumpToFoundLine(self, event): | ||||
| @@ -369,8 +372,42 @@ class PythonCtrl(CodeEditor.CodeCtrl): | ||||
|         self.SetKeyWords(0, string.join(keyword.kwlist)) | ||||
|  | ||||
|  | ||||
|     def CreatePopupMenu(self): | ||||
|         FINDCLASS_ID = wx.NewId() | ||||
|         FINDDEF_ID = wx.NewId() | ||||
|  | ||||
|         menu = CodeEditor.CodeCtrl.CreatePopupMenu(self) | ||||
|  | ||||
|         self.Bind(wx.EVT_MENU, self.OnPopFindDefinition, id=FINDDEF_ID) | ||||
|         menu.Insert(1, FINDDEF_ID, _("Find 'def'")) | ||||
|  | ||||
|         self.Bind(wx.EVT_MENU, self.OnPopFindClass, id=FINDCLASS_ID) | ||||
|         menu.Insert(2, FINDCLASS_ID, _("Find 'class'")) | ||||
|  | ||||
|         return menu | ||||
|  | ||||
|  | ||||
|     def OnPopFindDefinition(self, event): | ||||
|         view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|         if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|             pattern = view.GetCtrl().GetSelectedText().strip() | ||||
|             if pattern: | ||||
|                 searchPattern = "def\s+%s" % pattern | ||||
|                 wx.GetApp().GetService(FindInDirService.FindInDirService).FindInProject(searchPattern) | ||||
|  | ||||
|  | ||||
|     def OnPopFindClass(self, event): | ||||
|         view = wx.GetApp().GetDocumentManager().GetCurrentView() | ||||
|         if hasattr(view, "GetCtrl") and view.GetCtrl() and hasattr(view.GetCtrl(), "GetSelectedText"): | ||||
|             definition = "class\s+%s" | ||||
|             pattern = view.GetCtrl().GetSelectedText().strip() | ||||
|             if pattern: | ||||
|                 searchPattern = definition % pattern | ||||
|                 wx.GetApp().GetService(FindInDirService.FindInDirService).FindInProject(searchPattern) | ||||
|  | ||||
|  | ||||
|     def SetViewDefaults(self): | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Python", hasWordWrap = True, hasTabs = True) | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix="Python", hasWordWrap=True, hasTabs=True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetFontAndColorFromConfig(self): | ||||
| @@ -567,7 +604,7 @@ class PythonOptionsPanel(wx.Panel): | ||||
|         mainSizer = wx.BoxSizer(wx.VERTICAL)                 | ||||
|         mainSizer.Add(pathSizer, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, SPACE) | ||||
|  | ||||
|         self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = True, hasTabs = True, addPage=False) | ||||
|         self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = True, hasTabs = True, addPage=False, hasFolding=True) | ||||
|         mainSizer.Add(self._otherOptions, 0, wx.EXPAND|wx.BOTTOM, SPACE) | ||||
|         self.SetSizer(mainSizer) | ||||
|         parent.AddPage(self, _("Python")) | ||||
| @@ -577,7 +614,7 @@ class PythonOptionsPanel(wx.Panel): | ||||
|         defaultDir = os.path.dirname(self._pathTextCtrl.GetValue().strip()) | ||||
|         defaultFile = os.path.basename(self._pathTextCtrl.GetValue().strip()) | ||||
|         if _WINDOWS: | ||||
|             wildcard = _("Executable (*.exe)|*.exe|All (*.*)|*.*") | ||||
|             wildcard = _("Executable (*.exe)|*.exe|All|*.*") | ||||
|             if not defaultFile: | ||||
|                 defaultFile = "python.exe" | ||||
|         else: | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| # | ||||
| # Created:      8/10/03 | ||||
| # CVS-ID:       $Id$ | ||||
| # Copyright:    (c) 2003-2005 ActiveGrid, Inc. | ||||
| # Copyright:    (c) 2003-2006 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| @@ -47,9 +47,15 @@ TEXT_STATUS_BAR_ID = wx.NewId() | ||||
| class TextDocument(wx.lib.docview.Document): | ||||
|  | ||||
|  | ||||
|     def __init__(self): | ||||
|         wx.lib.docview.Document .__init__(self) | ||||
|         self._inModify = False | ||||
|  | ||||
|  | ||||
|     def SaveObject(self, fileObject): | ||||
|         view = self.GetFirstView() | ||||
|         fileObject.write(view.GetValue()) | ||||
|         view.SetModifyFalse() | ||||
|         return True | ||||
|          | ||||
|  | ||||
| @@ -57,24 +63,31 @@ class TextDocument(wx.lib.docview.Document): | ||||
|         view = self.GetFirstView() | ||||
|         data = fileObject.read() | ||||
|         view.SetValue(data) | ||||
|         view.SetModifyFalse() | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def IsModified(self): | ||||
|         view = self.GetFirstView() | ||||
|         if view: | ||||
|             return wx.lib.docview.Document.IsModified(self) or view.IsModified() | ||||
|         else: | ||||
|             return wx.lib.docview.Document.IsModified(self) | ||||
|             return view.IsModified() | ||||
|         return False | ||||
|  | ||||
|  | ||||
|     def Modify(self, mod): | ||||
|     def Modify(self, modify): | ||||
|         if self._inModify: | ||||
|             return | ||||
|         self._inModify = True | ||||
|          | ||||
|         view = self.GetFirstView() | ||||
|         wx.lib.docview.Document.Modify(self, mod) | ||||
|         if not mod and view: | ||||
|         if not modify and view: | ||||
|             view.SetModifyFalse() | ||||
|  | ||||
|         wx.lib.docview.Document.Modify(self, modify)  # this must called be after the SetModifyFalse call above. | ||||
|  | ||||
|         self._inModify = False | ||||
|          | ||||
|      | ||||
|     def OnCreateCommandProcessor(self): | ||||
|         # Don't create a command processor, it has its own | ||||
|         pass | ||||
| @@ -142,6 +155,8 @@ class TextView(wx.lib.docview.View): | ||||
|             self._dynSash._view = self | ||||
|             self._textEditor = self.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER) | ||||
|         wx.EVT_LEFT_DOWN(self._textEditor, self.OnLeftClick) | ||||
|         self._textEditor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModify) | ||||
|          | ||||
|         self._CreateSizer(frame) | ||||
|         self.Activate() | ||||
|         frame.Show(True) | ||||
| @@ -149,6 +164,10 @@ class TextView(wx.lib.docview.View): | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def OnModify(self, event): | ||||
|         self.GetDocument().Modify(self._textEditor.GetModify()) | ||||
|          | ||||
|  | ||||
|     def _CreateSizer(self, frame): | ||||
|         sizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
|         sizer.Add(self._dynSash, 1, wx.EXPAND) | ||||
| @@ -161,6 +180,9 @@ class TextView(wx.lib.docview.View): | ||||
|  | ||||
|  | ||||
|     def OnUpdate(self, sender = None, hint = None): | ||||
|         if wx.lib.docview.View.OnUpdate(self, sender, hint): | ||||
|             return | ||||
|  | ||||
|         if hint == "ViewStuff": | ||||
|             self.GetCtrl().SetViewDefaults() | ||||
|         elif hint == "Font": | ||||
| @@ -571,9 +593,11 @@ class TextView(wx.lib.docview.View): | ||||
|     def EnsureVisible(self, line): | ||||
|         self.GetCtrl().EnsureVisible(line-1)  # line numbering for editor is 0 based, we are 1 based. | ||||
|  | ||||
|  | ||||
|     def EnsureVisibleEnforcePolicy(self, line): | ||||
|         self.GetCtrl().EnsureVisibleEnforcePolicy(line-1)  # line numbering for editor is 0 based, we are 1 based. | ||||
|  | ||||
|  | ||||
|     def LineFromPosition(self, pos): | ||||
|         return self.GetCtrl().LineFromPosition(pos)+1  # line numbering for editor is 0 based, we are 1 based. | ||||
|  | ||||
| @@ -813,11 +837,12 @@ class TextStatusBar(wx.StatusBar): | ||||
| class TextOptionsPanel(wx.Panel): | ||||
|  | ||||
|  | ||||
|     def __init__(self, parent, id, configPrefix = "Text", label = "Text", hasWordWrap = True, hasTabs = False, addPage=True): | ||||
|     def __init__(self, parent, id, configPrefix = "Text", label = "Text", hasWordWrap = True, hasTabs = False, addPage=True, hasFolding=False): | ||||
|         wx.Panel.__init__(self, parent, id) | ||||
|         self._configPrefix = configPrefix | ||||
|         self._hasWordWrap = hasWordWrap | ||||
|         self._hasTabs = hasTabs | ||||
|         self._hasFolding = hasFolding | ||||
|         SPACE = 10 | ||||
|         HALF_SPACE   = 5 | ||||
|         config = wx.ConfigBase_Get() | ||||
| @@ -854,6 +879,9 @@ class TextOptionsPanel(wx.Panel): | ||||
|         self._viewRightEdgeCheckBox.SetValue(config.ReadInt(self._configPrefix + "EditorViewRightEdge", False)) | ||||
|         self._viewLineNumbersCheckBox = wx.CheckBox(self, -1, _("Show line numbers")) | ||||
|         self._viewLineNumbersCheckBox.SetValue(config.ReadInt(self._configPrefix + "EditorViewLineNumbers", True)) | ||||
|         if self._hasFolding: | ||||
|             self._viewFoldingCheckBox = wx.CheckBox(self, -1, _("Show folding")) | ||||
|             self._viewFoldingCheckBox.SetValue(config.ReadInt(self._configPrefix + "EditorViewFolding", True)) | ||||
|         if self._hasTabs: | ||||
|             self._hasTabsCheckBox = wx.CheckBox(self, -1, _("Use spaces instead of tabs")) | ||||
|             self._hasTabsCheckBox.SetValue(not wx.ConfigBase_Get().ReadInt(self._configPrefix + "EditorUseTabs", False)) | ||||
| @@ -874,6 +902,8 @@ class TextOptionsPanel(wx.Panel): | ||||
|         textPanelSizer.Add(self._viewIndentationGuideCheckBox, 0, wx.ALL, HALF_SPACE) | ||||
|         textPanelSizer.Add(self._viewRightEdgeCheckBox, 0, wx.ALL, HALF_SPACE) | ||||
|         textPanelSizer.Add(self._viewLineNumbersCheckBox, 0, wx.ALL, HALF_SPACE) | ||||
|         if self._hasFolding: | ||||
|             textPanelSizer.Add(self._viewFoldingCheckBox, 0, wx.ALL, HALF_SPACE) | ||||
|         if self._hasTabs: | ||||
|             textPanelSizer.Add(self._hasTabsCheckBox, 0, wx.ALL, HALF_SPACE) | ||||
|             textIndentWidthSizer = wx.BoxSizer(wx.HORIZONTAL) | ||||
| @@ -947,6 +977,9 @@ class TextOptionsPanel(wx.Panel): | ||||
|         config.WriteInt(self._configPrefix + "EditorViewRightEdge", self._viewRightEdgeCheckBox.GetValue()) | ||||
|         doViewStuffUpdate = doViewStuffUpdate or config.ReadInt(self._configPrefix + "EditorViewLineNumbers", True) != self._viewLineNumbersCheckBox.GetValue() | ||||
|         config.WriteInt(self._configPrefix + "EditorViewLineNumbers", self._viewLineNumbersCheckBox.GetValue()) | ||||
|         if self._hasFolding: | ||||
|             doViewStuffUpdate = doViewStuffUpdate or config.ReadInt(self._configPrefix + "EditorViewFolding", True) != self._viewFoldingCheckBox.GetValue() | ||||
|             config.WriteInt(self._configPrefix + "EditorViewFolding", self._viewFoldingCheckBox.GetValue()) | ||||
|         if self._hasWordWrap: | ||||
|             doViewStuffUpdate = doViewStuffUpdate or config.ReadInt(self._configPrefix + "EditorWordWrap", False) != self._wordWrapCheckBox.GetValue() | ||||
|             config.WriteInt(self._configPrefix + "EditorWordWrap", self._wordWrapCheckBox.GetValue()) | ||||
| @@ -1062,13 +1095,15 @@ class TextCtrl(wx.stc.StyledTextCtrl): | ||||
|         event.Skip() | ||||
|          | ||||
|  | ||||
|     def SetViewDefaults(self, configPrefix = "Text", hasWordWrap = True, hasTabs = False): | ||||
|     def SetViewDefaults(self, configPrefix="Text", hasWordWrap=True, hasTabs=False, hasFolding=False): | ||||
|         config = wx.ConfigBase_Get() | ||||
|         self.SetViewWhiteSpace(config.ReadInt(configPrefix + "EditorViewWhitespace", False)) | ||||
|         self.SetViewEOL(config.ReadInt(configPrefix + "EditorViewEOL", False)) | ||||
|         self.SetIndentationGuides(config.ReadInt(configPrefix + "EditorViewIndentationGuides", False)) | ||||
|         self.SetViewRightEdge(config.ReadInt(configPrefix + "EditorViewRightEdge", False)) | ||||
|         self.SetViewLineNumbers(config.ReadInt(configPrefix + "EditorViewLineNumbers", True)) | ||||
|         if hasFolding: | ||||
|             self.SetViewFolding(config.ReadInt(configPrefix + "EditorViewFolding", True)) | ||||
|         if hasWordWrap: | ||||
|             self.SetWordWrap(config.ReadInt(configPrefix + "EditorWordWrap", False)) | ||||
|         if hasTabs:  # These methods do not exist in STCTextEditor and are meant for subclasses | ||||
| @@ -1237,6 +1272,17 @@ class TextCtrl(wx.stc.StyledTextCtrl): | ||||
|             self.SetMarginWidth(1, 0) | ||||
|  | ||||
|  | ||||
|     def GetViewFolding(self): | ||||
|         return self.GetMarginWidth(2) > 0 | ||||
|  | ||||
|  | ||||
|     def SetViewFolding(self, viewFolding = True): | ||||
|         if viewFolding: | ||||
|             self.SetMarginWidth(2, 12) | ||||
|         else: | ||||
|             self.SetMarginWidth(2, 0) | ||||
|  | ||||
|  | ||||
|     def CanWordWrap(self): | ||||
|         return True | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -6,7 +6,7 @@ | ||||
| # | ||||
| # Created:      3/10/05 | ||||
| # CVS-ID:       $Id$ | ||||
| # Copyright:    (c) 2005 ActiveGrid, Inc. | ||||
| # Copyright:    (c) 2005-2006 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| @@ -15,12 +15,14 @@ import os.path | ||||
| import wx | ||||
| import string | ||||
| import ProjectEditor | ||||
| import activegrid.util.sysutils as sysutils | ||||
| import activegrid.util.strutils as strutils | ||||
| import activegrid.util.appdirs as appdirs | ||||
| import activegrid.util.fileutils as fileutils | ||||
| import activegrid.util.strutils as strutils | ||||
| import activegrid.util.sysutils as sysutils | ||||
| import activegrid.util.xmlutils as xmlutils | ||||
| _ = wx.GetTranslation | ||||
|  | ||||
| def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Directory"), fileExtension="*", startingName="", startingDirectory=None, choiceDirs=None, appDirDefaultStartDir=False, returnAll=False): | ||||
| def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Directory:"), fileExtension="*", startingName="", startingDirectory=None, choiceDirs=None, appDirDefaultStartDir=False, returnAll=False, useDirDialog=False): | ||||
|  | ||||
|     if not choiceDirs: | ||||
|         choiceDirs = [] | ||||
| @@ -61,8 +63,8 @@ def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Direc | ||||
|              | ||||
|         if os.getcwd() not in choiceDirs: | ||||
|             choiceDirs.append(os.getcwd())                 | ||||
|         if appdirs.documents_folder not in choiceDirs: | ||||
|             choiceDirs.append(appdirs.documents_folder)  | ||||
|         if appdirs.getSystemDir() not in choiceDirs: | ||||
|             choiceDirs.append(appdirs.getSystemDir())  | ||||
|  | ||||
|     if not startingDirectory: | ||||
|         startingDirectory = os.getcwd() | ||||
| @@ -85,12 +87,18 @@ def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Direc | ||||
|             else: | ||||
|                 name = _("%s.%s") % (nameCtrlValue, fileExtension) | ||||
|                  | ||||
|         dlg = wx.FileDialog(parent, _("Choose a filename and directory"), | ||||
|         if not useDirDialog: | ||||
|             dlg = wx.FileDialog(parent, _("Choose a filename and directory"), | ||||
|                        defaultDir = dirControl.GetValue().strip(), | ||||
|                        defaultFile = name, | ||||
|                        wildcard= "*.%s" % fileExtension, | ||||
|                        style=wx.SAVE|wx.CHANGE_DIR) | ||||
|  | ||||
|         else: | ||||
|             dlg = wx.DirDialog(wx.GetApp().GetTopWindow(), | ||||
|                         _("Choose a directory:"), | ||||
|                         defaultPath=dirControl.GetValue().strip(), | ||||
|                         style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) | ||||
|              | ||||
|         if dlg.ShowModal() != wx.ID_OK: | ||||
|             dlg.Destroy() | ||||
|             return | ||||
| @@ -98,49 +106,78 @@ def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Direc | ||||
|         dlg.Destroy() | ||||
|          | ||||
|         if path: | ||||
|             dir, filename = os.path.split(path) | ||||
|             if dirControl.FindString(dir) == wx.NOT_FOUND: | ||||
|                 dirControl.Insert(dir, 0) | ||||
|             dirControl.SetValue(dir) | ||||
|             dirControl.SetToolTipString(dir) | ||||
|             nameControl.SetValue(filename) | ||||
|             if not useDirDialog: | ||||
|                 dir, filename = os.path.split(path) | ||||
|                 if dirControl.FindString(dir) == wx.NOT_FOUND: | ||||
|                     dirControl.Insert(dir, 0) | ||||
|                 dirControl.SetValue(dir) | ||||
|                 dirControl.SetToolTipString(dir) | ||||
|                 nameControl.SetValue(filename) | ||||
|             else: | ||||
|                 dirControl.SetValue(path) | ||||
|                 dirControl.SetToolTipString(path) | ||||
|  | ||||
|     parent.Bind(wx.EVT_BUTTON, OnFindDirClick, button) | ||||
|      | ||||
|     def Validate(allowOverwriteOnPrompt=False, infoString='', noFirstCharDigit=False): | ||||
|     def Validate(allowOverwriteOnPrompt=False, infoString='', validClassName=False, ignoreFileConflicts=False): | ||||
|         projName = nameControl.GetValue().strip() | ||||
|         if projName == "": | ||||
|             wx.MessageBox(_("Please provide a %sfile name.") % infoString, _("Provide a File Name"))             | ||||
|             return False | ||||
|         if noFirstCharDigit and projName[0].isdigit(): | ||||
|             wx.MessageBox(_("File name cannot start with a number.  Please enter a different name."), _("Invalid File Name"))             | ||||
|             return False | ||||
|         if projName.find(' ') != -1: | ||||
|             wx.MessageBox(_("Please provide a %sfile name that does not contains spaces.") % infoString, _("Spaces in File Name"))             | ||||
|             return False | ||||
|         if not os.path.exists(dirControl.GetValue()): | ||||
|             wx.MessageBox(_("That %sdirectory does not exist. Please choose an existing directory.") % infoString, _("Provide a Valid Directory"))             | ||||
|         if validClassName: | ||||
|             if projName[0].isdigit(): | ||||
|                 wx.MessageBox(_("File name cannot start with a number.  Please enter a different name."), _("Invalid File Name"))             | ||||
|                 return False | ||||
|             if projName.endswith(".agp"): | ||||
|                 projName2 = projName[:-4] | ||||
|             else: | ||||
|                 projName2 = projName | ||||
|             if not projName2.replace("_", "a").isalnum():  # [a-zA-Z0-9_]  note '_' is allowed and ending '.agp'. | ||||
|                 wx.MessageBox(_("Name must be alphanumeric ('_' allowed).  Please enter a valid name."), _("Project Name")) | ||||
|                 return False | ||||
|  | ||||
|         dirName = dirControl.GetValue().strip() | ||||
|         if dirName == "": | ||||
|             wx.MessageBox(_("No directory.  Please provide a directory."), _("Provide a Directory"))             | ||||
|             return False | ||||
|          | ||||
|         filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(projName, "." + fileExtension)) | ||||
|         if os.path.exists(filePath): | ||||
|             if allowOverwriteOnPrompt: | ||||
|                 res = wx.MessageBox(_("That %sfile already exists. Would you like to overwrite it.") % infoString, "File Exists", style=wx.YES_NO|wx.NO_DEFAULT) | ||||
|                 return (res == wx.YES)   | ||||
|             else:                 | ||||
|                 wx.MessageBox(_("That %sfile already exists. Please choose a different name.") % infoString, "File Exists") | ||||
|                 return False                   | ||||
|         if os.sep == "\\" and dirName.find("/") != -1: | ||||
|             wx.MessageBox(_("Wrong delimiter '/' found in directory path.  Use '%s' as delimiter.") % os.sep, _("Provide a Valid Directory"))             | ||||
|             return False | ||||
|         if not os.path.exists(dirName): | ||||
|             wx.MessageBox(_("That %sdirectory does not exist.  Please choose an existing directory.") % infoString, _("Provide a Valid Directory"))             | ||||
|             return False | ||||
|         if not ignoreFileConflicts: | ||||
|             filePath = os.path.join(dirName, MakeNameEndInExtension(projName, "." + fileExtension)) | ||||
|             if os.path.exists(filePath): | ||||
|                 if allowOverwriteOnPrompt: | ||||
|                     res = wx.MessageBox(_("That %sfile already exists. Would you like to overwrite it.") % infoString, "File Exists", style=wx.YES_NO|wx.NO_DEFAULT) | ||||
|                     return (res == wx.YES)   | ||||
|                 else:                 | ||||
|                     wx.MessageBox(_("That %sfile already exists. Please choose a different name.") % infoString, "File Exists") | ||||
|                     return False | ||||
|  | ||||
|         return True     | ||||
|     HALF_SPACE = 5 | ||||
|     flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = HALF_SPACE, hgap = HALF_SPACE) | ||||
|     flexGridSizer.AddGrowableCol(1,1) | ||||
|     flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | ||||
|     flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) | ||||
|     flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE) | ||||
|     if not useDirDialog: | ||||
|         flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | ||||
|         flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) | ||||
|         flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE)         | ||||
|         flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | ||||
|         flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) | ||||
|         flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | ||||
|     else: | ||||
|         flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | ||||
|         flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) | ||||
|         flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | ||||
|         flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | ||||
|         flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) | ||||
|         flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE)         | ||||
|          | ||||
|     flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) | ||||
|     flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) | ||||
|     flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) | ||||
|     if returnAll: | ||||
|         return nameControl, dirControl, flexGridSizer, Validate, allControls | ||||
|     else: | ||||
| @@ -188,8 +225,8 @@ def CreateDirectoryOnlyControl( parent, dirLabel=_("Location:"), startingDirecto | ||||
|  | ||||
|         if os.getcwd() not in choiceDirs: | ||||
|             choiceDirs.append(os.getcwd())                 | ||||
|         if appdirs.documents_folder not in choiceDirs: | ||||
|             choiceDirs.append(appdirs.documents_folder)                 | ||||
|         if appdirs.getSystemDir() not in choiceDirs: | ||||
|             choiceDirs.append(appdirs.getSystemDir())                 | ||||
|              | ||||
|  | ||||
|     if not startingDirectory: | ||||
| @@ -221,6 +258,9 @@ def CreateDirectoryOnlyControl( parent, dirLabel=_("Location:"), startingDirecto | ||||
|         if dirName == "": | ||||
|             wx.MessageBox(_("Please provide a directory."), _("Provide a Directory"))             | ||||
|             return False | ||||
|         if os.sep == "\\" and dirName.find("/") != -1: | ||||
|             wx.MessageBox(_("Wrong delimiter '/' found in directory path.  Use '%s' as delimiter.") % os.sep, _("Provide a Valid Directory"))             | ||||
|             return False | ||||
|         if not os.path.exists(dirName): | ||||
|             wx.MessageBox(_("That directory does not exist. Please choose an existing directory."), _("Provide a Valid Directory"))             | ||||
|             return False | ||||
| @@ -241,17 +281,25 @@ def CreateNameOnlyControl( parent, fileLabel, startingName="", startingDirectory | ||||
|     fileLabelText = wx.StaticText(parent, -1, fileLabel) | ||||
|     nameControl = wx.TextCtrl(parent, -1, startingName, size=(-1,-1)) | ||||
|          | ||||
|     def Validate(allowOverwriteOnPrompt=False, noFirstCharDigit=False): | ||||
|     def Validate(allowOverwriteOnPrompt=False, validClassName=False): | ||||
|         projName = nameControl.GetValue().strip() | ||||
|         if projName == "": | ||||
|             wx.MessageBox(_("Blank name.  Please enter a valid name."), _("Project Name"))             | ||||
|             return False | ||||
|         if noFirstCharDigit and projName[0].isdigit(): | ||||
|             wx.MessageBox(_("Name cannot start with a number.  Please enter a valid name."), _("Project Name"))             | ||||
|             return False | ||||
|         if projName.find(' ') != -1: | ||||
|             wx.MessageBox(_("Spaces in name.  Name cannot have spaces.") % infoString, _("Project Name"))             | ||||
|             wx.MessageBox(_("Spaces in name.  Name cannot have spaces."), _("Project Name"))             | ||||
|             return False | ||||
|         if validClassName: | ||||
|             if projName[0].isdigit(): | ||||
|                 wx.MessageBox(_("Name cannot start with a number.  Please enter a valid name."), _("Project Name"))             | ||||
|                 return False | ||||
|             if projName.endswith(".agp"): | ||||
|                 projName2 = projName[:-4] | ||||
|             else: | ||||
|                 projName2 = projName | ||||
|             if not projName2.replace("_", "a").isalnum():  # [a-zA-Z0-9_]  note '_' is allowed and ending '.agp'. | ||||
|                 wx.MessageBox(_("Name must be alphanumeric ('_' allowed).  Please enter a valid name."), _("Project Name")) | ||||
|                 return False | ||||
|         path = os.path.join(startingDirectoryControl.GetValue().strip(), projName) | ||||
|         if os.path.exists(path): | ||||
|             if os.path.isdir(path): | ||||
| @@ -280,6 +328,29 @@ def CreateNameOnlyControl( parent, fileLabel, startingName="", startingDirectory | ||||
|     return nameControl, flexGridSizer, Validate | ||||
|      | ||||
|  | ||||
| def ValidateName(name, ext=None, hint="name"): | ||||
|     """ Returns an error string if there is something wrong with the name. | ||||
|         Otherwise it returns None | ||||
|     """ | ||||
|     if name == "": | ||||
|         return _("Blank %s.  Please enter a valid %s.") % (hint, hint) | ||||
|  | ||||
|     if name.find(' ') != -1: | ||||
|         return _("Spaces in %s.  %s cannot have spaces.") % (hint, hint.title()) | ||||
|  | ||||
|     if name[0].isdigit(): | ||||
|         return _("%s cannot start with a number.  Please enter a valid %s.") % (hint.title(), hint) | ||||
|  | ||||
|     if ext and name.endswith(ext):  # strip extension if provided | ||||
|         lenExt = len(ext) | ||||
|         name = name[:-lenExt] | ||||
|          | ||||
|     if not name.replace("_", "a").isalnum():  # [a-zA-Z0-9_]  note '_' is allowed and ext ending. | ||||
|         return _("%s must be alphanumeric ('_' allowed).  Please enter a valid %s.") % (hint.title(), hint) | ||||
|  | ||||
|     return None | ||||
|  | ||||
|  | ||||
| def GetCurrentProject(): | ||||
|     projectDocument = None | ||||
|     projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) | ||||
| @@ -330,6 +401,16 @@ def GetPythonExecPath(): | ||||
|     return pythonExecPath | ||||
|      | ||||
|  | ||||
| def GetPHPExecPath(): | ||||
|     PHPExecPath = wx.ConfigBase_Get().Read("ActiveGridPHPLocation") | ||||
|     return PHPExecPath | ||||
|  | ||||
|  | ||||
| def GetPHPINIPath(): | ||||
|     PHPINIPath = wx.ConfigBase_Get().Read("ActiveGridPHPINILocation") | ||||
|     return PHPINIPath | ||||
|  | ||||
|  | ||||
| def _DoRemoveRecursive(path, skipFile=None, skipped=False): | ||||
|     if path == skipFile: | ||||
|         skipped = True | ||||
| @@ -362,16 +443,62 @@ def CaseInsensitiveCompare(s1, s2): | ||||
|  | ||||
| def GetAnnotation(model, elementName): | ||||
|     """ Get an object's annotation used for tooltips """ | ||||
|     if hasattr(model, "__xsdcomplextype__"): | ||||
|     if hasattr(model, "_complexType"): | ||||
|         ct = model._complexType | ||||
|     elif hasattr(model, "__xsdcomplextype__"): | ||||
|         ct = model.__xsdcomplextype__ | ||||
|         if ct: | ||||
|             el = ct.findElement(elementName) | ||||
|             if el and el.annotation: | ||||
|                 return el.annotation | ||||
|     else: | ||||
|         ct = None | ||||
|              | ||||
|     if ct: | ||||
|         el = ct.findElement(elementName) | ||||
|         if el and el.annotation: | ||||
|             return el.annotation | ||||
|              | ||||
|     return "" | ||||
|  | ||||
|  | ||||
| def GetDisplayName(doc, name): | ||||
|     if name: | ||||
|         appDocMgr = doc.GetAppDocMgr() | ||||
|         if appDocMgr: | ||||
|             name = appDocMgr.toDisplayTypeName(name) | ||||
|         else: | ||||
|             namespace, name = xmlutils.splitType(name) | ||||
|             if namespace and hasattr(doc.GetModel(), "getXmlNamespaces"): | ||||
|                 for xmlkey, xmlval in doc.GetModel().getXmlNamespaces().iteritems(): | ||||
|                     if xmlval == namespace: | ||||
|                         name = "%s:%s" % (xmlkey, name) | ||||
|                         break                     | ||||
|      | ||||
|         if name: | ||||
|             import activegrid.model.schema as schemalib | ||||
|             baseTypeName = schemalib.mapXsdType(name) | ||||
|             if baseTypeName: | ||||
|                 name = baseTypeName | ||||
|  | ||||
|     return name | ||||
|  | ||||
|  | ||||
| def GetInternalName(doc, name): | ||||
|     if name: | ||||
|         appDocMgr = doc.GetAppDocMgr() | ||||
|         if appDocMgr: | ||||
|             name = appDocMgr.toInternalTypeName(name) | ||||
|         else: | ||||
|             namespace, name = xmlutils.splitType(name) | ||||
|             if namespace and hasattr(doc.GetModel(), "getXmlNamespaces"): | ||||
|                 for xmlkey, xmlval in doc.GetModel().getXmlNamespaces().iteritems(): | ||||
|                     if xmlkey == namespace: | ||||
|                         name = "%s:%s" % (xmlval, name) | ||||
|                         break   | ||||
|                                            | ||||
|         import activegrid.model.schema as schemalib | ||||
|         name = schemalib.mapAGType(name) | ||||
|  | ||||
|     return name | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
| # Methods for finding application level info | ||||
| #---------------------------------------------------------------------------- | ||||
| @@ -435,7 +562,8 @@ def GetAppDocMgrForDoc(doc): | ||||
|  | ||||
|  | ||||
| def GetAppInfoLanguage(doc=None): | ||||
|     from activegrid.server.deployment import LANGUAGE_DEFAULT | ||||
|     from activegrid.server.projectmodel import LANGUAGE_DEFAULT | ||||
|      | ||||
|     if doc: | ||||
|         language = doc.GetAppInfo().language | ||||
|     else: | ||||
| @@ -449,3 +577,159 @@ def GetAppInfoLanguage(doc=None): | ||||
|             doc.GetAppInfo().language = language  # once it is selected, it must be set. | ||||
|          | ||||
|     return language | ||||
|  | ||||
| def AddWsdlAgToProjectFromWsdlRegistration(wsdlRegistration): | ||||
|     """Add wsdl ag for registry entry.""" | ||||
|  | ||||
|     wsdlPath = wsdlRegistration.path | ||||
|     rootPath = None | ||||
|     serviceRefName = wsdlRegistration.name | ||||
|      | ||||
|     agwsDoc = _InitWsdlAg(wsdlPath, rootPath, serviceRefName) | ||||
|  | ||||
|     if (agwsDoc == None): | ||||
|         return | ||||
|  | ||||
|     serviceRef = agwsDoc.GetModel()     | ||||
|      | ||||
|     serviceRef.serviceType = wsdlRegistration.type | ||||
|  | ||||
|     import activegrid.server.deployment as deployment | ||||
|  | ||||
|     if (serviceRef.serviceType == deployment.SERVICE_LOCAL): | ||||
|         serviceRef.localService = deployment.LocalService( | ||||
|             wsdlRegistration.codeFile) | ||||
|          | ||||
|     elif (serviceRef.serviceType == deployment.SERVICE_DATABASE): | ||||
|         serviceRef.databaseService = deployment.DatabaseService( | ||||
|             wsdlRegistration.datasourceName) | ||||
|          | ||||
|     elif (serviceRef.serviceType == deployment.SERVICE_SOAP): | ||||
|         pass | ||||
|      | ||||
|     elif (serviceRef.serviceType == deployment.SERVICE_RSS): | ||||
|         serviceRef.rssService = deployment.RssService(wsdlRegistration.feedUrl) | ||||
|          | ||||
|     elif (serviceRef.serviceType == deployment.SERVICE_REST): | ||||
|         serviceRef.restService = deployment.RestService( | ||||
|             wsdlRegistration.baseUrl) | ||||
|     else: | ||||
|         raise AssertionError("Unknown service type") | ||||
|  | ||||
|     _AddToProject(agwsDoc, addWsdl=True) | ||||
|      | ||||
|  | ||||
| def AddWsdlAgToProject(wsdlPath, rootPath=fileutils.AG_SYSTEM_STATIC_VAR_REF, | ||||
|                        serviceRefName=None, className=None, serviceType=None, | ||||
|                        dataSourceName=None): | ||||
|     """ | ||||
|        wsdlPath: path to wsdl from rootPath. If wsdlPath is absolute, rootPath | ||||
|        is ignored. rootPath is also ignored when rootPath is set to None.  | ||||
|        rootPath: defaults to ${AG_SYSTEM_STATIC}. | ||||
|        serviceRefName: If None, it will be set to the wsdl file name without | ||||
|        the .wsdl file extension. | ||||
|        className: if not None, will be used for the the wsdlag's ClassName. | ||||
|        serviceType: defaults to local. | ||||
|        dataSourceName: if serviceType is deployment.DATABASE, the ds must be | ||||
|        provided. | ||||
|     """ | ||||
|     import WsdlAgEditor | ||||
|     import XFormWizard | ||||
|     import activegrid.model.basedocmgr as basedocmgr | ||||
|     import activegrid.server.deployment as deployment | ||||
|  | ||||
|     if (serviceType == None): | ||||
|         serviceType = deployment.SERVICE_LOCAL | ||||
|  | ||||
|  | ||||
|     agwsDoc = _InitWsdlAg(wsdlPath, rootPath, serviceRefName) | ||||
|  | ||||
|     if (agwsDoc == None): | ||||
|         return | ||||
|  | ||||
|     serviceRef = agwsDoc.GetModel()     | ||||
|      | ||||
|     serviceRef.serviceType = serviceType | ||||
|  | ||||
|     if (serviceType == deployment.SERVICE_DATABASE and dataSourceName != None): | ||||
|         serviceRef.databaseService = deployment.DatabaseService(dataSourceName) | ||||
|     else: | ||||
|         serviceRef.localService = deployment.LocalService(className=className) | ||||
|  | ||||
|     _AddToProject(agwsDoc) | ||||
|          | ||||
|  | ||||
| def _AddToProject(agwsDoc, addWsdl=False): | ||||
|     import activegrid.model.basedocmgr as basedocmgr     | ||||
|     projectDoc = GetCurrentProject() | ||||
|     agwsDoc.OnSaveDocument(agwsDoc.GetFilename()) | ||||
|  | ||||
|     files = [agwsDoc.fileName] | ||||
|     types = [basedocmgr.FILE_TYPE_SERVICE] | ||||
|     names = [agwsDoc.GetModel().name] | ||||
|     if (addWsdl): | ||||
|         m = agwsDoc.GetModel()         | ||||
|         wsdlName = os.path.splitext(os.path.basename(m.filePath))[0] | ||||
|         appDocMgr = projectDoc.GetAppDocMgr() | ||||
|         if (appDocMgr.findService(wsdlName) == None): | ||||
|             m = agwsDoc.GetModel()             | ||||
|             files.append(m.filePath) | ||||
|             types.append(None) | ||||
|             names.append(wsdlName) | ||||
|      | ||||
|     ProjectEditor.ProjectAddFilesCommand(projectDoc, files, types=types, | ||||
|                                          names=names).Do() | ||||
|      | ||||
|  | ||||
| def _InitWsdlAg(wsdlPath, rootPath=fileutils.AG_SYSTEM_STATIC_VAR_REF, | ||||
|                 serviceRefName=None): | ||||
|  | ||||
|     projectDoc = GetCurrentProject() | ||||
|     appDocMgr = projectDoc.GetAppDocMgr() | ||||
|  | ||||
|     if (serviceRefName == None): | ||||
|         serviceRefName = os.path.splitext(os.path.basename(wsdlPath))[0] | ||||
|      | ||||
|     if (appDocMgr.findServiceRef(serviceRefName) != None): | ||||
|         return None | ||||
|  | ||||
|     import WsdlAgEditor | ||||
|     import XFormWizard | ||||
|     import activegrid.server.deployment as deployment | ||||
|  | ||||
|     template = XFormWizard.GetTemplate(WsdlAgEditor.WsdlAgDocument) | ||||
|     ext = template.GetDefaultExtension() | ||||
|     fullPath = os.path.join(appDocMgr.homeDir, serviceRefName + ext) | ||||
|  | ||||
|     agwsDoc = template.CreateDocument( | ||||
|         fullPath, flags=(wx.lib.docview.DOC_NO_VIEW|wx.lib.docview.DOC_NEW| | ||||
|                          wx.lib.docview.DOC_OPEN_ONCE)) | ||||
|      | ||||
|     serviceRef = agwsDoc.GetModel() | ||||
|     serviceRef.name = serviceRefName | ||||
|  | ||||
|     if (rootPath == None or os.path.isabs(wsdlPath)): | ||||
|         serviceRef.filePath = wsdlPath | ||||
|     else: | ||||
|         # make sure to use forward slashes for the path to the .wsdl | ||||
|         wsdlPath = wsdlPath.replace("\\", "/") | ||||
|          | ||||
|         if not wsdlPath.startswith("/"): | ||||
|             wsdlPath = "/%s" % wsdlPath | ||||
|         serviceRef.filePath = "%s%s" % (rootPath, wsdlPath) | ||||
|  | ||||
|     agwsDoc.fileName = fullPath         | ||||
|  | ||||
|     return agwsDoc | ||||
|  | ||||
|  | ||||
| def GetSchemaName(schema): | ||||
|     return os.path.basename(schema.fileName) | ||||
|  | ||||
|  | ||||
| class AGChoice(wx.Choice): | ||||
|     """Extension to wx.Choice that fixes linux bug where first item of choices | ||||
|     passed into ctor would be visible, but not selected.""" | ||||
|     def __init__(self, parent, id, choices=[]): | ||||
|         super(AGChoice, self).__init__(parent=parent, id=id) | ||||
|         self.AppendItems(choices) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -78,7 +78,7 @@ class XmlCtrl(CodeEditor.CodeCtrl): | ||||
|  | ||||
|  | ||||
|     def SetViewDefaults(self): | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Xml", hasWordWrap = True, hasTabs = True) | ||||
|         CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Xml", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetFontAndColorFromConfig(self): | ||||
| @@ -115,7 +115,7 @@ class XmlCtrl(CodeEditor.CodeCtrl): | ||||
| class XmlOptionsPanel(STCTextEditor.TextOptionsPanel): | ||||
|  | ||||
|     def __init__(self, parent, id): | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Xml", label = "XML", hasWordWrap = True, hasTabs = True) | ||||
|         STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Xml", label = "XML", hasWordWrap = True, hasTabs = True, hasFolding=True) | ||||
|  | ||||
|  | ||||
|     def GetIcon(self): | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								wxPython/samples/ide/activegrid/tool/bmp_source/activegrid.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								wxPython/samples/ide/activegrid/tool/bmp_source/activegrid.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 170 KiB | 
| @@ -1,7 +1,7 @@ | ||||
| Middle-Mouse-Click on the tab for an open file will close the file. | ||||
| Ctrl-Space in any editor does code completion. | ||||
| Right-clicking on something in the 'Thing' column of the debugger's frame tab may allow you to introspect it for more information. | ||||
| Right-Mouse-Click in Outline window allows you to change display sorting. | ||||
| In an editor, you can add line markers via Ctrl-M and jump to the next marker with F4 or previous marker with Shift-F4. | ||||
| In an editor. you can use the numpad + and - keys to toggle folding. | ||||
| In 'Find in Directory', if you specify a file, it will display all matches in the Message Window. | ||||
| Breakpoints for the debugger can be set while the process is running | ||||
| Breakpoints for the debugger can be set while the process is running. | ||||
| A split window can be closed by dragging the sash to one of its borders. | ||||
| @@ -407,7 +407,13 @@ _SaferCreateProcess(appName=%r, | ||||
|                 elif env: | ||||
|                     uenv = {} | ||||
|                     for key, val in env.items(): | ||||
|                         uenv[unicode(key)] = unicode(val) | ||||
|                         try: | ||||
|                             uenv[unicode(key)] = unicode(val)   # default encoding | ||||
|                         except UnicodeError: | ||||
|                             try: | ||||
|                                 uenv[unicode(key, 'iso-8859-1')] = unicode(val, 'iso-8859-1')   # backup encoding | ||||
|                             except UnicodeError: | ||||
|                                 log.warn('Skipping environment variable "%s" in execution process: unable to convert to unicode using either the default encoding or ISO-8859-1' % (key)) | ||||
|                     env = uenv | ||||
|                 hProcess, hThread, processId, threadId\ | ||||
|                     = win32process.CreateProcess(appName, cmd, processSA, | ||||
|   | ||||
| @@ -14,7 +14,16 @@ import copy | ||||
| import os | ||||
| import os.path | ||||
| import activegrid.util.xmlutils as xmlutils | ||||
| from IDE import ACTIVEGRID_BASE_IDE | ||||
| import activegrid.util.aglogging as aglogging | ||||
|  | ||||
| # REVIEW 07-Mar-06 stoens@activegrid.com -- Ideally move the pieces required | ||||
| # to generate the .dpl file out of this module so there's no dependency on wx, | ||||
| # instead of doing this try/catch (IDE drags in wx). | ||||
| try: | ||||
|     from IDE import ACTIVEGRID_BASE_IDE | ||||
| except: | ||||
|     ACTIVEGRID_BASE_IDE = False | ||||
|      | ||||
| if not ACTIVEGRID_BASE_IDE: | ||||
|     import activegrid.model.basedocmgr as basedocmgr | ||||
|     import AppInfo | ||||
| @@ -27,64 +36,6 @@ if not ACTIVEGRID_BASE_IDE: | ||||
| PROJECT_VERSION_050730 = '10' | ||||
| PROJECT_VERSION_050826 = '11' | ||||
|  | ||||
|      | ||||
| #---------------------------------------------------------------------------- | ||||
| # XML Marshalling Methods | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| def load(fileObject): | ||||
|     version = xmlutils.getAgVersion(fileObject.name) | ||||
|     # most current versions on top | ||||
|     if version == PROJECT_VERSION_050826: | ||||
|         fileObject.seek(0) | ||||
|         if ACTIVEGRID_BASE_IDE: | ||||
|             KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} | ||||
|         else: | ||||
|             KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo} | ||||
|         project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) | ||||
|     elif version == PROJECT_VERSION_050730: | ||||
|         fileObject.seek(0) | ||||
|         project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}) | ||||
|         project = project.upgradeVersion() | ||||
|     else: | ||||
|         # assume it is old version without version number | ||||
|         fileObject.seek(0) | ||||
|         project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}) | ||||
|         if project: | ||||
|             project = project.upgradeVersion() | ||||
|         else: | ||||
|             print "Project, unknown version:", version | ||||
|             return None | ||||
|              | ||||
|     if project: | ||||
|         project._projectDir = os.path.dirname(fileObject.name) | ||||
|         project.RelativeToAbsPath() | ||||
|          | ||||
|     return project | ||||
|  | ||||
|  | ||||
| def save(fileObject, project, productionDeployment=False): | ||||
|     if not project._projectDir: | ||||
|         project._projectDir = os.path.dirname(fileObject.name) | ||||
|     project.AbsToRelativePath()  # temporarily change it to relative paths for saving | ||||
|     if ACTIVEGRID_BASE_IDE: | ||||
|         KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} | ||||
|     else: | ||||
|         KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo} | ||||
|  | ||||
|     savedHomeDir = project.homeDir         | ||||
|     if productionDeployment: | ||||
|         # for deployments, we don't want an abs path in homeDir since that | ||||
|         # would tie the app to the current filesystem. So unset it. | ||||
|         project.homeDir = None | ||||
|          | ||||
|     xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) | ||||
|  | ||||
|     if productionDeployment: | ||||
|         project.homeDir = savedHomeDir | ||||
|      | ||||
|     project.RelativeToAbsPath()  # swap it back to absolute path | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
| # Classes | ||||
| @@ -93,7 +44,7 @@ def save(fileObject, project, productionDeployment=False): | ||||
| class BaseProject(object): | ||||
|  | ||||
|     __xmlname__ = "project" | ||||
|     __xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback') | ||||
|     __xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback', '_cacheEnabled') | ||||
|     __xmlattributes__ = ("_homeDir", "version") | ||||
|     __xmlrename__ = { "_homeDir":"homeDir", "_appInfo":"appInfo" } | ||||
|     __xmlflattensequence__ = { "_files":("file",) } | ||||
| @@ -107,9 +58,15 @@ class BaseProject(object): | ||||
|         self._files = [] | ||||
|         self._projectDir = None  # default for homeDir, set on load | ||||
|         self._homeDir = None         # user set homeDir for use in calculating relative path | ||||
|         self._cacheEnabled = 0 | ||||
|         if not ACTIVEGRID_BASE_IDE: | ||||
|             self._appInfo = AppInfo.AppInfo() | ||||
|          | ||||
|  | ||||
|  | ||||
|     def initialize(self): | ||||
|         for file in self._files: | ||||
|             file._parentProj = self | ||||
|  | ||||
|  | ||||
|     def __copy__(self): | ||||
|         clone = Project() | ||||
| @@ -117,18 +74,13 @@ class BaseProject(object): | ||||
|         clone._projectDir = self._projectDir | ||||
|         clone._homeDir = self._homeDir | ||||
|         if not ACTIVEGRID_BASE_IDE: | ||||
|             clone._appInfo = self._appInfo | ||||
|             clone._appInfo = copy.copy(self._appInfo) | ||||
|         return clone | ||||
|  | ||||
|      | ||||
|     def initialize(self): | ||||
|         """ Required method for xmlmarshaller """ | ||||
|         pass | ||||
|  | ||||
|  | ||||
|     def GetAppInfo(self): | ||||
|         return self._appInfo | ||||
|          | ||||
|  | ||||
|  | ||||
|     def AddFile(self, filePath=None, logicalFolder=None, type=None, name=None, file=None): | ||||
|         """ Usage: self.AddFile(filePath, logicalFolder, type, name)  # used for initial generation of object | ||||
| @@ -138,7 +90,7 @@ class BaseProject(object): | ||||
|         if file: | ||||
|             self._files.append(file) | ||||
|         else: | ||||
|             self._files.append(ProjectFile(filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback)) | ||||
|             self._files.append(ProjectFile(self, filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback)) | ||||
|  | ||||
|  | ||||
|     def RemoveFile(self, file): | ||||
| @@ -150,7 +102,7 @@ class BaseProject(object): | ||||
|             for file in self._files: | ||||
|                 if file.filePath == filePath: | ||||
|                     return file | ||||
|                  | ||||
|  | ||||
|         return None | ||||
|  | ||||
|  | ||||
| @@ -160,6 +112,10 @@ class BaseProject(object): | ||||
|  | ||||
|     filePaths = property(_GetFilePaths) | ||||
|  | ||||
|     def _GetProjectFiles(self): | ||||
|         return self._files | ||||
|     projectFiles = property(_GetProjectFiles) | ||||
|  | ||||
|  | ||||
|     def _GetLogicalFolders(self): | ||||
|         folders = [] | ||||
| @@ -170,7 +126,7 @@ class BaseProject(object): | ||||
|  | ||||
|  | ||||
|     logicalFolders = property(_GetLogicalFolders) | ||||
|      | ||||
|  | ||||
|  | ||||
|     def _GetPhysicalFolders(self): | ||||
|         physicalFolders = [] | ||||
| @@ -189,11 +145,11 @@ class BaseProject(object): | ||||
|             return self._homeDir | ||||
|         else: | ||||
|             return self._projectDir | ||||
|          | ||||
|  | ||||
|  | ||||
|     def _SetHomeDir(self, parentPath): | ||||
|         self._homeDir = parentPath | ||||
|          | ||||
|  | ||||
|  | ||||
|     def _IsDefaultHomeDir(self): | ||||
|         return (self._homeDir == None) | ||||
| @@ -212,7 +168,7 @@ class BaseProject(object): | ||||
|             if relFolder and relFolder not in relativeFolders: | ||||
|                 relativeFolders.append(relFolder) | ||||
|         return relativeFolders | ||||
|          | ||||
|  | ||||
|  | ||||
|     def AbsToRelativePath(self): | ||||
|         for file in self._files: | ||||
| @@ -224,6 +180,33 @@ class BaseProject(object): | ||||
|             file.RelativeToAbsPath(self.homeDir) | ||||
|  | ||||
|  | ||||
|     def _SetCache(self, enable): | ||||
|         """ | ||||
|             Only turn this on if your operation assumes files on disk won't change. | ||||
|             Once your operation is done, turn this back off. | ||||
|             Nested enables are allowed, only the last disable will disable the cache. | ||||
|              | ||||
|             This bypasses the IsDocumentModificationDateCorrect call because the modification date check is too costly, it hits the disk and takes too long. | ||||
|         """ | ||||
|         if enable: | ||||
|             if self._cacheEnabled == 0: | ||||
|                 # clear old cache, don't want to accidentally return stale value | ||||
|                 for file in self._files: | ||||
|                     file.ClearCache()         | ||||
|  | ||||
|             self._cacheEnabled += 1 | ||||
|         else: | ||||
|             self._cacheEnabled -= 1 | ||||
|              | ||||
|  | ||||
|  | ||||
|     def _GetCache(self): | ||||
|         return (self._cacheEnabled > 0) | ||||
|  | ||||
|  | ||||
|     cacheEnabled = property(_GetCache, _SetCache) | ||||
|  | ||||
|  | ||||
|     #---------------------------------------------------------------------------- | ||||
|     # BaseDocumentMgr methods | ||||
|     #---------------------------------------------------------------------------- | ||||
| @@ -231,7 +214,7 @@ class BaseProject(object): | ||||
|  | ||||
|     def fullPath(self, fileName): | ||||
|         fileName = super(BaseProject, self).fullPath(fileName) | ||||
|          | ||||
|  | ||||
|         if os.path.isabs(fileName): | ||||
|             absPath = fileName | ||||
|         elif self.homeDir: | ||||
| @@ -242,7 +225,7 @@ class BaseProject(object): | ||||
|  | ||||
|  | ||||
|     def documentRefFactory(self, name, fileType, filePath): | ||||
|         return ProjectFile(filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback) | ||||
|         return ProjectFile(self, filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback) | ||||
|  | ||||
|  | ||||
|     def findAllRefs(self): | ||||
| @@ -256,8 +239,8 @@ class BaseProject(object): | ||||
|         if not xformdir: | ||||
|             xformdir = self.homeDir | ||||
|         return xformdir | ||||
|           | ||||
|     | ||||
|  | ||||
|  | ||||
|     def setRefs(self, files): | ||||
|         self._files = files | ||||
|  | ||||
| @@ -295,16 +278,17 @@ if ACTIVEGRID_BASE_IDE: | ||||
| else: | ||||
|     class Project(BaseProject, basedocmgr.BaseDocumentMgr): | ||||
|         pass | ||||
|          | ||||
|  | ||||
|  | ||||
| class ProjectFile(object): | ||||
|     __xmlname__ = "file" | ||||
|     __xmlexclude__ = ('_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',) | ||||
|     __xmlexclude__ = ('_parentProj', '_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',) | ||||
|     __xmlattributes__ = ["filePath", "logicalFolder", "type", "name"] | ||||
|     __xmldefaultnamespace__ = xmlutils.AG_NS_URL | ||||
|  | ||||
|  | ||||
|     def __init__(self, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None): | ||||
|     def __init__(self, parent=None, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None): | ||||
|         self._parentProj = parent | ||||
|         self.filePath = filePath | ||||
|         self.logicalFolder = logicalFolder | ||||
|         self.type = type | ||||
| @@ -316,35 +300,44 @@ class ProjectFile(object): | ||||
|  | ||||
|  | ||||
|     def _GetDocumentModel(self): | ||||
|         # possible bug is if document gets replaced outside of IDE, where we'll return previous doc. | ||||
|         # originally added a timestamp check but that increased the time again to 4x | ||||
|         if self._docModelCallbackCacheReturnValue:  # accelerator for caching document, got 4x speed up. | ||||
|         if (self._docCallbackCacheReturnValue | ||||
|         and (self._parentProj.cacheEnabled or self._docCallbackCacheReturnValue.IsDocumentModificationDateCorrect())): | ||||
|             return self._docModelCallbackCacheReturnValue | ||||
|              | ||||
|  | ||||
|         if self._getDocCallback: | ||||
|             self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath) | ||||
|             return self._docModelCallbackCacheReturnValue | ||||
|              | ||||
|  | ||||
|         return None | ||||
|  | ||||
|          | ||||
|  | ||||
|     document = property(_GetDocumentModel) | ||||
|      | ||||
|  | ||||
|  | ||||
|     def _GetDocument(self): | ||||
|         # Hack, just return the IDE document wrapper that corresponds to the runtime document model | ||||
|         # callers should have called ".document" before calling ".ideDocument" | ||||
|         if self._docCallbackCacheReturnValue:  # accelerator for caching document, got 4x speed up. | ||||
|         # Return the IDE document wrapper that corresponds to the runtime document model | ||||
|         if (self._docCallbackCacheReturnValue | ||||
|         and (self._parentProj.cacheEnabled or self._docCallbackCacheReturnValue.IsDocumentModificationDateCorrect())): | ||||
|             return self._docCallbackCacheReturnValue | ||||
|  | ||||
|         if self._getDocCallback: | ||||
|             self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath) | ||||
|             return self._docCallbackCacheReturnValue | ||||
|  | ||||
|         return None | ||||
|      | ||||
|  | ||||
|  | ||||
|     ideDocument = property(_GetDocument) | ||||
|  | ||||
|  | ||||
|     def ClearCache(self): | ||||
|         self._docCallbackCacheReturnValue = None | ||||
|         self._docModelCallbackCacheReturnValue = None | ||||
|  | ||||
|  | ||||
|     def _typeEnumeration(self): | ||||
|         return basedocmgr.FILE_TYPE_LIST | ||||
|          | ||||
|  | ||||
|  | ||||
|     def _GetPhysicalFolder(self): | ||||
|         dir = None | ||||
| @@ -356,7 +349,7 @@ class ProjectFile(object): | ||||
|  | ||||
|  | ||||
|     physicalFolder = property(_GetPhysicalFolder) | ||||
|      | ||||
|  | ||||
|  | ||||
|     def GetRelativeFolder(self, parentPath): | ||||
|         parentPathLen = len(parentPath) | ||||
| @@ -364,7 +357,7 @@ class ProjectFile(object): | ||||
|         dir = None | ||||
|         if self.filePath: | ||||
|             dir = os.path.dirname(self.filePath) | ||||
|             if dir.startswith(parentPath): | ||||
|             if dir.startswith(parentPath + os.sep): | ||||
|                 dir = "." + dir[parentPathLen:]  # convert to relative path | ||||
|             if os.sep != '/': | ||||
|                 dir = dir.replace(os.sep, '/')  # always save out with '/' as path separator for cross-platform compatibility. | ||||
| @@ -375,7 +368,7 @@ class ProjectFile(object): | ||||
|         """ Used to convert path to relative path for saving (disk format) """ | ||||
|         parentPathLen = len(parentPath) | ||||
|  | ||||
|         if self.filePath.startswith(parentPath): | ||||
|         if self.filePath.startswith(parentPath + os.sep): | ||||
|             self.filePath = "." + self.filePath[parentPathLen:]  # convert to relative path | ||||
|             if os.sep != '/': | ||||
|                 self.filePath = self.filePath.replace(os.sep, '/')  # always save out with '/' as path separator for cross-platform compatibility. | ||||
| @@ -385,8 +378,8 @@ class ProjectFile(object): | ||||
|  | ||||
|     def RelativeToAbsPath(self, parentPath): | ||||
|         """ Used to convert path to absolute path (for any necessary disk access) """ | ||||
|         if self.filePath.startswith("."):  # relative to project file | ||||
|             self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath)) | ||||
|         if self.filePath.startswith("./"):  # relative to project file | ||||
|             self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath))  # also converts '/' to os.sep | ||||
|  | ||||
|  | ||||
|     #---------------------------------------------------------------------------- | ||||
| @@ -399,21 +392,29 @@ class ProjectFile(object): | ||||
|         import wx.lib.docview | ||||
|         if not self._doc: | ||||
|             docMgr = wx.GetApp().GetDocumentManager() | ||||
|              | ||||
|             doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW) | ||||
|             if (doc == None):  # already open | ||||
|                 docs = docMgr.GetDocuments() | ||||
|                 for d in docs: | ||||
|                     if d.GetFilename() == self.filePath: | ||||
|                         doc = d | ||||
|                         break | ||||
|             self._doc = doc | ||||
|  | ||||
|             try: | ||||
|                 doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW) | ||||
|                 if (doc == None):  # already open | ||||
|                     docs = docMgr.GetDocuments() | ||||
|                     for d in docs: | ||||
|                         if d.GetFilename() == self.filePath: | ||||
|                             doc = d | ||||
|                             break | ||||
|                 self._doc = doc | ||||
|             except Exception,e: | ||||
|                 aglogging.reportException(e, stacktrace=True) | ||||
|                  | ||||
|         return self._doc | ||||
|          | ||||
|  | ||||
|  | ||||
|     def _GetLocalServiceProcessName(self): | ||||
|         # HACK: temporary solution to getting process name from wsdlag file. | ||||
|         return self._GetDoc().GetModel().processName | ||||
|         doc = self._GetDoc() | ||||
|         if doc: | ||||
|             return doc.GetModel().processName | ||||
|         else: | ||||
|             return None | ||||
|  | ||||
|  | ||||
|     processName = property(_GetLocalServiceProcessName) | ||||
| @@ -458,33 +459,39 @@ class ProjectFile(object): | ||||
|     localServiceClassName = property(_GetLocalServiceClassName, _SetLocalServiceClassName) | ||||
|  | ||||
|  | ||||
|     def getServiceParameter(self, message, part): | ||||
|         return self._GetDoc().GetModel().getServiceParameter(message, part) | ||||
|  | ||||
|  | ||||
| # only activate this code if we programatically need to access these values | ||||
| ##    def _GetRssServiceBaseURL(self): | ||||
| ##        return self._GetDoc().GetModel().rssServiceBaseURL | ||||
| ## | ||||
| ##         | ||||
| ## | ||||
| ##    def _SetRssServiceBaseURL(self, baseURL): | ||||
| ##        self._GetDoc().GetModel().rssServiceBaseURL = baseURL | ||||
| ##          | ||||
| ##    | ||||
| ## | ||||
| ## | ||||
| ##    rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL) | ||||
| ## | ||||
| ## | ||||
| ##    def _GetRssServiceRssVersion(self): | ||||
| ##        return self._GetDoc().GetModel().rssServiceRssVersion | ||||
| ##         | ||||
| ## | ||||
| ## | ||||
| ##    def _SetRssServiceRssVersion(self, rssVersion): | ||||
| ##        self._GetDoc().GetModel().rssServiceRssVersion = rssVersion | ||||
| ##             | ||||
| ## | ||||
| ## | ||||
| ##    rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion) | ||||
|  | ||||
|  | ||||
|     def _GetServiceRefServiceType(self): | ||||
|         # HACK: temporary solution to getting service type from wsdlag file. | ||||
|         model = self._GetDoc().GetModel() | ||||
|         doc = self._GetDoc() | ||||
|         if not doc: | ||||
|             return None | ||||
|         model = doc.GetModel() | ||||
|         if hasattr(model, 'serviceType'): | ||||
|             return model.serviceType | ||||
|         else: | ||||
| @@ -494,25 +501,27 @@ class ProjectFile(object): | ||||
|     def _SetServiceRefServiceType(self, serviceType): | ||||
|         # HACK: temporary solution to getting service type from wsdlag file. | ||||
|         self._GetDoc().GetModel().serviceType = serviceType | ||||
|          | ||||
|  | ||||
|  | ||||
|     serviceType = property(_GetServiceRefServiceType, _SetServiceRefServiceType) | ||||
|  | ||||
|  | ||||
|     def getExternalPackage(self): | ||||
|         # HACK: temporary solution to getting custom code filename from wsdlag file. | ||||
|         import activegrid.server.deployment as deploymentlib     | ||||
|          | ||||
|         import activegrid.model.projectmodel as projectmodel | ||||
|         import wx | ||||
|         import ProjectEditor | ||||
|  | ||||
|         appInfo = self._GetDoc().GetAppInfo() | ||||
|  | ||||
|         if appInfo.language == None: | ||||
|             language = deploymentlib.LANGUAGE_DEFAULT | ||||
|             language = wx.ConfigBase_Get().Read(ProjectEditor.APP_LAST_LANGUAGE, projectmodel.LANGUAGE_DEFAULT) | ||||
|         else: | ||||
|             language = appInfo.language | ||||
|              | ||||
|         if language == deploymentlib.LANGUAGE_PYTHON: | ||||
|  | ||||
|         if language == projectmodel.LANGUAGE_PYTHON: | ||||
|             suffix = ".py" | ||||
|         elif language == deploymentlib.LANGUAGE_PHP: | ||||
|         elif language == projectmodel.LANGUAGE_PHP: | ||||
|             suffix = ".php" | ||||
|         pyFilename = self.name + suffix | ||||
|         return self._GetDoc().GetAppDocMgr().fullPath(pyFilename) | ||||
| @@ -543,7 +552,63 @@ class Project_10: | ||||
|     def upgradeVersion(self): | ||||
|         currModel = Project() | ||||
|         for file in self._files: | ||||
|             currModel._files.append(ProjectFile(file)) | ||||
|             currModel._files.append(ProjectFile(currModel, file)) | ||||
|         return currModel | ||||
|  | ||||
|  | ||||
| #---------------------------------------------------------------------------- | ||||
| # XML Marshalling Methods | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| if ACTIVEGRID_BASE_IDE: | ||||
|     KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} | ||||
| else: | ||||
|     KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, | ||||
|                   "ag:appInfo" : AppInfo.AppInfo, | ||||
|                   "ag:deploymentDataSource" : AppInfo.DeploymentDataSource, | ||||
|                   "ag:dataSourceBinding" : AppInfo.DataSourceBinding} | ||||
|  | ||||
| def load(fileObject): | ||||
|     version = xmlutils.getAgVersion(fileObject.name) | ||||
|     # most current versions on top | ||||
|     if version == PROJECT_VERSION_050826: | ||||
|         fileObject.seek(0) | ||||
|         project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES, createGenerics=True) | ||||
|     elif version == PROJECT_VERSION_050730: | ||||
|         fileObject.seek(0) | ||||
|         project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}, createGenerics=True) | ||||
|         project = project.upgradeVersion() | ||||
|     else: | ||||
|         # assume it is old version without version number | ||||
|         fileObject.seek(0) | ||||
|         project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}, createGenerics=True) | ||||
|         if project: | ||||
|             project = project.upgradeVersion() | ||||
|         else: | ||||
|             print "Project, unknown version:", version | ||||
|             return None | ||||
|  | ||||
|     if project: | ||||
|         project._projectDir = os.path.dirname(fileObject.name) | ||||
|         project.RelativeToAbsPath() | ||||
|  | ||||
|     return project | ||||
|  | ||||
|  | ||||
| def save(fileObject, project, productionDeployment=False): | ||||
|     if not project._projectDir: | ||||
|         project._projectDir = os.path.dirname(fileObject.name) | ||||
|     project.AbsToRelativePath()  # temporarily change it to relative paths for saving | ||||
|     savedHomeDir = project.homeDir | ||||
|     if productionDeployment: | ||||
|         # for deployments, we don't want an abs path in homeDir since that | ||||
|         # would tie the app to the current filesystem. So unset it. | ||||
|         project.homeDir = None | ||||
|  | ||||
|     xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) | ||||
|  | ||||
|     if productionDeployment: | ||||
|         project.homeDir = savedHomeDir | ||||
|  | ||||
|     project.RelativeToAbsPath()  # swap it back to absolute path | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ import logging.config | ||||
| from activegrid.util.lang import * | ||||
| import activegrid.util.objutils as objutils | ||||
| import activegrid.util.sysutils as sysutils | ||||
| import activegrid.util.appdirs as appdirs | ||||
|  | ||||
| LEVEL_FATAL = logging.FATAL | ||||
| LEVEL_ERROR = logging.ERROR | ||||
| @@ -27,38 +28,47 @@ LEVEL_INFO = logging.INFO | ||||
| LEVEL_DEBUG = logging.DEBUG | ||||
|  | ||||
| EXCEPTION_INFO = 'exceptionInfo' | ||||
| loggingInitialized = False | ||||
|  | ||||
| LOG_MODE_IDE = 1 | ||||
| LOG_MODE_TESTRUN = 2 | ||||
| LOG_MODE_RUN = 3 | ||||
| def initLogging(mode): | ||||
|     configFile = None | ||||
|     if (mode == LOG_MODE_IDE): | ||||
|         configFile = os.getenv("AG_LOGCONFIG_IDE") | ||||
|     elif (mode == LOG_MODE_TESTRUN): | ||||
|         configFile = os.getenv("AG_LOGCONFIG_TESTRUN") | ||||
|     else: | ||||
|         configFile = os.getenv("AG_LOGCONFIG_RUN") | ||||
|     if ((configFile == None) or not os.path.exists(configFile)): | ||||
| def initLogging(mode, force=False): | ||||
|     global ag_debugLogger, loggingInitialized | ||||
|     if (force or not loggingInitialized): | ||||
|         loggingInitialized = True | ||||
|         configFile = None | ||||
|         if (mode == LOG_MODE_IDE): | ||||
|             configFile = "IDELog" | ||||
|             configFile = os.getenv("AG_LOGCONFIG_IDE") | ||||
|         elif (mode == LOG_MODE_TESTRUN): | ||||
|             configFile = "TestRunLog" | ||||
|             configFile = os.getenv("AG_LOGCONFIG_PYTESTRUN") | ||||
|         else: | ||||
|             configFile = "RunLog" | ||||
|         configFile = sysutils.mainModuleDir + "/py" + configFile + ".ini" | ||||
|     if (os.path.exists(configFile)): | ||||
|         fileConfig(configFile) | ||||
|     else: | ||||
|         defaultStream = sys.stderr | ||||
|         if (mode == LOG_MODE_RUN): | ||||
|             defaultStream = sys.stdout | ||||
|         handler = logging.StreamHandler(defaultStream) | ||||
|         handler.setLevel(logging.INFO) | ||||
|         handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s")) | ||||
|         logging.getLogger().addHandler(handler) | ||||
|     return configFile | ||||
|  | ||||
|             configFile = os.getenv("AG_LOGCONFIG_RUN") | ||||
|         if ((configFile == None) or not os.path.exists(configFile)): | ||||
|             if (mode == LOG_MODE_IDE): | ||||
|                 configFile = "IDELog" | ||||
|             elif (mode == LOG_MODE_TESTRUN): | ||||
|                 configFile = "TestRunLog" | ||||
|             else: | ||||
|                 configFile = "RunLog" | ||||
|             configFile = os.path.join(appdirs.getSystemDir(appdirs.AG_LOGS_DIR), "py" + configFile + ".ini") | ||||
|         if (os.path.exists(configFile)): | ||||
|             print "Using logging configuration file: %s" % configFile | ||||
|             fileConfig(configFile) | ||||
|         else: | ||||
|             print "*** Cannot find logging configuration file (%s) -- setting default logging level to WARN ***" % (configFile) | ||||
|             defaultStream = sys.stderr | ||||
|             if (mode == LOG_MODE_RUN): | ||||
|                 defaultStream = sys.stdout | ||||
|             handler = logging.StreamHandler(defaultStream) | ||||
|             handler.setLevel(logging.DEBUG) | ||||
|             handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s")) | ||||
|             logging.getLogger().addHandler(handler) | ||||
|             logging.getLogger().setLevel(logging.WARN) | ||||
|         ag_debugLogger = logging.getLogger("activegrid.debug") | ||||
|         ag_debugLogger.setLevel(logging.DEBUG) | ||||
|         return configFile | ||||
|      | ||||
| ag_debugLogger = logging.getLogger("activegrid.debug") | ||||
|  | ||||
| def log(logger, level, msg, *params): | ||||
| @@ -181,21 +191,18 @@ def addExceptionInfo(e, key, value): | ||||
|     if not e.exceptionInfo.has_key(key): # Never overwrite exception info since we assume earlier info is more specific | ||||
|         e.exceptionInfo[key] = value | ||||
|              | ||||
| def reportException(out=None, stacktrace=False, diffable=False, exception=None): | ||||
| def reportException(exception, out=None, stacktrace=False, diffable=False): | ||||
|     exstr = exceptionToString(exception, stacktrace, diffable) | ||||
|     if (out == None): | ||||
|         print exstr | ||||
|     else: | ||||
|         print >> out, exstr | ||||
|  | ||||
| def exceptionToString(exception=None, stacktrace=False, diffable=False): | ||||
|     if (exception == None): | ||||
|         extype, val, t = sys.exc_info() | ||||
|     else: | ||||
|         extype = objutils.typeToString(exception) | ||||
|         val = exception | ||||
|         if (stacktrace): | ||||
|             e,v,t = sys.exc_info() | ||||
| def exceptionToString(exception, stacktrace=False, diffable=False): | ||||
|     extype = objutils.typeToString(exception) | ||||
|     val = exception | ||||
|     if (stacktrace): | ||||
|         e,v,t = sys.exc_info() | ||||
|     if (diffable): | ||||
|         exstr = removeFileRefs(str(val)) | ||||
|     else: | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| # Name:         appdirs.py | ||||
| # Purpose:      Utilities for retrieving special application dirs | ||||
| # | ||||
| # Author:       Kevin Ollivier | ||||
| # Author:       Kevin Ollivier, Jeff Norton | ||||
| # | ||||
| # Created:      8/27/05 | ||||
| # CVS-ID:       $Id$ | ||||
| @@ -10,50 +10,117 @@ | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| # NOTE: This was made a separate file because it depends upon the  | ||||
| # wx.StandardPaths module, and thus, on wxWidgets, unlike other | ||||
| # utils modules. I wanted to ensure this module is never loaded | ||||
| # from the web server, etc. | ||||
|  | ||||
| from activegrid.util.lang import * | ||||
| import sys | ||||
| import os | ||||
| import string | ||||
| import wx | ||||
| import activegrid.util.sysutils as sysutils | ||||
|  | ||||
| def isWindows(): | ||||
|     return os.name == 'nt' | ||||
|  | ||||
| def _generateDocumentsDir(): | ||||
|     path = "" | ||||
|     if sys.platform == "win32": | ||||
|         from win32com.shell import shell, shellcon | ||||
|         path=shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0) | ||||
|     elif sys.platform == "darwin": | ||||
|         import macfs, MACFS | ||||
|         fsspec_disk, fsspec_desktop = macfs.FindFolder( MACFS.kOnSystemDisk, MACFS.kDocumentsFolderType, 0) | ||||
|         path = macfs.FSSpec((fsspec_disk, fsspec_desktop, '')).as_pathname() | ||||
|      | ||||
|     if path == "": | ||||
|         path = os.path.expanduser("~") | ||||
|  | ||||
|     return path | ||||
| def _getSystemDir(kind): | ||||
|     if (kind == AG_LOGS_DIR): | ||||
|         return os.path.join(getSystemDir(AG_SYSTEM_DIR) , "logs") | ||||
|     elif (kind == AG_DEMOS_DIR): | ||||
|         return os.path.join(getSystemDir(AG_SYSTEM_DIR), "demos") | ||||
|     else: | ||||
|         path = "" | ||||
|         if (sysutils.isServer()): | ||||
|             path = os.getenv("ACTIVEGRID_SERVER_HOME") | ||||
|             if ((path is None) or (len(path) < 1)): | ||||
|                 path = sysutils.mainModuleDir | ||||
|         else: | ||||
|             path = os.getenv("AG_DOCUMENTS_DIR") | ||||
|             if ((path is None) or (len(path) < 1)): | ||||
|                 if sysutils.isWindows(): | ||||
|                     ifDefPy() | ||||
|                     try: | ||||
|                         from win32com.shell import shell, shellcon | ||||
|                         path = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0) | ||||
|                     except: | ||||
|                         pass | ||||
|                     endIfDef() | ||||
|                     if ((path is None) or (len(path) < 1)): | ||||
|                         homedrive = asString(os.getenv("HOMEDRIVE")) | ||||
|                         homepath = os.getenv("HOMEPATH") | ||||
| ##                        if ((homedrive is not None) and (len(homedrive) > 0) and (homepath is not None) and (len(homepath) > 0)): | ||||
|                         path = os.path.join(homedrive, homepath, "MYDOCU~1") | ||||
|                 else: | ||||
|                     ifDefPy() | ||||
|                     if sys.platform == "darwin": | ||||
|                         try: | ||||
|                             import macfs | ||||
|                             import MACFS | ||||
|                             fsspec_disk, fsspec_desktop = macfs.FindFolder(MACFS.kOnSystemDisk, MACFS.kDocumentsFolderType, 0) | ||||
|                             path = macfs.FSSpec((fsspec_disk, fsspec_desktop, '')).as_pathname() | ||||
|                         except: | ||||
|                             pass | ||||
|                     endIfDef() | ||||
|                  | ||||
|                 ifDefPy() | ||||
|                 if ((path is None) or (len(path) < 1)): | ||||
|                     path = os.path.expanduser("~") | ||||
|                 endIfDef() | ||||
|                 if ((path is None) or (len(path) < 1)): | ||||
|                     path = "/" | ||||
|                 path = os.path.join(path, "ActiveGrid") | ||||
|              | ||||
| documents_folder = _generateDocumentsDir() | ||||
|         return path | ||||
|          | ||||
|  | ||||
| AG_SYSTEM_DIR = 0 | ||||
| AG_LOGS_DIR = 1 | ||||
| AG_DEMOS_DIR = 2 | ||||
|  | ||||
| __systemDir = None | ||||
| __logsDir = None | ||||
| __demosDir = None | ||||
|  | ||||
| def getSystemDir(kind=0): | ||||
|     if (kind == AG_SYSTEM_DIR): | ||||
|         global __systemDir | ||||
|         if (__systemDir is None): | ||||
|             __systemDir = _getSystemDir(kind) | ||||
|         return __systemDir | ||||
|     elif (kind == AG_LOGS_DIR): | ||||
|         global __logsDir | ||||
|         if (__logsDir is None): | ||||
|             __logsDir = _getSystemDir(kind) | ||||
|         return __logsDir | ||||
|     elif (kind == AG_DEMOS_DIR): | ||||
|         global __demosDir | ||||
|         if (__demosDir is None): | ||||
|             __demosDir = _getSystemDir(kind) | ||||
|         return __demosDir | ||||
|     return None | ||||
|  | ||||
|  | ||||
| # NOTE: We don't set this at startup because wxStandardPaths needs a running | ||||
| # application object. This makes sure the wxApp will always be created when | ||||
| # we get the folder. | ||||
| ifDefPy() | ||||
| def getAppDataFolder(): | ||||
|     # wxStandardPaths requires a running app | ||||
|     if wx.GetApp() and wx.Platform != "__WXGTK__": | ||||
|         data_folder = wx.StandardPaths.Get().GetUserDataDir() | ||||
|         if not os.path.exists(data_folder): | ||||
|             os.mkdir(data_folder) | ||||
|         return data_folder | ||||
|     else: | ||||
|         # wxBug: on *nix, it wants to point to ~/.appname, but | ||||
|         # so does wxConfig... For now, redirect this to ~/.appbuilder | ||||
|         # when this is fixed, we'll migrate settings to the correct place | ||||
|         return os.path.join(os.path.expanduser("~"), ".appbuilder") | ||||
|     try: | ||||
|         # NOTE: cannot import wx from the server | ||||
|         import wx | ||||
|         # wxStandardPaths requires a running app | ||||
|         if wx.GetApp() and wx.Platform != "__WXGTK__": | ||||
|             data_folder = wx.StandardPaths.Get().GetUserDataDir() | ||||
|             if not os.path.exists(data_folder): | ||||
|                 os.mkdir(data_folder) | ||||
|             return data_folder | ||||
|     except: | ||||
|         pass | ||||
|     # wxBug: on *nix, it wants to point to ~/.appname, but | ||||
|     # so does wxConfig... For now, redirect this to ~/.appbuilder | ||||
|     # when this is fixed, we'll migrate settings to the correct place | ||||
|     return os.path.join(os.path.expanduser("~"), ".appbuilder") | ||||
| endIfDef() | ||||
|  | ||||
|     return "" | ||||
| ifDefPy() | ||||
| def createSystemDirs(): | ||||
|     if (not os.path.exists(getSystemDir())): | ||||
|         os.mkdir(getSystemDir()) | ||||
|     if (not os.path.exists(getSystemDir(AG_LOGS_DIR))): | ||||
|         os.mkdir(getSystemDir(AG_LOGS_DIR)) | ||||
|     if (not os.path.exists(getSystemDir(AG_DEMOS_DIR))): | ||||
|         os.mkdir(getSystemDir(AG_DEMOS_DIR)) | ||||
| endIfDef() | ||||
|   | ||||
							
								
								
									
										118
									
								
								wxPython/samples/ide/activegrid/util/datetimeparser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								wxPython/samples/ide/activegrid/util/datetimeparser.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| #---------------------------------------------------------------------------- | ||||
| # Name:         datetimeparser.py | ||||
| # | ||||
| # Purpose:      - Instantiate datetime.datetime/date instance from a string | ||||
| #                 date representation. | ||||
| #                 Uses dateutil from http://labix.org/python-dateutil. | ||||
| # | ||||
| #               - Creates string representation of datetime/date instance. | ||||
| # | ||||
| # | ||||
| # Author:       Simon Toens | ||||
| # | ||||
| # Created:      28-Feb-06 | ||||
| # CVS-ID: | ||||
| # Copyright:    (c) 2005 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| import datetime | ||||
|  | ||||
| try: | ||||
|     import dateutil.parser | ||||
|     DATEUTIL_INSTALLED = True | ||||
| except ImportError: | ||||
|     DATEUTIL_INSTALLED = False | ||||
|  | ||||
| ISO_8601_DATE_FORMAT = "%Y-%m-%d" | ||||
| ISO_8601_TIME_FORMAT = "%H:%M:%S" | ||||
| ISO_8601_DATETIME_FORMAT = "%s %s" %(ISO_8601_DATE_FORMAT, | ||||
|                                      ISO_8601_TIME_FORMAT) | ||||
|  | ||||
| DEFAULT_DATETIME = datetime.datetime(1, 1, 1, 0, 0, 0, 0) | ||||
|  | ||||
|  | ||||
| def format(dateobj, formatstr=None): | ||||
|     if (formatstr != None and _isDateTimeObject(dateobj)): | ||||
|         return dateobj.strftime(str(formatstr)) | ||||
|     return str(dateobj) | ||||
|  | ||||
|  | ||||
| def parse(datestr, formatstr=None, asdate=False, astime=False): | ||||
|     """Instantiates and returns a datetime instance from the datestr datetime | ||||
|        representation. | ||||
|         | ||||
|        Optionally, a format string may be used. The format is only loosely | ||||
|        interpreted, its only purpose beeing to determine if the year is first | ||||
|        or last in datestr, and whether the day is in front or follows the | ||||
|        month. If no formatstr is passed in, dateutil tries its best to parse | ||||
|        the datestr. The default date format is YYYY-mm-dd HH:SS. | ||||
|         | ||||
|        If asdate is True, returns a date instance instead of a datetime | ||||
|        instance, if astime is True, returns a time instance instead of a | ||||
|        datetime instance.""" | ||||
|      | ||||
|         | ||||
|     dayfirst, yearfirst = _getDayFirstAndYearFirst(formatstr) | ||||
|  | ||||
|     rtn = None | ||||
|  | ||||
|     try: | ||||
|         if DATEUTIL_INSTALLED: | ||||
|             rtn = dateutil.parser.parse(str(datestr), fuzzy=True, | ||||
|                                         dayfirst=dayfirst, yearfirst=yearfirst, | ||||
|                                         default=DEFAULT_DATETIME) | ||||
|         else: | ||||
|             rtn = DEFAULT_DATETIME | ||||
|     except: | ||||
|         rtn = DEFAULT_DATETIME | ||||
|  | ||||
|     if (asdate and isinstance(rtn, datetime.datetime)): | ||||
|         rtn = datetime.date(rtn.year, rtn.month, rtn.day) | ||||
|     elif (astime and isinstance(rtn, datetime.datetime)): | ||||
|         rtn = datetime.time(rtn.hour, rtn.minute, rtn.second, rtn.microsecond) | ||||
|  | ||||
|     return rtn | ||||
|  | ||||
|  | ||||
| def _isDateTimeObject(obj): | ||||
|     return (isinstance(obj, datetime.datetime) or | ||||
|             isinstance(obj, datetime.date) or | ||||
|             isinstance(obj, datetime.time)) | ||||
|  | ||||
|  | ||||
| def _getDayFirstAndYearFirst(formatstr): | ||||
|     dayFirst = False | ||||
|     yearFirst = False | ||||
|      | ||||
|     gotYear = False | ||||
|     gotMonth = False | ||||
|     gotDay = False | ||||
|  | ||||
|     if (formatstr == None): | ||||
|         formatstr = "" | ||||
|      | ||||
|     for c in formatstr: | ||||
|         if (c.lower() == "y"): | ||||
|             if (gotYear): | ||||
|                 continue | ||||
|             if (not gotDay and not gotMonth): | ||||
|                 yearFirst = True | ||||
|             gotYear = True | ||||
|  | ||||
|         elif (c.lower() == "m"): | ||||
|             if (gotMonth): | ||||
|                 continue | ||||
|             if (not gotDay): | ||||
|                 dayFirst = False | ||||
|             gotMonth = True | ||||
|              | ||||
|         elif (c.lower() == "d"): | ||||
|             if (gotDay): | ||||
|                 continue | ||||
|             if (not gotMonth): | ||||
|                 dayFirst = True | ||||
|             gotDay = True | ||||
|          | ||||
|  | ||||
|     return dayFirst, yearFirst | ||||
| @@ -19,6 +19,7 @@ import zipfile | ||||
|  | ||||
| import activegrid.util.aglogging as aglogging | ||||
| import activegrid.util.sysutils as sysutils | ||||
| import activegrid.util.utillang as utillang | ||||
| from activegrid.util.lang import * | ||||
|  | ||||
| global fileutilsLogger | ||||
| @@ -31,6 +32,65 @@ fileutilsLogger = logging.getLogger("activegrid.util.fileutils") | ||||
| aglogging.setLevelFatal(fileutilsLogger) | ||||
| #logging.getLogger().addHandler(logging.StreamHandler(sys.stderr)) | ||||
|  | ||||
| def addRef(varname): | ||||
|     return "${%s}" % varname | ||||
|  | ||||
| AG_SYSTEM_VAR_NAMES = [] # all AG System vars, with ${} syntax | ||||
|  | ||||
| AG_SYSTEM_VAR = "AG_SYSTEM" | ||||
| AG_SYSTEM_VAR_REF = addRef(AG_SYSTEM_VAR) | ||||
| AG_SYSTEM_VAR_NAMES.append(AG_SYSTEM_VAR_REF) | ||||
|  | ||||
| AG_SYSTEM_STATIC_VAR = "AG_SYSTEM_STATIC" | ||||
| AG_SYSTEM_STATIC_VAR_REF = addRef(AG_SYSTEM_STATIC_VAR) | ||||
| AG_SYSTEM_VAR_NAMES.append(AG_SYSTEM_STATIC_VAR_REF) | ||||
|  | ||||
| AG_APP_VAR = "AG_APP" | ||||
| AG_APP_STATIC_VAR = "AG_APP_STATIC" | ||||
|  | ||||
| # _initAGSystemVars needs to be called to initialize the following two | ||||
| # containers: | ||||
| EXPANDED_AG_SYSTEM_VARS = {} # ${varname} -> value (path) | ||||
| # ${varname}, ordered from longest to shortest path value | ||||
| AG_SYSTEM_VARS_LENGTH_ORDER = []  | ||||
|  | ||||
| def _initAGSystemVars(): | ||||
|     if (len(EXPANDED_AG_SYSTEM_VARS) > 0): | ||||
|         return | ||||
|      | ||||
|     for v in AG_SYSTEM_VAR_NAMES: | ||||
|         EXPANDED_AG_SYSTEM_VARS[v] = os.path.abspath(expandVars(v)) | ||||
|         AG_SYSTEM_VARS_LENGTH_ORDER.append(v) | ||||
|          | ||||
|     AG_SYSTEM_VARS_LENGTH_ORDER.sort(_sortByValLength) | ||||
|  | ||||
|  | ||||
| def parameterizePathWithAGSystemVar(inpath): | ||||
|     """Returns parameterized path if path starts with a known AG directory. Otherwise returns path as it was passed in.""" | ||||
|     _initAGSystemVars() | ||||
|     path = inpath | ||||
|     if not sysutils.isWindows(): | ||||
|         # ensure we have forward slashes | ||||
|         path = path.replace("\\", "/") | ||||
|          | ||||
|     path = os.path.abspath(path) | ||||
|  | ||||
|     for varname in AG_SYSTEM_VARS_LENGTH_ORDER: | ||||
|         varval = EXPANDED_AG_SYSTEM_VARS[varname] | ||||
|         if path.startswith(varval): | ||||
|             return path.replace(varval, varname) | ||||
|          | ||||
|     return inpath | ||||
|  | ||||
| def startsWithAgSystemVar(path): | ||||
|     """Returns True if path starts with a known AG system env var, False otherwise.""" | ||||
|     for varname in AG_SYSTEM_VAR_NAMES: | ||||
|         if path.startswith(varname): | ||||
|             return True | ||||
|     return False | ||||
|          | ||||
| def _sortByValLength(v1, v2): | ||||
|     return len(EXPANDED_AG_SYSTEM_VARS[v2]) - len(EXPANDED_AG_SYSTEM_VARS[v1]) | ||||
|  | ||||
| def makeDirsForFile(filename): | ||||
|     d = os.path.dirname(filename) | ||||
| @@ -44,7 +104,7 @@ def createFile(filename, mode='w'): | ||||
|     f = file(filename, mode) | ||||
|     return f | ||||
|  | ||||
| def compareFiles(file1, file2): | ||||
| def compareFiles(file1, file2, ignore=None): | ||||
| ##    result = filecmp.cmp(file1, file2) | ||||
| ##    if result: | ||||
| ##        return 0 | ||||
| @@ -62,6 +122,9 @@ def compareFiles(file1, file2): | ||||
|         elif (len(line2) == 0): | ||||
|             return -1 | ||||
|         elif (line1 != line2): | ||||
|             if (ignore != None): | ||||
|                 if (line1.startswith(ignore) or line2.startswith(ignore)): | ||||
|                     continue | ||||
|             line1 = line1.replace(" ", "") | ||||
|             line2 = line2.replace(" ", "") | ||||
|             if (line1 != line2): | ||||
| @@ -81,7 +144,10 @@ def compareFiles(file1, file2): | ||||
|                         continue | ||||
|                 return -1 | ||||
|  | ||||
| def expandVars(value): | ||||
| def expandKnownAGVars(value): | ||||
|     return expandVars(value, includeEnv=False) | ||||
|  | ||||
| def expandVars(value, includeEnv=True): | ||||
|     """Syntax: ${myvar,default="default value"}""" | ||||
|     import activegrid.runtime as runtime | ||||
|     sx = value.find("${") | ||||
| @@ -97,16 +163,19 @@ def expandVars(value): | ||||
|                     defaultValue = value[defsx+10:endx-1] | ||||
|             if (defaultValue == None): | ||||
|                 varname = value[sx+2:endx] | ||||
|             if (varname == "AG_SYSTEM"): | ||||
|             if (varname == AG_SYSTEM_VAR): | ||||
|                 varval = runtime.appInfo.getSystemDir() | ||||
|             elif (varname == "AG_SYSTEM_STATIC"): | ||||
|             elif (varname == AG_SYSTEM_STATIC_VAR): | ||||
|                 varval = runtime.appInfo.getSystemStaticDir() | ||||
|             elif (varname == "AG_APP"): | ||||
|             elif (varname == AG_APP_VAR): | ||||
|                 varval = runtime.appInfo.getAppDir() | ||||
|             elif (varname == "AG_APP_STATIC"): | ||||
|             elif (varname == AG_APP_STATIC_VAR): | ||||
|                 varval = runtime.appInfo.getAppStaticDir() | ||||
|             else: | ||||
|                 varval = os.getenv(varname) | ||||
|                 if (includeEnv): | ||||
|                     varval = os.getenv(varname) | ||||
|                 else: | ||||
|                     varval = None | ||||
|             if ((varval == None) and (defaultValue != None)): | ||||
|                 varval = defaultValue | ||||
|             if (varval == None): | ||||
| @@ -148,22 +217,21 @@ def convertSourcePath(path, to, otherdir=None): | ||||
|         return otherdir + path[ix+7:] | ||||
|  | ||||
|  | ||||
| def visit(directory, files, extension): | ||||
| def visit(directory, files, extension, maxLevel=None, level=1): | ||||
|     testdirs = os.listdir(directory) | ||||
|     for thing in testdirs: | ||||
|         fullpath = os.path.join(directory, thing) | ||||
|         if (os.path.isdir(fullpath)): | ||||
|             visit(fullpath, files, extension) | ||||
|         if (os.path.isdir(fullpath) and (maxLevel == None or level < maxLevel)): | ||||
|             visit(fullpath, files, extension, maxLevel, level+1) | ||||
|         elif thing.endswith(extension): | ||||
|             fullname = os.path.normpath(os.path.join(directory, thing)) | ||||
|             if not fullname in files: | ||||
|                 files.append(fullname) | ||||
|   | ||||
| def listFilesByExtensionInPath(path=[], extension='.lyt'): | ||||
|     #Collect input and output arguments into one bunch | ||||
| def listFilesByExtensionInPath(path=[], extension='.lyt', maxLevel=None): | ||||
|     retval = [] | ||||
|     for directory in path: | ||||
|         visit(directory, retval, extension) | ||||
|         visit(directory, retval, extension, maxLevel) | ||||
|     return retval | ||||
|  | ||||
| def getFileLastModificationTime(fileName): | ||||
| @@ -311,6 +379,21 @@ def remove(file): | ||||
|         shutil.rmtree(file) | ||||
| endIfDef() | ||||
|  | ||||
| def getUserTempDir(): | ||||
|     systemTempDir = utillang.getSystemTempDir() | ||||
|     userName = sysutils.getUserName() | ||||
|     userNameNoSpace = userName.replace('_','__').replace(' ','_') | ||||
|     userTempDir = systemTempDir + os.sep + "activegrid_" + userNameNoSpace | ||||
|     return userTempDir | ||||
|  | ||||
| def createUserTempDir(): | ||||
|     userTempDir = getUserTempDir() | ||||
|     if not os.path.exists(userTempDir): | ||||
|         os.makedirs(userTempDir) | ||||
|         os.chmod(userTempDir, 0700) | ||||
|  | ||||
| createUserTempDir() | ||||
|  | ||||
| ifDefPy() | ||||
| import warnings | ||||
| warnings.filterwarnings("ignore", message="tmpnam is a potential security risk to your program") | ||||
|   | ||||
| @@ -16,7 +16,8 @@ import sys | ||||
| import os | ||||
| import __builtin__ | ||||
| import types | ||||
| import xml.sax.saxutils as saxutils | ||||
| import activegrid.util.utillang as utillang | ||||
| import activegrid.util.datetimeparser as datetimeparser | ||||
| from types import * | ||||
| from activegrid.util.lang import * | ||||
|  | ||||
| @@ -65,6 +66,18 @@ def setStaticAttr(obj, attr, value): | ||||
|         classDesc = obj.__class__ | ||||
|     setattr(classDesc, attr, value) | ||||
|  | ||||
| def hasAttrFast(obj, name): | ||||
|     if hasRawAttr(obj, name): | ||||
|         return True | ||||
|     if hasattr(obj, '_complexType'): | ||||
|         complexType=obj._complexType | ||||
|         element=complexType.findElement(name) | ||||
|         if element: | ||||
|             return True | ||||
|     if hasattr(obj, name): | ||||
|         return True | ||||
|     return False | ||||
|  | ||||
| def moduleForName(moduleName): | ||||
|     module = None | ||||
|     pathList = moduleName.split('.') | ||||
| @@ -114,15 +127,22 @@ def newInstance(className, objargs=None): | ||||
|         if ((len(objargs) < 1) or (objargs[0].lower() == "false") or (not objargs[0])): | ||||
|             return False | ||||
|         return True | ||||
|     if className == "str" or className == "unicode": # don"t strip: blanks are significant | ||||
|     if className == "str" or className == "unicode": # don't strip: blanks are significant | ||||
|         if len(objargs) > 0: | ||||
|             try: | ||||
|                 return saxutils.unescape(objargs[0]).encode() | ||||
|                 return utillang.unescape(objargs[0]).encode() | ||||
|             except: | ||||
|                 return "?" | ||||
|         else: | ||||
|             return "" | ||||
|  | ||||
|              | ||||
|     if className == "date": | ||||
|         return datetimeparser.parse(objargs[0], asdate=True) | ||||
|     if className == "datetime": | ||||
|         return datetimeparser.parse(objargs[0]) | ||||
|     if className == "time": | ||||
|         return datetimeparser.parse(objargs[0], astime=True) | ||||
|          | ||||
|     classtype = classForName(className) | ||||
|     if (classtype == None): | ||||
|         raise Exception("Could not find class %s" % className) | ||||
| @@ -135,23 +155,35 @@ def newInstance(className, objargs=None): | ||||
| def getClassProperty(classType, propertyName): | ||||
|     return getattr(classType, propertyName) | ||||
|      | ||||
| def toDiffableRepr(value, exclude=None): | ||||
| def toDiffableRepr(value, maxLevel=None): | ||||
|     if (value == None): | ||||
|         return "None" | ||||
|     if (maxLevel == None): | ||||
|         maxLevel = 8 | ||||
|     maxLevel -= 1 | ||||
|     if (maxLevel < 0): | ||||
|         return typeToString(value, PRINT_OBJ_DIFFABLE) | ||||
| ##    if ((exclude != None) and not isinstance(value, (basestring, int))): | ||||
| ##        for v in exclude: | ||||
| ##            if (v is value): | ||||
| ##                return "<recursive reference>" | ||||
| ##        exclude.append(value) | ||||
| ##    elif (isinstance(value, ObjectType) and hasattr(value, "__dict__")): | ||||
| ##        if (exclude == None): | ||||
| ##            exclude = [] | ||||
| ##        s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, exclude)) | ||||
|     elif (not isinstance(value, (BooleanType, ClassType, ComplexType, DictType, DictionaryType,  | ||||
|     if (not isinstance(value, (BooleanType, ClassType, ComplexType, DictType, DictionaryType,  | ||||
|                                FloatType, IntType, ListType, LongType, StringType, TupleType,  | ||||
|                                UnicodeType, BufferType, BuiltinFunctionType, BuiltinMethodType, | ||||
|                                CodeType, FrameType, FunctionType, GeneratorType, InstanceType, | ||||
|                                LambdaType, MethodType, ModuleType, SliceType, TracebackType, | ||||
|                                TypeType, XRangeType))): | ||||
|         if (hasattr(value, "__str__")): | ||||
|         if (hasattr(value, "_toDiffableString")): | ||||
|             s = value._toDiffableString(maxLevel) | ||||
|         elif (hasattr(value, "__str__")): | ||||
|             s = str(value) | ||||
|         elif (hasattr(value, "__dict__")): | ||||
|             s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, exclude)) | ||||
|             s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, maxLevel)) | ||||
|         else: | ||||
|             s = str(type(value)) | ||||
|         ix2 = s.find(" object at 0x") | ||||
| @@ -173,33 +205,31 @@ def toDiffableRepr(value, exclude=None): | ||||
|                 else: | ||||
|                     items.append("'%s'" % v) | ||||
|             else: | ||||
|                 items.append(toDiffableString(v, exclude)) | ||||
|                 items.append(toDiffableString(v, maxLevel)) | ||||
|         s = "[" + ", ".join(items) + "]" | ||||
|     elif (isinstance(value, dict)): | ||||
|         if (exclude == None): | ||||
|             exclude = [] | ||||
|         items = [] | ||||
|         for key, val in value.iteritems(): | ||||
|             if (isinstance(val, UnicodeType)): | ||||
|                 items.append("'%s': u'%s'" % (key, toDiffableString(val, exclude))) | ||||
|                 items.append("'%s': u'%s'" % (key, toDiffableString(val, maxLevel))) | ||||
|             elif (isinstance(val, basestring)): | ||||
|                 items.append("'%s': '%s'" % (key, toDiffableString(val, exclude))) | ||||
|                 items.append("'%s': '%s'" % (key, toDiffableString(val, maxLevel))) | ||||
|             else: | ||||
|                 items.append("'%s': %s" % (key, toDiffableString(val, exclude))) | ||||
|                 items.append("'%s': %s" % (key, toDiffableString(val, maxLevel))) | ||||
|         s = "{" + ", ".join(items) + "}" | ||||
|     else: | ||||
|         s = str(value) | ||||
|     return s | ||||
|      | ||||
| def toDiffableString(value, exclude=None): | ||||
|     if (value == None): | ||||
|         return "None" | ||||
|     if ((exclude != None) and not isinstance(value, (basestring, int))): | ||||
|         for v in exclude: | ||||
|             if (v is value): | ||||
|                 return "<recursive reference>" | ||||
|         exclude.append(value) | ||||
|     s = toDiffableRepr(value) | ||||
| def toDiffableString(value, maxLevel=None): | ||||
| ##    if (value == None): | ||||
| ##        return "None" | ||||
| ##    if ((exclude != None) and not isinstance(value, (basestring, int))): | ||||
| ##        for v in exclude: | ||||
| ##            if (v is value): | ||||
| ##                return "<recursive reference>" | ||||
| ##        exclude.append(value) | ||||
|     s = toDiffableRepr(value, maxLevel) | ||||
|     ds = "" | ||||
|     i = s.find(" at 0x")  | ||||
|     start = 0 | ||||
|   | ||||
							
								
								
									
										380
									
								
								wxPython/samples/ide/activegrid/util/parser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								wxPython/samples/ide/activegrid/util/parser.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,380 @@ | ||||
| #---------------------------------------------------------------------------- | ||||
| # Name:         parser.py | ||||
| # Purpose:      parsing utilities | ||||
| # | ||||
| # Author:       Jeff Norton | ||||
| # | ||||
| # Created:      8/9/05 | ||||
| # CVS-ID:       $Id$ | ||||
| # Copyright:    (c) 2004-2005 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| import re | ||||
| from activegrid.util.lang import * | ||||
| ifDefPy() | ||||
| import string | ||||
| import array | ||||
| endIfDef() | ||||
|  | ||||
| XPATH_ROOT_VAR = '__rootObj__' | ||||
| GETOBJECTPARTNAMES  =   ["primaryRef", "ref", "orderings", "limit"] | ||||
|  | ||||
| class Tokenizer(object): | ||||
|      | ||||
|     TOKEN_IDENT = 1 | ||||
|     TOKEN_STRING = 2 | ||||
|     TOKEN_OP = 3 | ||||
|     TOKEN_WS = 4 | ||||
| ##    TOKEN_PLACEHOLDER = 5 | ||||
|      | ||||
|     def __init__(self, text, identStart=None, tokenSep=None, ignoreWhitespace=True): | ||||
|         """ | ||||
| Turn a string into individual tokens.  Three types of tokens are recognized: | ||||
|     TOKEN_IDENT:   identifiers (those that start with the identStart pattern) | ||||
|     TOKEN_STRING:  quoted string | ||||
|     TOKEN_OP:      everything else | ||||
| Tokens are separated by white space or the tokenSep pattern.   | ||||
| Constructor parameters: | ||||
|     text:  The string to tokenize | ||||
|     identStart:  A regular expression describing characters which start an identifier | ||||
|                  The default expression accepts letters, "_", and "/". | ||||
|     tokenSep:    A regular expression describing the characters which end a token  | ||||
|                  (in addition to whitespace).  The default expression accepts | ||||
|                  anything except alpha-numerics, "_", "/", and ":". | ||||
| Usage: | ||||
|     Invoke getNextToken (or next) to get the next token.  The instance variables | ||||
|     token, and tokenVal will be populated with the current token type (TOKEN_IDENT, | ||||
|     TOKEN_STRING, or TOEKN_OP) and value respectively.  nextToken and nextTokenVal | ||||
|     will also be available for lookahead.   The next method is similar to | ||||
|     getNextToken but also returns the token value.  A value of None signals end | ||||
|     of stream.                                            | ||||
|         """ | ||||
|         self.ignoreWhitespace=ignoreWhitespace | ||||
|         ifDefPy() | ||||
|         if (isinstance(text, array.array)): | ||||
|             text = text.tostring() | ||||
|         endIfDef() | ||||
|         self.text = asString(text) | ||||
|         self.textIndex = 0 | ||||
|         self.textLen = len(self.text) | ||||
|         self.token = None | ||||
|         self.tokenVal = None | ||||
|         self.nextToken = None | ||||
|         self.nextTokenVal = None | ||||
|         if (identStart == None): | ||||
|             identStart = "[a-zA-Z_/]" | ||||
|         if (tokenSep == None): | ||||
|             tokenSep = "[^a-zA-Z0-9_/:]" | ||||
|         self.identStart = re.compile(identStart) | ||||
|         self.tokenSep = re.compile(tokenSep) | ||||
|         self.getNextToken() # Prime the pump | ||||
|          | ||||
|     def isEscaped(text, index): | ||||
|         if ((index > 0) and (text[index-1] == '\\') and ((index < 2) or (text[index-2] != '\\'))): | ||||
|             return True | ||||
|         return False | ||||
|     isEscaped = staticmethod(isEscaped) | ||||
|  | ||||
|     def findClosingQuote(text, index, char): | ||||
|         index = index + 1 | ||||
|         while True: | ||||
|             endIndex = text.find(char, index) | ||||
|             if (endIndex < 1): | ||||
|                 return -1 | ||||
|             if (Tokenizer.isEscaped(text, endIndex)): | ||||
|                 index = endIndex+1 | ||||
|             else: | ||||
|                 break | ||||
|         return endIndex + 1 | ||||
|     findClosingQuote = staticmethod(findClosingQuote) | ||||
|  | ||||
|     def _findClosing(self, char): | ||||
|         if (self.textIndex >= self.textLen): | ||||
|             raise Exception("The text \"%s\" has an unmatched string starting at %d" % (self.text, self.textIndex)) | ||||
|         index = Tokenizer.findClosingQuote(self.text, self.textIndex, char) | ||||
|         if (index < 0): | ||||
|             raise Exception("The text \"%s\" has an unmatched string starting at %d" % (self.text, self.textIndex-1)) | ||||
|         return index | ||||
|          | ||||
|     def next(self): | ||||
|         self.getNextToken() | ||||
|         if (self.token == None): | ||||
|             raise StopIteration() | ||||
|         return self.tokenVal | ||||
|  | ||||
|     def getNextToken(self): | ||||
|         self.token = self.nextToken | ||||
|         self.tokenVal = self.nextTokenVal | ||||
|         while (self.textIndex < self.textLen): | ||||
|             c = self.text[self.textIndex] | ||||
|             if (c not in string.whitespace): | ||||
|                 if (c == '"' or c == "'" or c == '`'): | ||||
|                     endIndex = self._findClosing(c) | ||||
|                     self.nextToken = self.TOKEN_STRING | ||||
|                     self.nextTokenVal = self.text[self.textIndex:endIndex] | ||||
|                     self.textIndex = endIndex | ||||
|                     return | ||||
|                 elif (self.identStart.search(c)): | ||||
|                     endMatch = self.tokenSep.search(self.text, self.textIndex+1) | ||||
|                     if (endMatch): | ||||
|                         endIndex = endMatch.start() | ||||
|                     else: | ||||
|                         endIndex = self.textLen | ||||
|                     self.nextToken = self.TOKEN_IDENT | ||||
|                     self.nextTokenVal = self.text[self.textIndex:endIndex] | ||||
|                     self.textIndex = endIndex | ||||
|                     return | ||||
|                 else: | ||||
|                     self.nextToken = self.TOKEN_OP | ||||
|                     endIndex = self.textIndex + 1 | ||||
|                     if (c == '<' or c == '>' or c == '!' or c == '='): | ||||
|                         if ((endIndex < self.textLen) and (self.text[endIndex] == '=')): | ||||
|                             endIndex += 1 | ||||
|                     elif ((c == '%') and (endIndex < self.textLen)): | ||||
|                         c = self.text[endIndex] | ||||
|                         if (c in ['d', 'i', 'o', 'u', 'x', 'X', 'e', 'E', 'f', 'F', 'g', 'G', 'c', 'r', 's', '%']): | ||||
|                             endIndex += 1 | ||||
| ##                            self.nextToken = self.TOKEN_PLACEHOLDER # Should really be this but no one can handle it yet | ||||
|                     self.nextTokenVal = self.text[self.textIndex:endIndex] | ||||
|                     self.textIndex = endIndex | ||||
|                     return | ||||
|             elif not self.ignoreWhitespace: | ||||
|                 self.nextToken=self.TOKEN_WS | ||||
|                 self.nextTokenVal="" | ||||
|                 while c in string.whitespace: | ||||
|                     self.nextTokenVal+=c | ||||
|                     self.textIndex+=1 | ||||
|                     if self.textIndex==len(self.text): | ||||
|                         break | ||||
|                     c=self.text[self.textIndex] | ||||
|                 return | ||||
|             self.textIndex += 1 | ||||
|         self.nextToken = None | ||||
|         self.nextTokenVal = None | ||||
|  | ||||
| def isXPathNonVar(var): | ||||
|     """Returns true iff var is a string ("foo" or 'foo') or a number.""" | ||||
|     if (var.startswith("'") and var.endswith("'")) or \ | ||||
|             (var.startswith('"') and var.endswith('"')): | ||||
|         return True | ||||
|  | ||||
|     # list from XPathToCode, below | ||||
|     if var.lower() in ["count", "empty", "true", "false", "null", "and", "or", \ | ||||
|             "like", "not"]: | ||||
|         return True | ||||
|  | ||||
|     try: | ||||
|         t=int(var) | ||||
|         return True | ||||
|     except TypeError, e: | ||||
|         pass | ||||
|     except ValueError, e: | ||||
|         pass | ||||
|  | ||||
|     return False | ||||
|  | ||||
| def xpathToCode(xpaths, convertBracket=True): | ||||
|     if ((xpaths == None) or (len(xpaths) < 1)): | ||||
|         return "True" | ||||
|     if (not isinstance(xpaths, (list, tuple))): | ||||
|         xpaths = [xpaths] | ||||
|     result = [] | ||||
|     for xpath in xpaths: | ||||
|         t = Tokenizer(xpath, "[a-zA-Z0-9_/:\.]", "[^a-zA-Z0-9_/:\.]", ignoreWhitespace=False) | ||||
|         expr = [] | ||||
|         lastToken=None | ||||
|         while t.nextToken != None: | ||||
|             t.getNextToken() | ||||
|             if (t.token == Tokenizer.TOKEN_WS): | ||||
|                 expr.append(" ") | ||||
|             elif (t.token == Tokenizer.TOKEN_OP): | ||||
|                 if (t.tokenVal == "="): | ||||
|                     expr.append("==") | ||||
|                 elif (t.tokenVal == "[" and convertBracket): | ||||
|                     expr.append("(") | ||||
|                 elif (t.tokenVal == "]" and convertBracket): | ||||
|                     expr.append(")") | ||||
|                 else: | ||||
|                     expr.append(t.tokenVal) | ||||
|             elif (t.token == Tokenizer.TOKEN_IDENT): | ||||
|                 if (t.tokenVal == "and"): | ||||
|                     expr.append(" and ") | ||||
|                 elif (t.tokenVal == "or"): | ||||
|                     expr.append(" or ") | ||||
|                 elif (t.tokenVal == "not"): | ||||
|                     expr.append(" not ") | ||||
|                 elif (t.tokenVal == "like"): | ||||
|                     # REVIEW stoens@activegrid.com 02-Nov-05 -- | ||||
|                     # This is very limited support for like: | ||||
|                     # typically like queries look like this: "foo like 'blah%'". | ||||
|                     # So translate this into "foo.startswith(blah)". | ||||
|                     # We should use a regular expression to support '%'s in | ||||
|                     # arbitrary places in the string. After 1.1. | ||||
|                     if t.nextToken and t.nextTokenVal.endswith("%'"): | ||||
|                         t.getNextToken() # throw away the "like" token | ||||
|                         last = len(expr) - 1 | ||||
|                         expr[last] = "%s.startswith(%s')"\ | ||||
|                             % (expr[last], t.tokenVal[:-2]) | ||||
|                     else: | ||||
|                         # old behavior | ||||
|                         expr.append(t.tokenVal) | ||||
|                      | ||||
|                 elif (t.tokenVal == "count"): | ||||
|                     expr.append("len") | ||||
|                 elif (t.tokenVal == 'empty'): | ||||
|                     expr.append('ctx.isEmptyPath') | ||||
|                 elif (t.tokenVal == 'true'): | ||||
|                     expr.append(_parseConstantFunction(t, 'True')) | ||||
|                 elif (t.tokenVal == 'false'): | ||||
|                     expr.append(_parseConstantFunction(t, 'False')) | ||||
|                 elif (t.tokenVal == 'null'): | ||||
|                     expr.append(_parseConstantFunction(t, 'None')) | ||||
|                 elif (-1!=t.tokenVal.find(':')): | ||||
|                     serviceDef, args=_parseServiceFunction(t) | ||||
|  | ||||
|                     # XXX handle serviceDef, args being None | ||||
|  | ||||
|                     for i in range(len(args)): | ||||
|                         args[i]=xpathToCode(args[i], False) | ||||
|                     jargs="[%s]" % (",".join(args)) | ||||
|  | ||||
|                     # XXX should be processmodel.DATASERVICE_PROCESS_NAME, not "dataservice" | ||||
|                     if serviceDef[0]=='dataservice': | ||||
|                         expr.append("runtimesupport.invokeDataServiceWrapper(%s, %s, ctx, locals())" % \ | ||||
|                                 (serviceDef, jargs)) | ||||
|                     else: | ||||
|                         expr.append("runtimesupport.invokeServiceWrapper(%s, %s, ctx)" % \ | ||||
|                                 (serviceDef, jargs)) | ||||
|                 else: | ||||
|                     if (lastToken==')' or lastToken==']'): | ||||
|                         wasFunc=True | ||||
|                     else: | ||||
|                         wasFunc=False | ||||
|                     if (t.tokenVal.startswith('/')) and not wasFunc: | ||||
|                         expr.append(XPATH_ROOT_VAR) | ||||
|                     expr.append(t.tokenVal.replace('/','.')) | ||||
|                 lastToken=t.tokenVal | ||||
|             else:  | ||||
|                 expr.append(t.tokenVal) | ||||
|                  | ||||
|  | ||||
|         if (len(expr) == 2 and expr[0]==" "): | ||||
|             expr = "".join(expr) | ||||
|             result.append(expr) | ||||
|         elif (len(expr) > 1): | ||||
|             expr = "".join(expr) | ||||
|             result.append("(%s)" % expr) | ||||
|         elif (len(expr) > 0): | ||||
|             result.append(expr[0]) | ||||
|          | ||||
|     return " and ".join(result) | ||||
|  | ||||
| def _parseArgs(t): | ||||
|     args=[] | ||||
|     argcon="" | ||||
|  | ||||
|     if t.tokenVal!='(': | ||||
|         return [] | ||||
|     if t.nextTokenVal==')': | ||||
|         t.getNextToken() | ||||
|         return [] | ||||
|  | ||||
|     depth=1 | ||||
|  | ||||
|     while(depth!=0): | ||||
|         if not t.nextToken: | ||||
|             raise Exception("parameters list with no closing ) after token: %s" % t.tokenVal) | ||||
|         t.getNextToken() | ||||
|  | ||||
|         if t.tokenVal=='(': | ||||
|             depth+=1 | ||||
|         if t.tokenVal==')': | ||||
|             depth-=1 | ||||
|  | ||||
|         if depth==0 or (depth==1 and t.tokenVal==','): | ||||
|             args.append(argcon) | ||||
|             argcon="" | ||||
|         else: | ||||
|             argcon+=t.tokenVal | ||||
|     return args | ||||
|  | ||||
| def _parseServiceFunction(t): | ||||
|     """Parses what appears to be a service function call into serviceDefs and args lists. | ||||
|  | ||||
|     Returns None, None if the serviceFunction appears to be invalid. | ||||
|     """ | ||||
|     if t.nextTokenVal!='(': | ||||
|         return t.tokenVal, None | ||||
|  | ||||
|     serviceDef=t.tokenVal.split(':') | ||||
|     t.getNextToken() | ||||
|     args=_parseArgs(t) | ||||
|  | ||||
|     return serviceDef, args | ||||
|      | ||||
| def _parseConstantFunction(t, outputValue): | ||||
|     firstVal = t.tokenVal | ||||
|     if t.nextTokenVal != '(': | ||||
|         return firstVal | ||||
|     t.getNextToken() | ||||
|     if t.nextTokenVal != ')': | ||||
|         return "%s%s" % (firstVal, '(') | ||||
|     t.getNextToken() | ||||
|     return outputValue | ||||
|  | ||||
| def parseDSPredicate(ctx, str, vars, valueList=None): | ||||
|     from activegrid.util.utillang import evalCode | ||||
|     from activegrid.util.utillang import ObjAsDict | ||||
|  | ||||
|     if valueList == None: | ||||
|         valueList = [] | ||||
|     indexVar=0 | ||||
|     oldIndexVar=0 | ||||
|     sourceStr=str | ||||
|     inlinedPredicate=[] | ||||
|     qualifications=[] | ||||
|     while True: | ||||
|         oldIndexVar = indexVar | ||||
|         dollarCurlForm = False | ||||
|         quoted = False | ||||
|         indexVar = sourceStr.find("bpws:getVariableData", indexVar) | ||||
|         if indexVar == -1: | ||||
|             indexVar = sourceStr.find("${", oldIndexVar) | ||||
|             if indexVar == -1: | ||||
|                 break | ||||
|             dollarCurlForm = True | ||||
|         if indexVar > 0 and sourceStr[indexVar-1] in ('"',"'"): | ||||
|             quoted = True | ||||
|         if not dollarCurlForm: | ||||
|             openParen = sourceStr.find("(", indexVar) | ||||
|             if openParen == -1: | ||||
|                 break | ||||
|             closeParen = sourceStr.find(")", openParen) | ||||
|             if closeParen == -1: | ||||
|                 break | ||||
|         else: | ||||
|             openParen = indexVar+1 | ||||
|             closeParen = sourceStr.find("}", openParen) | ||||
|             if closeParen == -1: | ||||
|                 break | ||||
|         varRef = sourceStr[openParen+1: closeParen] | ||||
|         if varRef.startswith('"') or varRef.startswith("'"): | ||||
|             varRef = varRef[1:] | ||||
|         if varRef.endswith('"') or varRef.endswith("'"): | ||||
|             varRef = varRef[:-1] | ||||
|         if isinstance(vars, dict) or isinstance(vars, ObjAsDict): | ||||
|             varRefCode = xpathToCode(varRef) | ||||
|             value = evalCode(varRefCode, vars) | ||||
|         else: | ||||
|             value = ctx.evalPath(vars, varRef) | ||||
|         inlinedPredicate.append(sourceStr[oldIndexVar:indexVar]) | ||||
|         if quoted: | ||||
|             inlinedPredicate.append("%s" % value) | ||||
|         else: | ||||
|             inlinedPredicate.append('%s') | ||||
|             valueList.append(value) | ||||
|         indexVar = closeParen+1 | ||||
|     inlinedPredicate.append(sourceStr[oldIndexVar:]) | ||||
|     qualifications.append(''.join(inlinedPredicate)) | ||||
|     return qualifications, valueList | ||||
| @@ -21,3 +21,91 @@ def caseInsensitiveCompare(s1, s2): | ||||
|         return -1 | ||||
|     else: | ||||
|         return 1 | ||||
|  | ||||
| def multiSplit(stringList, tokenList=[" "]): | ||||
|     """Splits strings in stringList by tokens, returns list of string.""" | ||||
|     if not stringList: return [] | ||||
|     if isinstance(tokenList, basestring): | ||||
|         tokenList = [tokenList] | ||||
|     if isinstance(stringList, basestring): | ||||
|         stringList = [stringList] | ||||
|     rtnList = stringList | ||||
|     for token in tokenList: | ||||
|         rtnList = rtnList[:] | ||||
|         for string in rtnList: | ||||
|             if string.find(token) > -1: | ||||
|                 rtnList.remove(string) | ||||
|                 names = string.split(token) | ||||
|                 for name in names: | ||||
|                     name = name.strip() | ||||
|                     if name: | ||||
|                         rtnList.append(name) | ||||
|     return rtnList | ||||
|  | ||||
| QUOTES = ("\"", "'") | ||||
|  | ||||
| def _findArgStart(argStr): | ||||
|     i = -1 | ||||
|     for c in argStr: | ||||
|         i += 1 | ||||
|         if (c == " "): | ||||
|             continue | ||||
|         elif (c == ","): | ||||
|             continue | ||||
|         return i | ||||
|     return None | ||||
|  | ||||
| def _findArgEnd(argStr): | ||||
|     quotedArg = True | ||||
|     argEndChar = argStr[0] | ||||
|     if (not argEndChar in QUOTES): | ||||
|         argEndChar = "," | ||||
|         quotedArg = False | ||||
|     i = -1 | ||||
|     firstChar = True | ||||
|     for c in argStr: | ||||
|         i+= 1 | ||||
|         if (firstChar): | ||||
|             firstChar = False | ||||
|             if (quotedArg): | ||||
|                 continue | ||||
|         if (c == argEndChar): | ||||
|             if (quotedArg): | ||||
|                 return min(i+1, len(argStr)) | ||||
|             else: | ||||
|                 return i | ||||
|     return i | ||||
|  | ||||
| def parseArgs(argStr, stripQuotes=False): | ||||
|     """ | ||||
|     Given a str representation of method arguments, returns list arguments (as | ||||
|     strings). | ||||
|      | ||||
|     Input: "('[a,b]', 'c', 1)" -> Output: ["'[a,b]'", "'c'", "1"]. | ||||
|  | ||||
|     If stripQuotes, removes quotes from quoted arg. | ||||
|     """ | ||||
|     if (argStr.startswith("(")): | ||||
|         argStr = argStr[1:] | ||||
|         if (argStr.endswith(")")): | ||||
|             argStr = argStr[:-1] | ||||
|         else: | ||||
|             raise AssertionError("Expected argStr to end with ')'") | ||||
|  | ||||
|     rtn = [] | ||||
|     argsStr = argStr.strip() | ||||
|     while (True): | ||||
|         startIndex = _findArgStart(argStr) | ||||
|         if (startIndex == None): | ||||
|             break | ||||
|         argStr = argStr[startIndex:] | ||||
|         endIndex = _findArgEnd(argStr) | ||||
|         if (endIndex == len(argStr) - 1): | ||||
|             rtn.append(argStr.strip()) | ||||
|             break         | ||||
|         t = argStr[:endIndex].strip() | ||||
|         if (stripQuotes and t[0] in QUOTES and t[-1] in QUOTES): | ||||
|             t = t[1:-1] | ||||
|         rtn.append(t) | ||||
|         argStr = argStr[endIndex:] | ||||
|     return rtn | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|  | ||||
| import sys | ||||
| import os | ||||
| import time | ||||
|  | ||||
| # this will be set to true in IDE.py when we are running release builds. | ||||
| isRelease = False | ||||
| @@ -26,6 +27,12 @@ isRelease = False | ||||
|  | ||||
| MAINMODULE_DIR = "AG_MAINMODULE_DIR" | ||||
| IS_RELEASE = "AG_IS_RELEASE" | ||||
| IS_COMMERCIAL = "AG_IS_COMMERCIAL" | ||||
| AG_SYSTEM_START_TIME_ENV_NAME = "AG_SYSTEM_START_TIME" | ||||
|  | ||||
| def isCommercial(): | ||||
|      | ||||
|     return os.path.exists(os.path.join(mainModuleDir,"commercial.txt")) or 'true' == (str(os.getenv(IS_COMMERCIAL)).lower()) | ||||
|   | ||||
| def isRelease(): | ||||
|     return 'true' == (str(os.getenv(IS_RELEASE)).lower()) | ||||
| @@ -39,7 +46,16 @@ def setRelease(value): | ||||
| def isWindows(): | ||||
|     return os.name == 'nt' | ||||
|  | ||||
| __isServer = False | ||||
|  | ||||
| def setServerMode(isServer): | ||||
|     global __isServer | ||||
|     __isServer = isServer | ||||
|      | ||||
| def isServer(): | ||||
|     global __isServer | ||||
|     return __isServer | ||||
|      | ||||
| def _generateMainModuleDir(): | ||||
|     mainModuleDir = os.getenv(MAINMODULE_DIR) | ||||
|     if mainModuleDir:  # if environment variable set, return it | ||||
| @@ -85,3 +101,16 @@ def getCommandNameForExecPath(execPath): | ||||
|         return '"%s"' % execPath | ||||
|     return execPath | ||||
|  | ||||
| def getUserName(): | ||||
|     if isWindows(): | ||||
|         return os.getenv('USERNAME') | ||||
|     else: | ||||
|         # 06-Feb-06 stoens@activegrid.com -- | ||||
|         # this blows up the linux cc runs with "Inappropriate ioctl for device" | ||||
|         #return os.getlogin() | ||||
|         return os.getenv('USER')         | ||||
|  | ||||
| def getCurrentTimeAsFloat(): | ||||
|     return time.time() | ||||
|  | ||||
| systemStartTime = getCurrentTimeAsFloat() | ||||
|   | ||||
							
								
								
									
										146
									
								
								wxPython/samples/ide/activegrid/util/utillang.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								wxPython/samples/ide/activegrid/util/utillang.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| #---------------------------------------------------------------------------- | ||||
| # Name:         utillang.py | ||||
| # Purpose:      Provide language specific utilities  | ||||
| # | ||||
| # Author:       Joel Hare | ||||
| # | ||||
| # Created:      8/23/05 | ||||
| # CVS-ID:       $Id$ | ||||
| # Copyright:    (c) 2004-2005 ActiveGrid, Inc. | ||||
| # License:      wxWindows License | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| import os | ||||
| import sys | ||||
| import UserDict | ||||
| import tempfile | ||||
| import xml.sax.saxutils as saxutils | ||||
|  | ||||
| import activegrid.util.parser as parser | ||||
|  | ||||
| PY2WEB_codepages = { | ||||
|      'cp1251' : 'CP-1251', | ||||
|      'koi8_r' : 'KOI8-R', | ||||
| } | ||||
|  | ||||
| def evalXPath(xpath, data, specialEntries=None): | ||||
|     codeStr = parser.xpathToCode(xpath) | ||||
|     return evalCode(codeStr, data, specialEntries) | ||||
|  | ||||
| def evalCode(codeStr, data, specialEntries=None): | ||||
|     if isinstance(data, ObjAsDict): | ||||
|         namespace = data | ||||
|     elif isinstance(data, dict): | ||||
|         namespace = dict(data) | ||||
|     else: | ||||
|         namespace = ObjAsDict(data) | ||||
|     if specialEntries: | ||||
|         for key, value in specialEntries.items(): | ||||
|             namespace.addSpecialEntry(key, value) | ||||
|     return eval(codeStr, {}, namespace) | ||||
|  | ||||
| def deriveCharset(): | ||||
|     charset = None | ||||
|     encodingString = sys.getdefaultencoding() | ||||
|     if encodingString != 'ascii': | ||||
|         charset = PY2WEB_codepages.get(encodingString.lower()) | ||||
|         if charset == None: | ||||
|             charset = encodingString | ||||
|     return charset | ||||
|  | ||||
| def toUTF8(value): | ||||
|     """ | ||||
|     Converts all unicode and non-string values to utf-8. | ||||
|     This assumes string instances are already encoded in utf-8. | ||||
|     Note that us-ascii is a subset of utf-8. | ||||
|     """ | ||||
|     if isinstance(value, unicode): | ||||
|         return value.encode('utf-8') | ||||
|     return str(value) | ||||
|  | ||||
| def toUnicode(value): | ||||
|     """ | ||||
|     Converts all strings non-string values to unicode. | ||||
|     This assumes string instances are encoded in utf-8. | ||||
|     Note that us-ascii is a subset of utf-8. | ||||
|     """ | ||||
|     if not isinstance(value, unicode): | ||||
|         if not isinstance(value, str): | ||||
|             return unicode(value) | ||||
|         return unicode(value, 'utf-8') | ||||
|     return value | ||||
|      | ||||
|  | ||||
| def getSystemTempDir(): | ||||
|     return tempfile.gettempdir() | ||||
|  | ||||
| def getEnvVar(name, defaultVal=None): | ||||
|     if os.environ.has_key(name): | ||||
|         return os.environ[name] | ||||
|     return defaultVal | ||||
|  | ||||
| class ObjAsDict(UserDict.DictMixin): | ||||
|     """ | ||||
|     Passing this to eval as the local variables dictionary allows the | ||||
|     evaluated code to access properties in the wrapped object | ||||
|     """ | ||||
|     def __init__(self, obj): | ||||
|         self.obj = obj | ||||
|         self.specialEntries = {} | ||||
|  | ||||
|     def __getitem__(self, key): | ||||
|         try: | ||||
|             return getattr(self.obj, key) | ||||
|         except AttributeError, e: | ||||
|             if self.specialEntries.has_key(key): | ||||
|                 return self.specialEntries[key] | ||||
|             raise KeyError(e.args) | ||||
|     def __setitem__(self, key, item): setattr(self.obj, key, item) | ||||
|     def __delitem__(self, key): delattr(self.obj, key) | ||||
|     def keys(self): | ||||
|         ret=[] | ||||
|         for i in list(dir(self.obj)+self.specialEntries.keys()): | ||||
|             if i=="__doc__" or i=="__module__": | ||||
|                 pass | ||||
|             elif i not in ret: | ||||
|                 ret.append(i) | ||||
|         return ret | ||||
|  | ||||
|     def addSpecialEntry(self, key, value): | ||||
|         self.specialEntries[key] = value | ||||
|  | ||||
| global saxXMLescapeDoubleQuote | ||||
| saxXMLescapeDoubleQuote = {'"':'"'} | ||||
|  | ||||
| global saxXMLescapesAllQuotes | ||||
| # IE doesn't support ' but it doesn't seem like we should need this escaped at all so I took it out. | ||||
| saxXMLescapesAllQuotes = {'"':'"', "'":"'"} | ||||
|  | ||||
| global saxXMLunescapes | ||||
| saxXMLunescapes = {'"':'"', "'":"'"} | ||||
|  | ||||
| def escape(data, extraEscapes=None): | ||||
|     """Escape ', ", &, <, and > in a string of data. | ||||
|  | ||||
|     Basically, everything that saxutils.escape does (and this calls that, at | ||||
|     least for now), but with " and ' added as well. | ||||
|  | ||||
|     TODO: make this faster; saxutils.escape() is really slow | ||||
|     """ | ||||
|      | ||||
|     global saxXMLescapeDoubleQuote | ||||
|     if (extraEscapes == None): | ||||
|         extraEscapes = saxXMLescapeDoubleQuote | ||||
|     return saxutils.escape(data, extraEscapes) | ||||
|  | ||||
| def unescape(data): | ||||
|     """Unescape ', ", &, <, and > in a string of data. | ||||
|  | ||||
|     Basically, everything that saxutils.unescape does (and this calls that, at | ||||
|     least for now), but with " and ' added as well. | ||||
|  | ||||
|     TODO: make this faster; saxutils.unescape() is really slow | ||||
|     """ | ||||
|      | ||||
|     global saxXMLunescapes | ||||
|     return saxutils.unescape(data, saxXMLunescapes) | ||||
| @@ -2,7 +2,7 @@ | ||||
| # Name:         xmlmarshaller.py | ||||
| # Purpose: | ||||
| # | ||||
| # Authors:       John Spurling, Joel Hare, Alan Mullendore | ||||
| # Authors:      John Spurling, Joel Hare, Jeff Norton, Alan Mullendore | ||||
| # | ||||
| # Created:      7/28/04 | ||||
| # CVS-ID:       $Id$ | ||||
| @@ -16,14 +16,18 @@ import logging | ||||
| ifDefPy() | ||||
| import xml.sax | ||||
| import xml.sax.handler | ||||
| import xml.sax.saxutils | ||||
| import datetime | ||||
| endIfDef() | ||||
| import xml.sax.saxutils as saxutils | ||||
| import activegrid.util.utillang as utillang | ||||
| import activegrid.util.objutils as objutils | ||||
| import activegrid.util.sysutils as sysutils | ||||
| import activegrid.util.aglogging as aglogging | ||||
|  | ||||
| MODULE_PATH = "__main__" | ||||
|  | ||||
| ## ToDO remove maxOccurs "unbounded" resolves to -1 hacks after bug 177 is fixed | ||||
| ##unboundedVal = 2147483647 # value used for maxOccurs == "unbounded" | ||||
|  | ||||
| """ | ||||
| Special attributes that we recognize: | ||||
| @@ -109,7 +113,6 @@ __xmlcdatacontent__ = "messyContent" | ||||
|  | ||||
| global xmlMarshallerLogger | ||||
| xmlMarshallerLogger = logging.getLogger("activegrid.util.xmlmarshaller.marshal") | ||||
| xmlMarshallerLogger.setLevel(aglogging.LEVEL_WARN) | ||||
| # INFO  : low-level info | ||||
| # DEBUG : debugging info | ||||
|  | ||||
| @@ -184,6 +187,7 @@ DICT_ITEM_VALUE_NAME = "value" | ||||
| ################################################################################ | ||||
|  | ||||
| def setattrignorecase(object, name, value): | ||||
| ##    print "[setattrignorecase] name = %s, value = %s" % (name, value) | ||||
|     if (name not in object.__dict__): | ||||
|         namelow = name.lower() | ||||
|         for attr in object.__dict__: | ||||
| @@ -193,27 +197,95 @@ def setattrignorecase(object, name, value): | ||||
|     object.__dict__[name] = value | ||||
|  | ||||
| def getComplexType(obj): | ||||
|     if (hasattr(obj, "_instancexsdcomplextype")): | ||||
|         return obj._instancexsdcomplextype | ||||
|     if (hasattr(obj, "__xsdcomplextype__")): | ||||
|         return obj.__xsdcomplextype__ | ||||
|     return None | ||||
|  | ||||
| def _objectfactory(objname, objargs=None, objclass=None): | ||||
|     "dynamically create an object based on the objname and return it." | ||||
| ##    print "[objectfactory] objname [%s]" % (objname) | ||||
| def _objectfactory(objtype, objargs=None, objclass=None): | ||||
|     "dynamically create an object based on the objtype and return it." | ||||
|     if not isinstance(objargs, list): | ||||
|         objargs = [objargs] | ||||
|     if (objclass != None): | ||||
|         obj = None | ||||
|         if (len(objargs) > 0): | ||||
|             if (hasattr(objclass, "__xmlcdatacontent__")): | ||||
|                 obj = objclass() | ||||
|                 contentAttr = obj.__xmlcdatacontent__ | ||||
|                 obj.__dict__[contentAttr] = str(objargs[0]) | ||||
|                 return obj | ||||
|             return objclass(*objargs) | ||||
|             else: | ||||
|                 obj = objclass(*objargs) | ||||
|         else: | ||||
|             return objclass() | ||||
|     return objutils.newInstance(objname, objargs) | ||||
|             obj = objclass() | ||||
|         if ((obj != None) and (hasattr(obj, 'postUnmarshal'))): | ||||
|             obj.postUnmarshal() | ||||
|         return obj | ||||
|     return objutils.newInstance(objtype, objargs) | ||||
|  | ||||
| class GenericXMLObject(object): | ||||
|     def __init__(self, content=None): | ||||
|         if content != None: | ||||
|             self._content = content | ||||
|             self.__xmlcontent__ = '_content' | ||||
|  | ||||
|     def __str__(self): | ||||
|         return "GenericXMLObject(%s)" % objutils.toDiffableString(self.__dict__) | ||||
|  | ||||
|     def setXMLAttributes(self, xmlName, attrs=None, children=None, nsMap=None, defaultNS=None): | ||||
|         if xmlName != None: | ||||
|             i = xmlName.rfind(':') | ||||
|             if i < 0: | ||||
|                 self.__xmlname__ = xmlName | ||||
|                 if defaultNS != None: | ||||
|                     self.__xmldefaultnamespace__ = str(defaultNS) | ||||
|             else: | ||||
|                 self.__xmlname__ = xmlName[i+1:] | ||||
|                 prefix = xmlName[:i] | ||||
|                 if nsMap.has_key(prefix): | ||||
|                     self.__xmldefaultnamespace__ = str(nsMap[prefix]) | ||||
|         if attrs != None: | ||||
|             for attrname, attr in attrs.items(): | ||||
|                 attrname = str(attrname) | ||||
|                 if attrname == XMLNS or attrname.startswith(XMLNS_PREFIX): | ||||
|                     pass | ||||
|                 elif attrname == "objtype": | ||||
|                     pass | ||||
|                 else: | ||||
|                     if not hasattr(self, '__xmlattributes__'): | ||||
|                         self.__xmlattributes__ = [] | ||||
|                     i = attrname.rfind(':') | ||||
|                     if i >= 0: | ||||
|                         prefix = attrname[:i] | ||||
|                         attrname = attrname[i+1:] | ||||
|                         if not hasattr(self, '__xmlattrnamespaces__'): | ||||
|                             self.__xmlattrnamespaces__ = {} | ||||
|                         if self.__xmlattrnamespaces__.has_key(prefix): | ||||
|                             alist = self.__xmlattrnamespaces__[prefix] | ||||
|                         else: | ||||
|                             alist = [] | ||||
|                         alist.append(attrname) | ||||
|                         self.__xmlattrnamespaces__[prefix] = alist | ||||
|                     self.__xmlattributes__.append(attrname) | ||||
|             if hasattr(self, '__xmlattributes__'): | ||||
|                 self.__xmlattributes__.sort() | ||||
|         if children != None and len(children) > 0: | ||||
|             childList = [] | ||||
|             flattenList = {} | ||||
|             for childname, child in children: | ||||
|                 childstr = str(childname) | ||||
|                 if childstr in childList: | ||||
|                     if not flattenList.has_key(childstr): | ||||
|                         flattenList[childstr] = (childstr,) | ||||
|                 else: | ||||
|                     childList.append(childstr) | ||||
|             if len(flattenList) > 0: | ||||
|                 self.__xmlflattensequence__ = flattenList | ||||
|                  | ||||
|     def initialize(self, arg1=None): | ||||
|         pass | ||||
|              | ||||
|      | ||||
| class Element: | ||||
|     def __init__(self, name, attrs=None, xsname=None): | ||||
|         self.name = name | ||||
| @@ -222,9 +294,11 @@ class Element: | ||||
|         self.children = [] | ||||
|         self.objclass = None | ||||
|         self.xsname = xsname | ||||
|         self.objtype = None | ||||
|          | ||||
|     def getobjtype(self): | ||||
|         objtype = self.attrs.get("objtype") | ||||
| #        objtype = self.attrs.get("objtype") | ||||
|         objtype = self.objtype | ||||
|         if (objtype == None): | ||||
|             if (len(self.children) > 0): | ||||
|                 objtype = "dict" | ||||
| @@ -238,16 +312,35 @@ class NsElement(object): | ||||
|         self.targetNS = None | ||||
|         self.defaultNS = None | ||||
|         self.prefix = None | ||||
|          | ||||
|     def isEmpty(self): | ||||
|         return ((self.nsMap == {}) and (self.targetNS == None) and (self.defaultNS == None)) | ||||
|  | ||||
|     def __str__(self): | ||||
|         if self.prefix == None: | ||||
|             strVal = 'prefix = None; ' | ||||
|         else: | ||||
|             strVal = 'prefix = "%s"; ' % (self.prefix) | ||||
|         if self.targetNS == None: | ||||
|             strVal += 'targetNS = None; ' | ||||
|         else: | ||||
|             strVal += 'targetNS = "%s"; ' % (self.targetNS) | ||||
|         if self.defaultNS == None: | ||||
|             strVal += 'defaultNS = None; ' | ||||
|         else: | ||||
|             strVal += 'defaultNS = "%s"; ' % (self.defaultNS) | ||||
|         if len(self.nsMap) == 0: | ||||
|             strVal += 'nsMap = None; ' | ||||
|         else: | ||||
|             strVal += 'nsMap = {' | ||||
|             for ik, iv in self.nsMap.iteritems(): | ||||
|                 strVal += '%s=%s; ' % (ik,iv) | ||||
|             strVal += '}' | ||||
|         return strVal | ||||
|                 | ||||
|     def setKnownTypes(self, masterKnownTypes, masterKnownNamespaces, parentNSE): | ||||
|         # if we're a nested element, extend our parent element's mapping | ||||
|         if parentNSE != None: | ||||
|             self.knownTypes = parentNSE.knownTypes.copy() | ||||
|             # but if we have a different default namespace, replace the parent's default mappings | ||||
|             if parentNSE.defaultNS != self.defaultNS: | ||||
|             if (self.defaultNS != None) and (parentNSE.defaultNS != self.defaultNS): | ||||
|                 newKT = self.knownTypes.copy() | ||||
|                 for tag in newKT: | ||||
|                     if tag.find(':') < 0: | ||||
| @@ -283,7 +376,6 @@ class NsElement(object): | ||||
|                     self.knownTypes[knownTagName] = mapClass | ||||
|             else:                                           # e.g. "ItemSearchRequest" | ||||
|                 self.knownTypes[tag] = mapClass | ||||
| ##                print 'mapping <%s> to class "%s"' % (tag, mapClass.__name__) | ||||
|  | ||||
|     def expandQName(self, eName, attrName, attrValue): | ||||
|         bigValue = attrValue | ||||
| @@ -298,38 +390,57 @@ class NsElement(object): | ||||
|                 if shortNs == attrNS: | ||||
|                     bigValue = '%s:%s' % (longNs, attrNCName) | ||||
|                     break | ||||
| ##        print '[expandQName] input attrName = "%s" and attrValue "%s"; output = "%s"' % (attrName, attrValue, bigValue) | ||||
|         return bigValue | ||||
|  | ||||
| class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|     def __init__(self, knownTypes=None, knownNamespaces=None): | ||||
|     def __init__(self, knownTypes=None, knownNamespaces=None, xmlSource=None, createGenerics=False): | ||||
|         self.rootelement = None | ||||
|         if (knownTypes == None): | ||||
|             self.knownTypes = {} | ||||
|         if xmlSource == None: | ||||
|             self.xmlSource = "unknown" | ||||
|         else: | ||||
|             self.knownTypes = knownTypes | ||||
|         if (knownNamespaces == None): | ||||
|             self.knownNamespaces = {} | ||||
|         else: | ||||
|             self.knownNamespaces = knownNamespaces | ||||
|             self.xmlSource = xmlSource | ||||
|         self.createGenerics = createGenerics | ||||
|         self.skipper = False | ||||
|         self.elementstack = [] | ||||
|         self.nsstack = [] | ||||
|         self.collectContent = None | ||||
|         if (knownNamespaces == None): | ||||
|             self.knownNamespaces = {} | ||||
|         else: | ||||
|             self.knownNamespaces = knownNamespaces | ||||
|         self.reversedNamespaces = {} | ||||
|         for longns, shortns in self.knownNamespaces.iteritems(): | ||||
|             self.reversedNamespaces[shortns] = longns | ||||
|         self.knownTypes = {} | ||||
|         if (knownTypes != None): | ||||
|             for tag, cls in knownTypes.iteritems(): | ||||
|                 i = tag.rfind(':') | ||||
|                 if i >= 0: | ||||
|                     shortns = tag[:i] | ||||
|                     tag = tag[i+1:] | ||||
|                     if not self.reversedNamespaces.has_key(shortns): | ||||
|                         errorString = 'Error unmarshalling XML document from source "%s": knownTypes specifies an unmapped short namespace "%s" for element "%s"' % (self.xmlSource, shortns, tag) | ||||
|                         raise UnmarshallerException(errorString) | ||||
|                     longns = self.reversedNamespaces[shortns] | ||||
|                     tag = '%s:%s' % (longns, tag) | ||||
|                 self.knownTypes[tag] = cls | ||||
|         #printKnownTypes(self.knownTypes, 'Unmarshaller.XMLObjectFactory.__init__') | ||||
|         xml.sax.handler.ContentHandler.__init__(self) | ||||
|  | ||||
|     def appendElementStack(self, newElement, newNS): | ||||
|         self.elementstack.append(newElement) | ||||
|         if (newNS.isEmpty()): | ||||
|             if (len(self.nsstack) > 0): | ||||
|                 newNS = self.nsstack[-1] | ||||
|             else: | ||||
|                 newNS.knownTypes = self.knownTypes.copy() | ||||
|         else: | ||||
|             if (len(self.nsstack) > 0): | ||||
|                 newNS.setKnownTypes(self.knownTypes, self.knownNamespaces, self.nsstack[-1]) | ||||
|             else: | ||||
|                 newNS.setKnownTypes(self.knownTypes, self.knownNamespaces, None) | ||||
|         if (len(self.nsstack) > 0): | ||||
|             oldNS = self.nsstack[-1] | ||||
|             if newNS.defaultNS == None: | ||||
|                 newNS.defaultNS = oldNS.defaultNS | ||||
|             if newNS.targetNS == None: | ||||
|                 newNS.targetNS = oldNS.targetNS | ||||
|             if len(newNS.nsMap) == 0: | ||||
|                 newNS.nsMap = oldNS.nsMap | ||||
|             elif len(oldNS.nsMap) > 0: | ||||
|                 map = oldNS.nsMap.copy() | ||||
|                 map.update(newNS.nsMap) | ||||
|                 newNS.nsMap = map | ||||
|         self.nsstack.append(newNS) | ||||
|         return newNS | ||||
|      | ||||
| @@ -353,11 +464,16 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|             strVal += '>' | ||||
|             self.collectContent.content += strVal | ||||
|         xsname = name | ||||
|         if name.find(':') > -1:  # Strip namespace prefixes for now until actually looking them up in xsd | ||||
|             name = name[name.rfind(":") + 1:] | ||||
|         i = name.rfind(':') | ||||
|         if i >= 0: | ||||
|             nsname = name[:i] | ||||
|             name = name[i+1:] | ||||
|         else: | ||||
|             nsname = None | ||||
|         element = Element(name, attrs.copy(), xsname=xsname) | ||||
|         # if the element has namespace attributes, process them and add them to our stack | ||||
|         nse = NsElement() | ||||
|         objtype = None | ||||
|         for k in attrs.getNames(): | ||||
|             if k.startswith('xmlns'): | ||||
|                 longNs = attrs[k] | ||||
| @@ -371,8 +487,28 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|                     nse.nsMap[shortNs] = longNs | ||||
|             elif k == 'targetNamespace': | ||||
|                 nse.targetNS = attrs.getValue(k) | ||||
|             elif k == 'objtype': | ||||
|                 objtype = attrs.getValue(k) | ||||
|         nse = self.appendElementStack(element, nse) | ||||
|         element.objclass = nse.knownTypes.get(xsname) | ||||
|         if nsname != None: | ||||
|             if nse.nsMap.has_key(nsname): | ||||
|                 longname = '%s:%s' % (nse.nsMap[nsname], name) | ||||
| ##            elif objtype == None: | ||||
| ##                errorString = 'Error unmarshalling XML document from source "%s": tag "%s" at line "%d", column "%d" has an undefined namespace' % (self.xmlSource, xsname, self._locator.getLineNumber(), self._locator.getColumnNumber()) | ||||
| ##                raise UnmarshallerException(errorString) | ||||
|             elif self.reversedNamespaces.has_key(nsname): | ||||
|                 longname = '%s:%s' % (self.reversedNamespaces[nsname], name) | ||||
|             else: | ||||
|                 longname = xsname | ||||
|         elif nse.defaultNS != None: | ||||
|             longname = '%s:%s' % (nse.defaultNS, name) | ||||
|         else: | ||||
|             longname = name | ||||
|         element.objtype = objtype | ||||
|         element.objclass = self.knownTypes.get(longname) | ||||
|         if element.objclass == None and len(self.knownNamespaces) == 0: | ||||
|             # handles common case where tags are unqualified and knownTypes are too, but there's a defaultNS | ||||
|             element.objclass = self.knownTypes.get(name) | ||||
|         if (hasattr(element.objclass, "__xmlcontent__")): | ||||
|             self.collectContent = element | ||||
|  | ||||
| @@ -387,8 +523,9 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|     def endElement(self, name): | ||||
| ##        print "[endElement] </%s>" % name | ||||
|         xsname = name | ||||
|         if name.find(":") > -1:  # Strip namespace prefixes for now until actually looking them up in xsd | ||||
|             name = name[name.find(":") + 1:] | ||||
|         i = name.rfind(':') | ||||
|         if i >= 0:  # Strip namespace prefixes for now until actually looking them up in xsd | ||||
|             name = name[i+1:] | ||||
|         if self.skipper: | ||||
|             if xsname == "xs:annotation" or xsname == "xsd:annotation":     # here too | ||||
|                 self.skipper = False | ||||
| @@ -405,34 +542,36 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|         element, nse = self.popElementStack() | ||||
|         if ((len(self.elementstack) > 1) and (self.elementstack[-1].getobjtype() == "None")): | ||||
|             parentElement = self.elementstack[-2] | ||||
| ##            print "[endElement] %s: found parent with objtype==None: using its grandparent" % name | ||||
|         elif (len(self.elementstack) > 0): | ||||
|             parentElement = self.elementstack[-1] | ||||
|         objtype = element.getobjtype() | ||||
| ##        print "element objtype is: ", objtype | ||||
|         if (objtype == "None"): | ||||
| ##            print "[endElement] %s: skipping a (objtype==None) end tag" % name | ||||
|             return | ||||
|         constructorarglist = [] | ||||
|         if (len(element.content) > 0): | ||||
|             strippedElementContent = element.content.strip() | ||||
|             if (len(strippedElementContent) > 0): | ||||
|                 constructorarglist.append(element.content) | ||||
|         # If the element requires an object, but none is known, use the GenericXMLObject class | ||||
|         if ((element.objclass == None) and (element.attrs.get("objtype") == None) and ((len(element.attrs) > 0) or (len(element.children) > 0))): | ||||
|             if self.createGenerics: | ||||
|                 element.objclass = GenericXMLObject | ||||
|         obj = _objectfactory(objtype, constructorarglist, element.objclass) | ||||
|         if element.objclass == GenericXMLObject: | ||||
|             obj.setXMLAttributes(str(xsname), element.attrs, element.children, nse.nsMap, nse.defaultNS) | ||||
|         complexType = getComplexType(obj) | ||||
|         if (obj != None): | ||||
|             if (hasattr(obj, "__xmlname__") and getattr(obj, "__xmlname__") == "sequence"): | ||||
|                 self.elementstack[-1].children = oldChildren | ||||
|                 return | ||||
|         if (len(element.attrs) > 0) and not isinstance(obj, list): | ||||
| ##            print "[endElement] %s: element has attrs and the obj is not a list" % name | ||||
|             for attrname, attr in element.attrs.items(): | ||||
|                 if attrname == XMLNS or attrname.startswith(XMLNS_PREFIX): | ||||
|                     if attrname.startswith(XMLNS_PREFIX): | ||||
|                         ns = attrname[XMLNS_PREFIX_LENGTH:] | ||||
|                     else: | ||||
|                         ns = "" | ||||
|                     if complexType != None: | ||||
|                     if complexType != None or element.objclass == GenericXMLObject: | ||||
|                         if not hasattr(obj, "__xmlnamespaces__"): | ||||
|                             obj.__xmlnamespaces__ = {ns:attr} | ||||
|                         elif ns not in obj.__xmlnamespaces__: | ||||
| @@ -447,7 +586,6 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|                         xsdElement = complexType.findElement(attrname) | ||||
|                         if (xsdElement != None): | ||||
|                             type = xsdElement.type | ||||
| ##                            print 'Unmarshalling element "%s", attribute "%s" with type "%s"' % (name, xsdElement.name, type) | ||||
|                             if (type != None): | ||||
|                                 if (type == TYPE_QNAME): | ||||
|                                     attr = nse.expandQName(name, attrname, attr) | ||||
| @@ -455,11 +593,15 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|                                 ### ToDO remove maxOccurs hack after bug 177 is fixed | ||||
|                                 if attrname == "maxOccurs" and attr == "unbounded": | ||||
|                                     attr = "-1" | ||||
|                                 attr = _objectfactory(type, attr) | ||||
|                                 try: | ||||
|                                     attr = _objectfactory(type, attr) | ||||
|                                 except Exception, exceptData: | ||||
|                                     errorString = 'Error unmarshalling attribute "%s" at line %d, column %d in XML document from source "%s": %s' % (attrname, self._locator.getLineNumber(), self._locator.getColumnNumber(), self.xmlSource, str(exceptData)) | ||||
|                                     raise UnmarshallerException(errorString) | ||||
|                     try: | ||||
|                         setattrignorecase(obj, _toAttrName(obj, attrname), attr) | ||||
|                     except AttributeError: | ||||
|                         errorString = 'Error unmarshalling XML document at line %i, column %i: The object type of attribute "%s" of XML element "%s": not specified or known' % (self._locator.getLineNumber(), self._locator.getColumnNumber(), attrname, name) | ||||
|                         errorString = 'Error setting value of attribute "%s" at line %d, column %d in XML document from source "%s": object type of XML element "%s" is not specified or known' % (attrname, self._locator.getLineNumber(), self._locator.getColumnNumber(), self.xmlSource, name) | ||||
|                         raise UnmarshallerException(errorString) | ||||
| ##                    obj.__dict__[_toAttrName(obj, attrname)] = attr | ||||
|         # stuff any child attributes meant to be in a sequence via the __xmlflattensequence__ | ||||
| @@ -474,14 +616,12 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|                         flattenDict[str(xmlnametuple)] = sequencename | ||||
|                     else: | ||||
|                         for xmlname in xmlnametuple: | ||||
| ##                            print "[endElement]: adding flattenDict[%s] = %s" % (xmlname, sequencename) | ||||
|                             flattenDict[xmlname] = sequencename | ||||
|             else: | ||||
|                 raise Exception("Invalid type for __xmlflattensequence___ : it must be a dict") | ||||
|  | ||||
|         # reattach an object"s attributes to it | ||||
|         for childname, child in element.children: | ||||
| ##            print "[endElement] childname is: ", childname, "; child is: ", child | ||||
|             if (childname in flattenDict): | ||||
|                 sequencename = _toAttrName(obj, flattenDict[childname]) | ||||
|                 if (not hasattr(obj, sequencename)): | ||||
| @@ -499,12 +639,13 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|                 else: | ||||
|                     obj[childname] = child | ||||
|             else: | ||||
| ##                print "childname = %s, obj = %s, child = %s" % (childname, repr(obj), repr(child)) | ||||
|                 try: | ||||
|                     setattrignorecase(obj, _toAttrName(obj, childname), child) | ||||
|                 except AttributeError: | ||||
|                     raise MarshallerException("Error unmarshalling child element \"%s\" of XML element \"%s\": object type not specified or known" % (childname, name)) | ||||
| ##                obj.__dict__[_toAttrName(obj, childname)] = child | ||||
|                 # don't replace a good attribute value with a bad one | ||||
|                 childAttrName = _toAttrName(obj, childname) | ||||
|                 if (not hasattr(obj, childAttrName)) or (getattr(obj, childAttrName) == None) or (getattr(obj, childAttrName) == []) or (not isinstance(child, GenericXMLObject)): | ||||
|                     try: | ||||
|                         setattrignorecase(obj, childAttrName, child) | ||||
|                     except AttributeError: | ||||
|                         raise MarshallerException("Error unmarshalling child element \"%s\" of XML element \"%s\": object type not specified or known" % (childname, name)) | ||||
|  | ||||
|         if (complexType != None): | ||||
|             for element in complexType.elements: | ||||
| @@ -524,7 +665,6 @@ class XMLObjectFactory(xml.sax.ContentHandler): | ||||
|         if (len(self.elementstack) > 0): | ||||
| ##            print "[endElement] appending child with name: ", name, "; objtype: ", objtype | ||||
|             parentElement.children.append((name, obj)) | ||||
| ##            print "parentElement now has ", len(parentElement.children), " children" | ||||
|         else: | ||||
|             self.rootelement = obj | ||||
|              | ||||
| @@ -539,7 +679,12 @@ def _toAttrName(obj, name): | ||||
|                 break | ||||
| ##    if (name.startswith("__") and not name.endswith("__")): | ||||
| ##        name = "_%s%s" % (obj.__class__.__name__, name) | ||||
|     return name | ||||
|     return str(name) | ||||
|      | ||||
| def printKnownTypes(kt, where): | ||||
|     print 'KnownTypes from %s' % (where) | ||||
|     for tag, cls in kt.iteritems(): | ||||
|         print '%s => %s' % (tag, str(cls)) | ||||
|  | ||||
| __typeMappingXsdToLang = { | ||||
|     "string": "str", | ||||
| @@ -569,7 +714,7 @@ def xsdToLangType(xsdType): | ||||
|     if xsdType.startswith(XMLSCHEMA_XSD_URL): | ||||
|         xsdType = xsdType[len(XMLSCHEMA_XSD_URL)+1:] | ||||
|     elif xsdType.startswith(AG_URL): | ||||
|         xsdType = xsdType[len(AG_URL)+1:]         | ||||
|         xsdType = xsdType[len(AG_URL)+1:] | ||||
|     langType = __typeMappingXsdToLang.get(xsdType) | ||||
|     if (langType == None): | ||||
|         raise Exception("Unknown xsd type %s" % xsdType) | ||||
| @@ -588,8 +733,11 @@ def _getXmlValue(langValue): | ||||
|     else: | ||||
|         return str(langValue) | ||||
|  | ||||
| def unmarshal(xmlstr, knownTypes=None, knownNamespaces=None, xmlSource=None): | ||||
|     objectfactory = XMLObjectFactory(knownTypes, knownNamespaces) | ||||
| def unmarshal(xmlstr, knownTypes=None, knownNamespaces=None, xmlSource=None, createGenerics=False): | ||||
|     objectfactory = XMLObjectFactory(knownTypes, knownNamespaces, xmlSource, createGenerics) | ||||
|     # on Linux, pyXML's sax.parseString fails when passed unicode | ||||
|     if (not sysutils.isWindows()): | ||||
|         xmlstr = str(xmlstr) | ||||
|     try: | ||||
|         xml.sax.parseString(xmlstr, objectfactory) | ||||
|     except xml.sax.SAXParseException, errorData: | ||||
| @@ -600,17 +748,19 @@ def unmarshal(xmlstr, knownTypes=None, knownNamespaces=None, xmlSource=None): | ||||
|     return objectfactory.getRootObject() | ||||
|  | ||||
| def marshal(obj, elementName=None, prettyPrint=False, marshalType=True, indent=0, knownTypes=None, knownNamespaces=None, encoding=-1): | ||||
| ##    print '[marshal] entered with elementName = "%s"' % (elementName) | ||||
|     worker = XMLMarshalWorker(prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces)     | ||||
|     if obj != None and hasattr(obj, '__xmldeepexclude__'): | ||||
|         worker.xmldeepexclude = obj.__xmldeepexclude__ | ||||
|     xmlstr = "".join(worker._marshal(obj, elementName, indent=indent)) | ||||
|     if (isinstance(encoding, basestring)): | ||||
|         return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, xmlstr.encode(encoding)) | ||||
|     elif (encoding == None): | ||||
|     aglogging.info(xmlMarshallerLogger, "marshal produced string of type %s", type(xmlstr)) | ||||
|     if (encoding == None): | ||||
|         return xmlstr | ||||
|     else: | ||||
|         return '<?xml version="1.0" encoding="%s"?>\n%s' % (sys.getdefaultencoding(), xmlstr) | ||||
|     if (not isinstance(encoding, basestring)): | ||||
|         encoding = sys.getdefaultencoding() | ||||
|     if (not isinstance(xmlstr, unicode)): | ||||
|         xmlstr = xmlstr.decode() | ||||
|     xmlstr = u'<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, xmlstr) | ||||
|     return xmlstr.encode(encoding) | ||||
|  | ||||
| class XMLMarshalWorker(object): | ||||
|     def __init__(self, marshalType=True, prettyPrint=False, knownTypes=None, knownNamespaces=None): | ||||
| @@ -695,7 +845,7 @@ class XMLMarshalWorker(object): | ||||
|             newNS.prefix = self.nsstack[-1].prefix | ||||
|         else: | ||||
|             newNS.prefix = '' | ||||
|         if hasattr(obj, "__xmldefaultnamespace__"): | ||||
|         if obj != None and hasattr(obj, "__xmldefaultnamespace__"): | ||||
|             longPrefixNS = getattr(obj, "__xmldefaultnamespace__") | ||||
|             if longPrefixNS == defaultLongNS: | ||||
|                 newNS.prefix = '' | ||||
| @@ -705,13 +855,12 @@ class XMLMarshalWorker(object): | ||||
|                         if v == longPrefixNS: | ||||
|                             newNS.prefix = k + ':' | ||||
|                             break; | ||||
| ##                    print '[appendNSStack] found longPrefixNS in nameSpaces = "%s"' % (newNS.prefix) | ||||
|                 except: | ||||
|                     if (longPrefixNS in asDict(self.knownNamespaces)): | ||||
|                         newNS.prefix = self.knownNamespaces[longPrefixNS] + ':' | ||||
|                     else: | ||||
|                         raise MarshallerException('Error marshalling __xmldefaultnamespace__ ("%s") not defined in namespace stack' % (longPrefixNS)) | ||||
|         if hasattr(obj, "targetNamespace"): | ||||
|         if obj != None and hasattr(obj, "targetNamespace"): | ||||
|             newNS.targetNS = obj.targetNamespace | ||||
|         elif len(self.nsstack) > 0: | ||||
|             newNS.targetNS = self.nsstack[-1].targetNS | ||||
| @@ -749,9 +898,11 @@ class XMLMarshalWorker(object): | ||||
|              | ||||
|     def _marshal(self, obj, elementName=None, nameSpacePrefix="", indent=0): | ||||
|         if (obj != None): | ||||
|             xmlMarshallerLogger.debug("--> _marshal: elementName=%s%s, type=%s, obj=%s, indent=%d" % (nameSpacePrefix, elementName, type(obj), str(obj), indent)) | ||||
|             aglogging.debug(xmlMarshallerLogger, "--> _marshal: elementName=%s%s, type=%s, obj=%s, indent=%d", nameSpacePrefix, elementName, type(obj), str(obj), indent) | ||||
|         else: | ||||
|             xmlMarshallerLogger.debug("--> _marshal: elementName=%s%s, obj is None, indent=%d" % (nameSpacePrefix, elementName, indent)) | ||||
|             aglogging.debug(xmlMarshallerLogger, "--> _marshal: elementName=%s%s, obj is None, indent=%d", nameSpacePrefix, elementName, indent) | ||||
|         if ((obj != None) and (hasattr(obj, 'preMarshal'))): | ||||
|             obj.preMarshal() | ||||
|         excludeAttrs = [] | ||||
|         excludeAttrs.extend(self.xmldeepexclude) | ||||
|         if hasattr(obj, "__xmlexclude__"): | ||||
| @@ -768,8 +919,8 @@ class XMLMarshalWorker(object): | ||||
|             newline = "" | ||||
|             increment = 0 | ||||
|         ## Determine the XML element name. If it isn"t specified in the | ||||
|         ## parameter list, look for it in the __xmlname__ Lang | ||||
|         ## attribute, else use the default generic BASETYPE_ELEMENT_NAME. | ||||
|         ## parameter list, look for it in the __xmlname__ attribute, | ||||
|         ## else use the default generic BASETYPE_ELEMENT_NAME. | ||||
|         nameSpaceAttrs = self.appendNSStack(obj) | ||||
|         nameSpacePrefix = self.getNSPrefix()        | ||||
|         if not elementName: | ||||
| @@ -779,13 +930,15 @@ class XMLMarshalWorker(object): | ||||
|                 elementName = nameSpacePrefix + BASETYPE_ELEMENT_NAME | ||||
|         else: | ||||
|             elementName = nameSpacePrefix + elementName | ||||
| ##        print '[XMLMarshalWorker._marshal] elementName "%s"; nameSpaceAttrs is "%s"' % (elementName, nameSpaceAttrs) | ||||
|      | ||||
|         if (hasattr(obj, "__xmlsequencer__")) and (obj.__xmlsequencer__ != None): | ||||
|             if (XMLSCHEMA_XSD_URL in self.nsstack[-1].nameSpaces.values()): | ||||
|                 for kShort, vLong in self.nsstack[-1].nameSpaces.iteritems(): | ||||
|                     if vLong == XMLSCHEMA_XSD_URL: | ||||
|                         xsdPrefix = kShort + ':' | ||||
|                         if kShort != DEFAULT_NAMESPACE_KEY: | ||||
|                             xsdPrefix = kShort + ':' | ||||
|                         else: | ||||
|                             xsdPrefix = '' | ||||
|                         break | ||||
|             else: | ||||
|                 xsdPrefix = 'xs:' | ||||
| @@ -793,7 +946,6 @@ class XMLMarshalWorker(object): | ||||
|         else: | ||||
|             elementAdd = None | ||||
|                     | ||||
|     ##    print "marshal: entered with elementName: ", elementName | ||||
|         members_to_skip = [] | ||||
|         ## Add more members_to_skip based on ones the user has selected | ||||
|         ## via the __xmlexclude__ and __xmldeepexclude__ attributes. | ||||
| @@ -806,7 +958,6 @@ class XMLMarshalWorker(object): | ||||
|             xmlattributes = obj.__xmlattributes__ | ||||
|             members_to_skip.extend(xmlattributes) | ||||
|             for attr in xmlattributes: | ||||
| ##                print 'Processing element "%s"; attribute "%s"' % (elementName, attr) | ||||
|                 internalAttrName = attr | ||||
|                 ifDefPy() | ||||
|                 if (attr.startswith("__") and not attr.endswith("__")):  | ||||
| @@ -814,7 +965,6 @@ class XMLMarshalWorker(object): | ||||
|                 endIfDef() | ||||
|                 # Fail silently if a python attribute is specified to be | ||||
|                 # an XML attribute but is missing. | ||||
| ##            print "marshal:   processing attribute ", internalAttrName | ||||
|                 attrNameSpacePrefix = "" | ||||
|                 if hasattr(obj, "__xmlattrnamespaces__"): | ||||
|                     for nameSpaceKey, nameSpaceAttributes in getattr(obj, "__xmlattrnamespaces__").iteritems(): | ||||
| @@ -856,8 +1006,7 @@ class XMLMarshalWorker(object): | ||||
|                 else: | ||||
|                     value = objutils.toDiffableRepr(value) | ||||
|      | ||||
|                 objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, saxutils.escape(value)) | ||||
|     ##            print "marshal:   new objattrs is: ", objattrs | ||||
|                 objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, utillang.escape(value)) | ||||
|         if (obj == None): | ||||
|             xmlString = [""] | ||||
|         elif isinstance(obj, bool): | ||||
| @@ -873,9 +1022,18 @@ class XMLMarshalWorker(object): | ||||
|             objTypeStr = self._genObjTypeStr("float") | ||||
|             xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] | ||||
|         elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string | ||||
|             xmlString = ['%s<%s>%s</%s>%s' % (prefix, elementName, saxutils.escape(obj.encode()), elementName, newline)] | ||||
|             xmlString = ['%s<%s>%s</%s>%s' % (prefix, elementName, utillang.escape(obj.encode()), elementName, newline)] | ||||
|         elif isinstance(obj, basestring): | ||||
|             xmlString = ['%s<%s>%s</%s>%s' % (prefix, elementName, saxutils.escape(obj), elementName, newline)] | ||||
|             xmlString = ['%s<%s>%s</%s>%s' % (prefix, elementName, utillang.escape(obj), elementName, newline)] | ||||
|         elif isinstance(obj, datetime.datetime): | ||||
|             objTypeStr = self._genObjTypeStr("datetime") | ||||
|             xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] | ||||
|         elif isinstance(obj, datetime.date): | ||||
|             objTypeStr = self._genObjTypeStr("date") | ||||
|             xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] | ||||
|         elif isinstance(obj, datetime.time): | ||||
|             objTypeStr = self._genObjTypeStr("time") | ||||
|             xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] | ||||
|         elif isinstance(obj, list): | ||||
|             if len(obj) < 1: | ||||
|                 xmlString = "" | ||||
| @@ -910,13 +1068,15 @@ class XMLMarshalWorker(object): | ||||
|         elif hasattr(obj, "__xmlcontent__"): | ||||
|             contentValue = getattr(obj, obj.__xmlcontent__) | ||||
|             if contentValue == None:  | ||||
|                 contentValue = '' | ||||
|                 xmlString = ["%s<%s%s%s/>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, newline)]         | ||||
|             else: | ||||
|                 contentValue = saxutils.escape(contentValue) | ||||
|             xmlString = ["%s<%s%s%s>%s</%s>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, contentValue, elementName, newline)]         | ||||
|                 contentValue = utillang.escape(contentValue) | ||||
|                 xmlString = ["%s<%s%s%s>%s</%s>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, contentValue, elementName, newline)]         | ||||
|         else: | ||||
|             # Only add the objtype if the element tag is unknown to us. | ||||
|             if (self.isKnownType(elementName) == True):  | ||||
|             if (isinstance(obj, GenericXMLObject)): | ||||
|                 objTypeStr = "" | ||||
|             elif (self.isKnownType(elementName) == True): | ||||
|                 objTypeStr = "" | ||||
|             else: | ||||
|                 objTypeStr = self._genObjTypeStr("%s.%s" % (obj.__class__.__module__, className)) | ||||
| @@ -929,7 +1089,7 @@ class XMLMarshalWorker(object): | ||||
|             if hasattr(obj, "__xmlbody__"): | ||||
|                 xmlbody = getattr(obj, obj.__xmlbody__) | ||||
|                 if xmlbody != None: | ||||
|                     xmlMemberString.append(xmlbody)            | ||||
|                     xmlMemberString.append(utillang.escape(xmlbody)) | ||||
|             else: | ||||
|                 if hasattr(obj, "__xmlattrgroups__"): | ||||
|                     attrGroups = obj.__xmlattrgroups__.copy() | ||||
| @@ -975,21 +1135,17 @@ class XMLMarshalWorker(object): | ||||
|                             xmlname = None | ||||
|                             if (len(xmlnametuple) == 1): | ||||
|                                 xmlname = xmlnametuple[0] | ||||
|     ##                        ix = 0 | ||||
|                             if not isinstance(value, (list, tuple)): | ||||
|                               value = [value] | ||||
|                             for seqitem in value: | ||||
|     ##                            xmlname = xmlnametuple[ix] | ||||
|     ##                            ix += 1 | ||||
|     ##                            if (ix >= len(xmlnametuple)): | ||||
|     ##                                ix = 0 | ||||
|                                 xmlMemberString.extend(self._marshal(seqitem, xmlname, subElementNameSpacePrefix, indent=indent+increment)) | ||||
|                         else: | ||||
|                             if (hasattr(obj, "__xmlrename__") and name in asDict(obj.__xmlrename__)): | ||||
|                                 xmlname = obj.__xmlrename__[name] | ||||
|                             else: | ||||
|                                 xmlname = name | ||||
|                             xmlMemberString.extend(self._marshal(value, xmlname, subElementNameSpacePrefix, indent=indent+increment)) | ||||
|                             if (value != None): | ||||
|                                 xmlMemberString.extend(self._marshal(value, xmlname, subElementNameSpacePrefix, indent=indent+increment)) | ||||
|                     if (eName != "__nogroup__"): | ||||
|                         xmlMemberString.append("%s</%s>%s" % (prefix, eName, newline)) | ||||
|                         prefix = prefix[:-increment] | ||||
| @@ -1022,8 +1178,8 @@ class XMLMarshalWorker(object): | ||||
|                     xmlString.append("><![CDATA[%s]]></%s>%s" % (cdataContent, elementName, newline)) | ||||
|                 else: | ||||
|                     xmlString.append("/>%s" % newline) | ||||
|     ##        return xmlString | ||||
|         xmlMarshallerLogger.debug("<-- _marshal: %s" % str(xmlString)) | ||||
|         if aglogging.isEnabledForDebug(xmlMarshallerLogger): | ||||
|             aglogging.debug(xmlMarshallerLogger, "<-- _marshal: %s", objutils.toDiffableString(xmlString)) | ||||
|         #print "<-- _marshal: %s" % str(xmlString) | ||||
|         self.popNSStack() | ||||
|         return xmlString | ||||
|   | ||||
| @@ -22,35 +22,44 @@ import activegrid.util.aglogging as aglogging | ||||
|  | ||||
| xmlLogger = logging.getLogger("activegrid.util.xml") | ||||
|      | ||||
| def load(fileName, knownTypes=None, knownNamespaces=None): | ||||
| def load(fileName, knownTypes=None, knownNamespaces=None, createGenerics=False): | ||||
|     loadedObject = None | ||||
|     fileObject = file(fileName) | ||||
|     timeStart = time.time() | ||||
|     xml = "" | ||||
|     try: | ||||
|         xml = fileObject.read() | ||||
|         loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=fileName) | ||||
|         loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=fileName, createGenerics=createGenerics) | ||||
|         loadedObject.fileName = os.path.abspath(fileName) | ||||
|         if hasattr(loadedObject, 'initialize'): | ||||
|             loadedObject.initialize() | ||||
|     finally: | ||||
|         fileObject.close() | ||||
|         timeDone = time.time() | ||||
|         aglogging.info(xmlLogger, ('Load statistics for file %s: elapsed time = %f secs' % (fileName, timeDone-timeStart))) | ||||
|         if xmlLogger.isEnabledFor(aglogging.LEVEL_INFO): | ||||
|             timeDone = time.time() | ||||
|             aglogging.info(xmlLogger, ('Load statistics for file %s (%d bytes): elapsed time = %f secs' % (fileName, len(xml), timeDone-timeStart))) | ||||
|     return loadedObject | ||||
|  | ||||
| def loadURI(uri, knownTypes=None, knownNamespaces=None, xmlSource=None): | ||||
| def loadURI(uri, knownTypes=None, knownNamespaces=None, xmlSource=None, createGenerics=False): | ||||
|     loadedObject = None | ||||
|     xml = urllib.urlopen(uri).read() | ||||
|     loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource) | ||||
|     loadedObject.fileName = uri | ||||
|     if hasattr(loadedObject, 'initialize'): | ||||
|         loadedObject.initialize() | ||||
|     timeStart = time.time() | ||||
|     xml = "" | ||||
|     try: | ||||
|         xml = urllib.urlopen(uri).read() | ||||
|         loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource, createGenerics=createGenerics) | ||||
|         loadedObject.fileName = uri | ||||
|         if hasattr(loadedObject, 'initialize'): | ||||
|             loadedObject.initialize() | ||||
|     finally: | ||||
|         if xmlLogger.isEnabledFor(aglogging.LEVEL_INFO): | ||||
|             timeDone = time.time() | ||||
|             aglogging.info(xmlLogger, ('Load statistics for URI %s (%d bytes): elapsed time = %f secs' % (uri, len(xml), timeDone-timeStart))) | ||||
|     return loadedObject | ||||
|  | ||||
| def unmarshal(xml, knownTypes=None, knownNamespaces=None, xmlSource=None): | ||||
| def unmarshal(xml, knownTypes=None, knownNamespaces=None, xmlSource=None, createGenerics=False): | ||||
|     if (knownTypes == None):  | ||||
|         knownTypes, knownNamespaces = getAgKnownTypes() | ||||
|     return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource)     | ||||
|     return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource, createGenerics=createGenerics)     | ||||
|  | ||||
| def save(fileName, objectToSave, prettyPrint=True, marshalType=True, knownTypes=None, knownNamespaces=None, encoding='utf-8'): | ||||
|     if hasattr(objectToSave, '_xmlReadOnly') and objectToSave._xmlReadOnly == True: | ||||
| @@ -155,41 +164,6 @@ def getAgVersion(fileName): | ||||
|             version = xml[i+1:j] | ||||
|     return version | ||||
|  | ||||
| def escape(data): | ||||
|     """Escape ', ", &, <, and > in a string of data. | ||||
|  | ||||
|     Basically, everything that saxutils.escape does (and this calls that, at | ||||
|     least for now), but with " added as well. | ||||
|  | ||||
|     XXX TODO make this faster; saxutils.escape() is really slow | ||||
|     """ | ||||
|  | ||||
|     import xml.sax.saxutils as saxutils | ||||
|  | ||||
|     data=saxutils.escape(data) | ||||
|     data=data.replace("\"", """) | ||||
|  | ||||
|     # IE doesn't support ' | ||||
|     # data=data.replace("\'", "'") | ||||
|     data=data.replace("\'", "'") | ||||
|  | ||||
|     return data | ||||
|  | ||||
| def unescape(data): | ||||
|     """Unescape ', ", &, <, and > in a string of data. | ||||
|  | ||||
|     Basically, everything that saxutils.unescape does (and this calls that, at | ||||
|     least for now), but with " added as well. | ||||
|  | ||||
|     XXX TODO make this faster; saxutils.unescape() is really slow | ||||
|     """ | ||||
|  | ||||
|     import xml.sax.saxutils as saxutils | ||||
|  | ||||
|     data=data.replace(""", "\"") | ||||
|     data=data.replace("'", "\'") | ||||
|     return saxutils.unescape(data) | ||||
|  | ||||
|      | ||||
| AG_NS_URL = "http://www.activegrid.com/ag.xsd" | ||||
| BPEL_NS_URL = "http://schemas.xmlsoap.org/ws/2003/03/business-process" | ||||
| @@ -197,7 +171,9 @@ HTTP_WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/http/" | ||||
| MIME_WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/mime/" | ||||
| SOAP_NS_URL = "http://schemas.xmlsoap.org/wsdl/soap/" | ||||
| SOAP12_NS_URL = "http://schemas.xmlsoap.org/wsdl/soap12/" | ||||
| SOAP_NS_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/" | ||||
| WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/" | ||||
| WSSE_NS_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" | ||||
| XFORMS_NS_URL = "http://www.w3c.org/xform.xsd" | ||||
| XMLSCHEMA_NS_URL = "http://www.w3.org/2001/XMLSchema" | ||||
| XSI_NS_URL = "http://www.w3.org/2001/XMLSchema-instance" | ||||
| @@ -209,7 +185,8 @@ KNOWN_NAMESPACES = { AG_NS_URL          :  "ag", | ||||
|                      MIME_WSDL_NS_URL   :  "mime", | ||||
|                      SOAP_NS_URL        :  "soap", | ||||
|                      SOAP12_NS_URL      :  "soap12", | ||||
|                      WSDL_NS_URL        :  "wsdl",  | ||||
|                      WSDL_NS_URL        :  "wsdl", | ||||
|                      WSSE_NS_URL        :  "wsse",  | ||||
|                      XFORMS_NS_URL      :  "xforms",                              | ||||
|                      XMLSCHEMA_NS_URL   :  "xs", | ||||
|                      XACML_NS_URL       :  "xacml", | ||||
| @@ -226,19 +203,23 @@ def getAgXsdToClassName(): | ||||
|             "ag:body"            : "activegrid.model.processmodel.Body", | ||||
|             "ag:category_substitutions"    : "activegrid.server.layoutrenderer.CategorySubstitutions", | ||||
|             "ag:command"         : "activegrid.model.wsdl.Command", | ||||
|             "ag:setElement"      : "activegrid.model.processmodel.SetElementOperation", | ||||
|             "ag:css"             : "activegrid.server.layoutrenderer.CSS",  | ||||
|             "ag:cssRule"         : "activegrid.model.processmodel.CssRule", | ||||
|             "ag:databaseService" : "activegrid.server.deployment.DatabaseService", | ||||
|             "ag:datasource"      : "activegrid.data.dataservice.DataSource", | ||||
|             "ag:dataObjectList"  : "activegrid.data.datalang.DataObjectList", | ||||
|             "ag:debug"           : "activegrid.model.processmodel.DebugOperation", | ||||
|             "ag:deployment"      : "activegrid.server.deployment.Deployment", | ||||
|             "ag:formData"        : "activegrid.model.processmodel.FormData", | ||||
|             "ag:formVar"         : "activegrid.model.processmodel.FormVar", | ||||
|             "ag:generator"       : "activegrid.server.layoutrenderer.SerializableGenerator",  | ||||
|             "ag:head"            : "activegrid.server.layoutrenderer.Head",  | ||||
|             "ag:hr"              : "activegrid.model.processmodel.HorizontalRow", | ||||
|             "ag:identity"        : "activegrid.model.identitymodel.Identity", | ||||
|             "ag:identityref"     : "activegrid.server.deployment.IdentityRef", | ||||
|             "ag:image"           : "activegrid.model.processmodel.Image", | ||||
|             "ag:inputPart"       : "activegrid.model.processmodel.InputPart", | ||||
|             "ag:keystore"        : "activegrid.model.identitymodel.KeyStore", | ||||
|             "ag:label"           : "activegrid.model.processmodel.Label", | ||||
|             "ag:layout"          : "activegrid.server.layoutrenderer.Layout",  | ||||
|             "ag:layouts"         : "activegrid.server.layoutrenderer.Layouts",  | ||||
| @@ -246,9 +227,11 @@ def getAgXsdToClassName(): | ||||
|             "ag:localService"    : "activegrid.server.deployment.LocalService", | ||||
|             "ag:parameter"       : "activegrid.server.layoutrenderer.Parameter", | ||||
|             "ag:parameters"      : "activegrid.server.layoutrenderer.Parameters", | ||||
|             "ag:postInitialize"  : "activegrid.model.processmodel.PostInitialize", | ||||
|             "ag:processref"      : "activegrid.server.deployment.ProcessRef", | ||||
|             "ag:query"           : "activegrid.model.processmodel.Query", | ||||
|             "ag:soapService"     : "activegrid.server.deployment.SoapService", | ||||
|             "ag:redirect"        : "activegrid.server.layoutrenderer.Redirect",  | ||||
|             "ag:requiredFile"    : "activegrid.server.layoutrenderer.RequiredFile",  | ||||
|             "ag:resource"        : "activegrid.model.identitymodel.IDResource", | ||||
|             "ag:restService"     : "activegrid.server.deployment.RestService", | ||||
| @@ -355,27 +338,38 @@ def getAgXsdToClassName(): | ||||
|             "xforms:xforms"      : "activegrid.model.processmodel.XFormsRoot", | ||||
|             "xs:all"             : "activegrid.model.schema.XsdSequence", | ||||
|             "xs:any"             : "activegrid.model.schema.XsdAny", | ||||
|             "xs:anyAttribute"    : "activegrid.model.schema.XsdAnyAttribute", | ||||
|             "xs:attribute"       : "activegrid.model.schema.XsdAttribute", | ||||
|             "xs:choice"          : "activegrid.model.schema.XsdChoice", | ||||
|             "xs:complexContent"  : "activegrid.model.schema.XsdComplexContent", | ||||
|             "xs:complexType"     : "activegrid.model.schema.XsdComplexType", | ||||
|             "xs:documentation"   : "activegrid.model.schema.XsdDocumentation", | ||||
|             "xs:element"         : "activegrid.model.schema.XsdElement", | ||||
|             "xs:enumeration"     : "activegrid.model.schema.XsdEnumeration", | ||||
|             "xs:enumeration"     : "activegrid.model.schema.XsdFacetEnumeration", | ||||
|             "xs:extension"       : "activegrid.model.schema.XsdExtension", | ||||
|             "xs:fractionDigits"  : "activegrid.model.schema.XsdFacetFractionDigits", | ||||
|             "xs:field"           : "activegrid.model.schema.XsdKeyField", | ||||
|             "xs:import"          : "activegrid.model.schema.XsdInclude", | ||||
|             "xs:include"         : "activegrid.model.schema.XsdInclude", | ||||
|             "xs:key"             : "activegrid.model.schema.XsdKey", | ||||
|             "xs:keyref"          : "activegrid.model.schema.XsdKeyRef", | ||||
|             "xs:length"          : "activegrid.model.schema.XsdLength", | ||||
|             "xs:length"          : "activegrid.model.schema.XsdFacetLength", | ||||
|             "xs:list"            : "activegrid.model.schema.XsdList", | ||||
|             "xs:maxLength"       : "activegrid.model.schema.XsdMaxLength", | ||||
|             "xs:maxExclusive"    : "activegrid.model.schema.XsdFacetMaxExclusive", | ||||
|             "xs:maxInclusive"    : "activegrid.model.schema.XsdFacetMaxInclusive", | ||||
|             "xs:maxLength"       : "activegrid.model.schema.XsdFacetMaxLength", | ||||
|             "xs:minExclusive"    : "activegrid.model.schema.XsdFacetMinExclusive", | ||||
|             "xs:minInclusive"    : "activegrid.model.schema.XsdFacetMinInclusive", | ||||
|             "xs:minLength"       : "activegrid.model.schema.XsdFacetMinLength", | ||||
|             "xs:pattern"         : "activegrid.model.schema.XsdFacetPattern", | ||||
|             "xs:restriction"     : "activegrid.model.schema.XsdRestriction", | ||||
|             "xs:schema"          : "activegrid.model.schema.Schema", | ||||
|             "xs:selector"        : "activegrid.model.schema.XsdKeySelector",               | ||||
|             "xs:sequence"        : "activegrid.model.schema.XsdSequence", | ||||
|             "xs:simpleContent"   : "activegrid.model.schema.XsdSimpleContent", | ||||
|             "xs:simpleType"      : "activegrid.model.schema.XsdSimpleType", | ||||
|             "xs:totalDigits"     : "activegrid.model.schema.XsdTotalDigits", | ||||
|             "xs:totalDigits"     : "activegrid.model.schema.XsdFacetTotalDigits", | ||||
|             "xs:whiteSpace"      : "activegrid.model.schema.XsdFacetWhiteSpace", | ||||
|         } | ||||
|     return agXsdToClassName | ||||
|      | ||||
|   | ||||
| @@ -121,6 +121,7 @@ class FindService(wx.lib.pydocview.DocService): | ||||
|                 self._findDialog = None | ||||
|  | ||||
|             self._replaceDialog = FindReplaceDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Replace"), size=(320,200), findString=findString) | ||||
|             self._replaceDialog.CenterOnParent() | ||||
|             self._replaceDialog.Show(True) | ||||
|         else: | ||||
|             if self._replaceDialog != None: | ||||
| @@ -129,6 +130,7 @@ class FindService(wx.lib.pydocview.DocService): | ||||
|                 self._replaceDialog = None | ||||
|  | ||||
|             self._findDialog = FindDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Find"), size=(320,200), findString=findString) | ||||
|             self._findDialog.CenterOnParent() | ||||
|             self._findDialog.Show(True) | ||||
|  | ||||
|  | ||||
| @@ -152,6 +154,7 @@ class FindService(wx.lib.pydocview.DocService): | ||||
|         """ Display Goto Line Number dialog box """ | ||||
|         line = -1 | ||||
|         dialog = wx.TextEntryDialog(parent, _("Enter line number to go to:"), _("Go to Line")) | ||||
|         dialog.CenterOnParent() | ||||
|         if dialog.ShowModal() == wx.ID_OK: | ||||
|             try: | ||||
|                 line = int(dialog.GetValue()) | ||||
| @@ -356,7 +359,10 @@ class FindDialog(wx.Dialog): | ||||
|         wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent) | ||||
|         cancelBtn = wx.Button(self, wx.ID_CANCEL) | ||||
|         wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose) | ||||
|         buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) | ||||
|         BTM_SPACE = HALF_SPACE | ||||
|         if wx.Platform == "__WXMAC__": | ||||
|             BTM_SPACE = SPACE | ||||
|         buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) | ||||
|         buttonSizer.Add(cancelBtn, 0) | ||||
|         gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1)) | ||||
|  | ||||
| @@ -455,9 +461,14 @@ class FindReplaceDialog(FindDialog): | ||||
|         wx.EVT_BUTTON(self, FindService.REPLACEONE_ID, self.OnActionEvent) | ||||
|         replaceAllBtn = wx.Button(self, FindService.REPLACEALL_ID, _("Replace All")) | ||||
|         wx.EVT_BUTTON(self, FindService.REPLACEALL_ID, self.OnActionEvent) | ||||
|         buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) | ||||
|         buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, HALF_SPACE) | ||||
|         buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, HALF_SPACE) | ||||
|          | ||||
|         BTM_SPACE = HALF_SPACE | ||||
|         if wx.Platform == "__WXMAC__": | ||||
|             BTM_SPACE = SPACE | ||||
|              | ||||
|         buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) | ||||
|         buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, BTM_SPACE) | ||||
|         buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, BTM_SPACE) | ||||
|         buttonSizer.Add(cancelBtn, 0) | ||||
|         gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1)) | ||||
|  | ||||
| @@ -495,12 +506,24 @@ def getFindData(): | ||||
|     return \ | ||||
| '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ | ||||
| \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ | ||||
| \x00\x00\x81IDAT8\x8d\xa5S\xc1\x16\xc0\x10\x0ckk\xff\xff\xc7d\x87\xad^U\r\ | ||||
| \x93S\xe5U$\n\xb3$:\xc1e\x17(\x19Z\xb3$\x9e\xf1DD\xe2\x15\x01x\xea\x93\xef\ | ||||
| \x04\x989\xea\x1b\xf2U\xc0\xda\xb4\xeb\x11\x1f:\xd8\xb5\xff8\x93\xd4\xa9\xae\ | ||||
| @/S\xaaUwJ3\x85\xc0\x81\xee\xeb.q\x17C\x81\xd5XU \x1a\x93\xc6\x18\x8d\x90\ | ||||
| \xe8}\x89\x00\x9a&\x9b_k\x94\x0c\xdf\xd78\xf8\x0b\x99Y\xb4\x08c\x9e\xfe\xc6\ | ||||
| \xe3\x087\xf9\xd0D\x180\xf1#\x8e\x00\x00\x00\x00IEND\xaeB`\x82'  | ||||
| \x00\x01\xb1IDAT8\x8d\xa5\x93=o\xd3P\x14\x86\x1f\xa7\x11\x95<\xdc\xc6\xecN+5\ | ||||
| [\x86B\x99\xacLQ2Zr[\x89\xa1\xfd\x0b%\x95\x90\x00\xf1\x03\x80\x01\x98\x80\ | ||||
| \x19G\xac\x0cm\xff@Y\xd9:\xd9Ck\x94\xd6\xddb\x94\x9b\x98\xc8\xd2e1C\xe5\x8b\ | ||||
| \xdd\x14\x96\xbe\xdb=\x1f\xefy\xef\xf90\x8c\xda\x12wA\xbd\xfc\x18\xfa\x9fs\ | ||||
| \x80\xf9|\x0e\xc0\x93\xc1\x81\x01\xf0\xe6\xf5\xab\x1c`:\x9d\x02\xf0\xf6\xdd{\ | ||||
| \xa3\xc8\xa9\xddd\xec\xf5z\xb4Z\xeb\x00\x1c\x1f\x1d\xe6\x85\xdd\xf3<\x06\x83\ | ||||
| \xc1\x82\xbd\xa2 \x0cCL\xd3d<\x1e\x13\xc71\xb6m\x030\x1a\x8d\x08\x82\x00\x80\ | ||||
| \xb3\xb3s:\x9d\x8e\xce\xa9(h6\x9b8\x8e\x83m\xdb4\x1a\r\x82 \xe0\xc5\xf3g\xb9\ | ||||
| eY\xb4\xdbm\x1c\xc7Y\xe8\x81&\xf8\xf4\xf1C\xde\xedv+\xce\x97Owx\xfc\xe8k\xc5\ | ||||
| \xb6\xb7\xb7\x8b\xef\x0foW \x84\xe0\xea\xea\x02\xa5\x94n\x18\x80\x94\x92\xd9\ | ||||
| l\x02@\x96e\x95>\xd4nVO\xd3\xb9\x0e\xba\r\xa6i\xd2\xef\xf7\xf0\xfd!\xc7G\x87\ | ||||
| y\xed:)\xd5\x01J\xfd\xd6c\xfc~\x9a\xfc\x93\xe8\xf2\xf2\x02(Ma6\x9b \x84@)\ | ||||
| \xa5\t}\xff\x0b\xd0\'I~R\x14\xca\xb2L\xfb\x97\x97\xef-\xeeA!_J\x89\xeb\xba\ | ||||
| \xb8\xae\xab\xbf\x06\x7f\x97\xacP[\x87\xeb9\x0b!H\x92\ta\x18"\xa5\xd4U\xbd\ | ||||
| \xadm\xe3\xe1\x83\x8d<\x8a~\x90\xa6\xbf\x88\xe3\x18)\xa5&\xa9\x03X\x96E\xab\ | ||||
| \xb5\x8em7\xf5\xc2\x94\xb1\xba\xba\xc6\xe6\xe6\x06++\xf7\x89\xa2\xa8\xe2\xd3\ | ||||
| =89\xf9Va.\x14\x14\xd8\xdf?X VJa\x14\xd7X\xde\xef2\xbc\xadm\xe3\x7f~\xe3\xae\ | ||||
| \xe7\xfc\x07\x84;\xc5\x82\xa1m&\x95\x00\x00\x00\x00IEND\xaeB`\x82'  | ||||
|  | ||||
|  | ||||
| def getFindBitmap(): | ||||
|   | ||||
| @@ -17,45 +17,45 @@ import FindService | ||||
| _ = wx.GetTranslation | ||||
|  | ||||
| class TextDocument(wx.lib.docview.Document): | ||||
|      | ||||
|     def __init__(self): | ||||
|         wx.lib.docview.Document .__init__(self) | ||||
|         self._inModify = False | ||||
|  | ||||
|  | ||||
|     def OnSaveDocument(self, filename): | ||||
|     def SaveObject(self, fileObject): | ||||
|         view = self.GetFirstView() | ||||
|         if not view.GetTextCtrl().SaveFile(filename): | ||||
|             return False | ||||
|         self.Modify(False) | ||||
|         self.SetDocumentSaved(True) | ||||
|         #if wx.Platform == "__WXMAC__": | ||||
|         #    fn = wx.Filename(filename) | ||||
|         #    fn.MacSetDefaultTypeAndCreator() | ||||
|         fileObject.write(view.GetTextCtrl().GetValue()) | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def OnOpenDocument(self, filename): | ||||
|     def LoadObject(self, fileObject): | ||||
|         view = self.GetFirstView() | ||||
|         if not view.GetTextCtrl().LoadFile(filename): | ||||
|             return False | ||||
|         self.SetFilename(filename, True) | ||||
|         self.Modify(False) | ||||
|         self.UpdateAllViews() | ||||
|         self._savedYet = True | ||||
|         data = fileObject.read() | ||||
|         view.GetTextCtrl().SetValue(data) | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def IsModified(self): | ||||
|         view = self.GetFirstView() | ||||
|         if view and view.GetTextCtrl(): | ||||
|             return wx.lib.docview.Document.IsModified(self) or view.GetTextCtrl().IsModified() | ||||
|         else: | ||||
|             return wx.lib.docview.Document.IsModified(self) | ||||
|             return view.GetTextCtrl().IsModified() | ||||
|         return False | ||||
|  | ||||
|  | ||||
|     def Modify(self, mod): | ||||
|     def Modify(self, modify): | ||||
|         if self._inModify: | ||||
|             return | ||||
|         self._inModify = True | ||||
|          | ||||
|         view = self.GetFirstView() | ||||
|         wx.lib.docview.Document.Modify(self, mod) | ||||
|         if not mod and view and view.GetTextCtrl(): | ||||
|         if not modify and view and view.GetTextCtrl(): | ||||
|             view.GetTextCtrl().DiscardEdits() | ||||
|  | ||||
|         wx.lib.docview.Document.Modify(self, modify)  # this must called be after the DiscardEdits call above. | ||||
|  | ||||
|         self._inModify = False | ||||
|  | ||||
|  | ||||
| class TextView(wx.lib.docview.View): | ||||
|  | ||||
| @@ -75,6 +75,7 @@ class TextView(wx.lib.docview.View): | ||||
|         sizer = wx.BoxSizer() | ||||
|         font, color = self._GetFontAndColorFromConfig() | ||||
|         self._textCtrl = self._BuildTextCtrl(frame, font, color = color) | ||||
|         self._textCtrl.Bind(wx.EVT_TEXT, self.OnModify) | ||||
|         sizer.Add(self._textCtrl, 1, wx.EXPAND, 0) | ||||
|         frame.SetSizer(sizer) | ||||
|         frame.Layout() | ||||
| @@ -83,6 +84,10 @@ class TextView(wx.lib.docview.View): | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def OnModify(self, event): | ||||
|         self.GetDocument().Modify(True) | ||||
|  | ||||
|  | ||||
|     def _BuildTextCtrl(self, parent, font, color = wx.BLACK, value = "", selection = [0, 0]): | ||||
|         if self._wordWrap: | ||||
|             wordWrapStyle = wx.TE_WORDWRAP | ||||
| @@ -131,6 +136,9 @@ class TextView(wx.lib.docview.View): | ||||
|  | ||||
|  | ||||
|     def OnUpdate(self, sender = None, hint = None): | ||||
|         if wx.lib.docview.View.OnUpdate(self, sender, hint): | ||||
|             return | ||||
|  | ||||
|         if hint == "Word Wrap": | ||||
|             self.SetWordWrap(wx.ConfigBase_Get().ReadInt("TextEditorWordWrap", True)) | ||||
|         elif hint == "Font": | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| # | ||||
| # Created:      5/15/03 | ||||
| # CVS-ID:       $Id$ | ||||
| # Copyright:    (c) 2003-2005 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al) | ||||
| # Copyright:    (c) 2003-2006 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al) | ||||
| # License:      wxWindows license | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| @@ -214,8 +214,10 @@ class Document(wx.EvtHandler): | ||||
|         false otherwise. You may need to override this if your document view | ||||
|         maintains its own record of being modified (for example if using | ||||
|         xTextWindow to view and edit the document). | ||||
|         This method has been extended to notify its views that the dirty flag has changed. | ||||
|         """ | ||||
|         self._documentModified = modify | ||||
|         self.UpdateAllViews(hint=("modify", self, self._documentModified)) | ||||
|  | ||||
|  | ||||
|     def SetDocumentModificationDate(self): | ||||
| @@ -236,6 +238,16 @@ class Document(wx.EvtHandler): | ||||
|         return self._documentModificationDate | ||||
|  | ||||
|  | ||||
|     def IsDocumentModificationDateCorrect(self): | ||||
|         """ | ||||
|         Returns False if the file has been modified outside of the application. | ||||
|         This method has been added to wxPython and is not in wxWindows. | ||||
|         """ | ||||
|         if not os.path.exists(self.GetFilename()):  # document must be in memory only and can't be out of date | ||||
|             return True | ||||
|         return self._documentModificationDate == os.path.getmtime(self.GetFilename()) | ||||
|  | ||||
|  | ||||
|     def GetViews(self): | ||||
|         """ | ||||
|         Returns the list whose elements are the views on the document. | ||||
| @@ -271,6 +283,7 @@ class Document(wx.EvtHandler): | ||||
|         Destructor. Removes itself from the document manager. | ||||
|         """ | ||||
|         self.DeleteContents() | ||||
|         self._documentModificationDate = None | ||||
|         if self.GetDocumentManager(): | ||||
|             self.GetDocumentManager().RemoveDocument(self) | ||||
|         wx.EvtHandler.Destroy(self) | ||||
| @@ -364,7 +377,7 @@ class Document(wx.EvtHandler): | ||||
|             return True | ||||
|  | ||||
|         """ check for file modification outside of application """ | ||||
|         if os.path.exists(self.GetFilename()) and os.path.getmtime(self.GetFilename()) != self.GetDocumentModificationDate(): | ||||
|         if not self.IsDocumentModificationDateCorrect(): | ||||
|             msgTitle = wx.GetApp().GetAppName() | ||||
|             if not msgTitle: | ||||
|                 msgTitle = _("Application") | ||||
| @@ -485,9 +498,9 @@ class Document(wx.EvtHandler): | ||||
|                           self.GetDocumentWindow()) | ||||
|             return False | ||||
|  | ||||
|         self.SetDocumentModificationDate() | ||||
|         self.SetFilename(filename, True) | ||||
|         self.Modify(False) | ||||
|         self.SetDocumentModificationDate() | ||||
|         self.SetDocumentSaved(True) | ||||
|         #if wx.Platform == '__WXMAC__':  # Not yet implemented in wxPython | ||||
|         #    wx.FileName(file).MacSetDefaultTypeAndCreator() | ||||
| @@ -529,9 +542,9 @@ class Document(wx.EvtHandler): | ||||
|                           self.GetDocumentWindow()) | ||||
|             return False | ||||
|  | ||||
|         self.SetDocumentModificationDate() | ||||
|         self.SetFilename(filename, True) | ||||
|         self.Modify(False) | ||||
|         self.SetDocumentModificationDate() | ||||
|         self.SetDocumentSaved(True) | ||||
|         self.UpdateAllViews() | ||||
|         return True | ||||
| @@ -614,7 +627,7 @@ class Document(wx.EvtHandler): | ||||
|             return True | ||||
|  | ||||
|         """ check for file modification outside of application """ | ||||
|         if os.path.exists(self.GetFilename()) and os.path.getmtime(self.GetFilename()) != self.GetDocumentModificationDate(): | ||||
|         if not self.IsDocumentModificationDateCorrect(): | ||||
|             msgTitle = wx.GetApp().GetAppName() | ||||
|             if not msgTitle: | ||||
|                 msgTitle = _("Warning") | ||||
| @@ -844,8 +857,14 @@ class View(wx.EvtHandler): | ||||
|         unused but may in future contain application-specific information for | ||||
|         making updating more efficient. | ||||
|         """ | ||||
|         pass | ||||
|  | ||||
|         if hint: | ||||
|             if hint[0] == "modify":  # if dirty flag changed, update the view's displayed title | ||||
|                 frame = self.GetFrame() | ||||
|                 if frame and hasattr(frame, "OnTitleIsModified"): | ||||
|                     frame.OnTitleIsModified() | ||||
|                     return True | ||||
|         return False | ||||
|          | ||||
|  | ||||
|     def OnChangeFilename(self): | ||||
|         """ | ||||
| @@ -916,11 +935,11 @@ class View(wx.EvtHandler): | ||||
|         Call this from your view frame's OnActivate member to tell the | ||||
|         framework which view is currently active. If your windowing system | ||||
|         doesn't call OnActivate, you may need to call this function from | ||||
|         any place where you know the view must be active, and | ||||
|         OnMenuCommand or any place where you know the view must be active, and | ||||
|         the framework will need to get the current view. | ||||
|  | ||||
|         The prepackaged view frame wxDocChildFrame calls wxView.Activate from | ||||
|         its OnActivate member. | ||||
|         its OnActivate member and from its OnMenuCommand member. | ||||
|         """ | ||||
|         if self.GetDocument() and self.GetDocumentManager(): | ||||
|             self.OnActivateView(activate, self, self.GetDocumentManager().GetCurrentView()) | ||||
| @@ -1865,7 +1884,7 @@ class DocManager(wx.EvtHandler): | ||||
|             for document in self._docs: | ||||
|                 if document.GetFilename() and os.path.normcase(document.GetFilename()) == os.path.normcase(path): | ||||
|                     """ check for file modification outside of application """ | ||||
|                     if os.path.exists(path) and os.path.getmtime(path) != document.GetDocumentModificationDate(): | ||||
|                     if not document.IsDocumentModificationDateCorrect(): | ||||
|                         msgTitle = wx.GetApp().GetAppName() | ||||
|                         if not msgTitle: | ||||
|                             msgTitle = _("Warning") | ||||
| @@ -2148,7 +2167,7 @@ class DocManager(wx.EvtHandler): | ||||
|                     if len(descr) > 0: | ||||
|                         descr = descr + _('|') | ||||
|                     descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter()  # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk | ||||
|             descr = _("All (*.*)|*.*|%s") % descr  # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk | ||||
|             descr = _("All|*.*|%s") % descr  # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk | ||||
|         else: | ||||
|             descr = _("*.*") | ||||
|  | ||||
| @@ -2791,6 +2810,7 @@ class DocMDIChildFrame(wx.MDIChildFrame): | ||||
|             self._childView.Activate(event.GetActive()) | ||||
|         self._activated = 0 | ||||
|  | ||||
|  | ||||
|     def OnCloseWindow(self, event): | ||||
|         """ | ||||
|         Closes and deletes the current view and document. | ||||
| @@ -2846,6 +2866,28 @@ class DocMDIChildFrame(wx.MDIChildFrame): | ||||
|         self._childView = view | ||||
|  | ||||
|  | ||||
|     def OnTitleIsModified(self): | ||||
|         """ | ||||
|         Add/remove to the frame's title an indication that the document is dirty. | ||||
|         If the document is dirty, an '*' is appended to the title | ||||
|         This method has been added to wxPython and is not in wxWindows. | ||||
|         """ | ||||
|         title = self.GetTitle() | ||||
|         if title: | ||||
|             if self.GetDocument().IsModified(): | ||||
|                 if title.endswith("*"): | ||||
|                     return | ||||
|                 else: | ||||
|                     title = title + "*" | ||||
|                     self.SetTitle(title) | ||||
|             else: | ||||
|                 if title.endswith("*"): | ||||
|                     title = title[:-1] | ||||
|                     self.SetTitle(title)                 | ||||
|                 else: | ||||
|                     return | ||||
|  | ||||
|  | ||||
| class DocPrintout(wx.Printout): | ||||
|     """ | ||||
|     DocPrintout is a default Printout that prints the first page of a document | ||||
| @@ -2892,15 +2934,6 @@ class DocPrintout(wx.Printout): | ||||
|         return pageNum == 1 | ||||
|  | ||||
|  | ||||
|     def OnBeginDocument(self, startPage, endPage): | ||||
|         """ | ||||
|         Not quite sure why this was overridden, but it was in wxWindows! :) | ||||
|         """ | ||||
|         if not wx.Printout.OnBeginDocument(self, startPage, endPage): | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|  | ||||
|     def GetPageInfo(self): | ||||
|         """ | ||||
|         Indicates that the DocPrintout only has a single page. | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user