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
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 #----------------------------------------------------------------------------
50 LOCAL_TYPE_MAPPING
= { "projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel", }
54 xml
= fileObject
.read()
55 projectModel
= activegrid
.util
.xmlmarshaller
.unmarshal(xml
, knownTypes
=LOCAL_TYPE_MAPPING
)
59 def save(fileObject
, projectModel
):
60 xml
= activegrid
.util
.xmlmarshaller
.marshal(projectModel
, prettyPrint
=True, knownTypes
=LOCAL_TYPE_MAPPING
)
64 #----------------------------------------------------------------------------
66 #----------------------------------------------------------------------------
69 __xmlname__
= "projectmodel"
70 __xmlrename__
= { "_files":"files"}
77 class ProjectDocument(wx
.lib
.docview
.Document
):
81 wx
.lib
.docview
.Document
.__init
__(self
)
82 self
._projectModel
= ProjectModel()
86 return self
._projectModel
89 def OnCreate(self
, path
, flags
):
90 projectService
= wx
.GetApp().GetService(ProjectService
)
91 if projectService
.GetView():
92 # All project documents share the same view.
93 view
= projectService
.GetView()
96 if view
.GetDocument():
97 # All project documents need to share the same command processor,
98 # to enable redo/undo of cross project document commands
99 cmdProcessor
= view
.GetDocument().GetCommandProcessor()
101 self
.SetCommandProcessor(cmdProcessor
)
103 view
= self
.GetDocumentTemplate().CreateView(self
, flags
)
104 projectService
.SetView(view
)
110 def LoadObject(self
, fileObject
):
111 self
._projectModel
= activegrid
.tool
.ProjectEditor
.load(fileObject
)
112 self
._projectModel
._files
= self
.RelativeToAbsPath(self
._projectModel
._files
)
116 def SaveObject(self
, fileObject
):
117 absPath
= self
._projectModel
._files
118 self
._projectModel
._files
= self
.AbsToRelativePath(absPath
) # temporarily change it to relative paths for saving
119 activegrid
.tool
.ProjectEditor
.save(fileObject
, self
._projectModel
)
120 self
._projectModel
._files
= absPath
# swap it back to absolute path
124 def AbsToRelativePath(self
, paths
):
125 curPath
= os
.path
.dirname(self
.GetFilename())
126 curPathLen
= len(curPath
)
130 if path
.startswith(curPath
):
131 path
= "." + path
[curPathLen
:] # use relative path
133 path
= path
.replace(os
.sep
, '/', -1) # always save out with '/' as path separator for cross-platform compatibility.
135 pass # use absolute path
136 newFilePaths
.append(path
)
140 def RelativeToAbsPath(self
, paths
):
143 if path
.startswith("."): # relative to project file
144 curPath
= os
.path
.dirname(self
.GetFilename())
145 path
= os
.path
.normpath(os
.path
.join(curPath
, path
))
146 elif not ACTIVEGRID_BASE_IDE
:
147 print "Warning: absolute path '%s' found in project file, this may affect deployment" % path
148 newFilePaths
.append(path
)
152 def OnOpenDocument(self
, filename
):
153 view
= self
.GetFirstView()
154 frame
= view
.GetFrame()
156 if not os
.path
.exists(filename
):
157 wx
.GetApp().CloseSplash()
158 msgTitle
= wx
.GetApp().GetAppName()
160 msgTitle
= _("File Error")
161 wx
.MessageBox(_("Could not find '%s'.") % filename
,
163 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
165 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
167 fileObject
= file(filename
, 'r')
169 self
.LoadObject(fileObject
)
171 wx
.GetApp().CloseSplash()
172 msgTitle
= wx
.GetApp().GetAppName()
174 msgTitle
= _("File Error")
175 wx
.MessageBox(_("Could not open '%s'. %s") % (wx
.lib
.docview
.FileNameFromPath(filename
), sys
.exc_value
),
177 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
179 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
182 self
.SetFilename(filename
, True)
183 view
.AddProjectToView(self
)
184 self
.SetDocumentModificationDate()
185 self
.UpdateAllViews()
186 self
._savedYet
= True
191 def AddFile(self
, file):
192 return self
.AddFiles([file])
195 def AddFiles(self
, files
):
196 notAlreadyThereFiles
= filter(lambda x
: x
not in self
._projectModel
._files
, files
) # Filter to the files that are not already in the project
197 if len(notAlreadyThereFiles
) == 0:
198 self
.UpdateAllViews(hint
= ("select", self
, files
))
201 self
._projectModel
._files
= self
._projectModel
._files
+ notAlreadyThereFiles
202 self
.UpdateAllViews(hint
= ("add", self
, notAlreadyThereFiles
))
207 def RemoveFile(self
, file):
208 return self
.RemoveFiles([file])
211 def RemoveFiles(self
, files
):
213 self
._projectModel
._files
.remove(file)
214 self
.UpdateAllViews(hint
= ("remove", self
, files
))
219 def RenameFile(self
, oldFile
, newFile
, isProject
= False):
221 if oldFile
== newFile
:
224 # projects don't have to exist yet, so not required to rename old file,
225 # but files must exist, so we'll try to rename and allow exceptions to occur if can't.
226 if not isProject
or (isProject
and os
.path
.exists(oldFile
)):
227 os
.rename(oldFile
, newFile
)
230 documents
= self
.GetDocumentManager().GetDocuments()
231 for document
in documents
:
232 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
233 document
.SetFilename(newFile
)
234 document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFile
))
235 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
237 self
.RemoveFile(oldFile
)
238 self
.AddFile(newFile
)
239 documents
= self
.GetDocumentManager().GetDocuments()
240 for document
in documents
:
241 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
242 document
.SetFilename(newFile
, notifyViews
= True)
243 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
245 except OSError, (code
, message
):
246 msgTitle
= wx
.GetApp().GetAppName()
248 msgTitle
= _("File Error")
249 wx
.MessageBox("Could not rename '%s'. '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFile
), message
),
251 wx
.OK | wx
.ICON_EXCLAMATION
,
252 self
.GetFirstView().GetFrame())
257 return self
._projectModel
._files
260 def IsFileInProject(self
, filename
):
261 return filename
in self
.GetFiles()
264 class NewProjectWizard(Wizard
.BaseWizard
):
266 WIZTITLE
= _("New Project Wizard")
268 def __init__(self
, parent
):
269 self
._parent
= parent
270 self
._fullProjectPath
= None
271 Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
)
272 self
._projectLocationPage
= self
.CreateProjectLocation(self
)
273 wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
)
276 def CreateProjectLocation(self
,wizard
):
277 page
= Wizard
.TitledWizardPage(wizard
, _("Project File Location"))
279 page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n")))
280 self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation
= UICommon
.CreateDirectoryControl(page
, _("File Name:"), _("Directory:"), _("agp"), startingDirectory
=os
.getcwd())
281 page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
)
284 wizard
.FitToPage(page
)
288 def RunWizard(self
, existingTables
= None, existingRelationships
= None):
289 status
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
)
291 docManager
= wx
.GetApp().GetTopWindow().GetDocumentManager()
292 if os
.path
.exists(self
._fullProjectPath
):
293 # What if the document is already open and we're overwriting it?
294 documents
= docManager
.GetDocuments()
295 for document
in documents
:
296 if document
.GetFilename() == self
._fullProjectPath
: # If the renamed document is open, update it
297 document
.DeleteAllViews()
299 os
.remove(self
._fullProjectPath
)
301 for template
in docManager
.GetTemplates():
302 if template
.GetDocumentType() == ProjectDocument
:
303 doc
= template
.CreateDocument(self
._fullProjectPath
, flags
= wx
.lib
.docview
.DOC_NEW
)
304 doc
.OnSaveDocument(self
._fullProjectPath
)
305 view
= doc
.GetFirstView()
306 view
.AddProjectToView(doc
)
313 def OnWizPageChanging(self
, event
):
314 if event
.GetDirection(): # It's going forwards
315 if event
.GetPage() == self
._projectLocationPage
:
316 if not self
._fileValidation
():
319 self
._fullProjectPath
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(),'.agp'))
323 def OnShowCreatePages(self
):
325 import DataModelEditor
326 requestedPos
= self
.GetPositionTuple()
327 projectService
= wx
.GetApp().GetService(ProjectService
)
328 projectView
= projectService
.GetView()
330 wiz
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
)
331 if wiz
.RunWizard(dontDestroy
=True):
332 self
._schemaName
.SetValue(wiz
.GetSchemaFileName())
337 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
):
340 def CreateDocument(self
, path
, flags
):
342 return wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
)
344 wiz
= NewProjectWizard(wx
.GetApp().GetTopWindow())
347 return None # never return the doc, otherwise docview will think it is a new file and rename it
350 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
):
353 def __init__(self
, projectDoc
, files
):
354 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
355 self
._projectDoc
= projectDoc
360 if len(self
._files
) == 1:
361 return _("Add File %s") % os
.path
.basename(self
._files
[0])
363 return _("Add Files")
367 return self
._projectDoc
.AddFiles(self
._files
)
371 return self
._projectDoc
.RemoveFiles(self
._files
)
374 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
):
377 def __init__(self
, files
):
378 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
383 if len(self
._files
) == 1:
384 return _("Remove File %s") % os
.path
.basename((self
._files
[0])[1])
386 return _("Remove Files")
392 for data
in self
._files
:
393 proj
, filename
= data
394 if proj
not in projects
:
395 projects
.append(proj
)
396 for project
in projects
:
398 for data
in self
._files
:
399 proj
, filename
= data
401 files
.append(filename
)
402 status
= project
.RemoveFiles(files
) or status
409 for data
in self
._files
:
410 proj
, filename
= data
411 if proj
not in projects
:
412 projects
.append(proj
)
413 for project
in projects
:
415 for data
in self
._files
:
416 proj
, filename
= data
418 files
.append(filename
)
419 status
= project
.AddFiles(files
) or status
423 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
):
426 def __init__(self
, projectDoc
, oldFile
, newFile
, isProject
= False):
427 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
428 self
._projectDoc
= projectDoc
429 self
._oldFile
= oldFile
430 self
._newFile
= newFile
431 self
._isProject
= isProject
435 return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFile
), os
.path
.basename(self
._newFile
))
439 return self
._projectDoc
.RenameFile(self
._oldFile
, self
._newFile
, self
._isProject
)
443 return self
._projectDoc
.RenameFile(self
._newFile
, self
._oldFile
, self
._isProject
)
446 class ProjectTreeCtrl(wx
.TreeCtrl
):
449 #----------------------------------------------------------------------------
451 #----------------------------------------------------------------------------
453 def __init__(self
, parent
, id, style
):
454 wx
.TreeCtrl
.__init
__(self
, parent
, id, style
= style
)
456 templates
= wx
.GetApp().GetDocumentManager().GetTemplates()
457 iconList
= wx
.ImageList(16, 16, initialCount
= len(templates
))
458 self
._iconIndexLookup
= []
459 for template
in templates
:
460 icon
= template
.GetIcon()
462 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16:
465 if wx
.GetApp().GetDebug():
466 print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
467 iconIndex
= iconList
.AddIcon(icon
)
468 self
._iconIndexLookup
.append((template
, iconIndex
))
470 icon
= getBlankIcon()
471 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16:
474 if wx
.GetApp().GetDebug():
475 print "Warning: getBlankIcon isn't 16x16, not crossplatform"
476 self
._blankIconIndex
= iconList
.AddIcon(icon
)
477 self
.AssignImageList(iconList
)
480 def OnCompareItems(self
, item1
, item2
):
481 return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower())
484 def AppendItem(self
, parent
, filepath
):
485 item
= wx
.TreeCtrl
.AppendItem(self
, parent
, filepath
)
488 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filepath
)
489 if not template
and parent
== self
.GetRootItem(): # If the parent is a root it's a new project
490 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
492 for t
, iconIndex
in self
._iconIndexLookup
:
494 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
)
495 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
)
496 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Selected
)
501 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
)
502 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
)
503 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Selected
)
508 #----------------------------------------------------------------------------
510 #----------------------------------------------------------------------------
512 def SetData(self
, item
, longFilename
, projectDoc
=None):
513 self
.SetPyData(item
, (longFilename
, projectDoc
))
516 def GetData(self
, item
):
517 """ returns longFilename and optional
519 data
= self
.GetPyData(item
)
525 def GetLongFilename(self
, item
):
526 return self
.GetData(item
)[0]
529 def GetProjectDoc(self
, item
):
530 return self
.GetData(item
)[1]
533 class ProjectView(wx
.lib
.docview
.View
):
536 #----------------------------------------------------------------------------
538 #----------------------------------------------------------------------------
540 def __init__(self
, service
= None):
541 wx
.lib
.docview
.View
.__init
__(self
)
542 self
._service
= service
# not used, but kept to match other Services
543 self
._treeCtrl
= None
544 self
._editingSoDontKillFocus
= False
545 self
._checkEditMenu
= True
549 projectService
= wx
.GetApp().GetService(ProjectService
)
551 projectService
.SetView(None)
552 wx
.lib
.docview
.View
.Destroy(self
)
555 def GetDocument(self
):
556 if not self
._treeCtrl
:
559 items
= self
._treeCtrl
.GetSelections()
560 if not items
: # No selection, so just return first project
561 item
= self
._treeCtrl
.GetFirstVisibleItem()
563 return self
._GetItemProject
(item
)
568 project
= self
._GetItemProject
(item
)
575 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
576 return wx
.GetApp().GetDocumentManager()
579 def OnChangeFilename(self
):
581 title
= _("Projects")
582 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
583 title
= title
+ " - " + wx
.GetApp().GetAppName()
584 self
.GetFrame().SetTitle(title
)
585 project
= self
.GetDocument()
587 projectItem
= self
._GetProjectItem
(project
)
588 name
= self
._treeCtrl
.GetItemText(self
._GetProjectItem
(project
))
589 name2
= self
._MakeProjectName
(project
)
591 self
._treeCtrl
.SetItemText(projectItem
, name2
)
592 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
595 def Activate(self
, activate
= True):
596 if not wx
.GetApp().IsMDI():
597 if activate
and not self
.IsShown():
601 wx
.lib
.docview
.View
.Activate(self
, activate
= activate
)
602 if activate
and self
._treeCtrl
:
603 self
._treeCtrl
.SetFocus()
606 def OnCreate(self
, doc
, flags
):
607 config
= wx
.ConfigBase_Get()
608 if wx
.GetApp().IsMDI():
609 self
._embeddedWindow
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
)
610 self
.SetFrame(self
._embeddedWindow
)
611 frame
= self
._embeddedWindow
613 self
._embeddedWindow
= None
614 pos
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1)
615 # make sure frame is visible
616 screenWidth
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
)
617 screenHeight
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
)
618 if pos
[0] < 0 or pos
[0] >= screenWidth
or pos
[1] < 0 or pos
[1] >= screenHeight
:
619 pos
= wx
.DefaultPosition
621 size
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1))
623 title
= _("Projects")
624 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
625 title
= title
+ " - " + wx
.GetApp().GetAppName()
627 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title
= title
, pos
= pos
, size
= size
)
628 if config
.ReadInt("ProjectFrameMaximized", False):
631 sizer
= wx
.BoxSizer()
632 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
)
633 self
._treeCtrl
.AddRoot(_("Projects"))
634 wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
)
635 wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
)
637 if self
._embeddedWindow
:
638 sizer
.Add(self
._treeCtrl
)
641 sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
, 0)
642 frame
.SetSizer(sizer
)
646 if wx
.GetApp().IsMDI():
647 wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
)
648 wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
)
650 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
651 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
)
653 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
)
654 wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
)
655 wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
)
656 wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
)
657 wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
)
658 # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
660 # drag-and-drop support
661 dt
= ProjectFileDropTarget(self
)
662 self
._treeCtrl
.SetDropTarget(dt
)
667 def OnBeginDrag(self
, event
):
668 item
= event
.GetItem()
670 if item
== self
._treeCtrl
.GetRootItem():
672 self
._draggingItem
= item
676 def OnEndDrag(self
, event
):
677 item
= event
.GetItem()
679 # don't allow object to be dragged to itself
680 if item
== self
._draggingItem
:
683 rootItem
= self
._treeCtrl
.GetRootItem()
685 # don't let object replace root view
687 wx
.MessageBox(_("Cannot replace root view with item."))
690 # don't allow object to be dragged to a direct descendant
691 ancestor
= self
._treeCtrl
.GetItemParent(item
)
692 while ancestor
!= rootItem
:
693 if ancestor
== self
._draggingItem
:
694 wx
.MessageBox(_("Cannot make item direct descendant of self."))
697 ancestor
= self
._treeCtrl
.GetItemParent(ancestor
)
699 if self
._treeCtrl
.GetItemParent(item
) == self
._treeCtrl
.GetItemParent(self
._draggingItem
):
700 # put it in same folder as it was originally, no-op.
702 if item
== self
._treeCtrl
.GetItemParent(self
._draggingItem
):
703 # put it in same folder as it was originally, no-op.
706 self
.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self
, item
, self
._draggingItem
))
709 def WriteProjectConfig(self
):
710 frame
= self
.GetFrame()
711 config
= wx
.ConfigBase_Get()
712 if frame
and not self
._embeddedWindow
:
713 if not frame
.IsMaximized():
714 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0])
715 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1])
716 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0])
717 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1])
718 config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized())
720 if config
.ReadInt("ProjectSaveDocs", True):
721 projectFileNames
= []
724 for projectItem
in self
._GetChildItems
(self
._treeCtrl
.GetRootItem()):
725 project
= self
._GetItemProject
(projectItem
)
726 if not project
.OnSaveModified():
728 if project
.GetDocumentSaved(): # Might be a new document and "No" selected to save it
729 projectFileNames
.append(str(project
.GetFilename()))
730 projectExpanded
.append(self
._treeCtrl
.IsExpanded(projectItem
))
731 config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__())
732 config
.Write("ProjectExpandedSavedDocs", projectExpanded
.__repr
__())
735 def OnClose(self
, deleteWindow
= True):
736 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
737 self
.WriteProjectConfig()
738 project
= self
.GetDocument()
741 if not self
.GetDocument().Close():
745 projectItem
= self
._GetProjectItem
(project
)
747 self
._treeCtrl
.Delete(projectItem
)
748 # We don't need to delete the window since it is a floater/embedded
752 def _GetParentFrame(self
):
753 return wx
.GetTopLevelParent(self
.GetFrame())
756 def OnUpdate(self
, sender
= None, hint
= None):
757 wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
)
760 projectItem
= self
._GetProjectItem
(hint
[1])
762 self
._treeCtrl
.UnselectAll()
763 self
._treeCtrl
.Expand(projectItem
)
766 item
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
767 self
._treeCtrl
.SetData(item
, file)
768 self
._treeCtrl
.SelectItem(item
)
769 self
._treeCtrl
.EnsureVisible(item
)
770 self
._treeCtrl
.SortChildren(projectItem
)
772 self
._treeCtrl
.EnsureVisible(item
) # need to be called after SortChildren
773 elif hint
[0] == "remove":
774 projectItem
= self
._GetProjectItem
(hint
[1])
776 self
._treeCtrl
.UnselectAll()
777 children
= self
._GetChildItems
(projectItem
)
778 for child
in children
:
779 if self
._GetItemFile
(child
) in files
:
780 self
._treeCtrl
.Delete(child
)
781 elif hint
[0] == "select":
782 projectItem
= self
._GetProjectItem
(hint
[1])
784 self
._treeCtrl
.UnselectAll()
785 children
= self
._GetChildItems
(projectItem
)
786 for child
in children
:
787 if self
._GetItemFile
(child
) in files
:
788 self
._treeCtrl
.SelectItem(child
)
789 self
._treeCtrl
.EnsureVisible(child
)
790 elif hint
[0] == "rename":
791 projectItem
= self
._GetProjectItem
(hint
[1])
792 self
._treeCtrl
.SetItemText(projectItem
, os
.path
.basename(hint
[2]))
795 def ProcessEvent(self
, event
):
797 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
798 self
.OnAddFileToProject(event
)
800 elif id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
:
801 self
.OnAddDirToProject(event
)
803 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
804 return False # Implement this one in the service
805 elif id == ProjectService
.RENAME_ID
:
808 elif id == ProjectService
.DELETE_FILE_ID
:
809 self
.OnDeleteFile(event
)
811 elif id == wx
.ID_CUT
:
814 elif id == wx
.ID_COPY
:
817 elif id == wx
.ID_PASTE
:
820 elif (id == wx
.ID_CLEAR
821 or id == ProjectService
.REMOVE_FROM_PROJECT
):
824 elif id == wx
.ID_SELECTALL
:
825 self
.OnSelectAll(event
)
827 elif id == ProjectService
.OPEN_SELECTION_ID
:
828 self
.OnOpenSelection(event
)
830 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
831 self
.OnProperties(event
)
837 def ProcessUpdateUIEvent(self
, event
):
838 # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
839 if self
._checkEditMenu
:
840 doc
= self
.GetDocument()
841 if doc
and not doc
.GetCommandProcessor().GetEditMenu():
842 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
843 self
._checkEditMenu
= False
848 or id == ProjectService
.RENAME_ID
849 or id == ProjectService
.ADD_FILES_TO_PROJECT_ID
850 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
851 or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
852 or id == ProjectService
.DELETE_FILE_ID
):
853 event
.Enable(self
._HasSelection
())
855 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
858 elif id == wx
.ID_PASTE
:
859 event
.Enable(self
.CanPaste())
861 elif id == wx
.ID_SELECTALL
:
862 event
.Enable(self
._HasFiles
())
864 elif (id == wx
.ID_CLEAR
865 or id == ProjectService
.REMOVE_FROM_PROJECT
866 or id == ProjectService
.OPEN_SELECTION_ID
):
867 event
.Enable(self
._HasFilesSelected
())
872 #----------------------------------------------------------------------------
874 #----------------------------------------------------------------------------
877 if not self
.GetFrame():
879 return self
.GetFrame().IsShown()
886 def Show(self
, show
= True):
887 self
.GetFrame().Show(show
)
888 if wx
.GetApp().IsMDI():
889 mdiParentFrame
= wx
.GetApp().GetTopWindow()
890 mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
)
893 #----------------------------------------------------------------------------
894 # Methods for ProjectDocument and ProjectService to call
895 #----------------------------------------------------------------------------
897 def SetExpandedProjects(self
, expandedProjects
):
898 self
._treeCtrl
.UnselectAll()
900 for i
, item
in enumerate(self
._GetChildItems
(self
._treeCtrl
.GetRootItem())):
904 if expandedProjects
[i
]:
905 self
._treeCtrl
.Expand(item
)
907 self
._treeCtrl
.Collapse(item
)
910 self
._treeCtrl
.EnsureVisible(firstItem
)
913 def GetSelectedFile(self
):
914 for item
in self
._treeCtrl
.GetSelections():
915 return self
._GetItemFile
(item
)
918 def GetSelectedFiles(self
):
920 for item
in self
._treeCtrl
.GetSelections():
921 filename
= self
._GetItemFile
(item
)
922 if filename
and filename
not in filenames
:
923 filenames
.append(filename
)
927 def AddProjectToView(self
, document
):
928 rootItem
= self
._treeCtrl
.GetRootItem()
929 projectItem
= self
._treeCtrl
.AppendItem(rootItem
, self
._MakeProjectName
(document
))
930 self
._treeCtrl
.SetData(projectItem
, document
.GetFilename(), document
)
931 for file in document
.GetFiles():
932 fileItem
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
933 self
._treeCtrl
.SetData(fileItem
, file)
934 self
._treeCtrl
.SortChildren(rootItem
)
935 self
._treeCtrl
.SortChildren(projectItem
)
936 self
._treeCtrl
.UnselectAll()
937 self
._treeCtrl
.Expand(projectItem
)
938 self
._treeCtrl
.SelectItem(projectItem
)
939 if self
._embeddedWindow
:
940 document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
944 winWithFocus
= wx
.Window
.FindFocus()
948 if winWithFocus
== self
._treeCtrl
:
950 winWithFocus
= winWithFocus
.GetParent()
954 #----------------------------------------------------------------------------
956 #----------------------------------------------------------------------------
958 def OnProperties(self
, event
):
959 items
= self
._treeCtrl
.GetSelections()
963 if self
._IsItemProject
(item
):
964 projectPropertiesDialog
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
._GetItemProject
(item
).GetFilename())
965 if projectPropertiesDialog
.ShowModal() == wx
.ID_OK
:
967 projectPropertiesDialog
.Destroy()
968 elif self
._IsItemFile
(item
):
969 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
970 filePropertiesService
.ShowPropertiesDialog(self
._GetItemFile
(item
))
973 def OnAddFileToProject(self
, event
):
974 if wx
.Platform
== "__WXMSW__" or wx
.Platform
== "__WXGTK__" or wx
.Platform
== "__WXMAC__":
977 for temp
in self
.GetDocumentManager()._templates
:
980 descr
= descr
+ _('|')
981 allfilter
= allfilter
+ _(';')
982 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
983 allfilter
= allfilter
+ temp
.GetFileFilter()
984 descr
= _("All") + _(" (") + allfilter
+ _(") |") + allfilter
+ _('|') + descr
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
985 descr
= descr
+ _("|") + _("Any (*.*) | *.*")
989 startDirectory
= os
.path
.dirname(self
.GetDocument().GetFilename())
992 dialog
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), startDirectory
, "", descr
, wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
)
993 if dialog
.ShowModal() != wx
.ID_OK
:
995 paths
= dialog
.GetPaths()
998 paths
= wx
.FileSelector(_("Add Files"), startDirectory
, "", wildcard
= descr
, flags
= wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
, parent
=self
.GetFrame())
999 if type(paths
) == types
.StringType
:
1002 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
))
1003 self
.Activate(True) # after add, should put focus on project editor
1006 def OnAddDirToProject(self
, event
):
1007 frame
= wx
.Dialog(None, -1, _("Add Directory Files to Project"), size
= (320,200))
1008 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1010 flexGridSizer
= wx
.FlexGridSizer(cols
= 2, vgap
=HALF_SPACE
, hgap
=HALF_SPACE
)
1011 flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER_VERTICAL
, 0)
1012 lineSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1013 dirCtrl
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(250,-1))
1014 dirCtrl
.SetToolTipString(dirCtrl
.GetValue())
1015 lineSizer
.Add(dirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND
)
1016 findDirButton
= wx
.Button(frame
, -1, _("Browse..."))
1017 lineSizer
.Add(findDirButton
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, HALF_SPACE
)
1018 flexGridSizer
.Add(lineSizer
, 1, wx
.EXPAND
)
1020 def OnBrowseButton(event
):
1021 dlg
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
)
1022 dir = dirCtrl
.GetValue()
1025 if dlg
.ShowModal() == wx
.ID_OK
:
1026 dirCtrl
.SetValue(dlg
.GetPath())
1027 dirCtrl
.SetToolTipString(dirCtrl
.GetValue())
1028 dirCtrl
.SetInsertionPointEnd()
1031 wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
)
1033 visibleTemplates
= []
1034 for template
in self
.GetDocumentManager()._templates
:
1035 if template
.IsVisible():
1036 visibleTemplates
.append(template
)
1041 for template
in visibleTemplates
:
1043 descr
= descr
+ _('|')
1044 allfilter
= allfilter
+ _(';')
1045 descr
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")")
1046 choices
.append(descr
)
1047 allfilter
= allfilter
+ template
.GetFileFilter()
1048 choices
.insert(0, _("All (%s)") % allfilter
)
1049 filterChoice
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
)
1050 filterChoice
.SetSelection(0)
1051 filterChoice
.SetToolTipString(_("Select file type filter."))
1052 flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
1053 flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
)
1055 contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
)
1057 subfolderCtrl
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories"))
1058 subfolderCtrl
.SetValue(True)
1059 contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
)
1061 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
1062 findBtn
= wx
.Button(frame
, wx
.ID_OK
, _("Add"))
1063 findBtn
.SetDefault()
1064 buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
1065 buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0)
1066 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
1068 frame
.SetSizer(contentSizer
)
1071 status
= frame
.ShowModal()
1074 while status
== wx
.ID_OK
and not passedCheck
:
1075 if not os
.path
.exists(dirCtrl
.GetValue()):
1076 dlg
= wx
.MessageDialog(frame
,
1077 _("'%s' does not exist.") % dirCtrl
.GetValue(),
1078 _("Find in Directory"),
1079 wx
.OK | wx
.ICON_EXCLAMATION
1084 status
= frame
.ShowModal()
1088 if status
== wx
.ID_OK
:
1091 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
1093 doc
= self
.GetDocument()
1094 searchSubfolders
= subfolderCtrl
.IsChecked()
1095 dirString
= dirCtrl
.GetValue()
1097 if os
.path
.isfile(dirString
):
1098 # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter.
1099 # We'll assume they know what they're doing.
1104 index
= filterChoice
.GetSelection()
1106 template
= visibleTemplates
[index
-1]
1108 # do search in files on disk
1109 for root
, dirs
, files
in os
.walk(dirString
):
1110 if not searchSubfolders
and root
!= dirString
:
1114 if index
== 0: # all
1115 for template
in visibleTemplates
:
1116 if template
.FileMatchesTemplate(name
):
1117 filename
= os
.path
.join(root
, name
)
1119 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1120 if doc
.IsFileInProject(filename
):
1123 paths
.append(filename
)
1125 else: # use selected filter
1126 if template
.FileMatchesTemplate(name
):
1127 filename
= os
.path
.join(root
, name
)
1128 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
1129 if not doc
.IsFileInProject(filename
):
1130 paths
.append(filename
)
1132 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
1134 doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
))
1135 self
.Activate(True) # after add, should put focus on project editor
1140 def DoAddFilesToProject(self
, filenames
):
1141 # method used by Drag-n-Drop to add files to current Project
1142 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
))
1145 def DoSelectFiles(self
, filenames
):
1146 # method used by Drag-n-Drop to select files in current Project
1147 self
._treeCtrl
.UnselectAll()
1148 for file in filenames
:
1149 item
= self
._GetFileItem
(longFileName
=file)
1151 self
._treeCtrl
.SelectItem(item
, True)
1152 self
._treeCtrl
.EnsureVisible(item
)
1155 def DoSelectProject(self
, x
, y
):
1156 # method used by Drag-n-Drop to set current Project based on cursor position
1157 item
, flag
= self
._treeCtrl
.HitTest((x
,y
))
1161 project
= self
._GetItemProject
(item
)
1165 projectItem
= self
._GetProjectItem
(project
)
1166 self
._treeCtrl
.UnselectAll()
1167 self
._treeCtrl
.SelectItem(projectItem
)
1171 def OnFocus(self
, event
):
1172 wx
.GetApp().GetDocumentManager().ActivateView(self
)
1176 def OnKillFocus(self
, event
):
1177 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
1178 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
1179 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
1180 childFrame
= wx
.GetApp().GetTopWindow().GetActiveChild()
1182 childFrame
.Activate()
1186 def OnRightClick(self
, event
):
1188 if not self
._treeCtrl
.GetSelections():
1190 if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]):
1191 return # Don't do a menu if it's just the root item selected
1193 if self
._HasFilesSelected
(): # Files context
1194 menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection"))
1195 menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True)
1196 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
)
1198 for item
in self
._treeCtrl
.GetSelections():
1199 if self
._IsItemProcessModelFile
(item
):
1200 itemIDs
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None]
1202 else: # Project context
1203 itemIDs
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None]
1204 menuBar
= self
._GetParentFrame
().GetMenuBar()
1205 itemIDs
= itemIDs
+ [ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
]
1207 itemIDs
= itemIDs
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
]
1208 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
]
1209 for itemID
in itemIDs
:
1211 menu
.AppendSeparator()
1213 if itemID
== ProjectService
.RUN_SELECTED_PM_ID
:
1214 menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process"))
1215 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
)
1216 elif itemID
== ProjectService
.REMOVE_FROM_PROJECT
:
1217 menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project"))
1218 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
)
1219 wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
)
1221 item
= menuBar
.FindItemById(itemID
)
1223 menu
.Append(itemID
, item
.GetLabel())
1224 self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY()))
1228 def OnRunSelectedPM(self
, event
):
1229 projectService
= wx
.GetApp().GetService(ProjectService
)
1231 projectService
.OnRunProcessModel(event
, runSelected
=True)
1234 def OnRename(self
, event
):
1235 if self
._treeCtrl
.GetSelections():
1236 self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0])
1239 def OnBeginLabelEdit(self
, event
):
1240 self
._editingSoDontKillFocus
= True
1241 item
= event
.GetItem()
1242 if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
):
1246 def OnEndLabelEdit(self
, event
):
1247 self
._editingSoDontKillFocus
= False
1248 item
= event
.GetItem()
1249 newName
= event
.GetLabel()
1250 if not newName
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)):
1253 if self
._IsItemFile
(item
):
1254 oldFile
= self
._GetItemFile
(item
)
1255 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1256 project
= self
._GetItemProject
(item
)
1257 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
)):
1260 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0]))
1261 elif self
._IsItemProject
(item
):
1262 oldFile
= self
._GetItemProject
(item
).GetFilename()
1263 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
1264 project
= self
._GetItemProject
(item
)
1265 if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
, True)):
1268 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
1272 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
1273 #fileDataObject = wx.FileDataObject()
1274 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
1275 if not wx
.TheClipboard
.IsOpened():
1276 if wx
.TheClipboard
.Open():
1277 fileDataObject
= wx
.FileDataObject()
1278 hasFilesInClipboard
= wx
.TheClipboard
.GetData(fileDataObject
)
1279 wx
.TheClipboard
.Close()
1281 hasFilesInClipboard
= False
1282 return hasFilesInClipboard
1285 def OnCut(self
, event
):
1290 def OnCopy(self
, event
):
1291 fileDataObject
= wx
.FileDataObject()
1292 items
= self
._treeCtrl
.GetSelections()
1294 if self
._IsItemFile
(item
):
1295 file = self
._treeCtrl
.GetLongFilename(item
)
1296 fileDataObject
.AddFile(file)
1297 if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open():
1298 wx
.TheClipboard
.SetData(fileDataObject
)
1299 wx
.TheClipboard
.Close()
1302 def OnPaste(self
, event
):
1303 if wx
.TheClipboard
.Open():
1304 fileDataObject
= wx
.FileDataObject()
1305 if wx
.TheClipboard
.GetData(fileDataObject
):
1306 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames()))
1307 wx
.TheClipboard
.Close()
1310 def OnClear(self
, event
):
1311 items
= self
._treeCtrl
.GetSelections()
1314 if self
._IsItemFile
(item
):
1315 files
.append((self
._GetItemProject
(item
), self
._GetItemFile
(item
)))
1316 self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files
))
1319 def OnDeleteFile(self
, event
):
1320 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1321 _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"),
1323 wx
.YES_NO|wx
.ICON_QUESTION
)
1324 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1327 items
= self
._treeCtrl
.GetSelections()
1331 if self
._IsItemFile
(item
):
1332 filename
= self
._GetItemFile
(item
)
1333 files
.append((self
._GetItemProject
(item
), filename
))
1334 if filename
not in delFiles
:
1335 delFiles
.append(filename
)
1337 # remove selected files from projects
1340 proj
, filename
= data
1341 if proj
not in projects
:
1342 projects
.append(proj
)
1343 for project
in projects
:
1346 proj
, filename
= data
1348 filenames
.append(filename
)
1349 project
.RemoveFiles(filenames
)
1351 # remove selected files from file system
1352 for filename
in delFiles
:
1353 if os
.path
.exists(filename
):
1357 wx
.MessageBox("Could not delete '%s'. %s" % (os
.path
.basename(filename
), sys
.exc_value
),
1359 wx
.OK | wx
.ICON_EXCLAMATION
)
1362 def OnKeyPressed(self
, event
):
1363 key
= event
.KeyCode()
1364 if key
== wx
.WXK_DELETE
:
1370 def OnSelectAll(self
, event
):
1371 project
= self
.GetDocument()
1373 self
._treeCtrl
.UnselectAll()
1374 for child
in self
._GetChildItems
(self
._GetProjectItem
(project
)):
1375 self
._treeCtrl
.SelectItem(child
)
1378 def OnOpenSelectionSDI(self
, event
):
1379 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1380 wx
.CallAfter(self
.OnOpenSelection
, None)
1383 def OnOpenSelection(self
, event
):
1386 items
= self
._treeCtrl
.GetSelections()
1388 if self
._IsItemFile
(item
):
1389 filepath
= self
._GetItemFile
(item
)
1390 if not os
.path
.exists(filepath
):
1391 msgTitle
= wx
.GetApp().GetAppName()
1393 msgTitle
= _("File Not Found")
1394 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1395 _("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
)),
1397 wx
.YES_NO|wx
.ICON_QUESTION
1399 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1401 findFile
= wx
.FileDialog(self
.GetFrame(),
1403 wx
.lib
.docview
.PathOnly(filepath
),
1404 wx
.lib
.docview
.FileNameFromPath(filepath
),
1407 if findFile
.ShowModal() == wx
.ID_OK
and findFile
.GetPath():
1408 newpath
= findFile
.GetPath()
1413 # update Project Model with new location
1414 project
= self
._GetItemProject
(item
)
1415 project
.RemoveFile(filepath
)
1416 project
.AddFile(newpath
)
1419 doc
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
)
1421 shortFilename
= self
._treeCtrl
.GetItemText(item
)
1422 if shortFilename
.endswith(".agp"):
1423 projItem
= self
._GetProjectItem
(shortFilename
=shortFilename
)
1424 self
._treeCtrl
.UnselectAll()
1425 if not self
._treeCtrl
.IsExpanded(projItem
):
1426 self
._treeCtrl
.Expand(projItem
)
1427 if not self
._treeCtrl
.IsVisible(projItem
):
1428 self
._treeCtrl
.EnsureVisible(projItem
)
1429 if not self
._treeCtrl
.IsSelected(projItem
):
1430 self
._treeCtrl
.SelectItem(projItem
)
1432 except IOError, (code
, message
):
1433 msgTitle
= wx
.GetApp().GetAppName()
1435 msgTitle
= _("File Error")
1436 wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
),
1438 wx
.OK | wx
.ICON_EXCLAMATION
,
1442 #----------------------------------------------------------------------------
1443 # Convenience methods
1444 #----------------------------------------------------------------------------
1446 def _HasFiles(self
):
1447 if not self
._treeCtrl
:
1449 return self
._treeCtrl
.GetCount() > 1 # 1 item = root item, don't count as having files
1452 def _HasSelection(self
):
1453 if not self
._treeCtrl
:
1456 items
= self
._treeCtrl
.GetSelections()
1463 def _HasFilesSelected(self
):
1464 if not self
._treeCtrl
:
1466 items
= self
._treeCtrl
.GetSelections()
1470 if not self
._IsItemFile
(item
):
1475 def _MakeProjectName(self
, project
):
1476 return project
.GetPrintableName()
1479 # Return the tree item for a project
1480 def _GetProjectItem(self
, project
=None, shortFilename
=None):
1481 rootItem
= self
._treeCtrl
.GetRootItem()
1482 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1485 if self
._treeCtrl
.GetProjectDoc(child
) == project
:
1488 if self
._treeCtrl
.GetItemText(child
) == shortFilename
:
1490 (child
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1494 # Returns the project for an item, either for a project item or a file that is part of a project
1495 def _GetItemProject(self
, item
):
1496 if self
._IsItemRoot
(item
):
1498 if self
._IsItemProject
(item
):
1499 return self
._treeCtrl
.GetProjectDoc(item
)
1500 if self
._IsItemFile
(item
):
1501 return self
._treeCtrl
.GetProjectDoc(self
._treeCtrl
.GetItemParent(item
))
1505 def _GetItemFile(self
, item
):
1506 if self
._IsItemFile
(item
):
1507 return self
._treeCtrl
.GetLongFilename(item
)
1512 def _GetFileItem(self
, shortFileName
= None, longFileName
= None):
1513 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1515 rootItem
= self
._treeCtrl
.GetRootItem()
1516 (project
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
)
1517 while project
.IsOk():
1518 (child
, cookie2
) = self
._treeCtrl
.GetFirstChild(project
)
1521 if self
._treeCtrl
.GetItemText(child
) == shortFileName
:
1524 if self
._treeCtrl
.GetLongFilename(child
) == longFileName
:
1526 (child
, cookie2
) = self
._treeCtrl
.GetNextChild(project
, cookie2
)
1527 (project
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
)
1531 def _IsItemRoot(self
, item
):
1532 return item
== self
._treeCtrl
.GetRootItem()
1535 def _IsItemProject(self
, item
):
1536 return self
._treeCtrl
.GetProjectDoc(item
) != None
1539 def _IsItemFile(self
, item
):
1540 return self
._treeCtrl
.GetProjectDoc(item
) == None
1543 def _IsItemProcessModelFile(self
, item
):
1544 if ACTIVEGRID_BASE_IDE
:
1547 if self
._IsItemFile
(item
):
1548 filename
= self
._treeCtrl
.GetLongFilename(item
)
1550 for template
in self
.GetDocumentManager().GetTemplates():
1551 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1552 ext
= template
.GetDefaultExtension()
1557 if filename
.endswith(ext
):
1563 def _GetChildItems(self
, parentItem
):
1565 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
)
1567 children
.append(child
)
1568 (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
)
1573 class ProjectFileDropTarget(wx
.FileDropTarget
):
1575 def __init__(self
, view
):
1576 wx
.FileDropTarget
.__init
__(self
)
1580 def OnDropFiles(self
, x
, y
, filenames
):
1581 if self
._view
.DoSelectProject(x
, y
):
1582 self
._view
.DoAddFilesToProject(filenames
)
1583 self
._view
.DoSelectFiles(filenames
)
1588 def OnDragOver(self
, x
, y
, default
):
1589 if self
._view
.DoSelectProject(x
,y
):
1594 class ProjectPropertiesDialog(wx
.Dialog
):
1597 def __init__(self
, parent
, filename
):
1598 wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size
= (310, 330))
1600 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
1602 notebook
= wx
.Notebook(self
, -1)
1603 tab
= wx
.Panel(notebook
, -1)
1605 gridSizer
= RowColSizer()
1607 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0)
1608 if os
.path
.isfile(filename
):
1609 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1)
1611 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0)
1612 gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1)
1614 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0)
1615 gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1)
1617 lineSizer
= wx
.BoxSizer(wx
.VERTICAL
) # let the line expand horizontally without vertical expansion
1618 lineSizer
.Add(wx
.StaticLine(tab
, -1, size
= (10,-1)), 0, wx
.EXPAND
)
1619 gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2)
1621 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0)
1622 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1)
1624 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0)
1625 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1)
1627 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0)
1628 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1)
1631 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1)
1633 # add a border around the inside of the tab
1634 spacerGrid
= wx
.BoxSizer(wx
.VERTICAL
)
1635 spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
);
1636 tab
.SetSizer(spacerGrid
)
1637 notebook
.AddPage(tab
, _("General"))
1638 if wx
.Platform
== "__WXMSW__":
1639 notebook
.SetPageSize((310,200))
1641 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1642 sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
)
1643 sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
)
1645 self
.SetSizer(sizer
)
1650 class ProjectOptionsPanel(wx
.Panel
):
1653 def __init__(self
, parent
, id):
1654 wx
.Panel
.__init
__(self
, parent
, id)
1655 self
._useSashMessageShown
= False
1656 config
= wx
.ConfigBase_Get()
1657 self
._projSaveDocsCheckBox
= wx
.CheckBox(self
, -1, _("Remember open projects"))
1658 self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True))
1659 projectBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1660 projectSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1661 projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1662 if not ACTIVEGRID_BASE_IDE
:
1663 self
._projShowWelcomeCheckBox
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog"))
1664 self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True))
1665 projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1666 projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
)
1667 self
.SetSizer(projectBorderSizer
)
1669 parent
.AddPage(self
, _("Project"))
1671 def OnUseSashSelect(self
, event
):
1672 if not self
._useSashMessageShown
:
1673 msgTitle
= wx
.GetApp().GetAppName()
1675 msgTitle
= _("Document Options")
1676 wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1678 wx
.OK | wx
.ICON_INFORMATION
,
1680 self
._useSashMessageShown
= True
1683 def OnOK(self
, optionsDialog
):
1684 config
= wx
.ConfigBase_Get()
1685 config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue())
1686 if not ACTIVEGRID_BASE_IDE
:
1687 config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue())
1690 class ProjectService(Service
.Service
):
1692 #----------------------------------------------------------------------------
1694 #----------------------------------------------------------------------------
1695 SHOW_WINDOW
= wx
.NewId() # keep this line for each subclass, need unique ID for each Service
1696 RUNPM_ID
= wx
.NewId()
1697 RUN_SELECTED_PM_ID
= wx
.NewId()
1698 RUN_CURRENT_PM_ID
= wx
.NewId()
1699 ADD_FILES_TO_PROJECT_ID
= wx
.NewId()
1700 ADD_CURRENT_FILE_TO_PROJECT_ID
= wx
.NewId()
1701 RENAME_ID
= wx
.NewId()
1702 OPEN_SELECTION_ID
= wx
.NewId()
1703 REMOVE_FROM_PROJECT
= wx
.NewId()
1704 DELETE_FILE_ID
= wx
.NewId()
1705 ADD_ALL_FILES_TO_PROJECT_ID
= wx
.NewId()
1708 #----------------------------------------------------------------------------
1709 # Overridden methods
1710 #----------------------------------------------------------------------------
1712 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1713 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1714 self
._runHandlers
= []
1715 self
._suppressOpenProjectMessages
= False
1718 def _CreateView(self
):
1719 return ProjectView(self
)
1722 def ShowWindow(self
, show
= True):
1723 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1724 Service
.Service
.ShowWindow(self
, show
)
1727 project
= self
.GetView().GetDocument()
1729 self
.OpenSavedProjects()
1732 #----------------------------------------------------------------------------
1733 # Service specific methods
1734 #----------------------------------------------------------------------------
1736 def GetSuppressOpenProjectMessages(self
):
1737 return self
._suppressOpenProjectMessages
1740 def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
):
1741 self
._suppressOpenProjectMessages
= suppressOpenProjectMessages
1744 def GetRunHandlers(self
):
1745 return self
._runHandlers
1748 def AddRunHandler(self
, runHandler
):
1749 self
._runHandlers
.append(runHandler
)
1752 def RemoveRunHandler(self
, runHandler
):
1753 self
._runHandlers
.remove(runHandler
)
1756 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1757 Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
1759 projectMenu
= wx
.Menu()
1761 ## accelTable = wx.AcceleratorTable([
1762 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1764 ## frame.SetAcceleratorTable(accelTable)
1765 isProjectDocument
= document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1766 if wx
.GetApp().IsMDI() or isProjectDocument
:
1767 if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
):
1768 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project"))
1769 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1770 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1771 if not menuBar
.FindItemById(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
):
1772 projectMenu
.Append(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project"))
1773 wx
.EVT_MENU(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1774 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1775 if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
):
1776 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1777 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
)
1778 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1779 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
1780 menuBar
.Insert(viewMenuIndex
+ 1, projectMenu
, _("&Project"))
1781 editMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit")))
1782 if not menuBar
.FindItemById(ProjectService
.RENAME_ID
):
1783 editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item"))
1784 wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
)
1785 wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
)
1786 if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
):
1787 editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system."))
1788 wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
)
1789 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
)
1794 def OnCloseFrame(self
, event
):
1795 if not self
.GetView():
1798 if wx
.GetApp().IsMDI():
1799 # close all non-project documents first
1800 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1801 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1802 if not self
.GetDocumentManager().CloseDocument(document
, False):
1805 # write project config afterwards because user may change filenames on closing of new documents
1806 self
.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1808 # close all project documents after closing other documents
1809 # because user may save a new document with a new name or cancel closing a document
1810 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1811 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1812 if not document
.OnSaveModified():
1815 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1816 elif self
.GetView() == event
.GetEventObject().GetView():
1821 #----------------------------------------------------------------------------
1822 # Event Processing Methods
1823 #----------------------------------------------------------------------------
1825 def ProcessEventBeforeWindows(self
, event
):
1827 if id == wx
.ID_CLOSE_ALL
:
1828 self
.OnFileCloseAll(event
)
1833 def ProcessEvent(self
, event
):
1834 if Service
.Service
.ProcessEvent(self
, event
):
1838 if id == ProjectService
.RUN_SELECTED_PM_ID
:
1839 self
.OnRunProcessModel(event
, runSelected
=True)
1841 elif id == ProjectService
.RUN_CURRENT_PM_ID
:
1842 self
.OnRunProcessModel(event
, runCurrentFile
=True)
1844 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1845 self
.OnAddCurrentFileToProject(event
)
1847 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1849 return self
.GetView().ProcessEvent(event
)
1856 def ProcessUpdateUIEvent(self
, event
):
1857 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1861 if (id == ProjectService
.RUNPM_ID
1862 or id == ProjectService
.RUN_SELECTED_PM_ID
1863 or id == ProjectService
.RUN_CURRENT_PM_ID
):
1864 event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
())
1866 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1867 event
.Enable(self
._CanAddCurrentFileToProject
())
1869 elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
1870 or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
1871 or id == ProjectService
.RENAME_ID
1872 or id == ProjectService
.OPEN_SELECTION_ID
1873 or id == ProjectService
.DELETE_FILE_ID
):
1876 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1878 return self
.GetView().ProcessUpdateUIEvent(event
)
1885 def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False):
1886 project
= self
.GetView().GetDocument()
1890 for template
in self
.GetDocumentManager().GetTemplates():
1891 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1892 ext
= template
.GetDefaultExtension()
1897 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1901 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1903 if doc
.GetFilename() in files
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1904 if not doc
.GetProcessModel().beginProcess
:
1905 wx
.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1908 filesModified
= False
1910 if doc
.IsModified():
1911 filesModified
= True
1914 frame
= self
.GetView().GetFrame()
1915 yesNoMsg
= wx
.MessageDialog(frame
,
1916 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1918 wx
.YES_NO|wx
.ICON_QUESTION
1920 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1921 wx
.GetTopLevelParent(frame
).OnFileSaveAll(None)
1924 fileToRun
= self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1926 fileToRun
= self
.GetView().GetSelectedFile()
1927 elif len(files
) > 1:
1928 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
1929 strings
= map(lambda file: os
.path
.basename(file), files
)
1930 res
= wx
.GetSingleChoiceIndex(_("Select a process to run:"),
1933 project
.GetFirstView()._GetParentFrame
())
1936 fileToRun
= files
[res
]
1938 fileToRun
= files
[0]
1940 self
.RunProcessModel(fileToRun
)
1943 def RunProcessModel(self
, fileToRun
):
1944 for runHandler
in self
.GetRunHandlers():
1945 if runHandler
.RunProjectFile(fileToRun
):
1947 os
.system('"' + fileToRun
+ '"')
1950 def _HasProcessModel(self
):
1951 project
= self
.GetView().GetDocument()
1955 for template
in self
.GetDocumentManager().GetTemplates():
1956 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1957 ext
= template
.GetDefaultExtension()
1962 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1972 def _HasOpenedProjects(self
):
1973 for document
in self
.GetDocumentManager().GetDocuments():
1974 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1979 def _HasCurrentFile(self
):
1980 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1984 def _CanAddCurrentFileToProject(self
):
1985 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1988 if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1990 if not currentDoc
._savedYet
:
1992 for document
in self
.GetDocumentManager().GetDocuments():
1993 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1995 return False # There are no documents open
1998 def GetFilesFromCurrentProject(self
):
1999 view
= self
.GetView()
2001 project
= view
.GetDocument()
2003 return project
.GetFiles()
2007 def GetCurrentProject(self
):
2008 view
= self
.GetView()
2010 return view
.GetDocument()
2014 def FindProjectByFile(self
, filename
):
2015 for document
in self
.GetDocumentManager().GetDocuments():
2016 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2017 if document
.GetFilename() == filename
:
2019 elif document
.IsFileInProject(filename
):
2024 def GetCurrentProjectNames(self
):
2026 for document
in self
.GetDocumentManager().GetDocuments():
2027 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2028 projects
.append(document
)
2031 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2032 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2036 def OnAddCurrentFileToProject(self
, event
):
2037 if not self
._CanAddCurrentFileToProject
():
2040 for document
in self
.GetDocumentManager().GetDocuments():
2041 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
2042 projects
.append(document
)
2045 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
2046 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
2047 res
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"),
2048 _("Add to Project"),
2050 self
.GetDocumentManager().FindSuitableParent())
2053 file = self
.GetDocumentManager().GetCurrentDocument().GetFilename()
2054 projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file]))
2055 self
.GetView().Activate(True) # after add, should put focus on project editor
2058 def OnFileCloseAll(self
, event
):
2059 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
2060 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
2061 if not self
.GetDocumentManager().CloseDocument(document
, False):
2063 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
2066 def OpenSavedProjects(self
):
2067 config
= wx
.ConfigBase_Get()
2069 if config
.ReadInt("ProjectSaveDocs", True):
2070 docString
= config
.Read("ProjectSavedDocs")
2073 for fileName
in eval(docString
):
2074 if isinstance(fileName
, types
.StringTypes
):
2075 if os
.path
.exists(fileName
):
2076 doc
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
)
2080 expandedString
= config
.Read("ProjectExpandedSavedDocs")
2082 view
= doc
.GetFirstView()
2083 view
.SetExpandedProjects(eval(expandedString
))
2087 class ProjectEditorMoveCommand(wx
.lib
.docview
.Command
):
2089 def __init__(self
, view
, newPositionItem
, item
):
2090 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
2093 self
._file
= view
._treeCtrl
.GetLongFilename(item
)
2094 if view
._IsItemFile
(item
):
2095 self
._projectOld
= view
._GetItemProject
(item
)
2096 else: # view._IsItemProject(item):
2097 self
._projectOld
= None
2098 self
._projectNew
= view
._GetItemProject
(newPositionItem
)
2102 return _("Move File %s") % os
.path
.basename(self
._file
)
2106 if self
._projectOld
:
2107 self
._projectOld
.RemoveFile(self
._file
)
2108 if self
._projectNew
:
2109 self
._projectNew
.AddFile(self
._file
)
2114 if self
._projectNew
:
2115 self
._projectNew
.RemoveFile(self
._file
)
2116 if self
._projectOld
:
2117 self
._projectOld
.AddFile(self
._file
)
2121 #----------------------------------------------------------------------------
2122 # Icon Bitmaps - generated by encode_bitmaps.py
2123 #----------------------------------------------------------------------------
2124 from wx
import ImageFromStream
, BitmapFromImage
2128 def getProjectData():
2130 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2131 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2132 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
2133 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
2134 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
2135 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
2137 def getProjectBitmap():
2138 return BitmapFromImage(getProjectImage())
2140 def getProjectImage():
2141 stream
= cStringIO
.StringIO(getProjectData())
2142 return ImageFromStream(stream
)
2144 def getProjectIcon():
2145 return wx
.IconFromBitmap(getProjectBitmap())
2148 #----------------------------------------------------------------------------
2152 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2153 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2154 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
2155 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
2156 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
2157 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
2158 \x00\x00IEND\xaeB`\x82'
2161 def getBlankBitmap():
2162 return BitmapFromImage(getBlankImage())
2164 def getBlankImage():
2165 stream
= cStringIO
.StringIO(getBlankData())
2166 return ImageFromStream(stream
)
2169 return wx
.IconFromBitmap(getBlankBitmap())