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())