1 #----------------------------------------------------------------------------
2 # Name: ProjectEditor.py
3 # Purpose: IDE-style Project Editor for wx.lib.pydocview
5 # Author: Peter Yared, Morgan Hua
9 # Copyright: (c) 2003, 2004, 2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
14 import wx
.lib
.pydocview
19 from wxPython
.lib
.rcsizer
import RowColSizer
23 import DebuggerService
25 import activegrid
.util
.xmlmarshaller
27 from IDE
import ACTIVEGRID_BASE_IDE
28 if not ACTIVEGRID_BASE_IDE
:
29 import ProcessModelEditor
33 if wx
.Platform
== '__WXMSW__':
39 #----------------------------------------------------------------------------
40 # XML Marshalling Methods
41 #----------------------------------------------------------------------------
44 xml
= fileObject
.read()
45 projectModel
= activegrid
.util
.xmlmarshaller
.unmarshal(xml
)
49 def save(fileObject
, projectModel
):
50 xml
= activegrid
.util
.xmlmarshaller
.marshal(projectModel
, prettyPrint
=True)
54 #----------------------------------------------------------------------------
56 #----------------------------------------------------------------------------
59 __xmlname__
= "projectmodel"
60 __xmlrename__
= { "_files":"files", "_homepath":"homepath" }
67 class ProjectDocument(wx
.lib
.docview
.Document
):
70 wx
.lib
.docview
.Document
.__init
__(self
)
71 self
._projectModel
= ProjectModel()
75 return self
._projectModel
78 def OnCreate(self
, path
, flags
):
79 projectService
= wx
.GetApp().GetService(ProjectService
)
80 if projectService
.GetView():
81 view
= projectService
.GetView()
84 view
= self
.GetDocumentTemplate().CreateView(self
, flags
)
85 projectService
.SetView(view
)
89 def LoadObject(self
, fileObject
):
90 self
._projectModel
= activegrid
.tool
.ProjectEditor
.load(fileObject
)
94 def SaveObject(self
, fileObject
):
95 activegrid
.tool
.ProjectEditor
.save(fileObject
, self
._projectModel
)
99 def OnSaveDocument(self
, filename
):
100 self
._projectModel
._homepath
= wx
.lib
.docview
.PathOnly(filename
)
101 return wx
.lib
.docview
.Document
.OnSaveDocument(self
, filename
)
104 def OnOpenDocument(self
, filename
):
105 view
= self
.GetFirstView()
106 frame
= view
.GetFrame()
108 if not os
.path
.exists(filename
):
109 wx
.GetApp().CloseSplash()
110 msgTitle
= wx
.GetApp().GetAppName()
112 msgTitle
= _("File Error")
113 wx
.MessageBox(_("Could not find '%s'.") % filename
,
115 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
117 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
119 fileObject
= file(filename
, 'r')
121 self
.LoadObject(fileObject
)
123 wx
.GetApp().CloseSplash()
124 msgTitle
= wx
.GetApp().GetAppName()
126 msgTitle
= _("File Error")
127 wx
.MessageBox(_("Could not open '%s'. %s") % (wx
.lib
.docview
.FileNameFromPath(filename
), sys
.exc_value
),
129 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
131 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
135 # if the project file has moved, then ask the user if we should readjust the paths of all the files in the project
136 newHomepath
= wx
.lib
.docview
.PathOnly(filename
)
137 if newHomepath
!= self
._projectModel
._homepath
:
138 wx
.GetApp().CloseSplash()
139 msgTitle
= wx
.GetApp().GetAppName()
141 msgTitle
= _("Project Moved")
142 projectService
= wx
.GetApp().GetService(activegrid
.tool
.ProjectEditor
.ProjectService
)
143 yesNoMsg
= wx
.MessageDialog(frame
,
144 _("The project file '%s' was moved from:\n '%s'\nto:\n '%s'.\n\nWould you like to automatically adjust the project contents accordingly?") % (wx
.lib
.docview
.FileNameFromPath(filename
), self
._projectModel
._homepath
, wx
.lib
.docview
.PathOnly(filename
)),
146 wx
.YES_NO | wx
.STAY_ON_TOP
148 if projectService
.GetSuppressOpenProjectMessages() or yesNoMsg
.ShowModal() == wx
.ID_YES
:
149 if not projectService
.GetSuppressOpenProjectMessages():
150 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
151 messageService
.ShowWindow()
152 messageView
= messageService
.GetView()
153 messageView
.ClearLines()
154 messageView
.AddLines(_("The project file '%s' was moved from:\n '%s'\nto:\n '%s'\n") % (wx
.lib
.docview
.FileNameFromPath(filename
), self
._projectModel
._homepath
, wx
.lib
.docview
.PathOnly(filename
)))
155 messageView
.AddLines(_("Updating file references:\n"))
157 for index
, filepath
in enumerate(self
._projectModel
._files
):
158 if filepath
.startswith(self
._projectModel
._homepath
+ os
.sep
):
159 newfile
= newHomepath
+ filepath
[len(self
._projectModel
._homepath
):len(filepath
)]
160 if os
.path
.exists(newfile
):
161 self
._projectModel
._files
[index
] = newfile
162 if not projectService
.GetSuppressOpenProjectMessages():
163 messageView
.AddLines(_(" Success: '%s' location changed from '%s' to '%s'\n") % (wx
.lib
.docview
.FileNameFromPath(filepath
), wx
.lib
.docview
.PathOnly(filepath
), newHomepath
))
166 if not projectService
.GetSuppressOpenProjectMessages():
167 messageView
.AddLines(_(" Failure: Couldn't find '%s', file wasn't located at '%s'\n") % (wx
.lib
.docview
.FileNameFromPath(filepath
), newHomepath
))
169 if not projectService
.GetSuppressOpenProjectMessages():
170 messageView
.AddLines(_( " Unmodified: '%s' location wasn't relative to '%s'\n") % (filepath
, self
._projectModel
._homepath
))
171 self
._projectModel
._homepath
= newHomepath
172 if not projectService
.GetSuppressOpenProjectMessages():
173 messageView
.AddLines(_("Project file updated."))
175 self
.SetFilename(filename
, True)
176 view
.AddProjectToView(self
)
177 self
.UpdateAllViews()
178 self
._savedYet
= True
183 def AddFile(self
, file):
184 return self
.AddFiles([file])
187 def AddFiles(self
, files
):
188 notAlreadyThereFiles
= filter(lambda x
: x
not in self
._projectModel
._files
, files
) # Filter to the files that are not already in the project
189 if len(notAlreadyThereFiles
) == 0:
190 self
.UpdateAllViews(hint
= ("select", self
, files
))
193 self
._projectModel
._files
= self
._projectModel
._files
+ notAlreadyThereFiles
194 self
.UpdateAllViews(hint
= ("add", self
, notAlreadyThereFiles
))
199 def RemoveFile(self
, file):
200 return self
.RemoveFiles([file])
203 def RemoveFiles(self
, files
):
205 self
._projectModel
._files
.remove(file)
206 self
.UpdateAllViews(hint
= ("remove", self
, files
))
211 def RenameFile(self
, oldFile
, newFile
, isProject
= False):
213 if oldFile
== newFile
:
216 # projects don't have to exist yet, so not required to rename old file,
217 # but files must exist, so we'll try to rename and allow exceptions to occur if can't.
218 if not isProject
or (isProject
and os
.path
.exists(oldFile
)):
219 os
.rename(oldFile
, newFile
)
222 documents
= self
.GetDocumentManager().GetDocuments()
223 for document
in documents
:
224 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
225 document
.SetFilename(newFile
)
226 document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFile
))
227 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
229 self
.RemoveFile(oldFile
)
230 self
.AddFile(newFile
)
231 documents
= self
.GetDocumentManager().GetDocuments()
232 for document
in documents
:
233 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
234 document
.SetFilename(newFile
, notifyViews
= True)
235 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
237 except OSError, (code
, message
):
238 msgTitle
= wx
.GetApp().GetAppName()
240 msgTitle
= _("File Error")
241 wx
.MessageBox("Could not rename '%s'. '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFile
), message
),
243 wx
.OK | wx
.ICON_EXCLAMATION
,
244 self
.GetFirstView().GetFrame())
249 return self
._projectModel
._files
252 def IsFileInProject(self
, filename
):
253 return filename
in self
.GetFiles()
258 class NewProjectWizard(Wizard
.BaseWizard
):
260 WIZTITLE
= _("New Project Wizard")
262 def __init__(self
, parent
):
263 self
._parent
= parent
264 self
._fullProjectPath
= None
265 Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
)
266 self
._projectLocationPage
= self
.CreateProjectLocation(self
)
267 wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
)
269 def CreateProjectLocation(self
,wizard
):
270 page
= Wizard
.TitledWizardPage(wizard
, _("Project File Location"))
272 page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n")))
273 self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation
= UICommon
.CreateDirectoryControl(page
, _("File Name:"), _("Directory:"), _("agp"), startingDirectory
=os
.getcwd())
274 page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
)
277 wizard
.FitToPage(page
)
280 def RunWizard(self
, existingTables
= None, existingRelationships
= None):
281 status
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
)
283 docManager
= wx
.GetApp().GetTopWindow().GetDocumentManager()
284 if os
.path
.exists(self
._fullProjectPath
):
285 # What if the document is already open and we're overwriting it?
286 documents
= docManager
.GetDocuments()
287 for document
in documents
:
288 if document
.GetFilename() == self
._fullProjectPath
: # If the renamed document is open, update it
289 document
.DeleteAllViews()
291 os
.remove(self
._fullProjectPath
)
293 for template
in docManager
.GetTemplates():
294 if template
.GetDocumentType() == ProjectDocument
:
295 doc
= template
.CreateDocument(self
._fullProjectPath
, flags
= wx
.lib
.docview
.DOC_NEW
)
296 doc
.OnSaveDocument(self
._fullProjectPath
)
297 view
= doc
.GetFirstView()
298 view
.AddProjectToView(doc
)
305 def OnWizPageChanging(self
, event
):
306 if event
.GetDirection(): # It's going forwards
307 if event
.GetPage() == self
._projectLocationPage
:
308 if not self
._fileValidation
():
311 self
._fullProjectPath
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(),'.agp'))
315 def OnShowCreatePages(self
):
317 import DataModelEditor
318 requestedPos
= self
.GetPositionTuple()
319 projectService
= wx
.GetApp().GetService(ProjectService
)
320 projectView
= projectService
.GetView()
322 wiz
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
)
323 if wiz
.RunWizard(dontDestroy
=True):
324 self
._schemaName
.SetValue(wiz
.GetSchemaFileName())
328 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
):
330 def CreateDocument(self
, path
, flags
):
332 return wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
)
334 wiz
= NewProjectWizard(wx
.GetApp().GetTopWindow())
337 return None # never return the doc, otherwise docview will think it is a new file and rename it
339 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
):
341 def __init__(self
, projectDoc
, files
):
342 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
343 self
._projectDoc
= projectDoc
348 if len(self
._files
) == 1:
351 return _("Add Files")
355 return self
._projectDoc
.AddFiles(self
._files
)
359 return self
._projectDoc
.RemoveFiles(self
._files
)
362 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
):
364 def __init__(self
, projectDoc
, files
):
365 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
366 self
._projectDoc
= projectDoc
371 if len(self
._files
) == 1:
372 return _("Remove File")
374 return _("Remove Files")
378 return self
._projectDoc
.RemoveFiles(self
._files
)
382 return self
._projectDoc
.AddFiles(self
._files
)
385 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
):
387 def __init__(self
, projectDoc
, oldFile
, newFile
, isProject
= False):
388 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
389 self
._projectDoc
= projectDoc
390 self
._oldFile
= oldFile
391 self
._newFile
= newFile
392 self
._isProject
= isProject
396 return _("Rename File")
400 return self
._projectDoc
.RenameFile(self
._oldFile
, self
._newFile
, self
._isProject
)
404 return self
._projectDoc
.RenameFile(self
._newFile
, self
._oldFile
, self
._isProject
)
407 class ProjectTreeCtrl(wx
.TreeCtrl
):
409 def __init__(self
, parent
, id, style
):
410 wx
.TreeCtrl
.__init
__(self
, parent
, id, style
= style
)
412 templates
= wx
.GetApp().GetDocumentManager().GetTemplates()
413 iconList
= wx
.ImageList(16, 16, initialCount
= len(templates
))
414 self
._iconIndexLookup
= []
415 for template
in templates
:
416 icon
= template
.GetIcon()
418 if icon
.GetHeight() != 16:
419 icon
.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
420 if icon
.GetWidth() != 16:
421 icon
.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
422 iconIndex
= iconList
.AddIcon(icon
)
423 self
._iconIndexLookup
.append((template
, iconIndex
))
425 icon
= getBlankIcon()
426 if icon
.GetHeight() != 16:
427 icon
.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
428 if icon
.GetWidth() != 16:
429 icon
.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
430 self
._blankIconIndex
= iconList
.AddIcon(icon
)
431 self
.AssignImageList(iconList
)
434 def OnCompareItems(self
, item1
, item2
):
435 return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower())
438 def AppendItem(self
, parent
, filepath
):
439 item
= wx
.TreeCtrl
.AppendItem(self
, parent
, filepath
)
442 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filepath
)
443 if not template
and parent
== self
.GetRootItem(): # If the parent is a root it's a new project
444 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
446 for t
, iconIndex
in self
._iconIndexLookup
:
448 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
)
449 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
)
450 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Selected
)
455 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
)
456 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
)
457 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Selected
)
462 class ProjectView(wx
.lib
.docview
.View
):
465 #----------------------------------------------------------------------------
467 #----------------------------------------------------------------------------
469 def __init__(self
, service
= None):
470 wx
.lib
.docview
.View
.__init
__(self
)
471 self
._service
= service
# not used, but kept to match other Services
472 self
._lastDirectory
= ""
473 self
._treeCtrl
= None
474 self
._editingSoDontKillFocus
= False
475 self
._checkEditMenu
= True
479 projectService
= wx
.GetApp().GetService(ProjectService
)
481 projectService
.SetView(None)
482 wx
.lib
.docview
.View
.Destroy(self
)
485 def GetDocument(self
):
486 if not self
._treeCtrl
:
489 items
= self
._treeCtrl
.GetSelections()
490 if not items
: # No selection, so just return first project
491 item
= self
._treeCtrl
.GetFirstVisibleItem()
493 return self
._GetItemProject
(item
)
498 project
= self
._GetItemProject
(item
)
505 def GetDocumentManager(self
): # Overshadow this since the superclass uses the view._viewDocument attribute directly, which the project editor doesn't use since it hosts multiple docs
506 return wx
.GetApp().GetDocumentManager()
509 def OnChangeFilename(self
):
511 title
= _("Projects")
512 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
513 title
= title
+ " - " + wx
.GetApp().GetAppName()
514 self
.GetFrame().SetTitle(title
)
515 project
= self
.GetDocument()
517 projectItem
= self
._GetProjectItem
(project
)
518 name
= self
._treeCtrl
.GetItemText(self
._GetProjectItem
(project
))
519 name2
= self
._MakeProjectName
(project
)
521 self
._treeCtrl
.SetItemText(projectItem
, name2
)
522 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
525 def Activate(self
, activate
= True):
526 if not wx
.GetApp().IsMDI():
527 if activate
and not self
.IsShown():
531 wx
.lib
.docview
.View
.Activate(self
, activate
= activate
)
532 if activate
and self
._treeCtrl
:
533 self
._treeCtrl
.SetFocus()
536 def OnCreate(self
, doc
, flags
):
537 config
= wx
.ConfigBase_Get()
538 if wx
.GetApp().IsMDI():
539 self
._embeddedWindow
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
)
540 self
.SetFrame(self
._embeddedWindow
)
541 frame
= self
._embeddedWindow
543 self
._embeddedWindow
= None
544 pos
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1)
545 # make sure frame is visible
546 screenWidth
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
)
547 screenHeight
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
)
548 if pos
[0] < 0 or pos
[0] >= screenWidth
or pos
[1] < 0 or pos
[1] >= screenHeight
:
549 pos
= wx
.DefaultPosition
551 size
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1))
553 title
= _("Projects")
554 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
555 title
= title
+ " - " + wx
.GetApp().GetAppName()
557 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title
= title
, pos
= pos
, size
= size
)
558 if config
.ReadInt("ProjectFrameMaximized", False):
561 sizer
= wx
.BoxSizer()
562 self
._treeCtrl
= ProjectTreeCtrl(frame
, -1, style
= wx
.TR_HIDE_ROOT | wx
.TR_HAS_BUTTONS | wx
.TR_EDIT_LABELS | wx
.TR_DEFAULT_STYLE | wx
.TR_MULTIPLE
)
563 self
._treeCtrl
.AddRoot(_("Projects"))
565 if self
._embeddedWindow
:
566 sizer
.Add(self
._treeCtrl
)
569 sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
, 0)
570 frame
.SetSizer(sizer
)
574 if wx
.GetApp().IsMDI():
575 wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
)
576 wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
)
578 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
579 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
)
581 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
)
582 wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
)
583 wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
)
584 wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
)
585 wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
)
586 # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
588 # drag-and-drop support
589 dt
= ProjectFileDropTarget(self
)
590 self
._treeCtrl
.SetDropTarget(dt
)
595 def WriteProjectConfig(self
):
596 frame
= self
.GetFrame()
597 config
= wx
.ConfigBase_Get()
598 if frame
and not self
._embeddedWindow
:
599 if not frame
.IsMaximized():
600 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0])
601 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1])
602 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0])
603 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1])
604 config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized())
606 if config
.ReadInt("ProjectSaveDocs", True):
607 projectFileNames
= []
610 for projectItem
in self
._GetChildItems
(self
._treeCtrl
.GetRootItem()):
611 project
= self
._GetItemProject
(projectItem
)
612 if not project
.OnSaveModified():
614 if project
.GetDocumentSaved(): # Might be a new document and "No" selected to save it
615 projectFileNames
.append(str(project
.GetFilename()))
616 projectExpanded
.append(self
._treeCtrl
.IsExpanded(projectItem
))
617 config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__())
618 config
.Write("ProjectExpandedSavedDocs", projectExpanded
.__repr
__())
621 def OnClose(self
, deleteWindow
= True):
622 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
623 self
.WriteProjectConfig()
624 project
= self
.GetDocument()
627 if not self
.GetDocument().Close():
631 projectItem
= self
._GetProjectItem
(project
)
633 self
._treeCtrl
.Delete(projectItem
)
634 # We don't need to delete the window since it is a floater/embedded
638 def _GetParentFrame(self
):
639 return wx
.GetTopLevelParent(self
.GetFrame())
642 def OnUpdate(self
, sender
= None, hint
= None):
643 wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
)
646 projectItem
= self
._GetProjectItem
(hint
[1])
648 self
._treeCtrl
.UnselectAll()
649 self
._treeCtrl
.Expand(projectItem
)
651 item
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
652 self
._treeCtrl
.SetPyData(item
, file)
653 self
._treeCtrl
.SelectItem(item
)
654 self
._treeCtrl
.EnsureVisible(item
) # wxBug: Doesn't work
655 self
._treeCtrl
.SortChildren(projectItem
)
656 elif hint
[0] == "remove":
657 projectItem
= self
._GetProjectItem
(hint
[1])
659 children
= self
._GetChildItems
(projectItem
)
660 for child
in children
:
661 if self
._GetItemFile
(child
) in files
:
662 self
._treeCtrl
.Delete(child
)
663 elif hint
[0] == "select":
664 projectItem
= self
._GetProjectItem
(hint
[1])
666 self
._treeCtrl
.UnselectAll()
667 children
= self
._GetChildItems
(projectItem
)
668 for child
in children
:
669 if self
._GetItemFile
(child
) in files
:
670 self
._treeCtrl
.SelectItem(child
)
671 self
._treeCtrl
.EnsureVisible(child
) # wxBug: Doesn't work
672 elif hint
[0] == "rename":
673 projectItem
= self
._GetProjectItem
(hint
[1])
674 self
._treeCtrl
.SetItemText(projectItem
, os
.path
.basename(hint
[2]))
677 def ProcessEvent(self
, event
):
679 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
680 self
.OnAddFileToProject(event
)
682 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
683 return False # Implement this one in the service
684 elif id == ProjectService
.RENAME_ID
:
687 elif id == wx
.ID_CUT
:
690 elif id == wx
.ID_COPY
:
693 elif id == wx
.ID_PASTE
:
696 elif id == wx
.ID_CLEAR
or id == ProjectService
.REMOVE_FROM_PROJECT
:
699 elif id == wx
.ID_SELECTALL
:
700 self
.OnSelectAll(event
)
702 elif id == ProjectService
.OPEN_SELECTION_ID
:
703 self
.OnOpenSelection(event
)
705 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
706 self
.OnProperties(event
)
711 def ProcessUpdateUIEvent(self
, event
):
712 # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
713 if self
._checkEditMenu
:
714 doc
= self
.GetDocument()
715 if doc
and not doc
.GetCommandProcessor().GetEditMenu():
716 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
717 self
._checkEditMenu
= False
719 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
720 event
.Enable(self
._HasProjectsSelected
() or self
._HasFilesSelected
())
722 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
725 elif id == ProjectService
.RENAME_ID
:
726 event
.Enable(self
._HasFilesSelected
() or self
._HasProjectsSelected
())
728 elif id == wx
.ID_CUT
:
729 event
.Enable(self
._AreSelectedItemsFromSameProject
())
731 elif id == wx
.ID_COPY
:
732 event
.Enable(self
._HasFilesSelected
())
734 elif id == wx
.ID_PASTE
:
735 event
.Enable(self
.CanPaste())
737 elif id == wx
.ID_CLEAR
or id == ProjectService
.REMOVE_FROM_PROJECT
:
738 event
.Enable(self
._AreSelectedItemsFromSameProject
())
740 elif id == wx
.ID_SELECTALL
:
741 event
.Enable(self
._HasFiles
())
743 elif id == ProjectService
.OPEN_SELECTION_ID
:
744 event
.Enable(self
._HasFilesSelected
())
746 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
747 event
.Enable(self
._HasProjectsSelected
() or self
._HasFilesSelected
())
752 #----------------------------------------------------------------------------
754 #----------------------------------------------------------------------------
757 if not self
.GetFrame():
759 return self
.GetFrame().IsShown()
766 def Show(self
, show
= True):
767 self
.GetFrame().Show(show
)
768 if wx
.GetApp().IsMDI():
769 mdiParentFrame
= wx
.GetApp().GetTopWindow()
770 mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
)
773 #----------------------------------------------------------------------------
774 # Methods for ProjectDocument and ProjectService to call
775 #----------------------------------------------------------------------------
777 def SetExpandedProjects(self
, expandedProjects
):
778 self
._treeCtrl
.UnselectAll()
780 for i
, item
in enumerate(self
._GetChildItems
(self
._treeCtrl
.GetRootItem())):
783 if expandedProjects
[i
]:
784 self
._treeCtrl
.Expand(item
)
786 self
._treeCtrl
.Collapse(item
)
787 # wxBug: This causes a crash, tried using ScrollTo which crashed as well. Then tried calling it with wx.CallAfter and that crashed as well, with both EnsureVisible and ScrollTo
788 # self._treeCtrl.EnsureVisible(self._treeCtrl.GetRootItem())
789 # So doing the following massive hack which forces the treectrl to scroll up to the top item
791 if expandedProjects
[i
]:
792 self
._treeCtrl
.Collapse(firstItem
)
793 self
._treeCtrl
.Expand(firstItem
)
795 self
._treeCtrl
.Expand(firstItem
)
796 self
._treeCtrl
.Collapse(firstItem
)
798 def GetSelectedFile(self
):
799 for item
in self
._treeCtrl
.GetSelections():
800 return self
._GetItemFile
(item
)
802 def AddProjectToView(self
, document
):
803 rootItem
= self
._treeCtrl
.GetRootItem()
804 projectItem
= self
._treeCtrl
.AppendItem(rootItem
, self
._MakeProjectName
(document
))
805 self
._treeCtrl
.SetPyData(projectItem
, document
)
806 for file in document
.GetFiles():
807 fileItem
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
808 self
._treeCtrl
.SetPyData(fileItem
, file)
809 self
._treeCtrl
.SortChildren(rootItem
)
810 self
._treeCtrl
.SortChildren(projectItem
)
811 self
._treeCtrl
.UnselectAll()
812 self
._treeCtrl
.Expand(projectItem
)
813 self
._treeCtrl
.SelectItem(projectItem
)
814 if self
._embeddedWindow
:
815 document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
817 #----------------------------------------------------------------------------
818 # Methods for OutlineService
819 #----------------------------------------------------------------------------
820 def DoLoadOutlineCallback(self
, force
=False):
821 """ Project Editor is a special case for the Outline Service.
822 You need to be able to be active in the Project Manager without clearing
823 the Outline View. So we make the Project Editor a client of the Outline
824 Service, but we don't load anything in the Outline View, leaving the
825 contents of the Outline View alone (e.g. last document's outline view).
829 #----------------------------------------------------------------------------
831 #----------------------------------------------------------------------------
833 def OnProperties(self
, event
):
834 items
= self
._treeCtrl
.GetSelections()
838 if self
._IsItemProject
(item
):
839 projectPropertiesDialog
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
._GetItemProject
(item
).GetFilename())
840 if projectPropertiesDialog
.ShowModal() == wx
.ID_OK
:
842 projectPropertiesDialog
.Destroy()
843 elif self
._IsItemFile
(item
):
844 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
845 filePropertiesService
.ShowPropertiesDialog(self
._GetItemFile
(item
))
848 def OnAddFileToProject(self
, event
):
849 if wx
.Platform
== "__WXMSW__" or wx
.Platform
== "__WXGTK__" or wx
.Platform
== "__WXMAC__":
852 for temp
in self
.GetDocumentManager()._templates
:
855 descr
= descr
+ _('|')
856 allfilter
= allfilter
+ _(';')
857 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
858 allfilter
= allfilter
+ temp
.GetFileFilter()
859 descr
= _("All") + _(" (") + allfilter
+ _(") |") + allfilter
+ _('|') + descr
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
860 descr
= descr
+ _("|") + _("Any (*.*) | *.*")
864 dialog
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), self
._lastDirectory
, "", descr
, wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
)
865 if dialog
.ShowModal() != wx
.ID_OK
:
867 paths
= dialog
.GetPaths()
870 paths
= wx
.FileSelector(_("Add Files"), self
._lastDirectory
, "", wildcard
= descr
, flags
= wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
, parent
=self
.GetFrame())
871 if type(paths
) == types
.StringType
:
874 self
._lastDirectory
= wx
.lib
.docview
.PathOnly(paths
[0])
875 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
))
876 self
.Activate(True) # after add, should put focus on project editor
879 def DoAddFilesToProject(self
, filenames
):
880 # method used by Drag-n-Drop to add files to current Project
881 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
))
884 def DoSelectFiles(self
, filenames
):
885 # method used by Drag-n-Drop to select files in current Project
886 for selection
in self
._treeCtrl
.GetSelections():
887 self
._treeCtrl
.SelectItem(selection
, False)
888 for file in filenames
:
889 item
= self
._GetFileItem
(longFileName
=file)
891 self
._treeCtrl
.SelectItem(item
, True)
892 self
._treeCtrl
.EnsureVisible(item
)
895 def DoSelectProject(self
, x
, y
):
896 # method used by Drag-n-Drop to set current Project based on cursor position
897 item
, flag
= self
._treeCtrl
.HitTest((x
,y
))
901 project
= self
._GetItemProject
(item
)
905 projectItem
= self
._GetProjectItem
(project
)
906 self
._treeCtrl
.UnselectAll()
907 self
._treeCtrl
.SelectItem(projectItem
)
911 def OnFocus(self
, event
):
912 wx
.GetApp().GetDocumentManager().ActivateView(self
)
916 def OnKillFocus(self
, event
):
917 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
918 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
919 if not self
._editingSoDontKillFocus
: # wxBug: This didn't used to happen, but now when you start to edit an item in a wxTreeCtrl it puts out a KILL_FOCUS event, so we need to detect it
920 childFrame
= wx
.GetApp().GetTopWindow().GetActiveChild()
922 childFrame
.Activate()
926 def OnRightClick(self
, event
):
928 if not self
._treeCtrl
.GetSelections():
930 if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]):
931 return # Don't do a menu if it's just the root item selected
933 if self
._HasFilesSelected
(): # Files context
934 menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection"))
935 menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True)
936 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
)
938 for item
in self
._treeCtrl
.GetSelections():
939 if self
._IsItemProcessModelFile
(item
):
940 itemIDs
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None]
942 else: # Project context
943 itemIDs
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None]
944 menuBar
= self
._GetParentFrame
().GetMenuBar()
945 itemIDs
= itemIDs
+ [wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
, None, ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
, None, wx
.ID_UNDO
, wx
.ID_REDO
, None, wx
.ID_CUT
, wx
.ID_COPY
, wx
.ID_PASTE
, wx
.ID_CLEAR
, None, wx
.ID_SELECTALL
, None, ProjectService
.RENAME_ID
]
946 for itemID
in itemIDs
:
948 menu
.AppendSeparator()
950 if itemID
== ProjectService
.RUN_SELECTED_PM_ID
:
951 menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process"))
952 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
)
953 elif itemID
== ProjectService
.REMOVE_FROM_PROJECT
:
954 menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project"))
955 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
)
956 wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
)
958 item
= menuBar
.FindItemById(itemID
)
960 menu
.Append(itemID
, item
.GetLabel())
961 self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY()))
964 def OnRunSelectedPM(self
, event
):
965 projectService
= wx
.GetApp().GetService(ProjectService
)
966 projectService
.OnRunProcessModel(event
, runSelected
=True)
968 def OnRename(self
, event
):
969 if self
._treeCtrl
.GetSelections():
970 self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0])
973 def OnBeginLabelEdit(self
, event
):
974 self
._editingSoDontKillFocus
= True
975 item
= event
.GetItem()
976 if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
):
980 def OnEndLabelEdit(self
, event
):
981 self
._editingSoDontKillFocus
= False
982 item
= event
.GetItem()
983 newName
= event
.GetLabel()
984 if not newName
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)):
987 if self
._IsItemFile
(item
):
988 oldFile
= self
._GetItemFile
(item
)
989 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
990 if not self
._GetItemProject
(item
).GetCommandProcessor().Submit(ProjectRenameFileCommand(self
.GetDocument(), oldFile
, newFile
)):
993 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0]))
994 elif self
._IsItemProject
(item
):
995 oldFile
= self
._GetItemProject
(item
).GetFilename()
996 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
997 if not self
._GetItemProject
(item
).GetCommandProcessor().Submit(ProjectRenameFileCommand(self
.GetDocument(), oldFile
, newFile
, True)):
1000 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
1004 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
1005 #fileDataObject = wx.FileDataObject()
1006 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
1007 if not wx
.TheClipboard
.IsOpened():
1008 if wx
.TheClipboard
.Open():
1009 fileDataObject
= wx
.FileDataObject()
1010 hasFilesInClipboard
= wx
.TheClipboard
.GetData(fileDataObject
)
1011 wx
.TheClipboard
.Close()
1013 hasFilesInClipboard
= False
1014 return hasFilesInClipboard
1017 def OnCut(self
, event
):
1018 if self
._AreSelectedItemsFromSameProject
():
1023 def OnCopy(self
, event
):
1024 fileDataObject
= wx
.FileDataObject()
1025 items
= self
._treeCtrl
.GetSelections()
1027 if self
._IsItemFile
(item
):
1028 file = self
._treeCtrl
.GetPyData(item
)
1029 fileDataObject
.AddFile(file)
1030 if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open():
1031 wx
.TheClipboard
.SetData(fileDataObject
)
1032 wx
.TheClipboard
.Close()
1035 def OnPaste(self
, event
):
1036 if wx
.TheClipboard
.Open():
1037 fileDataObject
= wx
.FileDataObject()
1038 if wx
.TheClipboard
.GetData(fileDataObject
):
1039 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames()))
1040 wx
.TheClipboard
.Close()
1043 def OnClear(self
, event
):
1044 if self
._AreSelectedItemsFromSameProject
():
1045 items
= self
._treeCtrl
.GetSelections()
1048 if self
._IsItemFile
(item
):
1049 files
.append(self
._GetItemFile
(item
))
1050 self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self
._GetItemProject
(items
[0]), files
))
1053 def OnKeyPressed(self
, event
):
1054 key
= event
.KeyCode()
1055 if key
== wx
.WXK_DELETE
:
1061 def OnSelectAll(self
, event
):
1062 project
= self
.GetDocument()
1064 self
._treeCtrl
.UnselectAll()
1065 for child
in self
._GetChildItems
(self
._GetProjectItem
(project
)):
1066 self
._treeCtrl
.SelectItem(child
)
1069 def OnOpenSelectionSDI(self
, event
):
1070 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1071 wx
.CallAfter(self
.OnOpenSelection
, None)
1074 def OnOpenSelection(self
, event
):
1077 items
= self
._treeCtrl
.GetSelections()
1079 if self
._IsItemFile
(item
):
1080 filepath
= self
._GetItemFile
(item
)
1081 if not os
.path
.exists(filepath
):
1082 msgTitle
= wx
.GetApp().GetAppName()
1084 msgTitle
= _("File Not Found")
1085 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1086 _("The file '%s' was not found in '%s'.\n\nWould you like to browse for the file?") % (wx
.lib
.docview
.FileNameFromPath(filepath
), wx
.lib
.docview
.PathOnly(filepath
)),
1090 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1092 findFile
= wx
.FileDialog(self
.GetFrame(),
1094 wx
.lib
.docview
.PathOnly(filepath
),
1095 wx
.lib
.docview
.FileNameFromPath(filepath
),
1098 if findFile
.ShowModal() == wx
.ID_OK
and findFile
.GetPath():
1099 newpath
= findFile
.GetPath()
1104 # update Project Model with new location
1105 self
.GetDocument().RemoveFile(filepath
)
1106 self
.GetDocument().AddFile(newpath
)
1109 doc
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
)
1111 except IOError, (code
, message
):
1112 msgTitle
= wx
.GetApp().GetAppName()
1114 msgTitle
= _("File Error")
1115 wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
),
1117 wx
.OK | wx
.ICON_EXCLAMATION
,
1121 #----------------------------------------------------------------------------
1122 # Convenience methods
1123 #----------------------------------------------------------------------------
1125 def _HasFiles(self
):
1126 if not self
._treeCtrl
:
1128 return self
._treeCtrl
.GetCount() > 1 # 1 item = root item, don't count as having files
1131 def _HasProjectsSelected(self
):
1132 if not self
._treeCtrl
:
1134 items
= self
._treeCtrl
.GetSelections()
1138 if self
._IsItemProject
(item
):
1143 def _HasFilesSelected(self
):
1144 if not self
._treeCtrl
:
1146 items
= self
._treeCtrl
.GetSelections()
1150 if not self
._IsItemFile
(item
):
1155 def _MakeProjectName(self
, project
):
1156 return project
.GetPrintableName()
1159 # Return the tree item for a project
1160 def _GetProjectItem(self
, project
):
1161 children
= self
._GetChildItems
(self
._treeCtrl
.GetRootItem())
1162 for child
in children
:
1163 if self
._treeCtrl
.GetPyData(child
) == project
:
1168 # Returns the project for an item, either for a project item or a file that is part of a project
1169 def _GetItemProject(self
, item
):
1170 if self
._IsItemRoot
(item
):
1172 if self
._IsItemProject
(item
):
1173 return self
._treeCtrl
.GetPyData(item
)
1174 if self
._IsItemFile
(item
):
1175 return self
._treeCtrl
.GetPyData(self
._treeCtrl
.GetItemParent(item
))
1179 def _GetItemFile(self
, item
):
1180 if self
._IsItemFile
(item
):
1181 return self
._treeCtrl
.GetPyData(item
)
1186 def _GetFileItem(self
, shortFileName
= None, longFileName
= None):
1187 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1190 project_children
= self
._GetChildItems
(self
._treeCtrl
.GetRootItem())
1191 for child
in project_children
:
1192 file_children
= self
._GetChildItems
(child
)
1193 for file_child
in file_children
:
1194 if self
._treeCtrl
.GetItemText(file_child
) == shortFileName
:
1198 project_children
= self
._GetChildItems
(self
._treeCtrl
.GetRootItem())
1199 for child
in project_children
:
1200 file_children
= self
._GetChildItems
(child
)
1201 for file_child
in file_children
:
1202 if self
._treeCtrl
.GetPyData(file_child
) == longFileName
:
1207 def GetFilePathFromTreeName(self
, shortFileName
):
1209 Returns the data object given a short (display) file name for a file. The data
1210 object should be the full path.
1212 return self
._GetItemFile
(self
._GetFileItem
(shortFileName
))
1215 def SelectFileInTree(self
, shortFileName
):
1216 item
= self
._GetFileItem
(shortFileName
)
1218 for selection
in self
._treeCtrl
.GetSelections():
1219 self
._treeCtrl
.SelectItem(selection
, False)
1220 self
._treeCtrl
.SelectItem(item
, True)
1221 self
._treeCtrl
.EnsureVisible(item
)
1224 def _IsItemRoot(self
, item
):
1225 return item
== self
._treeCtrl
.GetRootItem()
1228 def _IsItemProject(self
, item
):
1229 return isinstance(self
._treeCtrl
.GetPyData(item
), ProjectDocument
)
1232 def _IsItemFile(self
, item
):
1233 return isinstance(self
._treeCtrl
.GetPyData(item
), types
.StringTypes
)
1236 def _IsItemProcessModelFile(self
, item
):
1237 if ACTIVEGRID_BASE_IDE
:
1240 if isinstance(self
._treeCtrl
.GetPyData(item
), types
.StringTypes
):
1241 filename
= self
._treeCtrl
.GetPyData(item
)
1243 for template
in self
.GetDocumentManager().GetTemplates():
1244 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1245 ext
= template
.GetDefaultExtension()
1250 if filename
.endswith(ext
):
1256 def _AreSelectedItemsFromSameProject(self
):
1257 if not self
._treeCtrl
:
1259 items
= self
._treeCtrl
.GetSelections()
1262 project
= self
._GetItemProject
(items
[0])
1266 if not self
._IsItemFile
(item
):
1268 if self
._GetItemProject
(item
) != project
:
1273 def _GetChildItems(self
, parentItem
):
1275 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
)
1277 children
.append(child
)
1278 (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
)
1283 class ProjectFileDropTarget(wx
.FileDropTarget
):
1285 def __init__(self
, view
):
1286 wx
.FileDropTarget
.__init
__(self
)
1290 def OnDropFiles(self
, x
, y
, filenames
):
1291 if self
._view
.DoSelectProject(x
, y
):
1292 self
._view
.DoAddFilesToProject(filenames
)
1293 self
._view
.DoSelectFiles(filenames
)
1298 def OnDragOver(self
, x
, y
, default
):
1299 if self
._view
.DoSelectProject(x
,y
):
1304 class ProjectPropertiesDialog(wx
.Dialog
):
1307 def __init__(self
, parent
, filename
):
1308 wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size
= (310, 330))
1313 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
1315 notebook
= wx
.Notebook(self
, -1)
1316 tab
= wx
.Panel(notebook
, -1)
1318 gridSizer
= RowColSizer()
1320 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0)
1321 if os
.path
.isfile(filename
):
1322 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1)
1324 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0)
1325 gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1)
1327 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0)
1328 gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1)
1330 lineSizer
= wx
.BoxSizer(wx
.VERTICAL
) # let the line expand horizontally without vertical expansion
1331 lineSizer
.Add(wx
.StaticLine(tab
, -1, size
= (10,-1)), 0, wx
.EXPAND
)
1332 gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2)
1334 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0)
1335 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1)
1337 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0)
1338 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1)
1340 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0)
1341 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1)
1344 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1)
1346 # add a border around the inside of the tab
1347 spacerGrid
= wx
.BoxSizer(wx
.VERTICAL
)
1348 spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
);
1349 tab
.SetSizer(spacerGrid
)
1350 notebook
.AddPage(tab
, _("General"))
1351 if wx
.Platform
== "__WXMSW__":
1352 notebook
.SetPageSize((310,200))
1354 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1355 sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
)
1356 sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
)
1359 self
.SetDimensions(-1, -1, 310, -1, wx
.SIZE_USE_EXISTING
)
1360 self
.SetSizer(sizer
)
1364 class ProjectOptionsPanel(wx
.Panel
):
1367 def __init__(self
, parent
, id):
1368 wx
.Panel
.__init
__(self
, parent
, id)
1369 self
._useSashMessageShown
= False
1372 config
= wx
.ConfigBase_Get()
1373 self
._projSaveDocsCheckBox
= wx
.CheckBox(self
, -1, _("Remember open projects"))
1374 self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True))
1375 projectBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1376 projectSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1377 projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1378 self
._projShowWelcomeCheckBox
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog"))
1379 self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True))
1380 projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1381 projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
)
1382 self
.SetSizer(projectBorderSizer
)
1384 parent
.AddPage(self
, _("Project"))
1386 def OnUseSashSelect(self
, event
):
1387 if not self
._useSashMessageShown
:
1388 msgTitle
= wx
.GetApp().GetAppName()
1390 msgTitle
= _("Document Options")
1391 wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1393 wx
.OK | wx
.ICON_INFORMATION
,
1395 self
._useSashMessageShown
= True
1398 def OnOK(self
, optionsDialog
):
1399 config
= wx
.ConfigBase_Get()
1400 config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue())
1401 config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue())
1404 class ProjectService(Service
.Service
):
1406 #----------------------------------------------------------------------------
1408 #----------------------------------------------------------------------------
1409 SHOW_WINDOW
= wx
.NewId() # keep this line for each subclass, need unique ID for each Service
1410 RUNPM_ID
= wx
.NewId()
1411 RUN_SELECTED_PM_ID
= wx
.NewId()
1412 RUN_CURRENT_PM_ID
= wx
.NewId()
1413 ADD_FILES_TO_PROJECT_ID
= wx
.NewId()
1414 ADD_CURRENT_FILE_TO_PROJECT_ID
= wx
.NewId()
1415 RENAME_ID
= wx
.NewId()
1416 OPEN_SELECTION_ID
= wx
.NewId()
1417 REMOVE_FROM_PROJECT
= wx
.NewId()
1420 #----------------------------------------------------------------------------
1421 # Overridden methods
1422 #----------------------------------------------------------------------------
1424 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1425 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1426 self
._runHandlers
= []
1427 self
._suppressOpenProjectMessages
= False
1430 def _CreateView(self
):
1431 return ProjectView(self
)
1434 def ShowWindow(self
, show
= True):
1435 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1436 Service
.Service
.ShowWindow(self
, show
)
1439 project
= self
.GetView().GetDocument()
1441 self
.OpenSavedProjects()
1444 #----------------------------------------------------------------------------
1445 # Service specific methods
1446 #----------------------------------------------------------------------------
1448 def GetSuppressOpenProjectMessages(self
):
1449 return self
._suppressOpenProjectMessages
1452 def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
):
1453 self
._suppressOpenProjectMessages
= suppressOpenProjectMessages
1456 def GetRunHandlers(self
):
1457 return self
._runHandlers
1460 def AddRunHandler(self
, runHandler
):
1461 self
._runHandlers
.append(runHandler
)
1464 def RemoveRunHandler(self
, runHandler
):
1465 self
._runHandlers
.remove(runHandler
)
1468 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1469 Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
1471 config
= wx
.ConfigBase_Get()
1473 projectMenu
= wx
.Menu()
1475 ## accelTable = wx.AcceleratorTable([
1476 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1478 ## frame.SetAcceleratorTable(accelTable)
1479 isProjectDocument
= document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1480 if wx
.GetApp().IsMDI() or isProjectDocument
:
1481 if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
):
1482 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("&Add Files to Project..."), _("Adds a document to the current project"))
1483 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1484 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1485 if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
):
1486 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1487 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
)
1488 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1489 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
1490 menuBar
.Insert(viewMenuIndex
+ 1, projectMenu
, _("&Project"))
1491 editMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit")))
1492 if not menuBar
.FindItemById(ProjectService
.RENAME_ID
):
1493 editMenu
.AppendSeparator()
1494 editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item"))
1495 wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
)
1496 wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
)
1501 def OnCloseFrame(self
, event
):
1502 if not self
.GetView():
1505 if wx
.GetApp().IsMDI():
1506 # close all non-project documents first
1507 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1508 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1509 if not self
.GetDocumentManager().CloseDocument(document
, False):
1512 # write project config afterwards because user may change filenames on closing of new documents
1513 self
.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1515 # close all project documents after closing other documents
1516 # because user may save a new document with a new name or cancel closing a document
1517 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1518 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1519 if not document
.OnSaveModified():
1522 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1523 elif self
.GetView() == event
.GetEventObject().GetView():
1528 #----------------------------------------------------------------------------
1529 # Event Processing Methods
1530 #----------------------------------------------------------------------------
1532 def ProcessEventBeforeWindows(self
, event
):
1534 if id == wx
.ID_CLOSE_ALL
:
1535 self
.OnFileCloseAll(event
)
1540 def ProcessEvent(self
, event
):
1541 if Service
.Service
.ProcessEvent(self
, event
):
1545 if id == ProjectService
.RUN_SELECTED_PM_ID
:
1546 self
.OnRunProcessModel(event
, runSelected
=True)
1548 elif id == ProjectService
.RUN_CURRENT_PM_ID
:
1549 self
.OnRunProcessModel(event
, runCurrentFile
=True)
1551 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1552 self
.OnAddCurrentFileToProject(event
)
1554 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1556 return self
.GetView().ProcessEvent(event
)
1563 def ProcessUpdateUIEvent(self
, event
):
1564 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1568 if id == ProjectService
.RUNPM_ID
or id == ProjectService
.RUN_SELECTED_PM_ID
or id == ProjectService
.RUN_CURRENT_PM_ID
:
1569 event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
())
1571 elif id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
1574 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1575 event
.Enable(self
._CanAddCurrentFileToProject
())
1577 elif id == ProjectService
.RENAME_ID
:
1580 elif id == ProjectService
.OPEN_SELECTION_ID
:
1583 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1585 return self
.GetView().ProcessUpdateUIEvent(event
)
1592 def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False):
1593 project
= self
.GetView().GetDocument()
1597 for template
in self
.GetDocumentManager().GetTemplates():
1598 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1599 ext
= template
.GetDefaultExtension()
1604 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1608 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1610 if doc
.GetFilename() in files
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1611 if not doc
.GetProcessModel().beginProcess
:
1612 wx
.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1615 filesModified
= False
1617 if doc
.IsModified():
1618 filesModified
= True
1621 frame
= self
.GetView().GetFrame()
1622 yesNoMsg
= wx
.MessageDialog(frame
,
1623 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1627 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1628 wx
.GetTopLevelParent(frame
).OnFileSaveAll(None)
1631 fileToRun
= self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1633 fileToRun
= self
.GetView().GetSelectedFile()
1634 elif len(files
) > 1:
1635 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
1636 strings
= map(lambda file: os
.path
.basename(file), files
)
1637 res
= wx
.GetSingleChoiceIndex(_("Select a process to run:"),
1640 project
.GetFirstView()._GetParentFrame
())
1643 fileToRun
= files
[res
]
1645 fileToRun
= files
[0]
1647 self
.RunProcessModel(fileToRun
)
1650 def RunProcessModel(self
, fileToRun
):
1651 for runHandler
in self
.GetRunHandlers():
1652 if runHandler
.RunProjectFile(fileToRun
):
1654 os
.system('"' + fileToRun
+ '"')
1657 def _HasProcessModel(self
):
1658 project
= self
.GetView().GetDocument()
1662 for template
in self
.GetDocumentManager().GetTemplates():
1663 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1664 ext
= template
.GetDefaultExtension()
1669 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1679 def _HasOpenedProjects(self
):
1680 for document
in self
.GetDocumentManager().GetDocuments():
1681 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1686 def _HasCurrentFile(self
):
1687 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1691 def _CanAddCurrentFileToProject(self
):
1692 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1695 if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1697 if not currentDoc
._savedYet
:
1699 for document
in self
.GetDocumentManager().GetDocuments():
1700 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1702 return False # There are no documents open
1705 def GetFilesFromCurrentProject(self
):
1706 view
= self
.GetView()
1708 project
= view
.GetDocument()
1710 return project
.GetFiles()
1714 def GetCurrentProject(self
):
1715 view
= self
.GetView()
1717 return view
.GetDocument()
1721 def FindProjectByFile(self
, filename
):
1722 for document
in self
.GetDocumentManager().GetDocuments():
1723 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1724 if document
.GetFilename() == filename
:
1726 elif document
.IsFileInProject(filename
):
1731 def GetCurrentProjectNames(self
):
1733 for document
in self
.GetDocumentManager().GetDocuments():
1734 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1735 projects
.append(document
)
1738 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
1739 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
1742 def OnAddCurrentFileToProject(self
, event
):
1743 if not self
._CanAddCurrentFileToProject
():
1746 for document
in self
.GetDocumentManager().GetDocuments():
1747 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1748 projects
.append(document
)
1751 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
1752 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
1753 res
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"),
1754 _("Add to Project"),
1756 self
.GetDocumentManager().FindSuitableParent())
1759 file = self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1760 projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file]))
1761 self
.GetView().Activate(True) # after add, should put focus on project editor
1764 def OnFileCloseAll(self
, event
):
1765 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1766 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1767 if not self
.GetDocumentManager().CloseDocument(document
, False):
1769 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
1772 def OpenSavedProjects(self
):
1773 config
= wx
.ConfigBase_Get()
1775 if config
.ReadInt("ProjectSaveDocs", True):
1776 docString
= config
.Read("ProjectSavedDocs")
1779 for fileName
in eval(docString
):
1780 if isinstance(fileName
, types
.StringTypes
):
1781 if os
.path
.exists(fileName
):
1782 doc
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
)
1786 expandedString
= config
.Read("ProjectExpandedSavedDocs")
1788 view
= doc
.GetFirstView()
1789 view
.SetExpandedProjects(eval(expandedString
))
1792 #----------------------------------------------------------------------------
1793 # Icon Bitmaps - generated by encode_bitmaps.py
1794 #----------------------------------------------------------------------------
1795 from wx
import ImageFromStream
, BitmapFromImage
1796 from wx
import EmptyIcon
1800 def getProjectData():
1802 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1803 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1804 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
1805 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
1806 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
1807 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
1809 def getProjectBitmap():
1810 return BitmapFromImage(getProjectImage())
1812 def getProjectImage():
1813 stream
= cStringIO
.StringIO(getProjectData())
1814 return ImageFromStream(stream
)
1816 def getProjectIcon():
1818 icon
.CopyFromBitmap(getProjectBitmap())
1822 #----------------------------------------------------------------------------
1826 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
1827 \x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\
1828 \x85IDATX\x85\xed\x97\xc9\n\xc0 \x0cD3\xda\xff\xffcMo\x96Z\xc4\xa5\x91\x14:9\
1829 \x8a\xe8\xcb\xd3\xb8\x00!\x8ag\x04\xd7\xd9E\xe4\xa8\x1b4'}3 B\xc4L\x7fs\x03\
1830 \xb3\t<\x0c\x94\x81tN\x04p%\xae9\xe9\xa8\x89m{`\xd4\x84\xfd\x12\xa8\x16{#\
1831 \x10\xdb\xab\xa0\x07a\x0e\x00\xe0\xb6\x1fz\x10\xdf;\x07V\xa3U5\xb5\x8d:\xdc\
1832 \r\x10\x80\x00\x04 \x00\x01\x08@\x80\xe6{\xa0w\x8f[\x85\xbb\x01\xfc\xfeoH\
1833 \x80\x13>\xf9(3zH\x1e\xfb\x00\x00\x00\x00IEND\xaeB`\x82"
1836 def getBlankBitmap():
1837 return BitmapFromImage(getBlankImage())
1839 def getBlankImage():
1840 stream
= cStringIO
.StringIO(getBlankData())
1841 return ImageFromStream(stream
)
1845 icon
.CopyFromBitmap(getBlankBitmap())