1 #---------------------------------------------------------------------------- 
   2 # Name:         ProjectEditor.py 
   3 # Purpose:      IDE-style Project Editor for wx.lib.pydocview 
   5 # Author:       Morgan Hua, Peter Yared 
   9 # Copyright:    (c) 2003, 2004, 2005 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  15 import wx
.lib
.pydocview
 
  17 from wxPython
.lib
.rcsizer 
import RowColSizer
 
  26 import activegrid
.util
.appdirs 
as appdirs
 
  27 import activegrid
.util
.fileutils 
as fileutils
 
  31 import project 
as projectlib
 
  32 import ExtensionService
 
  34 from IDE 
import ACTIVEGRID_BASE_IDE
 
  35 if not ACTIVEGRID_BASE_IDE
: 
  36     import activegrid
.server
.deployment 
as deploymentlib
 
  37     import ProcessModelEditor
 
  38     import DataModelEditor
 
  40     APP_LAST_LANGUAGE 
= "LastLanguage" 
  41     import activegrid
.model
.basedocmgr 
as basedocmgr
 
  42     import activegrid
.model
.basemodel 
as basemodel
 
  43     import PropertyService
 
  44     from activegrid
.server
.toolsupport 
import GetTemplate
 
  45     import activegrid
.util
.xmlutils 
as xmlutils
 
  46     import activegrid
.util
.sysutils 
as sysutils
 
  48 from SVNService 
import SVN_INSTALLED
 
  52 if wx
.Platform 
== '__WXMSW__': 
  57 #---------------------------------------------------------------------------- 
  59 #---------------------------------------------------------------------------- 
  62 PROJECT_EXTENSION 
= ".agp" 
  64 # wxBug: the wxTextCtrl and wxChoice controls on Mac do not correctly size 
  65 # themselves with sizers, so we need to add a right border to the sizer to 
  66 # get the control to shrink itself to fit in the sizer. 
  68 if wx
.Platform 
== "__WXMAC__": 
  72 PROJECT_KEY 
= "/AG_Projects" 
  73 PROJECT_DIRECTORY_KEY 
= "NewProjectDirectory" 
  75 NEW_PROJECT_DIRECTORY_DEFAULT 
= appdirs
.documents_folder
 
  77 #---------------------------------------------------------------------------- 
  79 #---------------------------------------------------------------------------- 
  81 def getProjectKeyName(projectName
, mode
): 
  82     return "%s/%s/%s" % (PROJECT_KEY
, projectName
.replace(os
.sep
, '|'), mode
) 
  85 def GetDocCallback(filepath
): 
  86     """ Get the Document used by the IDE and the in-memory document model used by runtime engine """ 
  87     docMgr 
= wx
.GetApp().GetDocumentManager() 
  89     doc 
= docMgr
.CreateDocument(filepath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
  90     if (doc 
== None):  # already open 
  91         for d 
in docMgr
.GetDocuments(): 
  92             if os
.path
.normcase(d
.GetFilename()) == os
.path
.normcase(filepath
): 
  96         projectService 
= wx
.GetApp().GetService(ProjectService
) 
  98             projectDocs 
= projectService
.FindProjectByFile(filepath
) 
 100                 projectDoc 
= projectDocs
[0] 
 101                 projectService
.AddProjectMapping(doc
, projectDoc
) 
 102                 if hasattr(doc
, "GetModel"): 
 103                     projectService
.AddProjectMapping(doc
.GetModel(), projectDoc
) 
 106     if doc 
and doc
.GetDocumentTemplate().GetDocumentType() == WsdlAgEditor
.WsdlAgDocument
: 
 107         # get referenced wsdl doc instead 
 108         if os
.path
.isabs(doc
.GetModel().filePath
):  # if absolute path, leave it alone 
 109             filepath 
= doc
.GetModel().filePath
 
 111             filepath 
= doc
.GetAppDocMgr().fullPath(doc
.GetModel().filePath
)  # check relative to project homeDir 
 113             if not os
.path
.isfile(filepath
): 
 114                 filepath 
= os
.path
.normpath(os
.path
.join(os
.path
.dirname(doc
.GetFilename()), doc
.GetModel().filePath
))  # check relative to wsdlag file 
 116                 if not os
.path
.isfile(filepath
): 
 117                     filename 
= os
.sep 
+ os
.path
.basename(doc
.GetModel().filePath
)  # check to see if in project file 
 118                     filePaths 
= findDocumentMgr(doc
).filePaths
 
 120                         if fp
.endswith(filename
): 
 124         doc 
= docMgr
.CreateDocument(filepath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
 125         if (doc 
== None):  # already open 
 126             for d 
in docMgr
.GetDocuments(): 
 127                 if os
.path
.normcase(d
.GetFilename()) == os
.path
.normcase(filepath
): 
 131             projectService 
= wx
.GetApp().GetService(ProjectService
) 
 133                 projectDocs 
= projectService
.FindProjectByFile(filepath
) 
 135                     projectDoc 
= projectDocs
[0] 
 136                     projectService
.AddProjectMapping(doc
, projectDoc
) 
 137                     if hasattr(doc
, "GetModel"): 
 138                         projectService
.AddProjectMapping(doc
.GetModel(), projectDoc
) 
 141         docModel 
= doc
.GetModel() 
 148 def findDocumentMgr(root
): 
 149     projectService 
= wx
.GetApp().GetService(ProjectService
) 
 151         projectDoc 
= projectService
.FindProjectFromMapping(root
) 
 153             return projectDoc
.GetModel() 
 155         projectDoc 
= projectService
.GetCurrentProject() 
 159         if isinstance(root
, wx
.lib
.docview
.Document
): 
 160             filepath 
= root
.GetFilename() 
 161         elif hasattr(root
, "fileName") and root
.fileName
: 
 162             filepath 
= root
.fileName
 
 167             if projectDoc
.IsFileInProject(filepath
): 
 168                 return projectDoc
.GetModel() 
 171             openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
 172             for openDoc 
in openDocs
: 
 173                 if openDoc 
== projectDoc
: 
 175                 if(isinstance(openDoc
, ProjectDocument
)): 
 176                     if openDoc
.IsFileInProject(filepath
): 
 177                         projects
.append(openDoc
) 
 180                 if len(projects
) == 1: 
 181                     return projects
[0].GetModel() 
 183                     choices 
= [os
.path
.basename(project
.GetFilename()) for project 
in projects
] 
 184                     dlg 
= wx
.SingleChoiceDialog(wx
.GetApp().GetTopWindow(), _("'%s' found in more than one project.\nWhich project should be used for this operation?") % os
.path
.basename(filepath
), _("Select Project"), choices
, wx
.DEFAULT_DIALOG_STYLE|wx
.RESIZE_BORDER|wx
.OK|wx
.CENTRE
) 
 187                     if dlg
.ShowModal() == wx
.ID_OK
: 
 188                         i 
= dlg
.GetSelection() 
 189                         projectDoc 
= projects
[i
] 
 191                     return projectDoc
.GetModel() 
 192         return projectDoc
.GetModel() 
 197 if not ACTIVEGRID_BASE_IDE
: 
 198     basemodel
.findGlobalDocumentMgr 
= findDocumentMgr
 
 201 #---------------------------------------------------------------------------- 
 203 #---------------------------------------------------------------------------- 
 205 class ProjectDocument(wx
.lib
.docview
.Document
): 
 208     def __init__(self
, model
=None): 
 209         wx
.lib
.docview
.Document
.__init
__(self
) 
 213             self
.SetModel(projectlib
.Project())  # initial model used by "File | New... | Project" 
 214         self
.GetModel().SetDocCallback(GetDocCallback
) 
 216         self
._stageProjectFile 
= False  
 220         model 
= copy
.copy(self
.GetModel())         
 221         clone 
=  ProjectDocument(model
) 
 222         clone
.SetFilename(self
.GetFilename()) 
 226     def GetFirstView(self
): 
 227         """ Bug: workaround.  If user tries to open an already open project with main menu "File | Open...", docview.DocManager.OnFileOpen() silently returns None if project is already open. 
 228             And to the user, it appears as if nothing has happened.  The user expects to see the open project. 
 229             This forces the project view to show the correct project. 
 231         view 
= wx
.lib
.docview
.Document
.GetFirstView(self
) 
 232         view
.SetProject(self
.GetFilename())  # ensure project is displayed in view 
 237         return self
._projectModel
 
 240     def SetModel(self
, model
): 
 241         self
._projectModel 
= model
 
 244     def OnCreate(self
, path
, flags
): 
 245         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 246         view 
= projectService
.GetView() 
 247         if view
:  # view already exists, reuse 
 248             # All project documents share the same view. 
 251             if view
.GetDocument(): 
 252                 # All project documents need to share the same command processor, 
 253                 # to enable redo/undo of cross project document commands 
 254                 cmdProcessor 
= view
.GetDocument().GetCommandProcessor() 
 256                     self
.SetCommandProcessor(cmdProcessor
) 
 257         else:  # generate view 
 258             view 
= self
.GetDocumentTemplate().CreateView(self
, flags
) 
 259             projectService
.SetView(view
) 
 264     def LoadObject(self
, fileObject
): 
 265         self
.SetModel(projectlib
.load(fileObject
)) 
 266         self
.GetModel().SetDocCallback(GetDocCallback
) 
 270     def SaveObject(self
, fileObject
): 
 271         projectlib
.save(fileObject
, self
.GetModel()) 
 275     def OnOpenDocument(self
, filePath
): 
 276         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 277         view 
= projectService
.GetView() 
 279         if not os
.path
.exists(filePath
): 
 280             wx
.GetApp().CloseSplash() 
 281             msgTitle 
= wx
.GetApp().GetAppName() 
 283                 msgTitle 
= _("File Error") 
 284             wx
.MessageBox(_("Could not find '%s'.") % filePath
, 
 286                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 287                           wx
.GetApp().GetTopWindow()) 
 288             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 290         fileObject 
= file(filePath
, 'r') 
 292             self
.LoadObject(fileObject
) 
 294             wx
.GetApp().CloseSplash() 
 295             msgTitle 
= wx
.GetApp().GetAppName() 
 297                 msgTitle 
= _("File Error") 
 298             wx
.MessageBox(_("Could not open '%s'.  %s") % (wx
.lib
.docview
.FileNameFromPath(filePath
), sys
.exc_value
), 
 300                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 301                           wx
.GetApp().GetTopWindow()) 
 302             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 305         self
.SetFilename(filePath
, True) 
 306         view
.AddProjectToView(self
) 
 307         self
.SetDocumentModificationDate() 
 308         self
.UpdateAllViews() 
 309         self
._savedYet 
= True 
 314     def AddFile(self
, filePath
, folderPath
=None, type=None, name
=None): 
 324         return self
.AddFiles([filePath
], folderPath
, types
, names
) 
 327     def AddFiles(self
, filePaths
=None, folderPath
=None, types
=None, names
=None, files
=None): 
 328         # Filter out files that are not already in the project 
 332             for filePath 
in filePaths
: 
 333                 if self
.GetModel().FindFile(filePath
): 
 334                     oldFilePaths
.append(filePath
) 
 336                     newFilePaths
.append(filePath
) 
 338             projectService 
= wx
.GetApp().GetService(ProjectService
) 
 339             for i
, filePath 
in enumerate(newFilePaths
): 
 348                     name 
= projectService
.FindNameDefault(filePath
) 
 351                     folder 
= projectService
.FindLogicalViewFolderDefault(filePath
) 
 355                 self
.GetModel().AddFile(filePath
, folder
, type, name
) 
 360                 if self
.GetModel().FindFile(file.filePath
): 
 361                     oldFilePaths
.append(file.filePath
) 
 363                     newFilePaths
.append(file.filePath
) 
 364                     self
.GetModel().AddFile(file=file) 
 368         self
.AddNameSpaces(newFilePaths
) 
 370         self
.UpdateAllViews(hint 
= ("add", self
, newFilePaths
, oldFilePaths
)) 
 371         if len(newFilePaths
): 
 378     def RemoveFile(self
, filePath
): 
 379         return self
.RemoveFiles([filePath
]) 
 382     def RemoveFiles(self
, filePaths
=None, files
=None): 
 388                 filePaths
.append(file.filePath
) 
 390         for filePath 
in filePaths
: 
 391             file = self
.GetModel().FindFile(filePath
) 
 393                 self
.GetModel().RemoveFile(file) 
 394                 removedFiles
.append(file.filePath
) 
 396         self
.UpdateAllViews(hint 
= ("remove", self
, removedFiles
)) 
 397         if len(removedFiles
): 
 404     def RenameFile(self
, oldFilePath
, newFilePath
, isProject 
= False): 
 406             if oldFilePath 
== newFilePath
: 
 409             # projects don't have to exist yet, so not required to rename old file, 
 410             # but files must exist, so we'll try to rename and allow exceptions to occur if can't. 
 411             if not isProject 
or (isProject 
and os
.path
.exists(oldFilePath
)): 
 412                 os
.rename(oldFilePath
, newFilePath
) 
 415                 documents 
= self
.GetDocumentManager().GetDocuments() 
 416                 for document 
in documents
: 
 417                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFilePath
):  # If the renamed document is open, update it 
 418                         document
.SetFilename(newFilePath
) 
 419                         document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFilePath
)) 
 420                         document
.UpdateAllViews(hint 
= ("rename", self
, oldFilePath
, newFilePath
)) 
 422                 self
.UpdateFilePath(oldFilePath
, newFilePath
) 
 423                 documents 
= self
.GetDocumentManager().GetDocuments() 
 424                 for document 
in documents
: 
 425                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFilePath
):  # If the renamed document is open, update it 
 426                         document
.SetFilename(newFilePath
, notifyViews 
= True) 
 427                         document
.UpdateAllViews(hint 
= ("rename", self
, oldFilePath
, newFilePath
)) 
 429         except OSError, (code
, message
): 
 430             msgTitle 
= wx
.GetApp().GetAppName() 
 432                 msgTitle 
= _("File Error") 
 433             wx
.MessageBox("Could not rename '%s'.  '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFilePath
), message
), 
 435                           wx
.OK | wx
.ICON_EXCLAMATION
, 
 436                           wx
.GetApp().GetTopWindow()) 
 440     def MoveFile(self
, file, newFolderPath
): 
 441         return self
.MoveFiles([file], newFolderPath
) 
 444     def MoveFiles(self
, files
, newFolderPath
): 
 446         isArray 
= isinstance(newFolderPath
, type([])) 
 447         for i 
in range(len(files
)): 
 449                 files
[i
].logicalFolder 
= newFolderPath
[i
] 
 451                 files
[i
].logicalFolder 
= newFolderPath
 
 452             filePaths
.append(files
[i
].filePath
) 
 454         self
.UpdateAllViews(hint 
= ("remove", self
, filePaths
)) 
 455         self
.UpdateAllViews(hint 
= ("add", self
, filePaths
, [])) 
 460     def UpdateFilePath(self
, oldFilePath
, newFilePath
): 
 461         file = self
.GetModel().FindFile(oldFilePath
) 
 462         self
.RemoveFile(oldFilePath
) 
 464             self
.AddFile(newFilePath
, file.logicalFolder
, file.type, file.name
) 
 466             self
.AddFile(newFilePath
) 
 469     def RemoveInvalidPaths(self
): 
 470         """Makes sure all paths project knows about are valid and point to existing files. Removes and returns list of invalid paths.""" 
 474         fileRefs 
= self
.GetFileRefs() 
 476         for fileRef 
in fileRefs
: 
 477             if not os
.path
.exists(fileRef
.filePath
): 
 478                 invalidFileRefs
.append(fileRef
) 
 480         for fileRef 
in invalidFileRefs
: 
 481             fileRefs
.remove(fileRef
) 
 483         return [fileRef
.filePath 
for fileRef 
in invalidFileRefs
] 
 485     def SetStageProjectFile(self
): 
 486         self
._stageProjectFile 
= True 
 488     def ArchiveProject(self
, zipdest
, tmpdir
=None, stagedir
=None): 
 489         """Stages the application files in tmpdir, and zips the stagedir, creating a zipfile that has the projectname, in zipdest. Returns path to zipfile. Optionally, pass in stagedir and we assume the app is already staged at stagedir (we don't stage again in that case).""" 
 492                 raise AssertionError("'tmpdir' must be set when not passing 'stagedir' so we know where to stage the app") 
 493             stagedir 
= self
.StageProject(tmpdir
) 
 494         if os
.path
.exists(zipdest
): 
 495             raise AssertionError("Cannot archive project, %s already exists" % zipdest
) 
 496         fileutils
.zip(zipdest
, stagedir
) 
 501     def StageProject(self
, tmpdir
): 
 502         """ Copies all files that project knows about into staging location. Files that live outside of the project dir are copied into the root of the stage dir, and their recorded file path is updated. Files that live inside of the project dir keep their relative path. Generates .dpl file into staging dir. Returns path to staging dir.""" 
 504         projname 
= self
.GetProjectName() 
 505         stagedir 
= os
.path
.join(tmpdir
, projname
) 
 506         fileutils
.remove(stagedir
) 
 507         os
.makedirs(stagedir
)         
 509         # remove invalid files from project 
 510         self
.RemoveInvalidPaths()         
 512         # required so relative paths are written correctly when .dpl file is 
 514         self
.SetFilename(os
.path
.join(stagedir
, 
 515                                       os
.path
.basename(self
.GetFilename()))) 
 516         projectdir 
= self
.GetModel().homeDir
 
 518         # Validate paths before actually copying, and populate a dict 
 519         # with src->dest so copying is easy. 
 520         # (fileDict: ProjectFile instance -> dest path (string)) 
 521         fileDict 
= self
._ValidateFilePaths
(projectdir
, stagedir
) 
 523         # copy files to staging dir 
 524         self
._StageFiles
(fileDict
) 
 526         # it is unfortunate we require this. it would be nice if filepaths 
 527         # were only in the project 
 528         self
._FixWsdlAgFiles
(stagedir
) 
 531         dplfilename 
= projname 
+ deploymentlib
.DEPLOYMENT_EXTENSION
 
 532         dplfilepath 
= os
.path
.join(stagedir
, dplfilename
) 
 533         self
.GenerateDeployment(dplfilepath
, productionDeployment
=True) 
 535         if self
._stageProjectFile
: 
 536             # save project so we get the .agp file. not required for deployment 
 537             # but convenient if user wants to open the deployment in the IDE 
 538             agpfilename 
= projname 
+ PROJECT_EXTENSION
 
 539             agpfilepath 
= os
.path
.join(stagedir
, agpfilename
)         
 542                 f 
= open(agpfilepath
, "w") 
 543                 # setting homeDir correctly is required for the "figuring out 
 544                 # relative paths" logic when saving the project 
 545                 self
.GetModel().homeDir 
= stagedir
 
 546                 projectlib
.save(f
, self
.GetModel(), productionDeployment
=True) 
 555     def _FixWsdlAgFiles(self
, stagedir
): 
 556         """For each wsdlag file in the stagedir: 
 557            Ensure the referenced wsdl file lives in root of stagedir. This 
 558            should be the case if wsdl is part of project (and staging has run). 
 559            If it is not at root of stagedir, copy it. Then update path in 
 561         files 
= os
.listdir(stagedir
) 
 563             if f
.endswith(WsdlAgEditor
.WsdlAgDocument
.WSDL_AG_EXT
): 
 564                 wsdlagpath 
= os
.path
.join(stagedir
, f
) 
 568                     fileObject 
= open(wsdlagpath
) 
 569                     serviceref 
= WsdlAgEditor
.load(fileObject
) 
 570                     if hasattr(serviceref
, "filePath") and serviceref
.filePath
: 
 571                         mod 
= self
.UpdateServiceRefFilePath(stagedir
,serviceref
) 
 578                 # no need to save the file if we did not change anything 
 581                 # write the wsdlag file 
 582                 fileObject 
= open(wsdlagpath
) 
 584                     serviceref 
= WsdlAgEditor
.save(fileObject
, serviceref
) 
 592     def UpdateServiceRefFilePath(self
, stagedir
, serviceref
): 
 593         """Returns True if serviceref.filePath has been updated, False otherwise.""" 
 594         if not os
.path
.exists(serviceref
.filePath
): 
 595             # should be an error? wrong place to 
 596             # validate that referenced file exists 
 597             # could print warning 
 600         # If the referenced file is in stagedir already, there's nothing to do 
 601         if fileutils
.hasAncestorDir(serviceref
.filePath
, stagedir
): 
 604         # The path points outside of stagedir. 
 606         # Check if we already have the referenced wsdl file at root, should be 
 607         # the case if the referenced wsdl is part of project 
 608         # Copy it if we don't have it 
 609         relPath 
= os
.path
.basename(serviceref
.filePath
) 
 610         stagepath 
= os
.path
.join(stagedir
, relPath
) 
 611         if not os
.path
.exists(stagepath
): 
 612             fileutils
.copyFile(serviceref
.filePath
, stagepath
) 
 614         serviceref
.filePath 
= relPath
 
 619     def _StageFiles(self
, fileDict
): 
 620         """Copy files to staging directory, update filePath attr of project's ProjectFile instances.""" 
 622         # fileDict: ProjectFile instance -> dest path (string) 
 624         for fileRef
, fileDest 
in fileDict
.items(): 
 625             fileutils
.copyFile(fileRef
.filePath
, fileDest
) 
 626             fileRef
.filePath 
= fileDest
 
 628     def _ValidateFilePaths(self
, projectdir
, stagedir
): 
 629         """If paths validate, returns a dict mapping ProjectFile to destination path. Destination path is the path the file needs to be copied to for staging. If paths don't validate, throws an IOError. 
 630            With our current slightly simplistic staging algorithm, staging will not work iff the project has files outside of the projectdir with names (filename without path) that: 
 631              -  match filenames of files living at the root of the project. 
 632              -  are same as those of any other file that lives outside of the projectdir. 
 634            We have this limitation because we move any file that lives outside of the project dir into the root of the stagedir (== copied project dir). We could make this smarter by either giving files unique names if we detect a collistion, or by creating some directory structure instead of putting all files from outside of the projectdir into the root of the stagedir (== copied projectdir).""" 
 636         # ProjectFile instance -> dest path (string) 
 639         projectRootFiles 
= sets
.Set()   # live at project root 
 640         foreignFiles 
= sets
.Set()       # live outside of project 
 642         fileRefsToDeploy 
= self
.GetFileRefs() 
 644         for fileRef 
in fileRefsToDeploy
: 
 645             relPath 
= fileutils
.getRelativePath(fileRef
.filePath
, projectdir
) 
 646             filename 
= os
.path
.basename(fileRef
.filePath
)             
 647             if not relPath
: # file lives outside of project dir... 
 649                 # do we have another file with the same name already? 
 650                 if filename 
in foreignFiles
: 
 651                     raise IOError("More than one file with name \"%s\" lives outside of the project. These files need to have unique names" % filename
) 
 652                 foreignFiles
.add(filename
)        
 653                 fileDest 
= os
.path
.join(stagedir
, filename
) 
 655                 # file lives somewhere within the project dir 
 656                 fileDest 
= os
.path
.join(stagedir
, relPath
) 
 657                 if not os
.path
.dirname(relPath
): 
 658                     projectRootFiles
.add(filename
) 
 660             rtn
[fileRef
] = fileDest
 
 662         # make sure we won't collide with a file that lives at root of 
 663         # projectdir when moving files into project 
 664         for filename 
in foreignFiles
: 
 665             if filename 
in projectRootFiles
: 
 666                 raise IOError("File outside of project, \"%s\", cannot have same name as file at project root" % filename
) 
 668         # REVIEW stoens@activegrid.com 19-Oct-05 -- 
 669         # We could also validate that user does not already have a .dpl file 
 670         # since we're going to generate one... 
 675     def RenameFolder(self
, oldFolderPath
, newFolderPath
): 
 676         for file in self
.GetModel()._files
: 
 677             if file.logicalFolder 
== oldFolderPath
: 
 678                 file.logicalFolder 
= newFolderPath
 
 679         self
.UpdateAllViews(hint 
= ("rename folder", self
, oldFolderPath
, newFolderPath
)) 
 685         return self
.GetModel().filePaths
 
 688     def GetFileRefs(self
): 
 689         return self
.GetModel().findAllRefs() 
 692     def SetFileRefs(self
, fileRefs
): 
 693         return self
.GetModel().setRefs(fileRefs
)     
 696     def IsFileInProject(self
, filename
): 
 697         return self
.GetModel().FindFile(filename
) 
 700     def GetAppInfo(self
): 
 701         return self
.GetModel().GetAppInfo() 
 704     def GetAppDocMgr(self
): 
 705         return self
.GetModel() 
 708     def GetProjectName(self
): 
 709         return os
.path
.splitext(os
.path
.basename(self
.GetFilename()))[0] 
 712     def GetDeploymentFilepath(self
): 
 713         projectName 
= self
.GetProjectName() 
 714         return os
.path
.join(self
.GetModel().homeDir
, projectName 
+ "RunTime_tmp" + deploymentlib
.DEPLOYMENT_EXTENSION
) 
 717     def GenerateDeployment(self
, deployFilepath
=None, preview
=False, productionDeployment
=False): 
 718         if ACTIVEGRID_BASE_IDE
: 
 721         def FindOpenDoc(filePath
): 
 722             openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
 723             for openDoc 
in openDocs
: 
 724                 if openDoc
.GetFilename() == filePath
: 
 728         if not deployFilepath
: 
 729             deployFilepath 
= self
.GetDeploymentFilepath() 
 731         deployment 
= deploymentlib
.Deployment(deployFilepath
) 
 733         defaultFlagsNoView 
= wx
.GetApp().GetDocumentManager().GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
 
 734         self
.GetAppInfo().CopyToDeployment(deployment
) 
 736         for file in self
.GetModel()._files
: 
 739             elif file.type == basedocmgr
.FILE_TYPE_SERVICE
:  # set serviceRefs 
 740                 doc 
= wx
.GetApp().GetDocumentManager().CreateDocument(file.filePath
, flags
=defaultFlagsNoView
) 
 741                 if (doc 
== None):  # already open 
 742                     doc 
= FindOpenDoc(file.filePath
) 
 744                     serviceRef 
= doc
.GetModel() 
 746                         documentRef 
= copy
.copy(serviceRef
) 
 747                         deployment
.serviceRefs
.append(documentRef
) 
 749                         if not productionDeployment
: 
 750                             # filePath should point to location of wsdl file 
 751                             # wsdlag filePath points to relative path to wsdl file from wsdlag location 
 752                             # but deployment needs relative path from deployment location, so here's the conversion 
 753                             curDir 
= os
.path
.dirname(self
.GetFilename()) + os
.sep
 
 754                             filePath 
= file.document
.fileName
 
 755                             if (filePath 
== None): 
 756                                 raise Exception("Cannot find file \"%s\"" % file.filePath
) 
 757                             if filePath
.startswith(curDir
): 
 758                                 filePath 
= filePath
[len(curDir
):] 
 760                                 filePath 
= filePath
.replace(os
.sep
, "/") 
 761                             documentRef
.filePath 
= filePath
 
 763                             documentRef
.document 
= file.document
 
 765                         if serviceRef
.serviceType 
== deploymentlib
.SERVICE_DATABASE 
and serviceRef
.databaseService
: 
 766                             dataSourceService 
= wx
.GetApp().GetService(DataModelEditor
.DataSourceService
) 
 767                             ds 
= dataSourceService
.getDataSource(serviceRef
.databaseService
.datasourceName
) 
 770                                 for d 
in deployment
.dataSources
: 
 771                                     if d
.name 
== ds
.name
: 
 775                                     deployment
.dataSources
.append(ds
) 
 777                 curDir 
= os
.path
.dirname(self
.GetFilename()) + os
.sep
 
 778                 filePath 
= file.filePath
 
 779                 if filePath
.startswith(curDir
): 
 780                     filePath 
= filePath
[len(curDir
):] 
 782                     filePath 
= filePath
.replace(os
.sep
, "/") 
 784                 if file.type == basedocmgr
.FILE_TYPE_XFORM
: 
 785                     documentRef 
= deploymentlib
.XFormRef() 
 786                     deployment
.xformRefs
.append(documentRef
) 
 787                 elif file.type == basedocmgr
.FILE_TYPE_PROCESS
: 
 788                     documentRef 
= deploymentlib
.ProcessRef() 
 789                     deployment
.processRefs
.append(documentRef
) 
 790                 elif file.type == basedocmgr
.FILE_TYPE_SCHEMA
: 
 792                     documentRef 
= deploymentlib
.SchemaRef() 
 793                     deployment
.schemaRefs
.append(documentRef
) 
 796                     doc 
= wx
.GetApp().GetDocumentManager().CreateDocument(file.filePath
, flags
=defaultFlagsNoView
) 
 797                     if (doc 
== None):  # already open 
 798                         doc 
= FindOpenDoc(file.filePath
) 
 800                         dataSourceService 
= wx
.GetApp().GetService(DataModelEditor
.DataSourceService
) 
 801                         ds 
= dataSourceService
.getDataSource(doc
.GetModel().getDefaultDataSourceName()) 
 804                             for d 
in deployment
.dataSources
: 
 805                                 if d
.name 
== ds
.name
: 
 809                                 deployment
.dataSources
.append(ds
) 
 812                         keyServices 
= doc
.GetModel().keyServices
 
 813                         for keyService 
in keyServices
:         
 814                             # add default key service to deployment 
 815                             if not productionDeployment
: 
 816                                 mainModuleDir 
= sysutils
.mainModuleDir
 
 818                                 mainModuleDir 
= sysutils
.MAINMODULE_DIR_VAR
 
 819                             wsdlFullPath 
= os
.path
.join(mainModuleDir
, "..", "wsdl", DataModelEditor
.DEFAULT_KEYSERVICE_WSDL_FILENAME
) 
 820                             keyServiceRef 
= deploymentlib
.ServiceRef(filePath
=wsdlFullPath
) 
 821                             deployment
.serviceRefs
.append(keyServiceRef
) 
 823                             keyServiceRef
.name 
= keyService
 
 824                             keyServiceRef
.serviceType 
= deploymentlib
.SERVICE_LOCAL
 
 825                             keyServiceRef
.localService 
= deploymentlib
.LocalService() 
 826                             if keyService 
== DataModelEditor
.DEFAULT_KEYSERVICE
: 
 827                                 keyServiceRef
.filePath 
= wsdlFullPath
 
 828                                 keyServiceRef
.localServiceClassName 
= DataModelEditor
.DEFAULT_KEYSERVICE_CLASSNAME
 
 831                 elif file.type == basedocmgr
.FILE_TYPE_SKIN
: 
 832                     documentRef 
= deploymentlib
.SkinRef(deployment
) 
 833                     deployment
.skinref 
= documentRef
 
 834                 elif file.type == basedocmgr
.FILE_TYPE_IDENTITY
: 
 835                     documentRef 
= deploymentlib
.IdentityRef() 
 836                     deployment
.identityRefs
.append(documentRef
) 
 840                 documentRef
.name 
= file.name
 
 841                 documentRef
.filePath 
= filePath
 
 842                 doc 
= FindOpenDoc(file.filePath
) 
 843                 if doc 
and hasattr(doc
, 'GetModel'): 
 844                     documentRef
.document 
= doc
.GetModel() 
 845                     if isinstance(documentRef
, deploymentlib
.XFormRef
): 
 846                         doc
.GetModel().linkDeployment(deployment
, deployment
.loader
) 
 849             deployment
.initialize()  # used in preview only 
 851         if 0: # preview:  # setPrototype not working, commented this out 
 852             deploymentlib
._deploymentCache
.setPrototype(deployment
.fileName
, deployment
) 
 854             deploymentlib
.saveThroughCache(deployment
.fileName
, deployment
) 
 856         return deployFilepath        
 
 859     def AddNameSpaces(self
, filePaths
): 
 860         """ Add any new wsdl namespaces to bpel files """ 
 861         """ Add any new schema namespaces to wsdl files """ 
 862         if ACTIVEGRID_BASE_IDE
: 
 865         serviceRefs 
= self
.GetAppDocMgr().allServiceRefs  
# wsdl 
 867         processRefs 
= self
.GetAppDocMgr().findRefsByFileType(basedocmgr
.FILE_TYPE_PROCESS
) # bpel 
 868         if processRefs 
and serviceRefs
: 
 869             for processRef 
in processRefs
: 
 870                 processDoc 
= processRef
._GetDoc
() 
 871                 process 
= processDoc
.GetModel() 
 874                 for serviceRef 
in serviceRefs
: 
 875                     wsdl 
= serviceRef
.document
 
 876                     if (wsdl
.fileName 
in filePaths
 
 877                     or serviceRef
.filePath 
in filePaths
): 
 878                         wsdlLongNS 
= wsdl
.targetNamespace
 
 879                         wsdlShortNS 
= self
.GetAppDocMgr().findShortNS(wsdlLongNS
) 
 881                             wsdlShortNS 
= xmlutils
.genShortNS(process
, wsdlLongNS
) 
 882                         xmlutils
.addNSAttribute(process
, wsdlShortNS
, wsdlLongNS
) 
 885                     processDoc
.OnSaveDocument(processDoc
.GetFilename()) 
 887         schemaRefs 
= self
.GetAppDocMgr().findRefsByFileType(basedocmgr
.FILE_TYPE_SCHEMA
) 
 888         if schemaRefs 
and serviceRefs
: 
 889             for serviceRef 
in serviceRefs
: 
 890                 wsdl 
= serviceRef
.document
 
 891                 wsdlDoc 
= serviceRef
.ideDocument
 
 894                 for schemaRef 
in schemaRefs
: 
 895                     schema 
= schemaRef
.document
 
 896                     if schema
.fileName 
in filePaths
: 
 897                         schemaLongNS 
= schema
.targetNamespace
 
 898                         schemaShortNS 
= self
.GetAppDocMgr().findShortNS(schemaLongNS
) 
 899                         if not schemaShortNS
: 
 900                             schemaShortNS 
= xmlutils
.genShortNS(process
, schemaLongNS
) 
 901                         xmlutils
.addNSAttribute(wsdl
, schemaShortNS
, schemaLongNS
) 
 904                     wsdlDoc
.OnSaveDocument(wsdlDoc
.GetFilename()) 
 907 class NewProjectWizard(Wizard
.BaseWizard
): 
 909     WIZTITLE 
= _("New Project Wizard") 
 912     def __init__(self
, parent
): 
 913         self
._parent 
= parent
 
 914         self
._fullProjectPath 
= None 
 915         Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
) 
 916         self
._projectLocationPage 
= self
.CreateProjectLocation(self
) 
 917         wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
) 
 920     def CreateProjectLocation(self
,wizard
): 
 921         page 
= Wizard
.TitledWizardPage(wizard
, _("Project File Location")) 
 923         page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nSelect the directory and filename for the project.\n\n"))) 
 924         self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation 
= UICommon
.CreateDirectoryControl(page
, fileExtension
="agp", appDirDefaultStartDir
=True) 
 925         page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
) 
 928         wizard
.FitToPage(page
) 
 932     def RunWizard(self
, existingTables 
= None, existingRelationships 
= None): 
 933         status 
= wx
.wizard
.Wizard
.RunWizard(self
, self
._projectLocationPage
) 
 935             wx
.ConfigBase_Get().Write(PROJECT_DIRECTORY_KEY
, self
._dirCtrl
.GetValue()) 
 936             docManager 
= wx
.GetApp().GetTopWindow().GetDocumentManager() 
 937             if os
.path
.exists(self
._fullProjectPath
): 
 938                 # What if the document is already open and we're overwriting it? 
 939                 documents 
= docManager
.GetDocuments() 
 940                 for document 
in documents
: 
 941                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(self
._fullProjectPath
):  # If the renamed document is open, update it 
 942                         document
.DeleteAllViews() 
 944                 os
.remove(self
._fullProjectPath
) 
 946             for template 
in docManager
.GetTemplates(): 
 947                 if template
.GetDocumentType() == ProjectDocument
: 
 948                     doc 
= template
.CreateDocument(self
._fullProjectPath
, flags 
= wx
.lib
.docview
.DOC_NEW
) 
 949                     doc
.OnSaveDocument(self
._fullProjectPath
) 
 950                     projectService 
= wx
.GetApp().GetService(ProjectService
) 
 951                     view 
= projectService
.GetView() 
 952                     view
.AddProjectToView(doc
) 
 959     def OnWizPageChanging(self
, event
): 
 960         if event
.GetDirection():  # It's going forwards 
 961             if event
.GetPage() == self
._projectLocationPage
: 
 962                 if not self
._fileValidation
(noFirstCharDigit
=True): 
 965                 self
._fullProjectPath 
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(), PROJECT_EXTENSION
)) 
 968     def OnShowCreatePages(self
): 
 970         import DataModelEditor
 
 971         requestedPos 
= self
.GetPositionTuple() 
 972         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 973         projectView 
= projectService
.GetView() 
 975         wiz 
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
) 
 976         if wiz
.RunWizard(dontDestroy
=True): 
 977            self
._schemaName
.SetValue(wiz
.GetSchemaFileName()) 
 982 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
): 
 985     def CreateDocument(self
, path
, flags
): 
 987             doc 
= wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
) 
 989                 doc
.GetModel()._projectDir 
= os
.path
.dirname(path
) 
 992             wiz 
= NewProjectWizard(wx
.GetApp().GetTopWindow()) 
 995             return None  # never return the doc, otherwise docview will think it is a new file and rename it 
 998 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
): 
1001     def __init__(self
, projectDoc
, filePaths
, folderPath
=None, types
=None, names
=None): 
1002         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1003         self
._projectDoc 
= projectDoc
 
1004         self
._allFilePaths 
= filePaths
 
1005         self
._folderPath 
= folderPath
 
1011             projectService 
= wx
.GetApp().GetService(ProjectService
) 
1012             for filePath 
in self
._allFilePaths
: 
1013                 self
._types
.append(projectService
.FindFileTypeDefault(filePath
)) 
1015         # list of files that will really be added 
1017         for filePath 
in self
._allFilePaths
: 
1018             if not projectDoc
.GetModel().FindFile(filePath
): 
1019                 self
._newFiles
.append(filePath
) 
1023         if len(self
._allFilePaths
) == 1: 
1024             return _("Add File %s") % os
.path
.basename(self
._allFilePaths
[0]) 
1026             return _("Add Files") 
1030         return self
._projectDoc
.AddFiles(self
._allFilePaths
, self
._folderPath
, self
._types
, self
._names
) 
1034         return self
._projectDoc
.RemoveFiles(self
._newFiles
) 
1037 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
): 
1040     def __init__(self
, projectDoc
, files
): 
1041         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1042         self
._projectDoc 
= projectDoc
 
1047         if len(self
._files
) == 1: 
1048             return _("Remove File %s") % os
.path
.basename(self
._files
[0].filePath
) 
1050             return _("Remove Files") 
1054         return self
._projectDoc
.RemoveFiles(files
=self
._files
) 
1058         return self
._projectDoc
.AddFiles(files
=self
._files
) 
1062 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
): 
1065     def __init__(self
, projectDoc
, oldFilePath
, newFilePath
, isProject 
= False): 
1066         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1067         self
._projectDoc 
= projectDoc
 
1068         self
._oldFilePath 
= oldFilePath
 
1069         self
._newFilePath 
= newFilePath
 
1070         self
._isProject 
= isProject
 
1074         return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFilePath
), os
.path
.basename(self
._newFilePath
)) 
1078         return self
._projectDoc
.RenameFile(self
._oldFilePath
, self
._newFilePath
, self
._isProject
) 
1082         return self
._projectDoc
.RenameFile(self
._newFilePath
, self
._oldFilePath
, self
._isProject
) 
1085 class ProjectRenameFolderCommand(wx
.lib
.docview
.Command
): 
1086     def __init__(self
, doc
, oldFolderPath
, newFolderPath
): 
1087         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1089         self
._oldFolderPath 
= oldFolderPath
 
1090         self
._newFolderPath 
= newFolderPath
 
1094         return _("Rename Folder %s to %s") % (os
.path
.basename(self
._oldFolderPath
), os
.path
.basename(self
._newFolderPath
)) 
1098         return self
._doc
.RenameFolder(self
._oldFolderPath
, self
._newFolderPath
) 
1102         return self
._doc
.RenameFolder(self
._newFolderPath
, self
._oldFolderPath
) 
1105 class ProjectAddFolderCommand(wx
.lib
.docview
.Command
): 
1106     def __init__(self
, view
, doc
, folderpath
): 
1107         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1110         self
._folderpath 
= folderpath
 
1114         return _("Add Folder %s") % (os
.path
.basename(self
._folderpath
)) 
1118         if self
._view
.GetDocument() != self
._doc
: 
1120         status 
= self
._view
.AddFolder(self
._folderpath
) 
1122             self
._view
._treeCtrl
.UnselectAll() 
1123             item 
= self
._view
._treeCtrl
.FindFolder(self
._folderpath
) 
1124             self
._view
._treeCtrl
.SelectItem(item
) 
1129         if self
._view
.GetDocument() != self
._doc
: 
1131         return self
._view
.DeleteFolder(self
._folderpath
) 
1134 class ProjectRemoveFolderCommand(wx
.lib
.docview
.Command
): 
1135     def __init__(self
, view
, doc
, folderpath
): 
1136         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1139         self
._folderpath 
= folderpath
 
1143         return _("Remove Folder %s") % (os
.path
.basename(self
._folderpath
)) 
1147         if self
._view
.GetDocument() != self
._doc
: 
1149         return self
._view
.DeleteFolder(self
._folderpath
) 
1153         if self
._view
.GetDocument() != self
._doc
: 
1155         status 
= self
._view
.AddFolder(self
._folderpath
) 
1157             self
._view
._treeCtrl
.UnselectAll() 
1158             item 
= self
._view
._treeCtrl
.FindFolder(self
._folderpath
) 
1159             self
._view
._treeCtrl
.SelectItem(item
) 
1163 class ProjectMoveFilesCommand(wx
.lib
.docview
.Command
): 
1165     def __init__(self
, doc
, files
, folderPath
): 
1166         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1169         self
._newFolderPath 
= folderPath
 
1171         self
._oldFolderPaths 
= [] 
1172         for file in self
._files
: 
1173             self
._oldFolderPaths
.append(file.logicalFolder
) 
1177         if len(self
._files
) == 1: 
1178             return _("Move File %s") % os
.path
.basename(self
._files
[0].filePath
) 
1180             return _("Move Files") 
1184         return self
._doc
.MoveFiles(self
._files
, self
._newFolderPath
) 
1188         return self
._doc
.MoveFiles(self
._files
, self
._oldFolderPaths
)             
1191 class ProjectTreeCtrl(wx
.TreeCtrl
): 
1193     #---------------------------------------------------------------------------- 
1194     # Overridden Methods 
1195     #---------------------------------------------------------------------------- 
1197     def __init__(self
, parent
, id, style
): 
1198         wx
.TreeCtrl
.__init
__(self
, parent
, id, style 
= style
) 
1200         templates 
= wx
.GetApp().GetDocumentManager().GetTemplates() 
1201         iconList 
= wx
.ImageList(16, 16, initialCount 
= len(templates
)) 
1202         self
._iconIndexLookup 
= [] 
1203         for template 
in templates
: 
1204             icon 
= template
.GetIcon() 
1206                 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1209                     if wx
.GetApp().GetDebug(): 
1210                         print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
 
1211                 iconIndex 
= iconList
.AddIcon(icon
) 
1212                 self
._iconIndexLookup
.append((template
, iconIndex
)) 
1214         icon 
= getBlankIcon() 
1215         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1218             if wx
.GetApp().GetDebug(): 
1219                 print "Warning: getBlankIcon isn't 16x16, not crossplatform" 
1220         self
._blankIconIndex 
= iconList
.AddIcon(icon
) 
1222         icon 
= getFolderClosedIcon() 
1223         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1226             if wx
.GetApp().GetDebug(): 
1227                 print "Warning: getFolderIcon isn't 16x16, not crossplatform" 
1228         self
._folderClosedIconIndex 
= iconList
.AddIcon(icon
) 
1230         icon 
= getFolderOpenIcon() 
1231         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1234             if wx
.GetApp().GetDebug(): 
1235                 print "Warning: getFolderIcon isn't 16x16, not crossplatform" 
1236         self
._folderOpenIconIndex 
= iconList
.AddIcon(icon
) 
1238         self
.AssignImageList(iconList
) 
1241     def OnCompareItems(self
, item1
, item2
): 
1242         item1IsFolder 
= (self
.GetPyData(item1
) == None) 
1243         item2IsFolder 
= (self
.GetPyData(item2
) == None) 
1244         if (item1IsFolder 
== item2IsFolder
):  # if both are folders or both not 
1245             return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower()) 
1246         elif item1IsFolder 
and not item2IsFolder
: # folders sort above non-folders 
1248         elif not item1IsFolder 
and item2IsFolder
: # folders sort above non-folders 
1252     def AppendFolder(self
, parent
, folderName
): 
1253         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, folderName
) 
1254         self
.SetItemImage(item
, self
._folderClosedIconIndex
, wx
.TreeItemIcon_Normal
) 
1255         self
.SetItemImage(item
, self
._folderOpenIconIndex
, wx
.TreeItemIcon_Expanded
) 
1256         self
.SetPyData(item
, None) 
1260     def AppendItem(self
, parent
, filename
, file): 
1261         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, filename
) 
1264         template 
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filename
) 
1266             for t
, iconIndex 
in self
._iconIndexLookup
: 
1268                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
) 
1269                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
) 
1270 ##                    self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected) 
1275             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
) 
1276             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
) 
1277 ##            self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected) 
1279         self
.SetPyData(item
, file) 
1284     def AddFolder(self
, folderPath
): 
1287         if folderPath 
!= None: 
1288             folderTree 
= folderPath
.split('/') 
1290             item 
= self
.GetRootItem() 
1291             for folderName 
in folderTree
: 
1294                 (child
, cookie
) = self
.GetFirstChild(item
) 
1296                     file = self
.GetPyData(child
) 
1300                         if self
.GetItemText(child
) == folderName
: 
1304                     (child
, cookie
) = self
.GetNextChild(item
, cookie
) 
1307                     item 
= self
.AppendFolder(item
, folderName
) 
1308                     folderItems
.append(item
) 
1313     def FindItem(self
, filePath
, parentItem
=None): 
1315             parentItem 
= self
.GetRootItem() 
1317         (child
, cookie
) = self
.GetFirstChild(parentItem
) 
1319             file = self
.GetPyData(child
) 
1321                 if file.filePath 
== filePath
: 
1324                 result 
= self
.FindItem(filePath
, child
)  # do recursive call 
1327             (child
, cookie
) = self
.GetNextChild(parentItem
, cookie
) 
1332     def FindFolder(self
, folderPath
): 
1333         if folderPath 
!= None: 
1334             folderTree 
= folderPath
.split('/') 
1336             item 
= self
.GetRootItem() 
1337             for folderName 
in folderTree
: 
1340                 (child
, cookie
) = self
.GetFirstChild(item
) 
1342                     file = self
.GetPyData(child
) 
1346                         if self
.GetItemText(child
) == folderName
: 
1350                     (child
, cookie
) = self
.GetNextChild(item
, cookie
) 
1358     def FindClosestFolder(self
, x
, y
): 
1359         item
, flags 
= self
.HitTest((x
,y
)) 
1361             file = self
.GetPyData(item
) 
1363                 item 
= self
.GetItemParent(item
) 
1369 class ProjectView(wx
.lib
.docview
.View
): 
1370     LOGICAL_MODE  
= "logical" 
1371     PHYSICAL_MODE 
= "physical" 
1373     #---------------------------------------------------------------------------- 
1374     # Overridden methods 
1375     #---------------------------------------------------------------------------- 
1377     def __init__(self
, service 
= None): 
1378         wx
.lib
.docview
.View
.__init
__(self
) 
1379         # self._service = service  # not used, but kept to match other Services 
1380         self
._projectChoice 
= None 
1381         self
._logicalBtn 
= None 
1382         self
._physicalBtn 
= None 
1383         self
._treeCtrl 
= None 
1384         self
._editingSoDontKillFocus 
= False 
1385         self
._checkEditMenu 
= True 
1386         self
._loading 
= False  # flag to not to try to saving state of folders while it is loading 
1389     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 
1390         return wx
.GetApp().GetDocumentManager() 
1394         projectService 
= wx
.GetApp().GetService(ProjectService
) 
1396             projectService
.SetView(None) 
1397         wx
.lib
.docview
.View
.Destroy(self
) 
1400     def GetDocument(self
): 
1401         if not self
._projectChoice
: 
1404         selItem 
= self
._projectChoice
.GetSelection() 
1405         if selItem 
== wx
.NOT_FOUND
: 
1408         document 
= self
._projectChoice
.GetClientData(selItem
) 
1412     def Activate(self
, activate 
= True): 
1413         if not wx
.GetApp().IsMDI(): 
1414             if activate 
and not self
.IsShown(): 
1418             wx
.lib
.docview
.View
.Activate(self
, activate 
= activate
) 
1419             if activate 
and self
._treeCtrl
: 
1420                 self
._treeCtrl
.SetFocus() 
1423     def OnCreate(self
, doc
, flags
): 
1424         config 
= wx
.ConfigBase_Get() 
1425         if wx
.GetApp().IsMDI(): 
1426             self
._embeddedWindow 
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
) 
1427             self
.SetFrame(self
._embeddedWindow
) 
1428             frame 
= self
._embeddedWindow
 
1429             wx
.EVT_SIZE(frame
, self
.OnSize
) 
1431             self
._embeddedWindow 
= None 
1432             pos 
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1) 
1433             # make sure frame is visible 
1434             screenWidth 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
) 
1435             screenHeight 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
) 
1436             if pos
[0] < 0 or pos
[0] >= screenWidth 
or pos
[1] < 0 or pos
[1] >= screenHeight
: 
1437                 pos 
= wx
.DefaultPosition
 
1439             size 
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1)) 
1441             title 
= _("Projects") 
1442             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI 
and wx
.GetApp().GetAppName(): 
1443                 title 
=  title 
+ " - " + wx
.GetApp().GetAppName() 
1445             frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title 
= title
, pos 
= pos
, size 
= size
) 
1446             if config
.ReadInt("ProjectFrameMaximized", False): 
1447                 frame
.Maximize(True) 
1449         panel 
= wx
.Panel(frame
, -1) 
1451         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1453         butSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
1455         self
._projectChoice 
= wx
.Choice(panel
, -1) 
1456         panel
.Bind(wx
.EVT_CHOICE
, self
.OnProjectSelect
, self
._projectChoice
) 
1457         w
, h 
= self
._projectChoice
.GetSize() 
1459         self
._logicalBtn 
= wx
.lib
.buttons
.GenBitmapToggleButton(panel
, -1, getLogicalModeOffBitmap(), size
=(h
,h
)) 
1460         self
._logicalBtn
.SetBitmapSelected(getLogicalModeOnBitmap()) 
1461         self
._logicalBtn
.SetToggle(True) 
1462         self
._logicalBtn
.SetToolTipString(_("View Files by Logical Groups")) 
1463         panel
.Bind(wx
.EVT_BUTTON
, self
.OnSelectMode
, self
._logicalBtn
) 
1464         self
._physicalBtn 
= wx
.lib
.buttons
.GenBitmapToggleButton(panel
, -1, getPhysicalModeOffBitmap(), size
=(h
,h
)) 
1465         self
._physicalBtn
.SetBitmapSelected(getPhysicalModeOnBitmap()) 
1466         self
._physicalBtn
.SetToolTipString(_("View Files by Physical Disk Layout")) 
1467         panel
.Bind(wx
.EVT_BUTTON
, self
.OnSelectMode
, self
._physicalBtn
) 
1469         butSizer
.Add(self
._projectChoice
, 1, wx
.EXPAND
) 
1470         butSizer
.Add(self
._logicalBtn
, 0) 
1471         butSizer
.Add(self
._physicalBtn
, 0) 
1472         sizer
.Add(butSizer
, 0, wx
.EXPAND
) 
1474         self
._treeCtrl 
= ProjectTreeCtrl(panel
, -1, style 
= wx
.TR_HIDE_ROOT | wx
.TR_HAS_BUTTONS | wx
.TR_EDIT_LABELS | wx
.TR_DEFAULT_STYLE | wx
.TR_MULTIPLE | wx
.TR_EXTENDED
) 
1475         self
._treeCtrl
.AddRoot(_("Projects")) 
1476         wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
) 
1477         wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
) 
1478         if self
._embeddedWindow
: 
1479             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND|wx
.BOTTOM
, HALF_SPACE
)  # allow space for embedded window resize-sash 
1481             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
) 
1482         panel
.SetSizer(sizer
) 
1484         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1486         if wx
.GetApp().IsMDI(): 
1487             sizer
.Add(panel
, 1, wx
.EXPAND|wx
.BOTTOM
, 1) # wx.Bug: without bottom margin, can't resize embedded window 
1489             sizer
.Add(panel
, 1, wx
.EXPAND
) 
1491         frame
.SetSizer(sizer
) 
1495         if wx
.GetApp().IsMDI(): 
1496             wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
) 
1497             wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
) 
1499         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
1500             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
) 
1502             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
) 
1503         wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
) 
1504         wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
) 
1505         wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
) 
1506         wx
.EVT_LEFT_DOWN(self
._treeCtrl
, self
.OnLeftClick
) 
1507         wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
) 
1508         wx
.EVT_TREE_ITEM_COLLAPSED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.SaveFolderState
) 
1509         wx
.EVT_TREE_ITEM_EXPANDED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.SaveFolderState
) 
1510         # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason 
1512         # drag-and-drop support 
1513         dt 
= ProjectFileDropTarget(self
) 
1514         self
._treeCtrl
.SetDropTarget(dt
) 
1519     def OnSelectMode(self
, event
): 
1520         btn 
= event
.GetEventObject() 
1521         down 
= event
.GetIsDown() 
1522         if btn 
== self
._logicalBtn
: 
1523             self
._physicalBtn
.SetToggle(not down
) 
1524         else:  # btn == self._physicalBtn: 
1525             self
._logicalBtn
.SetToggle(not down
) 
1526         self
.LoadProject(self
.GetDocument()) 
1530         if not self
._physicalBtn
.up
: 
1531             return ProjectView
.PHYSICAL_MODE
 
1532         else:  # elif self._logicalBtn.GetValue(): 
1533             return ProjectView
.LOGICAL_MODE
 
1536     def OnProjectSelect(self
, event
=None): 
1537         self
.LoadProject(self
.GetDocument()) 
1538         if self
.GetDocument(): 
1539             filename 
= self
.GetDocument().GetFilename() 
1542         self
._projectChoice
.SetToolTipString(filename
) 
1545     def OnSize(self
, event
): 
1547         wx
.CallAfter(self
.GetFrame().Layout
) 
1550     def OnBeginDrag(self
, event
): 
1551         if self
.GetMode() == ProjectView
.PHYSICAL_MODE
: 
1554         item 
= event
.GetItem() 
1556             self
._draggingItems 
= [] 
1557             for item 
in self
._treeCtrl
.GetSelections(): 
1558                 if self
._IsItemFile
(item
): 
1559                     self
._draggingItems
.append(item
) 
1560             if len(self
._draggingItems
): 
1564     def OnEndDrag(self
, event
): 
1565         item 
= event
.GetItem() 
1568             for ditem 
in self
._draggingItems
: 
1569                 file = self
._GetItemFile
(ditem
) 
1570                 if file not in files
: 
1573             folderPath 
= self
._GetItemFolderPath
(item
) 
1575             self
.GetDocument().GetCommandProcessor().Submit(ProjectMoveFilesCommand(self
.GetDocument(), files
, folderPath
)) 
1578     def WriteProjectConfig(self
): 
1579         frame 
= self
.GetFrame() 
1580         config 
= wx
.ConfigBase_Get() 
1581         if frame 
and not self
._embeddedWindow
: 
1582             if not frame
.IsMaximized(): 
1583                 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0]) 
1584                 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1]) 
1585                 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0]) 
1586                 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1]) 
1587             config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized()) 
1589         if config
.ReadInt("ProjectSaveDocs", True): 
1590             projectFileNames 
= [] 
1593             if self
._projectChoice
: 
1594                 for i 
in range(self
._projectChoice
.GetCount()): 
1595                     project 
= self
._projectChoice
.GetClientData(i
) 
1596                     if not project
.OnSaveModified(): 
1598                     if project
.GetDocumentSaved():  # Might be a new document and "No" selected to save it 
1599                         projectFileNames
.append(str(project
.GetFilename())) 
1600             config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__()) 
1603             if self
._projectChoice
.GetCount(): 
1604                 i 
= self
._projectChoice
.GetSelection() 
1605                 if i 
!= wx
.NOT_FOUND
: 
1606                     document 
= self
._projectChoice
.GetClientData(i
) 
1608                 config
.Write("ProjectCurrent", document
.GetFilename()) 
1610                 config
.DeleteEntry("ProjectCurrent") 
1613     def OnClose(self
, deleteWindow 
= True): 
1614         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
1615             self
.WriteProjectConfig() 
1617         project 
= self
.GetDocument() 
1620         if not project
.Close(): 
1623         if not deleteWindow
: 
1624             self
.RemoveCurrentDocumentUpdate() 
1626             # need this to accelerate closing down app if treeCtrl has lots of items 
1627             self
._treeCtrl
.Freeze() 
1628             rootItem 
= self
._treeCtrl
.GetRootItem() 
1629             self
._treeCtrl
.DeleteChildren(rootItem
) 
1630             self
._treeCtrl
.Thaw() 
1632         # We don't need to delete the window since it is a floater/embedded 
1636     def _GetParentFrame(self
): 
1637         return wx
.GetTopLevelParent(self
.GetFrame()) 
1640     def OnUpdate(self
, sender 
= None, hint 
= None): 
1641         wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
) 
1644             if hint
[0] == "add": 
1645                 projectDoc 
= hint
[1] 
1646                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1649                 self
._treeCtrl
.Freeze() 
1651                 newFilePaths 
= hint
[2]  # need to be added and selected, and sorted 
1652                 oldFilePaths 
= hint
[3]  # need to be selected 
1653                 self
._treeCtrl
.UnselectAll() 
1655                 mode 
= self
.GetMode() 
1657                 project 
= projectDoc
.GetModel() 
1658                 projectDir 
= project
.homeDir
 
1659                 rootItem 
= self
._treeCtrl
.GetRootItem() 
1661                 # add new folders and new items 
1663                 for filePath 
in newFilePaths
: 
1664                     file = project
.FindFile(filePath
) 
1666                         if mode 
== ProjectView
.LOGICAL_MODE
: 
1667                             folderPath 
= file.logicalFolder
 
1668                         else:  # ProjectView.PHYSICAL_MODE 
1669                             folderPath 
= file.GetRelativeFolder(projectDir
) 
1671                             self
._treeCtrl
.AddFolder(folderPath
) 
1672                             folder 
= self
._treeCtrl
.FindFolder(folderPath
) 
1675                         item 
= self
._treeCtrl
.AppendItem(folder
, os
.path
.basename(file.filePath
), file) 
1676                         addList
.append(item
) 
1678                 # sort folders with new items 
1680                 for item 
in addList
: 
1681                     parentItem 
= self
._treeCtrl
.GetItemParent(item
) 
1682                     if parentItem 
not in parentList
: 
1683                         parentList
.append(parentItem
) 
1684                 for parentItem 
in parentList
: 
1685                     self
._treeCtrl
.SortChildren(parentItem
) 
1687                 # select all the items user wanted to add 
1689                 for filePath 
in (oldFilePaths 
+ newFilePaths
): 
1690                     item 
= self
._treeCtrl
.FindItem(filePath
) 
1692                         self
._treeCtrl
.SelectItem(item
) 
1696                     self
._treeCtrl
.EnsureVisible(lastItem
) 
1698                 self
._treeCtrl
.Thaw() 
1701             elif hint
[0] == "remove": 
1702                 projectDoc 
= hint
[1] 
1703                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1706                 self
._treeCtrl
.Freeze() 
1709                 self
._treeCtrl
.UnselectAll() 
1711                 for filePath 
in filePaths
: 
1712                     item 
= self
._treeCtrl
.FindItem(filePath
) 
1714                         self
._treeCtrl
.Delete(item
) 
1716                 self
._treeCtrl
.UnselectAll()  # wxBug: even though we unselected earlier, an item still gets selected after the delete 
1718                 self
._treeCtrl
.Thaw() 
1721             elif hint
[0] == "rename": 
1722                 projectDoc 
= hint
[1] 
1723                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1726                 self
._treeCtrl
.Freeze() 
1727                 item 
= self
._treeCtrl
.FindItem(hint
[2]) 
1728                 self
._treeCtrl
.SetItemText(item
, os
.path
.basename(hint
[3])) 
1729                 self
._treeCtrl
.EnsureVisible(item
) 
1730                 self
._treeCtrl
.Thaw() 
1733             elif hint
[0] == "rename folder": 
1734                 projectDoc 
= hint
[1] 
1735                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1738                 self
._treeCtrl
.Freeze() 
1739                 item 
= self
._treeCtrl
.FindFolder(hint
[2]) 
1741                     self
._treeCtrl
.UnselectAll() 
1742                     self
._treeCtrl
.SetItemText(item
, os
.path
.basename(hint
[3])) 
1743                     self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
1744                     self
._treeCtrl
.SelectItem(item
) 
1745                     self
._treeCtrl
.EnsureVisible(item
) 
1746                 self
._treeCtrl
.Thaw() 
1750     def RemoveProjectUpdate(self
, projectDoc
): 
1751         """ Called by service after deleting a project, need to remove from project choices """ 
1752         i 
= self
._projectChoice
.FindString(self
._MakeProjectName
(projectDoc
)) 
1753         self
._projectChoice
.Delete(i
) 
1755         numProj 
= self
._projectChoice
.GetCount() 
1759             self
._projectChoice
.SetSelection(i
) 
1760         self
.OnProjectSelect() 
1763     def RemoveCurrentDocumentUpdate(self
, i
=-1): 
1764         """ Called by service after deleting a project, need to remove from project choices """ 
1765         i 
= self
._projectChoice
.GetSelection() 
1766         self
._projectChoice
.Delete(i
) 
1768         numProj 
= self
._projectChoice
.GetCount() 
1772             self
._projectChoice
.SetSelection(i
) 
1773         self
.OnProjectSelect() 
1776     def ProcessEvent(self
, event
): 
1778         if id == ProjectService
.CLOSE_PROJECT_ID
: 
1779             document 
= self
.GetDocument() 
1781                 if self
.GetDocumentManager().CloseDocument(document
, False): 
1782                     self
.RemoveCurrentDocumentUpdate() 
1784         elif id == ProjectService
.ADD_FILES_TO_PROJECT_ID
: 
1785             self
.OnAddFileToProject(event
) 
1787         elif id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
: 
1788             self
.OnAddDirToProject(event
) 
1790         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1791             return False  # Implement this one in the service 
1792         elif id == ProjectService
.ADD_FOLDER_ID
: 
1793             self
.OnAddFolder(event
) 
1795         elif id == ProjectService
.RENAME_ID
: 
1796             self
.OnRename(event
) 
1798         elif id == ProjectService
.DELETE_FILE_ID
: 
1799             self
.OnDeleteFile(event
) 
1801         elif id == ProjectService
.DELETE_PROJECT_ID
: 
1802             self
.OnDeleteProject(event
) 
1804         elif id == wx
.ID_CUT
: 
1807         elif id == wx
.ID_COPY
: 
1810         elif id == wx
.ID_PASTE
: 
1813         elif (id == wx
.ID_CLEAR
 
1814         or id == ProjectService
.REMOVE_FROM_PROJECT
): 
1817         elif id == wx
.ID_SELECTALL
: 
1818             self
.OnSelectAll(event
) 
1820         elif id == ProjectService
.OPEN_SELECTION_ID
: 
1821             self
.OnOpenSelection(event
) 
1823         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1824             self
.OnProperties(event
) 
1826         elif id == ProjectService
.PROJECT_PROPERTIES_ID
: 
1827             self
.OnProjectProperties(event
) 
1833     def ProcessUpdateUIEvent(self
, event
): 
1834         # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here 
1835         if self
._checkEditMenu
: 
1836             doc 
= self
.GetDocument() 
1837             if doc 
and not doc
.GetCommandProcessor().GetEditMenu(): 
1838                 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
1839             self
._checkEditMenu 
= False 
1842         if id == wx
.ID_CLOSE
: 
1843             # Too confusing, so disable closing from "File | Close" menu, must close from "Project | Close Current Project" menu 
1844             if self
.ProjectHasFocus() or self
.FilesHasFocus(): 
1849         elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
 
1850         or id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
 
1851         or id == ProjectService
.CLOSE_PROJECT_ID
 
1852         or id == ProjectService
.DELETE_PROJECT_ID
): 
1853             event
.Enable(self
.GetDocument() != None) 
1855         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1856             event
.Enable(False)  # Implement this one in the service 
1858         elif id == ProjectService
.ADD_FOLDER_ID
: 
1859             event
.Enable((self
.GetDocument() != None) and (self
.GetMode() == ProjectView
.LOGICAL_MODE
)) 
1861         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1863             if self
.ProjectHasFocus(): 
1864                 if self
.GetDocument(): 
1866             elif self
.FilesHasFocus(): 
1867                 items 
= self
._treeCtrl
.GetSelections() 
1870                     if self
._IsItemFile
(item
): 
1873             event
.Enable(status
) 
1875         elif (id == wx
.ID_CUT
 
1877         or id == ProjectService
.DELETE_FILE_ID
 
1878         or id == ProjectService
.REMOVE_FROM_PROJECT
 
1879         or id == ProjectService
.OPEN_SELECTION_ID
): 
1880             event
.Enable(self
._HasFilesSelected
()) 
1882         elif (id == wx
.ID_CLEAR
 
1883         or id == ProjectService
.RENAME_ID
): 
1884             event
.Enable(self
._HasFilesSelected
() or (self
.GetDocument() != None and self
.GetMode() == ProjectView
.LOGICAL_MODE 
and self
._HasFoldersSelected
())) 
1886         elif id == wx
.ID_PASTE
: 
1887             event
.Enable(self
.CanPaste()) 
1889         elif id == wx
.ID_SELECTALL
: 
1890             event
.Enable(self
._HasFiles
()) 
1892         elif (id == wx
.ID_PREVIEW
 
1893         or id == wx
.ID_PRINT
): 
1899     #---------------------------------------------------------------------------- 
1901     #---------------------------------------------------------------------------- 
1904         if not self
.GetFrame(): 
1906         return self
.GetFrame().IsShown() 
1913     def Show(self
, show 
= True): 
1914         self
.GetFrame().Show(show
) 
1915         if wx
.GetApp().IsMDI(): 
1916             mdiParentFrame 
= wx
.GetApp().GetTopWindow() 
1917             mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
) 
1920     #---------------------------------------------------------------------------- 
1921     # Methods for ProjectDocument and ProjectService to call 
1922     #---------------------------------------------------------------------------- 
1924     def SetProject(self
, projectPath
): 
1925         curSel 
= self
._projectChoice
.GetSelection() 
1926         for i 
in range(self
._projectChoice
.GetCount()): 
1927             document 
= self
._projectChoice
.GetClientData(i
) 
1928             if document
.GetFilename() == projectPath
: 
1929                 if curSel 
!= i
:  # don't reload if already loaded 
1930                     self
._projectChoice
.SetSelection(i
) 
1931                     self
.LoadProject(document
) 
1935     def GetSelectedFile(self
): 
1936         for item 
in self
._treeCtrl
.GetSelections(): 
1937             filePath 
= self
._GetItemFilePath
(item
) 
1943     def GetSelectedFiles(self
): 
1945         for item 
in self
._treeCtrl
.GetSelections(): 
1946             filePath 
= self
._GetItemFilePath
(item
) 
1947             if filePath 
and filePath 
not in filePaths
: 
1948                 filePaths
.append(filePath
) 
1952     def GetSelectedPhysicalFolder(self
): 
1953         if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
1956             for item 
in self
._treeCtrl
.GetSelections(): 
1957                 if not self
._IsItemFile
(item
): 
1958                     filePath 
= self
._GetItemFolderPath
(item
) 
1964     def GetSelectedProject(self
): 
1965         document 
= self
.GetDocument() 
1967             return document
.GetFilename() 
1972     def AddProjectToView(self
, document
): 
1973         i 
= self
._projectChoice
.Append(self
._MakeProjectName
(document
), document
) 
1974         self
._projectChoice
.SetSelection(i
) 
1975         self
.OnProjectSelect() 
1978     def LoadProject(self
, document
): 
1979         wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
1980         self
._treeCtrl
.Freeze() 
1982         rootItem 
= self
._treeCtrl
.GetRootItem() 
1983         self
._treeCtrl
.DeleteChildren(rootItem
) 
1986             mode 
= self
.GetMode() 
1987             docFilePath 
= document
.GetFilename() 
1989             if mode 
== ProjectView
.LOGICAL_MODE
: 
1990                 folders 
= document
.GetModel().logicalFolders
 
1992                 folders 
= document
.GetModel().GetRelativeFolders() 
1996             for folderPath 
in folders
: 
1997                 folderItems 
= folderItems 
+ self
._treeCtrl
.AddFolder(folderPath
) 
1999             for file in document
.GetModel()._files
: 
2000                 if mode 
== ProjectView
.LOGICAL_MODE
: 
2001                     folder 
= file.logicalFolder
 
2003                     folder 
= file.GetRelativeFolder(document
.GetModel().homeDir
) 
2005                     folderTree 
= folder
.split('/') 
2008                     for folderName 
in folderTree
: 
2010                         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(item
) 
2012                             if self
._treeCtrl
.GetItemText(child
) == folderName
: 
2016                             (child
, cookie
) = self
._treeCtrl
.GetNextChild(item
, cookie
) 
2019                             print "error folder '%s' not found for %s" % (folder
, file.filePath
) 
2024                 fileItem 
= self
._treeCtrl
.AppendItem(item
, os
.path
.basename(file.filePath
), file) 
2026             self
._treeCtrl
.SortChildren(rootItem
) 
2027             for item 
in folderItems
: 
2028                 self
._treeCtrl
.SortChildren(item
) 
2030             self
.LoadFolderState() 
2032             if self
._embeddedWindow
: 
2033                 document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
2035         self
._treeCtrl
.Thaw() 
2036         wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
2039     def ProjectHasFocus(self
): 
2040         """ Does Project Choice have focus """ 
2041         return (wx
.Window
.FindFocus() == self
._projectChoice
) 
2044     def FilesHasFocus(self
): 
2045         """ Does Project Tree have focus """ 
2046         winWithFocus 
= wx
.Window
.FindFocus() 
2047         if not winWithFocus
: 
2050             if winWithFocus 
== self
._treeCtrl
: 
2052             winWithFocus 
= winWithFocus
.GetParent() 
2056     def SaveFolderState(self
, event
=None): 
2057         """ Save the open/close state of folders """ 
2063         folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2064         for item 
in folderItemList
: 
2065             if self
._treeCtrl
.IsExpanded(item
): 
2066                 folderList
.append(self
._GetItemFolderPath
(item
)) 
2068         config 
= wx
.ConfigBase_Get() 
2069         config
.Write(getProjectKeyName(self
.GetDocument().GetFilename(), self
.GetMode()), repr(folderList
)) 
2072     def LoadFolderState(self
): 
2073         """ Load the open/close state of folders """ 
2074         self
._loading 
= True 
2076         config 
= wx
.ConfigBase_Get() 
2077         openFolderData 
= config
.Read(getProjectKeyName(self
.GetDocument().GetFilename(), self
.GetMode())) 
2079             folderList 
= eval(openFolderData
) 
2081             folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2082             for item 
in folderItemList
: 
2083                 f 
= self
._GetItemFolderPath
(item
) 
2085                     self
._treeCtrl
.Expand(item
) 
2086 ##                else:  # not needed, initial state is collapsed 
2087 ##                    self._treeCtrl.Collapse(item) 
2088         else:  # default is to open all folders     
2089             folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2090             for item 
in folderItemList
: 
2091                 self
._treeCtrl
.Expand(item
) 
2093         self
._loading 
= False 
2096     #---------------------------------------------------------------------------- 
2098     #---------------------------------------------------------------------------- 
2100     def OnProperties(self
, event
): 
2101         if self
.ProjectHasFocus(): 
2102             self
.OnProjectProperties(event
) 
2103         elif self
.FilesHasFocus(): 
2104             items 
= self
._treeCtrl
.GetSelections() 
2108             filePath 
= self
._GetItemFilePath
(item
) 
2110                 filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
2111                 filePropertiesService
.ShowPropertiesDialog(filePath
) 
2114     def OnProjectProperties(self
, event
): 
2115         if self
.GetDocument(): 
2116             dlg 
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
.GetDocument()) 
2117             dlg
.CenterOnParent() 
2120                 if dlg
.ShowModal() == wx
.ID_OK
: 
2121                     if hasattr(dlg
, "_appInfoCtrl") and dlg
._appInfoCtrl
._grid
.IsCellEditControlShown():  # for Linux 
2122                         dlg
._appInfoCtrl
._grid
.DisableCellEditControl()  # If editor is still active, force it to finish the edit before setting the new model. 
2124                     homeDir 
= dlg
._homeDirCtrl
.GetValue() 
2126                         if homeDir 
== ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
: 
2128                         if homeDir 
and not os
.path
.isdir(homeDir
): 
2129                             wx
.MessageBox(_("Home Dir '%s' does not exist.  Please specify a valid directory.") % homeDir
, 
2130                                         _("Project Properties"), 
2131                                         wx
.OK | wx
.ICON_EXCLAMATION
) 
2133                             if self
.GetDocument().GetModel()._homeDir 
!= homeDir
:  # don't set it if it hasn't changed 
2134                                 self
.GetDocument().GetModel().homeDir 
= homeDir
 
2135                                 self
.GetDocument().Modify(True) 
2138                         wx
.MessageBox(_("Blank Home Dir.  Please specify a valid directory."), 
2139                                     _("Project Properties"), 
2140                                     wx
.OK | wx
.ICON_EXCLAMATION
) 
2146     def OnAddFolder(self
, event
): 
2147         if self
.GetDocument(): 
2148             items 
= self
._treeCtrl
.GetSelections() 
2151                 if self
._IsItemFile
(item
): 
2152                     item 
= self
._treeCtrl
.GetItemParent(item
) 
2154                 folderDir 
= self
._GetItemFolderPath
(item
) 
2160             folderPath 
= _("%sUntitled") % folderDir
 
2162             while self
._treeCtrl
.FindFolder(folderPath
): 
2164                 folderPath 
= _("%sUntitled%s") % (folderDir
, i
) 
2165             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFolderCommand(self
, self
.GetDocument(), folderPath
)) 
2167             self
._treeCtrl
.UnselectAll() 
2168             item 
= self
._treeCtrl
.FindFolder(folderPath
) 
2169             self
._treeCtrl
.SelectItem(item
) 
2170             self
._treeCtrl
.EnsureVisible(item
) 
2174     def AddFolder(self
, folderPath
): 
2175         self
._treeCtrl
.AddFolder(folderPath
) 
2179     def DeleteFolder(self
, folderPath
): 
2180         item 
= self
._treeCtrl
.FindFolder(folderPath
) 
2181         self
._treeCtrl
.Delete(item
) 
2185     def OnAddFileToProject(self
, event
): 
2186         if wx
.Platform 
== "__WXMSW__" or wx
.Platform 
== "__WXGTK__" or wx
.Platform 
== "__WXMAC__": 
2188             for temp 
in self
.GetDocumentManager()._templates
: 
2189                 if temp
.IsVisible(): 
2191                         descr 
= descr 
+ _('|') 
2192                     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 
2193             descr 
= _("All (*.*)|*.*|%s") % descr 
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk 
2197         dialog 
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), wildcard
=descr
, style
=wx
.OPEN|wx
.HIDE_READONLY|wx
.MULTIPLE|wx
.CHANGE_DIR
) 
2198         # dialog.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
2199         if dialog
.ShowModal() != wx
.ID_OK
: 
2202         paths 
= dialog
.GetPaths() 
2207             if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2208                 selections 
= self
._treeCtrl
.GetSelections() 
2210                     item 
= selections
[0] 
2211                     if not self
._IsItemFile
(item
): 
2212                         folderPath 
= self
._GetItemFolderPath
(item
) 
2214             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
, folderPath
=folderPath
)) 
2215         self
.Activate()  # after add, should put focus on project editor 
2218     def OnAddDirToProject(self
, event
): 
2219         frame 
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("Add Directory Files to Project"), size
= (320,200)) 
2220         contentSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
2222         flexGridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap
=HALF_SPACE
, hgap
=HALF_SPACE
) 
2223         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER_VERTICAL
, 0) 
2224         lineSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
2225         dirCtrl 
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(250,-1)) 
2226         dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
2227         lineSizer
.Add(dirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND
) 
2228         findDirButton 
= wx
.Button(frame
, -1, _("Browse...")) 
2229         lineSizer
.Add(findDirButton
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, HALF_SPACE
) 
2230         flexGridSizer
.Add(lineSizer
, 1, wx
.EXPAND
) 
2232         def OnBrowseButton(event
): 
2233             dlg 
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
) 
2234             dir = dirCtrl
.GetValue() 
2237             dlg
.CenterOnParent() 
2238             if dlg
.ShowModal() == wx
.ID_OK
: 
2239                 dirCtrl
.SetValue(dlg
.GetPath()) 
2240                 dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
2241                 dirCtrl
.SetInsertionPointEnd() 
2243         wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
) 
2245         visibleTemplates 
= [] 
2246         for template 
in self
.GetDocumentManager()._templates
: 
2247             if template
.IsVisible(): 
2248                 visibleTemplates
.append(template
) 
2252         for template 
in visibleTemplates
: 
2254                 descr 
= descr 
+ _('|') 
2255             descr 
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")") 
2256             choices
.append(descr
) 
2257         choices
.insert(0, _("All (*.*)"))  # first item 
2258         filterChoice 
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
) 
2259         filterChoice
.SetSelection(0) 
2260         filterChoice
.SetToolTipString(_("Select file type filter.")) 
2261         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
) 
2262         flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
) 
2264         contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
) 
2266         subfolderCtrl 
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories")) 
2267         subfolderCtrl
.SetValue(True) 
2268         contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
) 
2270         buttonSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
2271         findBtn 
= wx
.Button(frame
, wx
.ID_OK
, _("Add")) 
2272         findBtn
.SetDefault() 
2273         buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
) 
2274         buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0) 
2275         contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
) 
2277         frame
.SetSizer(contentSizer
) 
2280         frame
.CenterOnParent() 
2281         status 
= frame
.ShowModal() 
2284         while status 
== wx
.ID_OK 
and not passedCheck
: 
2285             if not os
.path
.exists(dirCtrl
.GetValue()): 
2286                 dlg 
= wx
.MessageDialog(frame
, 
2287                                        _("'%s' does not exist.") % dirCtrl
.GetValue(), 
2288                                        _("Find in Directory"), 
2289                                        wx
.OK | wx
.ICON_EXCLAMATION
 
2291                 dlg
.CenterOnParent() 
2295                 status 
= frame
.ShowModal() 
2301         if status 
== wx
.ID_OK
: 
2302             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
2304             doc 
= self
.GetDocument() 
2305             searchSubfolders 
= subfolderCtrl
.IsChecked() 
2306             dirString 
= dirCtrl
.GetValue() 
2308             if os
.path
.isfile(dirString
): 
2309                 # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter. 
2310                 # We'll assume they know what they're doing. 
2315                 index 
= filterChoice
.GetSelection() 
2316                 lastIndex 
= filterChoice
.GetCount()-1 
2317                 if index 
and index 
!= lastIndex
:  # if not All or Any 
2318                     template 
= visibleTemplates
[index
-1] 
2320                 # do search in files on disk 
2321                 for root
, dirs
, files 
in os
.walk(dirString
): 
2322                     if not searchSubfolders 
and root 
!= dirString
: 
2326                         if index 
== 0:  # All 
2327                             for template 
in visibleTemplates
: 
2328                                 if template
.FileMatchesTemplate(name
): 
2329                                     filename 
= os
.path
.join(root
, name
) 
2331                                     # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2332                                     if doc
.IsFileInProject(filename
): 
2335                                     paths
.append(filename
) 
2337                         elif index 
== lastIndex
:  # Any 
2338                             filename 
= os
.path
.join(root
, name
) 
2339                             # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2340                             if not doc
.IsFileInProject(filename
): 
2341                                 paths
.append(filename
) 
2342                         else:  # use selected filter 
2343                             if template
.FileMatchesTemplate(name
): 
2344                                 filename 
= os
.path
.join(root
, name
) 
2345                                 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2346                                 if not doc
.IsFileInProject(filename
): 
2347                                     paths
.append(filename
) 
2350             if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2351                 selections 
= self
._treeCtrl
.GetSelections() 
2353                     item 
= selections
[0] 
2354                     if not self
._IsItemFile
(item
): 
2355                         folderPath 
= self
._GetItemFolderPath
(item
) 
2357             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
2359             doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
, folderPath
=folderPath
)) 
2360             self
.Activate()  # after add, should put focus on project editor 
2363     def DoAddFilesToProject(self
, filePaths
, folderPath
): 
2364         # method used by Drag-n-Drop to add files to current Project 
2365         self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filePaths
, folderPath
)) 
2368     def OnFocus(self
, event
): 
2369         self
.GetDocumentManager().ActivateView(self
) 
2373     def OnKillFocus(self
, event
): 
2374         # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame 
2375         # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame 
2376         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 
2377             topWindow 
= wx
.GetApp().GetTopWindow() 
2378             # wxBug: On Mac, this event can fire during shutdown, even after GetTopWindow() 
2379             # is set to NULL. So make sure we have a TLW before getting the active child. 
2381                 childFrame 
= topWindow
.GetActiveChild() 
2383                     childFrame
.Activate() 
2387     def OnLeftClick(self
, event
): 
2388         """ wxBug: If tree has selection, but focus is in another window, single click in tree should do 
2389             single selection of item at mouse position.  But what it does is just put focus back into the 
2390             window and all items go from inactive selection to active selection.  Another click on the item 
2391             either activates double-click or edit for that item.  This behavior is odd. 
2393             This fix makes gives the tree view the focus and makes the item under the mouse position the 
2394             only active selection, as expected. 
2396         if not self
.ProjectHasFocus() and not self
.FilesHasFocus() and not event
.ShiftDown() and not event
.ControlDown() and not event
.MetaDown(): 
2397             self
._treeCtrl
.UnselectAll() 
2399             item
, flags 
= self
._treeCtrl
.HitTest(event
.GetPosition()) 
2400             self
._treeCtrl
.SelectItem(item
) 
2406     def OnRightClick(self
, event
): 
2408         if not self
.GetSelectedProject(): 
2411         if self
._HasFilesSelected
():  # Files context 
2412             menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection")) 
2413             menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True) 
2414             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
) 
2416             extService 
= wx
.GetApp().GetService(ExtensionService
.ExtensionService
) 
2417             if extService 
and extService
.GetExtensions(): 
2419                 for ext 
in extService
.GetExtensions(): 
2420                     if not ext
.opOnSelectedFile
: 
2423                         menu
.AppendSeparator() 
2425                     menu
.Append(ext
.id, ext
.menuItemName
) 
2426                     wx
.EVT_MENU(self
._GetParentFrame
(), ext
.id, extService
.ProcessEvent
) 
2427                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ext
.id, extService
.ProcessUpdateUIEvent
) 
2430             for item 
in self
._treeCtrl
.GetSelections(): 
2431                 if self
._IsItemProcessModelFile
(item
): 
2432                     itemIDs 
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None] 
2434         else:  # Project context 
2436         menuBar 
= self
._GetParentFrame
().GetMenuBar() 
2437         itemIDs 
= itemIDs 
+ [ProjectService
.ADD_FILES_TO_PROJECT_ID
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, ProjectService
.ADD_FOLDER_ID
, ProjectService
.REMOVE_FROM_PROJECT
, None, ProjectService
.CLOSE_PROJECT_ID
, ProjectService
.DELETE_PROJECT_ID
, None, ProjectService
.PROJECT_PROPERTIES_ID
] 
2438         svnIDs 
= [SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
2440             itemIDs 
= itemIDs 
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
2441         globalIDs 
= [wx
.ID_UNDO
, wx
.ID_REDO
, wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
] 
2442         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
] 
2443         for itemID 
in itemIDs
: 
2445                 menu
.AppendSeparator() 
2447                 if itemID 
== ProjectService
.RUN_SELECTED_PM_ID
: 
2448                     menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process")) 
2449                     wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.OnRunSelectedPM
) 
2450                 elif itemID 
== ProjectService
.REMOVE_FROM_PROJECT
: 
2451                     menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project")) 
2452                     wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
) 
2453                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
) 
2455                     svnService 
= wx
.GetApp().GetService(SVNService
.SVNService
) 
2456                     item 
= menuBar
.FindItemById(itemID
) 
2458                         if itemID 
in svnIDs
: 
2459                             if SVN_INSTALLED 
and svnService
: 
2460                                 wx
.EVT_MENU(self
._GetParentFrame
(), itemID
, svnService
.ProcessEvent
) 
2461                         elif itemID 
in globalIDs
: 
2464                             wx
.EVT_MENU(self
._treeCtrl
, itemID
, self
.ProcessEvent
) 
2465                         menu
.Append(itemID
, item
.GetLabel()) 
2466         self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY())) 
2470     def OnRunSelectedPM(self
, event
): 
2471         projectService 
= wx
.GetApp().GetService(ProjectService
) 
2473             projectService
.OnRunProcessModel(event
, runSelected
=True) 
2476     def OnRename(self
, event
=None): 
2477         items 
= self
._treeCtrl
.GetSelections() 
2479             self
._treeCtrl
.EditLabel(items
[0]) 
2482     def OnBeginLabelEdit(self
, event
): 
2483         self
._editingSoDontKillFocus 
= True 
2484         item 
= event
.GetItem() 
2485         if (self
.GetMode() == ProjectView
.PHYSICAL_MODE
) and not self
._IsItemFile
(item
): 
2489     def OnEndLabelEdit(self
, event
): 
2490         self
._editingSoDontKillFocus 
= False 
2491         item 
= event
.GetItem() 
2492         newName 
= event
.GetLabel() 
2496         if self
._IsItemFile
(item
): 
2497             oldFilePath 
= self
._GetItemFilePath
(item
) 
2498             newFilePath 
= os
.path
.join(os
.path
.dirname(oldFilePath
), newName
) 
2499             doc 
= self
.GetDocument() 
2500             if not doc
.GetCommandProcessor().Submit(ProjectRenameFileCommand(doc
, oldFilePath
, newFilePath
)): 
2503             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
2505             oldFolderPath 
= self
._GetItemFolderPath
(item
) 
2506             newFolderPath 
= os
.path
.dirname(oldFolderPath
) 
2508                 newFolderPath 
+= "/" 
2509             newFolderPath 
+= newName
 
2510             if self
._treeCtrl
.FindFolder(newFolderPath
): 
2511                 wx
.MessageBox(_("Folder '%s' already exists.") % newName
, 
2513                             wx
.OK | wx
.ICON_EXCLAMATION
, 
2517             doc 
= self
.GetDocument() 
2518             if not doc
.GetCommandProcessor().Submit(ProjectRenameFolderCommand(doc
, oldFolderPath
, newFolderPath
)): 
2521             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
2525         # wxBug: Should be able to use IsSupported/IsSupportedFormat here 
2526         #fileDataObject = wx.FileDataObject() 
2527         #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject) 
2528         if not wx
.TheClipboard
.IsOpened(): 
2529             if wx
.TheClipboard
.Open(): 
2530                 fileDataObject 
= wx
.FileDataObject() 
2531                 hasFilesInClipboard 
= wx
.TheClipboard
.GetData(fileDataObject
) 
2532                 wx
.TheClipboard
.Close() 
2534             hasFilesInClipboard 
= False 
2535         return hasFilesInClipboard
 
2538     def OnCut(self
, event
): 
2543     def OnCopy(self
, event
): 
2544         fileDataObject 
= wx
.FileDataObject() 
2545         items 
= self
._treeCtrl
.GetSelections() 
2547             filePath 
= self
._GetItemFilePath
(item
) 
2549                 fileDataObject
.AddFile(filePath
) 
2550         if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open(): 
2551             wx
.TheClipboard
.SetData(fileDataObject
) 
2552             wx
.TheClipboard
.Close() 
2555     def OnPaste(self
, event
): 
2556         if wx
.TheClipboard
.Open(): 
2557             fileDataObject 
= wx
.FileDataObject() 
2558             if wx
.TheClipboard
.GetData(fileDataObject
): 
2560                 if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2561                     items 
= self
._treeCtrl
.GetSelections() 
2565                             folderPath 
= self
._GetItemFolderPath
(item
) 
2566                 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames(), folderPath
)) 
2567             wx
.TheClipboard
.Close() 
2570     def OnClear(self
, event
): 
2571         if self
._HasFilesSelected
(): 
2572             items 
= self
._treeCtrl
.GetSelections() 
2575                 file = self
._GetItemFile
(item
) 
2578             self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self
.GetDocument(), files
)) 
2580         elif self
._HasFoldersSelected
(): 
2581             items 
= self
._treeCtrl
.GetSelections() 
2583             if self
._treeCtrl
.GetChildrenCount(item
, False): 
2584                 wx
.MessageBox(_("Cannot remove folder '%s'.  Folder is not empty.") % self
._treeCtrl
.GetItemText(item
), 
2586                               wx
.OK | wx
.ICON_EXCLAMATION
, 
2590             folderPath 
= self
._GetItemFolderPath
(item
) 
2591             self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFolderCommand(self
, self
.GetDocument(), folderPath
)) 
2594     def OnDeleteFile(self
, event
): 
2595         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
2596                                  _("Delete cannot be reversed.\n\nRemove the selected files from the\nproject and file system permanently?"), 
2598                                  wx
.YES_NO|wx
.ICON_QUESTION
) 
2599         yesNoMsg
.CenterOnParent() 
2600         status 
= yesNoMsg
.ShowModal() 
2602         if status 
== wx
.ID_NO
: 
2605         items 
= self
._treeCtrl
.GetSelections() 
2608             filePath 
= self
._GetItemFilePath
(item
) 
2609             if filePath 
and filePath 
not in delFiles
: 
2610                 delFiles
.append(filePath
) 
2612         # remove selected files from project 
2613         self
.GetDocument().RemoveFiles(delFiles
) 
2615         # remove selected files from file system 
2616         for filePath 
in delFiles
: 
2617             if os
.path
.exists(filePath
): 
2621                     wx
.MessageBox("Could not delete '%s'.  %s" % (os
.path
.basename(filePath
), sys
.exc_value
), 
2623                                   wx
.OK | wx
.ICON_EXCLAMATION
, 
2626     def OnDeleteProject(self
, event
=None, noPrompt
=False, closeFiles
=True, delFiles
=True): 
2628         class DeleteProjectDialog(wx
.Dialog
): 
2630             def __init__(self
, parent
, doc
): 
2631                 wx
.Dialog
.__init
__(self
, parent
, -1, _("Delete Project"), size 
= (310, 330)) 
2633                 sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
2634                 sizer
.Add(wx
.StaticText(self
, -1, _("Delete cannot be reversed.\nDeleted files are removed from the file system permanently.\n\nThe project file '%s' will be closed and deleted.") % os
.path
.basename(doc
.GetFilename())), 0, wx
.ALL
, SPACE
) 
2635                 self
._delFilesCtrl 
= wx
.CheckBox(self
, -1, _("Delete all files in project")) 
2636                 self
._delFilesCtrl
.SetValue(True) 
2637                 self
._delFilesCtrl
.SetToolTipString(_("Deletes files from disk, whether open or closed")) 
2638                 sizer
.Add(self
._delFilesCtrl
, 0, wx
.LEFT|wx
.RIGHT|wx
.BOTTOM
, SPACE
) 
2639                 self
._closeDeletedCtrl 
= wx
.CheckBox(self
, -1, _("Close open files belonging to project")) 
2640                 self
._closeDeletedCtrl
.SetValue(True) 
2641                 self
._closeDeletedCtrl
.SetToolTipString(_("Closes open editors for files belonging to project")) 
2642                 sizer
.Add(self
._closeDeletedCtrl
, 0, wx
.LEFT|wx
.RIGHT|wx
.BOTTOM
, SPACE
) 
2644                 sizer
.Add(self
.CreateButtonSizer(wx
.OK | wx
.CANCEL
), 0, wx
.ALIGN_RIGHT|wx
.RIGHT|wx
.LEFT|wx
.BOTTOM
, SPACE
) 
2646                 self
.SetSizer(sizer
) 
2650         doc 
= self
.GetDocument() 
2652             dlg 
= DeleteProjectDialog(self
.GetFrame(), doc
) 
2653             dlg
.CenterOnParent() 
2654             status 
= dlg
.ShowModal() 
2655             delFiles 
= dlg
._delFilesCtrl
.GetValue() 
2656             closeFiles 
= dlg
._closeDeletedCtrl
.GetValue() 
2658             if status 
== wx
.ID_CANCEL
: 
2661         if closeFiles 
or delFiles
: 
2662             filesInProject 
= doc
.GetFiles() 
2663             filesInProject
.append(self
.GetDocument().GetDeploymentFilepath())  # remove deployment file also. 
2665             # don't remove self prematurely 
2666             filePath 
= doc
.GetFilename() 
2667             if filePath 
in filesInProject
: 
2668                 filesInProject
.remove(filePath
) 
2670             # don't close/delete files outside of project's directory 
2671             homeDir 
= doc
.GetModel().homeDir 
+ os
.sep
 
2672             for filePath 
in filesInProject
[:]: 
2673                 fileDir 
= os
.path
.dirname(filePath
) + os
.sep
 
2674                 if not fileDir
.startswith(homeDir
):   
2675                     filesInProject
.remove(filePath
) 
2678             # close any open views of documents in the project 
2679             openDocs 
= self
.GetDocumentManager().GetDocuments()[:]  # need copy or docs shift when closed 
2681                 if d
.GetFilename() in filesInProject
: 
2682                     d
.Modify(False)  # make sure it doesn't ask to save the file 
2683                     if isinstance(d
.GetDocumentTemplate(), ProjectTemplate
):  # if project, remove from project list drop down 
2684                         if self
.GetDocumentManager().CloseDocument(d
, True): 
2685                             self
.RemoveProjectUpdate(d
) 
2686                     else:  # regular file 
2687                         self
.GetDocumentManager().CloseDocument(d
, True) 
2689         # remove files in project from file system 
2692             for filePath 
in filesInProject
: 
2693                 if os
.path
.isfile(filePath
): 
2695                         dirPath 
= os
.path
.dirname(filePath
) 
2696                         if dirPath 
not in dirPaths
: 
2697                             dirPaths
.append(dirPath
) 
2701                         wx
.MessageBox("Could not delete file '%s'.\n%s" % (filePath
, sys
.exc_value
), 
2702                                       _("Delete Project"), 
2703                                       wx
.OK | wx
.ICON_EXCLAMATION
, 
2706         filePath 
= doc
.GetFilename() 
2710             doc
.Modify(False)  # make sure it doesn't ask to save the project 
2711             if self
.GetDocumentManager().CloseDocument(doc
, True): 
2712                 self
.RemoveCurrentDocumentUpdate() 
2714         # remove project file 
2716             dirPath 
= os
.path
.dirname(filePath
) 
2717             if dirPath 
not in dirPaths
: 
2718                 dirPaths
.append(dirPath
) 
2719         if os
.path
.isfile(filePath
): 
2723                 wx
.MessageBox("Could not delete project file '%s'.\n%s" % (filePath
, sys
.exc_value
), 
2724                               _("Delete Prjoect"), 
2725                               wx
.OK | wx
.ICON_EXCLAMATION
, 
2728         # remove empty directories from file system 
2730             dirPaths
.sort()     # sorting puts parent directories ahead of child directories 
2731             dirPaths
.reverse()  # remove child directories first 
2733             for dirPath 
in dirPaths
: 
2734                 if os
.path
.isdir(dirPath
): 
2735                     files 
= os
.listdir(dirPath
) 
2740                             wx
.MessageBox("Could not delete empty directory '%s'.\n%s" % (dirPath
, sys
.exc_value
), 
2741                                           _("Delete Project"), 
2742                                           wx
.OK | wx
.ICON_EXCLAMATION
, 
2746     def OnKeyPressed(self
, event
): 
2747         key 
= event
.KeyCode() 
2748         if key 
== wx
.WXK_DELETE
: 
2754     def OnSelectAll(self
, event
): 
2755         project 
= self
.GetDocument() 
2757             self
.DoSelectAll(self
._treeCtrl
.GetRootItem()) 
2760     def DoSelectAll(self
, parentItem
): 
2761         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
2763             if self
._IsItemFile
(child
): 
2764                 self
._treeCtrl
.SelectItem(child
) 
2766                 self
.DoSelectAll(child
) 
2767             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
2770     def OnOpenSelectionSDI(self
, event
): 
2771         # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window 
2772         wx
.CallAfter(self
.OnOpenSelection
, None) 
2775     def OnOpenSelection(self
, event
): 
2778             items 
= self
._treeCtrl
.GetSelections()[:] 
2780                 filepath 
= self
._GetItemFilePath
(item
) 
2782                     if not os
.path
.exists(filepath
): 
2783                         msgTitle 
= wx
.GetApp().GetAppName() 
2785                             msgTitle 
= _("File Not Found") 
2786                         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
2787                                       _("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
)), 
2789                                       wx
.YES_NO|wx
.ICON_QUESTION
 
2791                         yesNoMsg
.CenterOnParent() 
2792                         status 
= yesNoMsg
.ShowModal() 
2794                         if status 
== wx
.ID_NO
: 
2796                         findFileDlg 
= wx
.FileDialog(self
.GetFrame(), 
2798                                                  defaultFile
=wx
.lib
.docview
.FileNameFromPath(filepath
), 
2799                                                  style
=wx
.OPEN|wx
.FILE_MUST_EXIST|wx
.CHANGE_DIR
 
2801                         # findFileDlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
2802                         if findFileDlg
.ShowModal() == wx
.ID_OK
: 
2803                             newpath 
= findFileDlg
.GetPath() 
2806                         findFileDlg
.Destroy() 
2808                             # update Project Model with new location 
2809                             self
.GetDocument().UpdateFilePath(filepath
, newpath
) 
2812                     doc 
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
2813                     if not doc 
and filepath
.endswith(PROJECT_EXTENSION
):  # project already open 
2814                         self
.SetProject(filepath
) 
2816                         projectService 
= wx
.GetApp().GetService(ProjectService
) 
2818                             projectService
.AddProjectMapping(doc
) 
2819                             if hasattr(doc
, "GetModel"): 
2820                                 projectService
.AddProjectMapping(doc
.GetModel()) 
2823         except IOError, (code
, message
): 
2824             msgTitle 
= wx
.GetApp().GetAppName() 
2826                 msgTitle 
= _("File Error") 
2827             wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
), 
2829                           wx
.OK | wx
.ICON_EXCLAMATION
, 
2833     #---------------------------------------------------------------------------- 
2834     # Convenience methods 
2835     #---------------------------------------------------------------------------- 
2837     def _HasFiles(self
): 
2838         if not self
._treeCtrl
: 
2840         return self
._treeCtrl
.GetCount() > 1    #  1 item = root item, don't count as having files 
2843     def _HasFilesSelected(self
): 
2844         if not self
._treeCtrl
: 
2846         items 
= self
._treeCtrl
.GetSelections() 
2850             if self
._IsItemFile
(item
): 
2855     def _HasFoldersSelected(self
): 
2856         if not self
._treeCtrl
: 
2858         items 
= self
._treeCtrl
.GetSelections() 
2862             if self
._IsItemFile
(item
): 
2867     def _MakeProjectName(self
, project
): 
2868         return project
.GetPrintableName() 
2871     def _GetItemFilePath(self
, item
): 
2872         file = self
._GetItemFile
(item
) 
2874             return file.filePath
 
2879     def _GetItemFolderPath(self
, item
): 
2880         rootItem 
= self
._treeCtrl
.GetRootItem() 
2881         if item 
== rootItem
: 
2884         if self
._IsItemFile
(item
): 
2885             item 
= self
._treeCtrl
.GetItemParent(item
) 
2888         while item 
!= rootItem
: 
2890                 folderPath 
= self
._treeCtrl
.GetItemText(item
) + "/" + folderPath
 
2892                 folderPath 
= self
._treeCtrl
.GetItemText(item
) 
2893             item 
= self
._treeCtrl
.GetItemParent(item
) 
2898     def _GetItemFile(self
, item
): 
2899         return self
._treeCtrl
.GetPyData(item
) 
2902     def _IsItemFile(self
, item
): 
2903         return self
._GetItemFile
(item
) != None 
2906     def _IsItemProcessModelFile(self
, item
): 
2907         if ACTIVEGRID_BASE_IDE
: 
2910         if self
._IsItemFile
(item
): 
2911             filepath 
= self
._GetItemFilePath
(item
) 
2913             for template 
in self
.GetDocumentManager().GetTemplates(): 
2914                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
2915                     ext 
= template
.GetDefaultExtension() 
2920             if filepath
.endswith(ext
): 
2926     def _GetChildItems(self
, parentItem
): 
2928         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
2930             children
.append(child
) 
2931             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
2935     def _GetFolderItems(self
, parentItem
): 
2937         childrenItems 
= self
._GetChildItems
(parentItem
) 
2938         for childItem 
in childrenItems
: 
2939             if not self
._IsItemFile
(childItem
): 
2940                 folderItems
.append(childItem
) 
2941                 folderItems 
+= self
._GetFolderItems
(childItem
) 
2945 class ProjectFileDropTarget(wx
.FileDropTarget
): 
2947     def __init__(self
, view
): 
2948         wx
.FileDropTarget
.__init
__(self
) 
2952     def OnDropFiles(self
, x
, y
, filePaths
): 
2953         """ Do actual work of dropping files into project """ 
2954         if self
._view
.GetDocument(): 
2956             if self
._view
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2957                 folderItem 
= self
._view
._treeCtrl
.FindClosestFolder(x
,y
) 
2959                     folderPath 
= self
._view
._GetItemFolderPath
(folderItem
) 
2960             self
._view
.DoAddFilesToProject(filePaths
, folderPath
) 
2965     def OnDragOver(self
, x
, y
, default
): 
2966         """ Feedback to show copy cursor if copy is allowed """ 
2967         if self
._view
.GetDocument():  # only allow drop if project exists 
2972 class ProjectPropertiesDialog(wx
.Dialog
): 
2973     RELATIVE_TO_PROJECT_FILE 
= _("relative to project file") 
2975     def __init__(self
, parent
, document
): 
2976         wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size 
= (310, 330)) 
2978         filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
2980         notebook 
= wx
.Notebook(self
, -1) 
2982         tab 
= wx
.Panel(notebook
, -1) 
2983         gridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap 
= SPACE
, hgap 
= SPACE
) 
2984         gridSizer
.AddGrowableCol(1) 
2985         gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:"))) 
2986         filename 
= document
.GetFilename() 
2987         if os
.path
.isfile(filename
): 
2988             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1])) 
2990             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:"))) 
2991             gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.dirname(filename
), length
=50))) 
2993             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:"))) 
2994             gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes"))) 
2996             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
2997             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
2998             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
) 
3000             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
3001             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
3002             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
) 
3004             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:"))) 
3005             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
)))) 
3007             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:"))) 
3008             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
)))) 
3010             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:"))) 
3011             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
)))) 
3013             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]"))) 
3014         spacerGrid 
= wx
.BoxSizer(wx
.HORIZONTAL
)  # add a border around the inside of the tab 
3015         spacerGrid
.Add(gridSizer
, 1, wx
.ALL|wx
.EXPAND
, SPACE
); 
3016         tab
.SetSizer(spacerGrid
) 
3017         notebook
.AddPage(tab
, _("General")) 
3019         tab 
= wx
.Panel(notebook
, -1) 
3020         spacerGrid 
= wx
.BoxSizer(wx
.VERTICAL
)  # add a border around the inside of the tab 
3021         homePathLabel 
= wx
.StaticText(tab
, -1, _("Home Dir:")) 
3022         if document
.GetModel().isDefaultHomeDir
: 
3023             defaultHomeDir 
= ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
 
3025             defaultHomeDir 
= document
.GetModel().homeDir
 
3026         self
._homeDirCtrl 
= wx
.ComboBox(tab
, -1, defaultHomeDir
, size
=(125,-1), choices
=[ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
, document
.GetModel().homeDir
]) 
3027         self
._homeDirCtrl
.SetToolTipString(self
._homeDirCtrl
.GetValue())  
3028         if not document
.GetModel().isDefaultHomeDir
: 
3029             self
._homeDirCtrl
.SetInsertionPointEnd() 
3030         def OnDirChanged(event
): 
3031             self
._homeDirCtrl
.SetToolTip(wx
.ToolTip(self
._homeDirCtrl
.GetValue()))  # wx.Bug: SetToolTipString only sets it for the dropdown control, not for the text edit control, so need to replace it completely 
3032         wx
.EVT_COMBOBOX(self
._homeDirCtrl
, -1, OnDirChanged
) 
3033         wx
.EVT_TEXT(self
._homeDirCtrl
, -1, OnDirChanged
) 
3034         choosePathButton 
= wx
.Button(tab
, -1, _("Browse...")) 
3035         def OnBrowseButton(event
): 
3036             if self
._homeDirCtrl
.GetValue() == ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
: 
3037                 defaultHomeDir 
= document
.GetModel().homeDir
 
3039                 defaultHomeDir 
= self
._homeDirCtrl
.GetValue() 
3041             dlg 
= wx
.DirDialog(self
, "Choose a directory:", defaultHomeDir
, 
3042                               style
=wx
.DD_DEFAULT_STYLE|wx
.DD_NEW_DIR_BUTTON
) 
3043             if dlg
.ShowModal() == wx
.ID_OK
: 
3044                 self
._homeDirCtrl
.SetValue(dlg
.GetPath()) 
3045                 self
._homeDirCtrl
.SetInsertionPointEnd() 
3046                 self
._homeDirCtrl
.SetToolTip(wx
.ToolTip(dlg
.GetPath()))  # wx.Bug: SetToolTipString only sets it for the dropdown control, not for the text edit control, so need to replace it completely 
3048         wx
.EVT_BUTTON(choosePathButton
, -1, OnBrowseButton
) 
3049         pathSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3050         pathSizer
.Add(homePathLabel
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
3051         pathSizer
.Add(self
._homeDirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND|wx
.LEFT
, HALF_SPACE
) 
3052         pathSizer
.Add(choosePathButton
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.LEFT
, SPACE
) 
3053         spacerGrid
.Add(pathSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
); 
3054         instructionText 
= wx
.StaticText(tab
, -1, _("The physical view shows files relative to Home Dir.\nThe Home Dir default is the project file's directory.\nSetting the Home Dir overrides the default directory.")) 
3055         spacerGrid
.Add(instructionText
, 0, wx
.ALL
, SPACE
); 
3056         tab
.SetSizer(spacerGrid
) 
3057         notebook
.AddPage(tab
, _("Physical View")) 
3059         if not ACTIVEGRID_BASE_IDE
: 
3060             tab 
= wx
.Panel(notebook
, -1) 
3061             self
._appInfoCtrl 
= PropertyService
.PropertyCtrl(tab
, header
=False) 
3062             self
._appInfoCtrl
.SetDocument(document
) 
3063             self
._appInfoCtrl
.SetModel(document
.GetAppInfo()) 
3064             sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3065             sizer
.Add(self
._appInfoCtrl
, 1, wx
.EXPAND
) 
3067             notebook
.AddPage(tab
, _("App Info")) 
3069         if wx
.Platform 
== "__WXMSW__": 
3070             notebook
.SetPageSize((310,300)) 
3072         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3073         sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
) 
3074         sizer
.Add(self
.CreateButtonSizer(wx
.OK | wx
.CANCEL
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
) 
3076         self
.SetSizer(sizer
) 
3081 class ProjectOptionsPanel(wx
.Panel
): 
3084     def __init__(self
, parent
, id): 
3085         wx
.Panel
.__init
__(self
, parent
, id) 
3086         self
._useSashMessageShown 
= False 
3087         config 
= wx
.ConfigBase_Get() 
3088         self
._projSaveDocsCheckBox 
= wx
.CheckBox(self
, -1, _("Remember open projects")) 
3089         self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True)) 
3090         projectBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3091         projectSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3092         projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
3093         if not ACTIVEGRID_BASE_IDE
: 
3094             self
._projShowWelcomeCheckBox 
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog")) 
3095             self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog", True)) 
3096             projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
3098             sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3099             sizer
.Add(wx
.StaticText(self
, -1, _("Default language for projects:")), 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT
, HALF_SPACE
) 
3100             self
._langCtrl 
= wx
.Choice(self
, -1, choices
=deploymentlib
.LANGUAGE_LIST
)             
3101             self
._langCtrl
.SetStringSelection(config
.Read(APP_LAST_LANGUAGE
, deploymentlib
.LANGUAGE_DEFAULT
)) 
3102             self
._langCtrl
.SetToolTipString(_("Programming language to be used throughout the project.")) 
3103             sizer
.Add(self
._langCtrl
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT
, MAC_RIGHT_BORDER
) 
3104             projectSizer
.Add(sizer
, 0, wx
.ALL
, HALF_SPACE
) 
3106         projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
) 
3107         self
.SetSizer(projectBorderSizer
) 
3109         parent
.AddPage(self
, _("Project")) 
3112     def OnUseSashSelect(self
, event
): 
3113         if not self
._useSashMessageShown
: 
3114             msgTitle 
= wx
.GetApp().GetAppName() 
3116                 msgTitle 
= _("Document Options") 
3117             wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.", 
3119                           wx
.OK | wx
.ICON_INFORMATION
, 
3121             self
._useSashMessageShown 
= True 
3124     def OnOK(self
, optionsDialog
): 
3125         config 
= wx
.ConfigBase_Get() 
3126         config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue()) 
3127         if not ACTIVEGRID_BASE_IDE
: 
3128             config
.WriteInt("RunWelcomeDialog", self
._projShowWelcomeCheckBox
.GetValue()) 
3129             config
.Write(APP_LAST_LANGUAGE
, self
._langCtrl
.GetStringSelection()) 
3133         return getProjectIcon() 
3136 class ProjectService(Service
.Service
): 
3138     #---------------------------------------------------------------------------- 
3140     #---------------------------------------------------------------------------- 
3141     SHOW_WINDOW 
= wx
.NewId()  # keep this line for each subclass, need unique ID for each Service 
3142     RUN_SELECTED_PM_ID 
= wx
.NewId() 
3143     RUN_CURRENT_PM_ID 
= wx
.NewId() 
3144     RENAME_ID 
= wx
.NewId() 
3145     OPEN_SELECTION_ID 
= wx
.NewId() 
3146     REMOVE_FROM_PROJECT 
= wx
.NewId() 
3147     DELETE_FILE_ID 
= wx
.NewId() 
3148     ADD_FILES_TO_PROJECT_ID 
= wx
.NewId() 
3149     ADD_CURRENT_FILE_TO_PROJECT_ID 
= wx
.NewId() 
3150     ADD_DIR_FILES_TO_PROJECT_ID 
= wx
.NewId() 
3151     CLOSE_PROJECT_ID 
= wx
.NewId() 
3152     PROJECT_PROPERTIES_ID 
= wx
.NewId() 
3153     ADD_FOLDER_ID 
= wx
.NewId() 
3154     DELETE_PROJECT_ID 
= wx
.NewId() 
3157     #---------------------------------------------------------------------------- 
3158     # Overridden methods 
3159     #---------------------------------------------------------------------------- 
3161     def __init__(self
, serviceName
, embeddedWindowLocation 
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
): 
3162         Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
) 
3163         self
._runHandlers 
= [] 
3164         self
._suppressOpenProjectMessages 
= False 
3165         self
._logicalViewDefaults 
= [] 
3166         self
._fileTypeDefaults 
= [] 
3167         self
._nameDefaults 
= [] 
3168         self
._mapToProject 
= dict() 
3171     def _CreateView(self
): 
3172         return ProjectView(self
) 
3175     def ShowWindow(self
, show 
= True): 
3176         """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """ 
3177         Service
.Service
.ShowWindow(self
, show
) 
3180             project 
= self
.GetView().GetDocument() 
3182                 self
.OpenSavedProjects() 
3185     #---------------------------------------------------------------------------- 
3186     # Service specific methods 
3187     #---------------------------------------------------------------------------- 
3189     def GetSuppressOpenProjectMessages(self
): 
3190         return self
._suppressOpenProjectMessages
 
3193     def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
): 
3194         self
._suppressOpenProjectMessages 
= suppressOpenProjectMessages
 
3197     def GetRunHandlers(self
): 
3198         return self
._runHandlers
 
3201     def AddRunHandler(self
, runHandler
): 
3202         self
._runHandlers
.append(runHandler
) 
3205     def RemoveRunHandler(self
, runHandler
): 
3206         self
._runHandlers
.remove(runHandler
) 
3209     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
3210         Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
) 
3212         projectMenu 
= wx
.Menu() 
3214 ##            accelTable = wx.AcceleratorTable([ 
3215 ##                eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID")) 
3217 ##            frame.SetAcceleratorTable(accelTable) 
3218         isProjectDocument 
= document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
 
3219         if wx
.GetApp().IsMDI() or isProjectDocument
: 
3220             if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
): 
3221                 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project")) 
3222                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3223                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3224             if not menuBar
.FindItemById(ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
): 
3225                 projectMenu
.Append(ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project")) 
3226                 wx
.EVT_MENU(frame
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3227                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3228             if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
): 
3229                 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project")) 
3230                 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3231                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3232             if not menuBar
.FindItemById(ProjectService
.ADD_FOLDER_ID
): 
3233                 projectMenu
.Append(ProjectService
.ADD_FOLDER_ID
, _("Add Folder to Project"), _("Adds a new folder")) 
3234                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FOLDER_ID
, frame
.ProcessEvent
) 
3235                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FOLDER_ID
, frame
.ProcessUpdateUIEvent
) 
3236             if not menuBar
.FindItemById(ProjectService
.CLOSE_PROJECT_ID
): 
3237                 projectMenu
.AppendSeparator() 
3238                 projectMenu
.Append(ProjectService
.CLOSE_PROJECT_ID
, _("Close Project"), _("Closes currently open project")) 
3239                 wx
.EVT_MENU(frame
, ProjectService
.CLOSE_PROJECT_ID
, frame
.ProcessEvent
) 
3240                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.CLOSE_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3241             if not menuBar
.FindItemById(ProjectService
.DELETE_PROJECT_ID
): 
3242                 projectMenu
.Append(ProjectService
.DELETE_PROJECT_ID
, _("Delete Project..."), _("Delete currently open project and its files.")) 
3243                 wx
.EVT_MENU(frame
, ProjectService
.DELETE_PROJECT_ID
, frame
.ProcessEvent
) 
3244                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3245             if not menuBar
.FindItemById(ProjectService
.PROJECT_PROPERTIES_ID
): 
3246                 projectMenu
.AppendSeparator() 
3247                 projectMenu
.Append(ProjectService
.PROJECT_PROPERTIES_ID
, _("Project Properties"), _("Project Properties")) 
3248                 wx
.EVT_MENU(frame
, ProjectService
.PROJECT_PROPERTIES_ID
, frame
.ProcessEvent
) 
3249                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.PROJECT_PROPERTIES_ID
, frame
.ProcessUpdateUIEvent
) 
3250         index 
= menuBar
.FindMenu(_("&Format")) 
3252             index 
= menuBar
.FindMenu(_("&View")) 
3253         menuBar
.Insert(index 
+ 1, projectMenu
, _("&Project")) 
3254         editMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit"))) 
3255         if not menuBar
.FindItemById(ProjectService
.RENAME_ID
): 
3256             editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item")) 
3257             wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
) 
3258             wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
) 
3259         if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
): 
3260             editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system.")) 
3261             wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
) 
3262             wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
) 
3267     def OnCloseFrame(self
, event
): 
3268         if not self
.GetView(): 
3271         if wx
.GetApp().IsMDI(): 
3272             # close all non-project documents first 
3273             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3274                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3275                     if not self
.GetDocumentManager().CloseDocument(document
, False): 
3278             # write project config afterwards because user may change filenames on closing of new documents 
3279             self
.GetView().WriteProjectConfig()  # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere 
3281             # close all project documents after closing other documents 
3282             # because user may save a new document with a new name or cancel closing a document 
3283             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3284                 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3285                     if not document
.OnSaveModified(): 
3288         # This is called when any SDI frame is closed, so need to check if message window is closing or some other window 
3289         elif self
.GetView() == event
.GetEventObject().GetView(): 
3294     #---------------------------------------------------------------------------- 
3295     # Document Manager Methods 
3296     #---------------------------------------------------------------------------- 
3298     def FindProjectFromMapping(self
, key
): 
3299         """ Find which project a model or document belongs to """ 
3300         return self
._mapToProject
.get(key
) 
3303     def AddProjectMapping(self
, key
, projectDoc
=None): 
3304         """ Generate a mapping from model or document to project.  If no project given, use current project. 
3305             e.g. Which project does this model or document belong to (when it was opened)? 
3308             projectDoc 
= self
.GetCurrentProject() 
3309         self
._mapToProject
[key
] = projectDoc
 
3312     #---------------------------------------------------------------------------- 
3313     # Default Logical View Folder Methods 
3314     #---------------------------------------------------------------------------- 
3316     def AddLogicalViewFolderDefault(self
, pattern
, folder
): 
3317         self
._logicalViewDefaults
.append((pattern
, folder
)) 
3320     def FindLogicalViewFolderDefault(self
, filename
): 
3321         for (pattern
, folder
) in self
._logicalViewDefaults
: 
3322             if filename
.endswith(pattern
): 
3327     #---------------------------------------------------------------------------- 
3328     # Default File Type Methods 
3329     #---------------------------------------------------------------------------- 
3331     def AddFileTypeDefault(self
, pattern
, type): 
3332         self
._fileTypeDefaults
.append((pattern
, type)) 
3335     def FindFileTypeDefault(self
, filename
): 
3336         for (pattern
, type) in self
._fileTypeDefaults
: 
3337             if filename
.endswith(pattern
): 
3342     #---------------------------------------------------------------------------- 
3343     # Default Name Methods 
3344     #---------------------------------------------------------------------------- 
3346     def AddNameDefault(self
, pattern
, method
): 
3347         self
._nameDefaults
.append((pattern
, method
)) 
3350     def FindNameDefault(self
, filename
): 
3351         for (pattern
, method
) in self
._nameDefaults
: 
3352             if filename
.endswith(pattern
): 
3353                 return method(filename
) 
3357     def GetDefaultNameCallback(self
, filename
): 
3358         """ A method for generating name from filepath for Project Service """ 
3359         return os
.path
.splitext(os
.path
.basename(filename
))[0] 
3362     #---------------------------------------------------------------------------- 
3363     # Event Processing Methods 
3364     #---------------------------------------------------------------------------- 
3366     def ProcessEventBeforeWindows(self
, event
): 
3369         if id == wx
.ID_CLOSE_ALL
: 
3370             self
.OnFileCloseAll(event
) 
3375     def ProcessUpdateUIEventBeforeWindows(self
, event
): 
3378         if id == wx
.ID_CLOSE_ALL
: 
3379             for document 
in self
.GetDocumentManager().GetDocuments(): 
3380                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3387         elif id == wx
.ID_CLOSE
: 
3388             # "File | Close" is too confusing and hard to determine whether user wants to close a viewed file or the current project. 
3389             # Disallow "File | Close" if project is current document or active in project view. 
3390             # User must explicitly close project via "Project | Close Current Project". 
3391             document 
= self
.GetDocumentManager().GetCurrentDocument() 
3392             if document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3395             if self
.GetView().ProcessUpdateUIEvent(event
): 
3401     def ProcessEvent(self
, event
): 
3402         if Service
.Service
.ProcessEvent(self
, event
): 
3406         if id == ProjectService
.RUN_SELECTED_PM_ID
: 
3407             self
.OnRunProcessModel(event
, runSelected
=True) 
3409         elif id == ProjectService
.RUN_CURRENT_PM_ID
: 
3410             self
.OnRunProcessModel(event
, runCurrentFile
=True) 
3412         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
3413             self
.OnAddCurrentFileToProject(event
) 
3415         elif (id == ProjectService
.PROJECT_PROPERTIES_ID
 
3416         or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
 
3417         or id == ProjectService
.ADD_FOLDER_ID
 
3418         or id == ProjectService
.DELETE_PROJECT_ID
 
3419         or id == ProjectService
.CLOSE_PROJECT_ID
): 
3421                 return self
.GetView().ProcessEvent(event
) 
3428     def ProcessUpdateUIEvent(self
, event
): 
3429         if Service
.Service
.ProcessUpdateUIEvent(self
, event
): 
3433         if (id == ProjectService
.RUN_SELECTED_PM_ID
 
3434         or id == ProjectService
.RUN_CURRENT_PM_ID
): 
3437         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
3438             event
.Enable(self
._CanAddCurrentFileToProject
()) 
3440         elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
 
3441         or id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
 
3442         or id == ProjectService
.RENAME_ID
 
3443         or id == ProjectService
.OPEN_SELECTION_ID
 
3444         or id == ProjectService
.DELETE_FILE_ID
): 
3447         elif id == ProjectService
.PROJECT_PROPERTIES_ID
: 
3448             event
.Enable(self
._HasOpenedProjects
()) 
3450         elif (id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
 
3451         or id == ProjectService
.ADD_FOLDER_ID
 
3452         or id == ProjectService
.DELETE_PROJECT_ID
 
3453         or id == ProjectService
.CLOSE_PROJECT_ID
): 
3455                 return self
.GetView().ProcessUpdateUIEvent(event
) 
3462     def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False): 
3463         project 
= self
.GetCurrentProject() 
3466             doc 
= self
.GetDocumentManager().GetCurrentDocument() 
3467             if not doc 
or not hasattr(doc
, "GetFilename"): 
3469             fileToRun 
= doc
.GetFilename() 
3470             projects 
= self
.FindProjectByFile(fileToRun
) 
3473             elif project 
in projects
: 
3474                 # use current project 
3476             elif len(projects
) == 1: 
3477                 # only one project, display it 
3478                 project 
= projects
[0] 
3479                 self
.GetView().SetProject(project
.GetFilename()) 
3480             elif len(projects
) > 1: 
3481                 strings 
= map(lambda file: os
.path
.basename(file.GetFilename()), projects
) 
3482                 res 
= wx
.GetSingleChoiceIndex(_("More than one project uses '%s'.  Select project to run:") % os
.path
.basename(fileToRun
), 
3483                                               _("Select Project"), 
3485                                               self
.GetView()._GetParentFrame
()) 
3488                 project 
= projects
[res
] 
3489                 self
.GetView().SetProject(project
.GetFilename()) 
3493             for template 
in self
.GetDocumentManager().GetTemplates(): 
3494                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3495                     ext 
= template
.GetDefaultExtension() 
3500             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
3504             docs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
3506             filesModified 
= False 
3508                 if doc
.IsModified(): 
3509                     filesModified 
= True 
3512                 frame 
= self
.GetView().GetFrame() 
3513                 yesNoMsg 
= wx
.MessageDialog(frame
, 
3514                               _("Files have been modified.  Process may not reflect your current changes.\n\nWould you like to save all files before running?"), 
3516                               wx
.YES_NO|wx
.ICON_QUESTION
 
3518                 yesNoMsg
.CenterOnParent() 
3519                 status 
= yesNoMsg
.ShowModal() 
3521                 if status 
== wx
.ID_YES
: 
3522                     wx
.GetTopLevelParent(frame
).OnFileSaveAll(None) 
3525                 fileToRun 
= self
.GetDocumentManager().GetCurrentDocument().GetFilename() 
3527                 fileToRun 
= self
.GetView().GetSelectedFile() 
3528             elif len(files
) > 1: 
3529                 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower())) 
3530                 strings 
= map(lambda file: os
.path
.basename(file), files
) 
3531                 res 
= wx
.GetSingleChoiceIndex(_("Select a process to run:"), 
3534                                               self
.GetView()._GetParentFrame
()) 
3537                 fileToRun 
= files
[res
] 
3539                 fileToRun 
= files
[0] 
3541             deployFilePath 
= project
.GenerateDeployment() 
3542             self
.RunProcessModel(fileToRun
, project
.GetAppInfo().language
, deployFilePath
) 
3545     def RunProcessModel(self
, fileToRun
, language
, deployFilePath
): 
3546         for runHandler 
in self
.GetRunHandlers(): 
3547             if runHandler
.RunProjectFile(fileToRun
, language
, deployFilePath
): 
3549         os
.system('"' + fileToRun 
+ '"') 
3552     def _HasProcessModel(self
): 
3553         project 
= self
.GetView().GetDocument() 
3557             for template 
in self
.GetDocumentManager().GetTemplates(): 
3558                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3559                     ext 
= template
.GetDefaultExtension() 
3564             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
3574     def _HasOpenedProjects(self
): 
3575         for document 
in self
.GetDocumentManager().GetDocuments(): 
3576             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3581     def _CanAddCurrentFileToProject(self
): 
3582         currentDoc 
= self
.GetDocumentManager().GetCurrentDocument() 
3585         if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3587         if not currentDoc
._savedYet
: 
3589         if self
.GetView().GetDocument():  # a project is open 
3591         return False  # There are no documents open 
3594     def GetFilesFromCurrentProject(self
): 
3595         view 
= self
.GetView() 
3597             project 
= view
.GetDocument() 
3599                 return project
.GetFiles() 
3603     def GetCurrentProject(self
): 
3604         view 
= self
.GetView() 
3606             return view
.GetDocument() 
3610     def GetOpenProjects(self
): 
3612         for document 
in self
.GetDocumentManager().GetDocuments(): 
3613             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3614                 retval
.append(document
) 
3618     def FindProjectByFile(self
, filename
): 
3620         for document 
in self
.GetDocumentManager().GetDocuments(): 
3621             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3622                 if document
.GetFilename() == filename
: 
3623                     retval
.append(document
) 
3624                 elif document
.IsFileInProject(filename
): 
3625                     retval
.append(document
) 
3629     def OnAddCurrentFileToProject(self
, event
): 
3630         file = self
.GetDocumentManager().GetCurrentDocument().GetFilename() 
3631         document 
= self
.GetView().GetDocument() 
3632         document
.GetCommandProcessor().Submit(ProjectAddFilesCommand(document
, [file])) 
3633         self
.GetView().Activate()  # after add, should put focus on project editor 
3636     def OnFileCloseAll(self
, event
): 
3637         for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3638             if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3639                 if not self
.GetDocumentManager().CloseDocument(document
, False): 
3641                 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed 
3644     def OpenSavedProjects(self
): 
3645         config 
= wx
.ConfigBase_Get() 
3647         if config
.ReadInt("ProjectSaveDocs", True): 
3648             docString 
= config
.Read("ProjectSavedDocs") 
3651                 docList 
= eval(docString
) 
3652                 for fileName 
in docList
: 
3653                     if isinstance(fileName
, types
.StringTypes
): 
3654                         if os
.path
.exists(fileName
): 
3655                             doc 
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
3660                 currProject 
= config
.Read("ProjectCurrent") 
3661                 if currProject 
in docList
: 
3662                     self
.GetView().SetProject(currProject
) 
3667 #---------------------------------------------------------------------------- 
3668 # Icon Bitmaps - generated by encode_bitmaps.py 
3669 #---------------------------------------------------------------------------- 
3670 from wx 
import ImageFromStream
, BitmapFromImage
 
3674 def getProjectData(): 
3676 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3677 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3678 \x00\x01\x89IDAT8\x8d\xa5\x92\xcdJ\x02Q\x18\x86\x9fq&-+H\xd40\x033Bha\x05\ 
3679 \xfd\xac*[\xb7l\xd1\xae\xfbhQ7\x10\x04A]\x86\xd0&\xba\x01CW\n!B\xa2\x882\x8b\ 
3680 )R+"\x7fft\x9a\x16\x91\xcd4\xd3\x0f\xf4\xee\xce\xf9\xde\xf7\xe1\xfd\x0eG\x10\ 
3681 \\"\x9arb\xe8\xcf\x1a\x9d\x9e\n\x80\xd6\xad\x03\x10Z;\x13\xf8ER\xa7xd\x88\ 
3682 \xbe-D\x1f\xb8\xbf\x0c\xaf\xcf\x15C\xd2k\xf4\xc5(\x92^\x03 \xbe\x9b\xb3@\x85\ 
3683 n\xe9\xd8h\xde\xe6\x1d\xe9\xfe\xa9E\xc7\xfb\x91\xf9\xfd\x01D\xfa\xc9\xd8\xf7\ 
3684 \xcdPI\'\x01X\xd8>@p\xf7\x00($W\x8c\x8f&R\xa7\xa7\xa2u\xebL.\xef\xd9\x00\x97\ 
3685 \xa7\x87D\\er\x15\x95\xb9\xf5\x12\xa3\x81Y\x9bG\xfax0\xb3Z\x8d*\x95t\x92z\ 
3686 \xb5\x80yjhC\x83\x16\x96\x15\xdc\xc3AZ\x8d\xea{XN#g.,\xa6\xe0l\x9c\xde}\x89\ 
3687 \xb6\xc3\x9aR\xff\xe5\x01\x801}\x1c\x80\x9b\xcc\x05\xde\xb0\x9f\xd0t\x04oX\ 
3688 \xa6\xad4\xc9U\n\xc0&\x1e\xfd\xd6\x0e\x18\xd4Se\x00\xbca?m\xa5\xc9\x1d\xd0V\ 
3689 \x9a\x03\xa3\xd6\xadc\xa8\x8fv\xc0S\xa3H\xc8\x13\x01\xa2\x00\xc4V\x13\x94\ 
3690 \xb3)\xae\xae\x14\x8b\xd1\x17\x90laK\x03\xb3b\xab\t&\x02\xf7(\xf94\xf2k\x8c\ 
3691 \x8d\x8dy\xc7\xf0\xb7\x00\x80`t\x92`t\x87%\xa0\x9cM\xd1\xa8}\xce\xcc\xbf\xd1\ 
3692 \x11P\xce\xa6,\xe7\xaf\xdf\xd7,Ap\x89\x14\x92+\xc6_\x03\x8e\x80\xff\xc8\xf5\ 
3693 \xaf4\xf0\x06=\xf3\x8fJr]C\xd9\x00\x00\x00\x00IEND\xaeB`\x82' 
3695 def getProjectBitmap(): 
3696     return BitmapFromImage(getProjectImage()) 
3698 def getProjectImage(): 
3699     stream 
= cStringIO
.StringIO(getProjectData()) 
3700     return ImageFromStream(stream
) 
3702 def getProjectIcon(): 
3703     return wx
.IconFromBitmap(getProjectBitmap()) 
3706 #---------------------------------------------------------------------------- 
3710 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3711 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3712 \x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\ 
3713 \x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\ 
3714 \x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\ 
3715 \xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\ 
3716 \x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\ 
3717 \x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\ 
3718 \xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\ 
3719 \xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\ 
3720 \x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\ 
3721 \xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\ 
3722 \xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\ 
3726 def getBlankBitmap(): 
3727     return BitmapFromImage(getBlankImage()) 
3729 def getBlankImage(): 
3730     stream 
= cStringIO
.StringIO(getBlankData()) 
3731     return ImageFromStream(stream
) 
3734     return wx
.IconFromBitmap(getBlankBitmap()) 
3737 #---------------------------------------------------------------------- 
3738 def getFolderClosedData(): 
3740 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3741 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3742 \x00\x00\xffIDAT8\x8d\xa5\x93?N\x02A\x14\x87\xbf\x19&\x10B\xb4A\x0b*iL0!$\ 
3743 \x06\x0f\xe0\x05lH\x88G\xe1\x0c\xdbx\x11ZN`,\xa5\x01\x8aM\xa4\x80\x84\xc4Fc\ 
3744 \xd0\xe8\xb0\xae\xbbc\x01\x0b,\x19\x16X~\xd5\x9b\xf7\xe7\x9by3o\x84\x90\x19\ 
3745 \x8e\x91\x8a\x0c\xed:\x06\xc0\xf7g\x00x\xde\x14\x80\xf3\x9b\x07\xb1\x13\xa0]\ 
3746 \xc7d\xcbw\x00d\x17\x81\x82\xff\x01\xc0\xb0\xd3\x9f\x83\x7f\xf5\xb2\xe8\xaa\ 
3747 \xf1\xb4\x84\n!3h\xd71\xef\xaf=\xeb\x0e\xc5R\xcd\xea\xcfWZ"\xd6\xc2\xb6\xc4\ 
3748 \xdc\xe5\xad\xd5?h\xd7M\xb5\xd9\x15\n\xe6}{\xde\x94\xe2\xf5\xbd59I\x12V\x17\ 
3749 \x96F\n \xfc\xfbD\xaaS\xc2\x9fI:@\x041\xdf\xa3\x8d\xb0Y\xb3\xed\xaf\xa9\x00\ 
3750 \xbe\xde\xc6\x9c\x9c]\x10\xea\xc3O #\xc3\xd7:)/\x19\xb0>$\x87J\x01\x04\xc1n\ 
3751 \xc0\xcb\xf3cl]mv\xe3\x83\xb4o\xc1\xa6D\xf4\x1b\x07\xed\xba\xd9\xa7`+ \xad\ 
3752 \xfe\x01\xd1\x03SV!\xfbHa\x00\x00\x00\x00IEND\xaeB`\x82'  
3754 def getFolderClosedBitmap(): 
3755     return BitmapFromImage(getFolderClosedImage()) 
3757 def getFolderClosedImage(): 
3758     stream 
= cStringIO
.StringIO(getFolderClosedData()) 
3759     return ImageFromStream(stream
) 
3761 def getFolderClosedIcon(): 
3762     return wx
.IconFromBitmap(getFolderClosedBitmap()) 
3765 #---------------------------------------------------------------------- 
3766 def getFolderOpenData(): 
3768 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3769 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3770 \x00\x01>IDAT8\x8d\xa5\x93\xbdJ\x03A\x14\x85\xbfY\x03i\xac\x14\x92\xc2F\xad$\ 
3771 Z\xa4\x10\x11|\x01\xc1J\xdbt\xbe\x86\x9d\x85\x0f\xa0\xe0\x1b\x04,l\xc4J\x0b\ 
3772 \x0bA;a\x11\x13\xb1H\xc2\xc2\xca\x84@\x88n\xb2\xd9?\xcd\xd8d6.\x9b\x104\xa7\ 
3773 \xbas\xef=g\xce\x9d\xe1\na\xcc1\x0b\x8c\x99\xd8@F\x07_\xd6\xb9\n\xdd\x8f\xb8\ 
3774 \xd0s\x9a\x00\xe4\xb6O\xc5T\x81~\xf5D\x89\xdc\x0e\xd9_\x85,\xa0\xa2\x06\xefw\ 
3775 R\x01\x04\x9e\x03\xc0\xea\xde\x8dH\th\xa8\xa81:\xf8\x1e\x00\xf9\x8d\x03\x00\ 
3776 \xa4U\x07\xc0,\xdb\xaaX\xaa\xc4"\x99\x04\xd9\xf7\xe0\xfbs$\x12\x0e\x90\xad\ 
3777 \x0e\x00]\xeb*N\x9b\xe5u\x05P,UD\xc2\x81&K\xbb\r@\xd4\xba\x1f\x9a\xe9\xb0\ 
3778 \xb6\x7f\x96h}\xbe8\x1c9\xe89M\x16\xfc\x15\xa4\xdd\xc6\xe8\x9a\x18\xc3\x99\ 
3779 \x97w\x8f\x99\x86\xd8\x81\xb4\xea\x18]\x93\xfcf).\x0e\\9\x96\xf4r}\x84~\x87\ 
3780 \xc4\x08\x81\xe7\xa0\xfa\xb5\xa9\xb7\xa6\x1c\xf4\xdao\xcc/B\x04\x0c<\xfb\xef\ 
3781 \x02Zd\xa9P\x98\xd8\xf8\xfax\x1b\xc7\xa9o\xf4\xbdN\x8aP{z \x0c\xdc\xb1\xa4\ 
3782 \xdf\x10z\x99\xaa\x97[J\'\xc3\xc0\x9dH\x98(\xf0_\xcc\xbc\x8d?\xf2)\x7f\x8e|f\ 
3783 \xe54\x00\x00\x00\x00IEND\xaeB`\x82'  
3785 def getFolderOpenBitmap(): 
3786     return BitmapFromImage(getFolderOpenImage()) 
3788 def getFolderOpenImage(): 
3789     stream 
= cStringIO
.StringIO(getFolderOpenData()) 
3790     return ImageFromStream(stream
) 
3792 def getFolderOpenIcon(): 
3793     return wx
.IconFromBitmap(getFolderOpenBitmap()) 
3796 #---------------------------------------------------------------------- 
3797 def getLogicalModeOnData(): 
3799 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3800 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3801 \x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ 
3802 \xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ 
3803 \x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ 
3804 \xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ 
3805 \xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ 
3806 \xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ 
3807 \xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ 
3808 \xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ 
3809 \xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ 
3810 \x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ 
3811 \x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ 
3812 \xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ 
3813 h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ 
3814 \xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ 
3815 \x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ 
3816 \x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82'  
3818 def getLogicalModeOnBitmap(): 
3819     return BitmapFromImage(getLogicalModeOnImage()) 
3821 def getLogicalModeOnImage(): 
3822     stream 
= cStringIO
.StringIO(getLogicalModeOnData()) 
3823     return ImageFromStream(stream
) 
3825 #---------------------------------------------------------------------- 
3826 def getLogicalModeOffData(): 
3828 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3829 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3830 \x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ 
3831 \xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ 
3832 \x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ 
3833 \xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ 
3834 \xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ 
3835 \xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ 
3836 \xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ 
3837 \xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ 
3838 \xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ 
3839 \x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ 
3840 \x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ 
3841 \xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ 
3842 h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ 
3843 \xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ 
3844 \x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ 
3845 \x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82'  
3847 def getLogicalModeOffBitmap(): 
3848     return BitmapFromImage(getLogicalModeOffImage()) 
3850 def getLogicalModeOffImage(): 
3851     stream 
= cStringIO
.StringIO(getLogicalModeOffData()) 
3852     return ImageFromStream(stream
) 
3854 #---------------------------------------------------------------------- 
3855 def getPhysicalModeOnData(): 
3857 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3858 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3859 \x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ 
3860 \x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ 
3861 \xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ 
3862 \x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ 
3863 [{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ 
3864 \x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ 
3865 vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ 
3866 \xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ 
3867 I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ 
3868 \xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ 
3869 \xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ 
3870 \xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ 
3871 \'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ 
3872 \xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ 
3873 \xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ 
3874 \xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ 
3875 \xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ 
3876 \x00\x00\x00IEND\xaeB`\x82'  
3878 def getPhysicalModeOnBitmap(): 
3879     return BitmapFromImage(getPhysicalModeOnImage()) 
3881 def getPhysicalModeOnImage(): 
3882     stream 
= cStringIO
.StringIO(getPhysicalModeOnData()) 
3883     return ImageFromStream(stream
) 
3885 #---------------------------------------------------------------------- 
3886 def getPhysicalModeOffData(): 
3888 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3889 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3890 \x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ 
3891 \x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ 
3892 \xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ 
3893 \x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ 
3894 [{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ 
3895 \x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ 
3896 vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ 
3897 \xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ 
3898 I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ 
3899 \xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ 
3900 \xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ 
3901 \xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ 
3902 \'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ 
3903 \xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ 
3904 \xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ 
3905 \xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ 
3906 \xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ 
3907 \x00\x00\x00IEND\xaeB`\x82'  
3909 def getPhysicalModeOffBitmap(): 
3910     return BitmapFromImage(getPhysicalModeOffImage()) 
3912 def getPhysicalModeOffImage(): 
3913     stream 
= cStringIO
.StringIO(getPhysicalModeOffData()) 
3914     return ImageFromStream(stream
)