1 #----------------------------------------------------------------------------
2 # Name: ProjectEditor.py
3 # Purpose: IDE-style Project Editor for wx.lib.pydocview
5 # Author: Peter Yared, Morgan Hua
9 # Copyright: (c) 2003, 2004, 2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
14 import wx
.lib
.pydocview
19 from wxPython
.lib
.rcsizer
import RowColSizer
23 import DebuggerService
25 import activegrid
.util
.xmlmarshaller
27 from IDE
import ACTIVEGRID_BASE_IDE
28 if not ACTIVEGRID_BASE_IDE
:
29 import ProcessModelEditor
33 if wx
.Platform
== '__WXMSW__':
39 #----------------------------------------------------------------------------
40 # XML Marshalling Methods
41 #----------------------------------------------------------------------------
42 LOCAL_TYPE_MAPPING
= { "projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel", }
45 xml
= fileObject
.read()
46 projectModel
= activegrid
.util
.xmlmarshaller
.unmarshal(xml
, knownTypes
=LOCAL_TYPE_MAPPING
)
50 def save(fileObject
, projectModel
):
51 xml
= activegrid
.util
.xmlmarshaller
.marshal(projectModel
, prettyPrint
=True, knownTypes
=LOCAL_TYPE_MAPPING
)
55 #----------------------------------------------------------------------------
57 #----------------------------------------------------------------------------
60 __xmlname__
= "projectmodel"
61 __xmlrename__
= { "_files":"files", "_homepath":"homepath" }
68 class ProjectDocument(wx
.lib
.docview
.Document
):
71 wx
.lib
.docview
.Document
.__init
__(self
)
72 self
._projectModel
= ProjectModel()
76 return self
._projectModel
79 def OnCreate(self
, path
, flags
):
80 projectService
= wx
.GetApp().GetService(ProjectService
)
81 if projectService
.GetView():
82 view
= projectService
.GetView()
85 view
= self
.GetDocumentTemplate().CreateView(self
, flags
)
86 projectService
.SetView(view
)
90 def LoadObject(self
, fileObject
):
91 self
._projectModel
= activegrid
.tool
.ProjectEditor
.load(fileObject
)
95 def SaveObject(self
, fileObject
):
96 activegrid
.tool
.ProjectEditor
.save(fileObject
, self
._projectModel
)
100 def OnSaveDocument(self
, filename
):
101 self
._projectModel
._homepath
= wx
.lib
.docview
.PathOnly(filename
)
102 return wx
.lib
.docview
.Document
.OnSaveDocument(self
, filename
)
105 def OnOpenDocument(self
, filename
):
106 view
= self
.GetFirstView()
107 frame
= view
.GetFrame()
109 if not os
.path
.exists(filename
):
110 wx
.GetApp().CloseSplash()
111 msgTitle
= wx
.GetApp().GetAppName()
113 msgTitle
= _("File Error")
114 wx
.MessageBox(_("Could not find '%s'.") % filename
,
116 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
118 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
120 fileObject
= file(filename
, 'r')
122 self
.LoadObject(fileObject
)
124 wx
.GetApp().CloseSplash()
125 msgTitle
= wx
.GetApp().GetAppName()
127 msgTitle
= _("File Error")
128 wx
.MessageBox(_("Could not open '%s'. %s") % (wx
.lib
.docview
.FileNameFromPath(filename
), sys
.exc_value
),
130 wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
,
132 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
136 # if the project file has moved, then ask the user if we should readjust the paths of all the files in the project
137 newHomepath
= wx
.lib
.docview
.PathOnly(filename
)
138 if newHomepath
!= self
._projectModel
._homepath
:
139 wx
.GetApp().CloseSplash()
140 msgTitle
= wx
.GetApp().GetAppName()
142 msgTitle
= _("Project Moved")
143 projectService
= wx
.GetApp().GetService(activegrid
.tool
.ProjectEditor
.ProjectService
)
144 yesNoMsg
= wx
.MessageDialog(frame
,
145 _("The project file '%s' was moved from:\n '%s'\nto:\n '%s'.\n\nWould you like to automatically adjust the project contents accordingly?") % (wx
.lib
.docview
.FileNameFromPath(filename
), self
._projectModel
._homepath
, wx
.lib
.docview
.PathOnly(filename
)),
147 wx
.YES_NO | wx
.STAY_ON_TOP
149 if projectService
.GetSuppressOpenProjectMessages() or yesNoMsg
.ShowModal() == wx
.ID_YES
:
150 if not projectService
.GetSuppressOpenProjectMessages():
151 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
152 messageService
.ShowWindow()
153 messageView
= messageService
.GetView()
154 messageView
.ClearLines()
155 messageView
.AddLines(_("The project file '%s' was moved from:\n '%s'\nto:\n '%s'\n") % (wx
.lib
.docview
.FileNameFromPath(filename
), self
._projectModel
._homepath
, wx
.lib
.docview
.PathOnly(filename
)))
156 messageView
.AddLines(_("Updating file references:\n"))
158 for index
, filepath
in enumerate(self
._projectModel
._files
):
159 if filepath
.startswith(self
._projectModel
._homepath
+ os
.sep
):
160 newfile
= newHomepath
+ filepath
[len(self
._projectModel
._homepath
):len(filepath
)]
161 if os
.path
.exists(newfile
):
162 self
._projectModel
._files
[index
] = newfile
163 if not projectService
.GetSuppressOpenProjectMessages():
164 messageView
.AddLines(_(" Success: '%s' location changed from '%s' to '%s'\n") % (wx
.lib
.docview
.FileNameFromPath(filepath
), wx
.lib
.docview
.PathOnly(filepath
), newHomepath
))
167 if not projectService
.GetSuppressOpenProjectMessages():
168 messageView
.AddLines(_(" Failure: Couldn't find '%s', file wasn't located at '%s'\n") % (wx
.lib
.docview
.FileNameFromPath(filepath
), newHomepath
))
170 if not projectService
.GetSuppressOpenProjectMessages():
171 messageView
.AddLines(_( " Unmodified: '%s' location wasn't relative to '%s'\n") % (filepath
, self
._projectModel
._homepath
))
172 self
._projectModel
._homepath
= newHomepath
173 if not projectService
.GetSuppressOpenProjectMessages():
174 messageView
.AddLines(_("Project file updated."))
176 self
.SetFilename(filename
, True)
177 view
.AddProjectToView(self
)
178 self
.SetDocumentModificationDate()
179 self
.UpdateAllViews()
180 self
._savedYet
= True
185 def AddFile(self
, file):
186 return self
.AddFiles([file])
189 def AddFiles(self
, files
):
190 notAlreadyThereFiles
= filter(lambda x
: x
not in self
._projectModel
._files
, files
) # Filter to the files that are not already in the project
191 if len(notAlreadyThereFiles
) == 0:
192 self
.UpdateAllViews(hint
= ("select", self
, files
))
195 self
._projectModel
._files
= self
._projectModel
._files
+ notAlreadyThereFiles
196 self
.UpdateAllViews(hint
= ("add", self
, notAlreadyThereFiles
))
201 def RemoveFile(self
, file):
202 return self
.RemoveFiles([file])
205 def RemoveFiles(self
, files
):
207 self
._projectModel
._files
.remove(file)
208 self
.UpdateAllViews(hint
= ("remove", self
, files
))
213 def RenameFile(self
, oldFile
, newFile
, isProject
= False):
215 if oldFile
== newFile
:
218 # projects don't have to exist yet, so not required to rename old file,
219 # but files must exist, so we'll try to rename and allow exceptions to occur if can't.
220 if not isProject
or (isProject
and os
.path
.exists(oldFile
)):
221 os
.rename(oldFile
, newFile
)
224 documents
= self
.GetDocumentManager().GetDocuments()
225 for document
in documents
:
226 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
227 document
.SetFilename(newFile
)
228 document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFile
))
229 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
231 self
.RemoveFile(oldFile
)
232 self
.AddFile(newFile
)
233 documents
= self
.GetDocumentManager().GetDocuments()
234 for document
in documents
:
235 if document
.GetFilename() == oldFile
: # If the renamed document is open, update it
236 document
.SetFilename(newFile
, notifyViews
= True)
237 document
.UpdateAllViews(hint
= ("rename", document
, newFile
))
239 except OSError, (code
, message
):
240 msgTitle
= wx
.GetApp().GetAppName()
242 msgTitle
= _("File Error")
243 wx
.MessageBox("Could not rename '%s'. '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFile
), message
),
245 wx
.OK | wx
.ICON_EXCLAMATION
,
246 self
.GetFirstView().GetFrame())
251 return self
._projectModel
._files
254 def IsFileInProject(self
, filename
):
255 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
)
271 def CreateProjectLocation(self
,wizard
):
272 page
= Wizard
.TitledWizardPage(wizard
, _("Project File Location"))
274 page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n")))
275 self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation
= UICommon
.CreateDirectoryControl(page
, _("File Name:"), _("Directory:"), _("agp"), startingDirectory
=os
.getcwd())
276 page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
)
279 wizard
.FitToPage(page
)
282 def RunWizard(self
, existingTables
= None, existingRelationships
= None):
283 status
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
)
285 docManager
= wx
.GetApp().GetTopWindow().GetDocumentManager()
286 if os
.path
.exists(self
._fullProjectPath
):
287 # What if the document is already open and we're overwriting it?
288 documents
= docManager
.GetDocuments()
289 for document
in documents
:
290 if document
.GetFilename() == self
._fullProjectPath
: # If the renamed document is open, update it
291 document
.DeleteAllViews()
293 os
.remove(self
._fullProjectPath
)
295 for template
in docManager
.GetTemplates():
296 if template
.GetDocumentType() == ProjectDocument
:
297 doc
= template
.CreateDocument(self
._fullProjectPath
, flags
= wx
.lib
.docview
.DOC_NEW
)
298 doc
.OnSaveDocument(self
._fullProjectPath
)
299 view
= doc
.GetFirstView()
300 view
.AddProjectToView(doc
)
307 def OnWizPageChanging(self
, event
):
308 if event
.GetDirection(): # It's going forwards
309 if event
.GetPage() == self
._projectLocationPage
:
310 if not self
._fileValidation
():
313 self
._fullProjectPath
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(),'.agp'))
317 def OnShowCreatePages(self
):
319 import DataModelEditor
320 requestedPos
= self
.GetPositionTuple()
321 projectService
= wx
.GetApp().GetService(ProjectService
)
322 projectView
= projectService
.GetView()
324 wiz
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
)
325 if wiz
.RunWizard(dontDestroy
=True):
326 self
._schemaName
.SetValue(wiz
.GetSchemaFileName())
330 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
):
332 def CreateDocument(self
, path
, flags
):
334 return wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
)
336 wiz
= NewProjectWizard(wx
.GetApp().GetTopWindow())
339 return None # never return the doc, otherwise docview will think it is a new file and rename it
341 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
):
343 def __init__(self
, projectDoc
, files
):
344 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
345 self
._projectDoc
= projectDoc
350 if len(self
._files
) == 1:
353 return _("Add Files")
357 return self
._projectDoc
.AddFiles(self
._files
)
361 return self
._projectDoc
.RemoveFiles(self
._files
)
364 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
):
366 def __init__(self
, projectDoc
, files
):
367 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
368 self
._projectDoc
= projectDoc
373 if len(self
._files
) == 1:
374 return _("Remove File")
376 return _("Remove Files")
380 return self
._projectDoc
.RemoveFiles(self
._files
)
384 return self
._projectDoc
.AddFiles(self
._files
)
387 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
):
389 def __init__(self
, projectDoc
, oldFile
, newFile
, isProject
= False):
390 wx
.lib
.docview
.Command
.__init
__(self
, canUndo
= True)
391 self
._projectDoc
= projectDoc
392 self
._oldFile
= oldFile
393 self
._newFile
= newFile
394 self
._isProject
= isProject
398 return _("Rename File")
402 return self
._projectDoc
.RenameFile(self
._oldFile
, self
._newFile
, self
._isProject
)
406 return self
._projectDoc
.RenameFile(self
._newFile
, self
._oldFile
, self
._isProject
)
409 class ProjectTreeCtrl(wx
.TreeCtrl
):
411 def __init__(self
, parent
, id, style
):
412 wx
.TreeCtrl
.__init
__(self
, parent
, id, style
= style
)
414 templates
= wx
.GetApp().GetDocumentManager().GetTemplates()
415 iconList
= wx
.ImageList(16, 16, initialCount
= len(templates
))
416 self
._iconIndexLookup
= []
417 for template
in templates
:
418 icon
= template
.GetIcon()
420 if icon
.GetHeight() != 16:
421 icon
.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
422 if icon
.GetWidth() != 16:
423 icon
.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
424 iconIndex
= iconList
.AddIcon(icon
)
425 self
._iconIndexLookup
.append((template
, iconIndex
))
427 icon
= getBlankIcon()
428 if icon
.GetHeight() != 16:
429 icon
.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
430 if icon
.GetWidth() != 16:
431 icon
.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
432 self
._blankIconIndex
= iconList
.AddIcon(icon
)
433 self
.AssignImageList(iconList
)
436 def OnCompareItems(self
, item1
, item2
):
437 return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower())
440 def AppendItem(self
, parent
, filepath
):
441 item
= wx
.TreeCtrl
.AppendItem(self
, parent
, filepath
)
444 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filepath
)
445 if not template
and parent
== self
.GetRootItem(): # If the parent is a root it's a new project
446 template
= wx
.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
448 for t
, iconIndex
in self
._iconIndexLookup
:
450 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
)
451 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
)
452 self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Selected
)
457 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
)
458 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
)
459 self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Selected
)
464 class ProjectView(wx
.lib
.docview
.View
):
467 #----------------------------------------------------------------------------
469 #----------------------------------------------------------------------------
471 def __init__(self
, service
= None):
472 wx
.lib
.docview
.View
.__init
__(self
)
473 self
._service
= service
# not used, but kept to match other Services
474 self
._lastDirectory
= ""
475 self
._treeCtrl
= None
476 self
._editingSoDontKillFocus
= False
477 self
._checkEditMenu
= True
481 projectService
= wx
.GetApp().GetService(ProjectService
)
483 projectService
.SetView(None)
484 wx
.lib
.docview
.View
.Destroy(self
)
487 def GetDocument(self
):
488 if not self
._treeCtrl
:
491 items
= self
._treeCtrl
.GetSelections()
492 if not items
: # No selection, so just return first project
493 item
= self
._treeCtrl
.GetFirstVisibleItem()
495 return self
._GetItemProject
(item
)
500 project
= self
._GetItemProject
(item
)
507 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
508 return wx
.GetApp().GetDocumentManager()
511 def OnChangeFilename(self
):
513 title
= _("Projects")
514 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
515 title
= title
+ " - " + wx
.GetApp().GetAppName()
516 self
.GetFrame().SetTitle(title
)
517 project
= self
.GetDocument()
519 projectItem
= self
._GetProjectItem
(project
)
520 name
= self
._treeCtrl
.GetItemText(self
._GetProjectItem
(project
))
521 name2
= self
._MakeProjectName
(project
)
523 self
._treeCtrl
.SetItemText(projectItem
, name2
)
524 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
527 def Activate(self
, activate
= True):
528 if not wx
.GetApp().IsMDI():
529 if activate
and not self
.IsShown():
533 wx
.lib
.docview
.View
.Activate(self
, activate
= activate
)
534 if activate
and self
._treeCtrl
:
535 self
._treeCtrl
.SetFocus()
538 def OnCreate(self
, doc
, flags
):
539 config
= wx
.ConfigBase_Get()
540 if wx
.GetApp().IsMDI():
541 self
._embeddedWindow
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
)
542 self
.SetFrame(self
._embeddedWindow
)
543 frame
= self
._embeddedWindow
545 self
._embeddedWindow
= None
546 pos
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1)
547 # make sure frame is visible
548 screenWidth
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
)
549 screenHeight
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
)
550 if pos
[0] < 0 or pos
[0] >= screenWidth
or pos
[1] < 0 or pos
[1] >= screenHeight
:
551 pos
= wx
.DefaultPosition
553 size
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1))
555 title
= _("Projects")
556 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
and wx
.GetApp().GetAppName():
557 title
= title
+ " - " + wx
.GetApp().GetAppName()
559 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title
= title
, pos
= pos
, size
= size
)
560 if config
.ReadInt("ProjectFrameMaximized", False):
563 sizer
= wx
.BoxSizer()
564 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
)
565 self
._treeCtrl
.AddRoot(_("Projects"))
567 if self
._embeddedWindow
:
568 sizer
.Add(self
._treeCtrl
)
571 sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
, 0)
572 frame
.SetSizer(sizer
)
576 if wx
.GetApp().IsMDI():
577 wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
)
578 wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
)
580 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
581 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
)
583 wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
)
584 wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
)
585 wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
)
586 wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
)
587 wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
)
588 # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
590 # drag-and-drop support
591 dt
= ProjectFileDropTarget(self
)
592 self
._treeCtrl
.SetDropTarget(dt
)
597 def WriteProjectConfig(self
):
598 frame
= self
.GetFrame()
599 config
= wx
.ConfigBase_Get()
600 if frame
and not self
._embeddedWindow
:
601 if not frame
.IsMaximized():
602 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0])
603 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1])
604 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0])
605 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1])
606 config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized())
608 if config
.ReadInt("ProjectSaveDocs", True):
609 projectFileNames
= []
612 for projectItem
in self
._GetChildItems
(self
._treeCtrl
.GetRootItem()):
613 project
= self
._GetItemProject
(projectItem
)
614 if not project
.OnSaveModified():
616 if project
.GetDocumentSaved(): # Might be a new document and "No" selected to save it
617 projectFileNames
.append(str(project
.GetFilename()))
618 projectExpanded
.append(self
._treeCtrl
.IsExpanded(projectItem
))
619 config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__())
620 config
.Write("ProjectExpandedSavedDocs", projectExpanded
.__repr
__())
623 def OnClose(self
, deleteWindow
= True):
624 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
625 self
.WriteProjectConfig()
626 project
= self
.GetDocument()
629 if not self
.GetDocument().Close():
633 projectItem
= self
._GetProjectItem
(project
)
635 self
._treeCtrl
.Delete(projectItem
)
636 # We don't need to delete the window since it is a floater/embedded
640 def _GetParentFrame(self
):
641 return wx
.GetTopLevelParent(self
.GetFrame())
644 def OnUpdate(self
, sender
= None, hint
= None):
645 wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
)
648 projectItem
= self
._GetProjectItem
(hint
[1])
650 self
._treeCtrl
.UnselectAll()
651 self
._treeCtrl
.Expand(projectItem
)
653 item
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
654 self
._treeCtrl
.SetPyData(item
, file)
655 self
._treeCtrl
.SelectItem(item
)
656 self
._treeCtrl
.EnsureVisible(item
) # wxBug: Doesn't work
657 self
._treeCtrl
.SortChildren(projectItem
)
658 elif hint
[0] == "remove":
659 projectItem
= self
._GetProjectItem
(hint
[1])
661 children
= self
._GetChildItems
(projectItem
)
662 for child
in children
:
663 if self
._GetItemFile
(child
) in files
:
664 self
._treeCtrl
.Delete(child
)
665 elif hint
[0] == "select":
666 projectItem
= self
._GetProjectItem
(hint
[1])
668 self
._treeCtrl
.UnselectAll()
669 children
= self
._GetChildItems
(projectItem
)
670 for child
in children
:
671 if self
._GetItemFile
(child
) in files
:
672 self
._treeCtrl
.SelectItem(child
)
673 self
._treeCtrl
.EnsureVisible(child
) # wxBug: Doesn't work
674 elif hint
[0] == "rename":
675 projectItem
= self
._GetProjectItem
(hint
[1])
676 self
._treeCtrl
.SetItemText(projectItem
, os
.path
.basename(hint
[2]))
679 def ProcessEvent(self
, event
):
681 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
682 self
.OnAddFileToProject(event
)
684 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
685 return False # Implement this one in the service
686 elif id == ProjectService
.RENAME_ID
:
689 elif id == wx
.ID_CUT
:
692 elif id == wx
.ID_COPY
:
695 elif id == wx
.ID_PASTE
:
698 elif id == wx
.ID_CLEAR
or id == ProjectService
.REMOVE_FROM_PROJECT
:
701 elif id == wx
.ID_SELECTALL
:
702 self
.OnSelectAll(event
)
704 elif id == ProjectService
.OPEN_SELECTION_ID
:
705 self
.OnOpenSelection(event
)
707 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
708 self
.OnProperties(event
)
713 def ProcessUpdateUIEvent(self
, event
):
714 # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
715 if self
._checkEditMenu
:
716 doc
= self
.GetDocument()
717 if doc
and not doc
.GetCommandProcessor().GetEditMenu():
718 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
719 self
._checkEditMenu
= False
721 if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
722 event
.Enable(self
._HasProjectsSelected
() or self
._HasFilesSelected
())
724 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
727 elif id == ProjectService
.RENAME_ID
:
728 event
.Enable(self
._HasFilesSelected
() or self
._HasProjectsSelected
())
730 elif id == wx
.ID_CUT
:
731 event
.Enable(self
._AreSelectedItemsFromSameProject
())
733 elif id == wx
.ID_COPY
:
734 event
.Enable(self
._HasFilesSelected
())
736 elif id == wx
.ID_PASTE
:
737 event
.Enable(self
.CanPaste())
739 elif id == wx
.ID_CLEAR
or id == ProjectService
.REMOVE_FROM_PROJECT
:
740 event
.Enable(self
._AreSelectedItemsFromSameProject
())
742 elif id == wx
.ID_SELECTALL
:
743 event
.Enable(self
._HasFiles
())
745 elif id == ProjectService
.OPEN_SELECTION_ID
:
746 event
.Enable(self
._HasFilesSelected
())
748 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
749 event
.Enable(self
._HasProjectsSelected
() or self
._HasFilesSelected
())
754 #----------------------------------------------------------------------------
756 #----------------------------------------------------------------------------
759 if not self
.GetFrame():
761 return self
.GetFrame().IsShown()
768 def Show(self
, show
= True):
769 self
.GetFrame().Show(show
)
770 if wx
.GetApp().IsMDI():
771 mdiParentFrame
= wx
.GetApp().GetTopWindow()
772 mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
)
775 #----------------------------------------------------------------------------
776 # Methods for ProjectDocument and ProjectService to call
777 #----------------------------------------------------------------------------
779 def SetExpandedProjects(self
, expandedProjects
):
780 self
._treeCtrl
.UnselectAll()
782 for i
, item
in enumerate(self
._GetChildItems
(self
._treeCtrl
.GetRootItem())):
786 if expandedProjects
[i
]:
787 self
._treeCtrl
.Expand(item
)
789 self
._treeCtrl
.Collapse(item
)
792 self
._treeCtrl
.EnsureVisible(firstItem
)
795 def GetSelectedFile(self
):
796 for item
in self
._treeCtrl
.GetSelections():
797 return self
._GetItemFile
(item
)
800 def AddProjectToView(self
, document
):
801 rootItem
= self
._treeCtrl
.GetRootItem()
802 projectItem
= self
._treeCtrl
.AppendItem(rootItem
, self
._MakeProjectName
(document
))
803 self
._treeCtrl
.SetPyData(projectItem
, document
)
804 for file in document
.GetFiles():
805 fileItem
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file))
806 self
._treeCtrl
.SetPyData(fileItem
, file)
807 self
._treeCtrl
.SortChildren(rootItem
)
808 self
._treeCtrl
.SortChildren(projectItem
)
809 self
._treeCtrl
.UnselectAll()
810 self
._treeCtrl
.Expand(projectItem
)
811 self
._treeCtrl
.SelectItem(projectItem
)
812 if self
._embeddedWindow
:
813 document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
()))
816 #----------------------------------------------------------------------------
818 #----------------------------------------------------------------------------
820 def OnProperties(self
, event
):
821 items
= self
._treeCtrl
.GetSelections()
825 if self
._IsItemProject
(item
):
826 projectPropertiesDialog
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
._GetItemProject
(item
).GetFilename())
827 if projectPropertiesDialog
.ShowModal() == wx
.ID_OK
:
829 projectPropertiesDialog
.Destroy()
830 elif self
._IsItemFile
(item
):
831 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
832 filePropertiesService
.ShowPropertiesDialog(self
._GetItemFile
(item
))
835 def OnAddFileToProject(self
, event
):
836 if wx
.Platform
== "__WXMSW__" or wx
.Platform
== "__WXGTK__" or wx
.Platform
== "__WXMAC__":
839 for temp
in self
.GetDocumentManager()._templates
:
842 descr
= descr
+ _('|')
843 allfilter
= allfilter
+ _(';')
844 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
845 allfilter
= allfilter
+ temp
.GetFileFilter()
846 descr
= _("All") + _(" (") + allfilter
+ _(") |") + allfilter
+ _('|') + descr
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
847 descr
= descr
+ _("|") + _("Any (*.*) | *.*")
851 dialog
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), self
._lastDirectory
, "", descr
, wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
)
852 if dialog
.ShowModal() != wx
.ID_OK
:
854 paths
= dialog
.GetPaths()
857 paths
= wx
.FileSelector(_("Add Files"), self
._lastDirectory
, "", wildcard
= descr
, flags
= wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
, parent
=self
.GetFrame())
858 if type(paths
) == types
.StringType
:
861 self
._lastDirectory
= wx
.lib
.docview
.PathOnly(paths
[0])
862 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
))
863 self
.Activate(True) # after add, should put focus on project editor
866 def DoAddFilesToProject(self
, filenames
):
867 # method used by Drag-n-Drop to add files to current Project
868 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
))
871 def DoSelectFiles(self
, filenames
):
872 # method used by Drag-n-Drop to select files in current Project
873 for selection
in self
._treeCtrl
.GetSelections():
874 self
._treeCtrl
.SelectItem(selection
, False)
875 for file in filenames
:
876 item
= self
._GetFileItem
(longFileName
=file)
878 self
._treeCtrl
.SelectItem(item
, True)
879 self
._treeCtrl
.EnsureVisible(item
)
882 def DoSelectProject(self
, x
, y
):
883 # method used by Drag-n-Drop to set current Project based on cursor position
884 item
, flag
= self
._treeCtrl
.HitTest((x
,y
))
888 project
= self
._GetItemProject
(item
)
892 projectItem
= self
._GetProjectItem
(project
)
893 self
._treeCtrl
.UnselectAll()
894 self
._treeCtrl
.SelectItem(projectItem
)
898 def OnFocus(self
, event
):
899 wx
.GetApp().GetDocumentManager().ActivateView(self
)
903 def OnKillFocus(self
, event
):
904 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
905 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
906 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
907 childFrame
= wx
.GetApp().GetTopWindow().GetActiveChild()
909 childFrame
.Activate()
913 def OnRightClick(self
, event
):
915 if not self
._treeCtrl
.GetSelections():
917 if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]):
918 return # Don't do a menu if it's just the root item selected
920 if self
._HasFilesSelected
(): # Files context
921 menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection"))
922 menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True)
923 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
)
925 for item
in self
._treeCtrl
.GetSelections():
926 if self
._IsItemProcessModelFile
(item
):
927 itemIDs
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None]
929 else: # Project context
930 itemIDs
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None]
931 menuBar
= self
._GetParentFrame
().GetMenuBar()
932 itemIDs
= itemIDs
+ [wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
, None, ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
, None, wx
.ID_UNDO
, wx
.ID_REDO
, None, wx
.ID_CUT
, wx
.ID_COPY
, wx
.ID_PASTE
, wx
.ID_CLEAR
, None, wx
.ID_SELECTALL
, None, ProjectService
.RENAME_ID
]
933 for itemID
in itemIDs
:
935 menu
.AppendSeparator()
937 if itemID
== ProjectService
.RUN_SELECTED_PM_ID
:
938 menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process"))
939 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
)
940 elif itemID
== ProjectService
.REMOVE_FROM_PROJECT
:
941 menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project"))
942 wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
)
943 wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
)
945 item
= menuBar
.FindItemById(itemID
)
947 menu
.Append(itemID
, item
.GetLabel())
948 self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY()))
951 def OnRunSelectedPM(self
, event
):
952 projectService
= wx
.GetApp().GetService(ProjectService
)
953 projectService
.OnRunProcessModel(event
, runSelected
=True)
955 def OnRename(self
, event
):
956 if self
._treeCtrl
.GetSelections():
957 self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0])
960 def OnBeginLabelEdit(self
, event
):
961 self
._editingSoDontKillFocus
= True
962 item
= event
.GetItem()
963 if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
):
967 def OnEndLabelEdit(self
, event
):
968 self
._editingSoDontKillFocus
= False
969 item
= event
.GetItem()
970 newName
= event
.GetLabel()
971 if not newName
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)):
974 if self
._IsItemFile
(item
):
975 oldFile
= self
._GetItemFile
(item
)
976 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
977 if not self
._GetItemProject
(item
).GetCommandProcessor().Submit(ProjectRenameFileCommand(self
.GetDocument(), oldFile
, newFile
)):
980 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0]))
981 elif self
._IsItemProject
(item
):
982 oldFile
= self
._GetItemProject
(item
).GetFilename()
983 newFile
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
)
984 if not self
._GetItemProject
(item
).GetCommandProcessor().Submit(ProjectRenameFileCommand(self
.GetDocument(), oldFile
, newFile
, True)):
987 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem())
991 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
992 #fileDataObject = wx.FileDataObject()
993 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
994 if not wx
.TheClipboard
.IsOpened():
995 if wx
.TheClipboard
.Open():
996 fileDataObject
= wx
.FileDataObject()
997 hasFilesInClipboard
= wx
.TheClipboard
.GetData(fileDataObject
)
998 wx
.TheClipboard
.Close()
1000 hasFilesInClipboard
= False
1001 return hasFilesInClipboard
1004 def OnCut(self
, event
):
1005 if self
._AreSelectedItemsFromSameProject
():
1010 def OnCopy(self
, event
):
1011 fileDataObject
= wx
.FileDataObject()
1012 items
= self
._treeCtrl
.GetSelections()
1014 if self
._IsItemFile
(item
):
1015 file = self
._treeCtrl
.GetPyData(item
)
1016 fileDataObject
.AddFile(file)
1017 if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open():
1018 wx
.TheClipboard
.SetData(fileDataObject
)
1019 wx
.TheClipboard
.Close()
1022 def OnPaste(self
, event
):
1023 if wx
.TheClipboard
.Open():
1024 fileDataObject
= wx
.FileDataObject()
1025 if wx
.TheClipboard
.GetData(fileDataObject
):
1026 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames()))
1027 wx
.TheClipboard
.Close()
1030 def OnClear(self
, event
):
1031 if self
._AreSelectedItemsFromSameProject
():
1032 items
= self
._treeCtrl
.GetSelections()
1035 if self
._IsItemFile
(item
):
1036 files
.append(self
._GetItemFile
(item
))
1037 self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self
._GetItemProject
(items
[0]), files
))
1040 def OnKeyPressed(self
, event
):
1041 key
= event
.KeyCode()
1042 if key
== wx
.WXK_DELETE
:
1048 def OnSelectAll(self
, event
):
1049 project
= self
.GetDocument()
1051 self
._treeCtrl
.UnselectAll()
1052 for child
in self
._GetChildItems
(self
._GetProjectItem
(project
)):
1053 self
._treeCtrl
.SelectItem(child
)
1056 def OnOpenSelectionSDI(self
, event
):
1057 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1058 wx
.CallAfter(self
.OnOpenSelection
, None)
1061 def OnOpenSelection(self
, event
):
1064 items
= self
._treeCtrl
.GetSelections()
1066 if self
._IsItemFile
(item
):
1067 filepath
= self
._GetItemFile
(item
)
1068 if not os
.path
.exists(filepath
):
1069 msgTitle
= wx
.GetApp().GetAppName()
1071 msgTitle
= _("File Not Found")
1072 yesNoMsg
= wx
.MessageDialog(self
.GetFrame(),
1073 _("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
)),
1077 if yesNoMsg
.ShowModal() == wx
.ID_NO
:
1079 findFile
= wx
.FileDialog(self
.GetFrame(),
1081 wx
.lib
.docview
.PathOnly(filepath
),
1082 wx
.lib
.docview
.FileNameFromPath(filepath
),
1085 if findFile
.ShowModal() == wx
.ID_OK
and findFile
.GetPath():
1086 newpath
= findFile
.GetPath()
1091 # update Project Model with new location
1092 self
.GetDocument().RemoveFile(filepath
)
1093 self
.GetDocument().AddFile(newpath
)
1096 doc
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
)
1098 except IOError, (code
, message
):
1099 msgTitle
= wx
.GetApp().GetAppName()
1101 msgTitle
= _("File Error")
1102 wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
),
1104 wx
.OK | wx
.ICON_EXCLAMATION
,
1108 #----------------------------------------------------------------------------
1109 # Convenience methods
1110 #----------------------------------------------------------------------------
1112 def _HasFiles(self
):
1113 if not self
._treeCtrl
:
1115 return self
._treeCtrl
.GetCount() > 1 # 1 item = root item, don't count as having files
1118 def _HasProjectsSelected(self
):
1119 if not self
._treeCtrl
:
1121 items
= self
._treeCtrl
.GetSelections()
1125 if self
._IsItemProject
(item
):
1130 def _HasFilesSelected(self
):
1131 if not self
._treeCtrl
:
1133 items
= self
._treeCtrl
.GetSelections()
1137 if not self
._IsItemFile
(item
):
1142 def _MakeProjectName(self
, project
):
1143 return project
.GetPrintableName()
1146 # Return the tree item for a project
1147 def _GetProjectItem(self
, project
):
1148 children
= self
._GetChildItems
(self
._treeCtrl
.GetRootItem())
1149 for child
in children
:
1150 if self
._treeCtrl
.GetPyData(child
) == project
:
1155 # Returns the project for an item, either for a project item or a file that is part of a project
1156 def _GetItemProject(self
, item
):
1157 if self
._IsItemRoot
(item
):
1159 if self
._IsItemProject
(item
):
1160 return self
._treeCtrl
.GetPyData(item
)
1161 if self
._IsItemFile
(item
):
1162 return self
._treeCtrl
.GetPyData(self
._treeCtrl
.GetItemParent(item
))
1166 def _GetItemFile(self
, item
):
1167 if self
._IsItemFile
(item
):
1168 return self
._treeCtrl
.GetPyData(item
)
1173 def _GetFileItem(self
, shortFileName
= None, longFileName
= None):
1174 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1177 project_children
= self
._GetChildItems
(self
._treeCtrl
.GetRootItem())
1178 for child
in project_children
:
1179 file_children
= self
._GetChildItems
(child
)
1180 for file_child
in file_children
:
1181 if self
._treeCtrl
.GetItemText(file_child
) == shortFileName
:
1185 project_children
= self
._GetChildItems
(self
._treeCtrl
.GetRootItem())
1186 for child
in project_children
:
1187 file_children
= self
._GetChildItems
(child
)
1188 for file_child
in file_children
:
1189 if self
._treeCtrl
.GetPyData(file_child
) == longFileName
:
1194 def GetFilePathFromTreeName(self
, shortFileName
):
1196 Returns the data object given a short (display) file name for a file. The data
1197 object should be the full path.
1199 return self
._GetItemFile
(self
._GetFileItem
(shortFileName
))
1202 def SelectFileInTree(self
, shortFileName
):
1203 item
= self
._GetFileItem
(shortFileName
)
1205 for selection
in self
._treeCtrl
.GetSelections():
1206 self
._treeCtrl
.SelectItem(selection
, False)
1207 self
._treeCtrl
.SelectItem(item
, True)
1208 self
._treeCtrl
.EnsureVisible(item
)
1211 def _IsItemRoot(self
, item
):
1212 return item
== self
._treeCtrl
.GetRootItem()
1215 def _IsItemProject(self
, item
):
1216 return isinstance(self
._treeCtrl
.GetPyData(item
), ProjectDocument
)
1219 def _IsItemFile(self
, item
):
1220 return isinstance(self
._treeCtrl
.GetPyData(item
), types
.StringTypes
)
1223 def _IsItemProcessModelFile(self
, item
):
1224 if ACTIVEGRID_BASE_IDE
:
1227 if isinstance(self
._treeCtrl
.GetPyData(item
), types
.StringTypes
):
1228 filename
= self
._treeCtrl
.GetPyData(item
)
1230 for template
in self
.GetDocumentManager().GetTemplates():
1231 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1232 ext
= template
.GetDefaultExtension()
1237 if filename
.endswith(ext
):
1243 def _AreSelectedItemsFromSameProject(self
):
1244 if not self
._treeCtrl
:
1246 items
= self
._treeCtrl
.GetSelections()
1249 project
= self
._GetItemProject
(items
[0])
1253 if not self
._IsItemFile
(item
):
1255 if self
._GetItemProject
(item
) != project
:
1260 def _GetChildItems(self
, parentItem
):
1262 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
)
1264 children
.append(child
)
1265 (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
)
1270 class ProjectFileDropTarget(wx
.FileDropTarget
):
1272 def __init__(self
, view
):
1273 wx
.FileDropTarget
.__init
__(self
)
1277 def OnDropFiles(self
, x
, y
, filenames
):
1278 if self
._view
.DoSelectProject(x
, y
):
1279 self
._view
.DoAddFilesToProject(filenames
)
1280 self
._view
.DoSelectFiles(filenames
)
1285 def OnDragOver(self
, x
, y
, default
):
1286 if self
._view
.DoSelectProject(x
,y
):
1291 class ProjectPropertiesDialog(wx
.Dialog
):
1294 def __init__(self
, parent
, filename
):
1295 wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size
= (310, 330))
1300 filePropertiesService
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
)
1302 notebook
= wx
.Notebook(self
, -1)
1303 tab
= wx
.Panel(notebook
, -1)
1305 gridSizer
= RowColSizer()
1307 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0)
1308 if os
.path
.isfile(filename
):
1309 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1)
1311 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0)
1312 gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1)
1314 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0)
1315 gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1)
1317 lineSizer
= wx
.BoxSizer(wx
.VERTICAL
) # let the line expand horizontally without vertical expansion
1318 lineSizer
.Add(wx
.StaticLine(tab
, -1, size
= (10,-1)), 0, wx
.EXPAND
)
1319 gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2)
1321 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0)
1322 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1)
1324 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0)
1325 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1)
1327 gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0)
1328 gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1)
1331 gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1)
1333 # add a border around the inside of the tab
1334 spacerGrid
= wx
.BoxSizer(wx
.VERTICAL
)
1335 spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
);
1336 tab
.SetSizer(spacerGrid
)
1337 notebook
.AddPage(tab
, _("General"))
1338 if wx
.Platform
== "__WXMSW__":
1339 notebook
.SetPageSize((310,200))
1341 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
1342 sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
)
1343 sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
)
1346 self
.SetDimensions(-1, -1, 310, -1, wx
.SIZE_USE_EXISTING
)
1347 self
.SetSizer(sizer
)
1351 class ProjectOptionsPanel(wx
.Panel
):
1354 def __init__(self
, parent
, id):
1355 wx
.Panel
.__init
__(self
, parent
, id)
1356 self
._useSashMessageShown
= False
1359 config
= wx
.ConfigBase_Get()
1360 self
._projSaveDocsCheckBox
= wx
.CheckBox(self
, -1, _("Remember open projects"))
1361 self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True))
1362 projectBorderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1363 projectSizer
= wx
.BoxSizer(wx
.VERTICAL
)
1364 projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1365 if not ACTIVEGRID_BASE_IDE
:
1366 self
._projShowWelcomeCheckBox
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog"))
1367 self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True))
1368 projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)
1369 projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
)
1370 self
.SetSizer(projectBorderSizer
)
1372 parent
.AddPage(self
, _("Project"))
1374 def OnUseSashSelect(self
, event
):
1375 if not self
._useSashMessageShown
:
1376 msgTitle
= wx
.GetApp().GetAppName()
1378 msgTitle
= _("Document Options")
1379 wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1381 wx
.OK | wx
.ICON_INFORMATION
,
1383 self
._useSashMessageShown
= True
1386 def OnOK(self
, optionsDialog
):
1387 config
= wx
.ConfigBase_Get()
1388 config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue())
1389 if not ACTIVEGRID_BASE_IDE
:
1390 config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue())
1393 class ProjectService(Service
.Service
):
1395 #----------------------------------------------------------------------------
1397 #----------------------------------------------------------------------------
1398 SHOW_WINDOW
= wx
.NewId() # keep this line for each subclass, need unique ID for each Service
1399 RUNPM_ID
= wx
.NewId()
1400 RUN_SELECTED_PM_ID
= wx
.NewId()
1401 RUN_CURRENT_PM_ID
= wx
.NewId()
1402 ADD_FILES_TO_PROJECT_ID
= wx
.NewId()
1403 ADD_CURRENT_FILE_TO_PROJECT_ID
= wx
.NewId()
1404 RENAME_ID
= wx
.NewId()
1405 OPEN_SELECTION_ID
= wx
.NewId()
1406 REMOVE_FROM_PROJECT
= wx
.NewId()
1409 #----------------------------------------------------------------------------
1410 # Overridden methods
1411 #----------------------------------------------------------------------------
1413 def __init__(self
, serviceName
, embeddedWindowLocation
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
):
1414 Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
)
1415 self
._runHandlers
= []
1416 self
._suppressOpenProjectMessages
= False
1419 def _CreateView(self
):
1420 return ProjectView(self
)
1423 def ShowWindow(self
, show
= True):
1424 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1425 Service
.Service
.ShowWindow(self
, show
)
1428 project
= self
.GetView().GetDocument()
1430 self
.OpenSavedProjects()
1433 #----------------------------------------------------------------------------
1434 # Service specific methods
1435 #----------------------------------------------------------------------------
1437 def GetSuppressOpenProjectMessages(self
):
1438 return self
._suppressOpenProjectMessages
1441 def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
):
1442 self
._suppressOpenProjectMessages
= suppressOpenProjectMessages
1445 def GetRunHandlers(self
):
1446 return self
._runHandlers
1449 def AddRunHandler(self
, runHandler
):
1450 self
._runHandlers
.append(runHandler
)
1453 def RemoveRunHandler(self
, runHandler
):
1454 self
._runHandlers
.remove(runHandler
)
1457 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
1458 Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
1460 config
= wx
.ConfigBase_Get()
1462 projectMenu
= wx
.Menu()
1464 ## accelTable = wx.AcceleratorTable([
1465 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1467 ## frame.SetAcceleratorTable(accelTable)
1468 isProjectDocument
= document
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1469 if wx
.GetApp().IsMDI() or isProjectDocument
:
1470 if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
):
1471 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("&Add Files to Project..."), _("Adds a document to the current project"))
1472 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
)
1473 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1474 if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
):
1475 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1476 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
)
1477 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
)
1478 viewMenuIndex
= menuBar
.FindMenu(_("&View"))
1479 menuBar
.Insert(viewMenuIndex
+ 1, projectMenu
, _("&Project"))
1480 editMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit")))
1481 if not menuBar
.FindItemById(ProjectService
.RENAME_ID
):
1482 editMenu
.AppendSeparator()
1483 editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item"))
1484 wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
)
1485 wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
)
1490 def OnCloseFrame(self
, event
):
1491 if not self
.GetView():
1494 if wx
.GetApp().IsMDI():
1495 # close all non-project documents first
1496 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1497 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1498 if not self
.GetDocumentManager().CloseDocument(document
, False):
1501 # write project config afterwards because user may change filenames on closing of new documents
1502 self
.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1504 # close all project documents after closing other documents
1505 # because user may save a new document with a new name or cancel closing a document
1506 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1507 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1508 if not document
.OnSaveModified():
1511 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1512 elif self
.GetView() == event
.GetEventObject().GetView():
1517 #----------------------------------------------------------------------------
1518 # Event Processing Methods
1519 #----------------------------------------------------------------------------
1521 def ProcessEventBeforeWindows(self
, event
):
1523 if id == wx
.ID_CLOSE_ALL
:
1524 self
.OnFileCloseAll(event
)
1529 def ProcessEvent(self
, event
):
1530 if Service
.Service
.ProcessEvent(self
, event
):
1534 if id == ProjectService
.RUN_SELECTED_PM_ID
:
1535 self
.OnRunProcessModel(event
, runSelected
=True)
1537 elif id == ProjectService
.RUN_CURRENT_PM_ID
:
1538 self
.OnRunProcessModel(event
, runCurrentFile
=True)
1540 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1541 self
.OnAddCurrentFileToProject(event
)
1543 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1545 return self
.GetView().ProcessEvent(event
)
1552 def ProcessUpdateUIEvent(self
, event
):
1553 if Service
.Service
.ProcessUpdateUIEvent(self
, event
):
1557 if id == ProjectService
.RUNPM_ID
or id == ProjectService
.RUN_SELECTED_PM_ID
or id == ProjectService
.RUN_CURRENT_PM_ID
:
1558 event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
())
1560 elif id == ProjectService
.ADD_FILES_TO_PROJECT_ID
:
1563 elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
:
1564 event
.Enable(self
._CanAddCurrentFileToProject
())
1566 elif id == ProjectService
.RENAME_ID
:
1569 elif id == ProjectService
.OPEN_SELECTION_ID
:
1572 elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
:
1574 return self
.GetView().ProcessUpdateUIEvent(event
)
1581 def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False):
1582 project
= self
.GetView().GetDocument()
1586 for template
in self
.GetDocumentManager().GetTemplates():
1587 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1588 ext
= template
.GetDefaultExtension()
1593 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1597 docs
= wx
.GetApp().GetDocumentManager().GetDocuments()
1599 if doc
.GetFilename() in files
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1600 if not doc
.GetProcessModel().beginProcess
:
1601 wx
.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1604 filesModified
= False
1606 if doc
.IsModified():
1607 filesModified
= True
1610 frame
= self
.GetView().GetFrame()
1611 yesNoMsg
= wx
.MessageDialog(frame
,
1612 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1616 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
1617 wx
.GetTopLevelParent(frame
).OnFileSaveAll(None)
1620 fileToRun
= self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1622 fileToRun
= self
.GetView().GetSelectedFile()
1623 elif len(files
) > 1:
1624 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower()))
1625 strings
= map(lambda file: os
.path
.basename(file), files
)
1626 res
= wx
.GetSingleChoiceIndex(_("Select a process to run:"),
1629 project
.GetFirstView()._GetParentFrame
())
1632 fileToRun
= files
[res
]
1634 fileToRun
= files
[0]
1636 self
.RunProcessModel(fileToRun
)
1639 def RunProcessModel(self
, fileToRun
):
1640 for runHandler
in self
.GetRunHandlers():
1641 if runHandler
.RunProjectFile(fileToRun
):
1643 os
.system('"' + fileToRun
+ '"')
1646 def _HasProcessModel(self
):
1647 project
= self
.GetView().GetDocument()
1651 for template
in self
.GetDocumentManager().GetTemplates():
1652 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
:
1653 ext
= template
.GetDefaultExtension()
1658 files
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles())
1668 def _HasOpenedProjects(self
):
1669 for document
in self
.GetDocumentManager().GetDocuments():
1670 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1675 def _HasCurrentFile(self
):
1676 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1680 def _CanAddCurrentFileToProject(self
):
1681 currentDoc
= self
.GetDocumentManager().GetCurrentDocument()
1684 if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1686 if not currentDoc
._savedYet
:
1688 for document
in self
.GetDocumentManager().GetDocuments():
1689 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1691 return False # There are no documents open
1694 def GetFilesFromCurrentProject(self
):
1695 view
= self
.GetView()
1697 project
= view
.GetDocument()
1699 return project
.GetFiles()
1703 def GetCurrentProject(self
):
1704 view
= self
.GetView()
1706 return view
.GetDocument()
1710 def FindProjectByFile(self
, filename
):
1711 for document
in self
.GetDocumentManager().GetDocuments():
1712 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1713 if document
.GetFilename() == filename
:
1715 elif document
.IsFileInProject(filename
):
1720 def GetCurrentProjectNames(self
):
1722 for document
in self
.GetDocumentManager().GetDocuments():
1723 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1724 projects
.append(document
)
1727 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
1728 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
1731 def OnAddCurrentFileToProject(self
, event
):
1732 if not self
._CanAddCurrentFileToProject
():
1735 for document
in self
.GetDocumentManager().GetDocuments():
1736 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
:
1737 projects
.append(document
)
1740 projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower()))
1741 strings
= map(lambda project
: project
.GetPrintableName(), projects
)
1742 res
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"),
1743 _("Add to Project"),
1745 self
.GetDocumentManager().FindSuitableParent())
1748 file = self
.GetDocumentManager().GetCurrentDocument().GetFilename()
1749 projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file]))
1750 self
.GetView().Activate(True) # after add, should put focus on project editor
1753 def OnFileCloseAll(self
, event
):
1754 for document
in self
.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1755 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
:
1756 if not self
.GetDocumentManager().CloseDocument(document
, False):
1758 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
1761 def OpenSavedProjects(self
):
1762 config
= wx
.ConfigBase_Get()
1764 if config
.ReadInt("ProjectSaveDocs", True):
1765 docString
= config
.Read("ProjectSavedDocs")
1768 for fileName
in eval(docString
):
1769 if isinstance(fileName
, types
.StringTypes
):
1770 if os
.path
.exists(fileName
):
1771 doc
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
)
1775 expandedString
= config
.Read("ProjectExpandedSavedDocs")
1777 view
= doc
.GetFirstView()
1778 view
.SetExpandedProjects(eval(expandedString
))
1781 #----------------------------------------------------------------------------
1782 # Icon Bitmaps - generated by encode_bitmaps.py
1783 #----------------------------------------------------------------------------
1784 from wx
import ImageFromStream
, BitmapFromImage
1788 def getProjectData():
1790 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1791 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1792 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
1793 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
1794 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
1795 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
1797 def getProjectBitmap():
1798 return BitmapFromImage(getProjectImage())
1800 def getProjectImage():
1801 stream
= cStringIO
.StringIO(getProjectData())
1802 return ImageFromStream(stream
)
1804 def getProjectIcon():
1805 return wx
.IconFromBitmap(getProjectBitmap())
1808 #----------------------------------------------------------------------------
1812 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1813 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1814 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
1815 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
1816 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
1817 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
1818 \x00\x00IEND\xaeB`\x82'
1821 def getBlankBitmap():
1822 return BitmapFromImage(getBlankImage())
1824 def getBlankImage():
1825 stream
= cStringIO
.StringIO(getBlankData())
1826 return ImageFromStream(stream
)
1829 return wx
.IconFromBitmap(getBlankBitmap())