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 activegrid
.util
.objutils
27 from IDE
import ACTIVEGRID_BASE_IDE
28 if not ACTIVEGRID_BASE_IDE
:
29 import ProcessModelEditor
30 from SVNService
import SVN_INSTALLED
34 if wx
.Platform
== '__WXMSW__':
40 #----------------------------------------------------------------------------
42 #----------------------------------------------------------------------------
47 #----------------------------------------------------------------------------
48 # XML Marshalling Methods
49 #----------------------------------------------------------------------------
52 return activegrid
.util
.objutils
.defaultLoad(fileObject
)
54 def save(fileObject
, projectModel
):
55 activegrid
.util
.objutils
.defaultSave(fileObject
, projectModel
, prettyPrint
=True)
58 #----------------------------------------------------------------------------
60 #----------------------------------------------------------------------------
63 __xmlname__
= "projectmodel"
64 __xmlrename__
= { "_files":"files"}
74 class ProjectDocument(wx
.lib
.docview
.Document
):
78 wx
.lib
.docview
.Document
.__init
__(self
)
79 self
._projectModel
= ProjectModel()
83 return self
._projectModel
86 def OnCreate(self
, path
, flags
):
87 projectService
= wx
.GetApp().GetService(ProjectService
)
88 if projectService
.GetView():
89 # All project documents share the same view.
90 view
= projectService
.GetView()
93 if view
.GetDocument():
94 # All project documents need to share the same command processor,
95 # to enable redo/undo of cross project document commands
96 cmdProcessor
= view
.GetDocument().GetCommandProcessor()
98 self
.SetCommandProcessor(cmdProcessor
)
100 view
= self
.GetDocumentTemplate().CreateView(self
, flags
)
101 projectService
.SetView(view
)
107 def LoadObject(self
, fileObject
):
108 self
._projectModel
= activegrid
.tool
.ProjectEditor
.load(fileObject
)
109 self
._projectModel
._files
= self
.RelativeToAbsPath(self
._projectModel
._files
)
113 def SaveObject(self
, fileObject
):
114 absPath
= self
._projectModel
._files
115 self
._projectModel
._files
= self
.AbsToRelativePath(absPath
) # temporarily change it to relative paths for saving
116 activegrid
.tool
.ProjectEditor
.save(fileObject
, self
._projectModel
)
117 self
._projectModel
._files
= absPath
# swap it back to absolute path
121 def AbsToRelativePath(self
, paths
):
122 curPath
= os
.path
.dirname(self
.GetFilename())
123 curPathLen
= len(curPath
)
127 if path
.startswith(curPath
):
128 path
= "." + path
[curPathLen
:] # use relative path
130 path
= path
.replace(os
.sep
, '/', -1) # always save out with '/' as path separator for cross-platform compatibility.
132 pass # use absolute path
133 newFilePaths
.append(path
)
137 def RelativeToAbsPath(self
, paths
):
140 if path
.startswith("."): # relative to project file
141 curPath
= os
.path
.dirname(self
.GetFilename())
142 path
= os
.path
.normpath(os
.path
.join(curPath
, path
))
143 newFilePaths
.append(path
)
147 def OnOpenDocument(self
, filename
):
148 view
= self
.GetFirstView()
149 frame
= view
.GetFrame()
151 if not os
.path
.exists(filename
):
152 wx
.GetApp().CloseSplash()
153 msgTitle
= wx
.GetApp().GetAppName()
155 msgTitle
= _("File Error")
156 wx
.MessageBox(_("Could not find '%s'.") % filename
,
158 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
160 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
162 fileObject
= file(filename
, 'r')
164 self
.LoadObject(fileObject
)
166 wx
.GetApp().CloseSplash()
167 msgTitle
= wx
.GetApp().GetAppName()
169 msgTitle
= _("File Error")
170 wx
.MessageBox(_("Could not open '%s'. %s") % (wx
.lib
.docview
.FileNameFromPath(filename
), sys
.exc_value
),
172 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
174 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
177 self
.SetFilename(filename
, True)
178 view
.AddProjectToView(self
)
179 self
.SetDocumentModificationDate()
180 self
.UpdateAllViews()
181 self
._savedYet
= True
186 def AddFile(self
, file):
187 return self
.AddFiles([file])
190 def AddFiles(self
, files
):
191 notAlreadyThereFiles
= filter(lambda x
: x
not in self
._projectModel
._files
, files
) # Filter to the files that are not already in the project
192 if len(notAlreadyThereFiles
) == 0:
193 self
.UpdateAllViews(hint
= ("select", self
, files
))
196 self
._projectModel
._files
= self
._projectModel
._files
+ notAlreadyThereFiles
197 self
.UpdateAllViews(hint
= ("add", self
, notAlreadyThereFiles
))
202 def RemoveFile(self
, file):
203 return self
.RemoveFiles([file])
206 def RemoveFiles(self
, files
):
208 self
._projectModel
._files
.remove(file)
209 self
.UpdateAllViews(hint
= ("remove", self
, files
))
214 def RenameFile(self
, oldFile
, newFile
, isProject
= False):
216 if oldFile
== newFile
:
219 # projects don't have to exist yet, so not required to rename old file,
220 # but files must exist, so we'll try to rename and allow exceptions to occur if can't.
221 if not isProject
or (isProject
and os
.path
.exists(oldFile
)):
222 os
.rename(oldFile
, newFile
)
225 documents
= self
.GetDocumentManager().GetDocuments()
226 for document
in documents
:
227 if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFile
): # If the renamed document is open, update it
228 document
.SetFilename(newFile
)
229 document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFile
))
230 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
232 self
.RemoveFile(oldFile
)
233 self
.AddFile(newFile
)
234 documents
= self
.GetDocumentManager().GetDocuments()
235 for document
in documents
:
236 if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFile
): # If the renamed document is open, update it
237 document
.SetFilename(newFile
, notifyViews
= True)
238 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
240 except OSError, (code
, message
):
241 msgTitle
= wx
.GetApp().GetAppName()
243 msgTitle
= _("File Error")
244 wx
.MessageBox("Could not rename '%s'. '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFile
), message
),
246 wx
.OK | wx
.ICON_EXCLAMATION
,
247 self
.GetFirstView().GetFrame())
252 return self
._projectModel
._files
255 def IsFileInProject(self
, filename
):
256 return filename
in self
.GetFiles()
259 class NewProjectWizard(Wizard
.BaseWizard
):
261 WIZTITLE
= _("New Project Wizard")
263 def __init__(self
, parent
):
264 self
._parent
= parent
265 self
._fullProjectPath
= None
266 Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
)
267 self
._projectLocationPage
= self
.CreateProjectLocation(self
)
268 wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
)
271 def CreateProjectLocation(self
,wizard
):
272 page
= Wizard
.TitledWizardPage(wizard
, _("Project File Location"))
274 page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n")))
275 self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation
= UICommon
.CreateDirectoryControl(page
, _("File Name:"), _("Directory:"), _("agp"), startingDirectory
=os
.getcwd())
276 page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
)
279 wizard
.FitToPage(page
)
283 def RunWizard(self
, existingTables
= None, existingRelationships
= None):
284 status
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
)
286 docManager
= wx
.GetApp().GetTopWindow().GetDocumentManager()
287 if os
.path
.exists(self
._fullProjectPath
):
288 # What if the document is already open and we're overwriting it?
289 documents
= docManager
.GetDocuments()
290 for document
in documents
:
291 if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(self
._fullProjectPath
): # If the renamed document is open, update it
292 document
.DeleteAllViews()
294 os
.remove(self
._fullProjectPath
)
296 for template
in docManager
.GetTemplates():
297 if template
.GetDocumentType() == ProjectDocument
:
298 doc
= template
.CreateDocument(self
._fullProjectPath
, flags
= wx
.lib
.docview
.DOC_NEW
)
299 doc
.OnSaveDocument(self
._fullProjectPath
)
300 view
= doc
.GetFirstView()
301 view
.AddProjectToView(doc
)
308 def OnWizPageChanging(self
, event
):
309 if event
.GetDirection(): # It's going forwards
310 if event
.GetPage() == self
._projectLocationPage
:
311 if not self
._fileValidation
():
314 self
._fullProjectPath
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(),'.agp'))
318 def OnShowCreatePages(self
):
320 import DataModelEditor
321 requestedPos
= self
.GetPositionTuple()
322 projectService
= wx
.GetApp().GetService(ProjectService
)
323 projectView
= projectService
.GetView()
325 wiz
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
)
326 if wiz
.RunWizard(dontDestroy
=True):
327 self
._schemaName
.SetValue(wiz
.GetSchemaFileName())
332 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
):
335 def CreateDocument(self
, path
, flags
):
337 return wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
)
339 wiz
= NewProjectWizard(wx
.GetApp().GetTopWindow())
342 return None # never return the doc, otherwise docview will think it is a new file and rename it
345 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
):
348 def __init__(self
, projectDoc
, files
):
349 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
350 self
._projectDoc
= projectDoc
355 if len(self
._files
) == 1:
356 return _("Add File %s") % os
.path
.basename(self
._files
[0])
358 return _("Add Files")
362 return self
._projectDoc
.AddFiles(self
._files
)
366 return self
._projectDoc
.RemoveFiles(self
._files
)
369 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
):
372 def __init__(self
, files
):
373 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
378 if len(self
._files
) == 1:
379 return _("Remove File %s") % os
.path
.basename((self
._files
[0])[1])
381 return _("Remove Files")
387 for data
in self
._files
:
388 proj
, filename
= data
389 if proj
not in projects
:
390 projects
.append(proj
)
391 for project
in projects
:
393 for data
in self
._files
:
394 proj
, filename
= data
396 files
.append(filename
)
397 status
= project
.RemoveFiles(files
) or status
404 for data
in self
._files
:
405 proj
, filename
= data
406 if proj
not in projects
:
407 projects
.append(proj
)
408 for project
in projects
:
410 for data
in self
._files
:
411 proj
, filename
= data
413 files
.append(filename
)
414 status
= project
.AddFiles(files
) or status
418 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
):
421 def __init__(self
, projectDoc
, oldFile
, newFile
, isProject
= False):
422 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
423 self
._projectDoc
= projectDoc
424 self
._oldFile
= oldFile
425 self
._newFile
= newFile
426 self
._isProject
= isProject
430 return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFile
), os
.path
.basename(self
._newFile
))
434 return self
._projectDoc
.RenameFile(self
._oldFile
, self
._newFile
, self
._isProject
)
438 return self
._projectDoc
.RenameFile(self
._newFile
, self
._oldFile
, self
._isProject
)
441 class ProjectTreeCtrl(wx
.TreeCtrl
):
444 #----------------------------------------------------------------------------
446 #----------------------------------------------------------------------------
448 def __init__(self
, parent
, id, style
):
449 wx
.TreeCtrl
.__init
__(self
, parent
, id, style
= style
)
451 templates
= wx
.GetApp().GetDocumentManager().GetTemplates()
452 iconList
= wx
.ImageList(16, 16, initialCount
= len(templates
))
453 self
._iconIndexLookup
= []
454 for template
in templates
:
455 icon
= template
.GetIcon()
457 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16:
460 if wx
.GetApp().GetDebug():
461 print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
462 iconIndex
= iconList
.AddIcon(icon
)
463 self
._iconIndexLookup
.append((template
, iconIndex
))
465 icon
= getBlankIcon()
466 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16:
469 if wx
.GetApp().GetDebug():
470 print "Warning: getBlankIcon isn't 16x16, not crossplatform"
471 self
._blankIconIndex
= iconList
.AddIcon(icon
)
472 self
.AssignImageList(iconList
)
475 def OnCompareItems(self
, item1
, item2
):
476 return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower())
479 def AppendItem(self
, parent
, filepath
):
480 item
= wx
.TreeCtrl
.AppendItem(self
, parent
, filepath
)
483 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filepath
)
484 if not template
and parent
== self
.GetRootItem(): # If the parent is a root it's a new project
485 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
487 for t
, iconIndex
in self
._iconIndexLookup
:
489 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
)
490 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
)
491 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Selected
)
496 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
)
497 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
)
498 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Selected
)
503 #----------------------------------------------------------------------------
505 #----------------------------------------------------------------------------
507 def SetData(self
, item
, longFilename
, projectDoc
=None):
508 self
.SetPyData(item
, (longFilename
, projectDoc
))
511 def GetData(self
, item
):
512 """ returns longFilename and optional
514 data
= self
.GetPyData(item
)
520 def GetLongFilename(self
, item
):
521 return self
.GetData(item
)[0]
524 def GetProjectDoc(self
, item
):
525 return self
.GetData(item
)[1]
528 class ProjectView(wx
.lib
.docview
.View
):
531 #----------------------------------------------------------------------------
533 #----------------------------------------------------------------------------
535 def __init__(self
, service
= None):
536 wx
.lib
.docview
.View
.__init
__(self
)
537 self
._service
= service
# not used, but kept to match other Services
538 self
._treeCtrl
= None
539 self
._editingSoDontKillFocus
= False
540 self
._checkEditMenu
= True
544 projectService
= wx
.GetApp().GetService(ProjectService
)
546 projectService
.SetView(None)
547 wx
.lib
.docview
.View
.Destroy(self
)
550 def GetDocument(self
):
551 if not self
._treeCtrl
:
554 items
= self
._treeCtrl
.GetSelections()
555 if not items
: # No selection, so just return first project
556 item
= self
._treeCtrl
.GetFirstVisibleItem()
558 return self
._GetItemProject
(item
)
563 project
= self
._GetItemProject
(item
)
570 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
571 return wx
.GetApp().GetDocumentManager()
574 def OnChangeFilename(self
):
576 title
= _("Projects")
577 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
578 title
= title
+ " - " + wx
.GetApp().GetAppName()
579 self
.GetFrame().SetTitle(title
)
580 project
= self
.GetDocument()
582 projectItem
= self
._GetProjectItem
(project
)
583 name
= self
._treeCtrl
.GetItemText(self
._GetProjectItem
(project
))
584 name2
= self
._MakeProjectName
(project
)
586 self
._treeCtrl
.SetItemText(projectItem
, name2
)
587 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
590 def Activate(self
, activate
= True):
591 if not wx
.GetApp().IsMDI():
592 if activate
and not self
.IsShown():
596 wx
.lib
.docview
.View
.Activate(self
, activate
= activate
)
597 if activate
and self
._treeCtrl
:
598 self
._treeCtrl
.SetFocus()
601 def OnCreate(self
, doc
, flags
):
602 config
= wx
.ConfigBase_Get()
603 if wx
.GetApp().IsMDI():
604 self
._embeddedWindow
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
)
605 self
.SetFrame(self
._embeddedWindow
)
606 frame
= self
._embeddedWindow
608 self
._embeddedWindow
= None
609 pos
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1)
610 # make sure frame is visible
611 screenWidth
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
)
612 screenHeight
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
)
613 if pos
[0] < 0 or pos
[0] >= screenWidth
or pos
[1] < 0 or pos
[1] >= screenHeight
:
614 pos
= wx
.DefaultPosition
616 size
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1))
618 title
= _("Projects")
619 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
620 title
= title
+ " - " + wx
.GetApp().GetAppName()
622 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title
= title
, pos
= pos
, size
= size
)
623 if config
.ReadInt("ProjectFrameMaximized", False):
626 sizer
= wx
.BoxSizer()
627 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
)
628 self
._treeCtrl
.AddRoot(_("Projects"))
629 wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
)
630 wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
)
632 if self
._embeddedWindow
:
633 sizer
.Add(self
._treeCtrl
)
636 sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
, 0)
637 frame
.SetSizer(sizer
)
641 if wx
.GetApp().IsMDI():
642 wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
)
643 wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
)
645 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
646 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
)
648 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
)
649 wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
)
650 wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
)
651 wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
)
652 wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
)
653 # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
655 # drag-and-drop support
656 dt
= ProjectFileDropTarget(self
)
657 self
._treeCtrl
.SetDropTarget(dt
)
662 def OnBeginDrag(self
, event
):
663 item
= event
.GetItem()
665 if item
== self
._treeCtrl
.GetRootItem():
667 self
._draggingItem
= item
671 def OnEndDrag(self
, event
):
672 item
= event
.GetItem()
674 # don't allow object to be dragged to itself
675 if item
== self
._draggingItem
:
678 rootItem
= self
._treeCtrl
.GetRootItem()
680 # don't let object replace root view
682 wx
.MessageBox(_("Cannot replace root view with item."))
685 # don't allow object to be dragged to a direct descendant
686 ancestor
= self
._treeCtrl
.GetItemParent(item
)
687 while ancestor
!= rootItem
:
688 if ancestor
== self
._draggingItem
:
689 wx
.MessageBox(_("Cannot make item direct descendant of self."))
692 ancestor
= self
._treeCtrl
.GetItemParent(ancestor
)
694 if self
._treeCtrl
.GetItemParent(item
) == self
._treeCtrl
.GetItemParent(self
._draggingItem
):
695 # put it in same folder as it was originally, no-op.
697 if item
== self
._treeCtrl
.GetItemParent(self
._draggingItem
):
698 # put it in same folder as it was originally, no-op.
701 self
.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self
, item
, self
._draggingItem
))
704 def WriteProjectConfig(self
):
705 frame
= self
.GetFrame()
706 config
= wx
.ConfigBase_Get()
707 if frame
and not self
._embeddedWindow
:
708 if not frame
.IsMaximized():
709 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0])
710 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1])
711 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0])
712 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1])
713 config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized())
715 if config
.ReadInt("ProjectSaveDocs", True):
716 projectFileNames
= []
719 for projectItem
in self
._GetChildItems
(self
._treeCtrl
.GetRootItem()):
720 project
= self
._GetItemProject
(projectItem
)
721 if not project
.OnSaveModified():
723 if project
.GetDocumentSaved(): # Might be a new document and "No" selected to save it
724 projectFileNames
.append(str(project
.GetFilename()))
725 projectExpanded
.append(self
._treeCtrl
.IsExpanded(projectItem
))
726 config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__())
727 config
.Write("ProjectExpandedSavedDocs", projectExpanded
.__repr
__())
730 def OnClose(self
, deleteWindow
= True):
731 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
732 self
.WriteProjectConfig()
733 project
= self
.GetDocument()
736 if not self
.GetDocument().Close():
740 projectItem
= self
._GetProjectItem
(project
)
742 self
._treeCtrl
.Delete(projectItem
)
743 # We don't need to delete the window since it is a floater/embedded
747 def _GetParentFrame(self
):
748 return wx
.GetTopLevelParent(self
.GetFrame())
751 def OnUpdate(self
, sender
= None, hint
= None):
752 wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
)
755 projectItem
= self
._GetProjectItem
(hint
[1])
757 self
._treeCtrl
.UnselectAll()
758 self
._treeCtrl
.Expand(projectItem
)
761 item
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
762 self
._treeCtrl
.SetData(item
, file)
763 self
._treeCtrl
.SelectItem(item
)
764 self
._treeCtrl
.EnsureVisible(item
)
765 self
._treeCtrl
.SortChildren(projectItem
)
767 self
._treeCtrl
.EnsureVisible(item
) # need to be called after SortChildren
768 elif hint
[0] == "remove":
769 projectItem
= self
._GetProjectItem
(hint
[1])
771 self
._treeCtrl
.UnselectAll()
772 children
= self
._GetChildItems
(projectItem
)
773 for child
in children
:
774 if self
._GetItemFile
(child
) in files
:
775 self
._treeCtrl
.Delete(child
)
776 elif hint
[0] == "select":
777 projectItem
= self
._GetProjectItem
(hint
[1])
779 self
._treeCtrl
.UnselectAll()
780 children
= self
._GetChildItems
(projectItem
)
781 for child
in children
:
782 if self
._GetItemFile
(child
) in files
:
783 self
._treeCtrl
.SelectItem(child
)
784 self
._treeCtrl
.EnsureVisible(child
)
785 elif hint
[0] == "rename":
786 projectItem
= self
._GetProjectItem
(hint
[1])
787 self
._treeCtrl
.SetItemText(projectItem
, os
.path
.basename(hint
[2]))
790 def ProcessEvent(self
, event
):
792 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
793 self
.OnAddFileToProject(event
)
795 elif id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
:
796 self
.OnAddDirToProject(event
)
798 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
799 return False # Implement this one in the service
800 elif id == ProjectService
.RENAME_ID
:
803 elif id == ProjectService
.DELETE_FILE_ID
:
804 self
.OnDeleteFile(event
)
806 elif id == wx
.ID_CUT
:
809 elif id == wx
.ID_COPY
:
812 elif id == wx
.ID_PASTE
:
815 elif (id == wx
.ID_CLEAR
816 or id == ProjectService
.REMOVE_FROM_PROJECT
):
819 elif id == wx
.ID_SELECTALL
:
820 self
.OnSelectAll(event
)
822 elif id == ProjectService
.OPEN_SELECTION_ID
:
823 self
.OnOpenSelection(event
)
825 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
826 self
.OnProperties(event
)
832 def ProcessUpdateUIEvent(self
, event
):
833 # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
834 if self
._checkEditMenu
:
835 doc
= self
.GetDocument()
836 if doc
and not doc
.GetCommandProcessor().GetEditMenu():
837 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
838 self
._checkEditMenu
= False
843 or id == ProjectService
.RENAME_ID
844 or id == ProjectService
.ADD_FILES_TO_PROJECT_ID
845 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
846 or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
):
847 event
.Enable(self
._HasSelection
())
849 elif id == ProjectService
.DELETE_FILE_ID
:
850 event
.Enable(len(self
.GetSelectedFiles()) > 0)
852 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
855 elif id == wx
.ID_PASTE
:
856 event
.Enable(self
.CanPaste())
858 elif id == wx
.ID_SELECTALL
:
859 event
.Enable(self
._HasFiles
())
861 elif (id == wx
.ID_CLEAR
862 or id == ProjectService
.REMOVE_FROM_PROJECT
863 or id == ProjectService
.OPEN_SELECTION_ID
):
864 event
.Enable(self
._HasFilesSelected
())
866 elif (id == wx
.ID_PREVIEW
867 or id == wx
.ID_PRINT
):
873 #----------------------------------------------------------------------------
875 #----------------------------------------------------------------------------
878 if not self
.GetFrame():
880 return self
.GetFrame().IsShown()
887 def Show(self
, show
= True):
888 self
.GetFrame().Show(show
)
889 if wx
.GetApp().IsMDI():
890 mdiParentFrame
= wx
.GetApp().GetTopWindow()
891 mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
)
894 #----------------------------------------------------------------------------
895 # Methods for ProjectDocument and ProjectService to call
896 #----------------------------------------------------------------------------
898 def SetExpandedProjects(self
, expandedProjects
):
899 self
._treeCtrl
.UnselectAll()
901 for i
, item
in enumerate(self
._GetChildItems
(self
._treeCtrl
.GetRootItem())):
905 if expandedProjects
[i
]:
906 self
._treeCtrl
.Expand(item
)
908 self
._treeCtrl
.Collapse(item
)
911 self
._treeCtrl
.EnsureVisible(firstItem
)
914 def GetSelectedFile(self
):
915 for item
in self
._treeCtrl
.GetSelections():
916 return self
._GetItemFile
(item
)
919 def GetSelectedFiles(self
):
921 for item
in self
._treeCtrl
.GetSelections():
922 filename
= self
._GetItemFile
(item
)
923 if filename
and filename
not in filenames
:
924 filenames
.append(filename
)
928 def GetSelectedProjects(self
):
930 for item
in self
._treeCtrl
.GetSelections():
931 if self
._IsItemProject
(item
):
932 filename
= self
._treeCtrl
.GetLongFilename(item
)
933 if filename
and filename
not in filenames
:
934 filenames
.append(filename
)
938 def AddProjectToView(self
, document
):
939 rootItem
= self
._treeCtrl
.GetRootItem()
940 projectItem
= self
._treeCtrl
.AppendItem(rootItem
, self
._MakeProjectName
(document
))
941 self
._treeCtrl
.SetData(projectItem
, document
.GetFilename(), document
)
942 for file in document
.GetFiles():
943 fileItem
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
944 self
._treeCtrl
.SetData(fileItem
, file)
945 self
._treeCtrl
.SortChildren(rootItem
)
946 self
._treeCtrl
.SortChildren(projectItem
)
947 self
._treeCtrl
.UnselectAll()
948 self
._treeCtrl
.Expand(projectItem
)
949 self
._treeCtrl
.SelectItem(projectItem
)
950 if self
._embeddedWindow
:
951 document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
955 winWithFocus
= wx
.Window
.FindFocus()
959 if winWithFocus
== self
._treeCtrl
:
961 winWithFocus
= winWithFocus
.GetParent()
965 #----------------------------------------------------------------------------
967 #----------------------------------------------------------------------------
969 def OnProperties(self
, event
):
970 items
= self
._treeCtrl
.GetSelections()
974 if self
._IsItemProject
(item
):
975 projectPropertiesDialog
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
._GetItemProject
(item
).GetFilename())
976 if projectPropertiesDialog
.ShowModal() == wx
.ID_OK
:
978 projectPropertiesDialog
.Destroy()
979 elif self
._IsItemFile
(item
):
980 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
981 filePropertiesService
.ShowPropertiesDialog(self
._GetItemFile
(item
))
984 def OnAddFileToProject(self
, event
):
985 if wx
.Platform
== "__WXMSW__" or wx
.Platform
== "__WXGTK__" or wx
.Platform
== "__WXMAC__":
988 for temp
in self
.GetDocumentManager()._templates
:
991 descr
= descr
+ _('|')
992 allfilter
= allfilter
+ _(';')
993 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
994 allfilter
= allfilter
+ temp
.GetFileFilter()
995 descr
= _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter
, allfilter
, descr
) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
999 startDirectory
= os
.path
.dirname(self
.GetDocument().GetFilename())
1001 if True or _WINDOWS
:
1002 dialog
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), startDirectory
, "", descr
, wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
)
1003 if dialog
.ShowModal() != wx
.ID_OK
:
1005 paths
= dialog
.GetPaths()
1008 paths
= wx
.FileSelector(_("Add Files"), startDirectory
, "", wildcard
= descr
, flags
= wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
, parent
=self
.GetFrame())
1009 if type(paths
) == types
.StringType
:
1012 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
))
1013 self
.Activate(True) # after add, should put focus on project editor
1016 def OnAddDirToProject(self
, event
):
1017 frame
= wx
.Dialog(None, -1, _("Add Directory Files to Project"), size
= (320,200))
1018 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1020 flexGridSizer
= wx
.FlexGridSizer(cols
= 2, vgap
=HALF_SPACE
, hgap
=HALF_SPACE
)
1021 flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER_VERTICAL
, 0)
1022 lineSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1023 dirCtrl
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(250,-1))
1024 dirCtrl
.SetToolTipString(dirCtrl
.GetValue())
1025 lineSizer
.Add(dirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND
)
1026 findDirButton
= wx
.Button(frame
, -1, _("Browse..."))
1027 lineSizer
.Add(findDirButton
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, HALF_SPACE
)
1028 flexGridSizer
.Add(lineSizer
, 1, wx
.EXPAND
)
1030 def OnBrowseButton(event
):
1031 dlg
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
)
1032 dir = dirCtrl
.GetValue()
1035 if dlg
.ShowModal() == wx
.ID_OK
:
1036 dirCtrl
.SetValue(dlg
.GetPath())
1037 dirCtrl
.SetToolTipString(dirCtrl
.GetValue())
1038 dirCtrl
.SetInsertionPointEnd()
1041 wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
)
1043 visibleTemplates
= []
1044 for template
in self
.GetDocumentManager()._templates
:
1045 if template
.IsVisible():
1046 visibleTemplates
.append(template
)
1051 for template
in visibleTemplates
:
1053 descr
= descr
+ _('|')
1054 allfilter
= allfilter
+ _(';')
1055 descr
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")")
1056 choices
.append(descr
)
1057 allfilter
= allfilter
+ template
.GetFileFilter()
1058 choices
.insert(0, _("All (%s)") % allfilter
)
1059 filterChoice
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
)
1060 filterChoice
.SetSelection(0)
1061 filterChoice
.SetToolTipString(_("Select file type filter."))
1062 flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
1063 flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
)
1065 contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
)
1067 subfolderCtrl
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories"))
1068 subfolderCtrl
.SetValue(True)
1069 contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
)
1071 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1072 findBtn
= wx
.Button(frame
, wx
.ID_OK
, _("Add"))
1073 findBtn
.SetDefault()
1074 buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
1075 buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0)
1076 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
1078 frame
.SetSizer(contentSizer
)
1081 status
= frame
.ShowModal()
1084 while status
== wx
.ID_OK
and not passedCheck
:
1085 if not os
.path
.exists(dirCtrl
.GetValue()):
1086 dlg
= wx
.MessageDialog(frame
,
1087 _("'%s' does not exist.") % dirCtrl
.GetValue(),
1088 _("Find in Directory"),
1089 wx
.OK | wx
.ICON_EXCLAMATION
1094 status
= frame
.ShowModal()
1098 if status
== wx
.ID_OK
:
1101 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1103 doc
= self
.GetDocument()
1104 searchSubfolders
= subfolderCtrl
.IsChecked()
1105 dirString
= dirCtrl
.GetValue()
1107 if os
.path
.isfile(dirString
):
1108 # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter.
1109 # We'll assume they know what they're doing.
1114 index
= filterChoice
.GetSelection()
1116 template
= visibleTemplates
[index
-1]
1118 # do search in files on disk
1119 for root
, dirs
, files
in os
.walk(dirString
):
1120 if not searchSubfolders
and root
!= dirString
:
1124 if index
== 0: # all
1125 for template
in visibleTemplates
:
1126 if template
.FileMatchesTemplate(name
):
1127 filename
= os
.path
.join(root
, name
)
1129 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1130 if doc
.IsFileInProject(filename
):
1133 paths
.append(filename
)
1135 else: # use selected filter
1136 if template
.FileMatchesTemplate(name
):
1137 filename
= os
.path
.join(root
, name
)
1138 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1139 if not doc
.IsFileInProject(filename
):
1140 paths
.append(filename
)
1142 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1144 doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
))
1145 self
.Activate(True) # after add, should put focus on project editor
1150 def DoAddFilesToProject(self
, filenames
):
1151 # method used by Drag-n-Drop to add files to current Project
1152 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
))
1155 def DoSelectFiles(self
, filenames
):
1156 # method used by Drag-n-Drop to select files in current Project
1157 self
._treeCtrl
.UnselectAll()
1158 for file in filenames
:
1159 item
= self
._GetFileItem
(longFileName
=file)
1161 self
._treeCtrl
.SelectItem(item
, True)
1162 self
._treeCtrl
.EnsureVisible(item
)
1165 def DoSelectProject(self
, x
, y
):
1166 # method used by Drag-n-Drop to set current Project based on cursor position
1167 item
, flag
= self
._treeCtrl
.HitTest((x
,y
))
1171 project
= self
._GetItemProject
(item
)
1175 projectItem
= self
._GetProjectItem
(project
)
1176 self
._treeCtrl
.UnselectAll()
1177 self
._treeCtrl
.SelectItem(projectItem
)
1181 def OnFocus(self
, event
):
1182 wx
.GetApp().GetDocumentManager().ActivateView(self
)
1186 def OnKillFocus(self
, event
):
1187 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
1188 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
1189 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
1190 childFrame
= wx
.GetApp().GetTopWindow().GetActiveChild()
1192 childFrame
.Activate()
1196 def OnRightClick(self
, event
):
1198 if not self
._treeCtrl
.GetSelections():
1200 if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]):
1201 return # Don't do a menu if it's just the root item selected
1203 if self
._HasFilesSelected
(): # Files context
1204 menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection"))
1205 menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True)
1206 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
)
1208 for item
in self
._treeCtrl
.GetSelections():
1209 if self
._IsItemProcessModelFile
(item
):
1210 itemIDs
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None]
1212 else: # Project context
1213 itemIDs
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None]
1214 menuBar
= self
._GetParentFrame
().GetMenuBar()
1215 itemIDs
= itemIDs
+ [ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
]
1216 svnIDs
= [SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
]
1218 itemIDs
= itemIDs
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
]
1219 globalIDs
= [wx
.ID_UNDO
, wx
.ID_REDO
, wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
]
1220 itemIDs
= itemIDs
+ [None, wx
.ID_UNDO
, wx
.ID_REDO
, None, wx
.ID_CUT
, wx
.ID_COPY
, wx
.ID_PASTE
, wx
.ID_CLEAR
, None, wx
.ID_SELECTALL
, ProjectService
.RENAME_ID
, ProjectService
.DELETE_FILE_ID
, None, wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
]
1221 for itemID
in itemIDs
:
1223 menu
.AppendSeparator()
1225 if itemID
== ProjectService
.RUN_SELECTED_PM_ID
:
1226 menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process"))
1227 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
)
1228 elif itemID
== ProjectService
.REMOVE_FROM_PROJECT
:
1229 menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project"))
1230 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
)
1231 wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
)
1233 svnService
= wx
.GetApp().GetService(SVNService
.SVNService
)
1234 item
= menuBar
.FindItemById(itemID
)
1236 if itemID
in svnIDs
:
1237 if SVN_INSTALLED
and svnService
:
1238 wx
.EVT_MENU(self
._GetParentFrame
(), itemID
, svnService
.ProcessEvent
)
1239 elif itemID
in globalIDs
:
1242 wx
.EVT_MENU(self
._treeCtrl
, itemID
, self
.ProcessEvent
)
1243 menu
.Append(itemID
, item
.GetLabel())
1244 self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY()))
1248 def OnRunSelectedPM(self
, event
):
1249 projectService
= wx
.GetApp().GetService(ProjectService
)
1251 projectService
.OnRunProcessModel(event
, runSelected
=True)
1254 def OnRename(self
, event
):
1255 if self
._treeCtrl
.GetSelections():
1256 self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0])
1259 def OnBeginLabelEdit(self
, event
):
1260 self
._editingSoDontKillFocus
= True
1261 item
= event
.GetItem()
1262 if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
):
1266 def OnEndLabelEdit(self
, event
):
1267 self
._editingSoDontKillFocus
= False
1268 item
= event
.GetItem()
1269 newName
= event
.GetLabel()
1270 if not newName
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)):
1273 if self
._IsItemFile
(item
):
1274 oldFile
= self
._GetItemFile
(item
)
1275 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1276 project
= self
._GetItemProject
(item
)
1277 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
)):
1280 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0]))
1281 elif self
._IsItemProject
(item
):
1282 oldFile
= self
._GetItemProject
(item
).GetFilename()
1283 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1284 project
= self
._GetItemProject
(item
)
1285 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
, True)):
1288 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
1292 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
1293 #fileDataObject = wx.FileDataObject()
1294 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
1295 if not wx
.TheClipboard
.IsOpened():
1296 if wx
.TheClipboard
.Open():
1297 fileDataObject
= wx
.FileDataObject()
1298 hasFilesInClipboard
= wx
.TheClipboard
.GetData(fileDataObject
)
1299 wx
.TheClipboard
.Close()
1301 hasFilesInClipboard
= False
1302 return hasFilesInClipboard
1305 def OnCut(self
, event
):
1310 def OnCopy(self
, event
):
1311 fileDataObject
= wx
.FileDataObject()
1312 items
= self
._treeCtrl
.GetSelections()
1314 if self
._IsItemFile
(item
):
1315 file = self
._treeCtrl
.GetLongFilename(item
)
1316 fileDataObject
.AddFile(file)
1317 if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open():
1318 wx
.TheClipboard
.SetData(fileDataObject
)
1319 wx
.TheClipboard
.Close()
1322 def OnPaste(self
, event
):
1323 if wx
.TheClipboard
.Open():
1324 fileDataObject
= wx
.FileDataObject()
1325 if wx
.TheClipboard
.GetData(fileDataObject
):
1326 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames()))
1327 wx
.TheClipboard
.Close()
1330 def OnClear(self
, event
):
1331 items
= self
._treeCtrl
.GetSelections()
1334 if self
._IsItemFile
(item
):
1335 files
.append((self
._GetItemProject
(item
), self
._GetItemFile
(item
)))
1336 self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files
))
1339 def OnDeleteFile(self
, event
):
1340 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1341 _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"),
1343 wx
.YES_NO|wx
.ICON_QUESTION
)
1344 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1347 items
= self
._treeCtrl
.GetSelections()
1351 if self
._IsItemFile
(item
):
1352 filename
= self
._GetItemFile
(item
)
1353 files
.append((self
._GetItemProject
(item
), filename
))
1354 if filename
not in delFiles
:
1355 delFiles
.append(filename
)
1357 # remove selected files from projects
1360 proj
, filename
= data
1361 if proj
not in projects
:
1362 projects
.append(proj
)
1363 for project
in projects
:
1366 proj
, filename
= data
1368 filenames
.append(filename
)
1369 project
.RemoveFiles(filenames
)
1371 # remove selected files from file system
1372 for filename
in delFiles
:
1373 if os
.path
.exists(filename
):
1377 wx
.MessageBox("Could not delete '%s'. %s" % (os
.path
.basename(filename
), sys
.exc_value
),
1379 wx
.OK | wx
.ICON_EXCLAMATION
)
1382 def OnKeyPressed(self
, event
):
1383 key
= event
.KeyCode()
1384 if key
== wx
.WXK_DELETE
:
1390 def OnSelectAll(self
, event
):
1391 project
= self
.GetDocument()
1393 self
._treeCtrl
.UnselectAll()
1394 for child
in self
._GetChildItems
(self
._GetProjectItem
(project
)):
1395 self
._treeCtrl
.SelectItem(child
)
1398 def OnOpenSelectionSDI(self
, event
):
1399 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1400 wx
.CallAfter(self
.OnOpenSelection
, None)
1403 def OnOpenSelection(self
, event
):
1406 items
= self
._treeCtrl
.GetSelections()
1408 if self
._IsItemFile
(item
):
1409 filepath
= self
._GetItemFile
(item
)
1410 if not os
.path
.exists(filepath
):
1411 msgTitle
= wx
.GetApp().GetAppName()
1413 msgTitle
= _("File Not Found")
1414 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1415 _("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
)),
1417 wx
.YES_NO|wx
.ICON_QUESTION
1419 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1421 findFile
= wx
.FileDialog(self
.GetFrame(),
1423 wx
.lib
.docview
.PathOnly(filepath
),
1424 wx
.lib
.docview
.FileNameFromPath(filepath
),
1427 if findFile
.ShowModal() == wx
.ID_OK
and findFile
.GetPath():
1428 newpath
= findFile
.GetPath()
1433 # update Project Model with new location
1434 project
= self
._GetItemProject
(item
)
1435 project
.RemoveFile(filepath
)
1436 project
.AddFile(newpath
)
1439 doc
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
)
1441 shortFilename
= self
._treeCtrl
.GetItemText(item
)
1442 if shortFilename
.endswith(".agp"):
1443 projItem
= self
._GetProjectItem
(shortFilename
=shortFilename
)
1444 self
._treeCtrl
.UnselectAll()
1445 if not self
._treeCtrl
.IsExpanded(projItem
):
1446 self
._treeCtrl
.Expand(projItem
)
1447 if not self
._treeCtrl
.IsVisible(projItem
):
1448 self
._treeCtrl
.EnsureVisible(projItem
)
1449 if not self
._treeCtrl
.IsSelected(projItem
):
1450 self
._treeCtrl
.SelectItem(projItem
)
1452 except IOError, (code
, message
):
1453 msgTitle
= wx
.GetApp().GetAppName()
1455 msgTitle
= _("File Error")
1456 wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
),
1458 wx
.OK | wx
.ICON_EXCLAMATION
,
1462 #----------------------------------------------------------------------------
1463 # Convenience methods
1464 #----------------------------------------------------------------------------
1466 def _HasFiles(self
):
1467 if not self
._treeCtrl
:
1469 return self
._treeCtrl
.GetCount() > 1 # 1 item = root item, don't count as having files
1472 def _HasSelection(self
):
1473 if not self
._treeCtrl
:
1476 items
= self
._treeCtrl
.GetSelections()
1483 def _HasFilesSelected(self
):
1484 if not self
._treeCtrl
:
1486 items
= self
._treeCtrl
.GetSelections()
1490 if not self
._IsItemFile
(item
):
1495 def _MakeProjectName(self
, project
):
1496 return project
.GetPrintableName()
1499 # Return the tree item for a project
1500 def _GetProjectItem(self
, project
=None, shortFilename
=None):
1501 rootItem
= self
._treeCtrl
.GetRootItem()
1502 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1505 if self
._treeCtrl
.GetProjectDoc(child
) == project
:
1508 if self
._treeCtrl
.GetItemText(child
) == shortFilename
:
1510 (child
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1514 # Returns the project for an item, either for a project item or a file that is part of a project
1515 def _GetItemProject(self
, item
):
1516 if self
._IsItemRoot
(item
):
1518 if self
._IsItemProject
(item
):
1519 return self
._treeCtrl
.GetProjectDoc(item
)
1520 if self
._IsItemFile
(item
):
1521 return self
._treeCtrl
.GetProjectDoc(self
._treeCtrl
.GetItemParent(item
))
1525 def _GetItemFile(self
, item
):
1526 if self
._IsItemFile
(item
):
1527 return self
._treeCtrl
.GetLongFilename(item
)
1532 def _GetFileItem(self
, shortFileName
= None, longFileName
= None):
1533 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1535 rootItem
= self
._treeCtrl
.GetRootItem()
1536 (project
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1537 while project
.IsOk():
1538 (child
, cookie2
) = self
._treeCtrl
.GetFirstChild(project
)
1541 if self
._treeCtrl
.GetItemText(child
) == shortFileName
:
1544 if self
._treeCtrl
.GetLongFilename(child
) == longFileName
:
1546 (child
, cookie2
) = self
._treeCtrl
.GetNextChild(project
, cookie2
)
1547 (project
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1551 def _IsItemRoot(self
, item
):
1552 return item
== self
._treeCtrl
.GetRootItem()
1555 def _IsItemProject(self
, item
):
1556 return self
._treeCtrl
.GetProjectDoc(item
) != None
1559 def _IsItemFile(self
, item
):
1560 return self
._treeCtrl
.GetProjectDoc(item
) == None
1563 def _IsItemProcessModelFile(self
, item
):
1564 if ACTIVEGRID_BASE_IDE
:
1567 if self
._IsItemFile
(item
):
1568 filename
= self
._treeCtrl
.GetLongFilename(item
)
1570 for template
in self
.GetDocumentManager().GetTemplates():
1571 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1572 ext
= template
.GetDefaultExtension()
1577 if filename
.endswith(ext
):
1583 def _GetChildItems(self
, parentItem
):
1585 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
)
1587 children
.append(child
)
1588 (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
)
1593 class ProjectFileDropTarget(wx
.FileDropTarget
):
1595 def __init__(self
, view
):
1596 wx
.FileDropTarget
.__init
__(self
)
1600 def OnDropFiles(self
, x
, y
, filenames
):
1601 if self
._view
.DoSelectProject(x
, y
):
1602 self
._view
.DoAddFilesToProject(filenames
)
1603 self
._view
.DoSelectFiles(filenames
)
1608 def OnDragOver(self
, x
, y
, default
):
1609 if self
._view
.DoSelectProject(x
,y
):
1614 class ProjectPropertiesDialog(wx
.Dialog
):
1617 def __init__(self
, parent
, filename
):
1618 wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size
= (310, 330))
1620 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
1622 notebook
= wx
.Notebook(self
, -1)
1623 tab
= wx
.Panel(notebook
, -1)
1625 gridSizer
= RowColSizer()
1627 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0)
1628 if os
.path
.isfile(filename
):
1629 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1)
1631 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0)
1632 gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1)
1634 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0)
1635 gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1)
1637 lineSizer
= wx
.BoxSizer(wx
.VERTICAL
) # let the line expand horizontally without vertical expansion
1638 lineSizer
.Add(wx
.StaticLine(tab
, -1, size
= (10,-1)), 0, wx
.EXPAND
)
1639 gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2)
1641 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0)
1642 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1)
1644 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0)
1645 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1)
1647 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0)
1648 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1)
1651 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1)
1653 # add a border around the inside of the tab
1654 spacerGrid
= wx
.BoxSizer(wx
.VERTICAL
)
1655 spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
);
1656 tab
.SetSizer(spacerGrid
)
1657 notebook
.AddPage(tab
, _("General"))
1658 if wx
.Platform
== "__WXMSW__":
1659 notebook
.SetPageSize((310,200))
1661 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1662 sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
)
1663 sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
)
1665 self
.SetSizer(sizer
)
1670 class ProjectOptionsPanel(wx
.Panel
):
1673 def __init__(self
, parent
, id):
1674 wx
.Panel
.__init
__(self
, parent
, id)
1675 self
._useSashMessageShown
= False
1676 config
= wx
.ConfigBase_Get()
1677 self
._projSaveDocsCheckBox
= wx
.CheckBox(self
, -1, _("Remember open projects"))
1678 self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True))
1679 projectBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1680 projectSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1681 projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1682 if not ACTIVEGRID_BASE_IDE
:
1683 self
._projShowWelcomeCheckBox
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog"))
1684 self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True))
1685 projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1686 projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
)
1687 self
.SetSizer(projectBorderSizer
)
1689 parent
.AddPage(self
, _("Project"))
1691 def OnUseSashSelect(self
, event
):
1692 if not self
._useSashMessageShown
:
1693 msgTitle
= wx
.GetApp().GetAppName()
1695 msgTitle
= _("Document Options")
1696 wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1698 wx
.OK | wx
.ICON_INFORMATION
,
1700 self
._useSashMessageShown
= True
1703 def OnOK(self
, optionsDialog
):
1704 config
= wx
.ConfigBase_Get()
1705 config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue())
1706 if not ACTIVEGRID_BASE_IDE
:
1707 config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue())
1710 class ProjectService(Service
.Service
):
1712 #----------------------------------------------------------------------------
1714 #----------------------------------------------------------------------------
1715 SHOW_WINDOW
= wx
.NewId() # keep this line for each subclass, need unique ID for each Service
1716 RUNPM_ID
= wx
.NewId()
1717 RUN_SELECTED_PM_ID
= wx
.NewId()
1718 RUN_CURRENT_PM_ID
= wx
.NewId()
1719 ADD_FILES_TO_PROJECT_ID
= wx
.NewId()
1720 ADD_CURRENT_FILE_TO_PROJECT_ID
= wx
.NewId()
1721 RENAME_ID
= wx
.NewId()
1722 OPEN_SELECTION_ID
= wx
.NewId()
1723 REMOVE_FROM_PROJECT
= wx
.NewId()
1724 DELETE_FILE_ID
= wx
.NewId()
1725 ADD_ALL_FILES_TO_PROJECT_ID
= wx
.NewId()
1728 #----------------------------------------------------------------------------
1729 # Overridden methods
1730 #----------------------------------------------------------------------------
1732 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1733 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1734 self
._runHandlers
= []
1735 self
._suppressOpenProjectMessages
= False
1738 def _CreateView(self
):
1739 return ProjectView(self
)
1742 def ShowWindow(self
, show
= True):
1743 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1744 Service
.Service
.ShowWindow(self
, show
)
1747 project
= self
.GetView().GetDocument()
1749 self
.OpenSavedProjects()
1752 #----------------------------------------------------------------------------
1753 # Service specific methods
1754 #----------------------------------------------------------------------------
1756 def GetSuppressOpenProjectMessages(self
):
1757 return self
._suppressOpenProjectMessages
1760 def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
):
1761 self
._suppressOpenProjectMessages
= suppressOpenProjectMessages
1764 def GetRunHandlers(self
):
1765 return self
._runHandlers
1768 def AddRunHandler(self
, runHandler
):
1769 self
._runHandlers
.append(runHandler
)
1772 def RemoveRunHandler(self
, runHandler
):
1773 self
._runHandlers
.remove(runHandler
)
1776 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1777 Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
1779 projectMenu
= wx
.Menu()
1781 ## accelTable = wx.AcceleratorTable([
1782 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1784 ## frame.SetAcceleratorTable(accelTable)
1785 isProjectDocument
= document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1786 if wx
.GetApp().IsMDI() or isProjectDocument
:
1787 if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
):
1788 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project"))
1789 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1790 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1791 if not menuBar
.FindItemById(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
):
1792 projectMenu
.Append(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project"))
1793 wx
.EVT_MENU(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1794 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1795 if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
):
1796 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1797 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
)
1798 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1799 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
1800 menuBar
.Insert(viewMenuIndex
+ 1, projectMenu
, _("&Project"))
1801 editMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit")))
1802 if not menuBar
.FindItemById(ProjectService
.RENAME_ID
):
1803 editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item"))
1804 wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
)
1805 wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
)
1806 if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
):
1807 editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system."))
1808 wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
)
1809 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
)
1814 def OnCloseFrame(self
, event
):
1815 if not self
.GetView():
1818 if wx
.GetApp().IsMDI():
1819 # close all non-project documents first
1820 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1821 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1822 if not self
.GetDocumentManager().CloseDocument(document
, False):
1825 # write project config afterwards because user may change filenames on closing of new documents
1826 self
.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1828 # close all project documents after closing other documents
1829 # because user may save a new document with a new name or cancel closing a document
1830 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1831 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1832 if not document
.OnSaveModified():
1835 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1836 elif self
.GetView() == event
.GetEventObject().GetView():
1841 #----------------------------------------------------------------------------
1842 # Event Processing Methods
1843 #----------------------------------------------------------------------------
1845 def ProcessEventBeforeWindows(self
, event
):
1848 if id == wx
.ID_CLOSE_ALL
:
1849 self
.OnFileCloseAll(event
)
1852 elif id == wx
.ID_CLOSE
:
1853 document
= self
.GetDocumentManager().GetCurrentDocument()
1854 if document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1855 self
.OnProjectClose(event
)
1862 def ProcessUpdateUIEventBeforeWindows(self
, event
):
1865 if id == wx
.ID_CLOSE_ALL
:
1866 for document
in self
.GetDocumentManager().GetDocuments():
1867 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1874 elif id == wx
.ID_CLOSE
:
1875 document
= self
.GetDocumentManager().GetCurrentDocument()
1876 if document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1877 projectFilenames
= self
.GetView().GetSelectedProjects()
1878 if projectFilenames
and len(projectFilenames
):
1887 def ProcessEvent(self
, event
):
1888 if Service
.Service
.ProcessEvent(self
, event
):
1892 if id == ProjectService
.RUN_SELECTED_PM_ID
:
1893 self
.OnRunProcessModel(event
, runSelected
=True)
1895 elif id == ProjectService
.RUN_CURRENT_PM_ID
:
1896 self
.OnRunProcessModel(event
, runCurrentFile
=True)
1898 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1899 self
.OnAddCurrentFileToProject(event
)
1901 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1903 return self
.GetView().ProcessEvent(event
)
1910 def ProcessUpdateUIEvent(self
, event
):
1911 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1915 if (id == ProjectService
.RUNPM_ID
1916 or id == ProjectService
.RUN_SELECTED_PM_ID
1917 or id == ProjectService
.RUN_CURRENT_PM_ID
):
1918 event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
())
1920 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1921 event
.Enable(self
._CanAddCurrentFileToProject
())
1923 elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
1924 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
1925 or id == ProjectService
.RENAME_ID
1926 or id == ProjectService
.OPEN_SELECTION_ID
1927 or id == ProjectService
.DELETE_FILE_ID
):
1930 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1932 return self
.GetView().ProcessUpdateUIEvent(event
)
1939 def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False):
1940 project
= self
.GetView().GetDocument()
1944 for template
in self
.GetDocumentManager().GetTemplates():
1945 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1946 ext
= template
.GetDefaultExtension()
1951 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1955 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1957 if doc
.GetFilename() in files
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1958 if not doc
.GetProcessModel().beginProcess
:
1959 wx
.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1962 filesModified
= False
1964 if doc
.IsModified():
1965 filesModified
= True
1968 frame
= self
.GetView().GetFrame()
1969 yesNoMsg
= wx
.MessageDialog(frame
,
1970 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1972 wx
.YES_NO|wx
.ICON_QUESTION
1974 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1975 wx
.GetTopLevelParent(frame
).OnFileSaveAll(None)
1978 fileToRun
= self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1980 fileToRun
= self
.GetView().GetSelectedFile()
1981 elif len(files
) > 1:
1982 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
1983 strings
= map(lambda file: os
.path
.basename(file), files
)
1984 res
= wx
.GetSingleChoiceIndex(_("Select a process to run:"),
1987 project
.GetFirstView()._GetParentFrame
())
1990 fileToRun
= files
[res
]
1992 fileToRun
= files
[0]
1994 self
.RunProcessModel(fileToRun
)
1997 def RunProcessModel(self
, fileToRun
):
1998 for runHandler
in self
.GetRunHandlers():
1999 if runHandler
.RunProjectFile(fileToRun
):
2001 os
.system('"' + fileToRun
+ '"')
2004 def _HasProcessModel(self
):
2005 project
= self
.GetView().GetDocument()
2009 for template
in self
.GetDocumentManager().GetTemplates():
2010 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
2011 ext
= template
.GetDefaultExtension()
2016 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
2026 def _HasOpenedProjects(self
):
2027 for document
in self
.GetDocumentManager().GetDocuments():
2028 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2033 def _HasCurrentFile(self
):
2034 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
2038 def _CanAddCurrentFileToProject(self
):
2039 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
2042 if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2044 if not currentDoc
._savedYet
:
2046 for document
in self
.GetDocumentManager().GetDocuments():
2047 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2049 return False # There are no documents open
2052 def GetFilesFromCurrentProject(self
):
2053 view
= self
.GetView()
2055 project
= view
.GetDocument()
2057 return project
.GetFiles()
2061 def GetCurrentProject(self
):
2062 view
= self
.GetView()
2064 return view
.GetDocument()
2068 def FindProjectByFile(self
, filename
):
2069 for document
in self
.GetDocumentManager().GetDocuments():
2070 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2071 if document
.GetFilename() == filename
:
2073 elif document
.IsFileInProject(filename
):
2078 def GetCurrentProjectNames(self
):
2080 for document
in self
.GetDocumentManager().GetDocuments():
2081 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2082 projects
.append(document
)
2085 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2086 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2090 def OnAddCurrentFileToProject(self
, event
):
2091 if not self
._CanAddCurrentFileToProject
():
2094 for document
in self
.GetDocumentManager().GetDocuments():
2095 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2096 projects
.append(document
)
2099 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2100 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2101 res
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"),
2102 _("Add to Project"),
2104 self
.GetDocumentManager().FindSuitableParent())
2107 file = self
.GetDocumentManager().GetCurrentDocument().GetFilename()
2108 projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file]))
2109 self
.GetView().Activate(True) # after add, should put focus on project editor
2112 def OnProjectClose(self
, event
):
2113 projectFilenames
= self
.GetView().GetSelectedProjects()
2114 for filename
in projectFilenames
:
2115 doc
= self
.FindProjectByFile(filename
)
2117 self
.GetDocumentManager().CloseDocument(doc
, False)
2120 def OnFileCloseAll(self
, event
):
2121 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
2122 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
2123 if not self
.GetDocumentManager().CloseDocument(document
, False):
2125 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
2128 def OpenSavedProjects(self
):
2129 config
= wx
.ConfigBase_Get()
2131 if config
.ReadInt("ProjectSaveDocs", True):
2132 docString
= config
.Read("ProjectSavedDocs")
2135 for fileName
in eval(docString
):
2136 if isinstance(fileName
, types
.StringTypes
):
2137 if os
.path
.exists(fileName
):
2138 doc
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
)
2142 expandedString
= config
.Read("ProjectExpandedSavedDocs")
2144 view
= doc
.GetFirstView()
2145 view
.SetExpandedProjects(eval(expandedString
))
2149 class ProjectEditorMoveCommand(wx
.lib
.docview
.Command
):
2151 def __init__(self
, view
, newPositionItem
, item
):
2152 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
2155 self
._file
= view
._treeCtrl
.GetLongFilename(item
)
2156 if view
._IsItemFile
(item
):
2157 self
._projectOld
= view
._GetItemProject
(item
)
2158 else: # view._IsItemProject(item):
2159 self
._projectOld
= None
2160 self
._projectNew
= view
._GetItemProject
(newPositionItem
)
2164 return _("Move File %s") % os
.path
.basename(self
._file
)
2168 if self
._projectOld
:
2169 self
._projectOld
.RemoveFile(self
._file
)
2170 if self
._projectNew
:
2171 self
._projectNew
.AddFile(self
._file
)
2176 if self
._projectNew
:
2177 self
._projectNew
.RemoveFile(self
._file
)
2178 if self
._projectOld
:
2179 self
._projectOld
.AddFile(self
._file
)
2183 #----------------------------------------------------------------------------
2184 # Icon Bitmaps - generated by encode_bitmaps.py
2185 #----------------------------------------------------------------------------
2186 from wx
import ImageFromStream
, BitmapFromImage
2190 def getProjectData():
2192 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2193 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2194 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
2195 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
2196 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
2197 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
2199 def getProjectBitmap():
2200 return BitmapFromImage(getProjectImage())
2202 def getProjectImage():
2203 stream
= cStringIO
.StringIO(getProjectData())
2204 return ImageFromStream(stream
)
2206 def getProjectIcon():
2207 return wx
.IconFromBitmap(getProjectBitmap())
2210 #----------------------------------------------------------------------------
2214 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2215 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2216 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
2217 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
2218 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
2219 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
2220 \x00\x00IEND\xaeB`\x82'
2223 def getBlankBitmap():
2224 return BitmapFromImage(getBlankImage())
2226 def getBlankImage():
2227 stream
= cStringIO
.StringIO(getBlankData())
2228 return ImageFromStream(stream
)
2231 return wx
.IconFromBitmap(getBlankBitmap())