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