]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/ide/activegrid/tool/project.py
DocView and ActiveGrid IDE updates from Morgan Hua:
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / project.py
CommitLineData
02b800ce
RD
1#----------------------------------------------------------------------------
2# Name: project.py
3# Purpose: project model for wx.lib.pydocview
4#
5# Author: Morgan Hua
6#
7# Created: 8/25/05
8# CVS-ID: $Id$
9# Copyright: (c) 2005 ActiveGrid, Inc.
10# License: wxWindows License
11#----------------------------------------------------------------------------
12
13import copy
14import os
15import os.path
16import activegrid.util.xmlutils as xmlutils
aca310e5
RD
17import activegrid.util.aglogging as aglogging
18
19# REVIEW 07-Mar-06 stoens@activegrid.com -- Ideally move the pieces required
20# to generate the .dpl file out of this module so there's no dependency on wx,
21# instead of doing this try/catch (IDE drags in wx).
22try:
23 from IDE import ACTIVEGRID_BASE_IDE
24except:
25 ACTIVEGRID_BASE_IDE = False
26
02b800ce
RD
27if not ACTIVEGRID_BASE_IDE:
28 import activegrid.model.basedocmgr as basedocmgr
29 import AppInfo
30
31#----------------------------------------------------------------------------
32# Constants
33#----------------------------------------------------------------------------
34# Always add new versions, never edit the version number
35# This allows you to upgrade the file by checking the version number
36PROJECT_VERSION_050730 = '10'
37PROJECT_VERSION_050826 = '11'
38
02b800ce
RD
39
40#----------------------------------------------------------------------------
41# Classes
42#----------------------------------------------------------------------------
43
44class BaseProject(object):
45
46 __xmlname__ = "project"
aca310e5 47 __xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback', '_cacheEnabled')
02b800ce
RD
48 __xmlattributes__ = ("_homeDir", "version")
49 __xmlrename__ = { "_homeDir":"homeDir", "_appInfo":"appInfo" }
50 __xmlflattensequence__ = { "_files":("file",) }
51 __xmldefaultnamespace__ = xmlutils.AG_NS_URL
52 __xmlattrnamespaces__ = { "ag": ["version", "_homeDir"] }
53
54
55 def __init__(self):
56 self.__xmlnamespaces__ = { "ag" : xmlutils.AG_NS_URL }
57 self.version = PROJECT_VERSION_050826
58 self._files = []
59 self._projectDir = None # default for homeDir, set on load
60 self._homeDir = None # user set homeDir for use in calculating relative path
aca310e5 61 self._cacheEnabled = 0
02b800ce
RD
62 if not ACTIVEGRID_BASE_IDE:
63 self._appInfo = AppInfo.AppInfo()
aca310e5
RD
64
65
66 def initialize(self):
67 for file in self._files:
68 file._parentProj = self
69
02b800ce
RD
70
71 def __copy__(self):
72 clone = Project()
73 clone._files = [copy.copy(file) for file in self._files]
74 clone._projectDir = self._projectDir
75 clone._homeDir = self._homeDir
76 if not ACTIVEGRID_BASE_IDE:
aca310e5 77 clone._appInfo = copy.copy(self._appInfo)
02b800ce
RD
78 return clone
79
02b800ce
RD
80
81 def GetAppInfo(self):
82 return self._appInfo
aca310e5 83
02b800ce
RD
84
85 def AddFile(self, filePath=None, logicalFolder=None, type=None, name=None, file=None):
86 """ Usage: self.AddFile(filePath, logicalFolder, type, name) # used for initial generation of object
87 self.AddFile(file=xyzFile) # normally used for redo/undo
88 Add newly created file object using filePath and logicalFolder or given file object
89 """
90 if file:
91 self._files.append(file)
92 else:
aca310e5 93 self._files.append(ProjectFile(self, filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback))
02b800ce
RD
94
95
96 def RemoveFile(self, file):
97 self._files.remove(file)
98
99
100 def FindFile(self, filePath):
101 if filePath:
102 for file in self._files:
103 if file.filePath == filePath:
104 return file
aca310e5 105
02b800ce
RD
106 return None
107
108
109 def _GetFilePaths(self):
110 return [file.filePath for file in self._files]
111
112
113 filePaths = property(_GetFilePaths)
114
aca310e5
RD
115 def _GetProjectFiles(self):
116 return self._files
117 projectFiles = property(_GetProjectFiles)
118
02b800ce
RD
119
120 def _GetLogicalFolders(self):
121 folders = []
122 for file in self._files:
123 if file.logicalFolder and file.logicalFolder not in folders:
124 folders.append(file.logicalFolder)
125 return folders
126
127
128 logicalFolders = property(_GetLogicalFolders)
aca310e5 129
02b800ce
RD
130
131 def _GetPhysicalFolders(self):
132 physicalFolders = []
133 for file in self._files:
134 physicalFolder = file.physicalFolder
135 if physicalFolder and physicalFolder not in physicalFolders:
136 physicalFolders.append(physicalFolder)
137 return physicalFolders
138
139
140 physicalFolders = property(_GetPhysicalFolders)
141
142
143 def _GetHomeDir(self):
144 if self._homeDir:
145 return self._homeDir
146 else:
147 return self._projectDir
aca310e5 148
02b800ce
RD
149
150 def _SetHomeDir(self, parentPath):
151 self._homeDir = parentPath
aca310e5 152
02b800ce
RD
153
154 def _IsDefaultHomeDir(self):
155 return (self._homeDir == None)
156
157
158 isDefaultHomeDir = property(_IsDefaultHomeDir)
159
160
161 homeDir = property(_GetHomeDir, _SetHomeDir)
162
163
164 def GetRelativeFolders(self):
165 relativeFolders = []
166 for file in self._files:
167 relFolder = file.GetRelativeFolder(self.homeDir)
168 if relFolder and relFolder not in relativeFolders:
169 relativeFolders.append(relFolder)
170 return relativeFolders
aca310e5 171
02b800ce
RD
172
173 def AbsToRelativePath(self):
174 for file in self._files:
175 file.AbsToRelativePath(self.homeDir)
176
177
178 def RelativeToAbsPath(self):
179 for file in self._files:
180 file.RelativeToAbsPath(self.homeDir)
181
182
aca310e5
RD
183 def _SetCache(self, enable):
184 """
185 Only turn this on if your operation assumes files on disk won't change.
186 Once your operation is done, turn this back off.
187 Nested enables are allowed, only the last disable will disable the cache.
188
189 This bypasses the IsDocumentModificationDateCorrect call because the modification date check is too costly, it hits the disk and takes too long.
190 """
191 if enable:
192 if self._cacheEnabled == 0:
193 # clear old cache, don't want to accidentally return stale value
194 for file in self._files:
195 file.ClearCache()
196
197 self._cacheEnabled += 1
198 else:
199 self._cacheEnabled -= 1
200
201
202
203 def _GetCache(self):
204 return (self._cacheEnabled > 0)
205
206
207 cacheEnabled = property(_GetCache, _SetCache)
208
209
02b800ce
RD
210 #----------------------------------------------------------------------------
211 # BaseDocumentMgr methods
212 #----------------------------------------------------------------------------
213
214
215 def fullPath(self, fileName):
216 fileName = super(BaseProject, self).fullPath(fileName)
aca310e5 217
02b800ce
RD
218 if os.path.isabs(fileName):
219 absPath = fileName
220 elif self.homeDir:
221 absPath = os.path.join(self.homeDir, fileName)
222 else:
223 absPath = os.path.abspath(fileName)
224 return os.path.normpath(absPath)
225
226
227 def documentRefFactory(self, name, fileType, filePath):
aca310e5 228 return ProjectFile(self, filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback)
02b800ce
RD
229
230
231 def findAllRefs(self):
232 return self._files
233
234
235 def GetXFormsDirectory(self):
236 forms = self.findRefsByFileType(basedocmgr.FILE_TYPE_XFORM)
237 filePaths = map(lambda form: form.filePath, forms)
238 xformdir = os.path.commonprefix(filePaths)
239 if not xformdir:
240 xformdir = self.homeDir
241 return xformdir
aca310e5
RD
242
243
02b800ce
RD
244 def setRefs(self, files):
245 self._files = files
246
247
248 def findRefsByFileType(self, fileType):
249 fileList = []
250 for file in self._files:
251 if fileType == file.type:
252 fileList.append(file)
253 return fileList
254
255
256 def GenerateServiceRefPath(self, wsdlFilePath):
257 # HACK: temporary solution to getting wsdlag path from wsdl path.
258 import wx
259 from WsdlAgEditor import WsdlAgDocument
260 ext = WsdlAgDocument.WSDL_AG_EXT
261 for template in wx.GetApp().GetDocumentManager().GetTemplates():
262 if template.GetDocumentType() == WsdlAgDocument:
263 ext = template.GetDefaultExtension()
264 break;
265 wsdlAgFilePath = os.path.splitext(wsdlFilePath)[0] + ext
266 return wsdlAgFilePath
267
268
269 def SetDocCallback(self, getDocCallback):
270 self._getDocCallback = getDocCallback
271 for file in self._files:
272 file._getDocCallback = getDocCallback
273
274
275if ACTIVEGRID_BASE_IDE:
276 class Project(BaseProject):
277 pass
278else:
279 class Project(BaseProject, basedocmgr.BaseDocumentMgr):
280 pass
aca310e5 281
02b800ce
RD
282
283class ProjectFile(object):
284 __xmlname__ = "file"
aca310e5 285 __xmlexclude__ = ('_parentProj', '_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',)
02b800ce
RD
286 __xmlattributes__ = ["filePath", "logicalFolder", "type", "name"]
287 __xmldefaultnamespace__ = xmlutils.AG_NS_URL
288
289
aca310e5
RD
290 def __init__(self, parent=None, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None):
291 self._parentProj = parent
02b800ce
RD
292 self.filePath = filePath
293 self.logicalFolder = logicalFolder
294 self.type = type
295 self.name = name
296 self._getDocCallback = getDocCallback
297 self._docCallbackCacheReturnValue = None
298 self._docModelCallbackCacheReturnValue = None
299 self._doc = None
300
301
302 def _GetDocumentModel(self):
aca310e5
RD
303 if (self._docCallbackCacheReturnValue
304 and (self._parentProj.cacheEnabled or self._docCallbackCacheReturnValue.IsDocumentModificationDateCorrect())):
02b800ce 305 return self._docModelCallbackCacheReturnValue
aca310e5 306
02b800ce
RD
307 if self._getDocCallback:
308 self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath)
309 return self._docModelCallbackCacheReturnValue
aca310e5 310
02b800ce
RD
311 return None
312
aca310e5 313
02b800ce 314 document = property(_GetDocumentModel)
aca310e5 315
02b800ce
RD
316
317 def _GetDocument(self):
aca310e5
RD
318 # Return the IDE document wrapper that corresponds to the runtime document model
319 if (self._docCallbackCacheReturnValue
320 and (self._parentProj.cacheEnabled or self._docCallbackCacheReturnValue.IsDocumentModificationDateCorrect())):
02b800ce 321 return self._docCallbackCacheReturnValue
aca310e5
RD
322
323 if self._getDocCallback:
324 self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath)
325 return self._docCallbackCacheReturnValue
326
02b800ce 327 return None
aca310e5 328
02b800ce
RD
329
330 ideDocument = property(_GetDocument)
331
332
aca310e5
RD
333 def ClearCache(self):
334 self._docCallbackCacheReturnValue = None
335 self._docModelCallbackCacheReturnValue = None
336
337
02b800ce
RD
338 def _typeEnumeration(self):
339 return basedocmgr.FILE_TYPE_LIST
aca310e5 340
02b800ce
RD
341
342 def _GetPhysicalFolder(self):
343 dir = None
344 if self.filePath:
345 dir = os.path.dirname(self.filePath)
346 if os.sep != '/':
347 dir = dir.replace(os.sep, '/') # require '/' as delimiter
348 return dir
349
350
351 physicalFolder = property(_GetPhysicalFolder)
aca310e5 352
02b800ce
RD
353
354 def GetRelativeFolder(self, parentPath):
355 parentPathLen = len(parentPath)
356
357 dir = None
358 if self.filePath:
359 dir = os.path.dirname(self.filePath)
aca310e5 360 if dir.startswith(parentPath + os.sep):
02b800ce
RD
361 dir = "." + dir[parentPathLen:] # convert to relative path
362 if os.sep != '/':
363 dir = dir.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility.
364 return dir
365
366
367 def AbsToRelativePath(self, parentPath):
368 """ Used to convert path to relative path for saving (disk format) """
369 parentPathLen = len(parentPath)
370
aca310e5 371 if self.filePath.startswith(parentPath + os.sep):
02b800ce
RD
372 self.filePath = "." + self.filePath[parentPathLen:] # convert to relative path
373 if os.sep != '/':
374 self.filePath = self.filePath.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility.
375 else:
376 pass # not a decendant of project, use absolute path
377
378
379 def RelativeToAbsPath(self, parentPath):
380 """ Used to convert path to absolute path (for any necessary disk access) """
aca310e5
RD
381 if self.filePath.startswith("./"): # relative to project file
382 self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath)) # also converts '/' to os.sep
02b800ce
RD
383
384
385 #----------------------------------------------------------------------------
386 # BaseDocumentMgr methods
387 #----------------------------------------------------------------------------
388
389 def _GetDoc(self):
390 # HACK: temporary solution.
391 import wx
392 import wx.lib.docview
393 if not self._doc:
394 docMgr = wx.GetApp().GetDocumentManager()
aca310e5
RD
395
396 try:
397 doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW)
398 if (doc == None): # already open
399 docs = docMgr.GetDocuments()
400 for d in docs:
401 if d.GetFilename() == self.filePath:
402 doc = d
403 break
404 self._doc = doc
405 except Exception,e:
406 aglogging.reportException(e, stacktrace=True)
407
02b800ce 408 return self._doc
aca310e5 409
02b800ce
RD
410
411 def _GetLocalServiceProcessName(self):
412 # HACK: temporary solution to getting process name from wsdlag file.
aca310e5
RD
413 doc = self._GetDoc()
414 if doc:
415 return doc.GetModel().processName
416 else:
417 return None
02b800ce
RD
418
419
420 processName = property(_GetLocalServiceProcessName)
421
422
423 def _GetStateful(self):
424 # HACK: temporary solution to getting stateful from wsdlag file.
425 return self._GetDoc().GetModel().stateful
426
427
428 def _SetStateful(self, stateful):
429 # HACK: temporary solution to setting stateful from wsdlag file.
430 self._GetDoc().GetModel().stateful = stateful
431
432
433 stateful = property(_GetStateful, _SetStateful)
434
435
436 def _GetLocalServiceCodeFile(self):
437 # HACK: temporary solution to getting class name from wsdlag file.
438 return self._GetDoc().GetModel().localServiceCodeFile
439
440
441 def _SetLocalServiceCodeFile(self, codefile):
442 # HACK: temporary solution to setting class name from wsdlag file.
443 self._GetDoc().GetModel().localServiceCodeFile = codefile
444
445
446 localServiceCodeFile = property(_GetLocalServiceCodeFile, _SetLocalServiceCodeFile)
447
448
449 def _GetLocalServiceClassName(self):
450 # HACK: temporary solution to getting class name from wsdlag file.
451 return self._GetDoc().GetModel().localServiceClassName
452
453
454 def _SetLocalServiceClassName(self, className):
455 # HACK: temporary solution to setting class name from wsdlag file.
456 self._GetDoc().GetModel().localServiceClassName = className
457
458
459 localServiceClassName = property(_GetLocalServiceClassName, _SetLocalServiceClassName)
460
461
aca310e5
RD
462 def getServiceParameter(self, message, part):
463 return self._GetDoc().GetModel().getServiceParameter(message, part)
464
02b800ce
RD
465
466# only activate this code if we programatically need to access these values
467## def _GetRssServiceBaseURL(self):
468## return self._GetDoc().GetModel().rssServiceBaseURL
469##
aca310e5 470##
02b800ce
RD
471## def _SetRssServiceBaseURL(self, baseURL):
472## self._GetDoc().GetModel().rssServiceBaseURL = baseURL
aca310e5
RD
473##
474##
02b800ce
RD
475## rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL)
476##
477##
478## def _GetRssServiceRssVersion(self):
479## return self._GetDoc().GetModel().rssServiceRssVersion
aca310e5 480##
02b800ce
RD
481##
482## def _SetRssServiceRssVersion(self, rssVersion):
483## self._GetDoc().GetModel().rssServiceRssVersion = rssVersion
aca310e5 484##
02b800ce
RD
485##
486## rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion)
487
488
489 def _GetServiceRefServiceType(self):
490 # HACK: temporary solution to getting service type from wsdlag file.
aca310e5
RD
491 doc = self._GetDoc()
492 if not doc:
493 return None
494 model = doc.GetModel()
02b800ce
RD
495 if hasattr(model, 'serviceType'):
496 return model.serviceType
497 else:
498 return None
499
500
501 def _SetServiceRefServiceType(self, serviceType):
502 # HACK: temporary solution to getting service type from wsdlag file.
503 self._GetDoc().GetModel().serviceType = serviceType
aca310e5 504
02b800ce
RD
505
506 serviceType = property(_GetServiceRefServiceType, _SetServiceRefServiceType)
507
508
509 def getExternalPackage(self):
510 # HACK: temporary solution to getting custom code filename from wsdlag file.
aca310e5
RD
511 import activegrid.model.projectmodel as projectmodel
512 import wx
513 import ProjectEditor
514
02b800ce
RD
515 appInfo = self._GetDoc().GetAppInfo()
516
517 if appInfo.language == None:
aca310e5 518 language = wx.ConfigBase_Get().Read(ProjectEditor.APP_LAST_LANGUAGE, projectmodel.LANGUAGE_DEFAULT)
02b800ce
RD
519 else:
520 language = appInfo.language
aca310e5
RD
521
522 if language == projectmodel.LANGUAGE_PYTHON:
02b800ce 523 suffix = ".py"
aca310e5 524 elif language == projectmodel.LANGUAGE_PHP:
02b800ce
RD
525 suffix = ".php"
526 pyFilename = self.name + suffix
527 return self._GetDoc().GetAppDocMgr().fullPath(pyFilename)
528
529
530#----------------------------------------------------------------------------
531# Old Classes
532#----------------------------------------------------------------------------
533
534class Project_10:
535 """ Version 1.0, kept for upgrading to latest version. Over time, this should be deprecated. """
536 __xmlname__ = "project"
537 __xmlrename__ = { "_files":"files"}
538 __xmlexclude__ = ('fileName',)
539 __xmlattributes__ = ["version"]
540
541
542 def __init__(self):
543 self.version = PROJECT_VERSION_050730
544 self._files = []
545
546
547 def initialize(self):
548 """ Required method for xmlmarshaller """
549 pass
550
551
552 def upgradeVersion(self):
553 currModel = Project()
554 for file in self._files:
aca310e5 555 currModel._files.append(ProjectFile(currModel, file))
02b800ce
RD
556 return currModel
557
558
aca310e5
RD
559#----------------------------------------------------------------------------
560# XML Marshalling Methods
561#----------------------------------------------------------------------------
562
563if ACTIVEGRID_BASE_IDE:
564 KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile}
565else:
566 KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile,
567 "ag:appInfo" : AppInfo.AppInfo,
568 "ag:deploymentDataSource" : AppInfo.DeploymentDataSource,
569 "ag:dataSourceBinding" : AppInfo.DataSourceBinding}
570
571def load(fileObject):
572 version = xmlutils.getAgVersion(fileObject.name)
573 # most current versions on top
574 if version == PROJECT_VERSION_050826:
575 fileObject.seek(0)
576 project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES, createGenerics=True)
577 elif version == PROJECT_VERSION_050730:
578 fileObject.seek(0)
579 project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}, createGenerics=True)
580 project = project.upgradeVersion()
581 else:
582 # assume it is old version without version number
583 fileObject.seek(0)
584 project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}, createGenerics=True)
585 if project:
586 project = project.upgradeVersion()
587 else:
588 print "Project, unknown version:", version
589 return None
590
591 if project:
592 project._projectDir = os.path.dirname(fileObject.name)
593 project.RelativeToAbsPath()
594
595 return project
596
597
598def save(fileObject, project, productionDeployment=False):
599 if not project._projectDir:
600 project._projectDir = os.path.dirname(fileObject.name)
601 project.AbsToRelativePath() # temporarily change it to relative paths for saving
602 savedHomeDir = project.homeDir
603 if productionDeployment:
604 # for deployments, we don't want an abs path in homeDir since that
605 # would tie the app to the current filesystem. So unset it.
606 project.homeDir = None
607
608 xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES)
609
610 if productionDeployment:
611 project.homeDir = savedHomeDir
612
613 project.RelativeToAbsPath() # swap it back to absolute path
614