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
 
  17 from wxPython
.lib
.rcsizer 
import RowColSizer
 
  26 import activegrid
.util
.appdirs 
as appdirs
 
  27 import activegrid
.util
.fileutils 
as fileutils
 
  28 import activegrid
.util
.aglogging 
as aglogging
 
  32 import project 
as projectlib
 
  33 import ExtensionService
 
  35 from IDE 
import ACTIVEGRID_BASE_IDE
 
  36 if not ACTIVEGRID_BASE_IDE
: 
  37     import activegrid
.server
.deployment 
as deploymentlib
 
  38     import ProcessModelEditor
 
  39     import DataModelEditor
 
  40     import DeploymentGeneration
 
  43     APP_LAST_LANGUAGE 
= "LastLanguage" 
  44     import activegrid
.model
.basedocmgr 
as basedocmgr
 
  45     import activegrid
.model
.basemodel 
as basemodel
 
  46     import activegrid
.model
.projectmodel 
as projectmodel
 
  47     import PropertyService
 
  48     from activegrid
.server
.toolsupport 
import GetTemplate
 
  49     import activegrid
.util
.xmlutils 
as xmlutils
 
  50     import activegrid
.util
.sysutils 
as sysutils
 
  51     DataServiceExistenceException 
= DeploymentGeneration
.DataServiceExistenceException
 
  52     import WebBrowserService
 
  54 from SVNService 
import SVN_INSTALLED
 
  58 if wx
.Platform 
== '__WXMSW__': 
  63 #---------------------------------------------------------------------------- 
  65 #---------------------------------------------------------------------------- 
  68 PROJECT_EXTENSION 
= ".agp" 
  70 if not ACTIVEGRID_BASE_IDE
: 
  71     PRE_17_TMP_DPL_NAME 
= "RunTime_tmp" + deploymentlib
.DEPLOYMENT_EXTENSION
 
  72     _17_TMP_DPL_NAME 
= ".tmp" + deploymentlib
.DEPLOYMENT_EXTENSION
 
  74 # wxBug: the wxTextCtrl and wxChoice controls on Mac do not correctly size 
  75 # themselves with sizers, so we need to add a right border to the sizer to 
  76 # get the control to shrink itself to fit in the sizer. 
  78 if wx
.Platform 
== "__WXMAC__": 
  82 PROJECT_KEY 
= "/AG_Projects" 
  83 PROJECT_DIRECTORY_KEY 
= "NewProjectDirectory" 
  85 NEW_PROJECT_DIRECTORY_DEFAULT 
= appdirs
.getSystemDir() 
  87 #---------------------------------------------------------------------------- 
  89 #---------------------------------------------------------------------------- 
  91 def AddProjectMapping(doc
, projectDoc
=None, hint
=None): 
  92     projectService 
= wx
.GetApp().GetService(ProjectService
) 
  96                 hint 
= doc
.GetFilename() 
  97             projectDocs 
= projectService
.FindProjectByFile(hint
) 
  99                 projectDoc 
= projectDocs
[0] 
 101         projectService
.AddProjectMapping(doc
, projectDoc
) 
 102         if hasattr(doc
, "GetModel"): 
 103             projectService
.AddProjectMapping(doc
.GetModel(), projectDoc
) 
 106 def getProjectKeyName(projectName
, mode
=None): 
 108         return "%s/%s/%s" % (PROJECT_KEY
, projectName
.replace(os
.sep
, '|'), mode
) 
 110         return "%s/%s" % (PROJECT_KEY
, projectName
.replace(os
.sep
, '|')) 
 113 def GetDocCallback(filepath
): 
 114     """ Get the Document used by the IDE and the in-memory document model used by runtime engine """ 
 115     docMgr 
= wx
.GetApp().GetDocumentManager() 
 118         doc 
= docMgr
.CreateDocument(filepath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
 120             AddProjectMapping(doc
) 
 122             for d 
in docMgr
.GetDocuments(): 
 123                 if os
.path
.normcase(d
.GetFilename()) == os
.path
.normcase(filepath
): 
 128         aglogging
.reportException(e
, stacktrace
=True) 
 130     if doc 
and doc
.GetDocumentTemplate().GetDocumentType() == WsdlAgEditor
.WsdlAgDocument
: 
 131         # get referenced wsdl doc instead 
 132         if doc
.GetModel().filePath
: 
 133             if os
.path
.isabs(doc
.GetModel().filePath
):  # if absolute path, leave it alone 
 134                 filepath 
= doc
.GetModel().filePath
 
 136                 filepath 
= doc
.GetAppDocMgr().fullPath(doc
.GetModel().filePath
)  # check relative to project homeDir 
 138                 if not os
.path
.isfile(filepath
): 
 139                     filepath 
= os
.path
.normpath(os
.path
.join(os
.path
.dirname(doc
.GetFilename()), doc
.GetModel().filePath
))  # check relative to wsdlag file 
 141                     if not os
.path
.isfile(filepath
): 
 142                         filename 
= os
.sep 
+ os
.path
.basename(doc
.GetModel().filePath
)  # check to see if in project file 
 143                         filePaths 
= findDocumentMgr(doc
).filePaths
 
 145                             if fp
.endswith(filename
): 
 150                 doc 
= docMgr
.CreateDocument(filepath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
 153                 aglogging
.reportException(e
, stacktrace
=True) 
 156                 AddProjectMapping(doc
) 
 158                 for d 
in docMgr
.GetDocuments(): 
 159                     if os
.path
.normcase(d
.GetFilename()) == os
.path
.normcase(filepath
): 
 166         docModel 
= doc
.GetModel() 
 173 def findDocumentMgr(root
): 
 174     projectService 
= wx
.GetApp().GetService(ProjectService
) 
 176         projectDoc 
= projectService
.FindProjectFromMapping(root
) 
 178             return projectDoc
.GetModel() 
 180         projectDoc 
= projectService
.GetCurrentProject() 
 184         if isinstance(root
, wx
.lib
.docview
.Document
): 
 185             filepath 
= root
.GetFilename() 
 186         elif hasattr(root
, "fileName") and root
.fileName
: 
 187             filepath 
= root
.fileName
 
 192             if projectDoc
.IsFileInProject(filepath
): 
 193                 return projectDoc
.GetModel() 
 196             openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
 197             for openDoc 
in openDocs
: 
 198                 if openDoc 
== projectDoc
: 
 200                 if(isinstance(openDoc
, ProjectDocument
)): 
 201                     if openDoc
.IsFileInProject(filepath
): 
 202                         projects
.append(openDoc
) 
 205                 if len(projects
) == 1: 
 206                     return projects
[0].GetModel() 
 208                     choices 
= [os
.path
.basename(project
.GetFilename()) for project 
in projects
] 
 209                     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
) 
 212                     if dlg
.ShowModal() == wx
.ID_OK
: 
 213                         i 
= dlg
.GetSelection() 
 214                         projectDoc 
= projects
[i
] 
 216                     return projectDoc
.GetModel() 
 217         return projectDoc
.GetModel() 
 222 if not ACTIVEGRID_BASE_IDE
: 
 223     basemodel
.findGlobalDocumentMgr 
= findDocumentMgr
 
 226 #---------------------------------------------------------------------------- 
 228 #---------------------------------------------------------------------------- 
 230 if not ACTIVEGRID_BASE_IDE
: 
 231     class IDEResourceFactory(DeploymentGeneration
.DeploymentResourceFactory
): 
 233         def __init__(self
, openDocs
, dataSourceService
, projectDir
, 
 234                      preview
=False, deployFilepath
=None): 
 236             self
.openDocs 
= openDocs
 
 237             self
.dataSourceService 
= dataSourceService
 
 238             self
.projectDir 
= projectDir
 
 239             self
.preview 
= preview
 
 240             self
.deployFilepath 
= deployFilepath
 
 242             self
.defaultFlagsNoView 
= ( 
 243                 wx
.GetApp().GetDocumentManager().GetFlags()|
 
 244                 wx
.lib
.docview
.DOC_SILENT|
 
 245                 wx
.lib
.docview
.DOC_OPEN_ONCE|
 
 246                 wx
.lib
.docview
.DOC_NO_VIEW
) 
 248         def getModel(self
, projectFile
): 
 249             doc 
= wx
.GetApp().GetDocumentManager().CreateDocument( 
 250                 projectFile
.filePath
, flags
=self
.defaultFlagsNoView
) 
 251             if (doc 
== None):  # already open 
 252                 doc 
= self
._findOpenDoc
(projectFile
.filePath
) 
 254                 AddProjectMapping(doc
) 
 256                 return doc
.GetModel() 
 258         def getDataSource(self
, dataSourceName
): 
 259             # in preview mode, runtime needs the generated Deployment 
 260             # to contain the requried data source. But runtime doesn't 
 261             # actually need to communicate to db. So here is the logic to 
 262             # make preview works if the required data soruce has not 
 264             dataSource 
= self
.dataSourceService
.getDataSource(dataSourceName
) 
 265             if (dataSource 
!= None): 
 267             elif not self
.preview
: 
 268                 raise DataServiceExistenceException(dataSourceName
) 
 270                 # first to see if an existing dpl file is there, if so, 
 271                 # use the data source in dpl file 
 272                 if (self
.deployFilepath 
!= None): 
 275                         tempDply 
= xmlutils
.load(deployFilepath
) 
 278                     if (tempDply 
!= None): 
 279                         for tempDataSource 
in tempDply
.dataSources
: 
 280                             if (tempDataSource
.name 
== dataSourceName
): 
 281                                 return tempDataSource
 
 283                 # if unable to use dpl file, then create a dummy data source 
 284                 import activegrid
.data
.dataservice 
as dataservice
 
 285                 return dataservice
.DataSource( 
 286                     name
=dataSourceName
, dbtype
=dataservice
.DB_TYPE_SQLITE
) 
 288         def initDocumentRef(self
, projectFile
, documentRef
, dpl
): 
 289             doc 
= self
._findOpenDoc
(projectFile
.filePath
) 
 290             if (doc 
and hasattr(doc
, 'GetModel')): 
 291                 documentRef
.document 
= doc
.GetModel() 
 292                 if isinstance(documentRef
, deploymentlib
.XFormRef
): 
 293                     doc
.GetModel().linkDeployment(dpl
, dpl
.loader
) 
 295         def _findOpenDoc(self
, filePath
): 
 296             for openDoc 
in self
.openDocs
: 
 297                 if openDoc
.GetFilename() == filePath
: 
 301         def getProjectDir(self
): 
 302             return self
.projectDir
 
 305 class ProjectDocument(wx
.lib
.docview
.Document
): 
 307     def __init__(self
, model
=None): 
 308         wx
.lib
.docview
.Document
.__init
__(self
) 
 312             self
.SetModel(projectlib
.Project())  # initial model used by "File | New... | Project" 
 313         self
.GetModel().SetDocCallback(GetDocCallback
) 
 315         self
._stageProjectFile 
= False  
 319         model 
= copy
.copy(self
.GetModel())         
 320         clone 
=  ProjectDocument(model
) 
 321         clone
.SetFilename(self
.GetFilename()) 
 325     def GetFirstView(self
): 
 326         """ 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. 
 327             And to the user, it appears as if nothing has happened.  The user expects to see the open project. 
 328             This forces the project view to show the correct project. 
 330         view 
= wx
.lib
.docview
.Document
.GetFirstView(self
) 
 331         view
.SetProject(self
.GetFilename())  # ensure project is displayed in view 
 336         return self
._projectModel
 
 339     def SetModel(self
, model
): 
 340         self
._projectModel 
= model
 
 343     def OnCreate(self
, path
, flags
): 
 344         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 345         view 
= projectService
.GetView() 
 346         if view
:  # view already exists, reuse 
 347             # All project documents share the same view. 
 350             if view
.GetDocument(): 
 351                 # All project documents need to share the same command processor, 
 352                 # to enable redo/undo of cross project document commands 
 353                 cmdProcessor 
= view
.GetDocument().GetCommandProcessor() 
 355                     self
.SetCommandProcessor(cmdProcessor
) 
 356         else:  # generate view 
 357             view 
= self
.GetDocumentTemplate().CreateView(self
, flags
) 
 358             projectService
.SetView(view
) 
 363     def LoadObject(self
, fileObject
): 
 364         self
.SetModel(projectlib
.load(fileObject
)) 
 365         self
.GetModel().SetDocCallback(GetDocCallback
) 
 369     def SaveObject(self
, fileObject
): 
 370         projectlib
.save(fileObject
, self
.GetModel()) 
 374     def OnOpenDocument(self
, filePath
): 
 375         projectService 
= wx
.GetApp().GetService(ProjectService
) 
 376         view 
= projectService
.GetView() 
 378         if not os
.path
.exists(filePath
): 
 379             wx
.GetApp().CloseSplash() 
 380             msgTitle 
= wx
.GetApp().GetAppName() 
 382                 msgTitle 
= _("File Error") 
 383             wx
.MessageBox(_("Could not find '%s'.") % filePath
, 
 385                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 386                           wx
.GetApp().GetTopWindow()) 
 387             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 389         fileObject 
= file(filePath
, 'r') 
 391             self
.LoadObject(fileObject
) 
 393             wx
.GetApp().CloseSplash() 
 394             msgTitle 
= wx
.GetApp().GetAppName() 
 396                 msgTitle 
= _("File Error") 
 397             wx
.MessageBox(_("Could not open '%s'.  %s") % (wx
.lib
.docview
.FileNameFromPath(filePath
), sys
.exc_value
), 
 399                           wx
.OK | wx
.ICON_EXCLAMATION | wx
.STAY_ON_TOP
, 
 400                           wx
.GetApp().GetTopWindow()) 
 401             return True  # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed 
 404         self
.SetFilename(filePath
, True) 
 405         view
.AddProjectToView(self
) 
 406         self
.SetDocumentModificationDate() 
 407         self
.UpdateAllViews() 
 408         self
._savedYet 
= True 
 413     def AddFile(self
, filePath
, folderPath
=None, type=None, name
=None): 
 423         return self
.AddFiles([filePath
], folderPath
, types
, names
) 
 426     def AddFiles(self
, filePaths
=None, folderPath
=None, types
=None, names
=None, files
=None): 
 427         # Filter out files that are not already in the project 
 431             for filePath 
in filePaths
: 
 432                 if self
.GetModel().FindFile(filePath
): 
 433                     oldFilePaths
.append(filePath
) 
 435                     newFilePaths
.append(filePath
) 
 437             projectService 
= wx
.GetApp().GetService(ProjectService
) 
 438             for i
, filePath 
in enumerate(newFilePaths
): 
 447                     name 
= projectService
.FindNameDefault(filePath
) 
 450                     folder 
= projectService
.FindLogicalViewFolderDefault(filePath
) 
 454                 self
.GetModel().AddFile(filePath
, folder
, type, name
) 
 459                 if self
.GetModel().FindFile(file.filePath
): 
 460                     oldFilePaths
.append(file.filePath
) 
 462                     newFilePaths
.append(file.filePath
) 
 463                     self
.GetModel().AddFile(file=file) 
 467         self
.AddNameSpaces(newFilePaths
) 
 469         self
.UpdateAllViews(hint 
= ("add", self
, newFilePaths
, oldFilePaths
)) 
 470         if len(newFilePaths
): 
 477     def RemoveFile(self
, filePath
): 
 478         return self
.RemoveFiles([filePath
]) 
 481     def RemoveFiles(self
, filePaths
=None, files
=None): 
 487                 filePaths
.append(file.filePath
) 
 489         for filePath 
in filePaths
: 
 490             file = self
.GetModel().FindFile(filePath
) 
 492                 self
.GetModel().RemoveFile(file) 
 493                 removedFiles
.append(file.filePath
) 
 495         self
.UpdateAllViews(hint 
= ("remove", self
, removedFiles
)) 
 496         if len(removedFiles
): 
 503     def RenameFile(self
, oldFilePath
, newFilePath
, isProject 
= False): 
 505             if oldFilePath 
== newFilePath
: 
 508             # projects don't have to exist yet, so not required to rename old file, 
 509             # but files must exist, so we'll try to rename and allow exceptions to occur if can't. 
 510             if not isProject 
or (isProject 
and os
.path
.exists(oldFilePath
)): 
 511                 os
.rename(oldFilePath
, newFilePath
) 
 514                 documents 
= self
.GetDocumentManager().GetDocuments() 
 515                 for document 
in documents
: 
 516                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFilePath
):  # If the renamed document is open, update it 
 517                         document
.SetFilename(newFilePath
) 
 518                         document
.SetTitle(wx
.lib
.docview
.FileNameFromPath(newFilePath
)) 
 519                         document
.UpdateAllViews(hint 
= ("rename", self
, oldFilePath
, newFilePath
)) 
 521                 self
.UpdateFilePath(oldFilePath
, newFilePath
) 
 522                 documents 
= self
.GetDocumentManager().GetDocuments() 
 523                 for document 
in documents
: 
 524                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(oldFilePath
):  # If the renamed document is open, update it 
 525                         document
.SetFilename(newFilePath
, notifyViews 
= True) 
 526                         document
.UpdateAllViews(hint 
= ("rename", self
, oldFilePath
, newFilePath
)) 
 528         except OSError, (code
, message
): 
 529             msgTitle 
= wx
.GetApp().GetAppName() 
 531                 msgTitle 
= _("File Error") 
 532             wx
.MessageBox("Could not rename '%s'.  '%s'" % (wx
.lib
.docview
.FileNameFromPath(oldFilePath
), message
), 
 534                           wx
.OK | wx
.ICON_EXCLAMATION
, 
 535                           wx
.GetApp().GetTopWindow()) 
 539     def MoveFile(self
, file, newFolderPath
): 
 540         return self
.MoveFiles([file], newFolderPath
) 
 543     def MoveFiles(self
, files
, newFolderPath
): 
 545         isArray 
= isinstance(newFolderPath
, type([])) 
 546         for i 
in range(len(files
)): 
 548                 files
[i
].logicalFolder 
= newFolderPath
[i
] 
 550                 files
[i
].logicalFolder 
= newFolderPath
 
 551             filePaths
.append(files
[i
].filePath
) 
 553         self
.UpdateAllViews(hint 
= ("remove", self
, filePaths
)) 
 554         self
.UpdateAllViews(hint 
= ("add", self
, filePaths
, [])) 
 559     def UpdateFilePath(self
, oldFilePath
, newFilePath
): 
 560         file = self
.GetModel().FindFile(oldFilePath
) 
 561         self
.RemoveFile(oldFilePath
) 
 563             self
.AddFile(newFilePath
, file.logicalFolder
, file.type, file.name
) 
 565             self
.AddFile(newFilePath
) 
 568     def RemoveInvalidPaths(self
): 
 569         """Makes sure all paths project knows about are valid and point to existing files. Removes and returns list of invalid paths.""" 
 573         fileRefs 
= self
.GetFileRefs() 
 575         for fileRef 
in fileRefs
: 
 576             if not os
.path
.exists(fileRef
.filePath
): 
 577                 invalidFileRefs
.append(fileRef
) 
 579         for fileRef 
in invalidFileRefs
: 
 580             fileRefs
.remove(fileRef
) 
 582         return [fileRef
.filePath 
for fileRef 
in invalidFileRefs
] 
 585     def SetStageProjectFile(self
): 
 586         self
._stageProjectFile 
= True 
 589     def ArchiveProject(self
, zipdest
, stagedir
): 
 590         """Zips stagedir, creates a zipfile that has as name the projectname, in zipdest. Returns path to zipfile.""" 
 591         if os
.path
.exists(zipdest
): 
 592             raise AssertionError("Cannot archive project, %s already exists" % zipdest
) 
 593         fileutils
.zip(zipdest
, stagedir
) 
 598     def StageProject(self
, tmpdir
, targetDataSourceMapping
={}): 
 599         """ 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.""" 
 601         projname 
= self
.GetProjectName() 
 602         stagedir 
= os
.path
.join(tmpdir
, projname
) 
 603         fileutils
.remove(stagedir
) 
 604         os
.makedirs(stagedir
)         
 606         # remove invalid files from project 
 607         self
.RemoveInvalidPaths()         
 609         # required so relative paths are written correctly when .dpl file is 
 611         self
.SetFilename(os
.path
.join(stagedir
, 
 612                                       os
.path
.basename(self
.GetFilename()))) 
 613         projectdir 
= self
.GetModel().homeDir
 
 615         # Validate paths before actually copying, and populate a dict 
 616         # with src->dest so copying is easy. 
 617         # (fileDict: ProjectFile instance -> dest path (string)) 
 618         fileDict 
= self
._ValidateFilePaths
(projectdir
, stagedir
) 
 620         # copy files to staging dir 
 621         self
._StageFiles
(fileDict
) 
 623         # set target data source for schemas 
 624         self
._SetSchemaTargetDataSource
(fileDict
, targetDataSourceMapping
) 
 626         # it is unfortunate we require this. it would be nice if filepaths 
 627         # were only in the project 
 628         self
._FixWsdlAgFiles
(stagedir
) 
 631         dplfilename 
= projname 
+ deploymentlib
.DEPLOYMENT_EXTENSION
 
 632         dplfilepath 
= os
.path
.join(stagedir
, dplfilename
) 
 633         self
.GenerateDeployment(dplfilepath
) 
 635         if self
._stageProjectFile
: 
 636             # save project so we get the .agp file. not required for deployment 
 637             # but convenient if user wants to open the deployment in the IDE 
 638             agpfilename 
= projname 
+ PROJECT_EXTENSION
 
 639             agpfilepath 
= os
.path
.join(stagedir
, agpfilename
) 
 641             # if this project has deployment data sources configured, remove 
 642             # them. changing the project is fine, since this is a clone of 
 643             # the project the IDE has. 
 644             self
.GetModel().GetAppInfo().ResetDeploymentDataSources() 
 648                 f 
= open(agpfilepath
, "w") 
 650                 # setting homeDir correctly is required for the "figuring out 
 651                 # relative paths" logic when saving the project 
 652                 self
.GetModel().homeDir 
= stagedir
 
 654                 projectlib
.save(f
, self
.GetModel(), productionDeployment
=True) 
 662     def _FixWsdlAgFiles(self
, stagedir
): 
 663         """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.""" 
 664         files 
= os
.listdir(stagedir
) 
 666             if (f
.endswith(WsdlAgEditor
.WsdlAgDocument
.WSDL_AG_EXT
)): 
 667                 wsdlagpath 
= os
.path
.join(stagedir
, f
) 
 671                     fileObject 
= open(wsdlagpath
) 
 672                     serviceref 
= WsdlAgEditor
.load(fileObject
) 
 675                     if (hasattr(serviceref
, WsdlAgModel
.WSDL_FILE_ATTR
)): 
 676                         modified 
= (modified |
 
 677                                     self
._UpdateServiceRefPathAttr
( 
 678                                         stagedir
, serviceref
, 
 679                                         WsdlAgModel
.WSDL_FILE_ATTR
)) 
 681                     # referenced code file 
 682                     if (hasattr(serviceref
, WsdlAgModel
.LOCAL_SERVICE_ELEMENT
)): 
 683                         lse 
= getattr(serviceref
, 
 684                                       WsdlAgModel
.LOCAL_SERVICE_ELEMENT
) 
 685                         if (hasattr(lse
, WsdlAgModel
.LOCAL_SERVICE_FILE_ATTR
)): 
 686                             modified 
= (modified |
 
 687                                         self
._UpdateServiceRefPathAttr
( 
 689                                             WsdlAgModel
.LOCAL_SERVICE_FILE_ATTR
)) 
 698                 # no need to save the file if we did not change anything 
 699                 if not modified
: continue 
 701                 # write the wsdlag file 
 702                 fileObject 
= open(wsdlagpath
) 
 704                     serviceref 
= WsdlAgEditor
.save(fileObject
, serviceref
) 
 712     def _UpdateServiceRefPathAttr(self
, stagedir
, serviceref
, attrName
): 
 713         """Returns True if serviceref path has been updated, False otherwise.""" 
 715         filePath 
= getattr(serviceref
, attrName
) 
 717         if (filePath 
== None): 
 720         filePath 
= filePath
.strip() 
 722         if (len(filePath
) == 0): 
 726         # if filePath starts with one of the AG systems vars, we don't 
 727         # have to do anything 
 728         if (fileutils
.startsWithAgSystemVar(filePath
)): 
 731         # remove any known env var refs (we'll put them back a little below) 
 732         # we remove them here so that paths that do not have env vars also 
 733         # get parameterized correctly below 
 734         filePath 
= fileutils
.expandKnownAGVars(filePath
) 
 736         # make sure we have forward slashes. this is a workaround, which 
 737         # would not be necessary if we only write paths with forward slashes 
 739         filePath 
= filePath
.replace("\\", "/") 
 741         filePath 
= os
.path
.abspath(filePath
)         
 743         if (not os
.path
.exists(filePath
)): 
 744             # Wrong place to validate that referenced file exists, so just 
 748         # If the referenced file is in stagedir already, there's nothing to do 
 749         if (fileutils
.hasAncestorDir(filePath
, stagedir
)): 
 752         # The path points outside of stagedir. 
 754         # Check if we already have the referenced wsdl file at root, should be 
 755         # the case if the referenced wsdl is part of project. 
 756         # Copy it if we don't have it, unless it lives in one of the known 
 757         # product directories - in which case we parameterize the known path 
 758         # with one of our AG system vars 
 759         relPath 
= os
.path
.basename(filePath
) 
 760         stagePath 
= os
.path
.join(stagedir
, relPath
) 
 762         if (not os
.path
.exists(stagePath
)): 
 763             pFilePath 
= fileutils
.parameterizePathWithAGSystemVar(filePath
) 
 764             if pFilePath 
== filePath
: # no parameterization happened, copy 
 765                 fileutils
.copyFile(filePath
, stagePath
) 
 766                 setattr(serviceref
, attrName
, relPath
) 
 768                 setattr(serviceref
, attrName
, pFilePath
.replace("\\", "/")) 
 770             setattr(serviceref
, attrName
, relPath
) 
 775     def _SetSchemaTargetDataSource(self
, projectFiles
, dsmapping
): 
 776         """Update schema's default data source, if necessary.""" 
 778         for projectFile 
in projectFiles
: 
 779             if (projectFile
.type == basedocmgr
.FILE_TYPE_SCHEMA
): 
 780                 name 
= os
.path
.basename(projectFile
.filePath
) 
 781                 if (dsmapping
.has_key(name
)): 
 782                     schema 
= xmlutils
.load(projectFile
.filePath
) 
 783                     defaultName 
= schema
.getDefaultDataSourceName() 
 784                     if (defaultName 
!= dsmapping
[name
]): 
 785                         schema
.setDefaultDataSourceName(dsmapping
[name
]) 
 786                         xmlutils
.save(projectFile
.filePath
, schema
) 
 789     def _StageFiles(self
, fileDict
): 
 790         """Copy files to staging directory, update filePath attr of project's ProjectFile instances.""" 
 792         # fileDict: ProjectFile instance -> dest path (string) 
 794         for fileRef
, fileDest 
in fileDict
.items(): 
 795             fileutils
.copyFile(fileRef
.filePath
, fileDest
) 
 796             fileRef
.filePath 
= fileDest
 
 798     def _ValidateFilePaths(self
, projectdir
, stagedir
): 
 799         """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. 
 800            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: 
 801              -  match filenames of files living at the root of the project. 
 802              -  are same as those of any other file that lives outside of the projectdir. 
 804            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).""" 
 806         # ProjectFile instance -> dest path (string) 
 809         projectRootFiles 
= sets
.Set()   # live at project root 
 810         foreignFiles 
= sets
.Set()       # live outside of project 
 812         fileRefsToDeploy 
= self
.GetFileRefs() 
 814         for fileRef 
in fileRefsToDeploy
: 
 815             relPath 
= fileutils
.getRelativePath(fileRef
.filePath
, projectdir
) 
 816             filename 
= os
.path
.basename(fileRef
.filePath
)             
 817             if not relPath
: # file lives outside of project dir... 
 819                 # do we have another file with the same name already? 
 820                 if filename 
in foreignFiles
: 
 821                     raise IOError("More than one file with name \"%s\" lives outside of the project. These files need to have unique names" % filename
) 
 822                 foreignFiles
.add(filename
)        
 823                 fileDest 
= os
.path
.join(stagedir
, filename
) 
 825                 # file lives somewhere within the project dir 
 826                 fileDest 
= os
.path
.join(stagedir
, relPath
) 
 827                 if not os
.path
.dirname(relPath
): 
 828                     projectRootFiles
.add(filename
) 
 830             rtn
[fileRef
] = fileDest
 
 832         # make sure we won't collide with a file that lives at root of 
 833         # projectdir when moving files into project 
 834         for filename 
in foreignFiles
: 
 835             if filename 
in projectRootFiles
: 
 836                 raise IOError("File outside of project, \"%s\", cannot have same name as file at project root" % filename
) 
 840     def RenameFolder(self
, oldFolderPath
, newFolderPath
): 
 841         for file in self
.GetModel()._files
: 
 842             if file.logicalFolder 
== oldFolderPath
: 
 843                 file.logicalFolder 
= newFolderPath
 
 844         self
.UpdateAllViews(hint 
= ("rename folder", self
, oldFolderPath
, newFolderPath
)) 
 848     def GetSchemas(self
): 
 849         """Returns list of schema models (activegrid.model.schema.schema) for all schemas in this project.""" 
 852         resourceFactory 
= self
._GetResourceFactory
() 
 853         for projectFile 
in self
.GetModel().projectFiles
: 
 854             if (projectFile
.type == basedocmgr
.FILE_TYPE_SCHEMA
): 
 855                 schema 
= resourceFactory
.getModel(projectFile
) 
 862         return self
.GetModel().filePaths
 
 865     def GetFileRefs(self
): 
 866         return self
.GetModel().findAllRefs() 
 869     def SetFileRefs(self
, fileRefs
): 
 870         return self
.GetModel().setRefs(fileRefs
)     
 873     def IsFileInProject(self
, filename
): 
 874         return self
.GetModel().FindFile(filename
) 
 877     def GetAppInfo(self
): 
 878         return self
.GetModel().GetAppInfo() 
 881     def GetAppDocMgr(self
): 
 882         return self
.GetModel() 
 885     def GetProjectName(self
): 
 886         return os
.path
.splitext(os
.path
.basename(self
.GetFilename()))[0] 
 889     def GetDeploymentFilepath(self
, pre17
=False): 
 891             name 
= self
.GetProjectName() + PRE_17_TMP_DPL_NAME
 
 893             name 
= self
.GetProjectName() + _17_TMP_DPL_NAME
 
 894         return os
.path
.join(self
.GetModel().homeDir
, name
) 
 897     def _GetResourceFactory(self
, preview
=False, deployFilepath
=None): 
 898         return IDEResourceFactory( 
 899             openDocs
=wx
.GetApp().GetDocumentManager().GetDocuments(), 
 900             dataSourceService
=wx
.GetApp().GetService(DataModelEditor
.DataSourceService
), 
 901             projectDir
=os
.path
.dirname(self
.GetFilename()), 
 903             deployFilepath
=deployFilepath
) 
 905     def GenerateDeployment(self
, deployFilepath
=None, preview
=False): 
 907         if ACTIVEGRID_BASE_IDE
: 
 910         if not deployFilepath
: 
 911             deployFilepath 
= self
.GetDeploymentFilepath() 
 913         d 
= DeploymentGeneration
.DeploymentGenerator( 
 914             self
.GetModel(), self
._GetResourceFactory
(preview
, 
 917         dpl 
= d
.getDeployment(deployFilepath
) 
 920             dpl
.initialize()  # used in preview only 
 922         # REVIEW 07-Apr-06 stoens@activegrid.com -- Check if there's a 
 923         # tmp dpl file with pre 17 name, if so, delete it, so user doesn't end 
 924         # up with unused file in project dir. We should probably remove this 
 925         # check after 1.7 goes out. 
 926         fileutils
.remove(self
.GetDeploymentFilepath(pre17
=True)) 
 928         deploymentlib
.saveThroughCache(dpl
.fileName
, dpl
) 
 929         return deployFilepath
 
 931     def AddNameSpaces(self
, filePaths
): 
 932         """ Add any new wsdl and schema namespaces to bpel files """ 
 933         """ Add any new schema namespaces to wsdl files """ 
 934         if ACTIVEGRID_BASE_IDE
: 
 937         processRefs 
= self
.GetAppDocMgr().findRefsByFileType(basedocmgr
.FILE_TYPE_PROCESS
) # bpel 
 938         schemaRefs 
= self
.GetAppDocMgr().findRefsByFileType(basedocmgr
.FILE_TYPE_SCHEMA
) # xsd 
 939         serviceRefs 
= self
.GetAppDocMgr().allServiceRefs  
# wsdl 
 942         if processRefs 
and (serviceRefs 
or schemaRefs
): 
 943             for processRef 
in processRefs
: 
 944                 processDoc 
= processRef
.ideDocument
 
 945                 process 
= processDoc
.GetModel() 
 947                 if processDoc 
and process
: 
 950                     # add wsdl namespaces to bpel file 
 951                     for serviceRef 
in serviceRefs
: 
 952                         wsdl 
= serviceRef
.document
 
 954                         and (wsdl
.fileName 
in filePaths
 
 955                         or serviceRef
.filePath 
in filePaths
)): 
 956                             wsdlLongNS 
= wsdl
.targetNamespace
 
 957                             wsdlShortNS 
= self
.GetAppDocMgr().findShortNS(wsdlLongNS
) 
 959                                 wsdlShortNS 
= xmlutils
.genShortNS(process
, wsdlLongNS
) 
 960                             xmlutils
.addNSAttribute(process
, wsdlShortNS
, wsdlLongNS
) 
 963                     # add schema namespaces to bpel file 
 964                     for schemaRef 
in schemaRefs
: 
 965                         schema 
= schemaRef
.document
 
 966                         if schema 
and schema
.fileName 
in filePaths
: 
 967                             schemaLongNS 
= schema
.targetNamespace
 
 968                             schemaShortNS 
= self
.GetAppDocMgr().findShortNS(schemaLongNS
) 
 969                             if not schemaShortNS
: 
 970                                 schemaShortNS 
= xmlutils
.genShortNS(process
, schemaLongNS
) 
 971                             xmlutils
.addNSAttribute(process
, schemaShortNS
, schemaLongNS
) 
 975                         processDoc
.OnSaveDocument(processDoc
.GetFilename()) 
 979         if serviceRefs 
and schemaRefs
: 
 980             for serviceRef 
in serviceRefs
: 
 981                 wsdl 
= serviceRef
.document
 
 982                 wsdlDoc 
= serviceRef
.ideDocument
 
 987                     # add schema namespace to wsdl file 
 988                     for schemaRef 
in schemaRefs
: 
 989                         schema 
= schemaRef
.document
 
 990                         if schema 
and schema
.fileName 
in filePaths
: 
 991                             schemaLongNS 
= schema
.targetNamespace
 
 992                             schemaShortNS 
= self
.GetAppDocMgr().findShortNS(schemaLongNS
) 
 993                             if not schemaShortNS
: 
 994                                 schemaShortNS 
= xmlutils
.genShortNS(wsdl
, schemaLongNS
) 
 995                             xmlutils
.addNSAttribute(wsdl
, schemaShortNS
, schemaLongNS
) 
 999                         wsdlDoc
.OnSaveDocument(wsdlDoc
.GetFilename()) 
1002 class NewProjectWizard(Wizard
.BaseWizard
): 
1004     WIZTITLE 
= _("New Project Wizard") 
1007     def __init__(self
, parent
): 
1008         self
._parent 
= parent
 
1009         self
._fullProjectPath 
= None 
1010         Wizard
.BaseWizard
.__init
__(self
, parent
, self
.WIZTITLE
) 
1011         self
._projectLocationPage 
= self
.CreateProjectLocation(self
) 
1012         wx
.wizard
.EVT_WIZARD_PAGE_CHANGING(self
, self
.GetId(), self
.OnWizPageChanging
) 
1015     def CreateProjectLocation(self
,wizard
): 
1016         page 
= Wizard
.TitledWizardPage(wizard
, _("Name and Location")) 
1018         page
.GetSizer().Add(wx
.StaticText(page
, -1, _("\nEnter the name and location for the project.\n"))) 
1019         self
._projectName
, self
._dirCtrl
, sizer
, self
._fileValidation 
= UICommon
.CreateDirectoryControl(page
, fileExtension
="agp", appDirDefaultStartDir
=True, fileLabel
=_("Name:"), dirLabel
=_("Location:")) 
1020         page
.GetSizer().Add(sizer
, 1, flag
=wx
.EXPAND
) 
1023         wizard
.FitToPage(page
) 
1027     def RunWizard(self
, existingTables 
= None, existingRelationships 
= None): 
1028         status 
= Wizard
.BaseWizard
.RunWizard(self
, self
._projectLocationPage
) 
1030             wx
.ConfigBase_Get().Write(PROJECT_DIRECTORY_KEY
, self
._dirCtrl
.GetValue()) 
1031             docManager 
= wx
.GetApp().GetTopWindow().GetDocumentManager() 
1032             if os
.path
.exists(self
._fullProjectPath
): 
1033                 # What if the document is already open and we're overwriting it? 
1034                 documents 
= docManager
.GetDocuments() 
1035                 for document 
in documents
: 
1036                     if os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(self
._fullProjectPath
):  # If the renamed document is open, update it 
1037                         document
.DeleteAllViews() 
1039                 os
.remove(self
._fullProjectPath
) 
1041             for template 
in docManager
.GetTemplates(): 
1042                 if template
.GetDocumentType() == ProjectDocument
: 
1043                     doc 
= template
.CreateDocument(self
._fullProjectPath
, flags 
= wx
.lib
.docview
.DOC_NEW
) 
1044                     doc
.OnSaveDocument(self
._fullProjectPath
) 
1045                     projectService 
= wx
.GetApp().GetService(ProjectService
) 
1046                     view 
= projectService
.GetView() 
1047                     view
.AddProjectToView(doc
) 
1054     def OnWizPageChanging(self
, event
): 
1055         if event
.GetDirection():  # It's going forwards 
1056             if event
.GetPage() == self
._projectLocationPage
: 
1057                 if not self
._fileValidation
(validClassName
=True): 
1060                 self
._fullProjectPath 
= os
.path
.join(self
._dirCtrl
.GetValue(),UICommon
.MakeNameEndInExtension(self
._projectName
.GetValue(), PROJECT_EXTENSION
)) 
1063     def OnShowCreatePages(self
): 
1065         import DataModelEditor
 
1066         requestedPos 
= self
.GetPositionTuple() 
1067         projectService 
= wx
.GetApp().GetService(ProjectService
) 
1068         projectView 
= projectService
.GetView() 
1070         wiz 
= DataModelEditor
.ImportExportWizard(projectView
.GetFrame(), pos
=requestedPos
) 
1071         if wiz
.RunWizard(dontDestroy
=True): 
1072            self
._schemaName
.SetValue(wiz
.GetSchemaFileName()) 
1077 class ProjectTemplate(wx
.lib
.docview
.DocTemplate
): 
1080     def CreateDocument(self
, path
, flags
): 
1082             doc 
= wx
.lib
.docview
.DocTemplate
.CreateDocument(self
, path
, flags
) 
1084                 doc
.GetModel()._projectDir 
= os
.path
.dirname(path
) 
1087             wiz 
= NewProjectWizard(wx
.GetApp().GetTopWindow()) 
1090             return None  # never return the doc, otherwise docview will think it is a new file and rename it 
1093 class ProjectAddFilesCommand(wx
.lib
.docview
.Command
): 
1096     def __init__(self
, projectDoc
, filePaths
, folderPath
=None, types
=None, names
=None): 
1097         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1098         self
._projectDoc 
= projectDoc
 
1099         self
._allFilePaths 
= filePaths
 
1100         self
._folderPath 
= folderPath
 
1106             projectService 
= wx
.GetApp().GetService(ProjectService
) 
1107             for filePath 
in self
._allFilePaths
: 
1108                 self
._types
.append(projectService
.FindFileTypeDefault(filePath
)) 
1110         # list of files that will really be added 
1112         for filePath 
in self
._allFilePaths
: 
1113             if not projectDoc
.GetModel().FindFile(filePath
): 
1114                 self
._newFiles
.append(filePath
) 
1118         if len(self
._allFilePaths
) == 1: 
1119             return _("Add File %s") % os
.path
.basename(self
._allFilePaths
[0]) 
1121             return _("Add Files") 
1125         return self
._projectDoc
.AddFiles(self
._allFilePaths
, self
._folderPath
, self
._types
, self
._names
) 
1129         return self
._projectDoc
.RemoveFiles(self
._newFiles
) 
1132 class ProjectRemoveFilesCommand(wx
.lib
.docview
.Command
): 
1135     def __init__(self
, projectDoc
, files
): 
1136         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1137         self
._projectDoc 
= projectDoc
 
1142         if len(self
._files
) == 1: 
1143             return _("Remove File %s") % os
.path
.basename(self
._files
[0].filePath
) 
1145             return _("Remove Files") 
1149         return self
._projectDoc
.RemoveFiles(files
=self
._files
) 
1153         return self
._projectDoc
.AddFiles(files
=self
._files
) 
1157 class ProjectRenameFileCommand(wx
.lib
.docview
.Command
): 
1160     def __init__(self
, projectDoc
, oldFilePath
, newFilePath
, isProject 
= False): 
1161         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1162         self
._projectDoc 
= projectDoc
 
1163         self
._oldFilePath 
= oldFilePath
 
1164         self
._newFilePath 
= newFilePath
 
1165         self
._isProject 
= isProject
 
1169         return _("Rename File %s to %s") % (os
.path
.basename(self
._oldFilePath
), os
.path
.basename(self
._newFilePath
)) 
1173         return self
._projectDoc
.RenameFile(self
._oldFilePath
, self
._newFilePath
, self
._isProject
) 
1177         return self
._projectDoc
.RenameFile(self
._newFilePath
, self
._oldFilePath
, self
._isProject
) 
1180 class ProjectRenameFolderCommand(wx
.lib
.docview
.Command
): 
1181     def __init__(self
, doc
, oldFolderPath
, newFolderPath
): 
1182         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1184         self
._oldFolderPath 
= oldFolderPath
 
1185         self
._newFolderPath 
= newFolderPath
 
1189         return _("Rename Folder %s to %s") % (os
.path
.basename(self
._oldFolderPath
), os
.path
.basename(self
._newFolderPath
)) 
1193         return self
._doc
.RenameFolder(self
._oldFolderPath
, self
._newFolderPath
) 
1197         return self
._doc
.RenameFolder(self
._newFolderPath
, self
._oldFolderPath
) 
1200 class ProjectAddFolderCommand(wx
.lib
.docview
.Command
): 
1201     def __init__(self
, view
, doc
, folderpath
): 
1202         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1205         self
._folderpath 
= folderpath
 
1209         return _("Add Folder %s") % (os
.path
.basename(self
._folderpath
)) 
1213         if self
._view
.GetDocument() != self
._doc
: 
1215         status 
= self
._view
.AddFolder(self
._folderpath
) 
1217             self
._view
._treeCtrl
.UnselectAll() 
1218             item 
= self
._view
._treeCtrl
.FindFolder(self
._folderpath
) 
1219             self
._view
._treeCtrl
.SelectItem(item
) 
1224         if self
._view
.GetDocument() != self
._doc
: 
1226         return self
._view
.DeleteFolder(self
._folderpath
) 
1229 class ProjectRemoveFolderCommand(wx
.lib
.docview
.Command
): 
1230     def __init__(self
, view
, doc
, folderpath
): 
1231         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1234         self
._folderpath 
= folderpath
 
1238         return _("Remove Folder %s") % (os
.path
.basename(self
._folderpath
)) 
1242         if self
._view
.GetDocument() != self
._doc
: 
1244         return self
._view
.DeleteFolder(self
._folderpath
) 
1248         if self
._view
.GetDocument() != self
._doc
: 
1250         status 
= self
._view
.AddFolder(self
._folderpath
) 
1252             self
._view
._treeCtrl
.UnselectAll() 
1253             item 
= self
._view
._treeCtrl
.FindFolder(self
._folderpath
) 
1254             self
._view
._treeCtrl
.SelectItem(item
) 
1258 class ProjectMoveFilesCommand(wx
.lib
.docview
.Command
): 
1260     def __init__(self
, doc
, files
, folderPath
): 
1261         wx
.lib
.docview
.Command
.__init
__(self
, canUndo 
= True) 
1264         self
._newFolderPath 
= folderPath
 
1266         self
._oldFolderPaths 
= [] 
1267         for file in self
._files
: 
1268             self
._oldFolderPaths
.append(file.logicalFolder
) 
1272         if len(self
._files
) == 1: 
1273             return _("Move File %s") % os
.path
.basename(self
._files
[0].filePath
) 
1275             return _("Move Files") 
1279         return self
._doc
.MoveFiles(self
._files
, self
._newFolderPath
) 
1283         return self
._doc
.MoveFiles(self
._files
, self
._oldFolderPaths
)             
1286 class ProjectTreeCtrl(wx
.TreeCtrl
): 
1288     #---------------------------------------------------------------------------- 
1289     # Overridden Methods 
1290     #---------------------------------------------------------------------------- 
1292     def __init__(self
, parent
, id, style
): 
1293         wx
.TreeCtrl
.__init
__(self
, parent
, id, style 
= style
) 
1295         templates 
= wx
.GetApp().GetDocumentManager().GetTemplates() 
1296         iconList 
= wx
.ImageList(16, 16, initialCount 
= len(templates
)) 
1297         self
._iconIndexLookup 
= [] 
1298         for template 
in templates
: 
1299             icon 
= template
.GetIcon() 
1301                 if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1304                     if wx
.GetApp().GetDebug(): 
1305                         print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template
._docTypeName
 
1306                 iconIndex 
= iconList
.AddIcon(icon
) 
1307                 self
._iconIndexLookup
.append((template
, iconIndex
)) 
1309         icon 
= getBlankIcon() 
1310         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1313             if wx
.GetApp().GetDebug(): 
1314                 print "Warning: getBlankIcon isn't 16x16, not crossplatform" 
1315         self
._blankIconIndex 
= iconList
.AddIcon(icon
) 
1317         icon 
= getFolderClosedIcon() 
1318         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1321             if wx
.GetApp().GetDebug(): 
1322                 print "Warning: getFolderIcon isn't 16x16, not crossplatform" 
1323         self
._folderClosedIconIndex 
= iconList
.AddIcon(icon
) 
1325         icon 
= getFolderOpenIcon() 
1326         if icon
.GetHeight() != 16 or icon
.GetWidth() != 16: 
1329             if wx
.GetApp().GetDebug(): 
1330                 print "Warning: getFolderIcon isn't 16x16, not crossplatform" 
1331         self
._folderOpenIconIndex 
= iconList
.AddIcon(icon
) 
1333         self
.AssignImageList(iconList
) 
1336     def OnCompareItems(self
, item1
, item2
): 
1337         item1IsFolder 
= (self
.GetPyData(item1
) == None) 
1338         item2IsFolder 
= (self
.GetPyData(item2
) == None) 
1339         if (item1IsFolder 
== item2IsFolder
):  # if both are folders or both not 
1340             return cmp(self
.GetItemText(item1
).lower(), self
.GetItemText(item2
).lower()) 
1341         elif item1IsFolder 
and not item2IsFolder
: # folders sort above non-folders 
1343         elif not item1IsFolder 
and item2IsFolder
: # folders sort above non-folders 
1347     def AppendFolder(self
, parent
, folderName
): 
1348         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, folderName
) 
1349         self
.SetItemImage(item
, self
._folderClosedIconIndex
, wx
.TreeItemIcon_Normal
) 
1350         self
.SetItemImage(item
, self
._folderOpenIconIndex
, wx
.TreeItemIcon_Expanded
) 
1351         self
.SetPyData(item
, None) 
1355     def AppendItem(self
, parent
, filename
, file): 
1356         item 
= wx
.TreeCtrl
.AppendItem(self
, parent
, filename
) 
1359         template 
= wx
.GetApp().GetDocumentManager().FindTemplateForPath(filename
) 
1361             for t
, iconIndex 
in self
._iconIndexLookup
: 
1363                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Normal
) 
1364                     self
.SetItemImage(item
, iconIndex
, wx
.TreeItemIcon_Expanded
) 
1365 ##                    self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected) 
1370             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Normal
) 
1371             self
.SetItemImage(item
, self
._blankIconIndex
, wx
.TreeItemIcon_Expanded
) 
1372 ##            self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected) 
1374         self
.SetPyData(item
, file) 
1379     def AddFolder(self
, folderPath
): 
1382         if folderPath 
!= None: 
1383             folderTree 
= folderPath
.split('/') 
1385             item 
= self
.GetRootItem() 
1386             for folderName 
in folderTree
: 
1389                 (child
, cookie
) = self
.GetFirstChild(item
) 
1391                     file = self
.GetPyData(child
) 
1395                         if self
.GetItemText(child
) == folderName
: 
1399                     (child
, cookie
) = self
.GetNextChild(item
, cookie
) 
1402                     item 
= self
.AppendFolder(item
, folderName
) 
1403                     folderItems
.append(item
) 
1408     def FindItem(self
, filePath
, parentItem
=None): 
1410             parentItem 
= self
.GetRootItem() 
1412         (child
, cookie
) = self
.GetFirstChild(parentItem
) 
1414             file = self
.GetPyData(child
) 
1416                 if file.filePath 
== filePath
: 
1419                 result 
= self
.FindItem(filePath
, child
)  # do recursive call 
1422             (child
, cookie
) = self
.GetNextChild(parentItem
, cookie
) 
1427     def FindFolder(self
, folderPath
): 
1428         if folderPath 
!= None: 
1429             folderTree 
= folderPath
.split('/') 
1431             item 
= self
.GetRootItem() 
1432             for folderName 
in folderTree
: 
1435                 (child
, cookie
) = self
.GetFirstChild(item
) 
1437                     file = self
.GetPyData(child
) 
1441                         if self
.GetItemText(child
) == folderName
: 
1445                     (child
, cookie
) = self
.GetNextChild(item
, cookie
) 
1453     def FindClosestFolder(self
, x
, y
): 
1454         item
, flags 
= self
.HitTest((x
,y
)) 
1456             file = self
.GetPyData(item
) 
1458                 item 
= self
.GetItemParent(item
) 
1464 class ProjectView(wx
.lib
.docview
.View
): 
1465     LOGICAL_MODE  
= "logical" 
1466     PHYSICAL_MODE 
= "physical" 
1468     #---------------------------------------------------------------------------- 
1469     # Overridden methods 
1470     #---------------------------------------------------------------------------- 
1472     def __init__(self
, service 
= None): 
1473         wx
.lib
.docview
.View
.__init
__(self
) 
1474         # self._service = service  # not used, but kept to match other Services 
1475         self
._projectChoice 
= None 
1476         self
._logicalBtn 
= None 
1477         self
._physicalBtn 
= None 
1478         self
._treeCtrl 
= None 
1479         self
._editingSoDontKillFocus 
= False 
1480         self
._checkEditMenu 
= True 
1481         self
._loading 
= False  # flag to not to try to saving state of folders while it is loading 
1484     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 
1485         return wx
.GetApp().GetDocumentManager() 
1489         projectService 
= wx
.GetApp().GetService(ProjectService
) 
1491             projectService
.SetView(None) 
1492         wx
.lib
.docview
.View
.Destroy(self
) 
1495     def GetDocument(self
): 
1496         if not self
._projectChoice
: 
1499         selItem 
= self
._projectChoice
.GetSelection() 
1500         if selItem 
== wx
.NOT_FOUND
: 
1503         document 
= self
._projectChoice
.GetClientData(selItem
) 
1507     def Activate(self
, activate 
= True): 
1508         if not wx
.GetApp().IsMDI(): 
1509             if activate 
and not self
.IsShown(): 
1513             wx
.lib
.docview
.View
.Activate(self
, activate 
= activate
) 
1514             if activate 
and self
._treeCtrl
: 
1515                 self
._treeCtrl
.SetFocus() 
1518     def OnCreate(self
, doc
, flags
): 
1519         config 
= wx
.ConfigBase_Get() 
1520         if wx
.GetApp().IsMDI(): 
1521             self
._embeddedWindow 
= wx
.GetApp().GetTopWindow().GetEmbeddedWindow(wx
.lib
.pydocview
.EMBEDDED_WINDOW_TOPLEFT
) 
1522             self
.SetFrame(self
._embeddedWindow
) 
1523             frame 
= self
._embeddedWindow
 
1524             wx
.EVT_SIZE(frame
, self
.OnSize
) 
1526             self
._embeddedWindow 
= None 
1527             pos 
= config
.ReadInt("ProjectFrameXLoc", -1), config
.ReadInt("ProjectFrameYLoc", -1) 
1528             # make sure frame is visible 
1529             screenWidth 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_X
) 
1530             screenHeight 
= wx
.SystemSettings
.GetMetric(wx
.SYS_SCREEN_Y
) 
1531             if pos
[0] < 0 or pos
[0] >= screenWidth 
or pos
[1] < 0 or pos
[1] >= screenHeight
: 
1532                 pos 
= wx
.DefaultPosition
 
1534             size 
= wx
.Size(config
.ReadInt("ProjectFrameXSize", -1), config
.ReadInt("ProjectFrameYSize", -1)) 
1536             title 
= _("Projects") 
1537             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI 
and wx
.GetApp().GetAppName(): 
1538                 title 
=  title 
+ " - " + wx
.GetApp().GetAppName() 
1540             frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, 0, title 
= title
, pos 
= pos
, size 
= size
) 
1541             if config
.ReadInt("ProjectFrameMaximized", False): 
1542                 frame
.Maximize(True) 
1544         panel 
= wx
.Panel(frame
, -1) 
1546         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1548         butSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
1550         self
._projectChoice 
= wx
.Choice(panel
, -1) 
1551         panel
.Bind(wx
.EVT_CHOICE
, self
.OnProjectSelect
, self
._projectChoice
) 
1552         w
, h 
= self
._projectChoice
.GetSize() 
1554         self
._logicalBtn 
= wx
.lib
.buttons
.GenBitmapToggleButton(panel
, -1, getLogicalModeOffBitmap(), size
=(h
,h
)) 
1555         self
._logicalBtn
.SetBitmapSelected(getLogicalModeOnBitmap()) 
1556         self
._logicalBtn
.SetToggle(True) 
1557         self
._logicalBtn
.SetToolTipString(_("View Files by Logical Groups")) 
1558         panel
.Bind(wx
.EVT_BUTTON
, self
.OnSelectMode
, self
._logicalBtn
) 
1559         self
._physicalBtn 
= wx
.lib
.buttons
.GenBitmapToggleButton(panel
, -1, getPhysicalModeOffBitmap(), size
=(h
,h
)) 
1560         self
._physicalBtn
.SetBitmapSelected(getPhysicalModeOnBitmap()) 
1561         self
._physicalBtn
.SetToolTipString(_("View Files by Physical Disk Layout")) 
1562         panel
.Bind(wx
.EVT_BUTTON
, self
.OnSelectMode
, self
._physicalBtn
) 
1564         butSizer
.Add(self
._projectChoice
, 1, wx
.EXPAND
) 
1565         butSizer
.Add(self
._logicalBtn
, 0) 
1566         butSizer
.Add(self
._physicalBtn
, 0) 
1567         sizer
.Add(butSizer
, 0, wx
.EXPAND
) 
1569         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
) 
1570         self
._treeCtrl
.AddRoot(_("Projects")) 
1571         if self
._embeddedWindow
: 
1572             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND|wx
.BOTTOM
, HALF_SPACE
)  # allow space for embedded window resize-sash 
1574             sizer
.Add(self
._treeCtrl
, 1, wx
.EXPAND
) 
1575         panel
.SetSizer(sizer
) 
1577         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
1579         if wx
.GetApp().IsMDI(): 
1580             sizer
.Add(panel
, 1, wx
.EXPAND|wx
.BOTTOM
, 3) # wxBug: without bottom margin, can't resize embedded window 
1582             sizer
.Add(panel
, 1, wx
.EXPAND
) 
1584         frame
.SetSizer(sizer
) 
1588         if wx
.GetApp().IsMDI(): 
1589             wx
.EVT_SET_FOCUS(self
._treeCtrl
, self
.OnFocus
) 
1590             wx
.EVT_KILL_FOCUS(self
._treeCtrl
, self
.OnKillFocus
) 
1592         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
1593             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelectionSDI
) 
1595             wx
.EVT_TREE_ITEM_ACTIVATED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnOpenSelection
) 
1596         wx
.EVT_TREE_BEGIN_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginLabelEdit
) 
1597         wx
.EVT_TREE_END_LABEL_EDIT(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndLabelEdit
) 
1598         wx
.EVT_RIGHT_DOWN(self
._treeCtrl
, self
.OnRightClick
) 
1599         wx
.EVT_KEY_DOWN(self
._treeCtrl
, self
.OnKeyPressed
) 
1600         wx
.EVT_TREE_ITEM_COLLAPSED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.SaveFolderState
) 
1601         wx
.EVT_TREE_ITEM_EXPANDED(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.SaveFolderState
) 
1602         wx
.EVT_TREE_BEGIN_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnBeginDrag
) 
1603         wx
.EVT_TREE_END_DRAG(self
._treeCtrl
, self
._treeCtrl
.GetId(), self
.OnEndDrag
) 
1604         wx
.EVT_LEFT_DOWN(self
._treeCtrl
, self
.OnLeftClick
) 
1606         # drag-and-drop support 
1607         dt 
= ProjectFileDropTarget(self
) 
1608         self
._treeCtrl
.SetDropTarget(dt
) 
1613     def OnSelectMode(self
, event
): 
1614         btn 
= event
.GetEventObject() 
1615         down 
= event
.GetIsDown() 
1616         if btn 
== self
._logicalBtn
: 
1617             self
._physicalBtn
.SetToggle(not down
) 
1618         else:  # btn == self._physicalBtn: 
1619             self
._logicalBtn
.SetToggle(not down
) 
1620         self
.LoadProject(self
.GetDocument()) 
1624         if not self
._physicalBtn
.up
: 
1625             return ProjectView
.PHYSICAL_MODE
 
1626         else:  # elif self._logicalBtn.GetValue(): 
1627             return ProjectView
.LOGICAL_MODE
 
1630     def OnProjectSelect(self
, event
=None): 
1631         self
.LoadProject(self
.GetDocument()) 
1632         if self
.GetDocument(): 
1633             filename 
= self
.GetDocument().GetFilename() 
1636         self
._projectChoice
.SetToolTipString(filename
) 
1639     def OnSize(self
, event
): 
1641         wx
.CallAfter(self
.GetFrame().Layout
) 
1644     def OnBeginDrag(self
, event
): 
1645         if self
.GetMode() == ProjectView
.PHYSICAL_MODE
: 
1648         item 
= event
.GetItem() 
1650             self
._draggingItems 
= [] 
1651             for item 
in self
._treeCtrl
.GetSelections(): 
1652                 if self
._IsItemFile
(item
): 
1653                     self
._draggingItems
.append(item
) 
1654             if len(self
._draggingItems
): 
1658     def OnEndDrag(self
, event
): 
1659         item 
= event
.GetItem() 
1662             for ditem 
in self
._draggingItems
: 
1663                 file = self
._GetItemFile
(ditem
) 
1664                 if file not in files
: 
1667             folderPath 
= self
._GetItemFolderPath
(item
) 
1669             self
.GetDocument().GetCommandProcessor().Submit(ProjectMoveFilesCommand(self
.GetDocument(), files
, folderPath
)) 
1672     def WriteProjectConfig(self
): 
1673         frame 
= self
.GetFrame() 
1674         config 
= wx
.ConfigBase_Get() 
1675         if frame 
and not self
._embeddedWindow
: 
1676             if not frame
.IsMaximized(): 
1677                 config
.WriteInt("ProjectFrameXLoc", frame
.GetPositionTuple()[0]) 
1678                 config
.WriteInt("ProjectFrameYLoc", frame
.GetPositionTuple()[1]) 
1679                 config
.WriteInt("ProjectFrameXSize", frame
.GetSizeTuple()[0]) 
1680                 config
.WriteInt("ProjectFrameYSize", frame
.GetSizeTuple()[1]) 
1681             config
.WriteInt("ProjectFrameMaximized", frame
.IsMaximized()) 
1683         if config
.ReadInt("ProjectSaveDocs", True): 
1684             projectFileNames 
= [] 
1687             if self
._projectChoice
: 
1688                 for i 
in range(self
._projectChoice
.GetCount()): 
1689                     project 
= self
._projectChoice
.GetClientData(i
) 
1690                     if not project
.OnSaveModified(): 
1692                     if project
.GetDocumentSaved():  # Might be a new document and "No" selected to save it 
1693                         projectFileNames
.append(str(project
.GetFilename())) 
1694             config
.Write("ProjectSavedDocs", projectFileNames
.__repr
__()) 
1697             if self
._projectChoice
.GetCount(): 
1698                 i 
= self
._projectChoice
.GetSelection() 
1699                 if i 
!= wx
.NOT_FOUND
: 
1700                     document 
= self
._projectChoice
.GetClientData(i
) 
1702                 config
.Write("ProjectCurrent", document
.GetFilename()) 
1704                 config
.DeleteEntry("ProjectCurrent") 
1707     def OnClose(self
, deleteWindow 
= True): 
1708         if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
1709             self
.WriteProjectConfig() 
1711         project 
= self
.GetDocument() 
1714         if not project
.Close(): 
1717         if not deleteWindow
: 
1718             self
.RemoveCurrentDocumentUpdate() 
1720             # need this to accelerate closing down app if treeCtrl has lots of items 
1721             self
._treeCtrl
.Freeze() 
1723                 rootItem 
= self
._treeCtrl
.GetRootItem() 
1724                 self
._treeCtrl
.DeleteChildren(rootItem
) 
1726                 self
._treeCtrl
.Thaw() 
1728         # We don't need to delete the window since it is a floater/embedded 
1732     def _GetParentFrame(self
): 
1733         return wx
.GetTopLevelParent(self
.GetFrame()) 
1736     def OnUpdate(self
, sender 
= None, hint 
= None): 
1737         if wx
.lib
.docview
.View
.OnUpdate(self
, sender
, hint
): 
1741             if hint
[0] == "add": 
1742                 projectDoc 
= hint
[1] 
1743                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1746                 self
._treeCtrl
.Freeze() 
1749                     newFilePaths 
= hint
[2]  # need to be added and selected, and sorted 
1750                     oldFilePaths 
= hint
[3]  # need to be selected 
1751                     self
._treeCtrl
.UnselectAll() 
1753                     mode 
= self
.GetMode() 
1755                     project 
= projectDoc
.GetModel() 
1756                     projectDir 
= project
.homeDir
 
1757                     rootItem 
= self
._treeCtrl
.GetRootItem() 
1759                     # add new folders and new items 
1761                     for filePath 
in newFilePaths
: 
1762                         file = project
.FindFile(filePath
) 
1764                             if mode 
== ProjectView
.LOGICAL_MODE
: 
1765                                 folderPath 
= file.logicalFolder
 
1766                             else:  # ProjectView.PHYSICAL_MODE 
1767                                 folderPath 
= file.physicalFolder
 
1769                                 self
._treeCtrl
.AddFolder(folderPath
) 
1770                                 folder 
= self
._treeCtrl
.FindFolder(folderPath
) 
1773                             item 
= self
._treeCtrl
.AppendItem(folder
, os
.path
.basename(file.filePath
), file) 
1774                             addList
.append(item
) 
1776                     # sort folders with new items 
1778                     for item 
in addList
: 
1779                         parentItem 
= self
._treeCtrl
.GetItemParent(item
) 
1780                         if parentItem 
not in parentList
: 
1781                             parentList
.append(parentItem
) 
1782                     for parentItem 
in parentList
: 
1783                         self
._treeCtrl
.SortChildren(parentItem
) 
1785                     # select all the items user wanted to add 
1787                     for filePath 
in (oldFilePaths 
+ newFilePaths
): 
1788                         item 
= self
._treeCtrl
.FindItem(filePath
) 
1790                             self
._treeCtrl
.SelectItem(item
) 
1794                         self
._treeCtrl
.EnsureVisible(lastItem
) 
1797                     self
._treeCtrl
.Thaw() 
1800             elif hint
[0] == "remove": 
1801                 projectDoc 
= hint
[1] 
1802                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1805                 self
._treeCtrl
.Freeze() 
1809                     self
._treeCtrl
.UnselectAll() 
1811                     for filePath 
in filePaths
: 
1812                         item 
= self
._treeCtrl
.FindItem(filePath
) 
1814                             self
._treeCtrl
.Delete(item
) 
1816                     self
._treeCtrl
.UnselectAll()  # wxBug: even though we unselected earlier, an item still gets selected after the delete 
1819                     self
._treeCtrl
.Thaw() 
1822             elif hint
[0] == "rename": 
1823                 projectDoc 
= hint
[1] 
1824                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1827                 self
._treeCtrl
.Freeze() 
1829                     item 
= self
._treeCtrl
.FindItem(hint
[2]) 
1830                     self
._treeCtrl
.SetItemText(item
, os
.path
.basename(hint
[3])) 
1831                     self
._treeCtrl
.EnsureVisible(item
) 
1833                     self
._treeCtrl
.Thaw() 
1836             elif hint
[0] == "rename folder": 
1837                 projectDoc 
= hint
[1] 
1838                 if self
.GetDocument() != projectDoc
:  # project being updated isn't currently viewed project 
1841                 self
._treeCtrl
.Freeze() 
1843                     item 
= self
._treeCtrl
.FindFolder(hint
[2]) 
1845                         self
._treeCtrl
.UnselectAll() 
1846                         self
._treeCtrl
.SetItemText(item
, os
.path
.basename(hint
[3])) 
1847                         self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
1848                         self
._treeCtrl
.SelectItem(item
) 
1849                         self
._treeCtrl
.EnsureVisible(item
) 
1851                     self
._treeCtrl
.Thaw() 
1855     def RemoveProjectUpdate(self
, projectDoc
): 
1856         """ Called by service after deleting a project, need to remove from project choices """ 
1857         i 
= self
._projectChoice
.FindString(self
._MakeProjectName
(projectDoc
)) 
1858         self
._projectChoice
.Delete(i
) 
1860         numProj 
= self
._projectChoice
.GetCount() 
1864             self
._projectChoice
.SetSelection(i
) 
1865         self
.OnProjectSelect() 
1868     def RemoveCurrentDocumentUpdate(self
, i
=-1): 
1869         """ Called by service after deleting a project, need to remove from project choices """ 
1870         i 
= self
._projectChoice
.GetSelection() 
1871         self
._projectChoice
.Delete(i
) 
1873         numProj 
= self
._projectChoice
.GetCount() 
1877             self
._projectChoice
.SetSelection(i
) 
1878         self
.OnProjectSelect() 
1881     def ProcessEvent(self
, event
): 
1883         if id == ProjectService
.CLOSE_PROJECT_ID
: 
1884             projectDoc 
= self
.GetDocument() 
1886                 projectService 
= wx
.GetApp().GetService(ProjectService
) 
1888                     openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
1889                     for openDoc 
in openDocs
[:]:  # need to make a copy, as each file closes we're off by one 
1890                         if projectDoc 
== openDoc
:  # close project last 
1893                         if projectDoc 
== projectService
.FindProjectFromMapping(openDoc
): 
1894                             self
.GetDocumentManager().CloseDocument(openDoc
, False) 
1896                             projectService
.RemoveProjectMapping(openDoc
) 
1897                             if hasattr(openDoc
, "GetModel"): 
1898                                 projectService
.RemoveProjectMapping(openDoc
.GetModel()) 
1900                 if self
.GetDocumentManager().CloseDocument(projectDoc
, False): 
1901                     self
.RemoveCurrentDocumentUpdate() 
1903         elif id == ProjectService
.ADD_FILES_TO_PROJECT_ID
: 
1904             self
.OnAddFileToProject(event
) 
1906         elif id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
: 
1907             self
.OnAddDirToProject(event
) 
1909         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1910             return False  # Implement this one in the service 
1911         elif id == ProjectService
.ADD_FOLDER_ID
: 
1912             self
.OnAddFolder(event
) 
1914         elif id == ProjectService
.RENAME_ID
: 
1915             self
.OnRename(event
) 
1917         elif id == ProjectService
.DELETE_FILE_ID
: 
1918             self
.OnDeleteFile(event
) 
1920         elif id == ProjectService
.DELETE_PROJECT_ID
: 
1921             self
.OnDeleteProject(event
) 
1923         elif id == wx
.ID_CUT
: 
1926         elif id == wx
.ID_COPY
: 
1929         elif id == wx
.ID_PASTE
: 
1932         elif (id == wx
.ID_CLEAR
 
1933         or id == ProjectService
.REMOVE_FROM_PROJECT
): 
1936         elif id == wx
.ID_SELECTALL
: 
1937             self
.OnSelectAll(event
) 
1939         elif id == ProjectService
.OPEN_SELECTION_ID
: 
1940             self
.OnOpenSelection(event
) 
1942         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1943             self
.OnProperties(event
) 
1945         elif id == ProjectService
.PROJECT_PROPERTIES_ID
: 
1946             self
.OnProjectProperties(event
) 
1952     def ProcessUpdateUIEvent(self
, event
): 
1953         # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here 
1954         if self
._checkEditMenu
: 
1955             doc 
= self
.GetDocument() 
1956             if doc 
and not doc
.GetCommandProcessor().GetEditMenu(): 
1957                 doc
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
1958             self
._checkEditMenu 
= False 
1961         if id == wx
.ID_CLOSE
: 
1962             # Too confusing, so disable closing from "File | Close" menu, must close from "Project | Close Current Project" menu 
1963             if self
.ProjectHasFocus() or self
.FilesHasFocus(): 
1968         elif (id == ProjectService
.ADD_FILES_TO_PROJECT_ID
 
1969         or id == ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
 
1970         or id == ProjectService
.CLOSE_PROJECT_ID
 
1971         or id == ProjectService
.DELETE_PROJECT_ID
): 
1972             event
.Enable(self
.GetDocument() != None) 
1974         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
1975             event
.Enable(False)  # Implement this one in the service 
1977         elif id == ProjectService
.ADD_FOLDER_ID
: 
1978             event
.Enable((self
.GetDocument() != None) and (self
.GetMode() == ProjectView
.LOGICAL_MODE
)) 
1980         elif id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
: 
1982             if self
.ProjectHasFocus(): 
1983                 if self
.GetDocument(): 
1985             elif self
.FilesHasFocus(): 
1986                 items 
= self
._treeCtrl
.GetSelections() 
1989                     if self
._IsItemFile
(item
): 
1992             event
.Enable(status
) 
1994         elif (id == wx
.ID_CUT
 
1996         or id == ProjectService
.DELETE_FILE_ID
 
1997         or id == ProjectService
.REMOVE_FROM_PROJECT
 
1998         or id == ProjectService
.OPEN_SELECTION_ID
): 
1999             event
.Enable(self
._HasFilesSelected
()) 
2001         elif (id == wx
.ID_CLEAR
 
2002         or id == ProjectService
.RENAME_ID
): 
2003             items 
= self
._treeCtrl
.GetSelections() 
2005                 hasViewSelected 
= False 
2007                     if self
._IsItemFile
(item
): 
2008                         file = self
._GetItemFile
(item
) 
2009                         if file.type == 'xform': 
2010                             hasViewSelected 
= True 
2016             event
.Enable(self
._HasFilesSelected
() or (self
.GetDocument() != None and self
.GetMode() == ProjectView
.LOGICAL_MODE 
and self
._HasFoldersSelected
())) 
2018         elif id == wx
.ID_PASTE
: 
2019             event
.Enable(self
.CanPaste()) 
2021         elif id == wx
.ID_SELECTALL
: 
2022             event
.Enable(self
._HasFiles
()) 
2024         elif (id == wx
.ID_PREVIEW
 
2025         or id == wx
.ID_PRINT
): 
2031     #---------------------------------------------------------------------------- 
2033     #---------------------------------------------------------------------------- 
2036         if not self
.GetFrame(): 
2038         return self
.GetFrame().IsShown() 
2045     def Show(self
, show 
= True): 
2046         self
.GetFrame().Show(show
) 
2047         if wx
.GetApp().IsMDI(): 
2048             mdiParentFrame 
= wx
.GetApp().GetTopWindow() 
2049             mdiParentFrame
.ShowEmbeddedWindow(self
.GetFrame(), show
) 
2052     #---------------------------------------------------------------------------- 
2053     # Methods for ProjectDocument and ProjectService to call 
2054     #---------------------------------------------------------------------------- 
2056     def SetProject(self
, projectPath
): 
2057         curSel 
= self
._projectChoice
.GetSelection() 
2058         for i 
in range(self
._projectChoice
.GetCount()): 
2059             document 
= self
._projectChoice
.GetClientData(i
) 
2060             if document
.GetFilename() == projectPath
: 
2061                 if curSel 
!= i
:  # don't reload if already loaded 
2062                     self
._projectChoice
.SetSelection(i
) 
2063                     self
.LoadProject(document
) 
2067     def GetSelectedFile(self
): 
2068         for item 
in self
._treeCtrl
.GetSelections(): 
2069             filePath 
= self
._GetItemFilePath
(item
) 
2075     def GetSelectedFiles(self
): 
2077         for item 
in self
._treeCtrl
.GetSelections(): 
2078             filePath 
= self
._GetItemFilePath
(item
) 
2079             if filePath 
and filePath 
not in filePaths
: 
2080                 filePaths
.append(filePath
) 
2084     def GetSelectedPhysicalFolder(self
): 
2085         if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2088             for item 
in self
._treeCtrl
.GetSelections(): 
2089                 if not self
._IsItemFile
(item
): 
2090                     filePath 
= self
._GetItemFolderPath
(item
) 
2096     def GetSelectedProject(self
): 
2097         document 
= self
.GetDocument() 
2099             return document
.GetFilename() 
2104     def AddProjectToView(self
, document
): 
2105         i 
= self
._projectChoice
.Append(self
._MakeProjectName
(document
), document
) 
2106         self
._projectChoice
.SetSelection(i
) 
2107         self
.OnProjectSelect() 
2110     def LoadProject(self
, document
): 
2111         wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
2112         self
._treeCtrl
.Freeze() 
2115             rootItem 
= self
._treeCtrl
.GetRootItem() 
2116             self
._treeCtrl
.DeleteChildren(rootItem
) 
2119                 mode 
= self
.GetMode() 
2120                 docFilePath 
= document
.GetFilename() 
2122                 if mode 
== ProjectView
.LOGICAL_MODE
: 
2123                     folders 
= document
.GetModel().logicalFolders
 
2125                     folders 
= document
.GetModel().physicalFolders
 
2129                 for folderPath 
in folders
: 
2130                     folderItems 
= folderItems 
+ self
._treeCtrl
.AddFolder(folderPath
) 
2132                 for file in document
.GetModel()._files
: 
2133                     if mode 
== ProjectView
.LOGICAL_MODE
: 
2134                         folder 
= file.logicalFolder
 
2136                         folder 
= file.physicalFolder
 
2138                         folderTree 
= folder
.split('/') 
2141                         for folderName 
in folderTree
: 
2143                             (child
, cookie
) = self
._treeCtrl
.GetFirstChild(item
) 
2145                                 if self
._treeCtrl
.GetItemText(child
) == folderName
: 
2149                                 (child
, cookie
) = self
._treeCtrl
.GetNextChild(item
, cookie
) 
2152                                 print "error folder '%s' not found for %s" % (folder
, file.filePath
) 
2157                     fileItem 
= self
._treeCtrl
.AppendItem(item
, os
.path
.basename(file.filePath
), file) 
2159                 self
._treeCtrl
.SortChildren(rootItem
) 
2160                 for item 
in folderItems
: 
2161                     self
._treeCtrl
.SortChildren(item
) 
2163                 self
.LoadFolderState() 
2165                 self
._treeCtrl
.SetFocus() 
2166                 (child
, cookie
) = self
._treeCtrl
.GetFirstChild(self
._treeCtrl
.GetRootItem()) 
2168                     self
._treeCtrl
.UnselectAll() 
2169                     self
._treeCtrl
.SelectItem(child
) 
2170                     self
._treeCtrl
.ScrollTo(child
) 
2172                 if self
._embeddedWindow
: 
2173                     document
.GetCommandProcessor().SetEditMenu(wx
.GetApp().GetEditMenu(self
._GetParentFrame
())) 
2176             self
._treeCtrl
.Thaw() 
2177             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
2180     def ProjectHasFocus(self
): 
2181         """ Does Project Choice have focus """ 
2182         return (wx
.Window
.FindFocus() == self
._projectChoice
) 
2185     def FilesHasFocus(self
): 
2186         """ Does Project Tree have focus """ 
2187         winWithFocus 
= wx
.Window
.FindFocus() 
2188         if not winWithFocus
: 
2191             if winWithFocus 
== self
._treeCtrl
: 
2193             winWithFocus 
= winWithFocus
.GetParent() 
2197     def ClearFolderState(self
): 
2198         config 
= wx
.ConfigBase_Get() 
2199         config
.DeleteGroup(getProjectKeyName(self
.GetDocument().GetFilename())) 
2202     def SaveFolderState(self
, event
=None): 
2203         """ Save the open/close state of folders """ 
2209         folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2210         for item 
in folderItemList
: 
2211             if self
._treeCtrl
.IsExpanded(item
): 
2212                 folderList
.append(self
._GetItemFolderPath
(item
)) 
2214         config 
= wx
.ConfigBase_Get() 
2215         config
.Write(getProjectKeyName(self
.GetDocument().GetFilename(), self
.GetMode()), repr(folderList
)) 
2218     def LoadFolderState(self
): 
2219         """ Load the open/close state of folders. """ 
2220         self
._loading 
= True 
2222         config 
= wx
.ConfigBase_Get() 
2223         openFolderData 
= config
.Read(getProjectKeyName(self
.GetDocument().GetFilename(), self
.GetMode()), "") 
2225             folderList 
= eval(openFolderData
) 
2227             folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2228             for item 
in folderItemList
: 
2229                 folderPath 
= self
._GetItemFolderPath
(item
) 
2230                 if folderPath 
in folderList
: 
2231                     self
._treeCtrl
.Expand(item
) 
2233                     self
._treeCtrl
.Collapse(item
) 
2236             projectService 
= wx
.GetApp().GetService(ProjectService
) 
2238             folderItemList 
= self
._GetFolderItems
(self
._treeCtrl
.GetRootItem()) 
2239             for item 
in folderItemList
: 
2240                 folderPath 
= self
._GetItemFolderPath
(item
) 
2241                 if projectService
.FindLogicalViewFolderCollapsedDefault(folderPath
):  # get default initial state 
2242                     self
._treeCtrl
.Collapse(item
) 
2244                     self
._treeCtrl
.Expand(item
) 
2246         self
._loading 
= False 
2249     #---------------------------------------------------------------------------- 
2251     #---------------------------------------------------------------------------- 
2253     def OnProperties(self
, event
): 
2254         if self
.ProjectHasFocus(): 
2255             self
.OnProjectProperties(event
) 
2256         elif self
.FilesHasFocus(): 
2257             items 
= self
._treeCtrl
.GetSelections() 
2261             filePath 
= self
._GetItemFilePath
(item
) 
2263                 filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
2264                 filePropertiesService
.ShowPropertiesDialog(filePath
) 
2267     def OnProjectProperties(self
, event
): 
2268         if self
.GetDocument(): 
2269             dlg 
= ProjectPropertiesDialog(wx
.GetApp().GetTopWindow(), self
.GetDocument()) 
2270             dlg
.CenterOnParent() 
2273                 if dlg
.ShowModal() == wx
.ID_OK
: 
2274                     if hasattr(dlg
, "_appInfoCtrl") and dlg
._appInfoCtrl
._grid
.IsCellEditControlShown():  # for Linux 
2275                         dlg
._appInfoCtrl
._grid
.DisableCellEditControl()  # If editor is still active, force it to finish the edit before setting the new model. 
2277                     homeDir 
= dlg
._homeDirCtrl
.GetValue() 
2279                         if homeDir 
== ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
: 
2281                         if homeDir 
and not os
.path
.isdir(homeDir
): 
2282                             wx
.MessageBox(_("Home Dir '%s' does not exist.  Please specify a valid directory.") % homeDir
, 
2283                                         _("Project Properties"), 
2284                                         wx
.OK | wx
.ICON_EXCLAMATION
) 
2286                             if self
.GetDocument().GetModel()._homeDir 
!= homeDir
:  # don't set it if it hasn't changed 
2287                                 self
.GetDocument().GetModel().homeDir 
= homeDir
 
2288                                 self
.GetDocument().Modify(True) 
2291                         wx
.MessageBox(_("Blank Home Dir.  Please specify a valid directory."), 
2292                                     _("Project Properties"), 
2293                                     wx
.OK | wx
.ICON_EXCLAMATION
) 
2299     def OnAddFolder(self
, event
): 
2300         if self
.GetDocument(): 
2301             items 
= self
._treeCtrl
.GetSelections() 
2304                 if self
._IsItemFile
(item
): 
2305                     item 
= self
._treeCtrl
.GetItemParent(item
) 
2307                 folderDir 
= self
._GetItemFolderPath
(item
) 
2313             folderPath 
= _("%sUntitled") % folderDir
 
2315             while self
._treeCtrl
.FindFolder(folderPath
): 
2317                 folderPath 
= _("%sUntitled%s") % (folderDir
, i
) 
2318             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFolderCommand(self
, self
.GetDocument(), folderPath
)) 
2320             self
._treeCtrl
.UnselectAll() 
2321             item 
= self
._treeCtrl
.FindFolder(folderPath
) 
2322             self
._treeCtrl
.SelectItem(item
) 
2323             self
._treeCtrl
.EnsureVisible(item
) 
2327     def AddFolder(self
, folderPath
): 
2328         self
._treeCtrl
.AddFolder(folderPath
) 
2332     def DeleteFolder(self
, folderPath
): 
2333         item 
= self
._treeCtrl
.FindFolder(folderPath
) 
2334         self
._treeCtrl
.Delete(item
) 
2338     def OnAddFileToProject(self
, event
): 
2339         if wx
.Platform 
== "__WXMSW__" or wx
.Platform 
== "__WXGTK__" or wx
.Platform 
== "__WXMAC__": 
2341             for temp 
in self
.GetDocumentManager()._templates
: 
2342                 if temp
.IsVisible(): 
2344                         descr 
= descr 
+ _('|') 
2345                     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 
2346             descr 
= _("All|*.*|%s") % descr 
# spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk 
2350         dialog 
= wx
.FileDialog(self
.GetFrame(), _("Add Files"), wildcard
=descr
, style
=wx
.OPEN|wx
.HIDE_READONLY|wx
.MULTIPLE|wx
.CHANGE_DIR
) 
2351         # dialog.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
2352         if dialog
.ShowModal() != wx
.ID_OK
: 
2355         paths 
= dialog
.GetPaths() 
2360             if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2361                 selections 
= self
._treeCtrl
.GetSelections() 
2363                     item 
= selections
[0] 
2364                     if not self
._IsItemFile
(item
): 
2365                         folderPath 
= self
._GetItemFolderPath
(item
) 
2367             self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), paths
, folderPath
=folderPath
)) 
2368         self
.Activate()  # after add, should put focus on project editor 
2371     def OnAddDirToProject(self
, event
): 
2372         frame 
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("Add Directory Files to Project"), size
= (320,200)) 
2373         contentSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
2375         flexGridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap
=HALF_SPACE
, hgap
=HALF_SPACE
) 
2376         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Directory:")), 0, wx
.ALIGN_CENTER_VERTICAL
, 0) 
2377         lineSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
2378         dirCtrl 
= wx
.TextCtrl(frame
, -1, os
.path
.dirname(self
.GetDocument().GetFilename()), size
=(250,-1)) 
2379         dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
2380         lineSizer
.Add(dirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND
) 
2381         findDirButton 
= wx
.Button(frame
, -1, _("Browse...")) 
2382         lineSizer
.Add(findDirButton
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, HALF_SPACE
) 
2383         flexGridSizer
.Add(lineSizer
, 1, wx
.EXPAND
) 
2385         def OnBrowseButton(event
): 
2386             dlg 
= wx
.DirDialog(frame
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
) 
2387             dir = dirCtrl
.GetValue() 
2390             dlg
.CenterOnParent() 
2391             if dlg
.ShowModal() == wx
.ID_OK
: 
2392                 dirCtrl
.SetValue(dlg
.GetPath()) 
2393                 dirCtrl
.SetToolTipString(dirCtrl
.GetValue()) 
2394                 dirCtrl
.SetInsertionPointEnd() 
2396         wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
) 
2398         visibleTemplates 
= [] 
2399         for template 
in self
.GetDocumentManager()._templates
: 
2400             if template
.IsVisible(): 
2401                 visibleTemplates
.append(template
) 
2405         for template 
in visibleTemplates
: 
2407                 descr 
= descr 
+ _('|') 
2408             descr 
= template
.GetDescription() + _(" (") + template
.GetFileFilter() + _(")") 
2409             choices
.append(descr
) 
2410         choices
.insert(0, _("All"))  # first item 
2411         filterChoice 
= wx
.Choice(frame
, -1, size
=(250, -1), choices
=choices
) 
2412         filterChoice
.SetSelection(0) 
2413         filterChoice
.SetToolTipString(_("Select file type filter.")) 
2414         flexGridSizer
.Add(wx
.StaticText(frame
, -1, _("Files of type:")), 0, wx
.ALIGN_CENTER_VERTICAL
) 
2415         flexGridSizer
.Add(filterChoice
, 1, wx
.EXPAND
) 
2417         contentSizer
.Add(flexGridSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
) 
2419         subfolderCtrl 
= wx
.CheckBox(frame
, -1, _("Add files from subdirectories")) 
2420         subfolderCtrl
.SetValue(True) 
2421         contentSizer
.Add(subfolderCtrl
, 0, wx
.LEFT|wx
.ALIGN_CENTER_VERTICAL
, SPACE
) 
2423         buttonSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
2424         findBtn 
= wx
.Button(frame
, wx
.ID_OK
, _("Add")) 
2425         findBtn
.SetDefault() 
2426         buttonSizer
.Add(findBtn
, 0, wx
.RIGHT
, HALF_SPACE
) 
2427         buttonSizer
.Add(wx
.Button(frame
, wx
.ID_CANCEL
), 0) 
2428         contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
) 
2430         frame
.SetSizer(contentSizer
) 
2433         frame
.CenterOnParent() 
2434         status 
= frame
.ShowModal() 
2437         while status 
== wx
.ID_OK 
and not passedCheck
: 
2438             if not os
.path
.exists(dirCtrl
.GetValue()): 
2439                 dlg 
= wx
.MessageDialog(frame
, 
2440                                        _("'%s' does not exist.") % dirCtrl
.GetValue(), 
2441                                        _("Find in Directory"), 
2442                                        wx
.OK | wx
.ICON_EXCLAMATION
 
2444                 dlg
.CenterOnParent() 
2448                 status 
= frame
.ShowModal() 
2454         if status 
== wx
.ID_OK
: 
2455             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
2458                 doc 
= self
.GetDocument() 
2459                 searchSubfolders 
= subfolderCtrl
.IsChecked() 
2460                 dirString 
= dirCtrl
.GetValue() 
2462                 if os
.path
.isfile(dirString
): 
2463                     # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter. 
2464                     # We'll assume they know what they're doing. 
2469                     index 
= filterChoice
.GetSelection() 
2470                     lastIndex 
= filterChoice
.GetCount()-1 
2471                     if index 
and index 
!= lastIndex
:  # if not All or Any 
2472                         template 
= visibleTemplates
[index
-1] 
2474                     # do search in files on disk 
2475                     for root
, dirs
, files 
in os
.walk(dirString
): 
2476                         if not searchSubfolders 
and root 
!= dirString
: 
2480                             if index 
== 0:  # All 
2481                                 filename 
= os
.path
.join(root
, name
) 
2482                                 # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2483                                 if not doc
.IsFileInProject(filename
): 
2484                                     paths
.append(filename
) 
2485                             else:  # use selected filter 
2486                                 if template
.FileMatchesTemplate(name
): 
2487                                     filename 
= os
.path
.join(root
, name
) 
2488                                     # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. 
2489                                     if not doc
.IsFileInProject(filename
): 
2490                                         paths
.append(filename
) 
2493                 if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2494                     selections 
= self
._treeCtrl
.GetSelections() 
2496                         item 
= selections
[0] 
2497                         if not self
._IsItemFile
(item
): 
2498                             folderPath 
= self
._GetItemFolderPath
(item
) 
2500                 doc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc
, paths
, folderPath
=folderPath
)) 
2501                 self
.Activate()  # after add, should put focus on project editor 
2504                 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
2507     def DoAddFilesToProject(self
, filePaths
, folderPath
): 
2508         # method used by Drag-n-Drop to add files to current Project 
2509         self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), filePaths
, folderPath
)) 
2512     def OnFocus(self
, event
): 
2513         self
.GetDocumentManager().ActivateView(self
) 
2517     def OnKillFocus(self
, event
): 
2518         # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame 
2519         # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame 
2520         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 
2521             topWindow 
= wx
.GetApp().GetTopWindow() 
2522             # wxBug: On Mac, this event can fire during shutdown, even after GetTopWindow() 
2523             # is set to NULL. So make sure we have a TLW before getting the active child. 
2525                 childFrame 
= topWindow
.GetActiveChild() 
2527                     childFrame
.Activate() 
2531     def OnLeftClick(self
, event
): 
2533             wxBug: We also spurious drag events on a single click of on item that is already selected, 
2534             so the solution was to consume the left click event.  But his broke the single click expand/collapse 
2535             of a folder, so if it is a folder, we do an event.Skip() to allow the expand/collapse, 
2536             otherwise we consume the event. 
2538         # if folder let it collapse/expand 
2539         if wx
.Platform 
== '__WXMSW__': 
2540             item
, flags 
= self
._treeCtrl
.HitTest(event
.GetPosition()) 
2541             if item
.IsOk() and self
._treeCtrl
.GetChildrenCount(item
, False): 
2546     def OnRightClick(self
, event
): 
2548         if not self
.GetSelectedProject(): 
2551         if self
._HasFilesSelected
():  # Files context 
2552             menu
.Append(ProjectService
.OPEN_SELECTION_ID
, _("&Open"), _("Opens the selection")) 
2553             menu
.Enable(ProjectService
.OPEN_SELECTION_ID
, True) 
2554             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.OPEN_SELECTION_ID
, self
.OnOpenSelection
) 
2556             extService 
= wx
.GetApp().GetService(ExtensionService
.ExtensionService
) 
2557             if extService 
and extService
.GetExtensions(): 
2559                 for ext 
in extService
.GetExtensions(): 
2560                     if not ext
.opOnSelectedFile
: 
2563                         menu
.AppendSeparator() 
2565                     menu
.Append(ext
.id, ext
.menuItemName
) 
2566                     wx
.EVT_MENU(self
._GetParentFrame
(), ext
.id, extService
.ProcessEvent
) 
2567                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ext
.id, extService
.ProcessUpdateUIEvent
) 
2570             for item 
in self
._treeCtrl
.GetSelections(): 
2571                 if self
._IsItemProcessModelFile
(item
): 
2572                     itemIDs 
= [None, ProjectService
.RUN_SELECTED_PM_ID
, None] 
2574         else:  # Project context 
2576         menuBar 
= self
._GetParentFrame
().GetMenuBar() 
2577         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
] 
2578         svnIDs 
= [SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
2580             itemIDs 
= itemIDs 
+ [None, SVNService
.SVNService
.SVN_UPDATE_ID
, SVNService
.SVNService
.SVN_CHECKIN_ID
, SVNService
.SVNService
.SVN_REVERT_ID
] 
2581         globalIDs 
= [wx
.ID_UNDO
, wx
.ID_REDO
, wx
.ID_CLOSE
, wx
.ID_SAVE
, wx
.ID_SAVEAS
] 
2582         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
] 
2583         for itemID 
in itemIDs
: 
2585                 menu
.AppendSeparator() 
2587                 if itemID 
== ProjectService
.RUN_SELECTED_PM_ID 
and not ACTIVEGRID_BASE_IDE
: 
2588                     webBrowserService 
= wx
.GetApp().GetService(WebBrowserService
.WebBrowserService
) 
2589                     if webBrowserService
: 
2590                         if wx
.Platform 
== '__WXMSW__': 
2591                             menu
.Append(ProjectService
.RUN_SELECTED_PM_ID
, _("Run Process")) 
2592                             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_ID
, self
.ProjectServiceProcessEvent
) 
2594                         if wx
.Platform 
== '__WXMSW__': 
2595                             menuLabel 
= _("Run Process in External Browser") 
2597                             menuLabel 
= _("Run Process") 
2598                         menu
.Append(ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
, menuLabel
) 
2599                         wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
, self
.ProjectServiceProcessEvent
) 
2601                         if wx
.Platform 
== '__WXMSW__': 
2603                             if wx
.GetApp().GetUseTabbedMDI(): 
2604                                 menuLabel 
= _("Run Process in new Tab") 
2606                                 menuLabel 
= _("Run Process in new Window") 
2607                             menu
.Append(ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
, menuLabel
) 
2608                             wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
, self
.ProjectServiceProcessEvent
) 
2610                 elif itemID 
== ProjectService
.REMOVE_FROM_PROJECT
: 
2611                     menu
.Append(ProjectService
.REMOVE_FROM_PROJECT
, _("Remove Selected Files from Project")) 
2612                     wx
.EVT_MENU(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
.OnClear
) 
2613                     wx
.EVT_UPDATE_UI(self
._GetParentFrame
(), ProjectService
.REMOVE_FROM_PROJECT
, self
._GetParentFrame
().ProcessUpdateUIEvent
) 
2615                     item 
= menuBar
.FindItemById(itemID
) 
2618                             svnService 
= wx
.GetApp().GetService(SVNService
.SVNService
) 
2620                         if itemID 
in svnIDs
: 
2621                             if SVN_INSTALLED 
and svnService
: 
2622                                 wx
.EVT_MENU(self
._GetParentFrame
(), itemID
, svnService
.ProcessEvent
) 
2623                         elif itemID 
in globalIDs
: 
2626                             wx
.EVT_MENU(self
._treeCtrl
, itemID
, self
.ProcessEvent
) 
2627                         menu
.Append(itemID
, item
.GetLabel()) 
2628         self
._treeCtrl
.PopupMenu(menu
, wx
.Point(event
.GetX(), event
.GetY())) 
2632     def ProjectServiceProcessEvent(self
, event
): 
2633         projectService 
= wx
.GetApp().GetService(ProjectService
) 
2635             projectService
.ProcessEvent(event
) 
2638     def OnRename(self
, event
=None): 
2639         items 
= self
._treeCtrl
.GetSelections() 
2643         if wx
.Platform 
== "__WXGTK__": 
2644             dlg 
= wx
.TextEntryDialog(self
.GetFrame(), _("Enter New Name"), _("Enter New Name")) 
2645             dlg
.CenterOnParent() 
2646             if dlg
.ShowModal() == wx
.ID_OK
: 
2647                 text 
= dlg
.GetValue() 
2648                 self
.ChangeLabel(item
, text
) 
2651                 self
._treeCtrl
.EditLabel(item
) 
2654     def OnBeginLabelEdit(self
, event
): 
2655         self
._editingSoDontKillFocus 
= True 
2656         item 
= event
.GetItem() 
2657         if self
._IsItemFile
(item
): 
2658             file = self
._GetItemFile
(item
) 
2659             if file.type == 'xform': 
2661         if (self
.GetMode() == ProjectView
.PHYSICAL_MODE
) and not self
._IsItemFile
(item
): 
2665     def OnEndLabelEdit(self
, event
): 
2666         self
._editingSoDontKillFocus 
= False 
2667         item 
= event
.GetItem() 
2668         newName 
= event
.GetLabel() 
2669         if not self
.ChangeLabel(item
, newName
): 
2673     def ChangeLabel(self
, item
, newName
): 
2676         if self
._IsItemFile
(item
): 
2677             oldFilePath 
= self
._GetItemFilePath
(item
) 
2678             newFilePath 
= os
.path
.join(os
.path
.dirname(oldFilePath
), newName
) 
2679             doc 
= self
.GetDocument() 
2680             if not doc
.GetCommandProcessor().Submit(ProjectRenameFileCommand(doc
, oldFilePath
, newFilePath
)): 
2682             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
2684             oldFolderPath 
= self
._GetItemFolderPath
(item
) 
2685             newFolderPath 
= os
.path
.dirname(oldFolderPath
) 
2687                 newFolderPath 
+= "/" 
2688             newFolderPath 
+= newName
 
2689             if self
._treeCtrl
.FindFolder(newFolderPath
): 
2690                 wx
.MessageBox(_("Folder '%s' already exists.") % newName
, 
2692                             wx
.OK | wx
.ICON_EXCLAMATION
, 
2695             doc 
= self
.GetDocument() 
2696             if not doc
.GetCommandProcessor().Submit(ProjectRenameFolderCommand(doc
, oldFolderPath
, newFolderPath
)): 
2698             self
._treeCtrl
.SortChildren(self
._treeCtrl
.GetItemParent(item
)) 
2704         # wxBug: Should be able to use IsSupported/IsSupportedFormat here 
2705         #fileDataObject = wx.FileDataObject() 
2706         #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject) 
2707         hasFilesInClipboard 
= False 
2708         if not wx
.TheClipboard
.IsOpened(): 
2709             if wx
.TheClipboard
.Open(): 
2710                 fileDataObject 
= wx
.FileDataObject() 
2711                 hasFilesInClipboard 
= wx
.TheClipboard
.GetData(fileDataObject
) 
2712                 wx
.TheClipboard
.Close() 
2713         return hasFilesInClipboard
 
2716     def OnCut(self
, event
): 
2721     def OnCopy(self
, event
): 
2722         fileDataObject 
= wx
.FileDataObject() 
2723         items 
= self
._treeCtrl
.GetSelections() 
2725             filePath 
= self
._GetItemFilePath
(item
) 
2727                 fileDataObject
.AddFile(filePath
) 
2728         if len(fileDataObject
.GetFilenames()) > 0 and wx
.TheClipboard
.Open(): 
2729             wx
.TheClipboard
.SetData(fileDataObject
) 
2730             wx
.TheClipboard
.Close() 
2733     def OnPaste(self
, event
): 
2734         if wx
.TheClipboard
.Open(): 
2735             fileDataObject 
= wx
.FileDataObject() 
2736             if wx
.TheClipboard
.GetData(fileDataObject
): 
2738                 if self
.GetMode() == ProjectView
.LOGICAL_MODE
: 
2739                     items 
= self
._treeCtrl
.GetSelections() 
2743                             folderPath 
= self
._GetItemFolderPath
(item
) 
2744                 self
.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self
.GetDocument(), fileDataObject
.GetFilenames(), folderPath
)) 
2745             wx
.TheClipboard
.Close() 
2748     def OnClear(self
, event
): 
2749         if self
._HasFilesSelected
(): 
2750             items 
= self
._treeCtrl
.GetSelections() 
2753                 file = self
._GetItemFile
(item
) 
2756             self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self
.GetDocument(), files
)) 
2758         elif self
._HasFoldersSelected
(): 
2759             items 
= self
._treeCtrl
.GetSelections() 
2761             if self
._treeCtrl
.GetChildrenCount(item
, False): 
2762                 wx
.MessageBox(_("Cannot remove folder '%s'.  Folder is not empty.") % self
._treeCtrl
.GetItemText(item
), 
2764                               wx
.OK | wx
.ICON_EXCLAMATION
, 
2768             folderPath 
= self
._GetItemFolderPath
(item
) 
2769             self
.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFolderCommand(self
, self
.GetDocument(), folderPath
)) 
2772     def OnDeleteFile(self
, event
): 
2773         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
2774                                  _("Delete cannot be reversed.\n\nRemove the selected files from the\nproject and file system permanently?"), 
2776                                  wx
.YES_NO|wx
.ICON_QUESTION
) 
2777         yesNoMsg
.CenterOnParent() 
2778         status 
= yesNoMsg
.ShowModal() 
2780         if status 
== wx
.ID_NO
: 
2783         items 
= self
._treeCtrl
.GetSelections() 
2786             filePath 
= self
._GetItemFilePath
(item
) 
2787             if filePath 
and filePath 
not in delFiles
: 
2788                 delFiles
.append(filePath
) 
2790         # remove selected files from project 
2791         self
.GetDocument().RemoveFiles(delFiles
) 
2793         # remove selected files from file system 
2794         for filePath 
in delFiles
: 
2795             if os
.path
.exists(filePath
): 
2799                     wx
.MessageBox("Could not delete '%s'.  %s" % (os
.path
.basename(filePath
), sys
.exc_value
), 
2801                                   wx
.OK | wx
.ICON_EXCLAMATION
, 
2804     def OnDeleteProject(self
, event
=None, noPrompt
=False, closeFiles
=True, delFiles
=True): 
2806         class DeleteProjectDialog(wx
.Dialog
): 
2808             def __init__(self
, parent
, doc
): 
2809                 wx
.Dialog
.__init
__(self
, parent
, -1, _("Delete Project"), size 
= (310, 330)) 
2811                 sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
2812                 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
) 
2813                 self
._delFilesCtrl 
= wx
.CheckBox(self
, -1, _("Delete all files in project")) 
2814                 self
._delFilesCtrl
.SetValue(True) 
2815                 self
._delFilesCtrl
.SetToolTipString(_("Deletes files from disk, whether open or closed")) 
2816                 sizer
.Add(self
._delFilesCtrl
, 0, wx
.LEFT|wx
.RIGHT|wx
.BOTTOM
, SPACE
) 
2817                 self
._closeDeletedCtrl 
= wx
.CheckBox(self
, -1, _("Close open files belonging to project")) 
2818                 self
._closeDeletedCtrl
.SetValue(True) 
2819                 self
._closeDeletedCtrl
.SetToolTipString(_("Closes open editors for files belonging to project")) 
2820                 sizer
.Add(self
._closeDeletedCtrl
, 0, wx
.LEFT|wx
.RIGHT|wx
.BOTTOM
, SPACE
) 
2822                 sizer
.Add(self
.CreateButtonSizer(wx
.OK | wx
.CANCEL
), 0, wx
.ALIGN_RIGHT|wx
.RIGHT|wx
.LEFT|wx
.BOTTOM
, SPACE
) 
2824                 self
.SetSizer(sizer
) 
2828         doc 
= self
.GetDocument() 
2830             dlg 
= DeleteProjectDialog(self
.GetFrame(), doc
) 
2831             dlg
.CenterOnParent() 
2832             status 
= dlg
.ShowModal() 
2833             delFiles 
= dlg
._delFilesCtrl
.GetValue() 
2834             closeFiles 
= dlg
._closeDeletedCtrl
.GetValue() 
2836             if status 
== wx
.ID_CANCEL
: 
2839         if closeFiles 
or delFiles
: 
2840             filesInProject 
= doc
.GetFiles() 
2841             deploymentFilePath 
= self
.GetDocument().GetDeploymentFilepath() 
2842             if deploymentFilePath
: 
2843                 filesInProject
.append(deploymentFilePath
)  # remove deployment file also. 
2844                 import activegrid
.server
.secutils 
as secutils
 
2845                 keystoreFilePath 
= os
.path
.join(os
.path
.dirname(deploymentFilePath
), secutils
.AGKEYSTORE_FILENAME
) 
2846                 filesInProject
.append(keystoreFilePath
)  # remove keystore file also. 
2848             # don't remove self prematurely 
2849             filePath 
= doc
.GetFilename() 
2850             if filePath 
in filesInProject
: 
2851                 filesInProject
.remove(filePath
) 
2853             # don't close/delete files outside of project's directory 
2854             homeDir 
= doc
.GetModel().homeDir 
+ os
.sep
 
2855             for filePath 
in filesInProject
[:]: 
2856                 fileDir 
= os
.path
.dirname(filePath
) + os
.sep
 
2857                 if not fileDir
.startswith(homeDir
):   
2858                     filesInProject
.remove(filePath
) 
2861             # close any open views of documents in the project 
2862             openDocs 
= self
.GetDocumentManager().GetDocuments()[:]  # need copy or docs shift when closed 
2864                 if d
.GetFilename() in filesInProject
: 
2865                     d
.Modify(False)  # make sure it doesn't ask to save the file 
2866                     if isinstance(d
.GetDocumentTemplate(), ProjectTemplate
):  # if project, remove from project list drop down 
2867                         if self
.GetDocumentManager().CloseDocument(d
, True): 
2868                             self
.RemoveProjectUpdate(d
) 
2869                     else:  # regular file 
2870                         self
.GetDocumentManager().CloseDocument(d
, True) 
2872         # remove files in project from file system 
2875             for filePath 
in filesInProject
: 
2876                 if os
.path
.isfile(filePath
): 
2878                         dirPath 
= os
.path
.dirname(filePath
) 
2879                         if dirPath 
not in dirPaths
: 
2880                             dirPaths
.append(dirPath
) 
2884                         wx
.MessageBox("Could not delete file '%s'.\n%s" % (filePath
, sys
.exc_value
), 
2885                                       _("Delete Project"), 
2886                                       wx
.OK | wx
.ICON_EXCLAMATION
, 
2889         filePath 
= doc
.GetFilename() 
2891         self
.ClearFolderState()  # remove from registry folder settings 
2895             doc
.Modify(False)  # make sure it doesn't ask to save the project 
2896             if self
.GetDocumentManager().CloseDocument(doc
, True): 
2897                 self
.RemoveCurrentDocumentUpdate() 
2899         # remove project file 
2901             dirPath 
= os
.path
.dirname(filePath
) 
2902             if dirPath 
not in dirPaths
: 
2903                 dirPaths
.append(dirPath
) 
2904         if os
.path
.isfile(filePath
): 
2908                 wx
.MessageBox("Could not delete project file '%s'.\n%s" % (filePath
, sys
.exc_value
), 
2909                               _("Delete Prjoect"), 
2910                               wx
.OK | wx
.ICON_EXCLAMATION
, 
2913         # remove empty directories from file system 
2915             dirPaths
.sort()     # sorting puts parent directories ahead of child directories 
2916             dirPaths
.reverse()  # remove child directories first 
2918             for dirPath 
in dirPaths
: 
2919                 if os
.path
.isdir(dirPath
): 
2920                     files 
= os
.listdir(dirPath
) 
2925                             wx
.MessageBox("Could not delete empty directory '%s'.\n%s" % (dirPath
, sys
.exc_value
), 
2926                                           _("Delete Project"), 
2927                                           wx
.OK | wx
.ICON_EXCLAMATION
, 
2931     def OnKeyPressed(self
, event
): 
2932         key 
= event
.KeyCode() 
2933         if key 
== wx
.WXK_DELETE
: 
2939     def OnSelectAll(self
, event
): 
2940         project 
= self
.GetDocument() 
2942             self
.DoSelectAll(self
._treeCtrl
.GetRootItem()) 
2945     def DoSelectAll(self
, parentItem
): 
2946         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
2948             if self
._IsItemFile
(child
): 
2949                 self
._treeCtrl
.SelectItem(child
) 
2951                 self
.DoSelectAll(child
) 
2952             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
2955     def OnOpenSelectionSDI(self
, event
): 
2956         # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window 
2957         wx
.CallAfter(self
.OnOpenSelection
, None) 
2960     def OnOpenSelection(self
, event
): 
2963             items 
= self
._treeCtrl
.GetSelections()[:] 
2965                 filepath 
= self
._GetItemFilePath
(item
) 
2967                     if not os
.path
.exists(filepath
): 
2968                         msgTitle 
= wx
.GetApp().GetAppName() 
2970                             msgTitle 
= _("File Not Found") 
2971                         yesNoMsg 
= wx
.MessageDialog(self
.GetFrame(), 
2972                                       _("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
)), 
2974                                       wx
.YES_NO|wx
.ICON_QUESTION
 
2976                         yesNoMsg
.CenterOnParent() 
2977                         status 
= yesNoMsg
.ShowModal() 
2979                         if status 
== wx
.ID_NO
: 
2981                         findFileDlg 
= wx
.FileDialog(self
.GetFrame(), 
2983                                                  defaultFile
=wx
.lib
.docview
.FileNameFromPath(filepath
), 
2984                                                  style
=wx
.OPEN|wx
.FILE_MUST_EXIST|wx
.CHANGE_DIR
 
2986                         # findFileDlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
2987                         if findFileDlg
.ShowModal() == wx
.ID_OK
: 
2988                             newpath 
= findFileDlg
.GetPath() 
2991                         findFileDlg
.Destroy() 
2993                             # update Project Model with new location 
2994                             self
.GetDocument().UpdateFilePath(filepath
, newpath
) 
2997                     doc 
= self
.GetDocumentManager().CreateDocument(filepath
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
2998                     if not doc 
and filepath
.endswith(PROJECT_EXTENSION
):  # project already open 
2999                         self
.SetProject(filepath
) 
3001                         AddProjectMapping(doc
) 
3004         except IOError, (code
, message
): 
3005             msgTitle 
= wx
.GetApp().GetAppName() 
3007                 msgTitle 
= _("File Error") 
3008             wx
.MessageBox("Could not open '%s'." % wx
.lib
.docview
.FileNameFromPath(filepath
), 
3010                           wx
.OK | wx
.ICON_EXCLAMATION
, 
3014     #---------------------------------------------------------------------------- 
3015     # Convenience methods 
3016     #---------------------------------------------------------------------------- 
3018     def _HasFiles(self
): 
3019         if not self
._treeCtrl
: 
3021         return self
._treeCtrl
.GetCount() > 1    #  1 item = root item, don't count as having files 
3024     def _HasFilesSelected(self
): 
3025         if not self
._treeCtrl
: 
3027         items 
= self
._treeCtrl
.GetSelections() 
3031             if self
._IsItemFile
(item
): 
3036     def _HasFoldersSelected(self
): 
3037         if not self
._treeCtrl
: 
3039         items 
= self
._treeCtrl
.GetSelections() 
3043             if self
._IsItemFile
(item
): 
3048     def _MakeProjectName(self
, project
): 
3049         return project
.GetPrintableName() 
3052     def _GetItemFilePath(self
, item
): 
3053         file = self
._GetItemFile
(item
) 
3055             return file.filePath
 
3060     def _GetItemFolderPath(self
, item
): 
3061         rootItem 
= self
._treeCtrl
.GetRootItem() 
3062         if item 
== rootItem
: 
3065         if self
._IsItemFile
(item
): 
3066             item 
= self
._treeCtrl
.GetItemParent(item
) 
3069         while item 
!= rootItem
: 
3071                 folderPath 
= self
._treeCtrl
.GetItemText(item
) + "/" + folderPath
 
3073                 folderPath 
= self
._treeCtrl
.GetItemText(item
) 
3074             item 
= self
._treeCtrl
.GetItemParent(item
) 
3079     def _GetItemFile(self
, item
): 
3080         return self
._treeCtrl
.GetPyData(item
) 
3083     def _IsItemFile(self
, item
): 
3084         return self
._GetItemFile
(item
) != None 
3087     def _IsItemProcessModelFile(self
, item
): 
3088         if ACTIVEGRID_BASE_IDE
: 
3091         if self
._IsItemFile
(item
): 
3092             filepath 
= self
._GetItemFilePath
(item
) 
3094             for template 
in self
.GetDocumentManager().GetTemplates(): 
3095                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3096                     ext 
= template
.GetDefaultExtension() 
3101             if filepath
.endswith(ext
): 
3107     def _GetChildItems(self
, parentItem
): 
3109         (child
, cookie
) = self
._treeCtrl
.GetFirstChild(parentItem
) 
3111             children
.append(child
) 
3112             (child
, cookie
) = self
._treeCtrl
.GetNextChild(parentItem
, cookie
) 
3116     def _GetFolderItems(self
, parentItem
): 
3118         childrenItems 
= self
._GetChildItems
(parentItem
) 
3119         for childItem 
in childrenItems
: 
3120             if not self
._IsItemFile
(childItem
): 
3121                 folderItems
.append(childItem
) 
3122                 folderItems 
+= self
._GetFolderItems
(childItem
) 
3126 class ProjectFileDropTarget(wx
.FileDropTarget
): 
3128     def __init__(self
, view
): 
3129         wx
.FileDropTarget
.__init
__(self
) 
3133     def OnDropFiles(self
, x
, y
, filePaths
): 
3134         """ Do actual work of dropping files into project """ 
3135         if self
._view
.GetDocument(): 
3137             if self
._view
.GetMode() == ProjectView
.LOGICAL_MODE
: 
3138                 folderItem 
= self
._view
._treeCtrl
.FindClosestFolder(x
,y
) 
3140                     folderPath 
= self
._view
._GetItemFolderPath
(folderItem
) 
3141             self
._view
.DoAddFilesToProject(filePaths
, folderPath
) 
3146     def OnDragOver(self
, x
, y
, default
): 
3147         """ Feedback to show copy cursor if copy is allowed """ 
3148         if self
._view
.GetDocument():  # only allow drop if project exists 
3153 class ProjectPropertiesDialog(wx
.Dialog
): 
3154     RELATIVE_TO_PROJECT_FILE 
= _("relative to project file") 
3156     def __init__(self
, parent
, document
): 
3157         wx
.Dialog
.__init
__(self
, parent
, -1, _("Project Properties"), size 
= (310, 330)) 
3159         filePropertiesService 
= wx
.GetApp().GetService(wx
.lib
.pydocview
.FilePropertiesService
) 
3161         notebook 
= wx
.Notebook(self
, -1) 
3163         tab 
= wx
.Panel(notebook
, -1) 
3164         gridSizer 
= wx
.FlexGridSizer(cols 
= 2, vgap 
= SPACE
, hgap 
= SPACE
) 
3165         gridSizer
.AddGrowableCol(1) 
3166         gridSizer
.Add(wx
.StaticText(tab
, -1, _("Filename:"))) 
3167         filename 
= document
.GetFilename() 
3168         if os
.path
.isfile(filename
): 
3169             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1])) 
3171             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Location:"))) 
3172             gridSizer
.Add(wx
.StaticText(tab
, -1, filePropertiesService
.chopPath(os
.path
.dirname(filename
), length
=50))) 
3174             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Size:"))) 
3175             gridSizer
.Add(wx
.StaticText(tab
, -1, str(os
.path
.getsize(filename
)) + ' ' + _("bytes"))) 
3177             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
3178             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
3179             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
) 
3181             lineSizer 
= wx
.BoxSizer(wx
.VERTICAL
)    # let the line expand horizontally without vertical expansion 
3182             lineSizer
.Add(wx
.StaticLine(tab
, -1, size 
= (10,-1)), 0, wx
.EXPAND
) 
3183             gridSizer
.Add(lineSizer
, flag
=wx
.EXPAND|wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
) 
3185             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Created:"))) 
3186             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getctime(filename
)))) 
3188             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Modified:"))) 
3189             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getmtime(filename
)))) 
3191             gridSizer
.Add(wx
.StaticText(tab
, -1, _("Accessed:"))) 
3192             gridSizer
.Add(wx
.StaticText(tab
, -1, time
.ctime(os
.path
.getatime(filename
)))) 
3194             gridSizer
.Add(wx
.StaticText(tab
, -1, os
.path
.split(filename
)[1] + ' ' + _("[new project]"))) 
3195         spacerGrid 
= wx
.BoxSizer(wx
.HORIZONTAL
)  # add a border around the inside of the tab 
3196         spacerGrid
.Add(gridSizer
, 1, wx
.ALL|wx
.EXPAND
, SPACE
); 
3197         tab
.SetSizer(spacerGrid
) 
3198         notebook
.AddPage(tab
, _("General")) 
3200         tab 
= wx
.Panel(notebook
, -1) 
3201         spacerGrid 
= wx
.BoxSizer(wx
.VERTICAL
)  # add a border around the inside of the tab 
3202         homePathLabel 
= wx
.StaticText(tab
, -1, _("Home Dir:")) 
3203         if document
.GetModel().isDefaultHomeDir
: 
3204             defaultHomeDir 
= ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
 
3206             defaultHomeDir 
= document
.GetModel().homeDir
 
3207         self
._homeDirCtrl 
= wx
.ComboBox(tab
, -1, defaultHomeDir
, size
=(125,-1), choices
=[ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
, document
.GetModel().homeDir
]) 
3208         self
._homeDirCtrl
.SetToolTipString(self
._homeDirCtrl
.GetValue())  
3209         if not document
.GetModel().isDefaultHomeDir
: 
3210             self
._homeDirCtrl
.SetInsertionPointEnd() 
3211         def OnDirChanged(event
): 
3212             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 
3213         wx
.EVT_COMBOBOX(self
._homeDirCtrl
, -1, OnDirChanged
) 
3214         wx
.EVT_TEXT(self
._homeDirCtrl
, -1, OnDirChanged
) 
3215         choosePathButton 
= wx
.Button(tab
, -1, _("Browse...")) 
3216         def OnBrowseButton(event
): 
3217             if self
._homeDirCtrl
.GetValue() == ProjectPropertiesDialog
.RELATIVE_TO_PROJECT_FILE
: 
3218                 defaultHomeDir 
= document
.GetModel().homeDir
 
3220                 defaultHomeDir 
= self
._homeDirCtrl
.GetValue() 
3222             dlg 
= wx
.DirDialog(self
, "Choose a directory:", defaultHomeDir
, 
3223                               style
=wx
.DD_DEFAULT_STYLE|wx
.DD_NEW_DIR_BUTTON
) 
3224             if dlg
.ShowModal() == wx
.ID_OK
: 
3225                 self
._homeDirCtrl
.SetValue(dlg
.GetPath()) 
3226                 self
._homeDirCtrl
.SetInsertionPointEnd() 
3227                 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 
3229         wx
.EVT_BUTTON(choosePathButton
, -1, OnBrowseButton
) 
3230         pathSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3231         pathSizer
.Add(homePathLabel
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
3232         pathSizer
.Add(self
._homeDirCtrl
, 1, wx
.ALIGN_CENTER_VERTICAL|wx
.EXPAND|wx
.LEFT
, HALF_SPACE
) 
3233         pathSizer
.Add(choosePathButton
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.LEFT
, SPACE
) 
3234         spacerGrid
.Add(pathSizer
, 0, wx
.ALL|wx
.EXPAND
, SPACE
); 
3235         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.")) 
3236         spacerGrid
.Add(instructionText
, 0, wx
.ALL
, SPACE
); 
3237         tab
.SetSizer(spacerGrid
) 
3238         notebook
.AddPage(tab
, _("Physical View")) 
3240         if wx
.Platform 
== "__WXMSW__": 
3241             notebook
.SetPageSize((310,300)) 
3243         if not ACTIVEGRID_BASE_IDE
: 
3244             tab 
= wx
.Panel(notebook
, -1) 
3245             self
._appInfoCtrl 
= PropertyService
.PropertyCtrl(tab
, header
=False) 
3246             self
._appInfoCtrl
.SetDocument(document
) 
3247             self
._appInfoCtrl
.SetModel(document
.GetAppInfo()) 
3248             sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3249             sizer
.Add(self
._appInfoCtrl
, 1, wx
.EXPAND|wx
.ALL
, PropertyService
.LEAVE_MARGIN
) 
3251             notebook
.AddPage(tab
, _("App Info")) 
3252             self
._appInfoCtrl
._grid
.AutoSizeColumns() 
3255         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3256         sizer
.Add(notebook
, 0, wx
.ALL | wx
.EXPAND
, SPACE
) 
3257         sizer
.Add(self
.CreateButtonSizer(wx
.OK | wx
.CANCEL
), 0, wx
.ALIGN_RIGHT | wx
.RIGHT | wx
.BOTTOM
, HALF_SPACE
) 
3259         self
.SetSizer(sizer
) 
3264 class ProjectOptionsPanel(wx
.Panel
): 
3267     def __init__(self
, parent
, id): 
3268         wx
.Panel
.__init
__(self
, parent
, id) 
3269         self
._useSashMessageShown 
= False 
3270         config 
= wx
.ConfigBase_Get() 
3271         self
._projSaveDocsCheckBox 
= wx
.CheckBox(self
, -1, _("Remember open projects")) 
3272         self
._projSaveDocsCheckBox
.SetValue(config
.ReadInt("ProjectSaveDocs", True)) 
3273         projectBorderSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3274         projectSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
3275         projectSizer
.Add(self
._projSaveDocsCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
3276         if not ACTIVEGRID_BASE_IDE
: 
3277             self
._projShowWelcomeCheckBox 
= wx
.CheckBox(self
, -1, _("Show Welcome Dialog")) 
3278             self
._projShowWelcomeCheckBox
.SetValue(config
.ReadInt("RunWelcomeDialog2", True)) 
3279             projectSizer
.Add(self
._projShowWelcomeCheckBox
, 0, wx
.ALL
, HALF_SPACE
) 
3281             sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
3282             sizer
.Add(wx
.StaticText(self
, -1, _("Default language for projects:")), 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT
, HALF_SPACE
) 
3283             self
._langCtrl 
= wx
.Choice(self
, -1, choices
=projectmodel
.LANGUAGE_LIST
)             
3284             self
._langCtrl
.SetStringSelection(config
.Read(APP_LAST_LANGUAGE
, projectmodel
.LANGUAGE_DEFAULT
)) 
3285             self
._langCtrl
.SetToolTipString(_("Programming language to be used throughout the project.")) 
3286             sizer
.Add(self
._langCtrl
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT
, MAC_RIGHT_BORDER
) 
3287             projectSizer
.Add(sizer
, 0, wx
.ALL
, HALF_SPACE
) 
3289         projectBorderSizer
.Add(projectSizer
, 0, wx
.ALL
, SPACE
) 
3290         self
.SetSizer(projectBorderSizer
) 
3292         parent
.AddPage(self
, _("Project")) 
3295     def OnUseSashSelect(self
, event
): 
3296         if not self
._useSashMessageShown
: 
3297             msgTitle 
= wx
.GetApp().GetAppName() 
3299                 msgTitle 
= _("Document Options") 
3300             wx
.MessageBox("Project window embedded mode changes will not appear until the application is restarted.", 
3302                           wx
.OK | wx
.ICON_INFORMATION
, 
3304             self
._useSashMessageShown 
= True 
3307     def OnOK(self
, optionsDialog
): 
3308         config 
= wx
.ConfigBase_Get() 
3309         config
.WriteInt("ProjectSaveDocs", self
._projSaveDocsCheckBox
.GetValue()) 
3310         if not ACTIVEGRID_BASE_IDE
: 
3311             config
.WriteInt("RunWelcomeDialog2", self
._projShowWelcomeCheckBox
.GetValue()) 
3312             config
.Write(APP_LAST_LANGUAGE
, self
._langCtrl
.GetStringSelection()) 
3316         return getProjectIcon() 
3319 class ProjectService(Service
.Service
): 
3321     #---------------------------------------------------------------------------- 
3323     #---------------------------------------------------------------------------- 
3324     SHOW_WINDOW 
= wx
.NewId()  # keep this line for each subclass, need unique ID for each Service 
3325     RUN_SELECTED_PM_ID 
= wx
.NewId() 
3326     RUN_SELECTED_PM_INTERNAL_WINDOW_ID 
= wx
.NewId() 
3327     RUN_SELECTED_PM_EXTERNAL_BROWSER_ID 
= wx
.NewId() 
3328     RUN_CURRENT_PM_ID 
= wx
.NewId() 
3329     RUN_CURRENT_PM_INTERNAL_WINDOW_ID 
= wx
.NewId() 
3330     RUN_CURRENT_PM_EXTERNAL_BROWSER_ID 
= wx
.NewId() 
3331     RENAME_ID 
= wx
.NewId() 
3332     OPEN_SELECTION_ID 
= wx
.NewId() 
3333     REMOVE_FROM_PROJECT 
= wx
.NewId() 
3334     DELETE_FILE_ID 
= wx
.NewId() 
3335     ADD_FILES_TO_PROJECT_ID 
= wx
.NewId() 
3336     ADD_CURRENT_FILE_TO_PROJECT_ID 
= wx
.NewId() 
3337     ADD_DIR_FILES_TO_PROJECT_ID 
= wx
.NewId() 
3338     CLOSE_PROJECT_ID 
= wx
.NewId() 
3339     PROJECT_PROPERTIES_ID 
= wx
.NewId() 
3340     ADD_FOLDER_ID 
= wx
.NewId() 
3341     DELETE_PROJECT_ID 
= wx
.NewId() 
3344     #---------------------------------------------------------------------------- 
3345     # Overridden methods 
3346     #---------------------------------------------------------------------------- 
3348     def __init__(self
, serviceName
, embeddedWindowLocation 
= wx
.lib
.pydocview
.EMBEDDED_WINDOW_LEFT
): 
3349         Service
.Service
.__init
__(self
, serviceName
, embeddedWindowLocation
) 
3350         self
._runHandlers 
= [] 
3351         self
._suppressOpenProjectMessages 
= False 
3352         self
._logicalViewDefaults 
= [] 
3353         self
._logicalViewOpenDefaults 
= [] 
3354         self
._fileTypeDefaults 
= [] 
3355         self
._nameDefaults 
= [] 
3356         self
._mapToProject 
= dict() 
3359     def _CreateView(self
): 
3360         return ProjectView(self
) 
3363     def ShowWindow(self
, show 
= True): 
3364         """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """ 
3365         Service
.Service
.ShowWindow(self
, show
) 
3368             project 
= self
.GetView().GetDocument() 
3370                 self
.OpenSavedProjects() 
3373     #---------------------------------------------------------------------------- 
3374     # Service specific methods 
3375     #---------------------------------------------------------------------------- 
3377     def GetSuppressOpenProjectMessages(self
): 
3378         return self
._suppressOpenProjectMessages
 
3381     def SetSuppressOpenProjectMessages(self
, suppressOpenProjectMessages
): 
3382         self
._suppressOpenProjectMessages 
= suppressOpenProjectMessages
 
3385     def GetRunHandlers(self
): 
3386         return self
._runHandlers
 
3389     def AddRunHandler(self
, runHandler
): 
3390         self
._runHandlers
.append(runHandler
) 
3393     def RemoveRunHandler(self
, runHandler
): 
3394         self
._runHandlers
.remove(runHandler
) 
3397     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
3398         Service
.Service
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
) 
3400         projectMenu 
= wx
.Menu() 
3402 ##            accelTable = wx.AcceleratorTable([ 
3403 ##                eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID")) 
3405 ##            frame.SetAcceleratorTable(accelTable) 
3406         isProjectDocument 
= document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
 
3407         if wx
.GetApp().IsMDI() or isProjectDocument
: 
3408             if not menuBar
.FindItemById(ProjectService
.ADD_FILES_TO_PROJECT_ID
): 
3409                 projectMenu
.Append(ProjectService
.ADD_FILES_TO_PROJECT_ID
, _("Add &Files to Project..."), _("Adds a document to the current project")) 
3410                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3411                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3412             if not menuBar
.FindItemById(ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
): 
3413                 projectMenu
.Append(ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project")) 
3414                 wx
.EVT_MENU(frame
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3415                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3416             if not menuBar
.FindItemById(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
): 
3417                 projectMenu
.Append(ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, _("&Add Active File to Project..."), _("Adds the active document to a project")) 
3418                 wx
.EVT_MENU(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessEvent
) 
3419                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3420             if not menuBar
.FindItemById(ProjectService
.ADD_FOLDER_ID
): 
3421                 projectMenu
.Append(ProjectService
.ADD_FOLDER_ID
, _("New Folder"), _("Creates a new folder")) 
3422                 wx
.EVT_MENU(frame
, ProjectService
.ADD_FOLDER_ID
, frame
.ProcessEvent
) 
3423                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.ADD_FOLDER_ID
, frame
.ProcessUpdateUIEvent
) 
3424             if not menuBar
.FindItemById(ProjectService
.CLOSE_PROJECT_ID
): 
3425                 projectMenu
.AppendSeparator() 
3426                 projectMenu
.Append(ProjectService
.CLOSE_PROJECT_ID
, _("Close Project"), _("Closes currently open project")) 
3427                 wx
.EVT_MENU(frame
, ProjectService
.CLOSE_PROJECT_ID
, frame
.ProcessEvent
) 
3428                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.CLOSE_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3429             if not menuBar
.FindItemById(ProjectService
.DELETE_PROJECT_ID
): 
3430                 projectMenu
.Append(ProjectService
.DELETE_PROJECT_ID
, _("Delete Project..."), _("Delete currently open project and its files.")) 
3431                 wx
.EVT_MENU(frame
, ProjectService
.DELETE_PROJECT_ID
, frame
.ProcessEvent
) 
3432                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_PROJECT_ID
, frame
.ProcessUpdateUIEvent
) 
3433             if not menuBar
.FindItemById(ProjectService
.PROJECT_PROPERTIES_ID
): 
3434                 projectMenu
.AppendSeparator() 
3435                 projectMenu
.Append(ProjectService
.PROJECT_PROPERTIES_ID
, _("Project Properties"), _("Project Properties")) 
3436                 wx
.EVT_MENU(frame
, ProjectService
.PROJECT_PROPERTIES_ID
, frame
.ProcessEvent
) 
3437                 wx
.EVT_UPDATE_UI(frame
, ProjectService
.PROJECT_PROPERTIES_ID
, frame
.ProcessUpdateUIEvent
) 
3438         index 
= menuBar
.FindMenu(_("&Format")) 
3440             index 
= menuBar
.FindMenu(_("&View")) 
3441         menuBar
.Insert(index 
+ 1, projectMenu
, _("&Project")) 
3442         editMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&Edit"))) 
3443         if not menuBar
.FindItemById(ProjectService
.RENAME_ID
): 
3444             editMenu
.Append(ProjectService
.RENAME_ID
, _("&Rename"), _("Renames the active item")) 
3445             wx
.EVT_MENU(frame
, ProjectService
.RENAME_ID
, frame
.ProcessEvent
) 
3446             wx
.EVT_UPDATE_UI(frame
, ProjectService
.RENAME_ID
, frame
.ProcessUpdateUIEvent
) 
3447         if not menuBar
.FindItemById(ProjectService
.DELETE_FILE_ID
): 
3448             editMenu
.Append(ProjectService
.DELETE_FILE_ID
, _("Delete File"), _("Delete the file from the project and file system.")) 
3449             wx
.EVT_MENU(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessEvent
) 
3450             wx
.EVT_UPDATE_UI(frame
, ProjectService
.DELETE_FILE_ID
, frame
.ProcessUpdateUIEvent
) 
3455     def OnCloseFrame(self
, event
): 
3456         if not self
.GetView(): 
3459         if wx
.GetApp().IsMDI(): 
3460             # close all non-project documents first 
3461             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3462                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3463                     if not self
.GetDocumentManager().CloseDocument(document
, False): 
3466             # write project config afterwards because user may change filenames on closing of new documents 
3467             self
.GetView().WriteProjectConfig()  # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere 
3469             # close all project documents after closing other documents 
3470             # because user may save a new document with a new name or cancel closing a document 
3471             for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3472                 if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3473                     if not document
.OnSaveModified(): 
3476         # This is called when any SDI frame is closed, so need to check if message window is closing or some other window 
3477         elif self
.GetView() == event
.GetEventObject().GetView(): 
3482     #---------------------------------------------------------------------------- 
3483     # Document Manager Methods 
3484     #---------------------------------------------------------------------------- 
3486     def FindProjectFromMapping(self
, key
): 
3487         """ Find which project a model or document belongs to """ 
3488         return self
._mapToProject
.get(key
) 
3491     def AddProjectMapping(self
, key
, projectDoc
=None): 
3492         """ Generate a mapping from model or document to project.  If no project given, use current project. 
3493             e.g. Which project does this model or document belong to (when it was opened)? 
3496             projectDoc 
= self
.GetCurrentProject() 
3497         self
._mapToProject
[key
] = projectDoc
 
3500     def RemoveProjectMapping(self
, key
): 
3501         """ Remove mapping from model or document to project.  """ 
3502         if self
._mapToProject
.has_key(key
): 
3503             del self
._mapToProject
[key
] 
3506     #---------------------------------------------------------------------------- 
3507     # Default Logical View Folder Methods 
3508     #---------------------------------------------------------------------------- 
3510     def AddLogicalViewFolderDefault(self
, pattern
, folder
): 
3511         self
._logicalViewDefaults
.append((pattern
, folder
)) 
3514     def FindLogicalViewFolderDefault(self
, filename
): 
3515         for (pattern
, folder
) in self
._logicalViewDefaults
: 
3516             if filename
.endswith(pattern
): 
3521     def AddLogicalViewFolderCollapsedDefault(self
, folderName
, collapsed
=True): 
3522         # default is collapsed, don't add to list if collapse is True 
3524             self
._logicalViewOpenDefaults
.append(folderName
) 
3527     def FindLogicalViewFolderCollapsedDefault(self
, folderName
): 
3528         if folderName 
in self
._logicalViewOpenDefaults
: 
3533     #---------------------------------------------------------------------------- 
3534     # Default File Type Methods 
3535     #---------------------------------------------------------------------------- 
3537     def AddFileTypeDefault(self
, pattern
, type): 
3538         self
._fileTypeDefaults
.append((pattern
, type)) 
3541     def FindFileTypeDefault(self
, filename
): 
3542         for (pattern
, type) in self
._fileTypeDefaults
: 
3543             if filename
.endswith(pattern
): 
3548     #---------------------------------------------------------------------------- 
3549     # Default Name Methods 
3550     #---------------------------------------------------------------------------- 
3552     def AddNameDefault(self
, pattern
, method
): 
3553         self
._nameDefaults
.append((pattern
, method
)) 
3556     def FindNameDefault(self
, filename
): 
3557         for (pattern
, method
) in self
._nameDefaults
: 
3558             if filename
.endswith(pattern
): 
3559                 return method(filename
) 
3563     def GetDefaultNameCallback(self
, filename
): 
3564         """ A method for generating name from filepath for Project Service """ 
3565         return os
.path
.splitext(os
.path
.basename(filename
))[0] 
3568     #---------------------------------------------------------------------------- 
3569     # Event Processing Methods 
3570     #---------------------------------------------------------------------------- 
3572     def ProcessEventBeforeWindows(self
, event
): 
3575         if id == wx
.ID_CLOSE_ALL
: 
3576             self
.OnFileCloseAll(event
) 
3581     def ProcessUpdateUIEventBeforeWindows(self
, event
): 
3584         if id == wx
.ID_CLOSE_ALL
: 
3585             for document 
in self
.GetDocumentManager().GetDocuments(): 
3586                 if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3593         elif id == wx
.ID_CLOSE
: 
3594             # "File | Close" is too confusing and hard to determine whether user wants to close a viewed file or the current project. 
3595             # Disallow "File | Close" if project is current document or active in project view. 
3596             # User must explicitly close project via "Project | Close Current Project". 
3597             document 
= self
.GetDocumentManager().GetCurrentDocument() 
3598             if document 
and document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3601             if self
.GetView().ProcessUpdateUIEvent(event
): 
3607     def ProcessEvent(self
, event
): 
3608         if Service
.Service
.ProcessEvent(self
, event
): 
3612         if id == ProjectService
.RUN_SELECTED_PM_ID
: 
3613             self
.OnRunProcessModel(event
, runSelected
=True) 
3615         elif id == ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
: 
3616             self
.OnRunProcessModel(event
, runSelected
=True, newWindow
=True, forceInternal
=True) 
3618         elif id == ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
: 
3619             self
.OnRunProcessModel(event
, runSelected
=True, newWindow
=True, forceExternal
=True) 
3621         elif id == ProjectService
.RUN_CURRENT_PM_ID
: 
3622             self
.OnRunProcessModel(event
, runCurrentFile
=True) 
3624         elif id == ProjectService
.RUN_CURRENT_PM_INTERNAL_WINDOW_ID
: 
3625             self
.OnRunProcessModel(event
, runCurrentFile
=True, newWindow
=True, forceInternal
=True) 
3627         elif id == ProjectService
.RUN_CURRENT_PM_EXTERNAL_BROWSER_ID
: 
3628             self
.OnRunProcessModel(event
, runCurrentFile
=True, newWindow
=True, forceExternal
=True) 
3630         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
3631             self
.OnAddCurrentFileToProject(event
) 
3633         elif (id == ProjectService
.PROJECT_PROPERTIES_ID
 
3634         or id == wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
 
3635         or id == ProjectService
.ADD_FOLDER_ID
 
3636         or id == ProjectService
.DELETE_PROJECT_ID
 
3637         or id == ProjectService
.CLOSE_PROJECT_ID
): 
3639                 return self
.GetView().ProcessEvent(event
) 
3646     def ProcessUpdateUIEvent(self
, event
): 
3647         if Service
.Service
.ProcessUpdateUIEvent(self
, event
): 
3651         if id in [ProjectService
.RUN_SELECTED_PM_ID
, 
3652         ProjectService
.RUN_SELECTED_PM_INTERNAL_WINDOW_ID
, 
3653         ProjectService
.RUN_SELECTED_PM_EXTERNAL_BROWSER_ID
, 
3654         ProjectService
.RUN_CURRENT_PM_ID
, 
3655         ProjectService
.RUN_CURRENT_PM_INTERNAL_WINDOW_ID
, 
3656         ProjectService
.RUN_CURRENT_PM_EXTERNAL_BROWSER_ID
]: 
3659         elif id == ProjectService
.ADD_CURRENT_FILE_TO_PROJECT_ID
: 
3660             event
.Enable(self
._CanAddCurrentFileToProject
()) 
3662         elif id in [ProjectService
.ADD_FILES_TO_PROJECT_ID
, 
3663         ProjectService
.ADD_DIR_FILES_TO_PROJECT_ID
, 
3664         ProjectService
.RENAME_ID
, 
3665         ProjectService
.OPEN_SELECTION_ID
, 
3666         ProjectService
.DELETE_FILE_ID
]: 
3669         elif id == ProjectService
.PROJECT_PROPERTIES_ID
: 
3670             event
.Enable(self
._HasOpenedProjects
()) 
3672         elif id in [wx
.lib
.pydocview
.FilePropertiesService
.PROPERTIES_ID
, 
3673         ProjectService
.ADD_FOLDER_ID
, 
3674         ProjectService
.DELETE_PROJECT_ID
, 
3675         ProjectService
.CLOSE_PROJECT_ID
]: 
3677                 return self
.GetView().ProcessUpdateUIEvent(event
) 
3684     def OnRunProcessModel(self
, event
, runSelected
=False, runCurrentFile
=False, newWindow
=False, forceExternal
=False, forceInternal
=False): 
3685         project 
= self
.GetCurrentProject() 
3688             doc 
= self
.GetDocumentManager().GetCurrentDocument() 
3689             if not doc 
or not hasattr(doc
, "GetFilename"): 
3691             fileToRun 
= doc
.GetFilename() 
3692             projects 
= self
.FindProjectByFile(fileToRun
) 
3695             elif project 
in projects
: 
3696                 # use current project 
3698             elif len(projects
) == 1: 
3699                 # only one project, display it 
3700                 project 
= projects
[0] 
3701                 self
.GetView().SetProject(project
.GetFilename()) 
3702             elif len(projects
) > 1: 
3703                 strings 
= map(lambda file: os
.path
.basename(file.GetFilename()), projects
) 
3704                 res 
= wx
.GetSingleChoiceIndex(_("More than one project uses '%s'.  Select project to run:") % os
.path
.basename(fileToRun
), 
3705                                               _("Select Project"), 
3707                                               self
.GetView()._GetParentFrame
()) 
3710                 project 
= projects
[res
] 
3711                 self
.GetView().SetProject(project
.GetFilename()) 
3715             for template 
in self
.GetDocumentManager().GetTemplates(): 
3716                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3717                     ext 
= template
.GetDefaultExtension() 
3722             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
3726             docs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
3728             filesModified 
= False 
3730                 if doc
.IsModified(): 
3731                     filesModified 
= True 
3734                 frame 
= self
.GetView().GetFrame() 
3735                 yesNoMsg 
= wx
.MessageDialog(frame
, 
3736                               _("Files have been modified.  Process may not reflect your current changes.\n\nWould you like to save all files before running?"), 
3738                               wx
.YES_NO|wx
.ICON_QUESTION
 
3740                 yesNoMsg
.CenterOnParent() 
3741                 status 
= yesNoMsg
.ShowModal() 
3743                 if status 
== wx
.ID_YES
: 
3744                     wx
.GetTopLevelParent(frame
).OnFileSaveAll(None) 
3747                 fileToRun 
= self
.GetDocumentManager().GetCurrentDocument().GetFilename() 
3749                 fileToRun 
= self
.GetView().GetSelectedFile() 
3750             elif len(files
) > 1: 
3751                 files
.sort(lambda a
, b
: cmp(os
.path
.basename(a
).lower(), os
.path
.basename(b
).lower())) 
3752                 strings 
= map(lambda file: os
.path
.basename(file), files
) 
3753                 res 
= wx
.GetSingleChoiceIndex(_("Select a process to run:"), 
3756                                               self
.GetView()._GetParentFrame
()) 
3759                 fileToRun 
= files
[res
] 
3761                 fileToRun 
= files
[0] 
3764                 deployFilePath 
= project
.GenerateDeployment() 
3765             except DataServiceExistenceException
, e
: 
3766                 dataSourceName 
= str(e
) 
3767                 self
.PromptForMissingDataSource(dataSourceName
) 
3769             self
.RunProcessModel(fileToRun
, project
.GetAppInfo().language
, deployFilePath
, newWindow
, forceExternal
, forceInternal
) 
3772     def RunProcessModel(self
, fileToRun
, language
, deployFilePath
, newWindow
=True, forceExternal
=False, forceInternal
=False): 
3773         for runHandler 
in self
.GetRunHandlers(): 
3774             if runHandler
.RunProjectFile(fileToRun
, language
, deployFilePath
, newWindow
, forceExternal
, forceInternal
): 
3776         os
.system('"' + fileToRun 
+ '"') 
3779     def _HasProcessModel(self
): 
3780         project 
= self
.GetView().GetDocument() 
3784             for template 
in self
.GetDocumentManager().GetTemplates(): 
3785                 if template
.GetDocumentType() == ProcessModelEditor
.ProcessModelDocument
: 
3786                     ext 
= template
.GetDefaultExtension() 
3791             files 
= filter(lambda f
: f
.endswith(ext
), project
.GetFiles()) 
3801     def _HasOpenedProjects(self
): 
3802         for document 
in self
.GetDocumentManager().GetDocuments(): 
3803             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3808     def _CanAddCurrentFileToProject(self
): 
3809         currentDoc 
= self
.GetDocumentManager().GetCurrentDocument() 
3812         if currentDoc
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3814         if not currentDoc
._savedYet
: 
3816         if self
.GetView().GetDocument():  # a project is open 
3818         return False  # There are no documents open 
3821     def GetFilesFromCurrentProject(self
): 
3822         view 
= self
.GetView() 
3824             project 
= view
.GetDocument() 
3826                 return project
.GetFiles() 
3830     def GetCurrentProject(self
): 
3831         view 
= self
.GetView() 
3833             return view
.GetDocument() 
3837     def GetOpenProjects(self
): 
3839         for document 
in self
.GetDocumentManager().GetDocuments(): 
3840             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3841                 retval
.append(document
) 
3845     def FindProjectByFile(self
, filename
): 
3847         for document 
in self
.GetDocumentManager().GetDocuments(): 
3848             if document
.GetDocumentTemplate().GetDocumentType() == ProjectDocument
: 
3849                 if document
.GetFilename() == filename
: 
3850                     retval
.append(document
) 
3851                 elif document
.IsFileInProject(filename
): 
3852                     retval
.append(document
) 
3854         # make sure current project is first in list 
3855         currProject 
= self
.GetCurrentProject() 
3856         if currProject 
and currProject 
in retval
: 
3857             retval
.remove(currProject
) 
3858             retval
.insert(0, currProject
) 
3863     def OnAddCurrentFileToProject(self
, event
): 
3864         doc 
= self
.GetDocumentManager().GetCurrentDocument() 
3865         file = doc
.GetFilename() 
3866         projectDoc 
= self
.GetView().GetDocument() 
3867         projectDoc
.GetCommandProcessor().Submit(ProjectAddFilesCommand(projectDoc
, [file])) 
3869         AddProjectMapping(doc
, projectDoc
) 
3871         self
.GetView().Activate()  # after add, should put focus on project editor 
3874     def OnFileCloseAll(self
, event
): 
3875         for document 
in self
.GetDocumentManager().GetDocuments()[:]:  # Cloning list to make sure we go through all docs even as they are deleted 
3876             if document
.GetDocumentTemplate().GetDocumentType() != ProjectDocument
: 
3877                 if not self
.GetDocumentManager().CloseDocument(document
, False): 
3879                 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed 
3882     def OpenSavedProjects(self
): 
3883         config 
= wx
.ConfigBase_Get() 
3885         if config
.ReadInt("ProjectSaveDocs", True): 
3886             docString 
= config
.Read("ProjectSavedDocs") 
3889                 docList 
= eval(docString
) 
3890                 self
.GetView()._treeCtrl
.Freeze() 
3892                 for fileName 
in docList
: 
3893                     if isinstance(fileName
, types
.StringTypes
): 
3894                         if os
.path
.exists(fileName
): 
3895                             doc 
= self
.GetDocumentManager().CreateDocument(fileName
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
3896                 self
.GetView()._treeCtrl
.Thaw() 
3901                 currProject 
= config
.Read("ProjectCurrent") 
3902                 if currProject 
in docList
: 
3903                     self
.GetView().SetProject(currProject
) 
3908     def PromptForMissingDataSource(self
, dataSourceName
): 
3909         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
 
3910         msgTitle 
= "Unknown Data Source" 
3911         dataSourceMissingDlg 
= wx
.MessageDialog(self
.GetView().GetFrame(), prompt
, msgTitle
, wx
.YES_NO|wx
.ICON_QUESTION
) 
3912         dataSourceMissingDlg
.CenterOnParent() 
3913         if dataSourceMissingDlg
.ShowModal() == wx
.ID_YES
: 
3914             dataSourceMissingDlg
.Destroy() 
3915             self
._AddDataSource
(dataSourceName
) 
3917             dataSourceMissingDlg
.Destroy() 
3920     def _AddDataSource(self
, defaultDataSourceName
=None): 
3921         dataSourceService 
= wx
.GetApp().GetService(DataModelEditor
.DataSourceService
) 
3922         dsChoices 
= dataSourceService
.getDataSourceNames() 
3923         dlg 
= DataModelEditor
.AddDataSourceDialog(self
.GetView().GetFrame(), 'Add Data Source', dsChoices
, defaultDataSourceName
) 
3924         dlg
.CenterOnParent() 
3925         if dlg
.ShowModal() == wx
.ID_OK
: 
3926             dataSource 
= dlg
.GetDataSource() 
3931         if (dataSource 
== None): 
3932             wx
.MessageBox(_("Error getting data source."), self
._title
) 
3933         dataSourceService
.updateDataSource(dataSource
) 
3934         if ((dsChoices 
== None) or (len(dsChoices
) <= 0)): 
3935             wx
.ConfigBase_Get().Write(DataModelEditor
.SchemaOptionsPanel
.DEFAULT_DATASOURCE_KEY
, dataSource
.name
) 
3936         dataSourceService
.save() 
3940 #---------------------------------------------------------------------------- 
3941 # Icon Bitmaps - generated by encode_bitmaps.py 
3942 #---------------------------------------------------------------------------- 
3943 from wx 
import ImageFromStream
, BitmapFromImage
 
3947 def getProjectData(): 
3949 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3950 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3951 \x00\x01\x89IDAT8\x8d\xa5\x92\xcdJ\x02Q\x18\x86\x9fq&-+H\xd40\x033Bha\x05\ 
3952 \xfd\xac*[\xb7l\xd1\xae\xfbhQ7\x10\x04A]\x86\xd0&\xba\x01CW\n!B\xa2\x882\x8b\ 
3953 )R+"\x7fft\x9a\x16\x91\xcd4\xd3\x0f\xf4\xee\xce\xf9\xde\xf7\xe1\xfd\x0eG\x10\ 
3954 \\"\x9arb\xe8\xcf\x1a\x9d\x9e\n\x80\xd6\xad\x03\x10Z;\x13\xf8ER\xa7xd\x88\ 
3955 \xbe-D\x1f\xb8\xbf\x0c\xaf\xcf\x15C\xd2k\xf4\xc5(\x92^\x03 \xbe\x9b\xb3@\x85\ 
3956 n\xe9\xd8h\xde\xe6\x1d\xe9\xfe\xa9E\xc7\xfb\x91\xf9\xfd\x01D\xfa\xc9\xd8\xf7\ 
3957 \xcdPI\'\x01X\xd8>@p\xf7\x00($W\x8c\x8f&R\xa7\xa7\xa2u\xebL.\xef\xd9\x00\x97\ 
3958 \xa7\x87D\\er\x15\x95\xb9\xf5\x12\xa3\x81Y\x9bG\xfax0\xb3Z\x8d*\x95t\x92z\ 
3959 \xb5\x80yjhC\x83\x16\x96\x15\xdc\xc3AZ\x8d\xea{XN#g.,\xa6\xe0l\x9c\xde}\x89\ 
3960 \xb6\xc3\x9aR\xff\xe5\x01\x801}\x1c\x80\x9b\xcc\x05\xde\xb0\x9f\xd0t\x04oX\ 
3961 \xa6\xad4\xc9U\n\xc0&\x1e\xfd\xd6\x0e\x18\xd4Se\x00\xbca?m\xa5\xc9\x1d\xd0V\ 
3962 \x9a\x03\xa3\xd6\xadc\xa8\x8fv\xc0S\xa3H\xc8\x13\x01\xa2\x00\xc4V\x13\x94\ 
3963 \xb3)\xae\xae\x14\x8b\xd1\x17\x90laK\x03\xb3b\xab\t&\x02\xf7(\xf94\xf2k\x8c\ 
3964 \x8d\x8dy\xc7\xf0\xb7\x00\x80`t\x92`t\x87%\xa0\x9cM\xd1\xa8}\xce\xcc\xbf\xd1\ 
3965 \x11P\xce\xa6,\xe7\xaf\xdf\xd7,Ap\x89\x14\x92+\xc6_\x03\x8e\x80\xff\xc8\xf5\ 
3966 \xaf4\xf0\x06=\xf3\x8fJr]C\xd9\x00\x00\x00\x00IEND\xaeB`\x82' 
3968 def getProjectBitmap(): 
3969     return BitmapFromImage(getProjectImage()) 
3971 def getProjectImage(): 
3972     stream 
= cStringIO
.StringIO(getProjectData()) 
3973     return ImageFromStream(stream
) 
3975 def getProjectIcon(): 
3976     return wx
.IconFromBitmap(getProjectBitmap()) 
3979 #---------------------------------------------------------------------------- 
3983 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
3984 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
3985 \x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\ 
3986 \x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\ 
3987 \x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\ 
3988 \xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\ 
3989 \x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\ 
3990 \x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\ 
3991 \xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\ 
3992 \xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\ 
3993 \x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\ 
3994 \xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\ 
3995 \xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\ 
3999 def getBlankBitmap(): 
4000     return BitmapFromImage(getBlankImage()) 
4002 def getBlankImage(): 
4003     stream 
= cStringIO
.StringIO(getBlankData()) 
4004     return ImageFromStream(stream
) 
4007     return wx
.IconFromBitmap(getBlankBitmap()) 
4010 #---------------------------------------------------------------------- 
4011 def getFolderClosedData(): 
4013 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4014 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4015 \x00\x00\xffIDAT8\x8d\xa5\x93?N\x02A\x14\x87\xbf\x19&\x10B\xb4A\x0b*iL0!$\ 
4016 \x06\x0f\xe0\x05lH\x88G\xe1\x0c\xdbx\x11ZN`,\xa5\x01\x8aM\xa4\x80\x84\xc4Fc\ 
4017 \xd0\xe8\xb0\xae\xbbc\x01\x0b,\x19\x16X~\xd5\x9b\xf7\xe7\x9by3o\x84\x90\x19\ 
4018 \x8e\x91\x8a\x0c\xed:\x06\xc0\xf7g\x00x\xde\x14\x80\xf3\x9b\x07\xb1\x13\xa0]\ 
4019 \xc7d\xcbw\x00d\x17\x81\x82\xff\x01\xc0\xb0\xd3\x9f\x83\x7f\xf5\xb2\xe8\xaa\ 
4020 \xf1\xb4\x84\n!3h\xd71\xef\xaf=\xeb\x0e\xc5R\xcd\xea\xcfWZ"\xd6\xc2\xb6\xc4\ 
4021 \xdc\xe5\xad\xd5?h\xd7M\xb5\xd9\x15\n\xe6}{\xde\x94\xe2\xf5\xbd59I\x12V\x17\ 
4022 \x96F\n \xfc\xfbD\xaaS\xc2\x9fI:@\x041\xdf\xa3\x8d\xb0Y\xb3\xed\xaf\xa9\x00\ 
4023 \xbe\xde\xc6\x9c\x9c]\x10\xea\xc3O #\xc3\xd7:)/\x19\xb0>$\x87J\x01\x04\xc1n\ 
4024 \xc0\xcb\xf3cl]mv\xe3\x83\xb4o\xc1\xa6D\xf4\x1b\x07\xed\xba\xd9\xa7`+ \xad\ 
4025 \xfe\x01\xd1\x03SV!\xfbHa\x00\x00\x00\x00IEND\xaeB`\x82'  
4027 def getFolderClosedBitmap(): 
4028     return BitmapFromImage(getFolderClosedImage()) 
4030 def getFolderClosedImage(): 
4031     stream 
= cStringIO
.StringIO(getFolderClosedData()) 
4032     return ImageFromStream(stream
) 
4034 def getFolderClosedIcon(): 
4035     return wx
.IconFromBitmap(getFolderClosedBitmap()) 
4038 #---------------------------------------------------------------------- 
4039 def getFolderOpenData(): 
4041 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4042 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4043 \x00\x01>IDAT8\x8d\xa5\x93\xbdJ\x03A\x14\x85\xbfY\x03i\xac\x14\x92\xc2F\xad$\ 
4044 Z\xa4\x10\x11|\x01\xc1J\xdbt\xbe\x86\x9d\x85\x0f\xa0\xe0\x1b\x04,l\xc4J\x0b\ 
4045 \x0bA;a\x11\x13\xb1H\xc2\xc2\xca\x84@\x88n\xb2\xd9?\xcd\xd8d6.\x9b\x104\xa7\ 
4046 \xbas\xef=g\xce\x9d\xe1\na\xcc1\x0b\x8c\x99\xd8@F\x07_\xd6\xb9\n\xdd\x8f\xb8\ 
4047 \xd0s\x9a\x00\xe4\xb6O\xc5T\x81~\xf5D\x89\xdc\x0e\xd9_\x85,\xa0\xa2\x06\xefw\ 
4048 R\x01\x04\x9e\x03\xc0\xea\xde\x8dH\th\xa8\xa81:\xf8\x1e\x00\xf9\x8d\x03\x00\ 
4049 \xa4U\x07\xc0,\xdb\xaaX\xaa\xc4"\x99\x04\xd9\xf7\xe0\xfbs$\x12\x0e\x90\xad\ 
4050 \x0e\x00]\xeb*N\x9b\xe5u\x05P,UD\xc2\x81&K\xbb\r@\xd4\xba\x1f\x9a\xe9\xb0\ 
4051 \xb6\x7f\x96h}\xbe8\x1c9\xe89M\x16\xfc\x15\xa4\xdd\xc6\xe8\x9a\x18\xc3\x99\ 
4052 \x97w\x8f\x99\x86\xd8\x81\xb4\xea\x18]\x93\xfcf).\x0e\\9\x96\xf4r}\x84~\x87\ 
4053 \xc4\x08\x81\xe7\xa0\xfa\xb5\xa9\xb7\xa6\x1c\xf4\xdao\xcc/B\x04\x0c<\xfb\xef\ 
4054 \x02Zd\xa9P\x98\xd8\xf8\xfax\x1b\xc7\xa9o\xf4\xbdN\x8aP{z \x0c\xdc\xb1\xa4\ 
4055 \xdf\x10z\x99\xaa\x97[J\'\xc3\xc0\x9dH\x98(\xf0_\xcc\xbc\x8d?\xf2)\x7f\x8e|f\ 
4056 \xe54\x00\x00\x00\x00IEND\xaeB`\x82'  
4058 def getFolderOpenBitmap(): 
4059     return BitmapFromImage(getFolderOpenImage()) 
4061 def getFolderOpenImage(): 
4062     stream 
= cStringIO
.StringIO(getFolderOpenData()) 
4063     return ImageFromStream(stream
) 
4065 def getFolderOpenIcon(): 
4066     return wx
.IconFromBitmap(getFolderOpenBitmap()) 
4069 #---------------------------------------------------------------------- 
4070 def getLogicalModeOnData(): 
4072 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4073 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4074 \x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ 
4075 \xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ 
4076 \x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ 
4077 \xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ 
4078 \xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ 
4079 \xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ 
4080 \xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ 
4081 \xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ 
4082 \xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ 
4083 \x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ 
4084 \x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ 
4085 \xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ 
4086 h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ 
4087 \xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ 
4088 \x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ 
4089 \x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82'  
4091 def getLogicalModeOnBitmap(): 
4092     return BitmapFromImage(getLogicalModeOnImage()) 
4094 def getLogicalModeOnImage(): 
4095     stream 
= cStringIO
.StringIO(getLogicalModeOnData()) 
4096     return ImageFromStream(stream
) 
4098 #---------------------------------------------------------------------- 
4099 def getLogicalModeOffData(): 
4101 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4102 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4103 \x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ 
4104 \xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ 
4105 \x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ 
4106 \xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ 
4107 \xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ 
4108 \xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ 
4109 \xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ 
4110 \xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ 
4111 \xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ 
4112 \x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ 
4113 \x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ 
4114 \xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ 
4115 h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ 
4116 \xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ 
4117 \x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ 
4118 \x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82'  
4120 def getLogicalModeOffBitmap(): 
4121     return BitmapFromImage(getLogicalModeOffImage()) 
4123 def getLogicalModeOffImage(): 
4124     stream 
= cStringIO
.StringIO(getLogicalModeOffData()) 
4125     return ImageFromStream(stream
) 
4127 #---------------------------------------------------------------------- 
4128 def getPhysicalModeOnData(): 
4130 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4131 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4132 \x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ 
4133 \x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ 
4134 \xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ 
4135 \x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ 
4136 [{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ 
4137 \x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ 
4138 vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ 
4139 \xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ 
4140 I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ 
4141 \xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ 
4142 \xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ 
4143 \xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ 
4144 \'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ 
4145 \xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ 
4146 \xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ 
4147 \xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ 
4148 \xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ 
4149 \x00\x00\x00IEND\xaeB`\x82'  
4151 def getPhysicalModeOnBitmap(): 
4152     return BitmapFromImage(getPhysicalModeOnImage()) 
4154 def getPhysicalModeOnImage(): 
4155     stream 
= cStringIO
.StringIO(getPhysicalModeOnData()) 
4156     return ImageFromStream(stream
) 
4158 #---------------------------------------------------------------------- 
4159 def getPhysicalModeOffData(): 
4161 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
4162 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
4163 \x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ 
4164 \x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ 
4165 \xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ 
4166 \x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ 
4167 [{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ 
4168 \x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ 
4169 vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ 
4170 \xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ 
4171 I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ 
4172 \xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ 
4173 \xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ 
4174 \xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ 
4175 \'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ 
4176 \xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ 
4177 \xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ 
4178 \xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ 
4179 \xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ 
4180 \x00\x00\x00IEND\xaeB`\x82'  
4182 def getPhysicalModeOffBitmap(): 
4183     return BitmapFromImage(getPhysicalModeOffImage()) 
4185 def getPhysicalModeOffImage(): 
4186     stream 
= cStringIO
.StringIO(getPhysicalModeOffData()) 
4187     return ImageFromStream(stream
)