1 #----------------------------------------------------------------------------
2 # Name: PythonEditor.py
3 # Purpose: PythonEditor for wx.lib.pydocview tbat uses the Styled Text Control
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
16 import wx
.lib
.pydocview
18 import keyword
# So it knows what to hilite
19 import wx
.py
# For the Python interpreter
20 import wx
.stc
# For the Python interpreter
21 import cStringIO
# For indent
24 import keyword
# for GetAutoCompleteKeywordList
25 import sys
# for GetAutoCompleteKeywordList
26 import MessageService
# for OnCheckCode
28 import FindInDirService
29 from UICommon
import CaseInsensitiveCompare
31 import checker
# for pychecker
32 _CHECKER_INSTALLED
= True
34 _CHECKER_INSTALLED
= False
35 import os
.path
# for pychecker
38 if wx
.Platform
== '__WXMSW__':
44 VIEW_PYTHON_INTERPRETER_ID
= wx
.NewId()
47 class PythonDocument(CodeEditor
.CodeDocument
):
51 class PythonView(CodeEditor
.CodeView
):
54 def GetCtrlClass(self
):
55 """ Used in split window to instantiate new instances """
59 def ProcessUpdateUIEvent(self
, event
):
60 if not self
.GetCtrl():
64 if id == CodeEditor
.CHECK_CODE_ID
:
65 hasText
= self
.GetCtrl().GetTextLength() > 0
69 return CodeEditor
.CodeView
.ProcessUpdateUIEvent(self
, event
)
72 def OnActivateView(self
, activate
, activeView
, deactiveView
):
73 STCTextEditor
.TextView
.OnActivateView(self
, activate
, activeView
, deactiveView
)
74 if activate
and self
.GetCtrl():
75 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
78 wx
.CallAfter(self
.LoadOutline
) # need CallAfter because document isn't loaded yet
81 def OnClose(self
, deleteWindow
= True):
82 status
= STCTextEditor
.TextView
.OnClose(self
, deleteWindow
)
83 wx
.CallAfter(self
.ClearOutline
) # need CallAfter because when closing the document, it is Activated and then Close, so need to match OnActivateView's CallAfter
87 def GetAutoCompleteKeywordList(self
, context
, hint
):
90 if context
and len(context
):
91 obj
= eval(context
, globals(), locals())
93 if not hint
or len(hint
) == 0: # context isn't valid, maybe it was the hint
97 kw
= keyword
.kwlist
[:]
100 kw
= filter(lambda item
: item
[0] != '_', symTbl
) # remove local variables and methods
102 if hint
and len(hint
):
103 lowerHint
= hint
.lower()
104 filterkw
= filter(lambda item
: item
.lower().startswith(lowerHint
), kw
) # remove variables and methods that don't match hint
107 kw
.sort(CaseInsensitiveCompare
)
110 replaceLen
= len(hint
)
114 return " ".join(kw
), replaceLen
117 def OnCheckCode(self
):
118 if not _CHECKER_INSTALLED
:
119 wx
.MessageBox(_("pychecker not found. Please install pychecker."), _("Check Code"))
122 filename
= os
.path
.basename(self
.GetDocument().GetFilename())
124 # pychecker only works on files, doesn't take a stream or string input
125 if self
.GetDocument().IsModified():
126 dlg
= wx
.MessageDialog(self
.GetFrame(), _("'%s' has been modfied and must be saved first. Save file and check code?") % filename
, _("Check Code"))
128 val
= dlg
.ShowModal()
131 self
.GetDocument().Save()
135 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
136 messageService
.ShowWindow()
137 view
= messageService
.GetView()
142 view
.SetCallback(self
.OnJumpToFoundLine
)
144 # Set cursor to Wait cursor
145 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
148 # This takes a while for involved code
149 checker
.checkSyntax(self
.GetDocument().GetFilename(), view
)
152 # Set cursor to Default cursor
153 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
156 def OnJumpToFoundLine(self
, event
):
157 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
158 lineText
, pos
= messageService
.GetView().GetCurrLine()
160 lineEnd
= lineText
.find(".py:")
164 lineStart
= lineEnd
+ len(".py:")
165 lineEnd
= lineText
.find(":", lineStart
)
166 lineNum
= int(lineText
[lineStart
:lineEnd
])
168 filename
= lineText
[0:lineStart
- 1]
171 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
172 for openDoc
in openDocs
:
173 if openDoc
.GetFilename() == filename
:
174 foundView
= openDoc
.GetFirstView()
178 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(filename
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
)
179 foundView
= doc
.GetFirstView()
182 foundView
.GetFrame().SetFocus()
184 foundView
.GotoLine(lineNum
)
185 startPos
= foundView
.PositionFromLine(lineNum
)
186 endPos
= foundView
.GetLineEndPosition(lineNum
)
187 # wxBug: Need to select in reverse order, (end, start) to put cursor at head of line so positioning is correct
188 # Also, if we use the correct positioning order (start, end), somehow, when we open a edit window for the first
189 # time, we don't see the selection, it is scrolled off screen
190 foundView
.SetSelection(endPos
, startPos
)
191 wx
.GetApp().GetService(OutlineService
.OutlineService
).LoadOutline(foundView
, position
=startPos
)
195 class PythonInterpreterView(wx
.lib
.docview
.View
):
198 def OnCreate(self
, doc
, flags
):
199 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
)
200 sizer
= wx
.BoxSizer()
201 self
._pyCrust
= wx
.py
.crust
.Crust(frame
)
202 sizer
.Add(self
._pyCrust
, 1, wx
.EXPAND
, 0)
203 frame
.SetSizer(sizer
)
210 def ProcessEvent(self
, event
):
211 if not hasattr(self
, "_pyCrust") or not self
._pyCrust
:
212 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
213 stcControl
= wx
.Window_FindFocus()
214 if not isinstance(stcControl
, wx
.stc
.StyledTextCtrl
):
215 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
220 elif id == wx
.ID_REDO
:
223 elif id == wx
.ID_CUT
:
226 elif id == wx
.ID_COPY
:
229 elif id == wx
.ID_PASTE
:
232 elif id == wx
.ID_CLEAR
:
235 elif id == wx
.ID_SELECTALL
:
236 stcControl
.SetSelection(0, -1)
239 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
242 def ProcessUpdateUIEvent(self
, event
):
243 if not hasattr(self
, "_pyCrust") or not self
._pyCrust
:
244 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
245 stcControl
= wx
.Window_FindFocus()
246 if not isinstance(stcControl
, wx
.stc
.StyledTextCtrl
):
247 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
250 event
.Enable(stcControl
.CanUndo())
252 elif id == wx
.ID_REDO
:
253 event
.Enable(stcControl
.CanRedo())
255 elif id == wx
.ID_CUT
:
256 event
.Enable(stcControl
.CanCut())
258 elif id == wx
.ID_COPY
:
259 event
.Enable(stcControl
.CanCopy())
261 elif id == wx
.ID_PASTE
:
262 event
.Enable(stcControl
.CanPaste())
264 elif id == wx
.ID_CLEAR
:
265 event
.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected
267 elif id == wx
.ID_SELECTALL
:
268 event
.Enable(stcControl
.GetTextLength() > 0)
271 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
274 def OnClose(self
, deleteWindow
=True):
275 if deleteWindow
and self
.GetFrame():
276 self
.GetFrame().Destroy()
280 class PythonInterpreterDocument(wx
.lib
.docview
.Document
):
281 """ Generate Unique Doc Type """
285 class PythonService(CodeEditor
.CodeService
):
289 CodeEditor
.CodeService
.__init
__(self
)
290 docManager
= wx
.GetApp().GetDocumentManager()
291 pythonInterpreterTemplate
= wx
.lib
.docview
.DocTemplate(docManager
,
292 _("Python Interpreter"),
296 _("Python Interpreter Document"),
297 _("Python Interpreter View"),
298 PythonInterpreterDocument
,
299 PythonInterpreterView
,
300 flags
= wx
.lib
.docview
.TEMPLATE_INVISIBLE
,
301 icon
= getPythonIcon())
302 docManager
.AssociateTemplate(pythonInterpreterTemplate
)
305 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
306 CodeEditor
.CodeService
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
308 if document
and document
.GetDocumentTemplate().GetDocumentType() != PythonDocument
:
310 if not document
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
313 viewMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View")))
315 viewStatusBarItemPos
= self
.GetMenuItemPos(viewMenu
, wx
.lib
.pydocview
.VIEW_STATUSBAR_ID
)
316 viewMenu
.InsertCheckItem(viewStatusBarItemPos
+ 1, VIEW_PYTHON_INTERPRETER_ID
, _("Python &Interpreter"), _("Shows or hides the Python interactive window"))
317 wx
.EVT_MENU(frame
, VIEW_PYTHON_INTERPRETER_ID
, frame
.ProcessEvent
)
318 wx
.EVT_UPDATE_UI(frame
, VIEW_PYTHON_INTERPRETER_ID
, frame
.ProcessUpdateUIEvent
)
321 def ProcessEvent(self
, event
):
323 if id == VIEW_PYTHON_INTERPRETER_ID
:
324 self
.OnViewPythonInterpreter(event
)
327 return CodeEditor
.CodeService
.ProcessEvent(self
, event
)
330 def ProcessUpdateUIEvent(self
, event
):
332 if id == VIEW_PYTHON_INTERPRETER_ID
:
334 docManager
= wx
.GetApp().GetDocumentManager()
336 for doc
in docManager
.GetDocuments():
337 if isinstance(doc
, PythonInterpreterDocument
):
342 return CodeEditor
.CodeService
.ProcessUpdateUIEvent(self
, event
)
345 def OnViewPythonInterpreter(self
, event
):
346 for doc
in wx
.GetApp().GetDocumentManager().GetDocuments():
347 if isinstance(doc
, PythonInterpreterDocument
):
351 for template
in self
.GetDocumentManager().GetTemplates():
352 if template
.GetDocumentType() == PythonInterpreterDocument
:
353 newDoc
= template
.CreateDocument('', wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
)
355 newDoc
.SetDocumentName(template
.GetDocumentName())
356 newDoc
.SetDocumentTemplate(template
)
357 newDoc
.OnNewDocument()
358 newDoc
.SetWriteable(False)
359 newDoc
.GetFirstView().GetFrame().SetTitle(_("Python Interpreter"))
363 class PythonCtrl(CodeEditor
.CodeCtrl
):
366 def __init__(self
, parent
, id=-1, style
=wx
.NO_FULL_REPAINT_ON_RESIZE
):
367 CodeEditor
.CodeCtrl
.__init
__(self
, parent
, id, style
)
368 self
.SetProperty("tab.timmy.whinge.level", "1")
369 self
.SetProperty("fold.comment.python", "1")
370 self
.SetProperty("fold.quotes.python", "1")
371 self
.SetLexer(wx
.stc
.STC_LEX_PYTHON
)
372 self
.SetKeyWords(0, string
.join(keyword
.kwlist
))
375 def CreatePopupMenu(self
):
376 FINDCLASS_ID
= wx
.NewId()
377 FINDDEF_ID
= wx
.NewId()
379 menu
= CodeEditor
.CodeCtrl
.CreatePopupMenu(self
)
381 self
.Bind(wx
.EVT_MENU
, self
.OnPopFindDefinition
, id=FINDDEF_ID
)
382 menu
.Insert(1, FINDDEF_ID
, _("Find 'def'"))
384 self
.Bind(wx
.EVT_MENU
, self
.OnPopFindClass
, id=FINDCLASS_ID
)
385 menu
.Insert(2, FINDCLASS_ID
, _("Find 'class'"))
390 def OnPopFindDefinition(self
, event
):
391 view
= wx
.GetApp().GetDocumentManager().GetCurrentView()
392 if hasattr(view
, "GetCtrl") and view
.GetCtrl() and hasattr(view
.GetCtrl(), "GetSelectedText"):
393 pattern
= view
.GetCtrl().GetSelectedText().strip()
395 searchPattern
= "def\s+%s" % pattern
396 wx
.GetApp().GetService(FindInDirService
.FindInDirService
).FindInProject(searchPattern
)
399 def OnPopFindClass(self
, event
):
400 view
= wx
.GetApp().GetDocumentManager().GetCurrentView()
401 if hasattr(view
, "GetCtrl") and view
.GetCtrl() and hasattr(view
.GetCtrl(), "GetSelectedText"):
402 definition
= "class\s+%s"
403 pattern
= view
.GetCtrl().GetSelectedText().strip()
405 searchPattern
= definition
% pattern
406 wx
.GetApp().GetService(FindInDirService
.FindInDirService
).FindInProject(searchPattern
)
409 def SetViewDefaults(self
):
410 CodeEditor
.CodeCtrl
.SetViewDefaults(self
, configPrefix
="Python", hasWordWrap
=True, hasTabs
=True, hasFolding
=True)
413 def GetFontAndColorFromConfig(self
):
414 return CodeEditor
.CodeCtrl
.GetFontAndColorFromConfig(self
, configPrefix
= "Python")
417 def UpdateStyles(self
):
418 CodeEditor
.CodeCtrl
.UpdateStyles(self
)
420 if not self
.GetFont():
423 faces
= { 'font' : self
.GetFont().GetFaceName(),
424 'size' : self
.GetFont().GetPointSize(),
425 'size2': self
.GetFont().GetPointSize() - 2,
426 'color' : "%02x%02x%02x" % (self
.GetFontColor().Red(), self
.GetFontColor().Green(), self
.GetFontColor().Blue())
431 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces
)
433 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces
)
435 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, "face:%(font)s,fore:#007F7F,size:%(size)d" % faces
)
437 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces
)
438 # Single quoted string
439 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces
)
441 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces
)
443 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces
)
444 # Triple double quotes
445 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces
)
446 # Class name definition
447 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, "face:%(font)s,fore:#0000FF,bold,size:%(size)d" % faces
)
448 # Function or method name definition
449 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, "face:%(font)s,fore:#007F7F,bold,size:%(size)d" % faces
)
451 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, "face:%(font)s,size:%(size)d" % faces
)
453 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, "face:%(font)s,fore:#%(color)s,face:%(font)s,size:%(size)d" % faces
)
455 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, "face:%(font)s,fore:#7F7F7F,size:%(size)d" % faces
)
456 # End of line where string is not closed
457 self
.StyleSetSpec(wx
.stc
.STC_P_STRINGEOL
, "face:%(font)s,fore:#000000,face:%(font)s,back:#E0C0E0,eol,size:%(size)d" % faces
)
460 def OnUpdateUI(self
, evt
):
461 braces
= self
.GetMatchingBraces()
463 # check for matching braces
467 caretPos
= self
.GetCurrentPos()
469 charBefore
= self
.GetCharAt(caretPos
- 1)
470 styleBefore
= self
.GetStyleAt(caretPos
- 1)
473 if charBefore
and chr(charBefore
) in braces
and styleBefore
== wx
.stc
.STC_P_OPERATOR
:
474 braceAtCaret
= caretPos
- 1
478 charAfter
= self
.GetCharAt(caretPos
)
479 styleAfter
= self
.GetStyleAt(caretPos
)
480 if charAfter
and chr(charAfter
) in braces
and styleAfter
== wx
.stc
.STC_P_OPERATOR
:
481 braceAtCaret
= caretPos
483 if braceAtCaret
>= 0:
484 braceOpposite
= self
.BraceMatch(braceAtCaret
)
486 if braceAtCaret
!= -1 and braceOpposite
== -1:
487 self
.BraceBadLight(braceAtCaret
)
489 self
.BraceHighlight(braceAtCaret
, braceOpposite
)
495 (text
, caretPos
) = self
.GetCurLine()
497 self
._tokenizerChars
= {} # This is really too much, need to find something more like a C array
498 for i
in range(len(text
)):
499 self
._tokenizerChars
[i
] = 0
501 ctext
= cStringIO
.StringIO(text
)
503 tokenize
.tokenize(ctext
.readline
, self
)
507 # Left in for debugging purposes:
508 #for i in range(len(text)):
509 # print i, text[i], self._tokenizerChars[i]
511 if caretPos
== 0 or len(string
.strip(text
)) == 0: # At beginning of line or within an empty line
514 doExtraIndent
= False
520 startSquareBracketCount
= 0
521 endSquareBracketCount
= 0
522 startCurlyBracketCount
= 0
523 endCurlyBracketCount
= 0
526 for i
in range(caretPos
- 1, -1, -1): # Go through each character before the caret
527 if i
>= len(text
): # Sometimes the caret is at the end of the text if there is no LF
529 if self
._tokenizerChars
[i
] == 1:
531 elif self
._tokenizerChars
[i
] == 2:
532 startQuoteCount
= startQuoteCount
+ 1
533 elif self
._tokenizerChars
[i
] == 3:
534 endQuoteCount
= endQuoteCount
+ 1
535 elif text
[i
] == '(': # Would be nice to use a dict for this, but the code is much more readable this way
536 startParenCount
= startParenCount
+ 1
538 endParenCount
= endParenCount
+ 1
540 startSquareBracketCount
= startSquareBracketCount
+ 1
542 endSquareBracketCount
= endSquareBracketCount
+ 1
544 startCurlyBracketCount
= startCurlyBracketCount
+ 1
546 endCurlyBracketCount
= endCurlyBracketCount
+ 1
550 if startQuoteCount
> endQuoteCount
or startParenCount
> endParenCount
or startSquareBracketCount
> endSquareBracketCount
or startCurlyBracketCount
> endCurlyBracketCount
:
551 if i
+ 1 >= caretPos
: # Caret is right at the open paren, so just do indent as if colon was there
555 spaces
= " " * (i
+ 1)
559 spaces
= text
[0:len(text
) - len(string
.lstrip(text
))]
560 if caretPos
< len(spaces
): # If within the opening spaces of a line
561 spaces
= spaces
[:caretPos
]
564 if commentStart
!= -1:
565 text
= text
[0:commentStart
]
567 textNoTrailingSpaces
= text
[0:caretPos
].rstrip()
568 if doExtraIndent
or len(textNoTrailingSpaces
) and textNoTrailingSpaces
[-1] == ':':
569 spaces
= spaces
+ ' ' * self
.GetIndent()
570 self
.AddText('\n' + spaces
)
571 self
.EnsureCaretVisible()
574 # Callback for tokenizer in self.DoIndent
575 def __call__(self
, toktype
, toktext
, (srow
,scol
), (erow
,ecol
), line
):
576 if toktype
== tokenize
.COMMENT
:
577 for i
in range(scol
, ecol
+ 1):
578 self
._validChars
[i
] = False
579 elif toktype
== token
.STRING
:
580 self
._tokenizerChars
[scol
] = 2 # Open quote
581 self
._tokenizerChars
[ecol
- 1] = 3 # Close quote
582 for i
in range(scol
+ 1, ecol
- 2):
583 self
._tokenizerChars
[i
] = 1 # Part of string, 1 == ignore the char
586 class PythonOptionsPanel(wx
.Panel
):
588 def __init__(self
, parent
, id):
589 wx
.Panel
.__init
__(self
, parent
, id)
590 pathLabel
= wx
.StaticText(self
, -1, _("python.exe Path:"))
591 config
= wx
.ConfigBase_Get()
592 path
= config
.Read("ActiveGridPythonLocation")
593 self
._pathTextCtrl
= wx
.TextCtrl(self
, -1, path
, size
= (150, -1))
594 self
._pathTextCtrl
.SetToolTipString(self
._pathTextCtrl
.GetValue())
595 self
._pathTextCtrl
.SetInsertionPointEnd()
596 choosePathButton
= wx
.Button(self
, -1, _("Browse..."))
597 pathSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
600 pathSizer
.Add(pathLabel
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.LEFT|wx
.TOP
, HALF_SPACE
)
601 pathSizer
.Add(self
._pathTextCtrl
, 1, wx
.EXPAND|wx
.LEFT|wx
.TOP
, HALF_SPACE
)
602 pathSizer
.Add(choosePathButton
, 0, wx
.ALIGN_RIGHT|wx
.LEFT|wx
.RIGHT|wx
.TOP
, HALF_SPACE
)
603 wx
.EVT_BUTTON(self
, choosePathButton
.GetId(), self
.OnChoosePath
)
604 mainSizer
= wx
.BoxSizer(wx
.VERTICAL
)
605 mainSizer
.Add(pathSizer
, 0, wx
.EXPAND|wx
.LEFT|wx
.RIGHT|wx
.TOP
, SPACE
)
607 self
._otherOptions
= STCTextEditor
.TextOptionsPanel(self
, -1, configPrefix
= "Python", label
= "Python", hasWordWrap
= True, hasTabs
= True, addPage
=False, hasFolding
=True)
608 mainSizer
.Add(self
._otherOptions
, 0, wx
.EXPAND|wx
.BOTTOM
, SPACE
)
609 self
.SetSizer(mainSizer
)
610 parent
.AddPage(self
, _("Python"))
613 def OnChoosePath(self
, event
):
614 defaultDir
= os
.path
.dirname(self
._pathTextCtrl
.GetValue().strip())
615 defaultFile
= os
.path
.basename(self
._pathTextCtrl
.GetValue().strip())
617 wildcard
= _("Executable (*.exe)|*.exe|All|*.*")
619 defaultFile
= "python.exe"
622 dlg
= wx
.FileDialog(wx
.GetApp().GetTopWindow(),
624 defaultDir
=defaultDir
,
625 defaultFile
=defaultFile
,
627 style
=wx
.OPEN|wx
.FILE_MUST_EXIST|wx
.HIDE_READONLY
)
628 # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
629 if dlg
.ShowModal() == wx
.ID_OK
:
632 self
._pathTextCtrl
.SetValue(path
)
633 self
._pathTextCtrl
.SetToolTipString(self
._pathTextCtrl
.GetValue())
634 self
._pathTextCtrl
.SetInsertionPointEnd()
638 def OnOK(self
, optionsDialog
):
639 config
= wx
.ConfigBase_Get()
640 config
.Write("ActiveGridPythonLocation", self
._pathTextCtrl
.GetValue().strip())
642 self
._otherOptions
.OnOK(optionsDialog
)
646 return getPythonIcon()
649 #----------------------------------------------------------------------------
650 # Icon Bitmaps - generated by encode_bitmaps.py
651 #----------------------------------------------------------------------------
652 from wx
import ImageFromStream
, BitmapFromImage
658 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
659 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
660 \x00\x01\xe7IDAT8\x8d}\x921h\x13Q\x18\xc7\x7fw\xb9\x0ei\x9d*\xbd\xeb\x10\x8f\
661 ,\x99\x1c*A[\xaa\x19B\xe8\xd0\xb1\x0e%K\x87\x88T2\x88Cqp\tD\x14i\xe9\xe0V\
662 \xdaQ\xb7\xe0P\xa1\x8b\xa0(\x95$z\xd5Q1\x90\xa2\xd7\x9a4^\x87\xa0`\x92!w9\
663 \x87\xf8.\xb9\xa6\xc97\xbd\xef{\xef\xfb\xbd\xff\xfb\xbfO*~;v\xf9\x1f\xad\xba\
664 \x05@\xf9\xd4\x06\xc0::$\xbb\x96\x92\x18\x11\n@(4\xdd\xcdB\xd3\xd4\x1d\x85\
665 \x8b\x97\xe1\xe3;\x83\x99\xe5\x15\xb2\xe0\x8e\x82\xc8\xa3\xe8\x003\xcb+\xac\
666 \xaee\xdda\xfb\xb2\x90\rPw\x14\x00\x9a\xb5\n\xbf\xfflSz\x9d\xa2Y\xdc"zca\xe8\
667 \x05\xb2h\x14\xcd\xd0\xf3B\x9f\x98\xe5\xf9\xde\x13"\xaaB\xc7\xb1\xcfU!\x0b\
668 \xc3D4k\x15\xac\x93\x03\xf4\x89Y\xaf\x96\xffT\x028\x17\xa2\xf4\'\xcdZ\x85\
669 \xf7F\x06{\xaa\x80ev\xc1\x91\xb91>\x18\x0f\xb8\xb7\x95a\xe9\xca\x0b:\x8e\xed\
670 \xca\x01E\x1a\x00\x98\r\x89\x92\x91\xa1\xda\xd8\x87\x06ha\x1f\x1b\x80\xcd\
671 \x9d%\xe0\xa5\x0f"[G\x87\x98\x8d\xde/ia\x05-\xac`\x996\xf9\\\x0b\xcb\xb4)\
672 \x1bmOMn\xf7\xd5\xf0\'\\\x8b\xdces\xe7\x8d\xef\x80h\xd6\xc2\n\xf9\\\x0b]\xf5\
673 \xab\xf2\xcdApR#\xf1kp4b\xc9 \xf9\\\x0b\x80\xe4\xcdE\xaf\xdeqlW\xaeVL\xaf`~\
674 \xd9\x03@W\xd3\x00\xc4\x13\x0b\xc4\x92A\xcf\xd0\xf9\xe8:\x89\xebW\x01(|\xfd\
675 \xe1\xbe-~F\xbas\xff\x91\xf75\x82n\x9d\x1c\xf0}\xfciw\xdd\xe7A<\xd1\x1b\xa8j\
676 c\x9f\xb2\xd1F\x92\xe4\x80O\x12\xc0\xc6\xb3\x14\xf6Ta\xe0)g\x81\xba\x9a\xf6\
677 \x9b(\x07\x14I@\x84lq\xb8?\xe6\xa3\xeb\x00\xdc\xba\x9d\xf4+\x10*~\xfem\xf3\
678 \xf8\xe1\x06\xc7\xa7\xdb\xe8j\x9a\xf8\xdc\xa4\xb7\x1f[\\\xe5\xd2\x851/\xff\
679 \x07\xac\x9b\xd1e\x12\x96\x0f\xfd\x00\x00\x00\x00IEND\xaeB`\x82'
682 def getPythonBitmap():
683 return BitmapFromImage(getPythonImage())
685 def getPythonImage():
686 stream
= cStringIO
.StringIO(getPythonData())
687 return ImageFromStream(stream
)
690 return wx
.IconFromBitmap(getPythonBitmap())