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-2006 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  15 import wx
.lib
.pydocview
 
  25 import activegrid
.util
.appdirs 
as appdirs
 
  26 import activegrid
.util
.fileutils 
as fileutils
 
  27 import activegrid
.util
.aglogging 
as aglogging
 
  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
 
  39     import DeploymentGeneration
 
  42     APP_LAST_LANGUAGE 
= "LastLanguage" 
  43     import activegrid
.model
.basedocmgr 
as basedocmgr
 
  44     import activegrid
.model
.basemodel 
as basemodel
 
  45     import activegrid
.model
.projectmodel 
as projectmodel
 
  46     import PropertyService
 
  47     from activegrid
.server
.toolsupport 
import GetTemplate
 
  48     import activegrid
.util
.xmlutils 
as xmlutils
 
  49     import activegrid
.util
.sysutils 
as sysutils
 
  50     DataServiceExistenceException 
= DeploymentGeneration
.DataServiceExistenceException
 
  51     import WebBrowserService
 
  53 from SVNService 
import SVN_INSTALLED
 
  57 if wx
.Platform 
== '__WXMSW__': 
  62 #---------------------------------------------------------------------------- 
  64 #---------------------------------------------------------------------------- 
  67 PROJECT_EXTENSION 
= ".agp" 
  69 if not ACTIVEGRID_BASE_IDE
: 
  70     PRE_17_TMP_DPL_NAME 
= "RunTime_tmp" + deploymentlib
.DEPLOYMENT_EXTENSION
 
  71     _17_TMP_DPL_NAME 
= ".tmp" + deploymentlib
.DEPLOYMENT_EXTENSION
 
  73 # wxBug: the wxTextCtrl and wxChoice controls on Mac do not correctly size 
  74 # themselves with sizers, so we need to add a right border to the sizer to 
  75 # get the control to shrink itself to fit in the sizer. 
  77 if wx
.Platform 
== "__WXMAC__": 
  81 PROJECT_KEY 
= "/AG_Projects" 
  82 PROJECT_DIRECTORY_KEY 
= "NewProjectDirectory" 
  84 NEW_PROJECT_DIRECTORY_DEFAULT 
= appdirs
.getSystemDir() 
  86 #---------------------------------------------------------------------------- 
  88 #---------------------------------------------------------------------------- 
  90 def AddProjectMapping(doc
, projectDoc
=None, hint
=None): 
  91     projectService 
= wx
.GetApp().GetService(ProjectService
) 
  95                 hint 
= doc
.GetFilename() 
  96             projectDocs 
= projectService
.FindProjectByFile(hint
) 
  98                 projectDoc 
= projectDocs
[0] 
 100         projectService
.AddProjectMapping(doc
, projectDoc
) 
 101         if hasattr(doc
, "GetModel"): 
 102             projectService
.AddProjectMapping(doc
.GetModel(), projectDoc
) 
 105 def getProjectKeyName(projectName
, mode
=None): 
 107         return "%s/%s/%s" % (PROJECT_KEY
, projectName
.replace(os
.sep
, '|'), mode
) 
 109         return "%s/%s" % (PROJECT_KEY
, projectName
.replace(os
.sep
, '|')) 
 112 def GetDocCallback(filepath
): 
 113     """ Get the Document used by the IDE and the in-memory document model used by runtime engine """ 
 114     docMgr 
= wx
.GetApp().GetDocumentManager() 
 117         doc 
= docMgr
.CreateDocument(filepath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
 119             AddProjectMapping(doc
) 
 121             for d 
in docMgr
.GetDocuments(): 
 122                 if os
.path
.normcase(d
.GetFilename()) == os
.path
.normcase(filepath
): 
 127         aglogging
.reportException(e
, stacktrace
=True) 
 129     if doc 
and doc
.GetDocumentTemplate().GetDocumentType() == WsdlAgEditor
.WsdlAgDocument
: 
 130         # get referenced wsdl doc instead 
 131         if doc
.GetModel().filePath
: 
 132             if os
.path
.isabs(doc
.GetModel().filePath
):  # if absolute path, leave it alone 
 133                 filepath 
= doc
.GetModel().filePath
 
 135                 filepath 
= doc
.GetAppDocMgr().fullPath(doc
.GetModel().filePath
)  # check relative to project homeDir 
 137                 if not os
.path
.isfile(filepath
): 
 138                     filepath 
= os
.path
.normpath(os
.path
.join(os
.path
.dirname(doc
.GetFilename()), doc
.GetModel().filePath
))  # check relative to wsdlag file 
 140                     if not os
.path
.isfile(filepath
): 
 141                         filename 
= os
.sep 
+ os
.path
.basename(doc
.GetModel().filePath
)  # check to see if in project file 
 142                         filePaths 
= findDocumentMgr(doc
).filePaths
 
 144                             if fp
.endswith(filename
): 
 149                 doc 
= docMgr
.CreateDocument(filepath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
 152                 aglogging
.reportException(e
, stacktrace
=True) 
 155                 AddProjectMapping(doc
) 
 157                 for d 
in docMgr
.GetDocuments(): 
 158                     if os
.path
.normcase(d
.GetFilename()) == os
.path
.normcase(filepath
): 
 165         docModel 
= doc
.GetModel() 
 172 def findDocumentMgr(root
): 
 173     projectService 
= wx
.GetApp().GetService(ProjectService
) 
 175         projectDoc 
= projectService
.FindProjectFromMapping(root
) 
 177             return projectDoc
.GetModel() 
 179         projectDoc 
= projectService
.GetCurrentProject() 
 183         if isinstance(root
, wx
.lib
.docview
.Document
): 
 184             filepath 
= root
.GetFilename() 
 185         elif hasattr(root
, "fileName") and root
.fileName
: 
 186             filepath 
= root
.fileName
 
 191             if projectDoc
.IsFileInProject(filepath
): 
 192                 return projectDoc
.GetModel() 
 195             openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
 196             for openDoc 
in openDocs
: 
 197                 if openDoc 
== projectDoc
: 
 199                 if(isinstance(openDoc
, ProjectDocument
)): 
 200                     if openDoc
.IsFileInProject(filepath
): 
 201                         projects
.append(openDoc
) 
 204                 if len(projects
) == 1: 
 205                     return projects
[0].GetModel() 
 207                     choices 
= [os
.path
.basename(project
.GetFilename()) for project 
in projects
] 
 208                     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
) 
 211                     if dlg
.ShowModal() == wx
.ID_OK
: 
 212                         i 
= dlg
.GetSelection() 
 213                         projectDoc 
= projects
[i
] 
 215                     return projectDoc
.GetModel() 
 216         return projectDoc
.GetModel() 
 221 if not ACTIVEGRID_BASE_IDE
: 
 222     basemodel
.findGlobalDocumentMgr 
= findDocumentMgr
 
 225 #---------------------------------------------------------------------------- 
 227 #---------------------------------------------------------------------------- 
 229 if not ACTIVEGRID_BASE_IDE
: 
 230     class IDEResourceFactory(DeploymentGeneration
.DeploymentResourceFactory
): 
 232         def __init__(self
, openDocs
, dataSourceService
, projectDir
, 
 233                      preview
=False, deployFilepath
=None): 
 235             self
.openDocs 
= openDocs
 
 236             self
.dataSourceService 
= dataSourceService
 
 237             self
.projectDir 
= projectDir
 
 238             self
.preview 
= preview
 
 239             self
.deployFilepath 
= deployFilepath
 
 241             self
.defaultFlagsNoView 
= ( 
 242                 wx
.GetApp().GetDocumentManager().GetFlags()|
 
 243                 wx
.lib
.docview
.DOC_SILENT|
 
 244                 wx
.lib
.docview
.DOC_OPEN_ONCE|
 
 245                 wx
.lib
.docview
.DOC_NO_VIEW
) 
 247         def getModel(self
, projectFile
): 
 248             doc 
= wx
.GetApp().GetDocumentManager().CreateDocument( 
 249                 projectFile
.filePath
, flags
=self
.defaultFlagsNoView
) 
 250             if (doc 
== None):  # already open 
 251                 doc 
= self
._findOpenDoc
(projectFile
.filePath
) 
 253                 AddProjectMapping(doc
) 
 255                 return doc
.GetModel() 
 257         def getDataSource(self
, dataSourceName
): 
 258             # in preview mode, runtime needs the generated Deployment 
 259             # to contain the requried data source. But runtime doesn't 
 260             # actually need to communicate to db. So here is the logic to 
 261             # make preview works if the required data soruce has not 
 263             dataSource 
= self
.dataSourceService
.getDataSource(dataSourceName
) 
 264             if (dataSource 
!= None): 
 266             elif not self
.preview
: 
 267                 raise DataServiceExistenceException(dataSourceName
) 
 269                 # first to see if an existing dpl file is there, if so, 
 270                 # use the data source in dpl file 
 271                 if (self
.deployFilepath 
!= None): 
 274                         tempDply 
= xmlutils
.load(deployFilepath
) 
 277                     if (tempDply 
!= None): 
 278                         for tempDataSource 
in tempDply
.dataSources
: 
 279                             if (tempDataSource
.name 
== dataSourceName
): 
 280                                 return tempDataSource
 
 282                 # if unable to use dpl file, then create a dummy data source 
 283                 import activegrid
.data
.dataservice 
as dataservice
 
 284                 return dataservice
.DataSource( 
 285                     name
=dataSourceName
, dbtype
=dataservice
.DB_TYPE_SQLITE
) 
 287         def initDocumentRef(self
, projectFile
, documentRef
, dpl
): 
 288             doc 
= self
._findOpenDoc
(projectFile
.filePath
) 
 289             if (doc 
and hasattr(doc
, 'GetModel')): 
 290                 documentRef
.document 
= doc
.GetModel() 
 291                 if isinstance(documentRef
, deploymentlib
.XFormRef
): 
 292                     doc
.GetModel().linkDeployment(dpl
, dpl
.loader
) 
 294         def _findOpenDoc(self
, filePath
): 
 295             for openDoc 
in self
.openDocs
: 
 296                 if openDoc
.GetFilename() == filePath
: 
 300         def getProjectDir(self
): 
 301             return self
.projectDir
 
 304 class ProjectDocument(wx
.lib
.docview
.Document
): 
 306     def __init__(self
, model
=None): 
 307         wx
.lib
.docview
.Document
.__init
__(self
) 
 311             self
.SetModel(projectlib
.Project())  # initial model used by "File | New... | Project" 
 312         self
.GetModel().SetDocCallback(GetDocCallback
) 
 314         self
._stageProjectFile 
= False  
 318         model 
= copy
.copy(self
.GetModel())         
 319         clone 
=  ProjectDocument(model
) 
 320         clone
.SetFilename(self
.GetFilename()) 
 324     def GetFirstView(self
): 
 325         """ 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. 
 326             And to the user, it appears as if nothing has happened.  The user expects to see the open project. 
 327             This forces the project view to show the correct project. 
 329         view 
= wx
.lib
.docview
.Document
.GetFirstView(self
) 
 330         view
.SetProject(self
.GetFilename())  # ensure project is displayed in view 
 335         return self
._projectModel
 
 338     def SetModel(self
, model
): 
 339         self
._projectModel 
= model
 
 342     def OnCreate(self
, path
, flags
): 
 343         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 344         view 
= projectService
.GetView() 
 345         if view
:  # view already exists, reuse 
 346             # All project documents share the same view. 
 349             if view
.GetDocument(): 
 350                 # All project documents need to share the same command processor, 
 351                 # to enable redo/undo of cross project document commands 
 352                 cmdProcessor 
= view
.GetDocument().GetCommandProcessor() 
 354                     self
.SetCommandProcessor(cmdProcessor
) 
 355         else:  # generate view 
 356             view 
= self
.GetDocumentTemplate().CreateView(self
, flags
) 
 357             projectService
.SetView(view
) 
 362     def LoadObject(self
, fileObject
): 
 363         self
.SetModel(projectlib
.load(fileObject
)) 
 364         self
.GetModel().SetDocCallback(GetDocCallback
) 
 368     def SaveObject(self
, fileObject
): 
 369         projectlib
.save(fileObject
, self
.GetModel()) 
 373     def OnOpenDocument(self
, filePath
): 
 374         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 375         view 
= projectService
.GetView() 
 377         if not os
.path
.exists(filePath
): 
 378             wx
.GetApp().CloseSplash() 
 379             msgTitle 
= wx
.GetApp().GetAppName() 
 381                 msgTitle 
= _("File Error") 
 382             wx
.MessageBox(_("Could not find '%s'.") % filePath
, 
 384                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 385                           wx
.GetApp().GetTopWindow()) 
 386             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 388         fileObject 
= file(filePath
, 'r') 
 390             self
.LoadObject(fileObject
) 
 392             wx
.GetApp().CloseSplash() 
 393             msgTitle 
= wx
.GetApp().GetAppName() 
 395                 msgTitle 
= _("File Error") 
 396             wx
.MessageBox(_("Could not open '%s'.  %s") % (wx
.lib
.docview
.FileNameFromPath(filePath
), sys
.exc_value
), 
 398                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 399                           wx
.GetApp().GetTopWindow()) 
 400             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 403         self
.SetFilename(filePath
, True) 
 404         view
.AddProjectToView(self
) 
 405         self
.SetDocumentModificationDate() 
 406         self
.UpdateAllViews() 
 407         self
._savedYet 
= True 
 412     def AddFile(self
, filePath
, folderPath
=None, type=None, name
=None): 
 422         return self
.AddFiles([filePath
], folderPath
, types
, names
) 
 425     def AddFiles(self
, filePaths
=None, folderPath
=None, types
=None, names
=None, files
=None): 
 426         # Filter out files that are not already in the project 
 430             for filePath 
in filePaths
: 
 431                 if self
.GetModel().FindFile(filePath
): 
 432                     oldFilePaths
.append(filePath
) 
 434                     newFilePaths
.append(filePath
) 
 436             projectService 
= wx
.GetApp().GetService(ProjectService
) 
 437             for i
, filePath 
in enumerate(newFilePaths
): 
 446                     name 
= projectService
.FindNameDefault(filePath
) 
 449                     folder 
= projectService
.FindLogicalViewFolderDefault(filePath
) 
 453                 self
.GetModel().AddFile(filePath
, folder
, type, name
) 
 458                 if self
.GetModel().FindFile(file.filePath
): 
 459                     oldFilePaths
.append(file.filePath
) 
 461                     newFilePaths
.append(file.filePath
) 
 462                     self
.GetModel().AddFile(file=file) 
 466         self
.AddNameSpaces(newFilePaths
) 
 468         self
.UpdateAllViews(hint 
= ("add", self
, newFilePaths
, oldFilePaths
)) 
 469         if len(newFilePaths
): 
 476     def RemoveFile(self
, filePath
): 
 477         return self
.RemoveFiles([filePath
]) 
 480     def RemoveFiles(self
, filePaths
=None, files
=None): 
 486                 filePaths
.append(file.filePath
) 
 488         for filePath 
in filePaths
: 
 489             file = self
.GetModel().FindFile(filePath
) 
 491                 self
.GetModel().RemoveFile(file) 
 492                 removedFiles
.append(file.filePath
) 
 494         self
.UpdateAllViews(hint 
= ("remove", self
, removedFiles
)) 
 495         if len(removedFiles
): 
 502     def RenameFile(self
, oldFilePath
, newFilePath
, isProject 
= False): 
 504             if oldFilePath 
== newFilePath
: 
 507             # projects don't have to exist yet, so not required to rename old file, 
 508             # but files must exist, so we'll try to rename and allow exceptions to occur if can't. 
 509             if not isProject 
or (isProject 
and os
.path
.exists(oldFilePath
)): 
 510                 os
.rename(oldFilePath
, newFilePath
) 
 513                 documents 
= self
.GetDocumentManager().GetDocuments() 
 514                 for document 
in documents
: 
 515                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFilePath
):  # If the renamed document is open, update it 
 516                         document
.SetFilename(newFilePath
) 
 517                         document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFilePath
)) 
 518                         document
.UpdateAllViews(hint 
= ("rename", self
, oldFilePath
, newFilePath
)) 
 520                 self
.UpdateFilePath(oldFilePath
, newFilePath
) 
 521                 documents 
= self
.GetDocumentManager().GetDocuments() 
 522                 for document 
in documents
: 
 523                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFilePath
):  # If the renamed document is open, update it 
 524                         document
.SetFilename(newFilePath
, notifyViews 
= True) 
 525                         document
.UpdateAllViews(hint 
= ("rename", self
, oldFilePath
, newFilePath
)) 
 527         except OSError, (code
, message
): 
 528             msgTitle 
= wx
.GetApp().GetAppName() 
 530                 msgTitle 
= _("File Error") 
 531             wx
.MessageBox("Could not rename '%s'.  '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFilePath
), message
), 
 533                           wx
.OK | wx
.ICON_EXCLAMATION
, 
 534                           wx
.GetApp().GetTopWindow()) 
 538     def MoveFile(self
, file, newFolderPath
): 
 539         return self
.MoveFiles([file], newFolderPath
) 
 542     def MoveFiles(self
, files
, newFolderPath
): 
 544         isArray 
= isinstance(newFolderPath
, type([])) 
 545         for i 
in range(len(files
)): 
 547                 files
[i
].logicalFolder 
= newFolderPath
[i
] 
 549                 files
[i
].logicalFolder 
= newFolderPath
 
 550             filePaths
.append(files
[i
].filePath
) 
 552         self
.UpdateAllViews(hint 
= ("remove", self
, filePaths
)) 
 553         self
.UpdateAllViews(hint 
= ("add", self
, filePaths
, [])) 
 558     def UpdateFilePath(self
, oldFilePath
, newFilePath
): 
 559         file = self
.GetModel().FindFile(oldFilePath
) 
 560         self
.RemoveFile(oldFilePath
) 
 562             self
.AddFile(newFilePath
, file.logicalFolder
, file.type, file.name
) 
 564             self
.AddFile(newFilePath
) 
 567     def RemoveInvalidPaths(self
): 
 568         """Makes sure all paths project knows about are valid and point to existing files. Removes and returns list of invalid paths.""" 
 572         fileRefs 
= self
.GetFileRefs() 
 574         for fileRef 
in fileRefs
: 
 575             if not os
.path
.exists(fileRef
.filePath
): 
 576                 invalidFileRefs
.append(fileRef
) 
 578         for fileRef 
in invalidFileRefs
: 
 579             fileRefs
.remove(fileRef
) 
 581         return [fileRef
.filePath 
for fileRef 
in invalidFileRefs
] 
 584     def SetStageProjectFile(self
): 
 585         self
._stageProjectFile 
= True 
 588     def ArchiveProject(self
, zipdest
, stagedir
): 
 589         """Zips stagedir, creates a zipfile that has as name the projectname, in zipdest. Returns path to zipfile.""" 
 590         if os
.path
.exists(zipdest
): 
 591             raise AssertionError("Cannot archive project, %s already exists" % zipdest
) 
 592         fileutils
.zip(zipdest
, stagedir
) 
 597     def StageProject(self
, tmpdir
, targetDataSourceMapping
={}): 
 598         """ Copies all files this 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.""" 
 600         projname 
= self
.GetProjectName() 
 601         stagedir 
= os
.path
.join(tmpdir
, projname
) 
 602         fileutils
.remove(stagedir
) 
 603         os
.makedirs(stagedir
)         
 605         # remove invalid files from project 
 606         self
.RemoveInvalidPaths()         
 608         # required so relative paths are written correctly when .dpl file is 
 610         self
.SetFilename(os
.path
.join(stagedir
, 
 611                                       os
.path
.basename(self
.GetFilename()))) 
 612         projectdir 
= self
.GetModel().homeDir
 
 614         # Validate paths before actually copying, and populate a dict 
 615         # with src->dest so copying is easy. 
 616         # (fileDict: ProjectFile instance -> dest path (string)) 
 617         fileDict 
= self
._ValidateFilePaths
(projectdir
, stagedir
) 
 619         # copy files to staging dir 
 620         self
._StageFiles
(fileDict
) 
 622         # set target data source for schemas 
 623         self
._SetSchemaTargetDataSource
(fileDict
, targetDataSourceMapping
) 
 625         # it is unfortunate we require this. it would be nice if filepaths 
 626         # were only in the project 
 627         self
._FixWsdlAgFiles
(stagedir
) 
 630         dplfilename 
= projname 
+ deploymentlib
.DEPLOYMENT_EXTENSION
 
 631         dplfilepath 
= os
.path
.join(stagedir
, dplfilename
) 
 632         self
.GenerateDeployment(dplfilepath
) 
 634         if self
._stageProjectFile
: 
 635             # save project so we get the .agp file. not required for deployment 
 636             # but convenient if user wants to open the deployment in the IDE 
 637             agpfilename 
= projname 
+ PROJECT_EXTENSION
 
 638             agpfilepath 
= os
.path
.join(stagedir
, agpfilename
) 
 640             # if this project has deployment data sources configured, remove 
 641             # them. changing the project is fine, since this is a clone of 
 642             # the project the IDE has. 
 643             self
.GetModel().GetAppInfo().ResetDeploymentDataSources() 
 647                 f 
= open(agpfilepath
, "w") 
 649                 # setting homeDir correctly is required for the "figuring out 
 650                 # relative paths" logic when saving the project 
 651                 self
.GetModel().homeDir 
= stagedir
 
 653                 projectlib
.save(f
, self
.GetModel(), productionDeployment
=True) 
 661     def _FixWsdlAgFiles(self
, stagedir
): 
 662         """For each wsdlag file in the stagedir: if referenced artifact (wsdl or code file) is a known product file (such as securityservice.wsdl), make sure patch to it is parameterized with special env var. We do not want to copy those files. For user artifacts, ensure the file lives in root of stagedir. This should be the case if it is part of project (since staging has run). If it is not at root of stagedir, copy it. Then update path in wsdlag.""" 
 663         files 
= os
.listdir(stagedir
) 
 665             if (f
.endswith(WsdlAgEditor
.WsdlAgDocument
.WSDL_AG_EXT
)): 
 666                 wsdlagpath 
= os
.path
.join(stagedir
, f
) 
 670                     fileObject 
= open(wsdlagpath
) 
 671                     serviceref 
= WsdlAgEditor
.load(fileObject
) 
 674                     if (hasattr(serviceref
, WsdlAgModel
.WSDL_FILE_ATTR
)): 
 675                         modified 
= (modified |
 
 676                                     self
._UpdateServiceRefPathAttr
( 
 677                                         stagedir
, serviceref
, 
 678                                         WsdlAgModel
.WSDL_FILE_ATTR
)) 
 680                     # referenced code file 
 681                     if (hasattr(serviceref
, WsdlAgModel
.LOCAL_SERVICE_ELEMENT
)): 
 682                         lse 
= getattr(serviceref
, 
 683                                       WsdlAgModel
.LOCAL_SERVICE_ELEMENT
) 
 684                         if (hasattr(lse
, WsdlAgModel
.LOCAL_SERVICE_FILE_ATTR
)): 
 685                             modified 
= (modified |
 
 686                                         self
._UpdateServiceRefPathAttr
( 
 688                                             WsdlAgModel
.LOCAL_SERVICE_FILE_ATTR
)) 
 697                 # no need to save the file if we did not change anything 
 698                 if not modified
: continue 
 700                 # write the wsdlag file 
 701                 fileObject 
= open(wsdlagpath
) 
 703                     serviceref 
= WsdlAgEditor
.save(fileObject
, serviceref
) 
 711     def _UpdateServiceRefPathAttr(self
, stagedir
, serviceref
, attrName
): 
 712         """Returns True if serviceref path has been updated, False otherwise.""" 
 714         filePath 
= getattr(serviceref
, attrName
) 
 716         if (filePath 
== None): 
 719         filePath 
= filePath
.strip() 
 721         if (len(filePath
) == 0): 
 725         # if filePath starts with one of the AG systems vars, we don't 
 726         # have to do anything 
 727         if (fileutils
.startsWithAgSystemVar(filePath
)): 
 730         # remove any known env var refs (we'll put them back a little below) 
 731         # we remove them here so that paths that do not have env vars also 
 732         # get parameterized correctly below 
 733         filePath 
= fileutils
.expandKnownAGVars(filePath
) 
 735         # make sure we have forward slashes. this is a workaround, which 
 736         # would not be necessary if we only write paths with forward slashes 
 738         filePath 
= filePath
.replace("\\", "/") 
 740         filePath 
= os
.path
.abspath(filePath
)         
 742         if (not os
.path
.exists(filePath
)): 
 743             # Wrong place to validate that referenced file exists, so just 
 747         # If the referenced file is in stagedir already, there's nothing to do 
 748         if (fileutils
.hasAncestorDir(filePath
, stagedir
)): 
 751         # The path points outside of stagedir. 
 753         # Check if we already have the referenced wsdl file at root, should be 
 754         # the case if the referenced wsdl is part of project. 
 755         # Copy it if we don't have it, unless it lives in one of the known 
 756         # product directories - in which case we parameterize the known path 
 757         # with one of our AG system vars 
 758         relPath 
= os
.path
.basename(filePath
) 
 759         stagePath 
= os
.path
.join(stagedir
, relPath
) 
 761         if (not os
.path
.exists(stagePath
)): 
 762             pFilePath 
= fileutils
.parameterizePathWithAGSystemVar(filePath
) 
 763             if pFilePath 
== filePath
: # no parameterization happened, copy 
 764                 fileutils
.copyFile(filePath
, stagePath
) 
 765                 setattr(serviceref
, attrName
, relPath
) 
 767                 setattr(serviceref
, attrName
, pFilePath
.replace("\\", "/")) 
 769             setattr(serviceref
, attrName
, relPath
) 
 774     def _SetSchemaTargetDataSource(self
, projectFiles
, dsmapping
): 
 775         """Update schema's default data source, if necessary.""" 
 777         for projectFile 
in projectFiles
: 
 778             if (projectFile
.type == basedocmgr
.FILE_TYPE_SCHEMA
): 
 779                 name 
= os
.path
.basename(projectFile
.filePath
) 
 780                 if (dsmapping
.has_key(name
)): 
 781                     schema 
= xmlutils
.load(projectFile
.filePath
) 
 782                     defaultName 
= schema
.getDefaultDataSourceName() 
 783                     if (defaultName 
!= dsmapping
[name
]): 
 784                         schema
.setDefaultDataSourceName(dsmapping
[name
]) 
 785                         xmlutils
.save(projectFile
.filePath
, schema
) 
 788     def _StageFiles(self
, fileDict
): 
 789         """Copy files to staging directory, update filePath attr of project's ProjectFile instances.""" 
 791         # fileDict: ProjectFile instance -> dest path (string) 
 793         for fileRef
, fileDest 
in fileDict
.items(): 
 794             fileutils
.copyFile(fileRef
.filePath
, fileDest
) 
 795             fileRef
.filePath 
= fileDest
 
 797     def _ValidateFilePaths(self
, projectdir
, stagedir
): 
 798         """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. 
 799            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: 
 800              -  match filenames of files living at the root of the project. 
 801              -  are same as those of any other file that lives outside of the projectdir. 
 803            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).""" 
 805         # ProjectFile instance -> dest path (string) 
 808         projectRootFiles 
= sets
.Set()   # live at project root 
 809         foreignFiles 
= sets
.Set()       # live outside of project 
 811         fileRefsToDeploy 
= self
.GetFileRefs() 
 813         for fileRef 
in fileRefsToDeploy
: 
 814             relPath 
= fileutils
.getRelativePath(fileRef
.filePath
, projectdir
) 
 815             filename 
= os
.path
.basename(fileRef
.filePath
)             
 816             if not relPath
: # file lives outside of project dir... 
 818                 # do we have another file with the same name already? 
 819                 if filename 
in foreignFiles
: 
 820                     raise IOError("More than one file with name \"%s\" lives outside of the project. These files need to have unique names" % filename
) 
 821                 foreignFiles
.add(filename
)        
 822                 fileDest 
= os
.path
.join(stagedir
, filename
) 
 824                 # file lives somewhere within the project dir 
 825                 fileDest 
= os
.path
.join(stagedir
, relPath
) 
 826                 if not os
.path
.dirname(relPath
): 
 827                     projectRootFiles
.add(filename
) 
 829             rtn
[fileRef
] = fileDest
 
 831         # make sure we won't collide with a file that lives at root of 
 832         # projectdir when moving files into project 
 833         for filename 
in foreignFiles
: 
 834             if filename 
in projectRootFiles
: 
 835                 raise IOError("File outside of project, \"%s\", cannot have same name as file at project root" % filename
) 
 839     def RenameFolder(self
, oldFolderPath
, newFolderPath
): 
 840         for file in self
.GetModel()._files
: 
 841             if file.logicalFolder 
== oldFolderPath
: 
 842                 file.logicalFolder 
= newFolderPath
 
 843         self
.UpdateAllViews(hint 
= ("rename folder", self
, oldFolderPath
, newFolderPath
)) 
 847     def GetSchemas(self
): 
 848         """Returns list of schema models (activegrid.model.schema.schema) for all schemas in this project.""" 
 851         resourceFactory 
= self
._GetResourceFactory
() 
 852         for projectFile 
in self
.GetModel().projectFiles
: 
 853             if (projectFile
.type == basedocmgr
.FILE_TYPE_SCHEMA
): 
 854                 schema 
= resourceFactory
.getModel(projectFile
) 
 861         return self
.GetModel().filePaths
 
 864     def GetFileRefs(self
): 
 865         return self
.GetModel().findAllRefs() 
 868     def SetFileRefs(self
, fileRefs
): 
 869         return self
.GetModel().setRefs(fileRefs
)     
 872     def IsFileInProject(self
, filename
): 
 873         return self
.GetModel().FindFile(filename
) 
 876     def GetAppInfo(self
): 
 877         return self
.GetModel().GetAppInfo() 
 880     def GetAppDocMgr(self
): 
 881         return self
.GetModel() 
 884     def GetProjectName(self
): 
 885         return os
.path
.splitext(os
.path
.basename(self
.GetFilename()))[0] 
 888     def GetDeploymentFilepath(self
, pre17
=False): 
 890             name 
= self
.GetProjectName() + PRE_17_TMP_DPL_NAME
 
 892             name 
= self
.GetProjectName() + _17_TMP_DPL_NAME
 
 893         return os
.path
.join(self
.GetModel().homeDir
, name
) 
 896     def _GetResourceFactory(self
, preview
=False, deployFilepath
=None): 
 897         return IDEResourceFactory( 
 898             openDocs
=wx
.GetApp().GetDocumentManager().GetDocuments(), 
 899             dataSourceService
=wx
.GetApp().GetService(DataModelEditor
.DataSourceService
), 
 900             projectDir
=os
.path
.dirname(self
.GetFilename()), 
 902             deployFilepath
=deployFilepath
) 
 904     def GenerateDeployment(self
, deployFilepath
=None, preview
=False): 
 906         if ACTIVEGRID_BASE_IDE
: 
 909         if not deployFilepath
: 
 910             deployFilepath 
= self
.GetDeploymentFilepath() 
 912         d 
= DeploymentGeneration
.DeploymentGenerator( 
 913             self
.GetModel(), self
._GetResourceFactory
(preview
, 
 916         dpl 
= d
.getDeployment(deployFilepath
) 
 919             dpl
.initialize()  # used in preview only 
 921         # REVIEW 07-Apr-06 stoens@activegrid.com -- Check if there's a 
 922         # tmp dpl file with pre 17 name, if so, delete it, so user doesn't end 
 923         # up with unused file in project dir. We should probably remove this 
 924         # check after 1.7 goes out. 
 925         fileutils
.remove(self
.GetDeploymentFilepath(pre17
=True)) 
 927         deploymentlib
.saveThroughCache(dpl
.fileName
, dpl
) 
 928         return deployFilepath
 
 930     def AddNameSpaces(self
, filePaths
): 
 931         """ Add any new wsdl and schema namespaces to bpel files """ 
 932         """ Add any new schema namespaces to wsdl files """ 
 933         if ACTIVEGRID_BASE_IDE
: 
 936         processRefs 
= self
.GetAppDocMgr().findRefsByFileType(basedocmgr
.FILE_TYPE_PROCESS
) # bpel 
 937         schemaRefs 
= self
.GetAppDocMgr().findRefsByFileType(basedocmgr
.FILE_TYPE_SCHEMA
) # xsd 
 938         serviceRefs 
= self
.GetAppDocMgr().allServiceRefs  
# wsdl 
 941         if processRefs 
and (serviceRefs 
or schemaRefs
): 
 942             for processRef 
in processRefs
: 
 943                 processDoc 
= processRef
.ideDocument
 
 944                 process 
= processDoc
.GetModel() 
 946                 if processDoc 
and process
: 
 949                     # add wsdl namespaces to bpel file 
 950                     for serviceRef 
in serviceRefs
: 
 951                         wsdl 
= serviceRef
.document
 
 953                         and (wsdl
.fileName 
in filePaths
 
 954                         or serviceRef
.filePath 
in filePaths
)): 
 955                             wsdlLongNS 
= wsdl
.targetNamespace
 
 956                             wsdlShortNS 
= self
.GetAppDocMgr().findShortNS(wsdlLongNS
) 
 958                                 wsdlShortNS 
= xmlutils
.genShortNS(process
, wsdlLongNS
) 
 959                             xmlutils
.addNSAttribute(process
, wsdlShortNS
, wsdlLongNS
) 
 962                     # add schema namespaces to bpel file 
 963                     for schemaRef 
in schemaRefs
: 
 964                         schema 
= schemaRef
.document
 
 965                         if schema 
and schema
.fileName 
in filePaths
: 
 966                             schemaLongNS 
= schema
.targetNamespace
 
 967                             schemaShortNS 
= self
.GetAppDocMgr().findShortNS(schemaLongNS
) 
 968                             if not schemaShortNS
: 
 969                                 schemaShortNS 
= xmlutils
.genShortNS(process
, schemaLongNS
) 
 970                             xmlutils
.addNSAttribute(process
, schemaShortNS
, schemaLongNS
) 
 974                         processDoc
.OnSaveDocument(processDoc
.GetFilename()) 
 978         if serviceRefs 
and schemaRefs
: 
 979             for serviceRef 
in serviceRefs
: 
 980                 wsdl 
= serviceRef
.document
 
 981                 wsdlDoc 
= serviceRef
.ideDocument
 
 986                     # add schema namespace to wsdl file 
 987                     for schemaRef 
in schemaRefs
: 
 988                         schema 
= schemaRef
.document
 
 989                         if schema 
and schema
.fileName 
in filePaths
: 
 990                             schemaLongNS 
= schema
.targetNamespace
 
 991                             schemaShortNS 
= self
.GetAppDocMgr().findShortNS(schemaLongNS
) 
 992                             if not schemaShortNS
: 
 993                                 schemaShortNS 
= xmlutils
.genShortNS(wsdl
, schemaLongNS
) 
 994                             xmlutils
.addNSAttribute(wsdl
, schemaShortNS
, schemaLongNS
) 
 998                         wsdlDoc
.OnSaveDocument(wsdlDoc
.GetFilename()) 
1001 class NewProjectWizard(Wizard
.BaseWizard
): 
1003     WIZTITLE 
= _("New Project Wizard") 
1006     def __init__(self
, parent
): 
1007         self
._parent 
= parent
 
1008         self
._fullProjectPath 
= None 
1009         Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
) 
1010         self
._projectLocationPage 
= self
.CreateProjectLocation(self
) 
1011         wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
) 
1014     def CreateProjectLocation(self
,wizard
): 
1015         page 
= Wizard
.TitledWizardPage(wizard
, _("Name and Location")) 
1017         page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nEnter the name and location for the project.\n"))) 
1018         self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation 
= UICommon
.CreateDirectoryControl(page
, fileExtension
="agp", appDirDefaultStartDir
=True, fileLabel
=_("Name:"), dirLabel
=_("Location:")) 
1019         page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
) 
1022         wizard
.FitToPage(page
) 
1026     def RunWizard(self
, existingTables 
= None, existingRelationships 
= None): 
1027         status 
= Wizard
.BaseWizard
.RunWizard(self
, self
._projectLocationPage
) 
1029             wx
.ConfigBase_Get().Write(PROJECT_DIRECTORY_KEY
, self
._dirCtrl
.GetValue()) 
1030             docManager 
= wx
.GetApp().GetTopWindow().GetDocumentManager() 
1031             if os
.path
.exists(self
._fullProjectPath
): 
1032                 # What if the document is already open and we're overwriting it? 
1033                 documents 
= docManager
.GetDocuments() 
1034                 for document 
in documents
: 
1035                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(self
._fullProjectPath
):  # If the renamed document is open, update it 
1036                         document
.DeleteAllViews() 
1038                 os
.remove(self
._fullProjectPath
) 
1040             for template 
in docManager
.GetTemplates(): 
1041                 if template
.GetDocumentType() == ProjectDocument
: 
1042                     doc 
= template
.CreateDocument(self
._fullProjectPath
, flags 
= wx
.lib
.docview
.DOC_NEW
) 
1043                     doc
.OnSaveDocument(self
._fullProjectPath
) 
1044                     projectService 
= wx
.GetApp().GetService(ProjectService
) 
1045                     view 
= projectService
.GetView() 
1046                     view
.AddProjectToView(doc
) 
1053     def OnWizPageChanging(self
, event
): 
1054         if event
.GetDirection():  # It's going forwards 
1055             if event
.GetPage() == self
._projectLocationPage
: 
1056                 if not self
._fileValidation
(validClassName
=True): 
1059                 self
._fullProjectPath 
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(), PROJECT_EXTENSION
)) 
1062     def OnShowCreatePages(self
): 
1064         import DataModelEditor
 
1065         requestedPos 
= self
.GetPositionTuple() 
1066         projectService 
= wx
.GetApp().GetService(ProjectService
) 
1067         projectView 
= projectService
.GetView() 
1069         wiz 
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
) 
1070         if wiz
.RunWizard(dontDestroy
=True): 
1071            self
._schemaName
.SetValue(wiz
.GetSchemaFileName()) 
1076 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
): 
1079     def CreateDocument(self
, path
, flags
): 
1081             doc 
= wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
) 
1083                 doc
.GetModel()._projectDir 
= os
.path
.dirname(path
) 
1086             wiz 
= NewProjectWizard(wx
.GetApp().GetTopWindow()) 
1089             return None  # never return the doc, otherwise docview will think it is a new file and rename it 
1092 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
): 
1095     def __init__(self
, projectDoc
, filePaths
, folderPath
=None, types
=None, names
=None): 
1096         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1097         self
._projectDoc 
= projectDoc
 
1098         self
._allFilePaths 
= filePaths
 
1099         self
._folderPath 
= folderPath
 
1105             projectService 
= wx
.GetApp().GetService(ProjectService
) 
1106             for filePath 
in self
._allFilePaths
: 
1107                 self
._types
.append(projectService
.FindFileTypeDefault(filePath
)) 
1109         # list of files that will really be added 
1111         for filePath 
in self
._allFilePaths
: 
1112             if not projectDoc
.GetModel().FindFile(filePath
): 
1113                 self
._newFiles
.append(filePath
) 
1117         if len(self
._allFilePaths
) == 1: 
1118             return _("Add File %s") % os
.path
.basename(self
._allFilePaths
[0]) 
1120             return _("Add Files") 
1124         return self
._projectDoc
.AddFiles(self
._allFilePaths
, self
._folderPath
, self
._types
, self
._names
) 
1128         return self
._projectDoc
.RemoveFiles(self
._newFiles
) 
1131 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
): 
1134     def __init__(self
, projectDoc
, files
): 
1135         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1136         self
._projectDoc 
= projectDoc
 
1141         if len(self
._files
) == 1: 
1142             return _("Remove File %s") % os
.path
.basename(self
._files
[0].filePath
) 
1144             return _("Remove Files") 
1148         return self
._projectDoc
.RemoveFiles(files
=self
._files
) 
1152         return self
._projectDoc
.AddFiles(files
=self
._files
) 
1156 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
): 
1159     def __init__(self
, projectDoc
, oldFilePath
, newFilePath
, isProject 
= False): 
1160         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1161         self
._projectDoc 
= projectDoc
 
1162         self
._oldFilePath 
= oldFilePath
 
1163         self
._newFilePath 
= newFilePath
 
1164         self
._isProject 
= isProject
 
1168         return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFilePath
), os
.path
.basename(self
._newFilePath
)) 
1172         return self
._projectDoc
.RenameFile(self
._oldFilePath
, self
._newFilePath
, self
._isProject
) 
1176         return self
._projectDoc
.RenameFile(self
._newFilePath
, self
._oldFilePath
, self
._isProject
) 
1179 class ProjectRenameFolderCommand(wx
.lib
.docview
.Command
): 
1180     def __init__(self
, doc
, oldFolderPath
, newFolderPath
): 
1181         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1183         self
._oldFolderPath 
= oldFolderPath
 
1184         self
._newFolderPath 
= newFolderPath
 
1188         return _("Rename Folder %s to %s") % (os
.path
.basename(self
._oldFolderPath
), os
.path
.basename(self
._newFolderPath
)) 
1192         return self
._doc
.RenameFolder(self
._oldFolderPath
, self
._newFolderPath
) 
1196         return self
._doc
.RenameFolder(self
._newFolderPath
, self
._oldFolderPath
) 
1199 class ProjectAddFolderCommand(wx
.lib
.docview
.Command
): 
1200     def __init__(self
, view
, doc
, folderpath
): 
1201         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1204         self
._folderpath 
= folderpath
 
1208         return _("Add Folder %s") % (os
.path
.basename(self
._folderpath
)) 
1212         if self
._view
.GetDocument() != self
._doc
: 
1214         status 
= self
._view
.AddFolder(self
._folderpath
) 
1216             self
._view
._treeCtrl
.UnselectAll() 
1217             item 
= self
._view
._treeCtrl
.FindFolder(self
._folderpath
) 
1218             self
._view
._treeCtrl
.SelectItem(item
) 
1223         if self
._view
.GetDocument() != self
._doc
: 
1225         return self
._view
.DeleteFolder(self
._folderpath
) 
1228 class ProjectRemoveFolderCommand(wx
.lib
.docview
.Command
): 
1229     def __init__(self
, view
, doc
, folderpath
): 
1230         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1233         self
._folderpath 
= folderpath
 
1237         return _("Remove Folder %s") % (os
.path
.basename(self
._folderpath
)) 
1241         if self
._view
.GetDocument() != self
._doc
: 
1243         return self
._view
.DeleteFolder(self
._folderpath
) 
1247         if self
._view
.GetDocument() != self
._doc
: 
1249         status 
= self
._view
.AddFolder(self
._folderpath
) 
1251             self
._view
._treeCtrl
.UnselectAll() 
1252             item 
= self
._view
._treeCtrl
.FindFolder(self
._folderpath
) 
1253             self
._view
._treeCtrl
.SelectItem(item
) 
1257 class ProjectMoveFilesCommand(wx
.lib
.docview
.Command
): 
1259     def __init__(self
, doc
, files
, folderPath
): 
1260         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1263         self
._newFolderPath 
= folderPath
 
1265         self
._oldFolderPaths 
= [] 
1266         for file in self
._files
: 
1267             self
._oldFolderPaths
.append(file.logicalFolder
) 
1271         if len(self
._files
) == 1: 
1272             return _("Move File %s") % os
.path
.basename(self
._files
[0].filePath
) 
1274             return _("Move Files") 
1278         return self
._doc
.MoveFiles(self
._files
, self
._newFolderPath
) 
1282         return self
._doc
.MoveFiles(self
._files
, self
._oldFolderPaths
)             
1285 class ProjectTreeCtrl(wx
.TreeCtrl
): 
1287     #---------------------------------------------------------------------------- 
1288     # Overridden Methods 
1289     #---------------------------------------------------------------------------- 
1291     def __init__(self
, parent
, id, style
): 
1292         wx
.TreeCtrl
.__init
__(self
, parent
, id, style 
= style
) 
1294         templates 
= wx
.GetApp().GetDocumentManager().GetTemplates() 
1295         iconList 
= wx
.ImageList(16, 16, initialCount 
= len(templates
)) 
1296         self
._iconIndexLookup 
= [] 
1297         for template 
in templates
: 
1298             icon 
= template
.GetIcon() 
1300                 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1303                     if wx
.GetApp().GetDebug(): 
1304                         print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
 
1305                 iconIndex 
= iconList
.AddIcon(icon
) 
1306                 self
._iconIndexLookup
.append((template
, iconIndex
)) 
1308         icon 
= getBlankIcon() 
1309         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1312             if wx
.GetApp().GetDebug(): 
1313                 print "Warning: getBlankIcon isn't 16x16, not crossplatform" 
1314         self
._blankIconIndex 
= iconList
.AddIcon(icon
) 
1316         icon 
= getFolderClosedIcon() 
1317         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1320             if wx
.GetApp().GetDebug(): 
1321                 print "Warning: getFolderIcon isn't 16x16, not crossplatform" 
1322         self
._folderClosedIconIndex 
= iconList
.AddIcon(icon
) 
1324         icon 
= getFolderOpenIcon() 
1325         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1328             if wx
.GetApp().GetDebug(): 
1329                 print "Warning: getFolderIcon isn't 16x16, not crossplatform" 
1330         self
._folderOpenIconIndex 
= iconList
.AddIcon(icon
) 
1332         self
.AssignImageList(iconList
) 
1335     def OnCompareItems(self
, item1
, item2
): 
1336         item1IsFolder 
= (self
.GetPyData(item1
) == None) 
1337         item2IsFolder 
= (self
.GetPyData(item2
) == None) 
1338         if (item1IsFolder 
== item2IsFolder
):  # if both are folders or both not 
1339             return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower()) 
1340         elif item1IsFolder 
and not item2IsFolder
: # folders sort above non-folders 
1342         elif not item1IsFolder 
and item2IsFolder
: # folders sort above non-folders 
1346     def AppendFolder(self
, parent
, folderName
): 
1347         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, folderName
) 
1348         self
.SetItemImage(item
, self
._folderClosedIconIndex
, wx
.TreeItemIcon_Normal
) 
1349         self
.SetItemImage(item
, self
._folderOpenIconIndex
, wx
.TreeItemIcon_Expanded
) 
1350         self
.SetPyData(item
, None) 
1354     def AppendItem(self
, parent
, filename
, file): 
1355         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, filename
) 
1358         template 
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filename
) 
1360             for t
, iconIndex 
in self
._iconIndexLookup
: 
1362                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
) 
1363                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
) 
1364 ##                    self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected) 
1369             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
) 
1370             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
) 
1371 ##            self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected) 
1373         self
.SetPyData(item
, file) 
1378     def AddFolder(self
, folderPath
): 
1381         if folderPath 
!= None: 
1382             folderTree 
= folderPath
.split('/') 
1384             item 
= self
.GetRootItem() 
1385             for folderName 
in folderTree
: 
1388                 (child
, cookie
) = self
.GetFirstChild(item
) 
1390                     file = self
.GetPyData(child
) 
1394                         if self
.GetItemText(child
) == folderName
: 
1398                     (child
, cookie
) = self
.GetNextChild(item
, cookie
) 
1401                     item 
= self
.AppendFolder(item
, folderName
) 
1402                     folderItems
.append(item
) 
1407     def FindItem(self
, filePath
, parentItem
=None): 
1409             parentItem 
= self
.GetRootItem() 
1411         (child
, cookie
) = self
.GetFirstChild(parentItem
) 
1413             file = self
.GetPyData(child
) 
1415                 if file.filePath 
== filePath
: 
1418                 result 
= self
.FindItem(filePath
, child
)  # do recursive call 
1421             (child
, cookie
) = self
.GetNextChild(parentItem
, cookie
) 
1426     def FindFolder(self
, folderPath
): 
1427         if folderPath 
!= None: 
1428             folderTree 
= folderPath
.split('/') 
1430             item 
= self
.GetRootItem() 
1431             for folderName 
in folderTree
: 
1434                 (child
, cookie
) = self
.GetFirstChild(item
) 
1436                     file = self
.GetPyData(child
) 
1440                         if self
.GetItemText(child
) == folderName
: 
1444                     (child
, cookie
) = self
.GetNextChild(item
, cookie
) 
1452     def FindClosestFolder(self
, x
, y
): 
1453         item
, flags 
= self
.HitTest((x
,y
)) 
1455             file = self
.GetPyData(item
) 
1457                 item 
= self
.GetItemParent(item
) 
1463 class ProjectView(wx
.lib
.docview
.View
): 
1464     LOGICAL_MODE  
= "logical" 
1465     PHYSICAL_MODE 
= "physical" 
1467     #---------------------------------------------------------------------------- 
1468     # Overridden methods 
1469     #---------------------------------------------------------------------------- 
1471     def __init__(self
, service 
= None): 
1472         wx
.lib
.docview
.View
.__init
__(self
) 
1473         # self._service = service  # not used, but kept to match other Services 
1474         self
._projectChoice 
= None 
1475         self
._logicalBtn 
= None 
1476         self
._physicalBtn 
= None 
1477         self
._treeCtrl 
= None 
1478         self
._editingSoDontKillFocus 
= False 
1479         self
._checkEditMenu 
= True 
1480         self
._loading 
= False  # flag to not to try to saving state of folders while it is loading 
1483     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 
1484         return wx
.GetApp().GetDocumentManager() 
1488         projectService 
= wx
.GetApp().GetService(ProjectService
) 
1490             projectService
.SetView(None) 
1491         wx
.lib
.docview
.View
.Destroy(self
) 
1494     def GetDocument(self
): 
1495         if not self
._projectChoice
: 
1498         selItem 
= self
._projectChoice
.GetSelection() 
1499         if selItem 
== wx
.NOT_FOUND
: 
1502         document 
= self
._projectChoice
.GetClientData(selItem
) 
1506     def Activate(self
, activate 
= True): 
1507         if not wx
.GetApp().IsMDI(): 
1508             if activate 
and not self
.IsShown(): 
1512             wx
.lib
.docview
.View
.Activate(self
, activate 
= activate
) 
1513             if activate 
and self
._treeCtrl
: 
1514                 self
._treeCtrl
.SetFocus() 
1517     def OnCreate(self
, doc
, flags
): 
1518         config 
= wx
.ConfigBase_Get() 
1519         if wx
.GetApp().IsMDI(): 
1520             self
._embeddedWindow 
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
) 
1521             self
.SetFrame(self
._embeddedWindow
) 
1522             frame 
= self
._embeddedWindow
 
1523             wx
.EVT_SIZE(frame
, self
.OnSize
) 
1525             self
._embeddedWindow 
= None 
1526             pos 
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1) 
1527             # make sure frame is visible 
1528             screenWidth 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
) 
1529             screenHeight 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
) 
1530             if pos
[0] < 0 or pos
[0] >= screenWidth 
or pos
[1] < 0 or pos
[1] >= screenHeight
: 
1531                 pos 
= wx
.DefaultPosition
 
1533             size 
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1)) 
1535             title 
= _("Projects") 
1536             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI 
and wx
.GetApp().GetAppName(): 
1537                 title 
=  title 
+ " - " + wx
.GetApp().GetAppName() 
1539             frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title 
= title
, pos 
= pos
, size 
= size
) 
1540             if config
.ReadInt("ProjectFrameMaximized", False): 
1541                 frame
.Maximize(True) 
1543         panel 
= wx
.Panel(frame
, -1) 
1545         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1547         butSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
1549         self
._projectChoice 
= wx
.Choice(panel
, -1) 
1550         panel
.Bind(wx
.EVT_CHOICE
, self
.OnProjectSelect
, self
._projectChoice
) 
1551         w
, h 
= self
._projectChoice
.GetSize() 
1553         self
._logicalBtn 
= wx
.lib
.buttons
.GenBitmapToggleButton(panel
, -1, getLogicalModeOffBitmap(), size
=(h
,h
)) 
1554         self
._logicalBtn
.SetBitmapSelected(getLogicalModeOnBitmap()) 
1555         self
._logicalBtn
.SetToggle(True) 
1556         self
._logicalBtn
.SetToolTipString(_("View Files by Logical Groups")) 
1557         panel
.Bind(wx
.EVT_BUTTON
, self
.OnSelectMode
, self
._logicalBtn
) 
1558         self
._physicalBtn 
= wx
.lib
.buttons
.GenBitmapToggleButton(panel
, -1, getPhysicalModeOffBitmap(), size
=(h
,h
)) 
1559         self
._physicalBtn
.SetBitmapSelected(getPhysicalModeOnBitmap()) 
1560         self
._physicalBtn
.SetToolTipString(_("View Files by Physical Disk Layout")) 
1561         panel
.Bind(wx
.EVT_BUTTON
, self
.OnSelectMode
, self
._physicalBtn
) 
1563         butSizer
.Add(self
._projectChoice
, 1, wx
.EXPAND
) 
1564         butSizer
.Add(self
._logicalBtn
, 0) 
1565         butSizer
.Add(self
._physicalBtn
, 0) 
1566         sizer
.Add(butSizer
, 0, wx
.EXPAND
) 
1568         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
) 
1569         self
._treeCtrl
.AddRoot(_("Projects")) 
1570         if self
._embeddedWindow
: 
1571             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND|wx
.BOTTOM
, HALF_SPACE
)  # allow space for embedded window resize-sash 
1573             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
) 
1574         panel
.SetSizer(sizer
) 
1576         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1578         if wx
.GetApp().IsMDI(): 
1579             sizer
.Add(panel
, 1, wx
.EXPAND|wx
.BOTTOM
, 3) # wxBug: without bottom margin, can't resize embedded window 
1581             sizer
.Add(panel
, 1, wx
.EXPAND
) 
1583         frame
.SetSizer(sizer
) 
1587         if wx
.GetApp().IsMDI(): 
1588             wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
) 
1589             wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
) 
1591         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
1592             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
) 
1594             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
) 
1595         wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
) 
1596         wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
) 
1597         wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
) 
1598         wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
) 
1599         wx
.EVT_TREE_ITEM_COLLAPSED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.SaveFolderState
) 
1600         wx
.EVT_TREE_ITEM_EXPANDED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.SaveFolderState
) 
1601         wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
) 
1602         wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
) 
1603         wx
.EVT_LEFT_DOWN(self
._treeCtrl
, self
.OnLeftClick
) 
1605         # drag-and-drop support 
1606         dt 
= ProjectFileDropTarget(self
) 
1607         self
._treeCtrl
.SetDropTarget(dt
) 
1612     def OnSelectMode(self
, event
): 
1613         btn 
= event
.GetEventObject() 
1614         down 
= event
.GetIsDown() 
1615         if btn 
== self
._logicalBtn
: 
1616             self
._physicalBtn
.SetToggle(not down
) 
1617         else:  # btn == self._physicalBtn: 
1618             self
._logicalBtn
.SetToggle(not down
) 
1619         self
.LoadProject(self
.GetDocument()) 
1623         if not self
._physicalBtn
.up
: 
1624             return ProjectView
.PHYSICAL_MODE
 
1625         else:  # elif self._logicalBtn.GetValue(): 
1626             return ProjectView
.LOGICAL_MODE
 
1629     def OnProjectSelect(self
, event
=None): 
1630         self
.LoadProject(self
.GetDocument()) 
1631         if self
.GetDocument(): 
1632             filename 
= self
.GetDocument().GetFilename() 
1635         self
._projectChoice
.SetToolTipString(filename
) 
1638     def OnSize(self
, event
): 
1640         wx
.CallAfter(self
.GetFrame().Layout
) 
1643     def OnBeginDrag(self
, event
): 
1644         if self
.GetMode() == ProjectView
.PHYSICAL_MODE
: 
1647         item 
= event
.GetItem() 
1649             self
._draggingItems 
= [] 
1650             for item 
in self
._treeCtrl
.GetSelections(): 
1651                 if self
._IsItemFile
(item
): 
1652                     self
._draggingItems
.append(item
) 
1653             if len(self
._draggingItems
): 
1657     def OnEndDrag(self
, event
): 
1658         item 
= event
.GetItem() 
1661             for ditem 
in self
._draggingItems
: 
1662                 file = self
._GetItemFile
(ditem
) 
1663                 if file not in files
: 
1666             folderPath 
= self
._GetItemFolderPath
(item
) 
1668             self
.GetDocument().GetCommandProcessor().Submit(ProjectMoveFilesCommand(self
.GetDocument(), files
, folderPath
)) 
1671     def WriteProjectConfig(self
): 
1672         frame 
= self
.GetFrame() 
1673         config 
= wx
.ConfigBase_Get() 
1674         if frame 
and not self
._embeddedWindow
: 
1675             if not frame
.IsMaximized(): 
1676                 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0]) 
1677                 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1]) 
1678                 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0]) 
1679                 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1]) 
1680             config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized()) 
1682         if config
.ReadInt("ProjectSaveDocs", True): 
1683             projectFileNames 
= [] 
1686             if self
._projectChoice
: 
1687                 for i 
in range(self
._projectChoice
.GetCount()): 
1688                     project 
= self
._projectChoice
.GetClientData(i
) 
1689                     if not project
.OnSaveModified(): 
1691                     if project
.GetDocumentSaved():  # Might be a new document and "No" selected to save it 
1692                         projectFileNames
.append(str(project
.GetFilename())) 
1693             config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__()) 
1696             if self
._projectChoice
.GetCount(): 
1697                 i 
= self
._projectChoice
.GetSelection() 
1698                 if i 
!= wx
.NOT_FOUND
: 
1699                     document 
= self
._projectChoice
.GetClientData(i
) 
1701                 config
.Write("ProjectCurrent", document
.GetFilename()) 
1703                 config
.DeleteEntry("ProjectCurrent") 
1706     def OnClose(self
, deleteWindow 
= True): 
1707         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
1708             self
.WriteProjectConfig() 
1710         project 
= self
.GetDocument() 
1713         if not project
.Close(): 
1716         if not deleteWindow
: 
1717             self
.RemoveCurrentDocumentUpdate() 
1719             # need this to accelerate closing down app if treeCtrl has lots of items 
1720             self
._treeCtrl
.Freeze() 
1722                 rootItem 
= self
._treeCtrl
.GetRootItem() 
1723                 self
._treeCtrl
.DeleteChildren(rootItem
) 
1725                 self
._treeCtrl
.Thaw() 
1727         # We don't need to delete the window since it is a floater/embedded 
1731     def _GetParentFrame(self
): 
1732         return wx
.GetTopLevelParent(self
.GetFrame()) 
1735     def OnUpdate(self
, sender 
= None, hint 
= None): 
1736         if wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
): 
1740             if hint
[0] == "add": 
1741                 projectDoc 
= hint
[1] 
1742                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1745                 self
._treeCtrl
.Freeze() 
1748                     newFilePaths 
= hint
[2]  # need to be added and selected, and sorted 
1749                     oldFilePaths 
= hint
[3]  # need to be selected 
1750                     self
._treeCtrl
.UnselectAll() 
1752                     mode 
= self
.GetMode() 
1754                     project 
= projectDoc
.GetModel() 
1755                     projectDir 
= project
.homeDir
 
1756                     rootItem 
= self
._treeCtrl
.GetRootItem() 
1758                     # add new folders and new items 
1760                     for filePath 
in newFilePaths
: 
1761                         file = project
.FindFile(filePath
) 
1763                             if mode 
== ProjectView
.LOGICAL_MODE
: 
1764                                 folderPath 
= file.logicalFolder
 
1765                             else:  # ProjectView.PHYSICAL_MODE 
1766                                 folderPath 
= file.physicalFolder
 
1768                                 self
._treeCtrl
.AddFolder(folderPath
) 
1769                                 folder 
= self
._treeCtrl
.FindFolder(folderPath
) 
1772                             item 
= self
._treeCtrl
.AppendItem(folder
, os
.path
.basename(file.filePath
), file) 
1773                             addList
.append(item
) 
1775                     # sort folders with new items 
1777                     for item 
in addList
: 
1778                         parentItem 
= self
._treeCtrl
.GetItemParent(item
) 
1779                         if parentItem 
not in parentList
: 
1780                             parentList
.append(parentItem
) 
1781                     for parentItem 
in parentList
: 
1782                         self
._treeCtrl
.SortChildren(parentItem
) 
1784                     # select all the items user wanted to add 
1786                     for filePath 
in (oldFilePaths 
+ newFilePaths
): 
1787                         item 
= self
._treeCtrl
.FindItem(filePath
) 
1789                             self
._treeCtrl
.SelectItem(item
) 
1793                         self
._treeCtrl
.EnsureVisible(lastItem
) 
1796                     self
._treeCtrl
.Thaw() 
1799             elif hint
[0] == "remove": 
1800                 projectDoc 
= hint
[1] 
1801                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1804                 self
._treeCtrl
.Freeze() 
1808                     self
._treeCtrl
.UnselectAll() 
1810                     for filePath 
in filePaths
: 
1811                         item 
= self
._treeCtrl
.FindItem(filePath
) 
1813                             self
._treeCtrl
.Delete(item
) 
1815                     self
._treeCtrl
.UnselectAll()  # wxBug: even though we unselected earlier, an item still gets selected after the delete 
1818                     self
._treeCtrl
.Thaw() 
1821             elif hint
[0] == "rename": 
1822                 projectDoc 
= hint
[1] 
1823                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1826                 self
._treeCtrl
.Freeze() 
1828                     item 
= self
._treeCtrl
.FindItem(hint
[2]) 
1829                     self
._treeCtrl
.SetItemText(item
, os
.path
.basename(hint
[3])) 
1830                     self
._treeCtrl
.EnsureVisible(item
) 
1832                     self
._treeCtrl
.Thaw() 
1835             elif hint
[0] == "rename folder": 
1836                 projectDoc 
= hint
[1] 
1837                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1840                 self
._treeCtrl
.Freeze() 
1842                     item 
= self
._treeCtrl
.FindFolder(hint
[2]) 
1844                         self
._treeCtrl
.UnselectAll() 
1845                         self
._treeCtrl
.SetItemText(item
, os
.path
.basename(hint
[3])) 
1846                         self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
1847                         self
._treeCtrl
.SelectItem(item
) 
1848                         self
._treeCtrl
.EnsureVisible(item
) 
1850                     self
._treeCtrl
.Thaw() 
1854     def RemoveProjectUpdate(self
, projectDoc
): 
1855         """ Called by service after deleting a project, need to remove from project choices """ 
1856         i 
= self
._projectChoice
.FindString(self
._MakeProjectName
(projectDoc
)) 
1857         self
._projectChoice
.Delete(i
) 
1859         numProj 
= self
._projectChoice
.GetCount() 
1863             self
._projectChoice
.SetSelection(i
) 
1864         self
.OnProjectSelect() 
1867     def RemoveCurrentDocumentUpdate(self
, i
=-1): 
1868         """ Called by service after deleting a project, need to remove from project choices """ 
1869         i 
= self
._projectChoice
.GetSelection() 
1870         self
._projectChoice
.Delete(i
) 
1872         numProj 
= self
._projectChoice
.GetCount() 
1876             self
._projectChoice
.SetSelection(i
) 
1877         self
.OnProjectSelect() 
1880     def ProcessEvent(self
, event
): 
1882         if id == ProjectService
.CLOSE_PROJECT_ID
: 
1883             projectDoc 
= self
.GetDocument() 
1885                 projectService 
= wx
.GetApp().GetService(ProjectService
) 
1887                     openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
1888                     for openDoc 
in openDocs
[:]:  # need to make a copy, as each file closes we're off by one 
1889                         if projectDoc 
== openDoc
:  # close project last 
1892                         if projectDoc 
== projectService
.FindProjectFromMapping(openDoc
): 
1893                             self
.GetDocumentManager().CloseDocument(openDoc
, False) 
1895                             projectService
.RemoveProjectMapping(openDoc
) 
1896                             if hasattr(openDoc
, "GetModel"): 
1897                                 projectService
.RemoveProjectMapping(openDoc
.GetModel()) 
1899                 if self
.GetDocumentManager().CloseDocument(projectDoc
, False): 
1900                     self
.RemoveCurrentDocumentUpdate() 
1902         elif id == ProjectService
.ADD_FILES_TO_PROJECT_ID
: 
1903             self
.OnAddFileToProject(event
) 
1905         elif id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
: 
1906             self
.OnAddDirToProject(event
) 
1908         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1909             return False  # Implement this one in the service 
1910         elif id == ProjectService
.ADD_FOLDER_ID
: 
1911             self
.OnAddFolder(event
) 
1913         elif id == ProjectService
.RENAME_ID
: 
1914             self
.OnRename(event
) 
1916         elif id == ProjectService
.DELETE_FILE_ID
: 
1917             self
.OnDeleteFile(event
) 
1919         elif id == ProjectService
.DELETE_PROJECT_ID
: 
1920             self
.OnDeleteProject(event
) 
1922         elif id == wx
.ID_CUT
: 
1925         elif id == wx
.ID_COPY
: 
1928         elif id == wx
.ID_PASTE
: 
1931         elif (id == wx
.ID_CLEAR
 
1932         or id == ProjectService
.REMOVE_FROM_PROJECT
): 
1935         elif id == wx
.ID_SELECTALL
: 
1936             self
.OnSelectAll(event
) 
1938         elif id == ProjectService
.OPEN_SELECTION_ID
: 
1939             self
.OnOpenSelection(event
) 
1941         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1942             self
.OnProperties(event
) 
1944         elif id == ProjectService
.PROJECT_PROPERTIES_ID
: 
1945             self
.OnProjectProperties(event
) 
1951     def ProcessUpdateUIEvent(self
, event
): 
1952         # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here 
1953         if self
._checkEditMenu
: 
1954             doc 
= self
.GetDocument() 
1955             if doc 
and not doc
.GetCommandProcessor().GetEditMenu(): 
1956                 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
1957             self
._checkEditMenu 
= False 
1960         if id == wx
.ID_CLOSE
: 
1961             # Too confusing, so disable closing from "File | Close" menu, must close from "Project | Close Current Project" menu 
1962             if self
.ProjectHasFocus() or self
.FilesHasFocus(): 
1967         elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
 
1968         or id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
 
1969         or id == ProjectService
.CLOSE_PROJECT_ID
 
1970         or id == ProjectService
.DELETE_PROJECT_ID
): 
1971             event
.Enable(self
.GetDocument() != None) 
1973         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1974             event
.Enable(False)  # Implement this one in the service 
1976         elif id == ProjectService
.ADD_FOLDER_ID
: 
1977             event
.Enable((self
.GetDocument() != None) and (self
.GetMode() == ProjectView
.LOGICAL_MODE
)) 
1979         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1981             if self
.ProjectHasFocus(): 
1982                 if self
.GetDocument(): 
1984             elif self
.FilesHasFocus(): 
1985                 items 
= self
._treeCtrl
.GetSelections() 
1988                     if self
._IsItemFile
(item
): 
1991             event
.Enable(status
) 
1993         elif (id == wx
.ID_CUT
 
1995         or id == ProjectService
.DELETE_FILE_ID
 
1996         or id == ProjectService
.REMOVE_FROM_PROJECT
 
1997         or id == ProjectService
.OPEN_SELECTION_ID
): 
1998             event
.Enable(self
._HasFilesSelected
()) 
2000         elif (id == wx
.ID_CLEAR
 
2001         or id == ProjectService
.RENAME_ID
): 
2002             items 
= self
._treeCtrl
.GetSelections() 
2004                 hasViewSelected 
= False 
2006                     if self
._IsItemFile
(item
): 
2007                         file = self
._GetItemFile
(item
) 
2008                         if file.type == 'xform': 
2009                             hasViewSelected 
= True 
2015             event
.Enable(self
._HasFilesSelected
() or (self
.GetDocument() != None and self
.GetMode() == ProjectView
.LOGICAL_MODE 
and self
._HasFoldersSelected
())) 
2017         elif id == wx
.ID_PASTE
: 
2018             event
.Enable(self
.CanPaste()) 
2020         elif id == wx
.ID_SELECTALL
: 
2021             event
.Enable(self
._HasFiles
()) 
2023         elif (id == wx
.ID_PREVIEW
 
2024         or id == wx
.ID_PRINT
): 
2030     #---------------------------------------------------------------------------- 
2032     #---------------------------------------------------------------------------- 
2035         if not self
.GetFrame(): 
2037         return self
.GetFrame().IsShown() 
2044     def Show(self
, show 
= True): 
2045         self
.GetFrame().Show(show
) 
2046         if wx
.GetApp().IsMDI(): 
2047             mdiParentFrame 
= wx
.GetApp().GetTopWindow() 
2048             mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
) 
2051     #---------------------------------------------------------------------------- 
2052     # Methods for ProjectDocument and ProjectService to call 
2053     #---------------------------------------------------------------------------- 
2055     def SetProject(self
, projectPath
): 
2056         curSel 
= self
._projectChoice
.GetSelection() 
2057         for i 
in range(self
._projectChoice
.GetCount()): 
2058             document 
= self
._projectChoice
.GetClientData(i
) 
2059             if document
.GetFilename() == projectPath
: 
2060                 if curSel 
!= i
:  # don't reload if already loaded 
2061                     self
._projectChoice
.SetSelection(i
) 
2062                     self
.LoadProject(document
) 
2066     def GetSelectedFile(self
): 
2067         for item 
in self
._treeCtrl
.GetSelections(): 
2068             filePath 
= self
._GetItemFilePath
(item
) 
2074     def GetSelectedFiles(self
): 
2076         for item 
in self
._treeCtrl
.GetSelections(): 
2077             filePath 
= self
._GetItemFilePath
(item
) 
2078             if filePath 
and filePath 
not in filePaths
: 
2079                 filePaths
.append(filePath
) 
2083     def GetSelectedPhysicalFolder(self
): 
2084         if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2087             for item 
in self
._treeCtrl
.GetSelections(): 
2088                 if not self
._IsItemFile
(item
): 
2089                     filePath 
= self
._GetItemFolderPath
(item
) 
2095     def GetSelectedProject(self
): 
2096         document 
= self
.GetDocument() 
2098             return document
.GetFilename() 
2103     def AddProjectToView(self
, document
): 
2104         i 
= self
._projectChoice
.Append(self
._MakeProjectName
(document
), document
) 
2105         self
._projectChoice
.SetSelection(i
) 
2106         self
.OnProjectSelect() 
2109     def LoadProject(self
, document
): 
2110         wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
2111         self
._treeCtrl
.Freeze() 
2114             rootItem 
= self
._treeCtrl
.GetRootItem() 
2115             self
._treeCtrl
.DeleteChildren(rootItem
) 
2118                 mode 
= self
.GetMode() 
2119                 docFilePath 
= document
.GetFilename() 
2121                 if mode 
== ProjectView
.LOGICAL_MODE
: 
2122                     folders 
= document
.GetModel().logicalFolders
 
2124                     folders 
= document
.GetModel().physicalFolders
 
2128                 for folderPath 
in folders
: 
2129                     folderItems 
= folderItems 
+ self
._treeCtrl
.AddFolder(folderPath
) 
2131                 for file in document
.GetModel()._files
: 
2132                     if mode 
== ProjectView
.LOGICAL_MODE
: 
2133                         folder 
= file.logicalFolder
 
2135                         folder 
= file.physicalFolder
 
2137                         folderTree 
= folder
.split('/') 
2140                         for folderName 
in folderTree
: 
2142                             (child
, cookie
) = self
._treeCtrl
.GetFirstChild(item
) 
2144                                 if self
._treeCtrl
.GetItemText(child
) == folderName
: 
2148                                 (child
, cookie
) = self
._treeCtrl
.GetNextChild(item
, cookie
) 
2151                                 print "error folder '%s' not found for %s" % (folder
, file.filePath
) 
2156                     fileItem 
= self
._treeCtrl
.AppendItem(item
, os
.path
.basename(file.filePath
), file) 
2158                 self
._treeCtrl
.SortChildren(rootItem
) 
2159                 for item 
in folderItems
: 
2160                     self
._treeCtrl
.SortChildren(item
) 
2162                 self
.LoadFolderState() 
2164                 self
._treeCtrl
.SetFocus() 
2165                 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(self
._treeCtrl
.GetRootItem()) 
2167                     self
._treeCtrl
.UnselectAll() 
2168                     self
._treeCtrl
.SelectItem(child
) 
2169                     self
._treeCtrl
.ScrollTo(child
) 
2171                 if self
._embeddedWindow
: 
2172                     document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
2175             self
._treeCtrl
.Thaw() 
2176             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
2179     def ProjectHasFocus(self
): 
2180         """ Does Project Choice have focus """ 
2181         return (wx
.Window
.FindFocus() == self
._projectChoice
) 
2184     def FilesHasFocus(self
): 
2185         """ Does Project Tree have focus """ 
2186         winWithFocus 
= wx
.Window
.FindFocus() 
2187         if not winWithFocus
: 
2190             if winWithFocus 
== self
._treeCtrl
: 
2192             winWithFocus 
= winWithFocus
.GetParent() 
2196     def ClearFolderState(self
): 
2197         config 
= wx
.ConfigBase_Get() 
2198         config
.DeleteGroup(getProjectKeyName(self
.GetDocument().GetFilename())) 
2201     def SaveFolderState(self
, event
=None): 
2202         """ Save the open/close state of folders """ 
2208         folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2209         for item 
in folderItemList
: 
2210             if self
._treeCtrl
.IsExpanded(item
): 
2211                 folderList
.append(self
._GetItemFolderPath
(item
)) 
2213         config 
= wx
.ConfigBase_Get() 
2214         config
.Write(getProjectKeyName(self
.GetDocument().GetFilename(), self
.GetMode()), repr(folderList
)) 
2217     def LoadFolderState(self
): 
2218         """ Load the open/close state of folders. """ 
2219         self
._loading 
= True 
2221         config 
= wx
.ConfigBase_Get() 
2222         openFolderData 
= config
.Read(getProjectKeyName(self
.GetDocument().GetFilename(), self
.GetMode()), "") 
2224             folderList 
= eval(openFolderData
) 
2226             folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2227             for item 
in folderItemList
: 
2228                 folderPath 
= self
._GetItemFolderPath
(item
) 
2229                 if folderPath 
in folderList
: 
2230                     self
._treeCtrl
.Expand(item
) 
2232                     self
._treeCtrl
.Collapse(item
) 
2235             projectService 
= wx
.GetApp().GetService(ProjectService
) 
2237             folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2238             for item 
in folderItemList
: 
2239                 folderPath 
= self
._GetItemFolderPath
(item
) 
2240                 if projectService
.FindLogicalViewFolderCollapsedDefault(folderPath
):  # get default initial state 
2241                     self
._treeCtrl
.Collapse(item
) 
2243                     self
._treeCtrl
.Expand(item
) 
2245         self
._loading 
= False 
2248     #---------------------------------------------------------------------------- 
2250     #---------------------------------------------------------------------------- 
2252     def OnProperties(self
, event
): 
2253         if self
.ProjectHasFocus(): 
2254             self
.OnProjectProperties(event
) 
2255         elif self
.FilesHasFocus(): 
2256             items 
= self
._treeCtrl
.GetSelections() 
2260             filePath 
= self
._GetItemFilePath
(item
) 
2262                 filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
2263                 filePropertiesService
.ShowPropertiesDialog(filePath
) 
2266     def OnProjectProperties(self
, event
): 
2267         if self
.GetDocument(): 
2268             dlg 
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
.GetDocument()) 
2269             dlg
.CenterOnParent() 
2272                 if dlg
.ShowModal() == wx
.ID_OK
: 
2273                     if hasattr(dlg
, "_appInfoCtrl") and dlg
._appInfoCtrl
._grid
.IsCellEditControlShown():  # for Linux 
2274                         dlg
._appInfoCtrl
._grid
.DisableCellEditControl()  # If editor is still active, force it to finish the edit before setting the new model. 
2276                     homeDir 
= dlg
._homeDirCtrl
.GetValue() 
2278                         if homeDir 
== ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
: 
2280                         if homeDir 
and not os
.path
.isdir(homeDir
): 
2281                             wx
.MessageBox(_("Home Dir '%s' does not exist.  Please specify a valid directory.") % homeDir
, 
2282                                         _("Project Properties"), 
2283                                         wx
.OK | wx
.ICON_EXCLAMATION
) 
2285                             if self
.GetDocument().GetModel()._homeDir 
!= homeDir
:  # don't set it if it hasn't changed 
2286                                 self
.GetDocument().GetModel().homeDir 
= homeDir
 
2287                                 self
.GetDocument().Modify(True) 
2290                         wx
.MessageBox(_("Blank Home Dir.  Please specify a valid directory."), 
2291                                     _("Project Properties"), 
2292                                     wx
.OK | wx
.ICON_EXCLAMATION
) 
2298     def OnAddFolder(self
, event
): 
2299         if self
.GetDocument(): 
2300             items 
= self
._treeCtrl
.GetSelections() 
2303                 if self
._IsItemFile
(item
): 
2304                     item 
= self
._treeCtrl
.GetItemParent(item
) 
2306                 folderDir 
= self
._GetItemFolderPath
(item
) 
2312             folderPath 
= _("%sUntitled") % folderDir
 
2314             while self
._treeCtrl
.FindFolder(folderPath
): 
2316                 folderPath 
= _("%sUntitled%s") % (folderDir
, i
) 
2317             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFolderCommand(self
, self
.GetDocument(), folderPath
)) 
2319             self
._treeCtrl
.UnselectAll() 
2320             item 
= self
._treeCtrl
.FindFolder(folderPath
) 
2321             self
._treeCtrl
.SelectItem(item
) 
2322             self
._treeCtrl
.EnsureVisible(item
) 
2326     def AddFolder(self
, folderPath
): 
2327         self
._treeCtrl
.AddFolder(folderPath
) 
2331     def DeleteFolder(self
, folderPath
): 
2332         item 
= self
._treeCtrl
.FindFolder(folderPath
) 
2333         self
._treeCtrl
.Delete(item
) 
2337     def OnAddFileToProject(self
, event
): 
2338         if wx
.Platform 
== "__WXMSW__" or wx
.Platform 
== "__WXGTK__" or wx
.Platform 
== "__WXMAC__": 
2340             for temp 
in self
.GetDocumentManager()._templates
: 
2341                 if temp
.IsVisible(): 
2343                         descr 
= descr 
+ _('|') 
2344                     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 
2345             descr 
= _("All|*.*|%s") % descr 
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk 
2349         dialog 
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), wildcard
=descr
, style
=wx
.OPEN|wx
.HIDE_READONLY|wx
.MULTIPLE|wx
.CHANGE_DIR
) 
2350         # dialog.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
2351         if dialog
.ShowModal() != wx
.ID_OK
: 
2354         paths 
= dialog
.GetPaths() 
2359             if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2360                 selections 
= self
._treeCtrl
.GetSelections() 
2362                     item 
= selections
[0] 
2363                     if not self
._IsItemFile
(item
): 
2364                         folderPath 
= self
._GetItemFolderPath
(item
) 
2366             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
, folderPath
=folderPath
)) 
2367         self
.Activate()  # after add, should put focus on project editor 
2370     def OnAddDirToProject(self
, event
): 
2371         frame 
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("Add Directory Files to Project"), size
= (320,200)) 
2372         contentSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
2374         flexGridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap
=HALF_SPACE
, hgap
=HALF_SPACE
) 
2375         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER_VERTICAL
, 0) 
2376         lineSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
2377         dirCtrl 
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(250,-1)) 
2378         dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
2379         lineSizer
.Add(dirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND
) 
2380         findDirButton 
= wx
.Button(frame
, -1, _("Browse...")) 
2381         lineSizer
.Add(findDirButton
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, HALF_SPACE
) 
2382         flexGridSizer
.Add(lineSizer
, 1, wx
.EXPAND
) 
2384         def OnBrowseButton(event
): 
2385             dlg 
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
) 
2386             dir = dirCtrl
.GetValue() 
2389             dlg
.CenterOnParent() 
2390             if dlg
.ShowModal() == wx
.ID_OK
: 
2391                 dirCtrl
.SetValue(dlg
.GetPath()) 
2392                 dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
2393                 dirCtrl
.SetInsertionPointEnd() 
2395         wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
) 
2397         visibleTemplates 
= [] 
2398         for template 
in self
.GetDocumentManager()._templates
: 
2399             if template
.IsVisible(): 
2400                 visibleTemplates
.append(template
) 
2404         for template 
in visibleTemplates
: 
2406                 descr 
= descr 
+ _('|') 
2407             descr 
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")") 
2408             choices
.append(descr
) 
2409         choices
.insert(0, _("All"))  # first item 
2410         filterChoice 
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
) 
2411         filterChoice
.SetSelection(0) 
2412         filterChoice
.SetToolTipString(_("Select file type filter.")) 
2413         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
) 
2414         flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
) 
2416         contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
) 
2418         subfolderCtrl 
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories")) 
2419         subfolderCtrl
.SetValue(True) 
2420         contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
) 
2422         buttonSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
2423         findBtn 
= wx
.Button(frame
, wx
.ID_OK
, _("Add")) 
2424         findBtn
.SetDefault() 
2425         buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
) 
2426         buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0) 
2427         contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
) 
2429         frame
.SetSizer(contentSizer
) 
2432         frame
.CenterOnParent() 
2433         status 
= frame
.ShowModal() 
2436         while status 
== wx
.ID_OK 
and not passedCheck
: 
2437             if not os
.path
.exists(dirCtrl
.GetValue()): 
2438                 dlg 
= wx
.MessageDialog(frame
, 
2439                                        _("'%s' does not exist.") % dirCtrl
.GetValue(), 
2440                                        _("Find in Directory"), 
2441                                        wx
.OK | wx
.ICON_EXCLAMATION
 
2443                 dlg
.CenterOnParent() 
2447                 status 
= frame
.ShowModal() 
2453         if status 
== wx
.ID_OK
: 
2454             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
2457                 doc 
= self
.GetDocument() 
2458                 searchSubfolders 
= subfolderCtrl
.IsChecked() 
2459                 dirString 
= dirCtrl
.GetValue() 
2461                 if os
.path
.isfile(dirString
): 
2462                     # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter. 
2463                     # We'll assume they know what they're doing. 
2468                     index 
= filterChoice
.GetSelection() 
2469                     lastIndex 
= filterChoice
.GetCount()-1 
2470                     if index 
and index 
!= lastIndex
:  # if not All or Any 
2471                         template 
= visibleTemplates
[index
-1] 
2473                     # do search in files on disk 
2474                     for root
, dirs
, files 
in os
.walk(dirString
): 
2475                         if not searchSubfolders 
and root 
!= dirString
: 
2479                             if index 
== 0:  # All 
2480                                 filename 
= os
.path
.join(root
, name
) 
2481                                 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2482                                 if not doc
.IsFileInProject(filename
): 
2483                                     paths
.append(filename
) 
2484                             else:  # use selected filter 
2485                                 if template
.FileMatchesTemplate(name
): 
2486                                     filename 
= os
.path
.join(root
, name
) 
2487                                     # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2488                                     if not doc
.IsFileInProject(filename
): 
2489                                         paths
.append(filename
) 
2492                 if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2493                     selections 
= self
._treeCtrl
.GetSelections() 
2495                         item 
= selections
[0] 
2496                         if not self
._IsItemFile
(item
): 
2497                             folderPath 
= self
._GetItemFolderPath
(item
) 
2499                 doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
, folderPath
=folderPath
)) 
2500                 self
.Activate()  # after add, should put focus on project editor 
2503                 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
2506     def DoAddFilesToProject(self
, filePaths
, folderPath
): 
2507         # method used by Drag-n-Drop to add files to current Project 
2508         self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filePaths
, folderPath
)) 
2511     def OnFocus(self
, event
): 
2512         self
.GetDocumentManager().ActivateView(self
) 
2516     def OnKillFocus(self
, event
): 
2517         # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame 
2518         # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame 
2519         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 
2520             topWindow 
= wx
.GetApp().GetTopWindow() 
2521             # wxBug: On Mac, this event can fire during shutdown, even after GetTopWindow() 
2522             # is set to NULL. So make sure we have a TLW before getting the active child. 
2524                 childFrame 
= topWindow
.GetActiveChild() 
2526                     childFrame
.Activate() 
2530     def OnLeftClick(self
, event
): 
2532             wxBug: We also spurious drag events on a single click of on item that is already selected, 
2533             so the solution was to consume the left click event.  But his broke the single click expand/collapse 
2534             of a folder, so if it is a folder, we do an event.Skip() to allow the expand/collapse, 
2535             otherwise we consume the event. 
2537         # if folder let it collapse/expand 
2538         if wx
.Platform 
== '__WXMSW__': 
2539             item
, flags 
= self
._treeCtrl
.HitTest(event
.GetPosition()) 
2540             if item
.IsOk() and self
._treeCtrl
.GetChildrenCount(item
, False): 
2545     def OnRightClick(self
, event
): 
2547         if not self
.GetSelectedProject(): 
2550         if self
._HasFilesSelected
():  # Files context 
2551             menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection")) 
2552             menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True) 
2553             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
) 
2555             extService 
= wx
.GetApp().GetService(ExtensionService
.ExtensionService
) 
2556             if extService 
and extService
.GetExtensions(): 
2558                 for ext 
in extService
.GetExtensions(): 
2559                     if not ext
.opOnSelectedFile
: 
2562                         menu
.AppendSeparator() 
2564                     menu
.Append(ext
.id, ext
.menuItemName
) 
2565                     wx
.EVT_MENU(self
._GetParentFrame
(), ext
.id, extService
.ProcessEvent
) 
2566                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ext
.id, extService
.ProcessUpdateUIEvent
) 
2569             for item 
in self
._treeCtrl
.GetSelections(): 
2570                 if self
._IsItemProcessModelFile
(item
): 
2571                     itemIDs 
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None] 
2573         else:  # Project context 
2575         menuBar 
= self
._GetParentFrame
().GetMenuBar() 
2576         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
] 
2577         svnIDs 
= [SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
2579             itemIDs 
= itemIDs 
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
2580         globalIDs 
= [wx
.ID_UNDO
, wx
.ID_REDO
, wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
] 
2581         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
] 
2582         for itemID 
in itemIDs
: 
2584                 menu
.AppendSeparator() 
2586                 if itemID 
== ProjectService
.RUN_SELECTED_PM_ID 
and not ACTIVEGRID_BASE_IDE
: 
2587                     webBrowserService 
= wx
.GetApp().GetService(WebBrowserService
.WebBrowserService
) 
2588                     if webBrowserService
: 
2589                         if wx
.Platform 
== '__WXMSW__': 
2590                             menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process")) 
2591                             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.ProjectServiceProcessEvent
) 
2593                         if wx
.Platform 
== '__WXMSW__': 
2594                             menuLabel 
= _("Run Process in External Browser") 
2596                             menuLabel 
= _("Run Process") 
2597                         menu
.Append(ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
, menuLabel
) 
2598                         wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
, self
.ProjectServiceProcessEvent
) 
2600                         if wx
.Platform 
== '__WXMSW__': 
2602                             if wx
.GetApp().GetUseTabbedMDI(): 
2603                                 menuLabel 
= _("Run Process in new Tab") 
2605                                 menuLabel 
= _("Run Process in new Window") 
2606                             menu
.Append(ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
, menuLabel
) 
2607                             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
, self
.ProjectServiceProcessEvent
) 
2609                 elif itemID 
== ProjectService
.REMOVE_FROM_PROJECT
: 
2610                     menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project")) 
2611                     wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
) 
2612                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
) 
2614                     item 
= menuBar
.FindItemById(itemID
) 
2617                             svnService 
= wx
.GetApp().GetService(SVNService
.SVNService
) 
2619                         if itemID 
in svnIDs
: 
2620                             if SVN_INSTALLED 
and svnService
: 
2621                                 wx
.EVT_MENU(self
._GetParentFrame
(), itemID
, svnService
.ProcessEvent
) 
2622                         elif itemID 
in globalIDs
: 
2625                             wx
.EVT_MENU(self
._treeCtrl
, itemID
, self
.ProcessEvent
) 
2626                         menu
.Append(itemID
, item
.GetLabel()) 
2627         self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY())) 
2631     def ProjectServiceProcessEvent(self
, event
): 
2632         projectService 
= wx
.GetApp().GetService(ProjectService
) 
2634             projectService
.ProcessEvent(event
) 
2637     def OnRename(self
, event
=None): 
2638         items 
= self
._treeCtrl
.GetSelections() 
2642         if wx
.Platform 
== "__WXGTK__": 
2643             dlg 
= wx
.TextEntryDialog(self
.GetFrame(), _("Enter New Name"), _("Enter New Name")) 
2644             dlg
.CenterOnParent() 
2645             if dlg
.ShowModal() == wx
.ID_OK
: 
2646                 text 
= dlg
.GetValue() 
2647                 self
.ChangeLabel(item
, text
) 
2650                 self
._treeCtrl
.EditLabel(item
) 
2653     def OnBeginLabelEdit(self
, event
): 
2654         self
._editingSoDontKillFocus 
= True 
2655         item 
= event
.GetItem() 
2656         if self
._IsItemFile
(item
): 
2657             file = self
._GetItemFile
(item
) 
2658             if file.type == 'xform': 
2660         if (self
.GetMode() == ProjectView
.PHYSICAL_MODE
) and not self
._IsItemFile
(item
): 
2664     def OnEndLabelEdit(self
, event
): 
2665         self
._editingSoDontKillFocus 
= False 
2666         item 
= event
.GetItem() 
2667         newName 
= event
.GetLabel() 
2668         if not self
.ChangeLabel(item
, newName
): 
2672     def ChangeLabel(self
, item
, newName
): 
2675         if self
._IsItemFile
(item
): 
2676             oldFilePath 
= self
._GetItemFilePath
(item
) 
2677             newFilePath 
= os
.path
.join(os
.path
.dirname(oldFilePath
), newName
) 
2678             doc 
= self
.GetDocument() 
2679             if not doc
.GetCommandProcessor().Submit(ProjectRenameFileCommand(doc
, oldFilePath
, newFilePath
)): 
2681             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
2683             oldFolderPath 
= self
._GetItemFolderPath
(item
) 
2684             newFolderPath 
= os
.path
.dirname(oldFolderPath
) 
2686                 newFolderPath 
+= "/" 
2687             newFolderPath 
+= newName
 
2688             if self
._treeCtrl
.FindFolder(newFolderPath
): 
2689                 wx
.MessageBox(_("Folder '%s' already exists.") % newName
, 
2691                             wx
.OK | wx
.ICON_EXCLAMATION
, 
2694             doc 
= self
.GetDocument() 
2695             if not doc
.GetCommandProcessor().Submit(ProjectRenameFolderCommand(doc
, oldFolderPath
, newFolderPath
)): 
2697             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
2703         # wxBug: Should be able to use IsSupported/IsSupportedFormat here 
2704         #fileDataObject = wx.FileDataObject() 
2705         #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject) 
2706         hasFilesInClipboard 
= False 
2707         if not wx
.TheClipboard
.IsOpened(): 
2708             if wx
.TheClipboard
.Open(): 
2709                 fileDataObject 
= wx
.FileDataObject() 
2710                 hasFilesInClipboard 
= wx
.TheClipboard
.GetData(fileDataObject
) 
2711                 wx
.TheClipboard
.Close() 
2712         return hasFilesInClipboard
 
2715     def OnCut(self
, event
): 
2720     def OnCopy(self
, event
): 
2721         fileDataObject 
= wx
.FileDataObject() 
2722         items 
= self
._treeCtrl
.GetSelections() 
2724             filePath 
= self
._GetItemFilePath
(item
) 
2726                 fileDataObject
.AddFile(filePath
) 
2727         if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open(): 
2728             wx
.TheClipboard
.SetData(fileDataObject
) 
2729             wx
.TheClipboard
.Close() 
2732     def OnPaste(self
, event
): 
2733         if wx
.TheClipboard
.Open(): 
2734             fileDataObject 
= wx
.FileDataObject() 
2735             if wx
.TheClipboard
.GetData(fileDataObject
): 
2737                 if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2738                     items 
= self
._treeCtrl
.GetSelections() 
2742                             folderPath 
= self
._GetItemFolderPath
(item
) 
2743                 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames(), folderPath
)) 
2744             wx
.TheClipboard
.Close() 
2747     def OnClear(self
, event
): 
2748         if self
._HasFilesSelected
(): 
2749             items 
= self
._treeCtrl
.GetSelections() 
2752                 file = self
._GetItemFile
(item
) 
2755             self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self
.GetDocument(), files
)) 
2757         elif self
._HasFoldersSelected
(): 
2758             items 
= self
._treeCtrl
.GetSelections() 
2760             if self
._treeCtrl
.GetChildrenCount(item
, False): 
2761                 wx
.MessageBox(_("Cannot remove folder '%s'.  Folder is not empty.") % self
._treeCtrl
.GetItemText(item
), 
2763                               wx
.OK | wx
.ICON_EXCLAMATION
, 
2767             folderPath 
= self
._GetItemFolderPath
(item
) 
2768             self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFolderCommand(self
, self
.GetDocument(), folderPath
)) 
2771     def OnDeleteFile(self
, event
): 
2772         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
2773                                  _("Delete cannot be reversed.\n\nRemove the selected files from the\nproject and file system permanently?"), 
2775                                  wx
.YES_NO|wx
.ICON_QUESTION
) 
2776         yesNoMsg
.CenterOnParent() 
2777         status 
= yesNoMsg
.ShowModal() 
2779         if status 
== wx
.ID_NO
: 
2782         items 
= self
._treeCtrl
.GetSelections() 
2785             filePath 
= self
._GetItemFilePath
(item
) 
2786             if filePath 
and filePath 
not in delFiles
: 
2787                 delFiles
.append(filePath
) 
2789         # remove selected files from project 
2790         self
.GetDocument().RemoveFiles(delFiles
) 
2792         # remove selected files from file system 
2793         for filePath 
in delFiles
: 
2794             if os
.path
.exists(filePath
): 
2798                     wx
.MessageBox("Could not delete '%s'.  %s" % (os
.path
.basename(filePath
), sys
.exc_value
), 
2800                                   wx
.OK | wx
.ICON_EXCLAMATION
, 
2803     def OnDeleteProject(self
, event
=None, noPrompt
=False, closeFiles
=True, delFiles
=True): 
2805         class DeleteProjectDialog(wx
.Dialog
): 
2807             def __init__(self
, parent
, doc
): 
2808                 wx
.Dialog
.__init
__(self
, parent
, -1, _("Delete Project"), size 
= (310, 330)) 
2810                 sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
2811                 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
) 
2812                 self
._delFilesCtrl 
= wx
.CheckBox(self
, -1, _("Delete all files in project")) 
2813                 self
._delFilesCtrl
.SetValue(True) 
2814                 self
._delFilesCtrl
.SetToolTipString(_("Deletes files from disk, whether open or closed")) 
2815                 sizer
.Add(self
._delFilesCtrl
, 0, wx
.LEFT|wx
.RIGHT|wx
.BOTTOM
, SPACE
) 
2816                 self
._closeDeletedCtrl 
= wx
.CheckBox(self
, -1, _("Close open files belonging to project")) 
2817                 self
._closeDeletedCtrl
.SetValue(True) 
2818                 self
._closeDeletedCtrl
.SetToolTipString(_("Closes open editors for files belonging to project")) 
2819                 sizer
.Add(self
._closeDeletedCtrl
, 0, wx
.LEFT|wx
.RIGHT|wx
.BOTTOM
, SPACE
) 
2821                 sizer
.Add(self
.CreateButtonSizer(wx
.OK | wx
.CANCEL
), 0, wx
.ALIGN_RIGHT|wx
.RIGHT|wx
.LEFT|wx
.BOTTOM
, SPACE
) 
2823                 self
.SetSizer(sizer
) 
2827         doc 
= self
.GetDocument() 
2829             dlg 
= DeleteProjectDialog(self
.GetFrame(), doc
) 
2830             dlg
.CenterOnParent() 
2831             status 
= dlg
.ShowModal() 
2832             delFiles 
= dlg
._delFilesCtrl
.GetValue() 
2833             closeFiles 
= dlg
._closeDeletedCtrl
.GetValue() 
2835             if status 
== wx
.ID_CANCEL
: 
2838         if closeFiles 
or delFiles
: 
2839             filesInProject 
= doc
.GetFiles() 
2840             deploymentFilePath 
= self
.GetDocument().GetDeploymentFilepath() 
2841             if deploymentFilePath
: 
2842                 filesInProject
.append(deploymentFilePath
)  # remove deployment file also. 
2843                 import activegrid
.server
.secutils 
as secutils
 
2844                 keystoreFilePath 
= os
.path
.join(os
.path
.dirname(deploymentFilePath
), secutils
.AGKEYSTORE_FILENAME
) 
2845                 filesInProject
.append(keystoreFilePath
)  # remove keystore file also. 
2847             # don't remove self prematurely 
2848             filePath 
= doc
.GetFilename() 
2849             if filePath 
in filesInProject
: 
2850                 filesInProject
.remove(filePath
) 
2852             # don't close/delete files outside of project's directory 
2853             homeDir 
= doc
.GetModel().homeDir 
+ os
.sep
 
2854             for filePath 
in filesInProject
[:]: 
2855                 fileDir 
= os
.path
.dirname(filePath
) + os
.sep
 
2856                 if not fileDir
.startswith(homeDir
):   
2857                     filesInProject
.remove(filePath
) 
2860             # close any open views of documents in the project 
2861             openDocs 
= self
.GetDocumentManager().GetDocuments()[:]  # need copy or docs shift when closed 
2863                 if d
.GetFilename() in filesInProject
: 
2864                     d
.Modify(False)  # make sure it doesn't ask to save the file 
2865                     if isinstance(d
.GetDocumentTemplate(), ProjectTemplate
):  # if project, remove from project list drop down 
2866                         if self
.GetDocumentManager().CloseDocument(d
, True): 
2867                             self
.RemoveProjectUpdate(d
) 
2868                     else:  # regular file 
2869                         self
.GetDocumentManager().CloseDocument(d
, True) 
2871         # remove files in project from file system 
2874             for filePath 
in filesInProject
: 
2875                 if os
.path
.isfile(filePath
): 
2877                         dirPath 
= os
.path
.dirname(filePath
) 
2878                         if dirPath 
not in dirPaths
: 
2879                             dirPaths
.append(dirPath
) 
2883                         wx
.MessageBox("Could not delete file '%s'.\n%s" % (filePath
, sys
.exc_value
), 
2884                                       _("Delete Project"), 
2885                                       wx
.OK | wx
.ICON_EXCLAMATION
, 
2888         filePath 
= doc
.GetFilename() 
2890         self
.ClearFolderState()  # remove from registry folder settings 
2894             doc
.Modify(False)  # make sure it doesn't ask to save the project 
2895             if self
.GetDocumentManager().CloseDocument(doc
, True): 
2896                 self
.RemoveCurrentDocumentUpdate() 
2898         # remove project file 
2900             dirPath 
= os
.path
.dirname(filePath
) 
2901             if dirPath 
not in dirPaths
: 
2902                 dirPaths
.append(dirPath
) 
2903         if os
.path
.isfile(filePath
): 
2907                 wx
.MessageBox("Could not delete project file '%s'.\n%s" % (filePath
, sys
.exc_value
), 
2908                               _("Delete Prjoect"), 
2909                               wx
.OK | wx
.ICON_EXCLAMATION
, 
2912         # remove empty directories from file system 
2914             dirPaths
.sort()     # sorting puts parent directories ahead of child directories 
2915             dirPaths
.reverse()  # remove child directories first 
2917             for dirPath 
in dirPaths
: 
2918                 if os
.path
.isdir(dirPath
): 
2919                     files 
= os
.listdir(dirPath
) 
2924                             wx
.MessageBox("Could not delete empty directory '%s'.\n%s" % (dirPath
, sys
.exc_value
), 
2925                                           _("Delete Project"), 
2926                                           wx
.OK | wx
.ICON_EXCLAMATION
, 
2930     def OnKeyPressed(self
, event
): 
2931         key 
= event
.KeyCode() 
2932         if key 
== wx
.WXK_DELETE
: 
2938     def OnSelectAll(self
, event
): 
2939         project 
= self
.GetDocument() 
2941             self
.DoSelectAll(self
._treeCtrl
.GetRootItem()) 
2944     def DoSelectAll(self
, parentItem
): 
2945         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
2947             if self
._IsItemFile
(child
): 
2948                 self
._treeCtrl
.SelectItem(child
) 
2950                 self
.DoSelectAll(child
) 
2951             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
2954     def OnOpenSelectionSDI(self
, event
): 
2955         # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window 
2956         wx
.CallAfter(self
.OnOpenSelection
, None) 
2959     def OnOpenSelection(self
, event
): 
2962             items 
= self
._treeCtrl
.GetSelections()[:] 
2964                 filepath 
= self
._GetItemFilePath
(item
) 
2966                     if not os
.path
.exists(filepath
): 
2967                         msgTitle 
= wx
.GetApp().GetAppName() 
2969                             msgTitle 
= _("File Not Found") 
2970                         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
2971                                       _("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
)), 
2973                                       wx
.YES_NO|wx
.ICON_QUESTION
 
2975                         yesNoMsg
.CenterOnParent() 
2976                         status 
= yesNoMsg
.ShowModal() 
2978                         if status 
== wx
.ID_NO
: 
2980                         findFileDlg 
= wx
.FileDialog(self
.GetFrame(), 
2982                                                  defaultFile
=wx
.lib
.docview
.FileNameFromPath(filepath
), 
2983                                                  style
=wx
.OPEN|wx
.FILE_MUST_EXIST|wx
.CHANGE_DIR
 
2985                         # findFileDlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
2986                         if findFileDlg
.ShowModal() == wx
.ID_OK
: 
2987                             newpath 
= findFileDlg
.GetPath() 
2990                         findFileDlg
.Destroy() 
2992                             # update Project Model with new location 
2993                             self
.GetDocument().UpdateFilePath(filepath
, newpath
) 
2996                     doc 
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
2997                     if not doc 
and filepath
.endswith(PROJECT_EXTENSION
):  # project already open 
2998                         self
.SetProject(filepath
) 
3000                         AddProjectMapping(doc
) 
3003         except IOError, (code
, message
): 
3004             msgTitle 
= wx
.GetApp().GetAppName() 
3006                 msgTitle 
= _("File Error") 
3007             wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
), 
3009                           wx
.OK | wx
.ICON_EXCLAMATION
, 
3013     #---------------------------------------------------------------------------- 
3014     # Convenience methods 
3015     #---------------------------------------------------------------------------- 
3017     def _HasFiles(self
): 
3018         if not self
._treeCtrl
: 
3020         return self
._treeCtrl
.GetCount() > 1    #  1 item = root item, don't count as having files 
3023     def _HasFilesSelected(self
): 
3024         if not self
._treeCtrl
: 
3026         items 
= self
._treeCtrl
.GetSelections() 
3030             if self
._IsItemFile
(item
): 
3035     def _HasFoldersSelected(self
): 
3036         if not self
._treeCtrl
: 
3038         items 
= self
._treeCtrl
.GetSelections() 
3042             if self
._IsItemFile
(item
): 
3047     def _MakeProjectName(self
, project
): 
3048         return project
.GetPrintableName() 
3051     def _GetItemFilePath(self
, item
): 
3052         file = self
._GetItemFile
(item
) 
3054             return file.filePath
 
3059     def _GetItemFolderPath(self
, item
): 
3060         rootItem 
= self
._treeCtrl
.GetRootItem() 
3061         if item 
== rootItem
: 
3064         if self
._IsItemFile
(item
): 
3065             item 
= self
._treeCtrl
.GetItemParent(item
) 
3068         while item 
!= rootItem
: 
3070                 folderPath 
= self
._treeCtrl
.GetItemText(item
) + "/" + folderPath
 
3072                 folderPath 
= self
._treeCtrl
.GetItemText(item
) 
3073             item 
= self
._treeCtrl
.GetItemParent(item
) 
3078     def _GetItemFile(self
, item
): 
3079         return self
._treeCtrl
.GetPyData(item
) 
3082     def _IsItemFile(self
, item
): 
3083         return self
._GetItemFile
(item
) != None 
3086     def _IsItemProcessModelFile(self
, item
): 
3087         if ACTIVEGRID_BASE_IDE
: 
3090         if self
._IsItemFile
(item
): 
3091             filepath 
= self
._GetItemFilePath
(item
) 
3093             for template 
in self
.GetDocumentManager().GetTemplates(): 
3094                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3095                     ext 
= template
.GetDefaultExtension() 
3100             if filepath
.endswith(ext
): 
3106     def _GetChildItems(self
, parentItem
): 
3108         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
3110             children
.append(child
) 
3111             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
3115     def _GetFolderItems(self
, parentItem
): 
3117         childrenItems 
= self
._GetChildItems
(parentItem
) 
3118         for childItem 
in childrenItems
: 
3119             if not self
._IsItemFile
(childItem
): 
3120                 folderItems
.append(childItem
) 
3121                 folderItems 
+= self
._GetFolderItems
(childItem
) 
3125 class ProjectFileDropTarget(wx
.FileDropTarget
): 
3127     def __init__(self
, view
): 
3128         wx
.FileDropTarget
.__init
__(self
) 
3132     def OnDropFiles(self
, x
, y
, filePaths
): 
3133         """ Do actual work of dropping files into project """ 
3134         if self
._view
.GetDocument(): 
3136             if self
._view
.GetMode() == ProjectView
.LOGICAL_MODE
: 
3137                 folderItem 
= self
._view
._treeCtrl
.FindClosestFolder(x
,y
) 
3139                     folderPath 
= self
._view
._GetItemFolderPath
(folderItem
) 
3140             self
._view
.DoAddFilesToProject(filePaths
, folderPath
) 
3145     def OnDragOver(self
, x
, y
, default
): 
3146         """ Feedback to show copy cursor if copy is allowed """ 
3147         if self
._view
.GetDocument():  # only allow drop if project exists 
3152 class ProjectPropertiesDialog(wx
.Dialog
): 
3153     RELATIVE_TO_PROJECT_FILE 
= _("relative to project file") 
3155     def __init__(self
, parent
, document
): 
3156         wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size 
= (310, 330)) 
3158         filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
3160         notebook 
= wx
.Notebook(self
, -1) 
3162         tab 
= wx
.Panel(notebook
, -1) 
3163         gridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap 
= SPACE
, hgap 
= SPACE
) 
3164         gridSizer
.AddGrowableCol(1) 
3165         gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:"))) 
3166         filename 
= document
.GetFilename() 
3167         if os
.path
.isfile(filename
): 
3168             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1])) 
3170             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:"))) 
3171             gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.dirname(filename
), length
=50))) 
3173             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:"))) 
3174             gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes"))) 
3176             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
3177             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
3178             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
) 
3180             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
3181             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
3182             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
) 
3184             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:"))) 
3185             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
)))) 
3187             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:"))) 
3188             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
)))) 
3190             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:"))) 
3191             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
)))) 
3193             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]"))) 
3194         spacerGrid 
= wx
.BoxSizer(wx
.HORIZONTAL
)  # add a border around the inside of the tab 
3195         spacerGrid
.Add(gridSizer
, 1, wx
.ALL|wx
.EXPAND
, SPACE
); 
3196         tab
.SetSizer(spacerGrid
) 
3197         notebook
.AddPage(tab
, _("General")) 
3199         tab 
= wx
.Panel(notebook
, -1) 
3200         spacerGrid 
= wx
.BoxSizer(wx
.VERTICAL
)  # add a border around the inside of the tab 
3201         homePathLabel 
= wx
.StaticText(tab
, -1, _("Home Dir:")) 
3202         if document
.GetModel().isDefaultHomeDir
: 
3203             defaultHomeDir 
= ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
 
3205             defaultHomeDir 
= document
.GetModel().homeDir
 
3206         self
._homeDirCtrl 
= wx
.ComboBox(tab
, -1, defaultHomeDir
, size
=(125,-1), choices
=[ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
, document
.GetModel().homeDir
]) 
3207         self
._homeDirCtrl
.SetToolTipString(self
._homeDirCtrl
.GetValue())  
3208         if not document
.GetModel().isDefaultHomeDir
: 
3209             self
._homeDirCtrl
.SetInsertionPointEnd() 
3210         def OnDirChanged(event
): 
3211             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 
3212         wx
.EVT_COMBOBOX(self
._homeDirCtrl
, -1, OnDirChanged
) 
3213         wx
.EVT_TEXT(self
._homeDirCtrl
, -1, OnDirChanged
) 
3214         choosePathButton 
= wx
.Button(tab
, -1, _("Browse...")) 
3215         def OnBrowseButton(event
): 
3216             if self
._homeDirCtrl
.GetValue() == ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
: 
3217                 defaultHomeDir 
= document
.GetModel().homeDir
 
3219                 defaultHomeDir 
= self
._homeDirCtrl
.GetValue() 
3221             dlg 
= wx
.DirDialog(self
, "Choose a directory:", defaultHomeDir
, 
3222                               style
=wx
.DD_DEFAULT_STYLE|wx
.DD_NEW_DIR_BUTTON
) 
3223             if dlg
.ShowModal() == wx
.ID_OK
: 
3224                 self
._homeDirCtrl
.SetValue(dlg
.GetPath()) 
3225                 self
._homeDirCtrl
.SetInsertionPointEnd() 
3226                 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 
3228         wx
.EVT_BUTTON(choosePathButton
, -1, OnBrowseButton
) 
3229         pathSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3230         pathSizer
.Add(homePathLabel
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
3231         pathSizer
.Add(self
._homeDirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND|wx
.LEFT
, HALF_SPACE
) 
3232         pathSizer
.Add(choosePathButton
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.LEFT
, SPACE
) 
3233         spacerGrid
.Add(pathSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
); 
3234         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.")) 
3235         spacerGrid
.Add(instructionText
, 0, wx
.ALL
, SPACE
); 
3236         tab
.SetSizer(spacerGrid
) 
3237         notebook
.AddPage(tab
, _("Physical View")) 
3239         if wx
.Platform 
== "__WXMSW__": 
3240             notebook
.SetPageSize((310,300)) 
3242         if not ACTIVEGRID_BASE_IDE
: 
3243             tab 
= wx
.Panel(notebook
, -1) 
3244             self
._appInfoCtrl 
= PropertyService
.PropertyCtrl(tab
, header
=False) 
3245             self
._appInfoCtrl
.SetDocument(document
) 
3246             self
._appInfoCtrl
.SetModel(document
.GetAppInfo()) 
3247             sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3248             sizer
.Add(self
._appInfoCtrl
, 1, wx
.EXPAND|wx
.ALL
, PropertyService
.LEAVE_MARGIN
) 
3250             notebook
.AddPage(tab
, _("App Info")) 
3251             self
._appInfoCtrl
._grid
.AutoSizeColumns() 
3254         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3255         sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
) 
3256         sizer
.Add(self
.CreateButtonSizer(wx
.OK | wx
.CANCEL
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
) 
3258         self
.SetSizer(sizer
) 
3263 class ProjectOptionsPanel(wx
.Panel
): 
3266     def __init__(self
, parent
, id): 
3267         wx
.Panel
.__init
__(self
, parent
, id) 
3268         self
._useSashMessageShown 
= False 
3269         config 
= wx
.ConfigBase_Get() 
3270         self
._projSaveDocsCheckBox 
= wx
.CheckBox(self
, -1, _("Remember open projects")) 
3271         self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True)) 
3272         projectBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3273         projectSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3274         projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
3275         if not ACTIVEGRID_BASE_IDE
: 
3276             self
._projShowWelcomeCheckBox 
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog")) 
3277             self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog2", True)) 
3278             projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
3280             sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3281             sizer
.Add(wx
.StaticText(self
, -1, _("Default language for projects:")), 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT
, HALF_SPACE
) 
3282             self
._langCtrl 
= wx
.Choice(self
, -1, choices
=projectmodel
.LANGUAGE_LIST
)             
3283             self
._langCtrl
.SetStringSelection(config
.Read(APP_LAST_LANGUAGE
, projectmodel
.LANGUAGE_DEFAULT
)) 
3284             self
._langCtrl
.SetToolTipString(_("Programming language to be used throughout the project.")) 
3285             sizer
.Add(self
._langCtrl
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT
, MAC_RIGHT_BORDER
) 
3286             projectSizer
.Add(sizer
, 0, wx
.ALL
, HALF_SPACE
) 
3288         projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
) 
3289         self
.SetSizer(projectBorderSizer
) 
3291         parent
.AddPage(self
, _("Project")) 
3294     def OnUseSashSelect(self
, event
): 
3295         if not self
._useSashMessageShown
: 
3296             msgTitle 
= wx
.GetApp().GetAppName() 
3298                 msgTitle 
= _("Document Options") 
3299             wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.", 
3301                           wx
.OK | wx
.ICON_INFORMATION
, 
3303             self
._useSashMessageShown 
= True 
3306     def OnOK(self
, optionsDialog
): 
3307         config 
= wx
.ConfigBase_Get() 
3308         config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue()) 
3309         if not ACTIVEGRID_BASE_IDE
: 
3310             config
.WriteInt("RunWelcomeDialog2", self
._projShowWelcomeCheckBox
.GetValue()) 
3311             config
.Write(APP_LAST_LANGUAGE
, self
._langCtrl
.GetStringSelection()) 
3315         return getProjectIcon() 
3318 class ProjectService(Service
.Service
): 
3320     #---------------------------------------------------------------------------- 
3322     #---------------------------------------------------------------------------- 
3323     SHOW_WINDOW 
= wx
.NewId()  # keep this line for each subclass, need unique ID for each Service 
3324     RUN_SELECTED_PM_ID 
= wx
.NewId() 
3325     RUN_SELECTED_PM_INTERNAL_WINDOW_ID 
= wx
.NewId() 
3326     RUN_SELECTED_PM_EXTERNAL_BROWSER_ID 
= wx
.NewId() 
3327     RUN_CURRENT_PM_ID 
= wx
.NewId() 
3328     RUN_CURRENT_PM_INTERNAL_WINDOW_ID 
= wx
.NewId() 
3329     RUN_CURRENT_PM_EXTERNAL_BROWSER_ID 
= wx
.NewId() 
3330     RENAME_ID 
= wx
.NewId() 
3331     OPEN_SELECTION_ID 
= wx
.NewId() 
3332     REMOVE_FROM_PROJECT 
= wx
.NewId() 
3333     DELETE_FILE_ID 
= wx
.NewId() 
3334     ADD_FILES_TO_PROJECT_ID 
= wx
.NewId() 
3335     ADD_CURRENT_FILE_TO_PROJECT_ID 
= wx
.NewId() 
3336     ADD_DIR_FILES_TO_PROJECT_ID 
= wx
.NewId() 
3337     CLOSE_PROJECT_ID 
= wx
.NewId() 
3338     PROJECT_PROPERTIES_ID 
= wx
.NewId() 
3339     ADD_FOLDER_ID 
= wx
.NewId() 
3340     DELETE_PROJECT_ID 
= wx
.NewId() 
3343     #---------------------------------------------------------------------------- 
3344     # Overridden methods 
3345     #---------------------------------------------------------------------------- 
3347     def __init__(self
, serviceName
, embeddedWindowLocation 
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
): 
3348         Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
) 
3349         self
._runHandlers 
= [] 
3350         self
._suppressOpenProjectMessages 
= False 
3351         self
._logicalViewDefaults 
= [] 
3352         self
._logicalViewOpenDefaults 
= [] 
3353         self
._fileTypeDefaults 
= [] 
3354         self
._nameDefaults 
= [] 
3355         self
._mapToProject 
= dict() 
3358     def _CreateView(self
): 
3359         return ProjectView(self
) 
3362     def ShowWindow(self
, show 
= True): 
3363         """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """ 
3364         Service
.Service
.ShowWindow(self
, show
) 
3367             project 
= self
.GetView().GetDocument() 
3369                 self
.OpenSavedProjects() 
3372     #---------------------------------------------------------------------------- 
3373     # Service specific methods 
3374     #---------------------------------------------------------------------------- 
3376     def GetSuppressOpenProjectMessages(self
): 
3377         return self
._suppressOpenProjectMessages
 
3380     def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
): 
3381         self
._suppressOpenProjectMessages 
= suppressOpenProjectMessages
 
3384     def GetRunHandlers(self
): 
3385         return self
._runHandlers
 
3388     def AddRunHandler(self
, runHandler
): 
3389         self
._runHandlers
.append(runHandler
) 
3392     def RemoveRunHandler(self
, runHandler
): 
3393         self
._runHandlers
.remove(runHandler
) 
3396     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
3397         Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
) 
3399         projectMenu 
= wx
.Menu() 
3401 ##            accelTable = wx.AcceleratorTable([ 
3402 ##                eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID")) 
3404 ##            frame.SetAcceleratorTable(accelTable) 
3405         isProjectDocument 
= document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
 
3406         if wx
.GetApp().IsMDI() or isProjectDocument
: 
3407             if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
): 
3408                 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project")) 
3409                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3410                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3411             if not menuBar
.FindItemById(ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
): 
3412                 projectMenu
.Append(ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project")) 
3413                 wx
.EVT_MENU(frame
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3414                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3415             if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
): 
3416                 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project")) 
3417                 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3418                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3419             if not menuBar
.FindItemById(ProjectService
.ADD_FOLDER_ID
): 
3420                 projectMenu
.Append(ProjectService
.ADD_FOLDER_ID
, _("New Folder"), _("Creates a new folder")) 
3421                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FOLDER_ID
, frame
.ProcessEvent
) 
3422                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FOLDER_ID
, frame
.ProcessUpdateUIEvent
) 
3423             if not menuBar
.FindItemById(ProjectService
.CLOSE_PROJECT_ID
): 
3424                 projectMenu
.AppendSeparator() 
3425                 projectMenu
.Append(ProjectService
.CLOSE_PROJECT_ID
, _("Close Project"), _("Closes currently open project")) 
3426                 wx
.EVT_MENU(frame
, ProjectService
.CLOSE_PROJECT_ID
, frame
.ProcessEvent
) 
3427                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.CLOSE_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3428             if not menuBar
.FindItemById(ProjectService
.DELETE_PROJECT_ID
): 
3429                 projectMenu
.Append(ProjectService
.DELETE_PROJECT_ID
, _("Delete Project..."), _("Delete currently open project and its files.")) 
3430                 wx
.EVT_MENU(frame
, ProjectService
.DELETE_PROJECT_ID
, frame
.ProcessEvent
) 
3431                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3432             if not menuBar
.FindItemById(ProjectService
.PROJECT_PROPERTIES_ID
): 
3433                 projectMenu
.AppendSeparator() 
3434                 projectMenu
.Append(ProjectService
.PROJECT_PROPERTIES_ID
, _("Project Properties"), _("Project Properties")) 
3435                 wx
.EVT_MENU(frame
, ProjectService
.PROJECT_PROPERTIES_ID
, frame
.ProcessEvent
) 
3436                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.PROJECT_PROPERTIES_ID
, frame
.ProcessUpdateUIEvent
) 
3437         index 
= menuBar
.FindMenu(_("&Format")) 
3439             index 
= menuBar
.FindMenu(_("&View")) 
3440         menuBar
.Insert(index 
+ 1, projectMenu
, _("&Project")) 
3441         editMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit"))) 
3442         if not menuBar
.FindItemById(ProjectService
.RENAME_ID
): 
3443             editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item")) 
3444             wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
) 
3445             wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
) 
3446         if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
): 
3447             editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system.")) 
3448             wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
) 
3449             wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
) 
3454     def OnCloseFrame(self
, event
): 
3455         if not self
.GetView(): 
3458         if wx
.GetApp().IsMDI(): 
3459             # close all non-project documents first 
3460             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3461                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3462                     if not self
.GetDocumentManager().CloseDocument(document
, False): 
3465             # write project config afterwards because user may change filenames on closing of new documents 
3466             self
.GetView().WriteProjectConfig()  # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere 
3468             # close all project documents after closing other documents 
3469             # because user may save a new document with a new name or cancel closing a document 
3470             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3471                 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3472                     if not document
.OnSaveModified(): 
3475         # This is called when any SDI frame is closed, so need to check if message window is closing or some other window 
3476         elif self
.GetView() == event
.GetEventObject().GetView(): 
3481     #---------------------------------------------------------------------------- 
3482     # Document Manager Methods 
3483     #---------------------------------------------------------------------------- 
3485     def FindProjectFromMapping(self
, key
): 
3486         """ Find which project a model or document belongs to """ 
3487         return self
._mapToProject
.get(key
) 
3490     def AddProjectMapping(self
, key
, projectDoc
=None): 
3491         """ Generate a mapping from model or document to project.  If no project given, use current project. 
3492             e.g. Which project does this model or document belong to (when it was opened)? 
3495             projectDoc 
= self
.GetCurrentProject() 
3496         self
._mapToProject
[key
] = projectDoc
 
3499     def RemoveProjectMapping(self
, key
): 
3500         """ Remove mapping from model or document to project.  """ 
3501         if self
._mapToProject
.has_key(key
): 
3502             del self
._mapToProject
[key
] 
3505     #---------------------------------------------------------------------------- 
3506     # Default Logical View Folder Methods 
3507     #---------------------------------------------------------------------------- 
3509     def AddLogicalViewFolderDefault(self
, pattern
, folder
): 
3510         self
._logicalViewDefaults
.append((pattern
, folder
)) 
3513     def FindLogicalViewFolderDefault(self
, filename
): 
3514         for (pattern
, folder
) in self
._logicalViewDefaults
: 
3515             if filename
.endswith(pattern
): 
3520     def AddLogicalViewFolderCollapsedDefault(self
, folderName
, collapsed
=True): 
3521         # default is collapsed, don't add to list if collapse is True 
3523             self
._logicalViewOpenDefaults
.append(folderName
) 
3526     def FindLogicalViewFolderCollapsedDefault(self
, folderName
): 
3527         if folderName 
in self
._logicalViewOpenDefaults
: 
3532     #---------------------------------------------------------------------------- 
3533     # Default File Type Methods 
3534     #---------------------------------------------------------------------------- 
3536     def AddFileTypeDefault(self
, pattern
, type): 
3537         self
._fileTypeDefaults
.append((pattern
, type)) 
3540     def FindFileTypeDefault(self
, filename
): 
3541         for (pattern
, type) in self
._fileTypeDefaults
: 
3542             if filename
.endswith(pattern
): 
3547     #---------------------------------------------------------------------------- 
3548     # Default Name Methods 
3549     #---------------------------------------------------------------------------- 
3551     def AddNameDefault(self
, pattern
, method
): 
3552         self
._nameDefaults
.append((pattern
, method
)) 
3555     def FindNameDefault(self
, filename
): 
3556         for (pattern
, method
) in self
._nameDefaults
: 
3557             if filename
.endswith(pattern
): 
3558                 return method(filename
) 
3562     def GetDefaultNameCallback(self
, filename
): 
3563         """ A method for generating name from filepath for Project Service """ 
3564         return os
.path
.splitext(os
.path
.basename(filename
))[0] 
3567     #---------------------------------------------------------------------------- 
3568     # Event Processing Methods 
3569     #---------------------------------------------------------------------------- 
3571     def ProcessEventBeforeWindows(self
, event
): 
3574         if id == wx
.ID_CLOSE_ALL
: 
3575             self
.OnFileCloseAll(event
) 
3580     def ProcessUpdateUIEventBeforeWindows(self
, event
): 
3583         if id == wx
.ID_CLOSE_ALL
: 
3584             for document 
in self
.GetDocumentManager().GetDocuments(): 
3585                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3592         elif id == wx
.ID_CLOSE
: 
3593             # "File | Close" is too confusing and hard to determine whether user wants to close a viewed file or the current project. 
3594             # Disallow "File | Close" if project is current document or active in project view. 
3595             # User must explicitly close project via "Project | Close Current Project". 
3596             document 
= self
.GetDocumentManager().GetCurrentDocument() 
3597             if document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3600             if self
.GetView().ProcessUpdateUIEvent(event
): 
3606     def ProcessEvent(self
, event
): 
3607         if Service
.Service
.ProcessEvent(self
, event
): 
3611         if id == ProjectService
.RUN_SELECTED_PM_ID
: 
3612             self
.OnRunProcessModel(event
, runSelected
=True) 
3614         elif id == ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
: 
3615             self
.OnRunProcessModel(event
, runSelected
=True, newWindow
=True, forceInternal
=True) 
3617         elif id == ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
: 
3618             self
.OnRunProcessModel(event
, runSelected
=True, newWindow
=True, forceExternal
=True) 
3620         elif id == ProjectService
.RUN_CURRENT_PM_ID
: 
3621             self
.OnRunProcessModel(event
, runCurrentFile
=True) 
3623         elif id == ProjectService
.RUN_CURRENT_PM_INTERNAL_WINDOW_ID
: 
3624             self
.OnRunProcessModel(event
, runCurrentFile
=True, newWindow
=True, forceInternal
=True) 
3626         elif id == ProjectService
.RUN_CURRENT_PM_EXTERNAL_BROWSER_ID
: 
3627             self
.OnRunProcessModel(event
, runCurrentFile
=True, newWindow
=True, forceExternal
=True) 
3629         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
3630             self
.OnAddCurrentFileToProject(event
) 
3632         elif (id == ProjectService
.PROJECT_PROPERTIES_ID
 
3633         or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
 
3634         or id == ProjectService
.ADD_FOLDER_ID
 
3635         or id == ProjectService
.DELETE_PROJECT_ID
 
3636         or id == ProjectService
.CLOSE_PROJECT_ID
): 
3638                 return self
.GetView().ProcessEvent(event
) 
3645     def ProcessUpdateUIEvent(self
, event
): 
3646         if Service
.Service
.ProcessUpdateUIEvent(self
, event
): 
3650         if id in [ProjectService
.RUN_SELECTED_PM_ID
, 
3651         ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
, 
3652         ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
, 
3653         ProjectService
.RUN_CURRENT_PM_ID
, 
3654         ProjectService
.RUN_CURRENT_PM_INTERNAL_WINDOW_ID
, 
3655         ProjectService
.RUN_CURRENT_PM_EXTERNAL_BROWSER_ID
]: 
3658         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
3659             event
.Enable(self
._CanAddCurrentFileToProject
()) 
3661         elif id in [ProjectService
.ADD_FILES_TO_PROJECT_ID
, 
3662         ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, 
3663         ProjectService
.RENAME_ID
, 
3664         ProjectService
.OPEN_SELECTION_ID
, 
3665         ProjectService
.DELETE_FILE_ID
]: 
3668         elif id == ProjectService
.PROJECT_PROPERTIES_ID
: 
3669             event
.Enable(self
._HasOpenedProjects
()) 
3671         elif id in [wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
, 
3672         ProjectService
.ADD_FOLDER_ID
, 
3673         ProjectService
.DELETE_PROJECT_ID
, 
3674         ProjectService
.CLOSE_PROJECT_ID
]: 
3676                 return self
.GetView().ProcessUpdateUIEvent(event
) 
3683     def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False, newWindow
=False, forceExternal
=False, forceInternal
=False): 
3684         project 
= self
.GetCurrentProject() 
3687             doc 
= self
.GetDocumentManager().GetCurrentDocument() 
3688             if not doc 
or not hasattr(doc
, "GetFilename"): 
3690             fileToRun 
= doc
.GetFilename() 
3691             projects 
= self
.FindProjectByFile(fileToRun
) 
3694             elif project 
in projects
: 
3695                 # use current project 
3697             elif len(projects
) == 1: 
3698                 # only one project, display it 
3699                 project 
= projects
[0] 
3700                 self
.GetView().SetProject(project
.GetFilename()) 
3701             elif len(projects
) > 1: 
3702                 strings 
= map(lambda file: os
.path
.basename(file.GetFilename()), projects
) 
3703                 res 
= wx
.GetSingleChoiceIndex(_("More than one project uses '%s'.  Select project to run:") % os
.path
.basename(fileToRun
), 
3704                                               _("Select Project"), 
3706                                               self
.GetView()._GetParentFrame
()) 
3709                 project 
= projects
[res
] 
3710                 self
.GetView().SetProject(project
.GetFilename()) 
3714             for template 
in self
.GetDocumentManager().GetTemplates(): 
3715                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3716                     ext 
= template
.GetDefaultExtension() 
3721             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
3725             docs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
3727             filesModified 
= False 
3729                 if doc
.IsModified(): 
3730                     filesModified 
= True 
3733                 frame 
= self
.GetView().GetFrame() 
3734                 yesNoMsg 
= wx
.MessageDialog(frame
, 
3735                               _("Files have been modified.  Process may not reflect your current changes.\n\nWould you like to save all files before running?"), 
3737                               wx
.YES_NO|wx
.ICON_QUESTION
 
3739                 yesNoMsg
.CenterOnParent() 
3740                 status 
= yesNoMsg
.ShowModal() 
3742                 if status 
== wx
.ID_YES
: 
3743                     wx
.GetTopLevelParent(frame
).OnFileSaveAll(None) 
3746                 fileToRun 
= self
.GetDocumentManager().GetCurrentDocument().GetFilename() 
3748                 fileToRun 
= self
.GetView().GetSelectedFile() 
3749             elif len(files
) > 1: 
3750                 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower())) 
3751                 strings 
= map(lambda file: os
.path
.basename(file), files
) 
3752                 res 
= wx
.GetSingleChoiceIndex(_("Select a process to run:"), 
3755                                               self
.GetView()._GetParentFrame
()) 
3758                 fileToRun 
= files
[res
] 
3760                 fileToRun 
= files
[0] 
3763                 deployFilePath 
= project
.GenerateDeployment() 
3764             except DataServiceExistenceException
, e
: 
3765                 dataSourceName 
= str(e
) 
3766                 self
.PromptForMissingDataSource(dataSourceName
) 
3768             self
.RunProcessModel(fileToRun
, project
.GetAppInfo().language
, deployFilePath
, newWindow
, forceExternal
, forceInternal
) 
3771     def RunProcessModel(self
, fileToRun
, language
, deployFilePath
, newWindow
=True, forceExternal
=False, forceInternal
=False): 
3772         for runHandler 
in self
.GetRunHandlers(): 
3773             if runHandler
.RunProjectFile(fileToRun
, language
, deployFilePath
, newWindow
, forceExternal
, forceInternal
): 
3775         os
.system('"' + fileToRun 
+ '"') 
3778     def _HasProcessModel(self
): 
3779         project 
= self
.GetView().GetDocument() 
3783             for template 
in self
.GetDocumentManager().GetTemplates(): 
3784                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3785                     ext 
= template
.GetDefaultExtension() 
3790             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
3800     def _HasOpenedProjects(self
): 
3801         for document 
in self
.GetDocumentManager().GetDocuments(): 
3802             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3807     def _CanAddCurrentFileToProject(self
): 
3808         currentDoc 
= self
.GetDocumentManager().GetCurrentDocument() 
3811         if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3813         if not currentDoc
._savedYet
: 
3815         if self
.GetView().GetDocument():  # a project is open 
3817         return False  # There are no documents open 
3820     def GetFilesFromCurrentProject(self
): 
3821         view 
= self
.GetView() 
3823             project 
= view
.GetDocument() 
3825                 return project
.GetFiles() 
3829     def GetCurrentProject(self
): 
3830         view 
= self
.GetView() 
3832             return view
.GetDocument() 
3836     def GetOpenProjects(self
): 
3838         for document 
in self
.GetDocumentManager().GetDocuments(): 
3839             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3840                 retval
.append(document
) 
3844     def FindProjectByFile(self
, filename
): 
3846         for document 
in self
.GetDocumentManager().GetDocuments(): 
3847             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3848                 if document
.GetFilename() == filename
: 
3849                     retval
.append(document
) 
3850                 elif document
.IsFileInProject(filename
): 
3851                     retval
.append(document
) 
3853         # make sure current project is first in list 
3854         currProject 
= self
.GetCurrentProject() 
3855         if currProject 
and currProject 
in retval
: 
3856             retval
.remove(currProject
) 
3857             retval
.insert(0, currProject
) 
3862     def OnAddCurrentFileToProject(self
, event
): 
3863         doc 
= self
.GetDocumentManager().GetCurrentDocument() 
3864         file = doc
.GetFilename() 
3865         projectDoc 
= self
.GetView().GetDocument() 
3866         projectDoc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(projectDoc
, [file])) 
3868         AddProjectMapping(doc
, projectDoc
) 
3870         self
.GetView().Activate()  # after add, should put focus on project editor 
3873     def OnFileCloseAll(self
, event
): 
3874         for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3875             if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3876                 if not self
.GetDocumentManager().CloseDocument(document
, False): 
3878                 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed 
3881     def OpenSavedProjects(self
): 
3882         config 
= wx
.ConfigBase_Get() 
3884         if config
.ReadInt("ProjectSaveDocs", True): 
3885             docString 
= config
.Read("ProjectSavedDocs") 
3888                 docList 
= eval(docString
) 
3889                 self
.GetView()._treeCtrl
.Freeze() 
3891                 for fileName 
in docList
: 
3892                     if isinstance(fileName
, types
.StringTypes
): 
3893                         if os
.path
.exists(fileName
): 
3894                             doc 
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
3895                 self
.GetView()._treeCtrl
.Thaw() 
3900                 currProject 
= config
.Read("ProjectCurrent") 
3901                 if currProject 
in docList
: 
3902                     self
.GetView().SetProject(currProject
) 
3907     def PromptForMissingDataSource(self
, dataSourceName
): 
3908         prompt 
= "A required Data Source '%s' was not found.  The process cannot be run without this Data Source.\n\nWould you like to configure this Data Source now?" % dataSourceName
 
3909         msgTitle 
= "Unknown Data Source" 
3910         dataSourceMissingDlg 
= wx
.MessageDialog(self
.GetView().GetFrame(), prompt
, msgTitle
, wx
.YES_NO|wx
.ICON_QUESTION
) 
3911         dataSourceMissingDlg
.CenterOnParent() 
3912         if dataSourceMissingDlg
.ShowModal() == wx
.ID_YES
: 
3913             dataSourceMissingDlg
.Destroy() 
3914             self
._AddDataSource
(dataSourceName
) 
3916             dataSourceMissingDlg
.Destroy() 
3919     def _AddDataSource(self
, defaultDataSourceName
=None): 
3920         dataSourceService 
= wx
.GetApp().GetService(DataModelEditor
.DataSourceService
) 
3921         dsChoices 
= dataSourceService
.getDataSourceNames() 
3922         dlg 
= DataModelEditor
.AddDataSourceDialog(self
.GetView().GetFrame(), 'Add Data Source', dsChoices
, defaultDataSourceName
) 
3923         dlg
.CenterOnParent() 
3924         if dlg
.ShowModal() == wx
.ID_OK
: 
3925             dataSource 
= dlg
.GetDataSource() 
3930         if (dataSource 
== None): 
3931             wx
.MessageBox(_("Error getting data source."), self
._title
) 
3932         dataSourceService
.updateDataSource(dataSource
) 
3933         if ((dsChoices 
== None) or (len(dsChoices
) <= 0)): 
3934             wx
.ConfigBase_Get().Write(DataModelEditor
.SchemaOptionsPanel
.DEFAULT_DATASOURCE_KEY
, dataSource
.name
) 
3935         dataSourceService
.save() 
3939 #---------------------------------------------------------------------------- 
3940 # Icon Bitmaps - generated by encode_bitmaps.py 
3941 #---------------------------------------------------------------------------- 
3942 from wx 
import ImageFromStream
, BitmapFromImage
 
3946 def getProjectData(): 
3948 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3949 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3950 \x00\x01\x89IDAT8\x8d\xa5\x92\xcdJ\x02Q\x18\x86\x9fq&-+H\xd40\x033Bha\x05\ 
3951 \xfd\xac*[\xb7l\xd1\xae\xfbhQ7\x10\x04A]\x86\xd0&\xba\x01CW\n!B\xa2\x882\x8b\ 
3952 )R+"\x7fft\x9a\x16\x91\xcd4\xd3\x0f\xf4\xee\xce\xf9\xde\xf7\xe1\xfd\x0eG\x10\ 
3953 \\"\x9arb\xe8\xcf\x1a\x9d\x9e\n\x80\xd6\xad\x03\x10Z;\x13\xf8ER\xa7xd\x88\ 
3954 \xbe-D\x1f\xb8\xbf\x0c\xaf\xcf\x15C\xd2k\xf4\xc5(\x92^\x03 \xbe\x9b\xb3@\x85\ 
3955 n\xe9\xd8h\xde\xe6\x1d\xe9\xfe\xa9E\xc7\xfb\x91\xf9\xfd\x01D\xfa\xc9\xd8\xf7\ 
3956 \xcdPI\'\x01X\xd8>@p\xf7\x00($W\x8c\x8f&R\xa7\xa7\xa2u\xebL.\xef\xd9\x00\x97\ 
3957 \xa7\x87D\\er\x15\x95\xb9\xf5\x12\xa3\x81Y\x9bG\xfax0\xb3Z\x8d*\x95t\x92z\ 
3958 \xb5\x80yjhC\x83\x16\x96\x15\xdc\xc3AZ\x8d\xea{XN#g.,\xa6\xe0l\x9c\xde}\x89\ 
3959 \xb6\xc3\x9aR\xff\xe5\x01\x801}\x1c\x80\x9b\xcc\x05\xde\xb0\x9f\xd0t\x04oX\ 
3960 \xa6\xad4\xc9U\n\xc0&\x1e\xfd\xd6\x0e\x18\xd4Se\x00\xbca?m\xa5\xc9\x1d\xd0V\ 
3961 \x9a\x03\xa3\xd6\xadc\xa8\x8fv\xc0S\xa3H\xc8\x13\x01\xa2\x00\xc4V\x13\x94\ 
3962 \xb3)\xae\xae\x14\x8b\xd1\x17\x90laK\x03\xb3b\xab\t&\x02\xf7(\xf94\xf2k\x8c\ 
3963 \x8d\x8dy\xc7\xf0\xb7\x00\x80`t\x92`t\x87%\xa0\x9cM\xd1\xa8}\xce\xcc\xbf\xd1\ 
3964 \x11P\xce\xa6,\xe7\xaf\xdf\xd7,Ap\x89\x14\x92+\xc6_\x03\x8e\x80\xff\xc8\xf5\ 
3965 \xaf4\xf0\x06=\xf3\x8fJr]C\xd9\x00\x00\x00\x00IEND\xaeB`\x82' 
3967 def getProjectBitmap(): 
3968     return BitmapFromImage(getProjectImage()) 
3970 def getProjectImage(): 
3971     stream 
= cStringIO
.StringIO(getProjectData()) 
3972     return ImageFromStream(stream
) 
3974 def getProjectIcon(): 
3975     return wx
.IconFromBitmap(getProjectBitmap()) 
3978 #---------------------------------------------------------------------------- 
3982 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3983 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3984 \x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\ 
3985 \x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\ 
3986 \x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\ 
3987 \xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\ 
3988 \x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\ 
3989 \x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\ 
3990 \xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\ 
3991 \xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\ 
3992 \x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\ 
3993 \xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\ 
3994 \xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\ 
3998 def getBlankBitmap(): 
3999     return BitmapFromImage(getBlankImage()) 
4001 def getBlankImage(): 
4002     stream 
= cStringIO
.StringIO(getBlankData()) 
4003     return ImageFromStream(stream
) 
4006     return wx
.IconFromBitmap(getBlankBitmap()) 
4009 #---------------------------------------------------------------------- 
4010 def getFolderClosedData(): 
4012 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4013 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4014 \x00\x00\xffIDAT8\x8d\xa5\x93?N\x02A\x14\x87\xbf\x19&\x10B\xb4A\x0b*iL0!$\ 
4015 \x06\x0f\xe0\x05lH\x88G\xe1\x0c\xdbx\x11ZN`,\xa5\x01\x8aM\xa4\x80\x84\xc4Fc\ 
4016 \xd0\xe8\xb0\xae\xbbc\x01\x0b,\x19\x16X~\xd5\x9b\xf7\xe7\x9by3o\x84\x90\x19\ 
4017 \x8e\x91\x8a\x0c\xed:\x06\xc0\xf7g\x00x\xde\x14\x80\xf3\x9b\x07\xb1\x13\xa0]\ 
4018 \xc7d\xcbw\x00d\x17\x81\x82\xff\x01\xc0\xb0\xd3\x9f\x83\x7f\xf5\xb2\xe8\xaa\ 
4019 \xf1\xb4\x84\n!3h\xd71\xef\xaf=\xeb\x0e\xc5R\xcd\xea\xcfWZ"\xd6\xc2\xb6\xc4\ 
4020 \xdc\xe5\xad\xd5?h\xd7M\xb5\xd9\x15\n\xe6}{\xde\x94\xe2\xf5\xbd59I\x12V\x17\ 
4021 \x96F\n \xfc\xfbD\xaaS\xc2\x9fI:@\x041\xdf\xa3\x8d\xb0Y\xb3\xed\xaf\xa9\x00\ 
4022 \xbe\xde\xc6\x9c\x9c]\x10\xea\xc3O #\xc3\xd7:)/\x19\xb0>$\x87J\x01\x04\xc1n\ 
4023 \xc0\xcb\xf3cl]mv\xe3\x83\xb4o\xc1\xa6D\xf4\x1b\x07\xed\xba\xd9\xa7`+ \xad\ 
4024 \xfe\x01\xd1\x03SV!\xfbHa\x00\x00\x00\x00IEND\xaeB`\x82'  
4026 def getFolderClosedBitmap(): 
4027     return BitmapFromImage(getFolderClosedImage()) 
4029 def getFolderClosedImage(): 
4030     stream 
= cStringIO
.StringIO(getFolderClosedData()) 
4031     return ImageFromStream(stream
) 
4033 def getFolderClosedIcon(): 
4034     return wx
.IconFromBitmap(getFolderClosedBitmap()) 
4037 #---------------------------------------------------------------------- 
4038 def getFolderOpenData(): 
4040 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4041 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4042 \x00\x01>IDAT8\x8d\xa5\x93\xbdJ\x03A\x14\x85\xbfY\x03i\xac\x14\x92\xc2F\xad$\ 
4043 Z\xa4\x10\x11|\x01\xc1J\xdbt\xbe\x86\x9d\x85\x0f\xa0\xe0\x1b\x04,l\xc4J\x0b\ 
4044 \x0bA;a\x11\x13\xb1H\xc2\xc2\xca\x84@\x88n\xb2\xd9?\xcd\xd8d6.\x9b\x104\xa7\ 
4045 \xbas\xef=g\xce\x9d\xe1\na\xcc1\x0b\x8c\x99\xd8@F\x07_\xd6\xb9\n\xdd\x8f\xb8\ 
4046 \xd0s\x9a\x00\xe4\xb6O\xc5T\x81~\xf5D\x89\xdc\x0e\xd9_\x85,\xa0\xa2\x06\xefw\ 
4047 R\x01\x04\x9e\x03\xc0\xea\xde\x8dH\th\xa8\xa81:\xf8\x1e\x00\xf9\x8d\x03\x00\ 
4048 \xa4U\x07\xc0,\xdb\xaaX\xaa\xc4"\x99\x04\xd9\xf7\xe0\xfbs$\x12\x0e\x90\xad\ 
4049 \x0e\x00]\xeb*N\x9b\xe5u\x05P,UD\xc2\x81&K\xbb\r@\xd4\xba\x1f\x9a\xe9\xb0\ 
4050 \xb6\x7f\x96h}\xbe8\x1c9\xe89M\x16\xfc\x15\xa4\xdd\xc6\xe8\x9a\x18\xc3\x99\ 
4051 \x97w\x8f\x99\x86\xd8\x81\xb4\xea\x18]\x93\xfcf).\x0e\\9\x96\xf4r}\x84~\x87\ 
4052 \xc4\x08\x81\xe7\xa0\xfa\xb5\xa9\xb7\xa6\x1c\xf4\xdao\xcc/B\x04\x0c<\xfb\xef\ 
4053 \x02Zd\xa9P\x98\xd8\xf8\xfax\x1b\xc7\xa9o\xf4\xbdN\x8aP{z \x0c\xdc\xb1\xa4\ 
4054 \xdf\x10z\x99\xaa\x97[J\'\xc3\xc0\x9dH\x98(\xf0_\xcc\xbc\x8d?\xf2)\x7f\x8e|f\ 
4055 \xe54\x00\x00\x00\x00IEND\xaeB`\x82'  
4057 def getFolderOpenBitmap(): 
4058     return BitmapFromImage(getFolderOpenImage()) 
4060 def getFolderOpenImage(): 
4061     stream 
= cStringIO
.StringIO(getFolderOpenData()) 
4062     return ImageFromStream(stream
) 
4064 def getFolderOpenIcon(): 
4065     return wx
.IconFromBitmap(getFolderOpenBitmap()) 
4068 #---------------------------------------------------------------------- 
4069 def getLogicalModeOnData(): 
4071 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4072 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4073 \x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ 
4074 \xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ 
4075 \x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ 
4076 \xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ 
4077 \xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ 
4078 \xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ 
4079 \xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ 
4080 \xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ 
4081 \xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ 
4082 \x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ 
4083 \x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ 
4084 \xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ 
4085 h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ 
4086 \xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ 
4087 \x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ 
4088 \x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82'  
4090 def getLogicalModeOnBitmap(): 
4091     return BitmapFromImage(getLogicalModeOnImage()) 
4093 def getLogicalModeOnImage(): 
4094     stream 
= cStringIO
.StringIO(getLogicalModeOnData()) 
4095     return ImageFromStream(stream
) 
4097 #---------------------------------------------------------------------- 
4098 def getLogicalModeOffData(): 
4100 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4101 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4102 \x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ 
4103 \xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ 
4104 \x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ 
4105 \xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ 
4106 \xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ 
4107 \xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ 
4108 \xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ 
4109 \xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ 
4110 \xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ 
4111 \x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ 
4112 \x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ 
4113 \xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ 
4114 h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ 
4115 \xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ 
4116 \x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ 
4117 \x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82'  
4119 def getLogicalModeOffBitmap(): 
4120     return BitmapFromImage(getLogicalModeOffImage()) 
4122 def getLogicalModeOffImage(): 
4123     stream 
= cStringIO
.StringIO(getLogicalModeOffData()) 
4124     return ImageFromStream(stream
) 
4126 #---------------------------------------------------------------------- 
4127 def getPhysicalModeOnData(): 
4129 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4130 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4131 \x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ 
4132 \x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ 
4133 \xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ 
4134 \x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ 
4135 [{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ 
4136 \x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ 
4137 vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ 
4138 \xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ 
4139 I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ 
4140 \xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ 
4141 \xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ 
4142 \xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ 
4143 \'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ 
4144 \xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ 
4145 \xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ 
4146 \xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ 
4147 \xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ 
4148 \x00\x00\x00IEND\xaeB`\x82'  
4150 def getPhysicalModeOnBitmap(): 
4151     return BitmapFromImage(getPhysicalModeOnImage()) 
4153 def getPhysicalModeOnImage(): 
4154     stream 
= cStringIO
.StringIO(getPhysicalModeOnData()) 
4155     return ImageFromStream(stream
) 
4157 #---------------------------------------------------------------------- 
4158 def getPhysicalModeOffData(): 
4160 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4161 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4162 \x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ 
4163 \x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ 
4164 \xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ 
4165 \x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ 
4166 [{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ 
4167 \x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ 
4168 vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ 
4169 \xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ 
4170 I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ 
4171 \xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ 
4172 \xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ 
4173 \xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ 
4174 \'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ 
4175 \xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ 
4176 \xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ 
4177 \xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ 
4178 \xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ 
4179 \x00\x00\x00IEND\xaeB`\x82'  
4181 def getPhysicalModeOffBitmap(): 
4182     return BitmapFromImage(getPhysicalModeOffImage()) 
4184 def getPhysicalModeOffImage(): 
4185     stream 
= cStringIO
.StringIO(getPhysicalModeOffData()) 
4186     return ImageFromStream(stream
)