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