1 #---------------------------------------------------------------------------- 
   2 # Name:         ProjectEditor.py 
   3 # Purpose:      IDE-style Project Editor for wx.lib.pydocview 
   5 # Author:       Peter Yared, Morgan Hua 
   9 # Copyright:    (c) 2003, 2004, 2005 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  14 import wx
.lib
.pydocview
 
  19 from wxPython
.lib
.rcsizer 
import RowColSizer
 
  23 import activegrid
.util
.xmlutils
 
  27 from IDE 
import ACTIVEGRID_BASE_IDE
 
  28 if not ACTIVEGRID_BASE_IDE
: 
  29     import ProcessModelEditor
 
  30 from SVNService 
import SVN_INSTALLED
 
  34 if wx
.Platform 
== '__WXMSW__': 
  40 #---------------------------------------------------------------------------- 
  42 #---------------------------------------------------------------------------- 
  47 #---------------------------------------------------------------------------- 
  48 # XML Marshalling Methods 
  49 #---------------------------------------------------------------------------- 
  52     return activegrid
.util
.xmlutils
.defaultLoad(fileObject
, knownTypes
={"projectmodel" : ProjectModel}
) 
  54 def save(fileObject
, projectModel
): 
  55     activegrid
.util
.xmlutils
.defaultSave(fileObject
, projectModel
, prettyPrint
=True, knownTypes
={"projectmodel" : ProjectModel}
) 
  58 #---------------------------------------------------------------------------- 
  60 #---------------------------------------------------------------------------- 
  63     __xmlname__ 
= "projectmodel" 
  64     __xmlrename__ 
= { "_files":"files"}
 
  74 class ProjectDocument(wx
.lib
.docview
.Document
): 
  78         wx
.lib
.docview
.Document
.__init
__(self
) 
  79         self
._projectModel 
= ProjectModel() 
  83         return self
._projectModel
 
  86     def OnCreate(self
, path
, flags
): 
  87         projectService 
= wx
.GetApp().GetService(ProjectService
) 
  88         if projectService
.GetView(): 
  89             # All project documents share the same view. 
  90             view 
= projectService
.GetView() 
  93             if view
.GetDocument():     
  94                 # All project documents need to share the same command processor, 
  95                 # to enable redo/undo of cross project document commands 
  96                 cmdProcessor 
= view
.GetDocument().GetCommandProcessor() 
  98                     self
.SetCommandProcessor(cmdProcessor
) 
 100             view 
= self
.GetDocumentTemplate().CreateView(self
, flags
) 
 101             projectService
.SetView(view
) 
 107     def LoadObject(self
, fileObject
): 
 108         self
._projectModel 
= activegrid
.tool
.ProjectEditor
.load(fileObject
) 
 109         self
._projectModel
._files 
= self
.RelativeToAbsPath(self
._projectModel
._files
) 
 113     def SaveObject(self
, fileObject
): 
 114         absPath 
= self
._projectModel
._files
 
 115         self
._projectModel
._files 
= self
.AbsToRelativePath(absPath
)  # temporarily change it to relative paths for saving 
 116         activegrid
.tool
.ProjectEditor
.save(fileObject
, self
._projectModel
) 
 117         self
._projectModel
._files 
= absPath                          
# swap it back to absolute path 
 121     def AbsToRelativePath(self
, paths
): 
 122         curPath 
= os
.path
.dirname(self
.GetFilename()) 
 123         curPathLen 
= len(curPath
) 
 127             if path
.startswith(curPath
): 
 128                 path 
= "." + path
[curPathLen
:]  # use relative path 
 130                     path 
= path
.replace(os
.sep
, '/', -1)  # always save out with '/' as path separator for cross-platform compatibility. 
 132                 pass                            # use absolute path 
 133             newFilePaths
.append(path
) 
 137     def RelativeToAbsPath(self
, paths
): 
 140             if path
.startswith("."):  # relative to project file 
 141                 curPath 
= os
.path
.dirname(self
.GetFilename()) 
 142                 path 
= os
.path
.normpath(os
.path
.join(curPath
, path
)) 
 143             newFilePaths
.append(path
) 
 147     def OnOpenDocument(self
, filename
): 
 148         view 
= self
.GetFirstView() 
 149         frame 
= view
.GetFrame() 
 151         if not os
.path
.exists(filename
): 
 152             wx
.GetApp().CloseSplash() 
 153             msgTitle 
= wx
.GetApp().GetAppName() 
 155                 msgTitle 
= _("File Error") 
 156             wx
.MessageBox(_("Could not find '%s'.") % filename
, 
 158                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 160             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 162         fileObject 
= file(filename
, 'r') 
 164             self
.LoadObject(fileObject
) 
 166             wx
.GetApp().CloseSplash() 
 167             msgTitle 
= wx
.GetApp().GetAppName() 
 169                 msgTitle 
= _("File Error") 
 170             wx
.MessageBox(_("Could not open '%s'.  %s") % (wx
.lib
.docview
.FileNameFromPath(filename
), sys
.exc_value
), 
 172                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 174             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 177         self
.SetFilename(filename
, True) 
 178         view
.AddProjectToView(self
) 
 179         self
.SetDocumentModificationDate() 
 180         self
.UpdateAllViews() 
 181         self
._savedYet 
= True 
 186     def AddFile(self
, file): 
 187         return self
.AddFiles([file]) 
 190     def AddFiles(self
, files
): 
 191         notAlreadyThereFiles 
= filter(lambda x
: x 
not in self
._projectModel
._files
, files
)  # Filter to the files that are not already in the project 
 192         if len(notAlreadyThereFiles
) == 0: 
 193             self
.UpdateAllViews(hint 
= ("select", self
, files
)) 
 196             self
._projectModel
._files 
= self
._projectModel
._files 
+ notAlreadyThereFiles
 
 197             self
.UpdateAllViews(hint 
= ("add", self
, notAlreadyThereFiles
)) 
 202     def RemoveFile(self
, file): 
 203         return self
.RemoveFiles([file]) 
 206     def RemoveFiles(self
, files
): 
 208             self
._projectModel
._files
.remove(file) 
 209         self
.UpdateAllViews(hint 
= ("remove", self
, files
)) 
 214     def RenameFile(self
, oldFile
, newFile
, isProject 
= False): 
 216             if oldFile 
== newFile
: 
 219             # projects don't have to exist yet, so not required to rename old file, 
 220             # but files must exist, so we'll try to rename and allow exceptions to occur if can't. 
 221             if not isProject 
or (isProject 
and os
.path
.exists(oldFile
)): 
 222                 os
.rename(oldFile
, newFile
) 
 225                 documents 
= self
.GetDocumentManager().GetDocuments() 
 226                 for document 
in documents
: 
 227                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFile
):  # If the renamed document is open, update it 
 228                         document
.SetFilename(newFile
) 
 229                         document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFile
)) 
 230                         document
.UpdateAllViews(hint 
= ("rename", document
, newFile
)) 
 232                 self
.RemoveFile(oldFile
) 
 233                 self
.AddFile(newFile
) 
 234                 documents 
= self
.GetDocumentManager().GetDocuments() 
 235                 for document 
in documents
: 
 236                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFile
):  # If the renamed document is open, update it 
 237                         document
.SetFilename(newFile
, notifyViews 
= True) 
 238                         document
.UpdateAllViews(hint 
= ("rename", document
, newFile
)) 
 240         except OSError, (code
, message
): 
 241             msgTitle 
= wx
.GetApp().GetAppName() 
 243                 msgTitle 
= _("File Error") 
 244             wx
.MessageBox("Could not rename '%s'.  '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFile
), message
), 
 246                           wx
.OK | wx
.ICON_EXCLAMATION
, 
 247                           self
.GetFirstView().GetFrame()) 
 252         return self
._projectModel
._files
 
 255     def IsFileInProject(self
, filename
): 
 256         return filename 
in self
.GetFiles() 
 259 class NewProjectWizard(Wizard
.BaseWizard
): 
 261     WIZTITLE 
= _("New Project Wizard") 
 263     def __init__(self
, parent
): 
 264         self
._parent 
= parent
 
 265         self
._fullProjectPath 
= None 
 266         Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
) 
 267         self
._projectLocationPage 
= self
.CreateProjectLocation(self
) 
 268         wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
) 
 271     def CreateProjectLocation(self
,wizard
):    
 272         page 
= Wizard
.TitledWizardPage(wizard
, _("Project File Location")) 
 274         page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n"))) 
 275         self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation 
= UICommon
.CreateDirectoryControl(page
, _("File Name:"), _("Directory:"), _("agp"), startingDirectory
=os
.getcwd()) 
 276         page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
) 
 279         wizard
.FitToPage(page
) 
 283     def RunWizard(self
, existingTables 
= None, existingRelationships 
= None): 
 284         status 
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
) 
 286             docManager 
= wx
.GetApp().GetTopWindow().GetDocumentManager() 
 287             if os
.path
.exists(self
._fullProjectPath
): 
 288                 # What if the document is already open and we're overwriting it? 
 289                 documents 
= docManager
.GetDocuments() 
 290                 for document 
in documents
: 
 291                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(self
._fullProjectPath
):  # If the renamed document is open, update it 
 292                         document
.DeleteAllViews() 
 294                 os
.remove(self
._fullProjectPath
) 
 296             for template 
in docManager
.GetTemplates(): 
 297                 if template
.GetDocumentType() == ProjectDocument
: 
 298                     doc 
= template
.CreateDocument(self
._fullProjectPath
, flags 
= wx
.lib
.docview
.DOC_NEW
) 
 299                     doc
.OnSaveDocument(self
._fullProjectPath
)  
 300                     view 
= doc
.GetFirstView() 
 301                     view
.AddProjectToView(doc
) 
 308     def OnWizPageChanging(self
, event
): 
 309         if event
.GetDirection():  # It's going forwards 
 310             if event
.GetPage() == self
._projectLocationPage
: 
 311                 if not self
._fileValidation
(): 
 314                 self
._fullProjectPath 
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(),'.agp')) 
 318     def OnShowCreatePages(self
):                     
 320         import DataModelEditor
 
 321         requestedPos 
= self
.GetPositionTuple() 
 322         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 323         projectView 
= projectService
.GetView() 
 325         wiz 
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
) 
 326         if wiz
.RunWizard(dontDestroy
=True): 
 327            self
._schemaName
.SetValue(wiz
.GetSchemaFileName()) 
 332 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
): 
 335     def CreateDocument(self
, path
, flags
): 
 337             return wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
) 
 339             wiz 
= NewProjectWizard(wx
.GetApp().GetTopWindow()) 
 342             return None  # never return the doc, otherwise docview will think it is a new file and rename it 
 345 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
): 
 348     def __init__(self
, projectDoc
, files
): 
 349         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
 350         self
._projectDoc 
= projectDoc
 
 355         if len(self
._files
) == 1: 
 356             return _("Add File %s") % os
.path
.basename(self
._files
[0]) 
 358             return _("Add Files") 
 362         return self
._projectDoc
.AddFiles(self
._files
) 
 366         return self
._projectDoc
.RemoveFiles(self
._files
) 
 369 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
): 
 372     def __init__(self
, files
): 
 373         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
 378         if len(self
._files
) == 1: 
 379             return _("Remove File %s") % os
.path
.basename((self
._files
[0])[1]) 
 381             return _("Remove Files") 
 387         for data 
in self
._files
: 
 388             proj
, filename 
= data
 
 389             if proj 
not in projects
: 
 390                 projects
.append(proj
) 
 391         for project 
in projects
: 
 393             for data 
in self
._files
: 
 394                 proj
, filename 
= data
 
 396                     files
.append(filename
) 
 397             status 
= project
.RemoveFiles(files
) or status
 
 404         for data 
in self
._files
: 
 405             proj
, filename 
= data
 
 406             if proj 
not in projects
: 
 407                 projects
.append(proj
) 
 408         for project 
in projects
: 
 410             for data 
in self
._files
: 
 411                 proj
, filename 
= data
 
 413                     files
.append(filename
) 
 414             status 
= project
.AddFiles(files
) or status
 
 418 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
): 
 421     def __init__(self
, projectDoc
, oldFile
, newFile
, isProject 
= False): 
 422         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
 423         self
._projectDoc 
= projectDoc
 
 424         self
._oldFile 
= oldFile
 
 425         self
._newFile 
= newFile
 
 426         self
._isProject 
= isProject
 
 430         return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFile
), os
.path
.basename(self
._newFile
)) 
 434         return self
._projectDoc
.RenameFile(self
._oldFile
, self
._newFile
, self
._isProject
) 
 438         return self
._projectDoc
.RenameFile(self
._newFile
, self
._oldFile
, self
._isProject
) 
 441 class ProjectTreeCtrl(wx
.TreeCtrl
): 
 444     #---------------------------------------------------------------------------- 
 446     #---------------------------------------------------------------------------- 
 448     def __init__(self
, parent
, id, style
): 
 449         wx
.TreeCtrl
.__init
__(self
, parent
, id, style 
= style
) 
 451         templates 
= wx
.GetApp().GetDocumentManager().GetTemplates() 
 452         iconList 
= wx
.ImageList(16, 16, initialCount 
= len(templates
)) 
 453         self
._iconIndexLookup 
= [] 
 454         for template 
in templates
: 
 455             icon 
= template
.GetIcon() 
 457                 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
 460                     if wx
.GetApp().GetDebug(): 
 461                         print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
 
 462                 iconIndex 
= iconList
.AddIcon(icon
) 
 463                 self
._iconIndexLookup
.append((template
, iconIndex
)) 
 465         icon 
= getBlankIcon() 
 466         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
 469             if wx
.GetApp().GetDebug(): 
 470                 print "Warning: getBlankIcon isn't 16x16, not crossplatform" 
 471         self
._blankIconIndex 
= iconList
.AddIcon(icon
) 
 472         self
.AssignImageList(iconList
) 
 475     def OnCompareItems(self
, item1
, item2
): 
 476         return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower()) 
 479     def AppendItem(self
, parent
, filepath
): 
 480         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, filepath
) 
 483         template 
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filepath
) 
 484         if not template 
and parent 
== self
.GetRootItem(): # If the parent is a root it's a new project 
 485             template 
= wx
.GetApp().GetDocumentManager().FindTemplateForPath('.agp') 
 487             for t
, iconIndex 
in self
._iconIndexLookup
: 
 489                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
) 
 490                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
) 
 491                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Selected
) 
 496             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
) 
 497             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
) 
 498             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Selected
) 
 503     #---------------------------------------------------------------------------- 
 505     #---------------------------------------------------------------------------- 
 507     def SetData(self
, item
, longFilename
, projectDoc
=None): 
 508         self
.SetPyData(item
, (longFilename
, projectDoc
)) 
 511     def GetData(self
, item
): 
 512         """ returns longFilename and optional  
 514         data 
= self
.GetPyData(item
) 
 520     def GetLongFilename(self
, item
): 
 521         return self
.GetData(item
)[0] 
 524     def GetProjectDoc(self
, item
): 
 525         return self
.GetData(item
)[1] 
 528 class ProjectView(wx
.lib
.docview
.View
): 
 531     #---------------------------------------------------------------------------- 
 533     #---------------------------------------------------------------------------- 
 535     def __init__(self
, service 
= None): 
 536         wx
.lib
.docview
.View
.__init
__(self
) 
 537         self
._service 
= service  
# not used, but kept to match other Services 
 538         self
._treeCtrl 
= None 
 539         self
._editingSoDontKillFocus 
= False 
 540         self
._checkEditMenu 
= True 
 544         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 546             projectService
.SetView(None) 
 547         wx
.lib
.docview
.View
.Destroy(self
) 
 550     def GetDocument(self
): 
 551         if not self
._treeCtrl
: 
 554         items 
= self
._treeCtrl
.GetSelections() 
 555         if not items
: # No selection, so just return first project 
 556             item 
= self
._treeCtrl
.GetFirstVisibleItem() 
 558                 return self
._GetItemProject
(item
) 
 563             project 
= self
._GetItemProject
(item
) 
 570     def GetDocumentManager(self
):  # Overshadow this since the superclass uses the view._viewDocument attribute directly, which the project editor doesn't use since it hosts multiple docs 
 571         return wx
.GetApp().GetDocumentManager() 
 574     def OnChangeFilename(self
): 
 576             title 
= _("Projects") 
 577             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI 
and wx
.GetApp().GetAppName(): 
 578                 title 
=  title 
+ " - " + wx
.GetApp().GetAppName() 
 579             self
.GetFrame().SetTitle(title
) 
 580         project 
= self
.GetDocument() 
 582             projectItem 
= self
._GetProjectItem
(project
) 
 583             name 
= self
._treeCtrl
.GetItemText(self
._GetProjectItem
(project
)) 
 584             name2 
= self
._MakeProjectName
(project
) 
 586                 self
._treeCtrl
.SetItemText(projectItem
, name2
) 
 587                 self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem()) 
 590     def Activate(self
, activate 
= True): 
 591         if not wx
.GetApp().IsMDI(): 
 592             if activate 
and not self
.IsShown(): 
 596             wx
.lib
.docview
.View
.Activate(self
, activate 
= activate
) 
 597             if activate 
and self
._treeCtrl
: 
 598                 self
._treeCtrl
.SetFocus() 
 601     def OnCreate(self
, doc
, flags
): 
 602         config 
= wx
.ConfigBase_Get() 
 603         if wx
.GetApp().IsMDI(): 
 604             self
._embeddedWindow 
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
) 
 605             self
.SetFrame(self
._embeddedWindow
) 
 606             frame 
= self
._embeddedWindow
 
 608             self
._embeddedWindow 
= None 
 609             pos 
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1) 
 610             # make sure frame is visible 
 611             screenWidth 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
) 
 612             screenHeight 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
) 
 613             if pos
[0] < 0 or pos
[0] >= screenWidth 
or pos
[1] < 0 or pos
[1] >= screenHeight
: 
 614                 pos 
= wx
.DefaultPosition
 
 616             size 
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1)) 
 618             title 
= _("Projects") 
 619             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI 
and wx
.GetApp().GetAppName(): 
 620                 title 
=  title 
+ " - " + wx
.GetApp().GetAppName() 
 622             frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title 
= title
, pos 
= pos
, size 
= size
) 
 623             if config
.ReadInt("ProjectFrameMaximized", False): 
 626         sizer 
= wx
.BoxSizer() 
 627         self
._treeCtrl 
= ProjectTreeCtrl(frame
, -1, style 
= wx
.TR_HIDE_ROOT | wx
.TR_HAS_BUTTONS | wx
.TR_EDIT_LABELS | wx
.TR_DEFAULT_STYLE | wx
.TR_MULTIPLE
) 
 628         self
._treeCtrl
.AddRoot(_("Projects")) 
 629         wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
) 
 630         wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
) 
 632         if self
._embeddedWindow
: 
 633             sizer
.Add(self
._treeCtrl
) 
 636             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
, 0) 
 637         frame
.SetSizer(sizer
) 
 641         if wx
.GetApp().IsMDI(): 
 642             wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
) 
 643             wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
) 
 645         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 646             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
) 
 648             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
) 
 649         wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
) 
 650         wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
) 
 651         wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
) 
 652         wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
) 
 653         # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason 
 655         # drag-and-drop support 
 656         dt 
= ProjectFileDropTarget(self
) 
 657         self
._treeCtrl
.SetDropTarget(dt
) 
 662     def OnBeginDrag(self
, event
): 
 663         item 
= event
.GetItem() 
 665             if item 
== self
._treeCtrl
.GetRootItem(): 
 667             self
._draggingItem 
= item
 
 671     def OnEndDrag(self
, event
): 
 672         item 
= event
.GetItem() 
 674             # don't allow object to be dragged to itself 
 675             if item 
== self
._draggingItem
: 
 678             rootItem 
= self
._treeCtrl
.GetRootItem() 
 680             # don't let object replace root view 
 682                 wx
.MessageBox(_("Cannot replace root view with item.")) 
 685             # don't allow object to be dragged to a direct descendant 
 686             ancestor 
= self
._treeCtrl
.GetItemParent(item
) 
 687             while ancestor 
!= rootItem
: 
 688                 if ancestor 
== self
._draggingItem
: 
 689                     wx
.MessageBox(_("Cannot make item direct descendant of self.")) 
 692                     ancestor 
= self
._treeCtrl
.GetItemParent(ancestor
) 
 694             if self
._treeCtrl
.GetItemParent(item
) == self
._treeCtrl
.GetItemParent(self
._draggingItem
): 
 695                 # put it in same folder as it was originally, no-op. 
 697             if item 
== self
._treeCtrl
.GetItemParent(self
._draggingItem
): 
 698                 # put it in same folder as it was originally, no-op. 
 701             self
.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self
, item
, self
._draggingItem
)) 
 704     def WriteProjectConfig(self
): 
 705         frame 
= self
.GetFrame() 
 706         config 
= wx
.ConfigBase_Get() 
 707         if frame 
and not self
._embeddedWindow
: 
 708             if not frame
.IsMaximized(): 
 709                 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0]) 
 710                 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1]) 
 711                 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0]) 
 712                 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1]) 
 713             config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized()) 
 715         if config
.ReadInt("ProjectSaveDocs", True): 
 716             projectFileNames 
= [] 
 719                 for projectItem 
in self
._GetChildItems
(self
._treeCtrl
.GetRootItem()): 
 720                     project 
= self
._GetItemProject
(projectItem
) 
 721                     if not project
.OnSaveModified(): 
 723                     if project
.GetDocumentSaved():  # Might be a new document and "No" selected to save it 
 724                         projectFileNames
.append(str(project
.GetFilename())) 
 725                         projectExpanded
.append(self
._treeCtrl
.IsExpanded(projectItem
)) 
 726             config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__()) 
 727             config
.Write("ProjectExpandedSavedDocs", projectExpanded
.__repr
__()) 
 730     def OnClose(self
, deleteWindow 
= True): 
 731         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 732             self
.WriteProjectConfig() 
 733         project 
= self
.GetDocument() 
 736         if not self
.GetDocument().Close(): 
 740             projectItem 
= self
._GetProjectItem
(project
) 
 742                 self
._treeCtrl
.Delete(projectItem
) 
 743         # We don't need to delete the window since it is a floater/embedded 
 747     def _GetParentFrame(self
): 
 748         return wx
.GetTopLevelParent(self
.GetFrame()) 
 751     def OnUpdate(self
, sender 
= None, hint 
= None): 
 752         wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
) 
 755                 projectItem 
= self
._GetProjectItem
(hint
[1]) 
 757                 self
._treeCtrl
.UnselectAll() 
 758                 self
._treeCtrl
.Expand(projectItem
) 
 761                     item 
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file)) 
 762                     self
._treeCtrl
.SetData(item
, file) 
 763                     self
._treeCtrl
.SelectItem(item
) 
 764                     self
._treeCtrl
.EnsureVisible(item
) 
 765                 self
._treeCtrl
.SortChildren(projectItem
) 
 767                     self
._treeCtrl
.EnsureVisible(item
)  # need to be called after SortChildren 
 768             elif hint
[0] == "remove": 
 769                 projectItem 
= self
._GetProjectItem
(hint
[1]) 
 771                 self
._treeCtrl
.UnselectAll() 
 772                 children 
= self
._GetChildItems
(projectItem
) 
 773                 for child 
in children
: 
 774                     if self
._GetItemFile
(child
) in files
: 
 775                         self
._treeCtrl
.Delete(child
) 
 776             elif hint
[0] == "select": 
 777                 projectItem 
= self
._GetProjectItem
(hint
[1]) 
 779                 self
._treeCtrl
.UnselectAll() 
 780                 children 
= self
._GetChildItems
(projectItem
) 
 781                 for child 
in children
: 
 782                     if self
._GetItemFile
(child
) in files
: 
 783                         self
._treeCtrl
.SelectItem(child
) 
 784                         self
._treeCtrl
.EnsureVisible(child
) 
 785             elif hint
[0] == "rename": 
 786                 projectItem 
= self
._GetProjectItem
(hint
[1]) 
 787                 self
._treeCtrl
.SetItemText(projectItem
, os
.path
.basename(hint
[2])) 
 790     def ProcessEvent(self
, event
): 
 792         if id == ProjectService
.ADD_FILES_TO_PROJECT_ID
: 
 793             self
.OnAddFileToProject(event
) 
 795         elif id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
: 
 796             self
.OnAddDirToProject(event
) 
 798         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
 799             return False  # Implement this one in the service 
 800         elif id == ProjectService
.RENAME_ID
: 
 803         elif id == ProjectService
.DELETE_FILE_ID
: 
 804             self
.OnDeleteFile(event
) 
 806         elif id == wx
.ID_CUT
: 
 809         elif id == wx
.ID_COPY
: 
 812         elif id == wx
.ID_PASTE
: 
 815         elif (id == wx
.ID_CLEAR
 
 816         or id == ProjectService
.REMOVE_FROM_PROJECT
): 
 819         elif id == wx
.ID_SELECTALL
: 
 820             self
.OnSelectAll(event
) 
 822         elif id == ProjectService
.OPEN_SELECTION_ID
: 
 823             self
.OnOpenSelection(event
) 
 825         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
 826             self
.OnProperties(event
) 
 832     def ProcessUpdateUIEvent(self
, event
): 
 833         # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here 
 834         if self
._checkEditMenu
: 
 835             doc 
= self
.GetDocument() 
 836             if doc 
and not doc
.GetCommandProcessor().GetEditMenu(): 
 837                 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
 838             self
._checkEditMenu 
= False 
 843         or id == ProjectService
.RENAME_ID
 
 844         or id == ProjectService
.ADD_FILES_TO_PROJECT_ID
 
 845         or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
 
 846         or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
): 
 847             event
.Enable(self
._HasSelection
()) 
 849         elif id == ProjectService
.DELETE_FILE_ID
: 
 850             event
.Enable(len(self
.GetSelectedFiles()) > 0) 
 852         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
 855         elif id == wx
.ID_PASTE
: 
 856             event
.Enable(self
.CanPaste()) 
 858         elif id == wx
.ID_SELECTALL
: 
 859             event
.Enable(self
._HasFiles
()) 
 861         elif (id == wx
.ID_CLEAR
 
 862         or id == ProjectService
.REMOVE_FROM_PROJECT
 
 863         or id == ProjectService
.OPEN_SELECTION_ID
): 
 864             event
.Enable(self
._HasFilesSelected
()) 
 866         elif (id == wx
.ID_PREVIEW
 
 867         or id == wx
.ID_PRINT
): 
 873     #---------------------------------------------------------------------------- 
 875     #---------------------------------------------------------------------------- 
 878         if not self
.GetFrame(): 
 880         return self
.GetFrame().IsShown() 
 887     def Show(self
, show 
= True): 
 888         self
.GetFrame().Show(show
) 
 889         if wx
.GetApp().IsMDI(): 
 890             mdiParentFrame 
= wx
.GetApp().GetTopWindow() 
 891             mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
) 
 894     #---------------------------------------------------------------------------- 
 895     # Methods for ProjectDocument and ProjectService to call 
 896     #---------------------------------------------------------------------------- 
 898     def SetExpandedProjects(self
, expandedProjects
): 
 899         self
._treeCtrl
.UnselectAll() 
 901         for i
, item 
in enumerate(self
._GetChildItems
(self
._treeCtrl
.GetRootItem())): 
 905             if expandedProjects
[i
]: 
 906                 self
._treeCtrl
.Expand(item
) 
 908                 self
._treeCtrl
.Collapse(item
) 
 911             self
._treeCtrl
.EnsureVisible(firstItem
) 
 914     def GetSelectedFile(self
): 
 915         for item 
in self
._treeCtrl
.GetSelections(): 
 916             return self
._GetItemFile
(item
) 
 919     def GetSelectedFiles(self
): 
 921         for item 
in self
._treeCtrl
.GetSelections(): 
 922             filename 
= self
._GetItemFile
(item
) 
 923             if filename 
and filename 
not in filenames
: 
 924                 filenames
.append(filename
) 
 928     def GetSelectedProjects(self
): 
 930         for item 
in self
._treeCtrl
.GetSelections(): 
 931             if self
._IsItemProject
(item
): 
 932                 filename 
= self
._treeCtrl
.GetLongFilename(item
) 
 933                 if filename 
and filename 
not in filenames
: 
 934                     filenames
.append(filename
) 
 938     def AddProjectToView(self
, document
): 
 939         rootItem 
= self
._treeCtrl
.GetRootItem() 
 940         projectItem 
= self
._treeCtrl
.AppendItem(rootItem
, self
._MakeProjectName
(document
)) 
 941         self
._treeCtrl
.SetData(projectItem
, document
.GetFilename(), document
) 
 942         for file in document
.GetFiles(): 
 943             fileItem 
= self
._treeCtrl
.AppendItem(projectItem
, os
.path
.basename(file)) 
 944             self
._treeCtrl
.SetData(fileItem
, file) 
 945         self
._treeCtrl
.SortChildren(rootItem
) 
 946         self
._treeCtrl
.SortChildren(projectItem
) 
 947         self
._treeCtrl
.UnselectAll() 
 948         self
._treeCtrl
.Expand(projectItem
) 
 949         self
._treeCtrl
.SelectItem(projectItem
) 
 950         if self
._embeddedWindow
: 
 951             document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
 955         winWithFocus 
= wx
.Window
.FindFocus() 
 959             if winWithFocus 
== self
._treeCtrl
: 
 961             winWithFocus 
= winWithFocus
.GetParent() 
 965     #---------------------------------------------------------------------------- 
 967     #---------------------------------------------------------------------------- 
 969     def OnProperties(self
, event
): 
 970         items 
= self
._treeCtrl
.GetSelections() 
 974         if self
._IsItemProject
(item
): 
 975             projectPropertiesDialog 
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
._GetItemProject
(item
).GetFilename()) 
 976             if projectPropertiesDialog
.ShowModal() == wx
.ID_OK
: 
 978             projectPropertiesDialog
.Destroy() 
 979         elif self
._IsItemFile
(item
): 
 980             filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
 981             filePropertiesService
.ShowPropertiesDialog(self
._GetItemFile
(item
)) 
 984     def OnAddFileToProject(self
, event
): 
 985         if wx
.Platform 
== "__WXMSW__" or wx
.Platform 
== "__WXGTK__" or wx
.Platform 
== "__WXMAC__": 
 988             for temp 
in self
.GetDocumentManager()._templates
: 
 991                         descr 
= descr 
+ _('|') 
 992                         allfilter 
= allfilter 
+ _(';') 
 993                     descr 
= descr 
+ temp
.GetDescription() + _(" (") + temp
.GetFileFilter() + _(") |") + temp
.GetFileFilter()  # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk 
 994                     allfilter 
= allfilter 
+ temp
.GetFileFilter() 
 995             descr 
= _("All (%s)|%s|%s|Any (*.*) | *.*") %  (allfilter
, allfilter
, descr
)  # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk 
 999         startDirectory 
= os
.path
.dirname(self
.GetDocument().GetFilename()) 
1001         if True or _WINDOWS
: 
1002             dialog 
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), startDirectory
, "", descr
, wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
) 
1003             if dialog
.ShowModal() != wx
.ID_OK
: 
1005             paths 
= dialog
.GetPaths() 
1008             paths 
= wx
.FileSelector(_("Add Files"), startDirectory
, "", wildcard 
= descr
, flags 
= wx
.OPEN | wx
.HIDE_READONLY | wx
.MULTIPLE
, parent
=self
.GetFrame()) 
1009             if type(paths
) == types
.StringType
: 
1012             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
)) 
1013         self
.Activate(True)  # after add, should put focus on project editor 
1016     def OnAddDirToProject(self
, event
): 
1017         frame 
= wx
.Dialog(None, -1, _("Add Directory Files to Project"), size
= (320,200)) 
1018         contentSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1020         flexGridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap
=HALF_SPACE
, hgap
=HALF_SPACE
) 
1021         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER_VERTICAL
, 0) 
1022         lineSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
1023         dirCtrl 
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(250,-1)) 
1024         dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
1025         lineSizer
.Add(dirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND
) 
1026         findDirButton 
= wx
.Button(frame
, -1, _("Browse...")) 
1027         lineSizer
.Add(findDirButton
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, HALF_SPACE
) 
1028         flexGridSizer
.Add(lineSizer
, 1, wx
.EXPAND
) 
1030         def OnBrowseButton(event
): 
1031             dlg 
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
) 
1032             dir = dirCtrl
.GetValue() 
1035             if dlg
.ShowModal() == wx
.ID_OK
: 
1036                 dirCtrl
.SetValue(dlg
.GetPath()) 
1037                 dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
1038                 dirCtrl
.SetInsertionPointEnd() 
1041         wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
) 
1043         visibleTemplates 
= [] 
1044         for template 
in self
.GetDocumentManager()._templates
: 
1045             if template
.IsVisible(): 
1046                 visibleTemplates
.append(template
) 
1051         for template 
in visibleTemplates
: 
1053                 descr 
= descr 
+ _('|') 
1054                 allfilter 
= allfilter 
+ _(';') 
1055             descr 
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")") 
1056             choices
.append(descr
) 
1057             allfilter 
= allfilter 
+ template
.GetFileFilter() 
1058         choices
.insert(0, _("All (%s)") % allfilter
)  # first item 
1059         choices
.append(_("Any (*.*)"))  # last item 
1060         filterChoice 
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
) 
1061         filterChoice
.SetSelection(0) 
1062         filterChoice
.SetToolTipString(_("Select file type filter.")) 
1063         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
) 
1064         flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
) 
1066         contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
) 
1068         subfolderCtrl 
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories")) 
1069         subfolderCtrl
.SetValue(True) 
1070         contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
) 
1072         buttonSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
1073         findBtn 
= wx
.Button(frame
, wx
.ID_OK
, _("Add")) 
1074         findBtn
.SetDefault() 
1075         buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
) 
1076         buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0) 
1077         contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
) 
1079         frame
.SetSizer(contentSizer
) 
1082         status 
= frame
.ShowModal() 
1085         while status 
== wx
.ID_OK 
and not passedCheck
: 
1086             if not os
.path
.exists(dirCtrl
.GetValue()): 
1087                 dlg 
= wx
.MessageDialog(frame
, 
1088                                        _("'%s' does not exist.") % dirCtrl
.GetValue(), 
1089                                        _("Find in Directory"), 
1090                                        wx
.OK | wx
.ICON_EXCLAMATION
 
1095                 status 
= frame
.ShowModal() 
1099         if status 
== wx
.ID_OK
:             
1102             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
1104             doc 
= self
.GetDocument() 
1105             searchSubfolders 
= subfolderCtrl
.IsChecked() 
1106             dirString 
= dirCtrl
.GetValue() 
1108             if os
.path
.isfile(dirString
): 
1109                 # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter. 
1110                 # We'll assume they know what they're doing. 
1115                 index 
= filterChoice
.GetSelection() 
1116                 lastIndex 
= filterChoice
.GetCount()-1 
1117                 if index 
and index 
!= lastIndex
:  # if not All or Any 
1118                     template 
= visibleTemplates
[index
-1] 
1120                 # do search in files on disk 
1121                 for root
, dirs
, files 
in os
.walk(dirString
): 
1122                     if not searchSubfolders 
and root 
!= dirString
: 
1126                         if index 
== 0:  # All 
1127                             for template 
in visibleTemplates
: 
1128                                 if template
.FileMatchesTemplate(name
): 
1129                                     filename 
= os
.path
.join(root
, name
) 
1131                                     # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
1132                                     if doc
.IsFileInProject(filename
): 
1135                                     paths
.append(filename
) 
1137                         elif index 
== lastIndex
:  # Any 
1138                             filename 
= os
.path
.join(root
, name
) 
1139                             # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
1140                             if not doc
.IsFileInProject(filename
): 
1141                                 paths
.append(filename
)                     
1142                         else:  # use selected filter 
1143                             if template
.FileMatchesTemplate(name
): 
1144                                 filename 
= os
.path
.join(root
, name
) 
1145                                 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
1146                                 if not doc
.IsFileInProject(filename
): 
1147                                     paths
.append(filename
)                     
1149             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
1151             doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
)) 
1152             self
.Activate(True)  # after add, should put focus on project editor 
1157     def DoAddFilesToProject(self
, filenames
): 
1158         # method used by Drag-n-Drop to add files to current Project 
1159         self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filenames
)) 
1162     def DoSelectFiles(self
, filenames
): 
1163         # method used by Drag-n-Drop to select files in current Project 
1164         self
._treeCtrl
.UnselectAll() 
1165         for file in filenames
: 
1166             item 
= self
._GetFileItem
(longFileName
=file) 
1168                 self
._treeCtrl
.SelectItem(item
, True) 
1169                 self
._treeCtrl
.EnsureVisible(item
) 
1172     def DoSelectProject(self
, x
, y
): 
1173         # method used by Drag-n-Drop to set current Project based on cursor position 
1174         item
, flag 
= self
._treeCtrl
.HitTest((x
,y
)) 
1178         project 
= self
._GetItemProject
(item
) 
1182         projectItem 
= self
._GetProjectItem
(project
) 
1183         self
._treeCtrl
.UnselectAll() 
1184         self
._treeCtrl
.SelectItem(projectItem
) 
1188     def OnFocus(self
, event
): 
1189         wx
.GetApp().GetDocumentManager().ActivateView(self
) 
1193     def OnKillFocus(self
, event
): 
1194         # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame 
1195         # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame 
1196         if not self
._editingSoDontKillFocus
:  # wxBug: This didn't used to happen, but now when you start to edit an item in a wxTreeCtrl it puts out a KILL_FOCUS event, so we need to detect it 
1197             childFrame 
= wx
.GetApp().GetTopWindow().GetActiveChild() 
1199                 childFrame
.Activate() 
1203     def OnRightClick(self
, event
): 
1205         if not self
._treeCtrl
.GetSelections(): 
1207         if len(self
._treeCtrl
.GetSelections()) == 1 and self
._IsItemRoot
(self
._treeCtrl
.GetSelections()[0]): 
1208             return  # Don't do a menu if it's just the root item selected 
1210         if self
._HasFilesSelected
():  # Files context 
1211             menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection")) 
1212             menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True) 
1213             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
) 
1215             for item 
in self
._treeCtrl
.GetSelections(): 
1216                 if self
._IsItemProcessModelFile
(item
): 
1217                     itemIDs 
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None] 
1219         else:  # Project context 
1220             itemIDs 
= [wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
, None] 
1221         menuBar 
= self
._GetParentFrame
().GetMenuBar() 
1222         itemIDs 
= itemIDs 
+ [ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, ProjectService
.REMOVE_FROM_PROJECT
] 
1223         svnIDs 
= [SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
1225             itemIDs 
= itemIDs 
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
1226         globalIDs 
= [wx
.ID_UNDO
, wx
.ID_REDO
, wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
] 
1227         itemIDs 
= itemIDs 
+ [None, wx
.ID_UNDO
, wx
.ID_REDO
, None, wx
.ID_CUT
, wx
.ID_COPY
, wx
.ID_PASTE
, wx
.ID_CLEAR
, None, wx
.ID_SELECTALL
, ProjectService
.RENAME_ID
, ProjectService
.DELETE_FILE_ID
, None, wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
] 
1228         for itemID 
in itemIDs
: 
1230                 menu
.AppendSeparator() 
1232                 if itemID 
== ProjectService
.RUN_SELECTED_PM_ID
: 
1233                     menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process")) 
1234                     wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
) 
1235                 elif itemID 
== ProjectService
.REMOVE_FROM_PROJECT
: 
1236                     menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project")) 
1237                     wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
) 
1238                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
) 
1240                     svnService 
= wx
.GetApp().GetService(SVNService
.SVNService
) 
1241                     item 
= menuBar
.FindItemById(itemID
) 
1243                         if itemID 
in svnIDs
: 
1244                             if SVN_INSTALLED 
and svnService
: 
1245                                 wx
.EVT_MENU(self
._GetParentFrame
(), itemID
, svnService
.ProcessEvent
) 
1246                         elif itemID 
in globalIDs
: 
1249                             wx
.EVT_MENU(self
._treeCtrl
, itemID
, self
.ProcessEvent
) 
1250                         menu
.Append(itemID
, item
.GetLabel()) 
1251         self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY())) 
1255     def OnRunSelectedPM(self
, event
): 
1256         projectService 
= wx
.GetApp().GetService(ProjectService
) 
1258             projectService
.OnRunProcessModel(event
, runSelected
=True) 
1261     def OnRename(self
, event
): 
1262         if self
._treeCtrl
.GetSelections(): 
1263             self
._treeCtrl
.EditLabel(self
._treeCtrl
.GetSelections()[0]) 
1266     def OnBeginLabelEdit(self
, event
): 
1267         self
._editingSoDontKillFocus 
= True 
1268         item 
= event
.GetItem() 
1269         if not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
): 
1273     def OnEndLabelEdit(self
, event
): 
1274         self
._editingSoDontKillFocus 
= False 
1275         item 
= event
.GetItem() 
1276         newName 
= event
.GetLabel() 
1277         if not newName 
or (not self
._IsItemFile
(item
) and not self
._IsItemProject
(item
)): 
1280         if self
._IsItemFile
(item
): 
1281             oldFile 
= self
._GetItemFile
(item
) 
1282             newFile 
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
) 
1283             project 
= self
._GetItemProject
(item
) 
1284             if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
)): 
1287             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(self
._treeCtrl
.GetSelections()[0])) 
1288         elif self
._IsItemProject
(item
): 
1289             oldFile 
= self
._GetItemProject
(item
).GetFilename() 
1290             newFile 
= os
.path
.join(os
.path
.split(oldFile
)[0], newName
) 
1291             project 
= self
._GetItemProject
(item
)             
1292             if not project
.GetCommandProcessor().Submit(ProjectRenameFileCommand(project
, oldFile
, newFile
, True)): 
1295             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetRootItem()) 
1299         # wxBug: Should be able to use IsSupported/IsSupportedFormat here 
1300         #fileDataObject = wx.FileDataObject() 
1301         #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject) 
1302         if not wx
.TheClipboard
.IsOpened(): 
1303             if wx
.TheClipboard
.Open(): 
1304                 fileDataObject 
= wx
.FileDataObject() 
1305                 hasFilesInClipboard 
= wx
.TheClipboard
.GetData(fileDataObject
) 
1306                 wx
.TheClipboard
.Close() 
1308             hasFilesInClipboard 
= False 
1309         return hasFilesInClipboard
 
1312     def OnCut(self
, event
): 
1317     def OnCopy(self
, event
): 
1318         fileDataObject 
= wx
.FileDataObject() 
1319         items 
= self
._treeCtrl
.GetSelections() 
1321             if self
._IsItemFile
(item
): 
1322                 file = self
._treeCtrl
.GetLongFilename(item
) 
1323                 fileDataObject
.AddFile(file) 
1324         if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open(): 
1325             wx
.TheClipboard
.SetData(fileDataObject
) 
1326             wx
.TheClipboard
.Close() 
1329     def OnPaste(self
, event
): 
1330         if wx
.TheClipboard
.Open(): 
1331             fileDataObject 
= wx
.FileDataObject() 
1332             if wx
.TheClipboard
.GetData(fileDataObject
): 
1333                 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames())) 
1334             wx
.TheClipboard
.Close() 
1337     def OnClear(self
, event
): 
1338         items 
= self
._treeCtrl
.GetSelections() 
1341             if self
._IsItemFile
(item
): 
1342                 files
.append((self
._GetItemProject
(item
), self
._GetItemFile
(item
))) 
1343         self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files
)) 
1346     def OnDeleteFile(self
, event
): 
1347         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
1348                                  _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"), 
1350                                  wx
.YES_NO|wx
.ICON_QUESTION
) 
1351         if yesNoMsg
.ShowModal() == wx
.ID_NO
: 
1354         items 
= self
._treeCtrl
.GetSelections() 
1358             if self
._IsItemFile
(item
): 
1359                 filename 
= self
._GetItemFile
(item
) 
1360                 files
.append((self
._GetItemProject
(item
), filename
)) 
1361                 if filename 
not in delFiles
: 
1362                     delFiles
.append(filename
) 
1364         # remove selected files from projects 
1367             proj
, filename 
= data
 
1368             if proj 
not in projects
: 
1369                 projects
.append(proj
) 
1370         for project 
in projects
: 
1373                 proj
, filename 
= data
 
1375                     filenames
.append(filename
) 
1376             project
.RemoveFiles(filenames
) 
1378         # remove selected files from file system 
1379         for filename 
in delFiles
: 
1380             if os
.path
.exists(filename
): 
1384                     wx
.MessageBox("Could not delete '%s'.  %s" % (os
.path
.basename(filename
), sys
.exc_value
), 
1386                                   wx
.OK | wx
.ICON_EXCLAMATION
) 
1389     def OnKeyPressed(self
, event
): 
1390         key 
= event
.KeyCode() 
1391         if key 
== wx
.WXK_DELETE
: 
1397     def OnSelectAll(self
, event
): 
1398         project 
= self
.GetDocument() 
1400             self
._treeCtrl
.UnselectAll() 
1401             for child 
in self
._GetChildItems
(self
._GetProjectItem
(project
)): 
1402                 self
._treeCtrl
.SelectItem(child
) 
1405     def OnOpenSelectionSDI(self
, event
): 
1406         # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window 
1407         wx
.CallAfter(self
.OnOpenSelection
, None) 
1410     def OnOpenSelection(self
, event
): 
1413             items 
= self
._treeCtrl
.GetSelections() 
1415                 if self
._IsItemFile
(item
): 
1416                     filepath 
= self
._GetItemFile
(item
) 
1417                     if not os
.path
.exists(filepath
): 
1418                         msgTitle 
= wx
.GetApp().GetAppName() 
1420                             msgTitle 
= _("File Not Found") 
1421                         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
1422                                       _("The file '%s' was not found in '%s'.\n\nWould you like to browse for the file?") % (wx
.lib
.docview
.FileNameFromPath(filepath
), wx
.lib
.docview
.PathOnly(filepath
)), 
1424                                       wx
.YES_NO|wx
.ICON_QUESTION
 
1426                         if yesNoMsg
.ShowModal() == wx
.ID_NO
: 
1428                         findFile 
= wx
.FileDialog(self
.GetFrame(), 
1430                                                  wx
.lib
.docview
.PathOnly(filepath
), 
1431                                                  wx
.lib
.docview
.FileNameFromPath(filepath
), 
1434                         if findFile
.ShowModal() == wx
.ID_OK 
and findFile
.GetPath(): 
1435                             newpath 
= findFile
.GetPath() 
1440                             # update Project Model with new location 
1441                             project 
= self
._GetItemProject
(item
) 
1442                             project
.RemoveFile(filepath
) 
1443                             project
.AddFile(newpath
) 
1446                     doc 
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT
) 
1448                         shortFilename 
= self
._treeCtrl
.GetItemText(item
) 
1449                         if shortFilename
.endswith(".agp"): 
1450                             projItem 
= self
._GetProjectItem
(shortFilename
=shortFilename
) 
1451                             self
._treeCtrl
.UnselectAll() 
1452                             if not self
._treeCtrl
.IsExpanded(projItem
): 
1453                                 self
._treeCtrl
.Expand(projItem
) 
1454                             if not self
._treeCtrl
.IsVisible(projItem
): 
1455                                 self
._treeCtrl
.EnsureVisible(projItem
) 
1456                             if not self
._treeCtrl
.IsSelected(projItem
): 
1457                                 self
._treeCtrl
.SelectItem(projItem
) 
1459         except IOError, (code
, message
): 
1460             msgTitle 
= wx
.GetApp().GetAppName() 
1462                 msgTitle 
= _("File Error") 
1463             wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
), 
1465                           wx
.OK | wx
.ICON_EXCLAMATION
, 
1469     #---------------------------------------------------------------------------- 
1470     # Convenience methods 
1471     #---------------------------------------------------------------------------- 
1473     def _HasFiles(self
): 
1474         if not self
._treeCtrl
: 
1476         return self
._treeCtrl
.GetCount() > 1    #  1 item = root item, don't count as having files 
1479     def _HasSelection(self
): 
1480         if not self
._treeCtrl
: 
1483         items 
= self
._treeCtrl
.GetSelections() 
1490     def _HasFilesSelected(self
): 
1491         if not self
._treeCtrl
: 
1493         items 
= self
._treeCtrl
.GetSelections() 
1497             if not self
._IsItemFile
(item
): 
1502     def _MakeProjectName(self
, project
): 
1503         return project
.GetPrintableName() 
1506     # Return the tree item for a project 
1507     def _GetProjectItem(self
, project
=None, shortFilename
=None): 
1508         rootItem 
= self
._treeCtrl
.GetRootItem() 
1509         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
) 
1512                 if self
._treeCtrl
.GetProjectDoc(child
) == project
: 
1515                 if self
._treeCtrl
.GetItemText(child
) == shortFilename
: 
1517             (child
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
) 
1521     # Returns the project for an item, either for a project item or a file that is part of a project 
1522     def _GetItemProject(self
, item
): 
1523         if self
._IsItemRoot
(item
): 
1525         if self
._IsItemProject
(item
): 
1526             return self
._treeCtrl
.GetProjectDoc(item
) 
1527         if self
._IsItemFile
(item
): 
1528             return self
._treeCtrl
.GetProjectDoc(self
._treeCtrl
.GetItemParent(item
)) 
1532     def _GetItemFile(self
, item
): 
1533         if self
._IsItemFile
(item
): 
1534             return self
._treeCtrl
.GetLongFilename(item
) 
1539     def _GetFileItem(self
, shortFileName 
= None, longFileName 
= None): 
1540         """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """ 
1542         rootItem 
= self
._treeCtrl
.GetRootItem() 
1543         (project
, cookie
) = self
._treeCtrl
.GetFirstChild(rootItem
) 
1544         while project
.IsOk(): 
1545             (child
, cookie2
) = self
._treeCtrl
.GetFirstChild(project
) 
1548                     if self
._treeCtrl
.GetItemText(child
) == shortFileName
: 
1551                     if self
._treeCtrl
.GetLongFilename(child
) == longFileName
: 
1553                 (child
, cookie2
) = self
._treeCtrl
.GetNextChild(project
, cookie2
) 
1554             (project
, cookie
) = self
._treeCtrl
.GetNextChild(rootItem
, cookie
) 
1558     def _IsItemRoot(self
, item
): 
1559         return item 
== self
._treeCtrl
.GetRootItem() 
1562     def _IsItemProject(self
, item
): 
1563         return self
._treeCtrl
.GetProjectDoc(item
) != None 
1566     def _IsItemFile(self
, item
): 
1567         return self
._treeCtrl
.GetProjectDoc(item
) == None 
1570     def _IsItemProcessModelFile(self
, item
): 
1571         if ACTIVEGRID_BASE_IDE
: 
1574         if self
._IsItemFile
(item
): 
1575             filename 
= self
._treeCtrl
.GetLongFilename(item
) 
1577             for template 
in self
.GetDocumentManager().GetTemplates(): 
1578                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
1579                     ext 
= template
.GetDefaultExtension() 
1584             if filename
.endswith(ext
): 
1590     def _GetChildItems(self
, parentItem
): 
1592         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
1594             children
.append(child
) 
1595             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
1600 class ProjectFileDropTarget(wx
.FileDropTarget
): 
1602     def __init__(self
, view
): 
1603         wx
.FileDropTarget
.__init
__(self
) 
1607     def OnDropFiles(self
, x
, y
, filenames
): 
1608         if self
._view
.DoSelectProject(x
, y
): 
1609             self
._view
.DoAddFilesToProject(filenames
) 
1610             self
._view
.DoSelectFiles(filenames
) 
1615     def OnDragOver(self
, x
, y
, default
): 
1616         if self
._view
.DoSelectProject(x
,y
): 
1621 class ProjectPropertiesDialog(wx
.Dialog
): 
1624     def __init__(self
, parent
, filename
): 
1625         wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size 
= (310, 330)) 
1627         filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
1629         notebook 
= wx
.Notebook(self
, -1) 
1630         tab 
= wx
.Panel(notebook
, -1) 
1632         gridSizer 
= RowColSizer() 
1634         gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=0, col
=0) 
1635         if os
.path
.isfile(filename
): 
1636             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1]), row
=0, col
=1) 
1638             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=1, col
=0) 
1639             gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.split(filename
)[0])), flag
=wx
.BOTTOM
, border
=SPACE
, row
=1, col
=1) 
1641             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=2, col
=0) 
1642             gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes")), row
=2, col
=1) 
1644             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
1645             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
1646             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, border
=HALF_SPACE
, row
=3, col
=0, colspan
=2) 
1648             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=4, col
=0) 
1649             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
))), row
=4, col
=1) 
1651             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=5, col
=0) 
1652             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
))), row
=5, col
=1) 
1654             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:")), flag
=wx
.RIGHT
, border
=HALF_SPACE
, row
=6, col
=0) 
1655             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
))), row
=6, col
=1) 
1658             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]")), row
=0, col
=1) 
1660         # add a border around the inside of the tab 
1661         spacerGrid 
= wx
.BoxSizer(wx
.VERTICAL
) 
1662         spacerGrid
.Add(gridSizer
, 0, wx
.ALL
, SPACE
); 
1663         tab
.SetSizer(spacerGrid
) 
1664         notebook
.AddPage(tab
, _("General")) 
1665         if wx
.Platform 
== "__WXMSW__": 
1666             notebook
.SetPageSize((310,200)) 
1668         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1669         sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
) 
1670         sizer
.Add(self
.CreateButtonSizer(wx
.OK
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
) 
1672         self
.SetSizer(sizer
) 
1677 class ProjectOptionsPanel(wx
.Panel
): 
1680     def __init__(self
, parent
, id): 
1681         wx
.Panel
.__init
__(self
, parent
, id) 
1682         self
._useSashMessageShown 
= False 
1683         config 
= wx
.ConfigBase_Get() 
1684         self
._projSaveDocsCheckBox 
= wx
.CheckBox(self
, -1, _("Remember open projects")) 
1685         self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True)) 
1686         projectBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1687         projectSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1688         projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
1689         if not ACTIVEGRID_BASE_IDE
: 
1690             self
._projShowWelcomeCheckBox 
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog")) 
1691             self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True)) 
1692             projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
)         
1693         projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
) 
1694         self
.SetSizer(projectBorderSizer
) 
1696         parent
.AddPage(self
, _("Project")) 
1698     def OnUseSashSelect(self
, event
): 
1699         if not self
._useSashMessageShown
: 
1700             msgTitle 
= wx
.GetApp().GetAppName() 
1702                 msgTitle 
= _("Document Options") 
1703             wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.", 
1705                           wx
.OK | wx
.ICON_INFORMATION
, 
1707             self
._useSashMessageShown 
= True 
1710     def OnOK(self
, optionsDialog
): 
1711         config 
= wx
.ConfigBase_Get() 
1712         config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue()) 
1713         if not ACTIVEGRID_BASE_IDE
: 
1714             config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue()) 
1717 class ProjectService(Service
.Service
): 
1719     #---------------------------------------------------------------------------- 
1721     #---------------------------------------------------------------------------- 
1722     SHOW_WINDOW 
= wx
.NewId()  # keep this line for each subclass, need unique ID for each Service 
1723     RUNPM_ID 
= wx
.NewId() 
1724     RUN_SELECTED_PM_ID 
= wx
.NewId() 
1725     RUN_CURRENT_PM_ID 
= wx
.NewId() 
1726     ADD_FILES_TO_PROJECT_ID 
= wx
.NewId() 
1727     ADD_CURRENT_FILE_TO_PROJECT_ID 
= wx
.NewId() 
1728     RENAME_ID 
= wx
.NewId() 
1729     OPEN_SELECTION_ID 
= wx
.NewId() 
1730     REMOVE_FROM_PROJECT 
= wx
.NewId() 
1731     DELETE_FILE_ID 
= wx
.NewId() 
1732     ADD_ALL_FILES_TO_PROJECT_ID 
= wx
.NewId() 
1735     #---------------------------------------------------------------------------- 
1736     # Overridden methods 
1737     #---------------------------------------------------------------------------- 
1739     def __init__(self
, serviceName
, embeddedWindowLocation 
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
): 
1740         Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
) 
1741         self
._runHandlers 
= [] 
1742         self
._suppressOpenProjectMessages 
= False 
1745     def _CreateView(self
): 
1746         return ProjectView(self
) 
1749     def ShowWindow(self
, show 
= True): 
1750         """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """ 
1751         Service
.Service
.ShowWindow(self
, show
) 
1754             project 
= self
.GetView().GetDocument() 
1756                 self
.OpenSavedProjects() 
1759     #---------------------------------------------------------------------------- 
1760     # Service specific methods 
1761     #---------------------------------------------------------------------------- 
1763     def GetSuppressOpenProjectMessages(self
): 
1764         return self
._suppressOpenProjectMessages
 
1767     def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
): 
1768         self
._suppressOpenProjectMessages 
= suppressOpenProjectMessages
 
1771     def GetRunHandlers(self
): 
1772         return self
._runHandlers
 
1775     def AddRunHandler(self
, runHandler
): 
1776         self
._runHandlers
.append(runHandler
) 
1779     def RemoveRunHandler(self
, runHandler
): 
1780         self
._runHandlers
.remove(runHandler
) 
1783     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
1784         Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
) 
1786         projectMenu 
= wx
.Menu() 
1788 ##            accelTable = wx.AcceleratorTable([ 
1789 ##                eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID")) 
1791 ##            frame.SetAcceleratorTable(accelTable) 
1792         isProjectDocument 
= document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
 
1793         if wx
.GetApp().IsMDI() or isProjectDocument
: 
1794             if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
): 
1795                 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project")) 
1796                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
1797                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
1798             if not menuBar
.FindItemById(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
): 
1799                 projectMenu
.Append(ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project")) 
1800                 wx
.EVT_MENU(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
1801                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
1802             if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
): 
1803                 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project")) 
1804                 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
) 
1805                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
1806         viewMenuIndex 
= menuBar
.FindMenu(_("&View")) 
1807         menuBar
.Insert(viewMenuIndex 
+ 1, projectMenu
, _("&Project")) 
1808         editMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit"))) 
1809         if not menuBar
.FindItemById(ProjectService
.RENAME_ID
): 
1810             editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item")) 
1811             wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
) 
1812             wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
) 
1813         if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
): 
1814             editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system.")) 
1815             wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
) 
1816             wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
) 
1821     def OnCloseFrame(self
, event
): 
1822         if not self
.GetView(): 
1825         if wx
.GetApp().IsMDI(): 
1826             # close all non-project documents first 
1827             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
1828                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
1829                     if not self
.GetDocumentManager().CloseDocument(document
, False): 
1832             # write project config afterwards because user may change filenames on closing of new documents 
1833             self
.GetView().WriteProjectConfig()  # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere 
1835             # close all project documents after closing other documents 
1836             # because user may save a new document with a new name or cancel closing a document 
1837             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
1838                 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
1839                     if not document
.OnSaveModified(): 
1842         # This is called when any SDI frame is closed, so need to check if message window is closing or some other window 
1843         elif self
.GetView() == event
.GetEventObject().GetView(): 
1848     #---------------------------------------------------------------------------- 
1849     # Event Processing Methods 
1850     #---------------------------------------------------------------------------- 
1852     def ProcessEventBeforeWindows(self
, event
): 
1855         if id == wx
.ID_CLOSE_ALL
: 
1856             self
.OnFileCloseAll(event
) 
1859         elif id == wx
.ID_CLOSE
: 
1860             document 
= self
.GetDocumentManager().GetCurrentDocument() 
1861             if document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
1862                 self
.OnProjectClose(event
) 
1869     def ProcessUpdateUIEventBeforeWindows(self
, event
): 
1872         if id == wx
.ID_CLOSE_ALL
: 
1873             for document 
in self
.GetDocumentManager().GetDocuments(): 
1874                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
1881         elif id == wx
.ID_CLOSE
: 
1882             document 
= self
.GetDocumentManager().GetCurrentDocument() 
1883             if document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
1884                 projectFilenames 
= self
.GetView().GetSelectedProjects() 
1885                 if projectFilenames 
and len(projectFilenames
): 
1894     def ProcessEvent(self
, event
): 
1895         if Service
.Service
.ProcessEvent(self
, event
): 
1899         if id == ProjectService
.RUN_SELECTED_PM_ID
: 
1900             self
.OnRunProcessModel(event
, runSelected
=True) 
1902         elif id == ProjectService
.RUN_CURRENT_PM_ID
: 
1903             self
.OnRunProcessModel(event
, runCurrentFile
=True) 
1905         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1906             self
.OnAddCurrentFileToProject(event
) 
1908         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1910                 return self
.GetView().ProcessEvent(event
) 
1917     def ProcessUpdateUIEvent(self
, event
): 
1918         if Service
.Service
.ProcessUpdateUIEvent(self
, event
): 
1922         if (id == ProjectService
.RUNPM_ID
 
1923         or id == ProjectService
.RUN_SELECTED_PM_ID
 
1924         or id == ProjectService
.RUN_CURRENT_PM_ID
): 
1925             event
.Enable(self
._HasOpenedProjects
() and self
._HasProcessModel
()) 
1927         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1928             event
.Enable(self
._CanAddCurrentFileToProject
()) 
1930         elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
 
1931         or id == ProjectService
.ADD_ALL_FILES_TO_PROJECT_ID
 
1932         or id == ProjectService
.RENAME_ID
 
1933         or id == ProjectService
.OPEN_SELECTION_ID
 
1934         or id == ProjectService
.DELETE_FILE_ID
): 
1937         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1939                 return self
.GetView().ProcessUpdateUIEvent(event
) 
1946     def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False): 
1947         project 
= self
.GetView().GetDocument() 
1951             for template 
in self
.GetDocumentManager().GetTemplates(): 
1952                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
1953                     ext 
= template
.GetDefaultExtension() 
1958             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
1962             docs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
1964                 if doc
.GetFilename() in files 
and doc
.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
1965                     if not doc
.GetProcessModel().beginProcess
: 
1966                         wx
.MessageBox(_("Cannot run process.  No begin action found."), _("Run Process")) 
1969             filesModified 
= False 
1971                 if doc
.IsModified(): 
1972                     filesModified 
= True 
1975                 frame 
= self
.GetView().GetFrame()                 
1976                 yesNoMsg 
= wx
.MessageDialog(frame
, 
1977                               _("Files have been modified.  Process may not reflect your current changes.\n\nWould you like to save all files before running?"), 
1979                               wx
.YES_NO|wx
.ICON_QUESTION
 
1981                 if yesNoMsg
.ShowModal() == wx
.ID_YES
: 
1982                     wx
.GetTopLevelParent(frame
).OnFileSaveAll(None) 
1985                 fileToRun 
= self
.GetDocumentManager().GetCurrentDocument().GetFilename() 
1987                 fileToRun 
= self
.GetView().GetSelectedFile() 
1988             elif len(files
) > 1: 
1989                 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower())) 
1990                 strings 
= map(lambda file: os
.path
.basename(file), files
) 
1991                 res 
= wx
.GetSingleChoiceIndex(_("Select a process to run:"), 
1994                                               project
.GetFirstView()._GetParentFrame
()) 
1997                 fileToRun 
= files
[res
] 
1999                 fileToRun 
= files
[0] 
2001             self
.RunProcessModel(fileToRun
) 
2004     def RunProcessModel(self
, fileToRun
): 
2005         for runHandler 
in self
.GetRunHandlers(): 
2006             if runHandler
.RunProjectFile(fileToRun
): 
2008         os
.system('"' + fileToRun 
+ '"') 
2011     def _HasProcessModel(self
): 
2012         project 
= self
.GetView().GetDocument() 
2016             for template 
in self
.GetDocumentManager().GetTemplates(): 
2017                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
2018                     ext 
= template
.GetDefaultExtension() 
2023             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
2033     def _HasOpenedProjects(self
): 
2034         for document 
in self
.GetDocumentManager().GetDocuments(): 
2035             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
2040     def _HasCurrentFile(self
): 
2041         currentDoc 
= self
.GetDocumentManager().GetCurrentDocument() 
2045     def _CanAddCurrentFileToProject(self
): 
2046         currentDoc 
= self
.GetDocumentManager().GetCurrentDocument() 
2049         if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
2051         if not currentDoc
._savedYet
: 
2053         for document 
in self
.GetDocumentManager().GetDocuments(): 
2054             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
2056         return False  # There are no documents open 
2059     def GetFilesFromCurrentProject(self
): 
2060         view 
= self
.GetView() 
2062             project 
= view
.GetDocument() 
2064                 return project
.GetFiles() 
2068     def GetCurrentProject(self
): 
2069         view 
= self
.GetView() 
2071             return view
.GetDocument() 
2075     def FindProjectByFile(self
, filename
): 
2076         for document 
in self
.GetDocumentManager().GetDocuments(): 
2077             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
2078                 if document
.GetFilename() == filename
: 
2080                 elif document
.IsFileInProject(filename
): 
2085     def GetCurrentProjectNames(self
): 
2087         for document 
in self
.GetDocumentManager().GetDocuments(): 
2088             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
2089                 projects
.append(document
) 
2092         projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower())) 
2093         strings 
= map(lambda project
: project
.GetPrintableName(), projects
) 
2097     def OnAddCurrentFileToProject(self
, event
): 
2098         if not self
._CanAddCurrentFileToProject
(): 
2101         for document 
in self
.GetDocumentManager().GetDocuments(): 
2102             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
2103                 projects
.append(document
) 
2106         projects
.sort(lambda a
, b
: cmp(a
.GetPrintableName().lower(), b
.GetPrintableName().lower())) 
2107         strings 
= map(lambda project
: project
.GetPrintableName(), projects
) 
2108         res 
= wx
.GetSingleChoiceIndex(_("Select a project to add the file to:"), 
2109                                       _("Add to Project"), 
2111                                       self
.GetDocumentManager().FindSuitableParent()) 
2114         file = self
.GetDocumentManager().GetCurrentDocument().GetFilename() 
2115         projects
[res
].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects
[res
], [file])) 
2116         self
.GetView().Activate(True)  # after add, should put focus on project editor 
2119     def OnProjectClose(self
, event
): 
2120         projectFilenames 
= self
.GetView().GetSelectedProjects() 
2121         for filename 
in projectFilenames
: 
2122             doc 
= self
.FindProjectByFile(filename
) 
2124                 self
.GetDocumentManager().CloseDocument(doc
, False) 
2127     def OnFileCloseAll(self
, event
): 
2128         for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
2129             if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
2130                 if not self
.GetDocumentManager().CloseDocument(document
, False): 
2132                 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed 
2135     def OpenSavedProjects(self
): 
2136         config 
= wx
.ConfigBase_Get() 
2138         if config
.ReadInt("ProjectSaveDocs", True): 
2139             docString 
= config
.Read("ProjectSavedDocs") 
2142                 for fileName 
in eval(docString
): 
2143                     if isinstance(fileName
, types
.StringTypes
): 
2144                         if os
.path
.exists(fileName
): 
2145                             doc 
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT
) 
2149                     expandedString 
= config
.Read("ProjectExpandedSavedDocs") 
2151                         view 
= doc
.GetFirstView() 
2152                         view
.SetExpandedProjects(eval(expandedString
)) 
2156 class ProjectEditorMoveCommand(wx
.lib
.docview
.Command
): 
2158     def __init__(self
, view
, newPositionItem
, item
): 
2159         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
2162         self
._file 
= view
._treeCtrl
.GetLongFilename(item
) 
2163         if view
._IsItemFile
(item
): 
2164             self
._projectOld 
= view
._GetItemProject
(item
) 
2165         else:  # view._IsItemProject(item): 
2166             self
._projectOld 
= None 
2167         self
._projectNew 
= view
._GetItemProject
(newPositionItem
) 
2171         return _("Move File %s") % os
.path
.basename(self
._file
) 
2175         if self
._projectOld
: 
2176             self
._projectOld
.RemoveFile(self
._file
) 
2177         if self
._projectNew
: 
2178             self
._projectNew
.AddFile(self
._file
) 
2183         if self
._projectNew
: 
2184             self
._projectNew
.RemoveFile(self
._file
) 
2185         if self
._projectOld
: 
2186             self
._projectOld
.AddFile(self
._file
) 
2190 #---------------------------------------------------------------------------- 
2191 # Icon Bitmaps - generated by encode_bitmaps.py 
2192 #---------------------------------------------------------------------------- 
2193 from wx 
import ImageFromStream
, BitmapFromImage
 
2197 def getProjectData(): 
2199 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
2200 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
2201 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\ 
2202 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\ 
2203 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\ 
2204 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'  
2206 def getProjectBitmap(): 
2207     return BitmapFromImage(getProjectImage()) 
2209 def getProjectImage(): 
2210     stream 
= cStringIO
.StringIO(getProjectData()) 
2211     return ImageFromStream(stream
) 
2213 def getProjectIcon(): 
2214     return wx
.IconFromBitmap(getProjectBitmap()) 
2217 #---------------------------------------------------------------------------- 
2221 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
2222 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
2223 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\ 
2224 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\ 
2225 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\ 
2226 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\ 
2227 \x00\x00IEND\xaeB`\x82'  
2230 def getBlankBitmap(): 
2231     return BitmapFromImage(getBlankImage()) 
2233 def getBlankImage(): 
2234     stream 
= cStringIO
.StringIO(getBlankData()) 
2235     return ImageFromStream(stream
) 
2238     return wx
.IconFromBitmap(getBlankBitmap())