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
.xmlutils
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
.xmlutils
.defaultLoad(fileObject
, knownTypes
={"projectmodel" : ProjectModel}
)
54 def save(fileObject
, projectModel
):
55 activegrid
.util
.xmlutils
.defaultSave(fileObject
, projectModel
, prettyPrint
=True, knownTypes
={"projectmodel" : ProjectModel}
)
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
) # first item
1059 choices
.append(_("Any (*.*)")) # last item
1060 filterChoice
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
)
1061 filterChoice
.SetSelection(0)
1062 filterChoice
.SetToolTipString(_("Select file type filter."))
1063 flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
1064 flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
)
1066 contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
)
1068 subfolderCtrl
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories"))
1069 subfolderCtrl
.SetValue(True)
1070 contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
)
1072 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1073 findBtn
= wx
.Button(frame
, wx
.ID_OK
, _("Add"))
1074 findBtn
.SetDefault()
1075 buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
1076 buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0)
1077 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
1079 frame
.SetSizer(contentSizer
)
1082 status
= frame
.ShowModal()
1085 while status
== wx
.ID_OK
and not passedCheck
:
1086 if not os
.path
.exists(dirCtrl
.GetValue()):
1087 dlg
= wx
.MessageDialog(frame
,
1088 _("'%s' does not exist.") % dirCtrl
.GetValue(),
1089 _("Find in Directory"),
1090 wx
.OK | wx
.ICON_EXCLAMATION
1095 status
= frame
.ShowModal()
1099 if status
== wx
.ID_OK
:
1102 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1104 doc
= self
.GetDocument()
1105 searchSubfolders
= subfolderCtrl
.IsChecked()
1106 dirString
= dirCtrl
.GetValue()
1108 if os
.path
.isfile(dirString
):
1109 # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter.
1110 # We'll assume they know what they're doing.
1115 index
= filterChoice
.GetSelection()
1116 lastIndex
= filterChoice
.GetCount()-1
1117 if index
and index
!= lastIndex
: # if not All or Any
1118 template
= visibleTemplates
[index
-1]
1120 # do search in files on disk
1121 for root
, dirs
, files
in os
.walk(dirString
):
1122 if not searchSubfolders
and root
!= dirString
:
1126 if index
== 0: # All
1127 for template
in visibleTemplates
:
1128 if template
.FileMatchesTemplate(name
):
1129 filename
= os
.path
.join(root
, name
)
1131 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1132 if doc
.IsFileInProject(filename
):
1135 paths
.append(filename
)
1137 elif index
== lastIndex
: # Any
1138 filename
= os
.path
.join(root
, name
)
1139 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1140 if not doc
.IsFileInProject(filename
):
1141 paths
.append(filename
)
1142 else: # use selected filter
1143 if template
.FileMatchesTemplate(name
):
1144 filename
= os
.path
.join(root
, name
)
1145 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1146 if not doc
.IsFileInProject(filename
):
1147 paths
.append(filename
)
1149 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1151 doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
))
1152 self
.Activate(True) # after add, should put focus on project editor
1157 def DoAddFilesToProject(self
, filenames
):
1158 # method used by Drag-n-Drop to add files to current Project
1159 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
))
1162 def DoSelectFiles(self
, filenames
):
1163 # method used by Drag-n-Drop to select files in current Project
1164 self
._treeCtrl
.UnselectAll()
1165 for file in filenames
:
1166 item
= self
._GetFileItem
(longFileName
=file)
1168 self
._treeCtrl
.SelectItem(item
, True)
1169 self
._treeCtrl
.EnsureVisible(item
)
1172 def DoSelectProject(self
, x
, y
):
1173 # method used by Drag-n-Drop to set current Project based on cursor position
1174 item
, flag
= self
._treeCtrl
.HitTest((x
,y
))
1178 project
= self
._GetItemProject
(item
)
1182 projectItem
= self
._GetProjectItem
(project
)
1183 self
._treeCtrl
.UnselectAll()
1184 self
._treeCtrl
.SelectItem(projectItem
)
1188 def OnFocus(self
, event
):
1189 wx
.GetApp().GetDocumentManager().ActivateView(self
)
1193 def OnKillFocus(self
, event
):
1194 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
1195 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
1196 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
1197 childFrame
= wx
.GetApp().GetTopWindow().GetActiveChild()
1199 childFrame
.Activate()
1203 def OnRightClick(self
, event
):
1205 if not self
._treeCtrl
.GetSelections():
1207 if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]):
1208 return # Don't do a menu if it's just the root item selected
1210 if self
._HasFilesSelected
(): # Files context
1211 menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection"))
1212 menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True)
1213 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
)
1215 for item
in self
._treeCtrl
.GetSelections():
1216 if self
._IsItemProcessModelFile
(item
):
1217 itemIDs
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None]
1219 else: # Project context
1220 itemIDs
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None]
1221 menuBar
= self
._GetParentFrame
().GetMenuBar()
1222 itemIDs
= itemIDs
+ [ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
]
1223 svnIDs
= [SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
]
1225 itemIDs
= itemIDs
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
]
1226 globalIDs
= [wx
.ID_UNDO
, wx
.ID_REDO
, wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
]
1227 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
]
1228 for itemID
in itemIDs
:
1230 menu
.AppendSeparator()
1232 if itemID
== ProjectService
.RUN_SELECTED_PM_ID
:
1233 menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process"))
1234 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
)
1235 elif itemID
== ProjectService
.REMOVE_FROM_PROJECT
:
1236 menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project"))
1237 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
)
1238 wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
)
1240 svnService
= wx
.GetApp().GetService(SVNService
.SVNService
)
1241 item
= menuBar
.FindItemById(itemID
)
1243 if itemID
in svnIDs
:
1244 if SVN_INSTALLED
and svnService
:
1245 wx
.EVT_MENU(self
._GetParentFrame
(), itemID
, svnService
.ProcessEvent
)
1246 elif itemID
in globalIDs
:
1249 wx
.EVT_MENU(self
._treeCtrl
, itemID
, self
.ProcessEvent
)
1250 menu
.Append(itemID
, item
.GetLabel())
1251 self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY()))
1255 def OnRunSelectedPM(self
, event
):
1256 projectService
= wx
.GetApp().GetService(ProjectService
)
1258 projectService
.OnRunProcessModel(event
, runSelected
=True)
1261 def OnRename(self
, event
):
1262 if self
._treeCtrl
.GetSelections():
1263 self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0])
1266 def OnBeginLabelEdit(self
, event
):
1267 self
._editingSoDontKillFocus
= True
1268 item
= event
.GetItem()
1269 if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
):
1273 def OnEndLabelEdit(self
, event
):
1274 self
._editingSoDontKillFocus
= False
1275 item
= event
.GetItem()
1276 newName
= event
.GetLabel()
1277 if not newName
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)):
1280 if self
._IsItemFile
(item
):
1281 oldFile
= self
._GetItemFile
(item
)
1282 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1283 project
= self
._GetItemProject
(item
)
1284 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
)):
1287 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0]))
1288 elif self
._IsItemProject
(item
):
1289 oldFile
= self
._GetItemProject
(item
).GetFilename()
1290 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1291 project
= self
._GetItemProject
(item
)
1292 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
, True)):
1295 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
1299 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
1300 #fileDataObject = wx.FileDataObject()
1301 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
1302 if not wx
.TheClipboard
.IsOpened():
1303 if wx
.TheClipboard
.Open():
1304 fileDataObject
= wx
.FileDataObject()
1305 hasFilesInClipboard
= wx
.TheClipboard
.GetData(fileDataObject
)
1306 wx
.TheClipboard
.Close()
1308 hasFilesInClipboard
= False
1309 return hasFilesInClipboard
1312 def OnCut(self
, event
):
1317 def OnCopy(self
, event
):
1318 fileDataObject
= wx
.FileDataObject()
1319 items
= self
._treeCtrl
.GetSelections()
1321 if self
._IsItemFile
(item
):
1322 file = self
._treeCtrl
.GetLongFilename(item
)
1323 fileDataObject
.AddFile(file)
1324 if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open():
1325 wx
.TheClipboard
.SetData(fileDataObject
)
1326 wx
.TheClipboard
.Close()
1329 def OnPaste(self
, event
):
1330 if wx
.TheClipboard
.Open():
1331 fileDataObject
= wx
.FileDataObject()
1332 if wx
.TheClipboard
.GetData(fileDataObject
):
1333 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames()))
1334 wx
.TheClipboard
.Close()
1337 def OnClear(self
, event
):
1338 items
= self
._treeCtrl
.GetSelections()
1341 if self
._IsItemFile
(item
):
1342 files
.append((self
._GetItemProject
(item
), self
._GetItemFile
(item
)))
1343 self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files
))
1346 def OnDeleteFile(self
, event
):
1347 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1348 _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"),
1350 wx
.YES_NO|wx
.ICON_QUESTION
)
1351 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1354 items
= self
._treeCtrl
.GetSelections()
1358 if self
._IsItemFile
(item
):
1359 filename
= self
._GetItemFile
(item
)
1360 files
.append((self
._GetItemProject
(item
), filename
))
1361 if filename
not in delFiles
:
1362 delFiles
.append(filename
)
1364 # remove selected files from projects
1367 proj
, filename
= data
1368 if proj
not in projects
:
1369 projects
.append(proj
)
1370 for project
in projects
:
1373 proj
, filename
= data
1375 filenames
.append(filename
)
1376 project
.RemoveFiles(filenames
)
1378 # remove selected files from file system
1379 for filename
in delFiles
:
1380 if os
.path
.exists(filename
):
1384 wx
.MessageBox("Could not delete '%s'. %s" % (os
.path
.basename(filename
), sys
.exc_value
),
1386 wx
.OK | wx
.ICON_EXCLAMATION
)
1389 def OnKeyPressed(self
, event
):
1390 key
= event
.KeyCode()
1391 if key
== wx
.WXK_DELETE
:
1397 def OnSelectAll(self
, event
):
1398 project
= self
.GetDocument()
1400 self
._treeCtrl
.UnselectAll()
1401 for child
in self
._GetChildItems
(self
._GetProjectItem
(project
)):
1402 self
._treeCtrl
.SelectItem(child
)
1405 def OnOpenSelectionSDI(self
, event
):
1406 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1407 wx
.CallAfter(self
.OnOpenSelection
, None)
1410 def OnOpenSelection(self
, event
):
1413 items
= self
._treeCtrl
.GetSelections()
1415 if self
._IsItemFile
(item
):
1416 filepath
= self
._GetItemFile
(item
)
1417 if not os
.path
.exists(filepath
):
1418 msgTitle
= wx
.GetApp().GetAppName()
1420 msgTitle
= _("File Not Found")
1421 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1422 _("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
)),
1424 wx
.YES_NO|wx
.ICON_QUESTION
1426 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1428 findFile
= wx
.FileDialog(self
.GetFrame(),
1430 wx
.lib
.docview
.PathOnly(filepath
),
1431 wx
.lib
.docview
.FileNameFromPath(filepath
),
1434 if findFile
.ShowModal() == wx
.ID_OK
and findFile
.GetPath():
1435 newpath
= findFile
.GetPath()
1440 # update Project Model with new location
1441 project
= self
._GetItemProject
(item
)
1442 project
.RemoveFile(filepath
)
1443 project
.AddFile(newpath
)
1446 doc
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
)
1448 shortFilename
= self
._treeCtrl
.GetItemText(item
)
1449 if shortFilename
.endswith(".agp"):
1450 projItem
= self
._GetProjectItem
(shortFilename
=shortFilename
)
1451 self
._treeCtrl
.UnselectAll()
1452 if not self
._treeCtrl
.IsExpanded(projItem
):
1453 self
._treeCtrl
.Expand(projItem
)
1454 if not self
._treeCtrl
.IsVisible(projItem
):
1455 self
._treeCtrl
.EnsureVisible(projItem
)
1456 if not self
._treeCtrl
.IsSelected(projItem
):
1457 self
._treeCtrl
.SelectItem(projItem
)
1459 except IOError, (code
, message
):
1460 msgTitle
= wx
.GetApp().GetAppName()
1462 msgTitle
= _("File Error")
1463 wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
),
1465 wx
.OK | wx
.ICON_EXCLAMATION
,
1469 #----------------------------------------------------------------------------
1470 # Convenience methods
1471 #----------------------------------------------------------------------------
1473 def _HasFiles(self
):
1474 if not self
._treeCtrl
:
1476 return self
._treeCtrl
.GetCount() > 1 # 1 item = root item, don't count as having files
1479 def _HasSelection(self
):
1480 if not self
._treeCtrl
:
1483 items
= self
._treeCtrl
.GetSelections()
1490 def _HasFilesSelected(self
):
1491 if not self
._treeCtrl
:
1493 items
= self
._treeCtrl
.GetSelections()
1497 if not self
._IsItemFile
(item
):
1502 def _MakeProjectName(self
, project
):
1503 return project
.GetPrintableName()
1506 # Return the tree item for a project
1507 def _GetProjectItem(self
, project
=None, shortFilename
=None):
1508 rootItem
= self
._treeCtrl
.GetRootItem()
1509 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1512 if self
._treeCtrl
.GetProjectDoc(child
) == project
:
1515 if self
._treeCtrl
.GetItemText(child
) == shortFilename
:
1517 (child
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1521 # Returns the project for an item, either for a project item or a file that is part of a project
1522 def _GetItemProject(self
, item
):
1523 if self
._IsItemRoot
(item
):
1525 if self
._IsItemProject
(item
):
1526 return self
._treeCtrl
.GetProjectDoc(item
)
1527 if self
._IsItemFile
(item
):
1528 return self
._treeCtrl
.GetProjectDoc(self
._treeCtrl
.GetItemParent(item
))
1532 def _GetItemFile(self
, item
):
1533 if self
._IsItemFile
(item
):
1534 return self
._treeCtrl
.GetLongFilename(item
)
1539 def _GetFileItem(self
, shortFileName
= None, longFileName
= None):
1540 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1542 rootItem
= self
._treeCtrl
.GetRootItem()
1543 (project
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1544 while project
.IsOk():
1545 (child
, cookie2
) = self
._treeCtrl
.GetFirstChild(project
)
1548 if self
._treeCtrl
.GetItemText(child
) == shortFileName
:
1551 if self
._treeCtrl
.GetLongFilename(child
) == longFileName
:
1553 (child
, cookie2
) = self
._treeCtrl
.GetNextChild(project
, cookie2
)
1554 (project
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1558 def _IsItemRoot(self
, item
):
1559 return item
== self
._treeCtrl
.GetRootItem()
1562 def _IsItemProject(self
, item
):
1563 return self
._treeCtrl
.GetProjectDoc(item
) != None
1566 def _IsItemFile(self
, item
):
1567 return self
._treeCtrl
.GetProjectDoc(item
) == None
1570 def _IsItemProcessModelFile(self
, item
):
1571 if ACTIVEGRID_BASE_IDE
:
1574 if self
._IsItemFile
(item
):
1575 filename
= self
._treeCtrl
.GetLongFilename(item
)
1577 for template
in self
.GetDocumentManager().GetTemplates():
1578 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1579 ext
= template
.GetDefaultExtension()
1584 if filename
.endswith(ext
):
1590 def _GetChildItems(self
, parentItem
):
1592 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
)
1594 children
.append(child
)
1595 (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
)
1600 class ProjectFileDropTarget(wx
.FileDropTarget
):
1602 def __init__(self
, view
):
1603 wx
.FileDropTarget
.__init
__(self
)
1607 def OnDropFiles(self
, x
, y
, filenames
):
1608 if self
._view
.DoSelectProject(x
, y
):
1609 self
._view
.DoAddFilesToProject(filenames
)
1610 self
._view
.DoSelectFiles(filenames
)
1615 def OnDragOver(self
, x
, y
, default
):
1616 if self
._view
.DoSelectProject(x
,y
):
1621 class ProjectPropertiesDialog(wx
.Dialog
):
1624 def __init__(self
, parent
, filename
):
1625 wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size
= (310, 330))
1627 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
1629 notebook
= wx
.Notebook(self
, -1)
1630 tab
= wx
.Panel(notebook
, -1)
1632 gridSizer
= RowColSizer()
1634 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0)
1635 if os
.path
.isfile(filename
):
1636 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1)
1638 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0)
1639 gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1)
1641 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0)
1642 gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1)
1644 lineSizer
= wx
.BoxSizer(wx
.VERTICAL
) # let the line expand horizontally without vertical expansion
1645 lineSizer
.Add(wx
.StaticLine(tab
, -1, size
= (10,-1)), 0, wx
.EXPAND
)
1646 gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2)
1648 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0)
1649 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1)
1651 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0)
1652 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1)
1654 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0)
1655 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1)
1658 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1)
1660 # add a border around the inside of the tab
1661 spacerGrid
= wx
.BoxSizer(wx
.VERTICAL
)
1662 spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
);
1663 tab
.SetSizer(spacerGrid
)
1664 notebook
.AddPage(tab
, _("General"))
1665 if wx
.Platform
== "__WXMSW__":
1666 notebook
.SetPageSize((310,200))
1668 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1669 sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
)
1670 sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
)
1672 self
.SetSizer(sizer
)
1677 class ProjectOptionsPanel(wx
.Panel
):
1680 def __init__(self
, parent
, id):
1681 wx
.Panel
.__init
__(self
, parent
, id)
1682 self
._useSashMessageShown
= False
1683 config
= wx
.ConfigBase_Get()
1684 self
._projSaveDocsCheckBox
= wx
.CheckBox(self
, -1, _("Remember open projects"))
1685 self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True))
1686 projectBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1687 projectSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1688 projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1689 if not ACTIVEGRID_BASE_IDE
:
1690 self
._projShowWelcomeCheckBox
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog"))
1691 self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True))
1692 projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1693 projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
)
1694 self
.SetSizer(projectBorderSizer
)
1696 parent
.AddPage(self
, _("Project"))
1698 def OnUseSashSelect(self
, event
):
1699 if not self
._useSashMessageShown
:
1700 msgTitle
= wx
.GetApp().GetAppName()
1702 msgTitle
= _("Document Options")
1703 wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1705 wx
.OK | wx
.ICON_INFORMATION
,
1707 self
._useSashMessageShown
= True
1710 def OnOK(self
, optionsDialog
):
1711 config
= wx
.ConfigBase_Get()
1712 config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue())
1713 if not ACTIVEGRID_BASE_IDE
:
1714 config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue())
1717 class ProjectService(Service
.Service
):
1719 #----------------------------------------------------------------------------
1721 #----------------------------------------------------------------------------
1722 SHOW_WINDOW
= wx
.NewId() # keep this line for each subclass, need unique ID for each Service
1723 RUNPM_ID
= wx
.NewId()
1724 RUN_SELECTED_PM_ID
= wx
.NewId()
1725 RUN_CURRENT_PM_ID
= wx
.NewId()
1726 ADD_FILES_TO_PROJECT_ID
= wx
.NewId()
1727 ADD_CURRENT_FILE_TO_PROJECT_ID
= wx
.NewId()
1728 RENAME_ID
= wx
.NewId()
1729 OPEN_SELECTION_ID
= wx
.NewId()
1730 REMOVE_FROM_PROJECT
= wx
.NewId()
1731 DELETE_FILE_ID
= wx
.NewId()
1732 ADD_ALL_FILES_TO_PROJECT_ID
= wx
.NewId()
1735 #----------------------------------------------------------------------------
1736 # Overridden methods
1737 #----------------------------------------------------------------------------
1739 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1740 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1741 self
._runHandlers
= []
1742 self
._suppressOpenProjectMessages
= False
1745 def _CreateView(self
):
1746 return ProjectView(self
)
1749 def ShowWindow(self
, show
= True):
1750 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1751 Service
.Service
.ShowWindow(self
, show
)
1754 project
= self
.GetView().GetDocument()
1756 self
.OpenSavedProjects()
1759 #----------------------------------------------------------------------------
1760 # Service specific methods
1761 #----------------------------------------------------------------------------
1763 def GetSuppressOpenProjectMessages(self
):
1764 return self
._suppressOpenProjectMessages
1767 def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
):
1768 self
._suppressOpenProjectMessages
= suppressOpenProjectMessages
1771 def GetRunHandlers(self
):
1772 return self
._runHandlers
1775 def AddRunHandler(self
, runHandler
):
1776 self
._runHandlers
.append(runHandler
)
1779 def RemoveRunHandler(self
, runHandler
):
1780 self
._runHandlers
.remove(runHandler
)
1783 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1784 Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
1786 projectMenu
= wx
.Menu()
1788 ## accelTable = wx.AcceleratorTable([
1789 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1791 ## frame.SetAcceleratorTable(accelTable)
1792 isProjectDocument
= document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1793 if wx
.GetApp().IsMDI() or isProjectDocument
:
1794 if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
):
1795 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project"))
1796 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1797 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1798 if not menuBar
.FindItemById(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
):
1799 projectMenu
.Append(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project"))
1800 wx
.EVT_MENU(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1801 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1802 if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
):
1803 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1804 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
)
1805 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1806 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
1807 menuBar
.Insert(viewMenuIndex
+ 1, projectMenu
, _("&Project"))
1808 editMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit")))
1809 if not menuBar
.FindItemById(ProjectService
.RENAME_ID
):
1810 editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item"))
1811 wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
)
1812 wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
)
1813 if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
):
1814 editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system."))
1815 wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
)
1816 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
)
1821 def OnCloseFrame(self
, event
):
1822 if not self
.GetView():
1825 if wx
.GetApp().IsMDI():
1826 # close all non-project documents first
1827 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1828 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1829 if not self
.GetDocumentManager().CloseDocument(document
, False):
1832 # write project config afterwards because user may change filenames on closing of new documents
1833 self
.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1835 # close all project documents after closing other documents
1836 # because user may save a new document with a new name or cancel closing a document
1837 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1838 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1839 if not document
.OnSaveModified():
1842 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1843 elif self
.GetView() == event
.GetEventObject().GetView():
1848 #----------------------------------------------------------------------------
1849 # Event Processing Methods
1850 #----------------------------------------------------------------------------
1852 def ProcessEventBeforeWindows(self
, event
):
1855 if id == wx
.ID_CLOSE_ALL
:
1856 self
.OnFileCloseAll(event
)
1859 elif id == wx
.ID_CLOSE
:
1860 document
= self
.GetDocumentManager().GetCurrentDocument()
1861 if document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1862 self
.OnProjectClose(event
)
1869 def ProcessUpdateUIEventBeforeWindows(self
, event
):
1872 if id == wx
.ID_CLOSE_ALL
:
1873 for document
in self
.GetDocumentManager().GetDocuments():
1874 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1881 elif id == wx
.ID_CLOSE
:
1882 document
= self
.GetDocumentManager().GetCurrentDocument()
1883 if document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1884 projectFilenames
= self
.GetView().GetSelectedProjects()
1885 if projectFilenames
and len(projectFilenames
):
1894 def ProcessEvent(self
, event
):
1895 if Service
.Service
.ProcessEvent(self
, event
):
1899 if id == ProjectService
.RUN_SELECTED_PM_ID
:
1900 self
.OnRunProcessModel(event
, runSelected
=True)
1902 elif id == ProjectService
.RUN_CURRENT_PM_ID
:
1903 self
.OnRunProcessModel(event
, runCurrentFile
=True)
1905 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1906 self
.OnAddCurrentFileToProject(event
)
1908 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1910 return self
.GetView().ProcessEvent(event
)
1917 def ProcessUpdateUIEvent(self
, event
):
1918 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1922 if (id == ProjectService
.RUNPM_ID
1923 or id == ProjectService
.RUN_SELECTED_PM_ID
1924 or id == ProjectService
.RUN_CURRENT_PM_ID
):
1925 event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
())
1927 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1928 event
.Enable(self
._CanAddCurrentFileToProject
())
1930 elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
1931 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
1932 or id == ProjectService
.RENAME_ID
1933 or id == ProjectService
.OPEN_SELECTION_ID
1934 or id == ProjectService
.DELETE_FILE_ID
):
1937 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1939 return self
.GetView().ProcessUpdateUIEvent(event
)
1946 def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False):
1947 project
= self
.GetView().GetDocument()
1951 for template
in self
.GetDocumentManager().GetTemplates():
1952 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1953 ext
= template
.GetDefaultExtension()
1958 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1962 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1964 if doc
.GetFilename() in files
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1965 if not doc
.GetProcessModel().beginProcess
:
1966 wx
.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1969 filesModified
= False
1971 if doc
.IsModified():
1972 filesModified
= True
1975 frame
= self
.GetView().GetFrame()
1976 yesNoMsg
= wx
.MessageDialog(frame
,
1977 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1979 wx
.YES_NO|wx
.ICON_QUESTION
1981 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1982 wx
.GetTopLevelParent(frame
).OnFileSaveAll(None)
1985 fileToRun
= self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1987 fileToRun
= self
.GetView().GetSelectedFile()
1988 elif len(files
) > 1:
1989 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
1990 strings
= map(lambda file: os
.path
.basename(file), files
)
1991 res
= wx
.GetSingleChoiceIndex(_("Select a process to run:"),
1994 project
.GetFirstView()._GetParentFrame
())
1997 fileToRun
= files
[res
]
1999 fileToRun
= files
[0]
2001 self
.RunProcessModel(fileToRun
)
2004 def RunProcessModel(self
, fileToRun
):
2005 for runHandler
in self
.GetRunHandlers():
2006 if runHandler
.RunProjectFile(fileToRun
):
2008 os
.system('"' + fileToRun
+ '"')
2011 def _HasProcessModel(self
):
2012 project
= self
.GetView().GetDocument()
2016 for template
in self
.GetDocumentManager().GetTemplates():
2017 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
2018 ext
= template
.GetDefaultExtension()
2023 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
2033 def _HasOpenedProjects(self
):
2034 for document
in self
.GetDocumentManager().GetDocuments():
2035 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2040 def _HasCurrentFile(self
):
2041 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
2045 def _CanAddCurrentFileToProject(self
):
2046 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
2049 if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2051 if not currentDoc
._savedYet
:
2053 for document
in self
.GetDocumentManager().GetDocuments():
2054 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2056 return False # There are no documents open
2059 def GetFilesFromCurrentProject(self
):
2060 view
= self
.GetView()
2062 project
= view
.GetDocument()
2064 return project
.GetFiles()
2068 def GetCurrentProject(self
):
2069 view
= self
.GetView()
2071 return view
.GetDocument()
2075 def FindProjectByFile(self
, filename
):
2076 for document
in self
.GetDocumentManager().GetDocuments():
2077 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2078 if document
.GetFilename() == filename
:
2080 elif document
.IsFileInProject(filename
):
2085 def GetCurrentProjectNames(self
):
2087 for document
in self
.GetDocumentManager().GetDocuments():
2088 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2089 projects
.append(document
)
2092 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2093 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2097 def OnAddCurrentFileToProject(self
, event
):
2098 if not self
._CanAddCurrentFileToProject
():
2101 for document
in self
.GetDocumentManager().GetDocuments():
2102 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2103 projects
.append(document
)
2106 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2107 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2108 res
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"),
2109 _("Add to Project"),
2111 self
.GetDocumentManager().FindSuitableParent())
2114 file = self
.GetDocumentManager().GetCurrentDocument().GetFilename()
2115 projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file]))
2116 self
.GetView().Activate(True) # after add, should put focus on project editor
2119 def OnProjectClose(self
, event
):
2120 projectFilenames
= self
.GetView().GetSelectedProjects()
2121 for filename
in projectFilenames
:
2122 doc
= self
.FindProjectByFile(filename
)
2124 self
.GetDocumentManager().CloseDocument(doc
, False)
2127 def OnFileCloseAll(self
, event
):
2128 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
2129 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
2130 if not self
.GetDocumentManager().CloseDocument(document
, False):
2132 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
2135 def OpenSavedProjects(self
):
2136 config
= wx
.ConfigBase_Get()
2138 if config
.ReadInt("ProjectSaveDocs", True):
2139 docString
= config
.Read("ProjectSavedDocs")
2142 for fileName
in eval(docString
):
2143 if isinstance(fileName
, types
.StringTypes
):
2144 if os
.path
.exists(fileName
):
2145 doc
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
)
2149 expandedString
= config
.Read("ProjectExpandedSavedDocs")
2151 view
= doc
.GetFirstView()
2152 view
.SetExpandedProjects(eval(expandedString
))
2156 class ProjectEditorMoveCommand(wx
.lib
.docview
.Command
):
2158 def __init__(self
, view
, newPositionItem
, item
):
2159 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
2162 self
._file
= view
._treeCtrl
.GetLongFilename(item
)
2163 if view
._IsItemFile
(item
):
2164 self
._projectOld
= view
._GetItemProject
(item
)
2165 else: # view._IsItemProject(item):
2166 self
._projectOld
= None
2167 self
._projectNew
= view
._GetItemProject
(newPositionItem
)
2171 return _("Move File %s") % os
.path
.basename(self
._file
)
2175 if self
._projectOld
:
2176 self
._projectOld
.RemoveFile(self
._file
)
2177 if self
._projectNew
:
2178 self
._projectNew
.AddFile(self
._file
)
2183 if self
._projectNew
:
2184 self
._projectNew
.RemoveFile(self
._file
)
2185 if self
._projectOld
:
2186 self
._projectOld
.AddFile(self
._file
)
2190 #----------------------------------------------------------------------------
2191 # Icon Bitmaps - generated by encode_bitmaps.py
2192 #----------------------------------------------------------------------------
2193 from wx
import ImageFromStream
, BitmapFromImage
2197 def getProjectData():
2199 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2200 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2201 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
2202 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
2203 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
2204 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
2206 def getProjectBitmap():
2207 return BitmapFromImage(getProjectImage())
2209 def getProjectImage():
2210 stream
= cStringIO
.StringIO(getProjectData())
2211 return ImageFromStream(stream
)
2213 def getProjectIcon():
2214 return wx
.IconFromBitmap(getProjectBitmap())
2217 #----------------------------------------------------------------------------
2221 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2222 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2223 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
2224 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
2225 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
2226 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
2227 \x00\x00IEND\xaeB`\x82'
2230 def getBlankBitmap():
2231 return BitmapFromImage(getBlankImage())
2233 def getBlankImage():
2234 stream
= cStringIO
.StringIO(getBlankData())
2235 return ImageFromStream(stream
)
2238 return wx
.IconFromBitmap(getBlankBitmap())