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