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
.xmlmarshaller
26 from IDE
import ACTIVEGRID_BASE_IDE
27 if not ACTIVEGRID_BASE_IDE
:
28 import ProcessModelEditor
32 if wx
.Platform
== '__WXMSW__':
38 #----------------------------------------------------------------------------
40 #----------------------------------------------------------------------------
45 #----------------------------------------------------------------------------
46 # XML Marshalling Methods
47 #----------------------------------------------------------------------------
48 LOCAL_TYPE_MAPPING
= { "projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel", }
52 xml
= fileObject
.read()
53 projectModel
= activegrid
.util
.xmlmarshaller
.unmarshal(xml
, knownTypes
=LOCAL_TYPE_MAPPING
)
57 def save(fileObject
, projectModel
):
58 xml
= activegrid
.util
.xmlmarshaller
.marshal(projectModel
, prettyPrint
=True, knownTypes
=LOCAL_TYPE_MAPPING
)
62 #----------------------------------------------------------------------------
64 #----------------------------------------------------------------------------
67 __xmlname__
= "projectmodel"
68 __xmlrename__
= { "_files":"files"}
75 class ProjectDocument(wx
.lib
.docview
.Document
):
79 wx
.lib
.docview
.Document
.__init
__(self
)
80 self
._projectModel
= ProjectModel()
84 return self
._projectModel
87 def OnCreate(self
, path
, flags
):
88 projectService
= wx
.GetApp().GetService(ProjectService
)
89 if projectService
.GetView():
90 # All project documents share the same view.
91 view
= projectService
.GetView()
94 if view
.GetDocument():
95 # All project documents need to share the same command processor,
96 # to enable redo/undo of cross project document commands
97 cmdProcessor
= view
.GetDocument().GetCommandProcessor()
99 self
.SetCommandProcessor(cmdProcessor
)
101 view
= self
.GetDocumentTemplate().CreateView(self
, flags
)
102 projectService
.SetView(view
)
108 def LoadObject(self
, fileObject
):
109 self
._projectModel
= activegrid
.tool
.ProjectEditor
.load(fileObject
)
110 self
._projectModel
._files
= self
.RelativeToAbsPath(self
._projectModel
._files
)
114 def SaveObject(self
, fileObject
):
115 absPath
= self
._projectModel
._files
116 self
._projectModel
._files
= self
.AbsToRelativePath(absPath
) # temporarily change it to relative paths for saving
117 activegrid
.tool
.ProjectEditor
.save(fileObject
, self
._projectModel
)
118 self
._projectModel
._files
= absPath
# swap it back to absolute path
122 def AbsToRelativePath(self
, paths
):
123 curPath
= os
.path
.dirname(self
.GetFilename())
124 curPathLen
= len(curPath
)
128 if path
.startswith(curPath
):
129 path
= "." + path
[curPathLen
:] # use relative path
131 pass # use absolute path
132 newFilePaths
.append(path
)
136 def RelativeToAbsPath(self
, paths
):
139 if path
.startswith("."): # relative to project file
140 curPath
= os
.path
.dirname(self
.GetFilename())
141 path
= os
.path
.normpath(os
.path
.join(curPath
, path
))
142 elif not ACTIVEGRID_BASE_IDE
:
143 print "Warning: absolute path '%s' found in project file, this may affect deployment" % path
144 newFilePaths
.append(path
)
148 def OnOpenDocument(self
, filename
):
149 view
= self
.GetFirstView()
150 frame
= view
.GetFrame()
152 if not os
.path
.exists(filename
):
153 wx
.GetApp().CloseSplash()
154 msgTitle
= wx
.GetApp().GetAppName()
156 msgTitle
= _("File Error")
157 wx
.MessageBox(_("Could not find '%s'.") % filename
,
159 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
161 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
163 fileObject
= file(filename
, 'r')
165 self
.LoadObject(fileObject
)
167 wx
.GetApp().CloseSplash()
168 msgTitle
= wx
.GetApp().GetAppName()
170 msgTitle
= _("File Error")
171 wx
.MessageBox(_("Could not open '%s'. %s") % (wx
.lib
.docview
.FileNameFromPath(filename
), sys
.exc_value
),
173 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
175 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
178 self
.SetFilename(filename
, True)
179 view
.AddProjectToView(self
)
180 self
.SetDocumentModificationDate()
181 self
.UpdateAllViews()
182 self
._savedYet
= True
187 def AddFile(self
, file):
188 return self
.AddFiles([file])
191 def AddFiles(self
, files
):
192 notAlreadyThereFiles
= filter(lambda x
: x
not in self
._projectModel
._files
, files
) # Filter to the files that are not already in the project
193 if len(notAlreadyThereFiles
) == 0:
194 self
.UpdateAllViews(hint
= ("select", self
, files
))
197 self
._projectModel
._files
= self
._projectModel
._files
+ notAlreadyThereFiles
198 self
.UpdateAllViews(hint
= ("add", self
, notAlreadyThereFiles
))
203 def RemoveFile(self
, file):
204 return self
.RemoveFiles([file])
207 def RemoveFiles(self
, files
):
209 self
._projectModel
._files
.remove(file)
210 self
.UpdateAllViews(hint
= ("remove", self
, files
))
215 def RenameFile(self
, oldFile
, newFile
, isProject
= False):
217 if oldFile
== newFile
:
220 # projects don't have to exist yet, so not required to rename old file,
221 # but files must exist, so we'll try to rename and allow exceptions to occur if can't.
222 if not isProject
or (isProject
and os
.path
.exists(oldFile
)):
223 os
.rename(oldFile
, newFile
)
226 documents
= self
.GetDocumentManager().GetDocuments()
227 for document
in documents
:
228 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
229 document
.SetFilename(newFile
)
230 document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFile
))
231 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
233 self
.RemoveFile(oldFile
)
234 self
.AddFile(newFile
)
235 documents
= self
.GetDocumentManager().GetDocuments()
236 for document
in documents
:
237 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
238 document
.SetFilename(newFile
, notifyViews
= True)
239 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
241 except OSError, (code
, message
):
242 msgTitle
= wx
.GetApp().GetAppName()
244 msgTitle
= _("File Error")
245 wx
.MessageBox("Could not rename '%s'. '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFile
), message
),
247 wx
.OK | wx
.ICON_EXCLAMATION
,
248 self
.GetFirstView().GetFrame())
253 return self
._projectModel
._files
256 def IsFileInProject(self
, filename
):
257 return filename
in self
.GetFiles()
260 class NewProjectWizard(Wizard
.BaseWizard
):
262 WIZTITLE
= _("New Project Wizard")
264 def __init__(self
, parent
):
265 self
._parent
= parent
266 self
._fullProjectPath
= None
267 Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
)
268 self
._projectLocationPage
= self
.CreateProjectLocation(self
)
269 wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
)
272 def CreateProjectLocation(self
,wizard
):
273 page
= Wizard
.TitledWizardPage(wizard
, _("Project File Location"))
275 page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n")))
276 self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation
= UICommon
.CreateDirectoryControl(page
, _("File Name:"), _("Directory:"), _("agp"), startingDirectory
=os
.getcwd())
277 page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
)
280 wizard
.FitToPage(page
)
284 def RunWizard(self
, existingTables
= None, existingRelationships
= None):
285 status
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
)
287 docManager
= wx
.GetApp().GetTopWindow().GetDocumentManager()
288 if os
.path
.exists(self
._fullProjectPath
):
289 # What if the document is already open and we're overwriting it?
290 documents
= docManager
.GetDocuments()
291 for document
in documents
:
292 if document
.GetFilename() == self
._fullProjectPath
: # If the renamed document is open, update it
293 document
.DeleteAllViews()
295 os
.remove(self
._fullProjectPath
)
297 for template
in docManager
.GetTemplates():
298 if template
.GetDocumentType() == ProjectDocument
:
299 doc
= template
.CreateDocument(self
._fullProjectPath
, flags
= wx
.lib
.docview
.DOC_NEW
)
300 doc
.OnSaveDocument(self
._fullProjectPath
)
301 view
= doc
.GetFirstView()
302 view
.AddProjectToView(doc
)
309 def OnWizPageChanging(self
, event
):
310 if event
.GetDirection(): # It's going forwards
311 if event
.GetPage() == self
._projectLocationPage
:
312 if not self
._fileValidation
():
315 self
._fullProjectPath
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(),'.agp'))
319 def OnShowCreatePages(self
):
321 import DataModelEditor
322 requestedPos
= self
.GetPositionTuple()
323 projectService
= wx
.GetApp().GetService(ProjectService
)
324 projectView
= projectService
.GetView()
326 wiz
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
)
327 if wiz
.RunWizard(dontDestroy
=True):
328 self
._schemaName
.SetValue(wiz
.GetSchemaFileName())
333 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
):
336 def CreateDocument(self
, path
, flags
):
338 return wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
)
340 wiz
= NewProjectWizard(wx
.GetApp().GetTopWindow())
343 return None # never return the doc, otherwise docview will think it is a new file and rename it
346 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
):
349 def __init__(self
, projectDoc
, files
):
350 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
351 self
._projectDoc
= projectDoc
356 if len(self
._files
) == 1:
357 return _("Add File %s") % os
.path
.basename(self
._files
[0])
359 return _("Add Files")
363 return self
._projectDoc
.AddFiles(self
._files
)
367 return self
._projectDoc
.RemoveFiles(self
._files
)
370 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
):
373 def __init__(self
, files
):
374 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
379 if len(self
._files
) == 1:
380 return _("Remove File %s") % os
.path
.basename((self
._files
[0])[1])
382 return _("Remove Files")
388 for data
in self
._files
:
389 proj
, filename
= data
390 if proj
not in projects
:
391 projects
.append(proj
)
392 for project
in projects
:
394 for data
in self
._files
:
395 proj
, filename
= data
397 files
.append(filename
)
398 status
= project
.RemoveFiles(files
) or status
405 for data
in self
._files
:
406 proj
, filename
= data
407 if proj
not in projects
:
408 projects
.append(proj
)
409 for project
in projects
:
411 for data
in self
._files
:
412 proj
, filename
= data
414 files
.append(filename
)
415 status
= project
.AddFiles(files
) or status
419 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
):
422 def __init__(self
, projectDoc
, oldFile
, newFile
, isProject
= False):
423 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
424 self
._projectDoc
= projectDoc
425 self
._oldFile
= oldFile
426 self
._newFile
= newFile
427 self
._isProject
= isProject
431 return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFile
), os
.path
.basename(self
._newFile
))
435 return self
._projectDoc
.RenameFile(self
._oldFile
, self
._newFile
, self
._isProject
)
439 return self
._projectDoc
.RenameFile(self
._newFile
, self
._oldFile
, self
._isProject
)
442 class ProjectTreeCtrl(wx
.TreeCtrl
):
445 #----------------------------------------------------------------------------
447 #----------------------------------------------------------------------------
449 def __init__(self
, parent
, id, style
):
450 wx
.TreeCtrl
.__init
__(self
, parent
, id, style
= style
)
452 templates
= wx
.GetApp().GetDocumentManager().GetTemplates()
453 iconList
= wx
.ImageList(16, 16, initialCount
= len(templates
))
454 self
._iconIndexLookup
= []
455 for template
in templates
:
456 icon
= template
.GetIcon()
458 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16:
461 if wx
.GetApp().GetDebug():
462 print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
463 iconIndex
= iconList
.AddIcon(icon
)
464 self
._iconIndexLookup
.append((template
, iconIndex
))
466 icon
= getBlankIcon()
467 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16:
470 if wx
.GetApp().GetDebug():
471 print "Warning: getBlankIcon isn't 16x16, not crossplatform"
472 self
._blankIconIndex
= iconList
.AddIcon(icon
)
473 self
.AssignImageList(iconList
)
476 def OnCompareItems(self
, item1
, item2
):
477 return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower())
480 def AppendItem(self
, parent
, filepath
):
481 item
= wx
.TreeCtrl
.AppendItem(self
, parent
, filepath
)
484 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filepath
)
485 if not template
and parent
== self
.GetRootItem(): # If the parent is a root it's a new project
486 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
488 for t
, iconIndex
in self
._iconIndexLookup
:
490 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
)
491 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
)
492 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Selected
)
497 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
)
498 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
)
499 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Selected
)
504 #----------------------------------------------------------------------------
506 #----------------------------------------------------------------------------
508 def SetData(self
, item
, longFilename
, projectDoc
=None):
509 self
.SetPyData(item
, (longFilename
, projectDoc
))
512 def GetData(self
, item
):
513 """ returns longFilename and optional
515 data
= self
.GetPyData(item
)
521 def GetLongFilename(self
, item
):
522 return self
.GetData(item
)[0]
525 def GetProjectDoc(self
, item
):
526 return self
.GetData(item
)[1]
529 class ProjectView(wx
.lib
.docview
.View
):
532 #----------------------------------------------------------------------------
534 #----------------------------------------------------------------------------
536 def __init__(self
, service
= None):
537 wx
.lib
.docview
.View
.__init
__(self
)
538 self
._service
= service
# not used, but kept to match other Services
539 self
._treeCtrl
= None
540 self
._editingSoDontKillFocus
= False
541 self
._checkEditMenu
= True
545 projectService
= wx
.GetApp().GetService(ProjectService
)
547 projectService
.SetView(None)
548 wx
.lib
.docview
.View
.Destroy(self
)
551 def GetDocument(self
):
552 if not self
._treeCtrl
:
555 items
= self
._treeCtrl
.GetSelections()
556 if not items
: # No selection, so just return first project
557 item
= self
._treeCtrl
.GetFirstVisibleItem()
559 return self
._GetItemProject
(item
)
564 project
= self
._GetItemProject
(item
)
571 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
572 return wx
.GetApp().GetDocumentManager()
575 def OnChangeFilename(self
):
577 title
= _("Projects")
578 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
579 title
= title
+ " - " + wx
.GetApp().GetAppName()
580 self
.GetFrame().SetTitle(title
)
581 project
= self
.GetDocument()
583 projectItem
= self
._GetProjectItem
(project
)
584 name
= self
._treeCtrl
.GetItemText(self
._GetProjectItem
(project
))
585 name2
= self
._MakeProjectName
(project
)
587 self
._treeCtrl
.SetItemText(projectItem
, name2
)
588 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
591 def Activate(self
, activate
= True):
592 if not wx
.GetApp().IsMDI():
593 if activate
and not self
.IsShown():
597 wx
.lib
.docview
.View
.Activate(self
, activate
= activate
)
598 if activate
and self
._treeCtrl
:
599 self
._treeCtrl
.SetFocus()
602 def OnCreate(self
, doc
, flags
):
603 config
= wx
.ConfigBase_Get()
604 if wx
.GetApp().IsMDI():
605 self
._embeddedWindow
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
)
606 self
.SetFrame(self
._embeddedWindow
)
607 frame
= self
._embeddedWindow
609 self
._embeddedWindow
= None
610 pos
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1)
611 # make sure frame is visible
612 screenWidth
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
)
613 screenHeight
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
)
614 if pos
[0] < 0 or pos
[0] >= screenWidth
or pos
[1] < 0 or pos
[1] >= screenHeight
:
615 pos
= wx
.DefaultPosition
617 size
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1))
619 title
= _("Projects")
620 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
621 title
= title
+ " - " + wx
.GetApp().GetAppName()
623 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title
= title
, pos
= pos
, size
= size
)
624 if config
.ReadInt("ProjectFrameMaximized", False):
627 sizer
= wx
.BoxSizer()
628 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
)
629 self
._treeCtrl
.AddRoot(_("Projects"))
630 wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
)
631 wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
)
633 if self
._embeddedWindow
:
634 sizer
.Add(self
._treeCtrl
)
637 sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
, 0)
638 frame
.SetSizer(sizer
)
642 if wx
.GetApp().IsMDI():
643 wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
)
644 wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
)
646 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
647 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
)
649 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
)
650 wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
)
651 wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
)
652 wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
)
653 wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
)
654 # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
656 # drag-and-drop support
657 dt
= ProjectFileDropTarget(self
)
658 self
._treeCtrl
.SetDropTarget(dt
)
663 def OnBeginDrag(self
, event
):
664 item
= event
.GetItem()
666 if item
== self
._treeCtrl
.GetRootItem():
668 self
._draggingItem
= item
672 def OnEndDrag(self
, event
):
673 item
= event
.GetItem()
675 # don't allow object to be dragged to itself
676 if item
== self
._draggingItem
:
679 rootItem
= self
._treeCtrl
.GetRootItem()
681 # don't let object replace root view
683 wx
.MessageBox(_("Cannot replace root view with item."))
686 # don't allow object to be dragged to a direct descendant
687 ancestor
= self
._treeCtrl
.GetItemParent(item
)
688 while ancestor
!= rootItem
:
689 if ancestor
== self
._draggingItem
:
690 wx
.MessageBox(_("Cannot make item direct descendant of self."))
693 ancestor
= self
._treeCtrl
.GetItemParent(ancestor
)
695 if self
._treeCtrl
.GetItemParent(item
) == self
._treeCtrl
.GetItemParent(self
._draggingItem
):
696 # put it in same folder as it was originally, no-op.
698 if item
== self
._treeCtrl
.GetItemParent(self
._draggingItem
):
699 # put it in same folder as it was originally, no-op.
702 self
.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self
, item
, self
._draggingItem
))
705 def WriteProjectConfig(self
):
706 frame
= self
.GetFrame()
707 config
= wx
.ConfigBase_Get()
708 if frame
and not self
._embeddedWindow
:
709 if not frame
.IsMaximized():
710 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0])
711 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1])
712 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0])
713 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1])
714 config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized())
716 if config
.ReadInt("ProjectSaveDocs", True):
717 projectFileNames
= []
720 for projectItem
in self
._GetChildItems
(self
._treeCtrl
.GetRootItem()):
721 project
= self
._GetItemProject
(projectItem
)
722 if not project
.OnSaveModified():
724 if project
.GetDocumentSaved(): # Might be a new document and "No" selected to save it
725 projectFileNames
.append(str(project
.GetFilename()))
726 projectExpanded
.append(self
._treeCtrl
.IsExpanded(projectItem
))
727 config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__())
728 config
.Write("ProjectExpandedSavedDocs", projectExpanded
.__repr
__())
731 def OnClose(self
, deleteWindow
= True):
732 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
733 self
.WriteProjectConfig()
734 project
= self
.GetDocument()
737 if not self
.GetDocument().Close():
741 projectItem
= self
._GetProjectItem
(project
)
743 self
._treeCtrl
.Delete(projectItem
)
744 # We don't need to delete the window since it is a floater/embedded
748 def _GetParentFrame(self
):
749 return wx
.GetTopLevelParent(self
.GetFrame())
752 def OnUpdate(self
, sender
= None, hint
= None):
753 wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
)
756 projectItem
= self
._GetProjectItem
(hint
[1])
758 self
._treeCtrl
.UnselectAll()
759 self
._treeCtrl
.Expand(projectItem
)
762 item
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
763 self
._treeCtrl
.SetData(item
, file)
764 self
._treeCtrl
.SelectItem(item
)
765 self
._treeCtrl
.EnsureVisible(item
)
766 self
._treeCtrl
.SortChildren(projectItem
)
768 self
._treeCtrl
.EnsureVisible(item
) # need to be called after SortChildren
769 elif hint
[0] == "remove":
770 projectItem
= self
._GetProjectItem
(hint
[1])
772 self
._treeCtrl
.UnselectAll()
773 children
= self
._GetChildItems
(projectItem
)
774 for child
in children
:
775 if self
._GetItemFile
(child
) in files
:
776 self
._treeCtrl
.Delete(child
)
777 elif hint
[0] == "select":
778 projectItem
= self
._GetProjectItem
(hint
[1])
780 self
._treeCtrl
.UnselectAll()
781 children
= self
._GetChildItems
(projectItem
)
782 for child
in children
:
783 if self
._GetItemFile
(child
) in files
:
784 self
._treeCtrl
.SelectItem(child
)
785 self
._treeCtrl
.EnsureVisible(child
)
786 elif hint
[0] == "rename":
787 projectItem
= self
._GetProjectItem
(hint
[1])
788 self
._treeCtrl
.SetItemText(projectItem
, os
.path
.basename(hint
[2]))
791 def ProcessEvent(self
, event
):
793 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
794 self
.OnAddFileToProject(event
)
796 elif id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
:
797 self
.OnAddDirToProject(event
)
799 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
800 return False # Implement this one in the service
801 elif id == ProjectService
.RENAME_ID
:
804 elif id == ProjectService
.DELETE_FILE_ID
:
805 self
.OnDeleteFile(event
)
807 elif id == wx
.ID_CUT
:
810 elif id == wx
.ID_COPY
:
813 elif id == wx
.ID_PASTE
:
816 elif (id == wx
.ID_CLEAR
817 or id == ProjectService
.REMOVE_FROM_PROJECT
):
820 elif id == wx
.ID_SELECTALL
:
821 self
.OnSelectAll(event
)
823 elif id == ProjectService
.OPEN_SELECTION_ID
:
824 self
.OnOpenSelection(event
)
826 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
827 self
.OnProperties(event
)
833 def ProcessUpdateUIEvent(self
, event
):
834 # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
835 if self
._checkEditMenu
:
836 doc
= self
.GetDocument()
837 if doc
and not doc
.GetCommandProcessor().GetEditMenu():
838 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
839 self
._checkEditMenu
= False
844 or id == ProjectService
.RENAME_ID
845 or id == ProjectService
.ADD_FILES_TO_PROJECT_ID
846 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
847 or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
848 or id == ProjectService
.DELETE_FILE_ID
):
849 event
.Enable(self
._HasSelection
())
851 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
854 elif id == wx
.ID_PASTE
:
855 event
.Enable(self
.CanPaste())
857 elif id == wx
.ID_SELECTALL
:
858 event
.Enable(self
._HasFiles
())
860 elif (id == wx
.ID_CLEAR
861 or id == ProjectService
.REMOVE_FROM_PROJECT
862 or id == ProjectService
.OPEN_SELECTION_ID
):
863 event
.Enable(self
._HasFilesSelected
())
868 #----------------------------------------------------------------------------
870 #----------------------------------------------------------------------------
873 if not self
.GetFrame():
875 return self
.GetFrame().IsShown()
882 def Show(self
, show
= True):
883 self
.GetFrame().Show(show
)
884 if wx
.GetApp().IsMDI():
885 mdiParentFrame
= wx
.GetApp().GetTopWindow()
886 mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
)
889 #----------------------------------------------------------------------------
890 # Methods for ProjectDocument and ProjectService to call
891 #----------------------------------------------------------------------------
893 def SetExpandedProjects(self
, expandedProjects
):
894 self
._treeCtrl
.UnselectAll()
896 for i
, item
in enumerate(self
._GetChildItems
(self
._treeCtrl
.GetRootItem())):
900 if expandedProjects
[i
]:
901 self
._treeCtrl
.Expand(item
)
903 self
._treeCtrl
.Collapse(item
)
906 self
._treeCtrl
.EnsureVisible(firstItem
)
909 def GetSelectedFile(self
):
910 for item
in self
._treeCtrl
.GetSelections():
911 return self
._GetItemFile
(item
)
914 def AddProjectToView(self
, document
):
915 rootItem
= self
._treeCtrl
.GetRootItem()
916 projectItem
= self
._treeCtrl
.AppendItem(rootItem
, self
._MakeProjectName
(document
))
917 self
._treeCtrl
.SetData(projectItem
, document
.GetFilename(), document
)
918 for file in document
.GetFiles():
919 fileItem
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
920 self
._treeCtrl
.SetData(fileItem
, file)
921 self
._treeCtrl
.SortChildren(rootItem
)
922 self
._treeCtrl
.SortChildren(projectItem
)
923 self
._treeCtrl
.UnselectAll()
924 self
._treeCtrl
.Expand(projectItem
)
925 self
._treeCtrl
.SelectItem(projectItem
)
926 if self
._embeddedWindow
:
927 document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
930 #----------------------------------------------------------------------------
932 #----------------------------------------------------------------------------
934 def OnProperties(self
, event
):
935 items
= self
._treeCtrl
.GetSelections()
939 if self
._IsItemProject
(item
):
940 projectPropertiesDialog
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
._GetItemProject
(item
).GetFilename())
941 if projectPropertiesDialog
.ShowModal() == wx
.ID_OK
:
943 projectPropertiesDialog
.Destroy()
944 elif self
._IsItemFile
(item
):
945 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
946 filePropertiesService
.ShowPropertiesDialog(self
._GetItemFile
(item
))
949 def OnAddFileToProject(self
, event
):
950 if wx
.Platform
== "__WXMSW__" or wx
.Platform
== "__WXGTK__" or wx
.Platform
== "__WXMAC__":
953 for temp
in self
.GetDocumentManager()._templates
:
956 descr
= descr
+ _('|')
957 allfilter
= allfilter
+ _(';')
958 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
959 allfilter
= allfilter
+ temp
.GetFileFilter()
960 descr
= _("All") + _(" (") + allfilter
+ _(") |") + allfilter
+ _('|') + descr
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
961 descr
= descr
+ _("|") + _("Any (*.*) | *.*")
965 startDirectory
= os
.path
.dirname(self
.GetDocument().GetFilename())
968 dialog
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), startDirectory
, "", descr
, wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
)
969 if dialog
.ShowModal() != wx
.ID_OK
:
971 paths
= dialog
.GetPaths()
974 paths
= wx
.FileSelector(_("Add Files"), startDirectory
, "", wildcard
= descr
, flags
= wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
, parent
=self
.GetFrame())
975 if type(paths
) == types
.StringType
:
978 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
))
979 self
.Activate(True) # after add, should put focus on project editor
982 def OnAddDirToProject(self
, event
):
983 frame
= wx
.Dialog(None, -1, _("Add All Files from Directory to Project"), size
= (320,200))
984 borderSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
986 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
987 lineSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
988 lineSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER | wx
.RIGHT
, HALF_SPACE
)
989 dirCtrl
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(200,-1))
990 dirCtrl
.SetToolTipString(dirCtrl
.GetValue())
991 lineSizer
.Add(dirCtrl
, 0, wx
.LEFT
, HALF_SPACE
)
992 findDirButton
= wx
.Button(frame
, -1, "Browse...")
993 lineSizer
.Add(findDirButton
, 0, wx
.LEFT
, HALF_SPACE
)
994 contentSizer
.Add(lineSizer
, 0, wx
.BOTTOM
, SPACE
)
996 def OnBrowseButton(event
):
997 dlg
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
)
998 dir = dirCtrl
.GetValue()
1001 if dlg
.ShowModal() == wx
.ID_OK
:
1002 dirCtrl
.SetValue(dlg
.GetPath())
1003 dirCtrl
.SetToolTipString(dirCtrl
.GetValue())
1004 dirCtrl
.SetInsertionPointEnd()
1007 wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
)
1009 visibleTemplates
= []
1010 for template
in self
.GetDocumentManager()._templates
:
1011 if template
.IsVisible():
1012 visibleTemplates
.append(template
)
1017 for template
in visibleTemplates
:
1019 descr
= descr
+ _('|')
1020 allfilter
= allfilter
+ _(';')
1021 descr
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")")
1022 choices
.append(descr
)
1023 allfilter
= allfilter
+ template
.GetFileFilter()
1024 choices
.insert(0, _("All (%s)") % allfilter
)
1025 filterChoice
= wx
.Choice(frame
, -1, size
=(210, -1), choices
=choices
)
1026 filterChoice
.SetSelection(0)
1027 filterChoice
.SetToolTipString(_("Select file type filter."))
1028 lineSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1029 lineSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER | wx
.RIGHT
, HALF_SPACE
)
1030 lineSizer
.Add(filterChoice
, 1, wx
.LEFT
, HALF_SPACE
)
1031 contentSizer
.Add(lineSizer
, 0, wx
.BOTTOM|wx
.EXPAND
, SPACE
)
1033 subfolderCtrl
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories"))
1034 subfolderCtrl
.SetValue(True)
1035 contentSizer
.Add(subfolderCtrl
, 0, wx
.BOTTOM
, SPACE
)
1037 borderSizer
.Add(contentSizer
, 0, wx
.TOP|wx
.BOTTOM|wx
.LEFT
, SPACE
)
1039 buttonSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1040 findBtn
= wx
.Button(frame
, wx
.ID_OK
, _("Add"))
1041 findBtn
.SetDefault()
1042 buttonSizer
.Add(findBtn
, 0, wx
.BOTTOM
, HALF_SPACE
)
1043 buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0)
1044 borderSizer
.Add(buttonSizer
, 0, wx
.ALL
, SPACE
)
1046 frame
.SetSizer(borderSizer
)
1049 status
= frame
.ShowModal()
1052 while status
== wx
.ID_OK
and not passedCheck
:
1053 if not os
.path
.exists(dirCtrl
.GetValue()):
1054 dlg
= wx
.MessageDialog(frame
,
1055 _("'%s' does not exist.") % dirCtrl
.GetValue(),
1056 _("Find in Directory"),
1057 wx
.OK | wx
.ICON_EXCLAMATION
1062 status
= frame
.ShowModal()
1066 if status
== wx
.ID_OK
:
1069 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1071 doc
= self
.GetDocument()
1072 searchSubfolders
= subfolderCtrl
.IsChecked()
1073 dirString
= dirCtrl
.GetValue()
1075 if os
.path
.isfile(dirString
):
1076 # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter.
1077 # We'll assume they know what they're doing.
1082 index
= filterChoice
.GetSelection()
1084 template
= visibleTemplates
[index
-1]
1086 # do search in files on disk
1087 for root
, dirs
, files
in os
.walk(dirString
):
1088 if not searchSubfolders
and root
!= dirString
:
1092 if index
== 0: # all
1093 for template
in visibleTemplates
:
1094 if template
.FileMatchesTemplate(name
):
1095 filename
= os
.path
.join(root
, name
)
1097 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1098 if doc
.IsFileInProject(filename
):
1101 paths
.append(filename
)
1103 else: # use selected filter
1104 if template
.FileMatchesTemplate(name
):
1105 filename
= os
.path
.join(root
, name
)
1106 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1107 if not doc
.IsFileInProject(filename
):
1108 paths
.append(filename
)
1110 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1112 doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
))
1113 self
.Activate(True) # after add, should put focus on project editor
1118 def DoAddFilesToProject(self
, filenames
):
1119 # method used by Drag-n-Drop to add files to current Project
1120 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
))
1123 def DoSelectFiles(self
, filenames
):
1124 # method used by Drag-n-Drop to select files in current Project
1125 self
._treeCtrl
.UnselectAll()
1126 for file in filenames
:
1127 item
= self
._GetFileItem
(longFileName
=file)
1129 self
._treeCtrl
.SelectItem(item
, True)
1130 self
._treeCtrl
.EnsureVisible(item
)
1133 def DoSelectProject(self
, x
, y
):
1134 # method used by Drag-n-Drop to set current Project based on cursor position
1135 item
, flag
= self
._treeCtrl
.HitTest((x
,y
))
1139 project
= self
._GetItemProject
(item
)
1143 projectItem
= self
._GetProjectItem
(project
)
1144 self
._treeCtrl
.UnselectAll()
1145 self
._treeCtrl
.SelectItem(projectItem
)
1149 def OnFocus(self
, event
):
1150 wx
.GetApp().GetDocumentManager().ActivateView(self
)
1154 def OnKillFocus(self
, event
):
1155 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
1156 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
1157 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
1158 childFrame
= wx
.GetApp().GetTopWindow().GetActiveChild()
1160 childFrame
.Activate()
1164 def OnRightClick(self
, event
):
1166 if not self
._treeCtrl
.GetSelections():
1168 if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]):
1169 return # Don't do a menu if it's just the root item selected
1171 if self
._HasFilesSelected
(): # Files context
1172 menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection"))
1173 menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True)
1174 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
)
1176 for item
in self
._treeCtrl
.GetSelections():
1177 if self
._IsItemProcessModelFile
(item
):
1178 itemIDs
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None]
1180 else: # Project context
1181 itemIDs
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None]
1182 menuBar
= self
._GetParentFrame
().GetMenuBar()
1183 itemIDs
= itemIDs
+ [ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
, None, wx
.ID_UNDO
, wx
.ID_REDO
, None, wx
.ID_CUT
, wx
.ID_COPY
, wx
.ID_PASTE
, wx
.ID_CLEAR
, None, wx
.ID_SELECTALL
, ProjectService
.RENAME_ID
, ProjectService
.DELETE_FILE_ID
, None, wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
]
1184 for itemID
in itemIDs
:
1186 menu
.AppendSeparator()
1188 if itemID
== ProjectService
.RUN_SELECTED_PM_ID
:
1189 menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process"))
1190 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
)
1191 elif itemID
== ProjectService
.REMOVE_FROM_PROJECT
:
1192 menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project"))
1193 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
)
1194 wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
)
1196 item
= menuBar
.FindItemById(itemID
)
1198 menu
.Append(itemID
, item
.GetLabel())
1199 self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY()))
1203 def OnRunSelectedPM(self
, event
):
1204 projectService
= wx
.GetApp().GetService(ProjectService
)
1206 projectService
.OnRunProcessModel(event
, runSelected
=True)
1209 def OnRename(self
, event
):
1210 if self
._treeCtrl
.GetSelections():
1211 self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0])
1214 def OnBeginLabelEdit(self
, event
):
1215 self
._editingSoDontKillFocus
= True
1216 item
= event
.GetItem()
1217 if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
):
1221 def OnEndLabelEdit(self
, event
):
1222 self
._editingSoDontKillFocus
= False
1223 item
= event
.GetItem()
1224 newName
= event
.GetLabel()
1225 if not newName
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)):
1228 if self
._IsItemFile
(item
):
1229 oldFile
= self
._GetItemFile
(item
)
1230 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1231 project
= self
._GetItemProject
(item
)
1232 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
)):
1235 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0]))
1236 elif self
._IsItemProject
(item
):
1237 oldFile
= self
._GetItemProject
(item
).GetFilename()
1238 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1239 project
= self
._GetItemProject
(item
)
1240 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
, True)):
1243 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
1247 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
1248 #fileDataObject = wx.FileDataObject()
1249 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
1250 if not wx
.TheClipboard
.IsOpened():
1251 if wx
.TheClipboard
.Open():
1252 fileDataObject
= wx
.FileDataObject()
1253 hasFilesInClipboard
= wx
.TheClipboard
.GetData(fileDataObject
)
1254 wx
.TheClipboard
.Close()
1256 hasFilesInClipboard
= False
1257 return hasFilesInClipboard
1260 def OnCut(self
, event
):
1265 def OnCopy(self
, event
):
1266 fileDataObject
= wx
.FileDataObject()
1267 items
= self
._treeCtrl
.GetSelections()
1269 if self
._IsItemFile
(item
):
1270 file = self
._treeCtrl
.GetLongFilename(item
)
1271 fileDataObject
.AddFile(file)
1272 if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open():
1273 wx
.TheClipboard
.SetData(fileDataObject
)
1274 wx
.TheClipboard
.Close()
1277 def OnPaste(self
, event
):
1278 if wx
.TheClipboard
.Open():
1279 fileDataObject
= wx
.FileDataObject()
1280 if wx
.TheClipboard
.GetData(fileDataObject
):
1281 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames()))
1282 wx
.TheClipboard
.Close()
1285 def OnClear(self
, event
):
1286 items
= self
._treeCtrl
.GetSelections()
1289 if self
._IsItemFile
(item
):
1290 files
.append((self
._GetItemProject
(item
), self
._GetItemFile
(item
)))
1291 self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files
))
1294 def OnDeleteFile(self
, event
):
1295 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1296 _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"),
1298 wx
.YES_NO|wx
.ICON_QUESTION
)
1299 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1302 items
= self
._treeCtrl
.GetSelections()
1306 if self
._IsItemFile
(item
):
1307 filename
= self
._GetItemFile
(item
)
1308 files
.append((self
._GetItemProject
(item
), filename
))
1309 if filename
not in delFiles
:
1310 delFiles
.append(filename
)
1312 # remove selected files from projects
1315 proj
, filename
= data
1316 if proj
not in projects
:
1317 projects
.append(proj
)
1318 for project
in projects
:
1321 proj
, filename
= data
1323 filenames
.append(filename
)
1324 project
.RemoveFiles(filenames
)
1326 # remove selected files from file system
1327 for filename
in delFiles
:
1328 if os
.path
.exists(filename
):
1332 wx
.MessageBox("Could not delete '%s'. %s" % (os
.path
.basename(filename
), sys
.exc_value
),
1334 wx
.OK | wx
.ICON_EXCLAMATION
)
1337 def OnKeyPressed(self
, event
):
1338 key
= event
.KeyCode()
1339 if key
== wx
.WXK_DELETE
:
1345 def OnSelectAll(self
, event
):
1346 project
= self
.GetDocument()
1348 self
._treeCtrl
.UnselectAll()
1349 for child
in self
._GetChildItems
(self
._GetProjectItem
(project
)):
1350 self
._treeCtrl
.SelectItem(child
)
1353 def OnOpenSelectionSDI(self
, event
):
1354 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1355 wx
.CallAfter(self
.OnOpenSelection
, None)
1358 def OnOpenSelection(self
, event
):
1361 items
= self
._treeCtrl
.GetSelections()
1363 if self
._IsItemFile
(item
):
1364 filepath
= self
._GetItemFile
(item
)
1365 if not os
.path
.exists(filepath
):
1366 msgTitle
= wx
.GetApp().GetAppName()
1368 msgTitle
= _("File Not Found")
1369 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1370 _("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
)),
1372 wx
.YES_NO|wx
.ICON_QUESTION
1374 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1376 findFile
= wx
.FileDialog(self
.GetFrame(),
1378 wx
.lib
.docview
.PathOnly(filepath
),
1379 wx
.lib
.docview
.FileNameFromPath(filepath
),
1382 if findFile
.ShowModal() == wx
.ID_OK
and findFile
.GetPath():
1383 newpath
= findFile
.GetPath()
1388 # update Project Model with new location
1389 self
.GetDocument().RemoveFile(filepath
)
1390 self
.GetDocument().AddFile(newpath
)
1393 doc
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
)
1395 shortFilename
= self
._treeCtrl
.GetItemText(item
)
1396 if shortFilename
.endswith(".agp"):
1397 projItem
= self
._GetProjectItem
(shortFilename
=shortFilename
)
1398 self
._treeCtrl
.UnselectAll()
1399 if not self
._treeCtrl
.IsExpanded(projItem
):
1400 self
._treeCtrl
.Expand(projItem
)
1401 if not self
._treeCtrl
.IsVisible(projItem
):
1402 self
._treeCtrl
.EnsureVisible(projItem
)
1403 if not self
._treeCtrl
.IsSelected(projItem
):
1404 self
._treeCtrl
.SelectItem(projItem
)
1406 except IOError, (code
, message
):
1407 msgTitle
= wx
.GetApp().GetAppName()
1409 msgTitle
= _("File Error")
1410 wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
),
1412 wx
.OK | wx
.ICON_EXCLAMATION
,
1416 #----------------------------------------------------------------------------
1417 # Convenience methods
1418 #----------------------------------------------------------------------------
1420 def _HasFiles(self
):
1421 if not self
._treeCtrl
:
1423 return self
._treeCtrl
.GetCount() > 1 # 1 item = root item, don't count as having files
1426 def _HasSelection(self
):
1427 if not self
._treeCtrl
:
1430 items
= self
._treeCtrl
.GetSelections()
1437 def _HasFilesSelected(self
):
1438 if not self
._treeCtrl
:
1440 items
= self
._treeCtrl
.GetSelections()
1444 if not self
._IsItemFile
(item
):
1449 def _MakeProjectName(self
, project
):
1450 return project
.GetPrintableName()
1453 # Return the tree item for a project
1454 def _GetProjectItem(self
, project
=None, shortFilename
=None):
1455 rootItem
= self
._treeCtrl
.GetRootItem()
1456 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1459 if self
._treeCtrl
.GetProjectDoc(child
) == project
:
1462 if self
._treeCtrl
.GetItemText(child
) == shortFilename
:
1464 (child
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1468 # Returns the project for an item, either for a project item or a file that is part of a project
1469 def _GetItemProject(self
, item
):
1470 if self
._IsItemRoot
(item
):
1472 if self
._IsItemProject
(item
):
1473 return self
._treeCtrl
.GetProjectDoc(item
)
1474 if self
._IsItemFile
(item
):
1475 return self
._treeCtrl
.GetProjectDoc(self
._treeCtrl
.GetItemParent(item
))
1479 def _GetItemFile(self
, item
):
1480 if self
._IsItemFile
(item
):
1481 return self
._treeCtrl
.GetLongFilename(item
)
1486 def _GetFileItem(self
, shortFileName
= None, longFileName
= None):
1487 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1489 rootItem
= self
._treeCtrl
.GetRootItem()
1490 (project
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1491 while project
.IsOk():
1492 (child
, cookie2
) = self
._treeCtrl
.GetFirstChild(project
)
1495 if self
._treeCtrl
.GetItemText(child
) == shortFileName
:
1498 if self
._treeCtrl
.GetLongFilename(child
) == longFileName
:
1500 (child
, cookie2
) = self
._treeCtrl
.GetNextChild(project
, cookie
)
1501 (project
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1505 def _IsItemRoot(self
, item
):
1506 return item
== self
._treeCtrl
.GetRootItem()
1509 def _IsItemProject(self
, item
):
1510 return self
._treeCtrl
.GetProjectDoc(item
) != None
1513 def _IsItemFile(self
, item
):
1514 return self
._treeCtrl
.GetProjectDoc(item
) == None
1517 def _IsItemProcessModelFile(self
, item
):
1518 if ACTIVEGRID_BASE_IDE
:
1521 if self
._IsItemFile
(item
):
1522 filename
= self
._treeCtrl
.GetLongFilename(item
)
1524 for template
in self
.GetDocumentManager().GetTemplates():
1525 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1526 ext
= template
.GetDefaultExtension()
1531 if filename
.endswith(ext
):
1537 def _GetChildItems(self
, parentItem
):
1539 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
)
1541 children
.append(child
)
1542 (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
)
1547 class ProjectFileDropTarget(wx
.FileDropTarget
):
1549 def __init__(self
, view
):
1550 wx
.FileDropTarget
.__init
__(self
)
1554 def OnDropFiles(self
, x
, y
, filenames
):
1555 if self
._view
.DoSelectProject(x
, y
):
1556 self
._view
.DoAddFilesToProject(filenames
)
1557 self
._view
.DoSelectFiles(filenames
)
1562 def OnDragOver(self
, x
, y
, default
):
1563 if self
._view
.DoSelectProject(x
,y
):
1568 class ProjectPropertiesDialog(wx
.Dialog
):
1571 def __init__(self
, parent
, filename
):
1572 wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size
= (310, 330))
1574 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
1576 notebook
= wx
.Notebook(self
, -1)
1577 tab
= wx
.Panel(notebook
, -1)
1579 gridSizer
= RowColSizer()
1581 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0)
1582 if os
.path
.isfile(filename
):
1583 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1)
1585 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0)
1586 gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1)
1588 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0)
1589 gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1)
1591 lineSizer
= wx
.BoxSizer(wx
.VERTICAL
) # let the line expand horizontally without vertical expansion
1592 lineSizer
.Add(wx
.StaticLine(tab
, -1, size
= (10,-1)), 0, wx
.EXPAND
)
1593 gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2)
1595 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0)
1596 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1)
1598 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0)
1599 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1)
1601 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0)
1602 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1)
1605 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1)
1607 # add a border around the inside of the tab
1608 spacerGrid
= wx
.BoxSizer(wx
.VERTICAL
)
1609 spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
);
1610 tab
.SetSizer(spacerGrid
)
1611 notebook
.AddPage(tab
, _("General"))
1612 if wx
.Platform
== "__WXMSW__":
1613 notebook
.SetPageSize((310,200))
1615 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1616 sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
)
1617 sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
)
1620 self
.SetDimensions(-1, -1, 310, -1, wx
.SIZE_USE_EXISTING
)
1621 self
.SetSizer(sizer
)
1625 class ProjectOptionsPanel(wx
.Panel
):
1628 def __init__(self
, parent
, id):
1629 wx
.Panel
.__init
__(self
, parent
, id)
1630 self
._useSashMessageShown
= False
1631 config
= wx
.ConfigBase_Get()
1632 self
._projSaveDocsCheckBox
= wx
.CheckBox(self
, -1, _("Remember open projects"))
1633 self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True))
1634 projectBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1635 projectSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1636 projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1637 if not ACTIVEGRID_BASE_IDE
:
1638 self
._projShowWelcomeCheckBox
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog"))
1639 self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True))
1640 projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1641 projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
)
1642 self
.SetSizer(projectBorderSizer
)
1644 parent
.AddPage(self
, _("Project"))
1646 def OnUseSashSelect(self
, event
):
1647 if not self
._useSashMessageShown
:
1648 msgTitle
= wx
.GetApp().GetAppName()
1650 msgTitle
= _("Document Options")
1651 wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1653 wx
.OK | wx
.ICON_INFORMATION
,
1655 self
._useSashMessageShown
= True
1658 def OnOK(self
, optionsDialog
):
1659 config
= wx
.ConfigBase_Get()
1660 config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue())
1661 if not ACTIVEGRID_BASE_IDE
:
1662 config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue())
1665 class ProjectService(Service
.Service
):
1667 #----------------------------------------------------------------------------
1669 #----------------------------------------------------------------------------
1670 SHOW_WINDOW
= wx
.NewId() # keep this line for each subclass, need unique ID for each Service
1671 RUNPM_ID
= wx
.NewId()
1672 RUN_SELECTED_PM_ID
= wx
.NewId()
1673 RUN_CURRENT_PM_ID
= wx
.NewId()
1674 ADD_FILES_TO_PROJECT_ID
= wx
.NewId()
1675 ADD_CURRENT_FILE_TO_PROJECT_ID
= wx
.NewId()
1676 RENAME_ID
= wx
.NewId()
1677 OPEN_SELECTION_ID
= wx
.NewId()
1678 REMOVE_FROM_PROJECT
= wx
.NewId()
1679 DELETE_FILE_ID
= wx
.NewId()
1680 ADD_ALL_FILES_TO_PROJECT_ID
= wx
.NewId()
1683 #----------------------------------------------------------------------------
1684 # Overridden methods
1685 #----------------------------------------------------------------------------
1687 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1688 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1689 self
._runHandlers
= []
1690 self
._suppressOpenProjectMessages
= False
1693 def _CreateView(self
):
1694 return ProjectView(self
)
1697 def ShowWindow(self
, show
= True):
1698 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1699 Service
.Service
.ShowWindow(self
, show
)
1702 project
= self
.GetView().GetDocument()
1704 self
.OpenSavedProjects()
1707 #----------------------------------------------------------------------------
1708 # Service specific methods
1709 #----------------------------------------------------------------------------
1711 def GetSuppressOpenProjectMessages(self
):
1712 return self
._suppressOpenProjectMessages
1715 def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
):
1716 self
._suppressOpenProjectMessages
= suppressOpenProjectMessages
1719 def GetRunHandlers(self
):
1720 return self
._runHandlers
1723 def AddRunHandler(self
, runHandler
):
1724 self
._runHandlers
.append(runHandler
)
1727 def RemoveRunHandler(self
, runHandler
):
1728 self
._runHandlers
.remove(runHandler
)
1731 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1732 Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
1734 projectMenu
= wx
.Menu()
1736 ## accelTable = wx.AcceleratorTable([
1737 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1739 ## frame.SetAcceleratorTable(accelTable)
1740 isProjectDocument
= document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1741 if wx
.GetApp().IsMDI() or isProjectDocument
:
1742 if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
):
1743 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project"))
1744 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1745 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1746 if not menuBar
.FindItemById(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
):
1747 projectMenu
.Append(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, _("Add All Files to Project..."), _("Adds a directory's documents to the current project"))
1748 wx
.EVT_MENU(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1749 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1750 if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
):
1751 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1752 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
)
1753 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1754 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
1755 menuBar
.Insert(viewMenuIndex
+ 1, projectMenu
, _("&Project"))
1756 editMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit")))
1757 if not menuBar
.FindItemById(ProjectService
.RENAME_ID
):
1758 editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item"))
1759 wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
)
1760 wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
)
1761 if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
):
1762 editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system."))
1763 wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
)
1764 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
)
1769 def OnCloseFrame(self
, event
):
1770 if not self
.GetView():
1773 if wx
.GetApp().IsMDI():
1774 # close all non-project documents first
1775 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1776 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1777 if not self
.GetDocumentManager().CloseDocument(document
, False):
1780 # write project config afterwards because user may change filenames on closing of new documents
1781 self
.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1783 # close all project documents after closing other documents
1784 # because user may save a new document with a new name or cancel closing a document
1785 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1786 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1787 if not document
.OnSaveModified():
1790 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1791 elif self
.GetView() == event
.GetEventObject().GetView():
1796 #----------------------------------------------------------------------------
1797 # Event Processing Methods
1798 #----------------------------------------------------------------------------
1800 def ProcessEventBeforeWindows(self
, event
):
1802 if id == wx
.ID_CLOSE_ALL
:
1803 self
.OnFileCloseAll(event
)
1808 def ProcessEvent(self
, event
):
1809 if Service
.Service
.ProcessEvent(self
, event
):
1813 if id == ProjectService
.RUN_SELECTED_PM_ID
:
1814 self
.OnRunProcessModel(event
, runSelected
=True)
1816 elif id == ProjectService
.RUN_CURRENT_PM_ID
:
1817 self
.OnRunProcessModel(event
, runCurrentFile
=True)
1819 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1820 self
.OnAddCurrentFileToProject(event
)
1822 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1824 return self
.GetView().ProcessEvent(event
)
1831 def ProcessUpdateUIEvent(self
, event
):
1832 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1836 if (id == ProjectService
.RUNPM_ID
1837 or id == ProjectService
.RUN_SELECTED_PM_ID
1838 or id == ProjectService
.RUN_CURRENT_PM_ID
):
1839 event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
())
1841 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1842 event
.Enable(self
._CanAddCurrentFileToProject
())
1844 elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
1845 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
1846 or id == ProjectService
.RENAME_ID
1847 or id == ProjectService
.OPEN_SELECTION_ID
1848 or id == ProjectService
.DELETE_FILE_ID
):
1851 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1853 return self
.GetView().ProcessUpdateUIEvent(event
)
1860 def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False):
1861 project
= self
.GetView().GetDocument()
1865 for template
in self
.GetDocumentManager().GetTemplates():
1866 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1867 ext
= template
.GetDefaultExtension()
1872 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1876 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1878 if doc
.GetFilename() in files
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1879 if not doc
.GetProcessModel().beginProcess
:
1880 wx
.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1883 filesModified
= False
1885 if doc
.IsModified():
1886 filesModified
= True
1889 frame
= self
.GetView().GetFrame()
1890 yesNoMsg
= wx
.MessageDialog(frame
,
1891 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1893 wx
.YES_NO|wx
.ICON_QUESTION
1895 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1896 wx
.GetTopLevelParent(frame
).OnFileSaveAll(None)
1899 fileToRun
= self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1901 fileToRun
= self
.GetView().GetSelectedFile()
1902 elif len(files
) > 1:
1903 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
1904 strings
= map(lambda file: os
.path
.basename(file), files
)
1905 res
= wx
.GetSingleChoiceIndex(_("Select a process to run:"),
1908 project
.GetFirstView()._GetParentFrame
())
1911 fileToRun
= files
[res
]
1913 fileToRun
= files
[0]
1915 self
.RunProcessModel(fileToRun
)
1918 def RunProcessModel(self
, fileToRun
):
1919 for runHandler
in self
.GetRunHandlers():
1920 if runHandler
.RunProjectFile(fileToRun
):
1922 os
.system('"' + fileToRun
+ '"')
1925 def _HasProcessModel(self
):
1926 project
= self
.GetView().GetDocument()
1930 for template
in self
.GetDocumentManager().GetTemplates():
1931 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1932 ext
= template
.GetDefaultExtension()
1937 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1947 def _HasOpenedProjects(self
):
1948 for document
in self
.GetDocumentManager().GetDocuments():
1949 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1954 def _HasCurrentFile(self
):
1955 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1959 def _CanAddCurrentFileToProject(self
):
1960 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1963 if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1965 if not currentDoc
._savedYet
:
1967 for document
in self
.GetDocumentManager().GetDocuments():
1968 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1970 return False # There are no documents open
1973 def GetFilesFromCurrentProject(self
):
1974 view
= self
.GetView()
1976 project
= view
.GetDocument()
1978 return project
.GetFiles()
1982 def GetCurrentProject(self
):
1983 view
= self
.GetView()
1985 return view
.GetDocument()
1989 def FindProjectByFile(self
, filename
):
1990 for document
in self
.GetDocumentManager().GetDocuments():
1991 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1992 if document
.GetFilename() == filename
:
1994 elif document
.IsFileInProject(filename
):
1999 def GetCurrentProjectNames(self
):
2001 for document
in self
.GetDocumentManager().GetDocuments():
2002 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2003 projects
.append(document
)
2006 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2007 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2011 def OnAddCurrentFileToProject(self
, event
):
2012 if not self
._CanAddCurrentFileToProject
():
2015 for document
in self
.GetDocumentManager().GetDocuments():
2016 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2017 projects
.append(document
)
2020 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2021 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2022 res
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"),
2023 _("Add to Project"),
2025 self
.GetDocumentManager().FindSuitableParent())
2028 file = self
.GetDocumentManager().GetCurrentDocument().GetFilename()
2029 projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file]))
2030 self
.GetView().Activate(True) # after add, should put focus on project editor
2033 def OnFileCloseAll(self
, event
):
2034 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
2035 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
2036 if not self
.GetDocumentManager().CloseDocument(document
, False):
2038 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
2041 def OpenSavedProjects(self
):
2042 config
= wx
.ConfigBase_Get()
2044 if config
.ReadInt("ProjectSaveDocs", True):
2045 docString
= config
.Read("ProjectSavedDocs")
2048 for fileName
in eval(docString
):
2049 if isinstance(fileName
, types
.StringTypes
):
2050 if os
.path
.exists(fileName
):
2051 doc
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
)
2055 expandedString
= config
.Read("ProjectExpandedSavedDocs")
2057 view
= doc
.GetFirstView()
2058 view
.SetExpandedProjects(eval(expandedString
))
2062 class ProjectEditorMoveCommand(wx
.lib
.docview
.Command
):
2064 def __init__(self
, view
, newPositionItem
, item
):
2065 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
2068 self
._file
= view
._treeCtrl
.GetLongFilename(item
)
2069 if view
._IsItemFile
(item
):
2070 self
._projectOld
= view
._GetItemProject
(item
)
2071 else: # view._IsItemProject(item):
2072 self
._projectOld
= None
2073 self
._projectNew
= view
._GetItemProject
(newPositionItem
)
2077 return _("Move File %s") % os
.path
.basename(self
._file
)
2081 if self
._projectOld
:
2082 self
._projectOld
.RemoveFile(self
._file
)
2083 if self
._projectNew
:
2084 self
._projectNew
.AddFile(self
._file
)
2089 if self
._projectNew
:
2090 self
._projectNew
.RemoveFile(self
._file
)
2091 if self
._projectOld
:
2092 self
._projectOld
.AddFile(self
._file
)
2096 #----------------------------------------------------------------------------
2097 # Icon Bitmaps - generated by encode_bitmaps.py
2098 #----------------------------------------------------------------------------
2099 from wx
import ImageFromStream
, BitmapFromImage
2103 def getProjectData():
2105 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2106 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2107 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
2108 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
2109 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
2110 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
2112 def getProjectBitmap():
2113 return BitmapFromImage(getProjectImage())
2115 def getProjectImage():
2116 stream
= cStringIO
.StringIO(getProjectData())
2117 return ImageFromStream(stream
)
2119 def getProjectIcon():
2120 return wx
.IconFromBitmap(getProjectBitmap())
2123 #----------------------------------------------------------------------------
2127 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2128 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2129 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
2130 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
2131 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
2132 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
2133 \x00\x00IEND\xaeB`\x82'
2136 def getBlankBitmap():
2137 return BitmapFromImage(getBlankImage())
2139 def getBlankImage():
2140 stream
= cStringIO
.StringIO(getBlankData())
2141 return ImageFromStream(stream
)
2144 return wx
.IconFromBitmap(getBlankBitmap())