]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/tool/ProjectEditor.py
part of the revert of 1.8 got botched
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / ProjectEditor.py
1 #----------------------------------------------------------------------------
2 # Name: ProjectEditor.py
3 # Purpose: IDE-style Project Editor for wx.lib.pydocview
4 #
5 # Author: Peter Yared, Morgan Hua
6 #
7 # Created: 8/15/03
8 # CVS-ID: $Id$
9 # Copyright: (c) 2003, 2004, 2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
12
13 import wx.lib.docview
14 import wx.lib.pydocview
15 import types
16 import os
17 import os.path
18 import wx
19 from wxPython.lib.rcsizer import RowColSizer
20 import time
21 import Service
22 import MessageService
23 import DebuggerService
24 import sys
25 import activegrid.util.xmlmarshaller
26 import UICommon
27 from IDE import ACTIVEGRID_BASE_IDE
28 if not ACTIVEGRID_BASE_IDE:
29 import ProcessModelEditor
30
31 _ = wx.GetTranslation
32
33 if wx.Platform == '__WXMSW__':
34 _WINDOWS = True
35 else:
36 _WINDOWS = False
37
38
39 #----------------------------------------------------------------------------
40 # XML Marshalling Methods
41 #----------------------------------------------------------------------------
42 LOCAL_TYPE_MAPPING = { "projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel", }
43
44 def load(fileObject):
45 xml = fileObject.read()
46 projectModel = activegrid.util.xmlmarshaller.unmarshal(xml, knownTypes=LOCAL_TYPE_MAPPING)
47 return projectModel
48
49
50 def save(fileObject, projectModel):
51 xml = activegrid.util.xmlmarshaller.marshal(projectModel, prettyPrint=True, knownTypes=LOCAL_TYPE_MAPPING)
52 fileObject.write(xml)
53
54
55 #----------------------------------------------------------------------------
56 # Classes
57 #----------------------------------------------------------------------------
58
59 class ProjectModel:
60 __xmlname__ = "projectmodel"
61 __xmlrename__ = { "_files":"files", "_homepath":"homepath" }
62
63 def __init__(self):
64 self._homepath = None
65 self._files = []
66
67
68 class ProjectDocument(wx.lib.docview.Document):
69
70 def __init__(self):
71 wx.lib.docview.Document.__init__(self)
72 self._projectModel = ProjectModel()
73
74
75 def GetModel(self):
76 return self._projectModel
77
78
79 def OnCreate(self, path, flags):
80 projectService = wx.GetApp().GetService(ProjectService)
81 if projectService.GetView():
82 view = projectService.GetView()
83 self.AddView(view)
84 else:
85 view = self.GetDocumentTemplate().CreateView(self, flags)
86 projectService.SetView(view)
87 return view
88
89
90 def LoadObject(self, fileObject):
91 self._projectModel = activegrid.tool.ProjectEditor.load(fileObject)
92 return True
93
94
95 def SaveObject(self, fileObject):
96 activegrid.tool.ProjectEditor.save(fileObject, self._projectModel)
97 return True
98
99
100 def OnSaveDocument(self, filename):
101 self._projectModel._homepath = wx.lib.docview.PathOnly(filename)
102 return wx.lib.docview.Document.OnSaveDocument(self, filename)
103
104
105 def OnOpenDocument(self, filename):
106 view = self.GetFirstView()
107 frame = view.GetFrame()
108
109 if not os.path.exists(filename):
110 wx.GetApp().CloseSplash()
111 msgTitle = wx.GetApp().GetAppName()
112 if not msgTitle:
113 msgTitle = _("File Error")
114 wx.MessageBox(_("Could not find '%s'.") % filename,
115 msgTitle,
116 wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP,
117 frame)
118 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
119
120 fileObject = file(filename, 'r')
121 try:
122 self.LoadObject(fileObject)
123 except:
124 wx.GetApp().CloseSplash()
125 msgTitle = wx.GetApp().GetAppName()
126 if not msgTitle:
127 msgTitle = _("File Error")
128 wx.MessageBox(_("Could not open '%s'. %s") % (wx.lib.docview.FileNameFromPath(filename), sys.exc_value),
129 msgTitle,
130 wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP,
131 frame)
132 return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
133
134 self.Modify(False)
135
136 # if the project file has moved, then ask the user if we should readjust the paths of all the files in the project
137 newHomepath = wx.lib.docview.PathOnly(filename)
138 if newHomepath != self._projectModel._homepath:
139 wx.GetApp().CloseSplash()
140 msgTitle = wx.GetApp().GetAppName()
141 if not msgTitle:
142 msgTitle = _("Project Moved")
143 projectService = wx.GetApp().GetService(activegrid.tool.ProjectEditor.ProjectService)
144 yesNoMsg = wx.MessageDialog(frame,
145 _("The project file '%s' was moved from:\n '%s'\nto:\n '%s'.\n\nWould you like to automatically adjust the project contents accordingly?") % (wx.lib.docview.FileNameFromPath(filename), self._projectModel._homepath, wx.lib.docview.PathOnly(filename)),
146 msgTitle,
147 wx.YES_NO | wx.STAY_ON_TOP
148 )
149 if projectService.GetSuppressOpenProjectMessages() or yesNoMsg.ShowModal() == wx.ID_YES:
150 if not projectService.GetSuppressOpenProjectMessages():
151 messageService = wx.GetApp().GetService(MessageService.MessageService)
152 messageService.ShowWindow()
153 messageView = messageService.GetView()
154 messageView.ClearLines()
155 messageView.AddLines(_("The project file '%s' was moved from:\n '%s'\nto:\n '%s'\n") % (wx.lib.docview.FileNameFromPath(filename), self._projectModel._homepath, wx.lib.docview.PathOnly(filename)))
156 messageView.AddLines(_("Updating file references:\n"))
157
158 for index, filepath in enumerate(self._projectModel._files):
159 if filepath.startswith(self._projectModel._homepath + os.sep):
160 newfile = newHomepath + filepath[len(self._projectModel._homepath):len(filepath)]
161 if os.path.exists(newfile):
162 self._projectModel._files[index] = newfile
163 if not projectService.GetSuppressOpenProjectMessages():
164 messageView.AddLines(_(" Success: '%s' location changed from '%s' to '%s'\n") % (wx.lib.docview.FileNameFromPath(filepath), wx.lib.docview.PathOnly(filepath), newHomepath))
165 self.Modify(True)
166 else:
167 if not projectService.GetSuppressOpenProjectMessages():
168 messageView.AddLines(_(" Failure: Couldn't find '%s', file wasn't located at '%s'\n") % (wx.lib.docview.FileNameFromPath(filepath), newHomepath))
169 else:
170 if not projectService.GetSuppressOpenProjectMessages():
171 messageView.AddLines(_( " Unmodified: '%s' location wasn't relative to '%s'\n") % (filepath, self._projectModel._homepath))
172 self._projectModel._homepath = newHomepath
173 if not projectService.GetSuppressOpenProjectMessages():
174 messageView.AddLines(_("Project file updated."))
175
176 self.SetFilename(filename, True)
177 view.AddProjectToView(self)
178 self.SetDocumentModificationDate()
179 self.UpdateAllViews()
180 self._savedYet = True
181 view.Activate(True)
182 return True
183
184
185 def AddFile(self, file):
186 return self.AddFiles([file])
187
188
189 def AddFiles(self, files):
190 notAlreadyThereFiles = filter(lambda x: x not in self._projectModel._files, files) # Filter to the files that are not already in the project
191 if len(notAlreadyThereFiles) == 0:
192 self.UpdateAllViews(hint = ("select", self, files))
193 return False
194 else:
195 self._projectModel._files = self._projectModel._files + notAlreadyThereFiles
196 self.UpdateAllViews(hint = ("add", self, notAlreadyThereFiles))
197 self.Modify(True)
198 return True
199
200
201 def RemoveFile(self, file):
202 return self.RemoveFiles([file])
203
204
205 def RemoveFiles(self, files):
206 for file in files:
207 self._projectModel._files.remove(file)
208 self.UpdateAllViews(hint = ("remove", self, files))
209 self.Modify(True)
210 return True
211
212
213 def RenameFile(self, oldFile, newFile, isProject = False):
214 try:
215 if oldFile == newFile:
216 return False
217
218 # projects don't have to exist yet, so not required to rename old file,
219 # but files must exist, so we'll try to rename and allow exceptions to occur if can't.
220 if not isProject or (isProject and os.path.exists(oldFile)):
221 os.rename(oldFile, newFile)
222
223 if isProject:
224 documents = self.GetDocumentManager().GetDocuments()
225 for document in documents:
226 if document.GetFilename() == oldFile: # If the renamed document is open, update it
227 document.SetFilename(newFile)
228 document.SetTitle(wx.lib.docview.FileNameFromPath(newFile))
229 document.UpdateAllViews(hint = ("rename", document, newFile))
230 else:
231 self.RemoveFile(oldFile)
232 self.AddFile(newFile)
233 documents = self.GetDocumentManager().GetDocuments()
234 for document in documents:
235 if document.GetFilename() == oldFile: # If the renamed document is open, update it
236 document.SetFilename(newFile, notifyViews = True)
237 document.UpdateAllViews(hint = ("rename", document, newFile))
238 return True
239 except OSError, (code, message):
240 msgTitle = wx.GetApp().GetAppName()
241 if not msgTitle:
242 msgTitle = _("File Error")
243 wx.MessageBox("Could not rename '%s'. '%s'" % (wx.lib.docview.FileNameFromPath(oldFile), message),
244 msgTitle,
245 wx.OK | wx.ICON_EXCLAMATION,
246 self.GetFirstView().GetFrame())
247 return False
248
249
250 def GetFiles(self):
251 return self._projectModel._files
252
253
254 def IsFileInProject(self, filename):
255 return filename in self.GetFiles()
256
257
258 import Wizard
259
260 class NewProjectWizard(Wizard.BaseWizard):
261
262 WIZTITLE = _("New Project Wizard")
263
264 def __init__(self, parent):
265 self._parent = parent
266 self._fullProjectPath = None
267 Wizard.BaseWizard.__init__(self, parent, self.WIZTITLE)
268 self._projectLocationPage = self.CreateProjectLocation(self)
269 wx.wizard.EVT_WIZARD_PAGE_CHANGING(self, self.GetId(), self.OnWizPageChanging)
270
271 def CreateProjectLocation(self,wizard):
272 page = Wizard.TitledWizardPage(wizard, _("Project File Location"))
273
274 page.GetSizer().Add(wx.StaticText(page, -1, _("\nSelect the directory and filename for the project.\n\n")))
275 self._projectName, self._dirCtrl, sizer, self._fileValidation = UICommon.CreateDirectoryControl(page, _("File Name:"), _("Directory:"), _("agp"), startingDirectory=os.getcwd())
276 page.GetSizer().Add(sizer, 1, flag=wx.EXPAND)
277
278 wizard.Layout()
279 wizard.FitToPage(page)
280 return page
281
282 def RunWizard(self, existingTables = None, existingRelationships = None):
283 status = wx.wizard.Wizard.RunWizard(self, self._projectLocationPage)
284 if status:
285 docManager = wx.GetApp().GetTopWindow().GetDocumentManager()
286 if os.path.exists(self._fullProjectPath):
287 # What if the document is already open and we're overwriting it?
288 documents = docManager.GetDocuments()
289 for document in documents:
290 if document.GetFilename() == self._fullProjectPath: # If the renamed document is open, update it
291 document.DeleteAllViews()
292 break
293 os.remove(self._fullProjectPath)
294
295 for template in docManager.GetTemplates():
296 if template.GetDocumentType() == ProjectDocument:
297 doc = template.CreateDocument(self._fullProjectPath, flags = wx.lib.docview.DOC_NEW)
298 doc.OnSaveDocument(self._fullProjectPath)
299 view = doc.GetFirstView()
300 view.AddProjectToView(doc)
301 break
302
303 self.Destroy()
304 return status
305
306
307 def OnWizPageChanging(self, event):
308 if event.GetDirection(): # It's going forwards
309 if event.GetPage() == self._projectLocationPage:
310 if not self._fileValidation():
311 event.Veto()
312 return
313 self._fullProjectPath = os.path.join(self._dirCtrl.GetValue(),UICommon.MakeNameEndInExtension(self._projectName.GetValue(),'.agp'))
314
315
316
317 def OnShowCreatePages(self):
318 self.Hide()
319 import DataModelEditor
320 requestedPos = self.GetPositionTuple()
321 projectService = wx.GetApp().GetService(ProjectService)
322 projectView = projectService.GetView()
323
324 wiz = DataModelEditor.ImportExportWizard(projectView.GetFrame(), pos=requestedPos)
325 if wiz.RunWizard(dontDestroy=True):
326 self._schemaName.SetValue(wiz.GetSchemaFileName())
327 wiz.Destroy()
328 self.Show(True)
329
330 class ProjectTemplate(wx.lib.docview.DocTemplate):
331
332 def CreateDocument(self, path, flags):
333 if path:
334 return wx.lib.docview.DocTemplate.CreateDocument(self, path, flags)
335 else:
336 wiz = NewProjectWizard(wx.GetApp().GetTopWindow())
337 wiz.RunWizard()
338 wiz.Destroy()
339 return None # never return the doc, otherwise docview will think it is a new file and rename it
340
341 class ProjectAddFilesCommand(wx.lib.docview.Command):
342
343 def __init__(self, projectDoc, files):
344 wx.lib.docview.Command.__init__(self, canUndo = True)
345 self._projectDoc = projectDoc
346 self._files = files
347
348
349 def GetName(self):
350 if len(self._files) == 1:
351 return _("Add File")
352 else:
353 return _("Add Files")
354
355
356 def Do(self):
357 return self._projectDoc.AddFiles(self._files)
358
359
360 def Undo(self):
361 return self._projectDoc.RemoveFiles(self._files)
362
363
364 class ProjectRemoveFilesCommand(wx.lib.docview.Command):
365
366 def __init__(self, projectDoc, files):
367 wx.lib.docview.Command.__init__(self, canUndo = True)
368 self._projectDoc = projectDoc
369 self._files = files
370
371
372 def GetName(self):
373 if len(self._files) == 1:
374 return _("Remove File")
375 else:
376 return _("Remove Files")
377
378
379 def Do(self):
380 return self._projectDoc.RemoveFiles(self._files)
381
382
383 def Undo(self):
384 return self._projectDoc.AddFiles(self._files)
385
386
387 class ProjectRenameFileCommand(wx.lib.docview.Command):
388
389 def __init__(self, projectDoc, oldFile, newFile, isProject = False):
390 wx.lib.docview.Command.__init__(self, canUndo = True)
391 self._projectDoc = projectDoc
392 self._oldFile = oldFile
393 self._newFile = newFile
394 self._isProject = isProject
395
396
397 def GetName(self):
398 return _("Rename File")
399
400
401 def Do(self):
402 return self._projectDoc.RenameFile(self._oldFile, self._newFile, self._isProject)
403
404
405 def Undo(self):
406 return self._projectDoc.RenameFile(self._newFile, self._oldFile, self._isProject)
407
408
409 class ProjectTreeCtrl(wx.TreeCtrl):
410
411 def __init__(self, parent, id, style):
412 wx.TreeCtrl.__init__(self, parent, id, style = style)
413
414 templates = wx.GetApp().GetDocumentManager().GetTemplates()
415 iconList = wx.ImageList(16, 16, initialCount = len(templates))
416 self._iconIndexLookup = []
417 for template in templates:
418 icon = template.GetIcon()
419 if icon:
420 if icon.GetHeight() != 16:
421 icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
422 if icon.GetWidth() != 16:
423 icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
424 iconIndex = iconList.AddIcon(icon)
425 self._iconIndexLookup.append((template, iconIndex))
426
427 icon = getBlankIcon()
428 if icon.GetHeight() != 16:
429 icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
430 if icon.GetWidth() != 16:
431 icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
432 self._blankIconIndex = iconList.AddIcon(icon)
433 self.AssignImageList(iconList)
434
435
436 def OnCompareItems(self, item1, item2):
437 return cmp(self.GetItemText(item1).lower(), self.GetItemText(item2).lower())
438
439
440 def AppendItem(self, parent, filepath):
441 item = wx.TreeCtrl.AppendItem(self, parent, filepath)
442
443 found = False
444 template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filepath)
445 if not template and parent == self.GetRootItem(): # If the parent is a root it's a new project
446 template = wx.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
447 if template:
448 for t, iconIndex in self._iconIndexLookup:
449 if t is template:
450 self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Normal)
451 self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Expanded)
452 self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected)
453 found = True
454 break
455
456 if not found:
457 self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Normal)
458 self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Expanded)
459 self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected)
460
461 return item
462
463
464 class ProjectView(wx.lib.docview.View):
465
466
467 #----------------------------------------------------------------------------
468 # Overridden methods
469 #----------------------------------------------------------------------------
470
471 def __init__(self, service = None):
472 wx.lib.docview.View.__init__(self)
473 self._service = service # not used, but kept to match other Services
474 self._lastDirectory = ""
475 self._treeCtrl = None
476 self._editingSoDontKillFocus = False
477 self._checkEditMenu = True
478
479
480 def Destroy(self):
481 projectService = wx.GetApp().GetService(ProjectService)
482 if projectService:
483 projectService.SetView(None)
484 wx.lib.docview.View.Destroy(self)
485
486
487 def GetDocument(self):
488 if not self._treeCtrl:
489 return None
490
491 items = self._treeCtrl.GetSelections()
492 if not items: # No selection, so just return first project
493 item = self._treeCtrl.GetFirstVisibleItem()
494 if item.IsOk():
495 return self._GetItemProject(item)
496 else:
497 return None
498
499 for item in items:
500 project = self._GetItemProject(item)
501 if project:
502 return project
503
504 return None
505
506
507 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
508 return wx.GetApp().GetDocumentManager()
509
510
511 def OnChangeFilename(self):
512 if self.GetFrame():
513 title = _("Projects")
514 if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName():
515 title = title + " - " + wx.GetApp().GetAppName()
516 self.GetFrame().SetTitle(title)
517 project = self.GetDocument()
518 if project:
519 projectItem = self._GetProjectItem(project)
520 name = self._treeCtrl.GetItemText(self._GetProjectItem(project))
521 name2 = self._MakeProjectName(project)
522 if name != name2:
523 self._treeCtrl.SetItemText(projectItem, name2)
524 self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem())
525
526
527 def Activate(self, activate = True):
528 if not wx.GetApp().IsMDI():
529 if activate and not self.IsShown():
530 self.Show()
531
532 if self.IsShown():
533 wx.lib.docview.View.Activate(self, activate = activate)
534 if activate and self._treeCtrl:
535 self._treeCtrl.SetFocus()
536
537
538 def OnCreate(self, doc, flags):
539 config = wx.ConfigBase_Get()
540 if wx.GetApp().IsMDI():
541 self._embeddedWindow = wx.GetApp().GetTopWindow().GetEmbeddedWindow(wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT)
542 self.SetFrame(self._embeddedWindow)
543 frame = self._embeddedWindow
544 else:
545 self._embeddedWindow = None
546 pos = config.ReadInt("ProjectFrameXLoc", -1), config.ReadInt("ProjectFrameYLoc", -1)
547 # make sure frame is visible
548 screenWidth = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
549 screenHeight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
550 if pos[0] < 0 or pos[0] >= screenWidth or pos[1] < 0 or pos[1] >= screenHeight:
551 pos = wx.DefaultPosition
552
553 size = wx.Size(config.ReadInt("ProjectFrameXSize", -1), config.ReadInt("ProjectFrameYSize", -1))
554
555 title = _("Projects")
556 if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName():
557 title = title + " - " + wx.GetApp().GetAppName()
558
559 frame = wx.GetApp().CreateDocumentFrame(self, doc, 0, title = title, pos = pos, size = size)
560 if config.ReadInt("ProjectFrameMaximized", False):
561 frame.Maximize(True)
562
563 sizer = wx.BoxSizer()
564 self._treeCtrl = ProjectTreeCtrl(frame, -1, style = wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS | wx.TR_DEFAULT_STYLE | wx.TR_MULTIPLE)
565 self._treeCtrl.AddRoot(_("Projects"))
566
567 if self._embeddedWindow:
568 sizer.Add(self._treeCtrl)
569 sizer.Fit(frame)
570 else:
571 sizer.Add(self._treeCtrl, 1, wx.EXPAND, 0)
572 frame.SetSizer(sizer)
573 frame.Layout()
574 self.Activate()
575
576 if wx.GetApp().IsMDI():
577 wx.EVT_SET_FOCUS(self._treeCtrl, self.OnFocus)
578 wx.EVT_KILL_FOCUS(self._treeCtrl, self.OnKillFocus)
579
580 if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
581 wx.EVT_TREE_ITEM_ACTIVATED(self._treeCtrl, self._treeCtrl.GetId(), self.OnOpenSelectionSDI)
582 else:
583 wx.EVT_TREE_ITEM_ACTIVATED(self._treeCtrl, self._treeCtrl.GetId(), self.OnOpenSelection)
584 wx.EVT_TREE_BEGIN_LABEL_EDIT(self._treeCtrl, self._treeCtrl.GetId(), self.OnBeginLabelEdit)
585 wx.EVT_TREE_END_LABEL_EDIT(self._treeCtrl, self._treeCtrl.GetId(), self.OnEndLabelEdit)
586 wx.EVT_RIGHT_DOWN(self._treeCtrl, self.OnRightClick)
587 wx.EVT_KEY_DOWN(self._treeCtrl, self.OnKeyPressed)
588 # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
589
590 # drag-and-drop support
591 dt = ProjectFileDropTarget(self)
592 self._treeCtrl.SetDropTarget(dt)
593
594 return True
595
596
597 def WriteProjectConfig(self):
598 frame = self.GetFrame()
599 config = wx.ConfigBase_Get()
600 if frame and not self._embeddedWindow:
601 if not frame.IsMaximized():
602 config.WriteInt("ProjectFrameXLoc", frame.GetPositionTuple()[0])
603 config.WriteInt("ProjectFrameYLoc", frame.GetPositionTuple()[1])
604 config.WriteInt("ProjectFrameXSize", frame.GetSizeTuple()[0])
605 config.WriteInt("ProjectFrameYSize", frame.GetSizeTuple()[1])
606 config.WriteInt("ProjectFrameMaximized", frame.IsMaximized())
607
608 if config.ReadInt("ProjectSaveDocs", True):
609 projectFileNames = []
610 projectExpanded = []
611 if self._treeCtrl:
612 for projectItem in self._GetChildItems(self._treeCtrl.GetRootItem()):
613 project = self._GetItemProject(projectItem)
614 if not project.OnSaveModified():
615 return
616 if project.GetDocumentSaved(): # Might be a new document and "No" selected to save it
617 projectFileNames.append(str(project.GetFilename()))
618 projectExpanded.append(self._treeCtrl.IsExpanded(projectItem))
619 config.Write("ProjectSavedDocs", projectFileNames.__repr__())
620 config.Write("ProjectExpandedSavedDocs", projectExpanded.__repr__())
621
622
623 def OnClose(self, deleteWindow = True):
624 if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
625 self.WriteProjectConfig()
626 project = self.GetDocument()
627 if not project:
628 return True
629 if not self.GetDocument().Close():
630 return True
631 self.Activate(False)
632 if project:
633 projectItem = self._GetProjectItem(project)
634 if projectItem:
635 self._treeCtrl.Delete(projectItem)
636 # We don't need to delete the window since it is a floater/embedded
637 return True
638
639
640 def _GetParentFrame(self):
641 return wx.GetTopLevelParent(self.GetFrame())
642
643
644 def OnUpdate(self, sender = None, hint = None):
645 wx.lib.docview.View.OnUpdate(self, sender, hint)
646 if hint:
647 if hint[0] == "add":
648 projectItem = self._GetProjectItem(hint[1])
649 files = hint[2]
650 self._treeCtrl.UnselectAll()
651 self._treeCtrl.Expand(projectItem)
652 for file in files:
653 item = self._treeCtrl.AppendItem(projectItem, os.path.basename(file))
654 self._treeCtrl.SetPyData(item, file)
655 self._treeCtrl.SelectItem(item)
656 self._treeCtrl.EnsureVisible(item) # wxBug: Doesn't work
657 self._treeCtrl.SortChildren(projectItem)
658 elif hint[0] == "remove":
659 projectItem = self._GetProjectItem(hint[1])
660 files = hint[2]
661 children = self._GetChildItems(projectItem)
662 for child in children:
663 if self._GetItemFile(child) in files:
664 self._treeCtrl.Delete(child)
665 elif hint[0] == "select":
666 projectItem = self._GetProjectItem(hint[1])
667 files = hint[2]
668 self._treeCtrl.UnselectAll()
669 children = self._GetChildItems(projectItem)
670 for child in children:
671 if self._GetItemFile(child) in files:
672 self._treeCtrl.SelectItem(child)
673 self._treeCtrl.EnsureVisible(child) # wxBug: Doesn't work
674 elif hint[0] == "rename":
675 projectItem = self._GetProjectItem(hint[1])
676 self._treeCtrl.SetItemText(projectItem, os.path.basename(hint[2]))
677
678
679 def ProcessEvent(self, event):
680 id = event.GetId()
681 if id == ProjectService.ADD_FILES_TO_PROJECT_ID:
682 self.OnAddFileToProject(event)
683 return True
684 elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
685 return False # Implement this one in the service
686 elif id == ProjectService.RENAME_ID:
687 self.OnRename(event)
688 return True
689 elif id == wx.ID_CUT:
690 self.OnCut(event)
691 return True
692 elif id == wx.ID_COPY:
693 self.OnCopy(event)
694 return True
695 elif id == wx.ID_PASTE:
696 self.OnPaste(event)
697 return True
698 elif id == wx.ID_CLEAR or id == ProjectService.REMOVE_FROM_PROJECT:
699 self.OnClear(event)
700 return True
701 elif id == wx.ID_SELECTALL:
702 self.OnSelectAll(event)
703 return True
704 elif id == ProjectService.OPEN_SELECTION_ID:
705 self.OnOpenSelection(event)
706 return True
707 elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
708 self.OnProperties(event)
709 return True
710 else:
711 return False
712
713 def ProcessUpdateUIEvent(self, event):
714 # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
715 if self._checkEditMenu:
716 doc = self.GetDocument()
717 if doc and not doc.GetCommandProcessor().GetEditMenu():
718 doc.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame()))
719 self._checkEditMenu = False
720 id = event.GetId()
721 if id == ProjectService.ADD_FILES_TO_PROJECT_ID:
722 event.Enable(self._HasProjectsSelected() or self._HasFilesSelected())
723 return True
724 elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
725 event.Enable(False)
726 return True
727 elif id == ProjectService.RENAME_ID:
728 event.Enable(self._HasFilesSelected() or self._HasProjectsSelected())
729 return True
730 elif id == wx.ID_CUT:
731 event.Enable(self._AreSelectedItemsFromSameProject())
732 return True
733 elif id == wx.ID_COPY:
734 event.Enable(self._HasFilesSelected())
735 return True
736 elif id == wx.ID_PASTE:
737 event.Enable(self.CanPaste())
738 return True
739 elif id == wx.ID_CLEAR or id == ProjectService.REMOVE_FROM_PROJECT:
740 event.Enable(self._AreSelectedItemsFromSameProject())
741 return True
742 elif id == wx.ID_SELECTALL:
743 event.Enable(self._HasFiles())
744 return True
745 elif id == ProjectService.OPEN_SELECTION_ID:
746 event.Enable(self._HasFilesSelected())
747 return True
748 elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
749 event.Enable(self._HasProjectsSelected() or self._HasFilesSelected())
750 return True
751 else:
752 return False
753
754 #----------------------------------------------------------------------------
755 # Display Methods
756 #----------------------------------------------------------------------------
757
758 def IsShown(self):
759 if not self.GetFrame():
760 return False
761 return self.GetFrame().IsShown()
762
763
764 def Hide(self):
765 self.Show(False)
766
767
768 def Show(self, show = True):
769 self.GetFrame().Show(show)
770 if wx.GetApp().IsMDI():
771 mdiParentFrame = wx.GetApp().GetTopWindow()
772 mdiParentFrame.ShowEmbeddedWindow(self.GetFrame(), show)
773
774
775 #----------------------------------------------------------------------------
776 # Methods for ProjectDocument and ProjectService to call
777 #----------------------------------------------------------------------------
778
779 def SetExpandedProjects(self, expandedProjects):
780 self._treeCtrl.UnselectAll()
781 firstItem = None
782 for i, item in enumerate(self._GetChildItems(self._treeCtrl.GetRootItem())):
783 if i == 0:
784 firstItem = item
785
786 if expandedProjects[i]:
787 self._treeCtrl.Expand(item)
788 else:
789 self._treeCtrl.Collapse(item)
790
791 if firstItem:
792 self._treeCtrl.EnsureVisible(firstItem)
793
794
795 def GetSelectedFile(self):
796 for item in self._treeCtrl.GetSelections():
797 return self._GetItemFile(item)
798
799
800 def AddProjectToView(self, document):
801 rootItem = self._treeCtrl.GetRootItem()
802 projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document))
803 self._treeCtrl.SetPyData(projectItem, document)
804 for file in document.GetFiles():
805 fileItem = self._treeCtrl.AppendItem(projectItem, os.path.basename(file))
806 self._treeCtrl.SetPyData(fileItem, file)
807 self._treeCtrl.SortChildren(rootItem)
808 self._treeCtrl.SortChildren(projectItem)
809 self._treeCtrl.UnselectAll()
810 self._treeCtrl.Expand(projectItem)
811 self._treeCtrl.SelectItem(projectItem)
812 if self._embeddedWindow:
813 document.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame()))
814
815
816 #----------------------------------------------------------------------------
817 # Control events
818 #----------------------------------------------------------------------------
819
820 def OnProperties(self, event):
821 items = self._treeCtrl.GetSelections()
822 if not items:
823 return
824 item = items[0]
825 if self._IsItemProject(item):
826 projectPropertiesDialog = ProjectPropertiesDialog(wx.GetApp().GetTopWindow(), self._GetItemProject(item).GetFilename())
827 if projectPropertiesDialog.ShowModal() == wx.ID_OK:
828 pass # Handle OK
829 projectPropertiesDialog.Destroy()
830 elif self._IsItemFile(item):
831 filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService)
832 filePropertiesService.ShowPropertiesDialog(self._GetItemFile(item))
833
834
835 def OnAddFileToProject(self, event):
836 if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__":
837 allfilter = ''
838 descr = ''
839 for temp in self.GetDocumentManager()._templates:
840 if temp.IsVisible():
841 if len(descr) > 0:
842 descr = descr + _('|')
843 allfilter = allfilter + _(';')
844 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
845 allfilter = allfilter + temp.GetFileFilter()
846 descr = _("All") + _(" (") + allfilter + _(") |") + allfilter + _('|') + descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
847 descr = descr + _("|") + _("Any (*.*) | *.*")
848 else:
849 descr = _("*.*")
850 if True or _WINDOWS:
851 dialog = wx.FileDialog(self.GetFrame(), _("Add Files"), self._lastDirectory, "", descr, wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE)
852 if dialog.ShowModal() != wx.ID_OK:
853 return
854 paths = dialog.GetPaths()
855 dialog.Destroy()
856 else:
857 paths = wx.FileSelector(_("Add Files"), self._lastDirectory, "", wildcard = descr, flags = wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE, parent=self.GetFrame())
858 if type(paths) == types.StringType:
859 paths = [paths]
860 if len(paths):
861 self._lastDirectory = wx.lib.docview.PathOnly(paths[0])
862 self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), paths))
863 self.Activate(True) # after add, should put focus on project editor
864
865
866 def DoAddFilesToProject(self, filenames):
867 # method used by Drag-n-Drop to add files to current Project
868 self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), filenames))
869
870
871 def DoSelectFiles(self, filenames):
872 # method used by Drag-n-Drop to select files in current Project
873 for selection in self._treeCtrl.GetSelections():
874 self._treeCtrl.SelectItem(selection, False)
875 for file in filenames:
876 item = self._GetFileItem(longFileName=file)
877 if item:
878 self._treeCtrl.SelectItem(item, True)
879 self._treeCtrl.EnsureVisible(item)
880
881
882 def DoSelectProject(self, x, y):
883 # method used by Drag-n-Drop to set current Project based on cursor position
884 item, flag = self._treeCtrl.HitTest((x,y))
885 if not item:
886 return False
887
888 project = self._GetItemProject(item)
889 if not project:
890 return False
891
892 projectItem = self._GetProjectItem(project)
893 self._treeCtrl.UnselectAll()
894 self._treeCtrl.SelectItem(projectItem)
895 return True
896
897
898 def OnFocus(self, event):
899 wx.GetApp().GetDocumentManager().ActivateView(self)
900 event.Skip()
901
902
903 def OnKillFocus(self, event):
904 # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
905 # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
906 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
907 childFrame = wx.GetApp().GetTopWindow().GetActiveChild()
908 if childFrame:
909 childFrame.Activate()
910 event.Skip()
911
912
913 def OnRightClick(self, event):
914 self.Activate(True)
915 if not self._treeCtrl.GetSelections():
916 return
917 if len(self._treeCtrl.GetSelections()) == 1 and self._IsItemRoot(self._treeCtrl.GetSelections()[0]):
918 return # Don't do a menu if it's just the root item selected
919 menu = wx.Menu()
920 if self._HasFilesSelected(): # Files context
921 menu.Append(ProjectService.OPEN_SELECTION_ID, _("&Open"), _("Opens the selection"))
922 menu.Enable(ProjectService.OPEN_SELECTION_ID, True)
923 wx.EVT_MENU(self._GetParentFrame(), ProjectService.OPEN_SELECTION_ID, self.OnOpenSelection)
924 itemIDs = [None]
925 for item in self._treeCtrl.GetSelections():
926 if self._IsItemProcessModelFile(item):
927 itemIDs = [None, ProjectService.RUN_SELECTED_PM_ID, None]
928 break
929 else: # Project context
930 itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None]
931 menuBar = self._GetParentFrame().GetMenuBar()
932 itemIDs = itemIDs + [wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID, None, ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT, None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, None, ProjectService.RENAME_ID]
933 for itemID in itemIDs:
934 if not itemID:
935 menu.AppendSeparator()
936 else:
937 if itemID == ProjectService.RUN_SELECTED_PM_ID:
938 menu.Append(ProjectService.RUN_SELECTED_PM_ID, _("Run Process"))
939 wx.EVT_MENU(self._GetParentFrame(), ProjectService.RUN_SELECTED_PM_ID, self.OnRunSelectedPM)
940 elif itemID == ProjectService.REMOVE_FROM_PROJECT:
941 menu.Append(ProjectService.REMOVE_FROM_PROJECT, _("Remove Selected Files from Project"))
942 wx.EVT_MENU(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self.OnClear)
943 wx.EVT_UPDATE_UI(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self._GetParentFrame().ProcessUpdateUIEvent)
944 else:
945 item = menuBar.FindItemById(itemID)
946 if item:
947 menu.Append(itemID, item.GetLabel())
948 self._treeCtrl.PopupMenu(menu, wx.Point(event.GetX(), event.GetY()))
949 menu.Destroy()
950
951 def OnRunSelectedPM(self, event):
952 projectService = wx.GetApp().GetService(ProjectService)
953 projectService.OnRunProcessModel(event, runSelected=True)
954
955 def OnRename(self, event):
956 if self._treeCtrl.GetSelections():
957 self._treeCtrl.EditLabel(self._treeCtrl.GetSelections()[0])
958
959
960 def OnBeginLabelEdit(self, event):
961 self._editingSoDontKillFocus = True
962 item = event.GetItem()
963 if not self._IsItemFile(item) and not self._IsItemProject(item):
964 event.Veto()
965
966
967 def OnEndLabelEdit(self, event):
968 self._editingSoDontKillFocus = False
969 item = event.GetItem()
970 newName = event.GetLabel()
971 if not newName or (not self._IsItemFile(item) and not self._IsItemProject(item)):
972 event.Veto()
973 return
974 if self._IsItemFile(item):
975 oldFile = self._GetItemFile(item)
976 newFile = os.path.join(os.path.split(oldFile)[0], newName)
977 if not self._GetItemProject(item).GetCommandProcessor().Submit(ProjectRenameFileCommand(self.GetDocument(), oldFile, newFile)):
978 event.Veto()
979 return
980 self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(self._treeCtrl.GetSelections()[0]))
981 elif self._IsItemProject(item):
982 oldFile = self._GetItemProject(item).GetFilename()
983 newFile = os.path.join(os.path.split(oldFile)[0], newName)
984 if not self._GetItemProject(item).GetCommandProcessor().Submit(ProjectRenameFileCommand(self.GetDocument(), oldFile, newFile, True)):
985 event.Veto()
986 return
987 self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem())
988
989
990 def CanPaste(self):
991 # wxBug: Should be able to use IsSupported/IsSupportedFormat here
992 #fileDataObject = wx.FileDataObject()
993 #hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
994 if not wx.TheClipboard.IsOpened():
995 if wx.TheClipboard.Open():
996 fileDataObject = wx.FileDataObject()
997 hasFilesInClipboard = wx.TheClipboard.GetData(fileDataObject)
998 wx.TheClipboard.Close()
999 else:
1000 hasFilesInClipboard = False
1001 return hasFilesInClipboard
1002
1003
1004 def OnCut(self, event):
1005 if self._AreSelectedItemsFromSameProject():
1006 self.OnCopy(event)
1007 self.OnClear(event)
1008
1009
1010 def OnCopy(self, event):
1011 fileDataObject = wx.FileDataObject()
1012 items = self._treeCtrl.GetSelections()
1013 for item in items:
1014 if self._IsItemFile(item):
1015 file = self._treeCtrl.GetPyData(item)
1016 fileDataObject.AddFile(file)
1017 if len(fileDataObject.GetFilenames()) > 0 and wx.TheClipboard.Open():
1018 wx.TheClipboard.SetData(fileDataObject)
1019 wx.TheClipboard.Close()
1020
1021
1022 def OnPaste(self, event):
1023 if wx.TheClipboard.Open():
1024 fileDataObject = wx.FileDataObject()
1025 if wx.TheClipboard.GetData(fileDataObject):
1026 self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), fileDataObject.GetFilenames()))
1027 wx.TheClipboard.Close()
1028
1029
1030 def OnClear(self, event):
1031 if self._AreSelectedItemsFromSameProject():
1032 items = self._treeCtrl.GetSelections()
1033 files = []
1034 for item in items:
1035 if self._IsItemFile(item):
1036 files.append(self._GetItemFile(item))
1037 self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self._GetItemProject(items[0]), files))
1038
1039
1040 def OnKeyPressed(self, event):
1041 key = event.KeyCode()
1042 if key == wx.WXK_DELETE:
1043 self.OnClear(event)
1044 else:
1045 event.Skip()
1046
1047
1048 def OnSelectAll(self, event):
1049 project = self.GetDocument()
1050 if project:
1051 self._treeCtrl.UnselectAll()
1052 for child in self._GetChildItems(self._GetProjectItem(project)):
1053 self._treeCtrl.SelectItem(child)
1054
1055
1056 def OnOpenSelectionSDI(self, event):
1057 # Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
1058 wx.CallAfter(self.OnOpenSelection, None)
1059
1060
1061 def OnOpenSelection(self, event):
1062 doc = None
1063 try:
1064 items = self._treeCtrl.GetSelections()
1065 for item in items:
1066 if self._IsItemFile(item):
1067 filepath = self._GetItemFile(item)
1068 if not os.path.exists(filepath):
1069 msgTitle = wx.GetApp().GetAppName()
1070 if not msgTitle:
1071 msgTitle = _("File Not Found")
1072 yesNoMsg = wx.MessageDialog(self.GetFrame(),
1073 _("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)),
1074 msgTitle,
1075 wx.YES_NO
1076 )
1077 if yesNoMsg.ShowModal() == wx.ID_NO:
1078 continue
1079 findFile = wx.FileDialog(self.GetFrame(),
1080 _("Choose a file"),
1081 wx.lib.docview.PathOnly(filepath),
1082 wx.lib.docview.FileNameFromPath(filepath),
1083 style = wx.OPEN
1084 )
1085 if findFile.ShowModal() == wx.ID_OK and findFile.GetPath():
1086 newpath = findFile.GetPath()
1087 else:
1088 newpath = None
1089 findFile.Destroy()
1090 if newpath:
1091 # update Project Model with new location
1092 self.GetDocument().RemoveFile(filepath)
1093 self.GetDocument().AddFile(newpath)
1094 filepath = newpath
1095
1096 doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT)
1097
1098 except IOError, (code, message):
1099 msgTitle = wx.GetApp().GetAppName()
1100 if not msgTitle:
1101 msgTitle = _("File Error")
1102 wx.MessageBox("Could not open '%s'." % wx.lib.docview.FileNameFromPath(filepath),
1103 msgTitle,
1104 wx.OK | wx.ICON_EXCLAMATION,
1105 self.GetFrame())
1106
1107
1108 #----------------------------------------------------------------------------
1109 # Convenience methods
1110 #----------------------------------------------------------------------------
1111
1112 def _HasFiles(self):
1113 if not self._treeCtrl:
1114 return False
1115 return self._treeCtrl.GetCount() > 1 # 1 item = root item, don't count as having files
1116
1117
1118 def _HasProjectsSelected(self):
1119 if not self._treeCtrl:
1120 return False
1121 items = self._treeCtrl.GetSelections()
1122 if not items:
1123 return False
1124 for item in items:
1125 if self._IsItemProject(item):
1126 return True
1127 return False
1128
1129
1130 def _HasFilesSelected(self):
1131 if not self._treeCtrl:
1132 return False
1133 items = self._treeCtrl.GetSelections()
1134 if not items:
1135 return False
1136 for item in items:
1137 if not self._IsItemFile(item):
1138 return False
1139 return True
1140
1141
1142 def _MakeProjectName(self, project):
1143 return project.GetPrintableName()
1144
1145
1146 # Return the tree item for a project
1147 def _GetProjectItem(self, project):
1148 children = self._GetChildItems(self._treeCtrl.GetRootItem())
1149 for child in children:
1150 if self._treeCtrl.GetPyData(child) == project:
1151 return child
1152 return None
1153
1154
1155 # Returns the project for an item, either for a project item or a file that is part of a project
1156 def _GetItemProject(self, item):
1157 if self._IsItemRoot(item):
1158 return None
1159 if self._IsItemProject(item):
1160 return self._treeCtrl.GetPyData(item)
1161 if self._IsItemFile(item):
1162 return self._treeCtrl.GetPyData(self._treeCtrl.GetItemParent(item))
1163 return None
1164
1165
1166 def _GetItemFile(self, item):
1167 if self._IsItemFile(item):
1168 return self._treeCtrl.GetPyData(item)
1169 else:
1170 return None
1171
1172
1173 def _GetFileItem(self, shortFileName = None, longFileName = None):
1174 """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """
1175
1176 if shortFileName:
1177 project_children = self._GetChildItems(self._treeCtrl.GetRootItem())
1178 for child in project_children:
1179 file_children = self._GetChildItems(child)
1180 for file_child in file_children:
1181 if self._treeCtrl.GetItemText(file_child) == shortFileName:
1182 return file_child
1183 return None
1184 else:
1185 project_children = self._GetChildItems(self._treeCtrl.GetRootItem())
1186 for child in project_children:
1187 file_children = self._GetChildItems(child)
1188 for file_child in file_children:
1189 if self._treeCtrl.GetPyData(file_child) == longFileName:
1190 return file_child
1191 return None
1192
1193
1194 def GetFilePathFromTreeName(self, shortFileName):
1195 """
1196 Returns the data object given a short (display) file name for a file. The data
1197 object should be the full path.
1198 """
1199 return self._GetItemFile(self._GetFileItem(shortFileName))
1200
1201
1202 def SelectFileInTree(self, shortFileName):
1203 item = self._GetFileItem(shortFileName)
1204 if item:
1205 for selection in self._treeCtrl.GetSelections():
1206 self._treeCtrl.SelectItem(selection, False)
1207 self._treeCtrl.SelectItem(item, True)
1208 self._treeCtrl.EnsureVisible(item)
1209
1210
1211 def _IsItemRoot(self, item):
1212 return item == self._treeCtrl.GetRootItem()
1213
1214
1215 def _IsItemProject(self, item):
1216 return isinstance(self._treeCtrl.GetPyData(item), ProjectDocument)
1217
1218
1219 def _IsItemFile(self, item):
1220 return isinstance(self._treeCtrl.GetPyData(item), types.StringTypes)
1221
1222
1223 def _IsItemProcessModelFile(self, item):
1224 if ACTIVEGRID_BASE_IDE:
1225 return False
1226
1227 if isinstance(self._treeCtrl.GetPyData(item), types.StringTypes):
1228 filename = self._treeCtrl.GetPyData(item)
1229 ext = None
1230 for template in self.GetDocumentManager().GetTemplates():
1231 if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
1232 ext = template.GetDefaultExtension()
1233 break;
1234 if not ext:
1235 return False
1236
1237 if filename.endswith(ext):
1238 return True
1239
1240 return False
1241
1242
1243 def _AreSelectedItemsFromSameProject(self):
1244 if not self._treeCtrl:
1245 return False
1246 items = self._treeCtrl.GetSelections()
1247 if not items:
1248 return False
1249 project = self._GetItemProject(items[0])
1250 if project == None:
1251 return False
1252 for item in items:
1253 if not self._IsItemFile(item):
1254 return False
1255 if self._GetItemProject(item) != project:
1256 return False
1257 return True
1258
1259
1260 def _GetChildItems(self, parentItem):
1261 children = []
1262 (child, cookie) = self._treeCtrl.GetFirstChild(parentItem)
1263 while child.IsOk():
1264 children.append(child)
1265 (child, cookie) = self._treeCtrl.GetNextChild(parentItem, cookie)
1266 return children
1267
1268
1269
1270 class ProjectFileDropTarget(wx.FileDropTarget):
1271
1272 def __init__(self, view):
1273 wx.FileDropTarget.__init__(self)
1274 self._view = view
1275
1276
1277 def OnDropFiles(self, x, y, filenames):
1278 if self._view.DoSelectProject(x, y):
1279 self._view.DoAddFilesToProject(filenames)
1280 self._view.DoSelectFiles(filenames)
1281 return True
1282 return False
1283
1284
1285 def OnDragOver(self, x, y, default):
1286 if self._view.DoSelectProject(x,y):
1287 return wx.DragCopy
1288 return wx.DragNone
1289
1290
1291 class ProjectPropertiesDialog(wx.Dialog):
1292
1293
1294 def __init__(self, parent, filename):
1295 wx.Dialog.__init__(self, parent, -1, _("Project Properties"), size = (310, 330))
1296
1297 HALF_SPACE = 5
1298 SPACE = 10
1299
1300 filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService)
1301
1302 notebook = wx.Notebook(self, -1)
1303 tab = wx.Panel(notebook, -1)
1304
1305 gridSizer = RowColSizer()
1306
1307 gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0)
1308 if os.path.isfile(filename):
1309 gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1]), row=0, col=1)
1310
1311 gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0)
1312 gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.split(filename)[0])), flag=wx.BOTTOM, border=SPACE, row=1, col=1)
1313
1314 gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0)
1315 gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1)
1316
1317 lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion
1318 lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND)
1319 gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2)
1320
1321 gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0)
1322 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1)
1323
1324 gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0)
1325 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1)
1326
1327 gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0)
1328 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1)
1329
1330 else:
1331 gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1] + ' ' + _("[new project]")), row=0, col=1)
1332
1333 # add a border around the inside of the tab
1334 spacerGrid = wx.BoxSizer(wx.VERTICAL)
1335 spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE);
1336 tab.SetSizer(spacerGrid)
1337 notebook.AddPage(tab, _("General"))
1338 if wx.Platform == "__WXMSW__":
1339 notebook.SetPageSize((310,200))
1340
1341 sizer = wx.BoxSizer(wx.VERTICAL)
1342 sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
1343 sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
1344
1345 sizer.Fit(self)
1346 self.SetDimensions(-1, -1, 310, -1, wx.SIZE_USE_EXISTING)
1347 self.SetSizer(sizer)
1348 self.Layout()
1349
1350
1351 class ProjectOptionsPanel(wx.Panel):
1352
1353
1354 def __init__(self, parent, id):
1355 wx.Panel.__init__(self, parent, id)
1356 self._useSashMessageShown = False
1357 SPACE = 10
1358 HALF_SPACE = 5
1359 config = wx.ConfigBase_Get()
1360 self._projSaveDocsCheckBox = wx.CheckBox(self, -1, _("Remember open projects"))
1361 self._projSaveDocsCheckBox.SetValue(config.ReadInt("ProjectSaveDocs", True))
1362 projectBorderSizer = wx.BoxSizer(wx.VERTICAL)
1363 projectSizer = wx.BoxSizer(wx.VERTICAL)
1364 projectSizer.Add(self._projSaveDocsCheckBox, 0, wx.ALL, HALF_SPACE)
1365 if not ACTIVEGRID_BASE_IDE:
1366 self._projShowWelcomeCheckBox = wx.CheckBox(self, -1, _("Show Welcome Dialog"))
1367 self._projShowWelcomeCheckBox.SetValue(config.ReadInt("RunWelcomeDialog", True))
1368 projectSizer.Add(self._projShowWelcomeCheckBox, 0, wx.ALL, HALF_SPACE)
1369 projectBorderSizer.Add(projectSizer, 0, wx.ALL, SPACE)
1370 self.SetSizer(projectBorderSizer)
1371 self.Layout()
1372 parent.AddPage(self, _("Project"))
1373
1374 def OnUseSashSelect(self, event):
1375 if not self._useSashMessageShown:
1376 msgTitle = wx.GetApp().GetAppName()
1377 if not msgTitle:
1378 msgTitle = _("Document Options")
1379 wx.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
1380 msgTitle,
1381 wx.OK | wx.ICON_INFORMATION,
1382 self.GetParent())
1383 self._useSashMessageShown = True
1384
1385
1386 def OnOK(self, optionsDialog):
1387 config = wx.ConfigBase_Get()
1388 config.WriteInt("ProjectSaveDocs", self._projSaveDocsCheckBox.GetValue())
1389 if not ACTIVEGRID_BASE_IDE:
1390 config.WriteInt("RunWelcomeDialog", self._projShowWelcomeCheckBox.GetValue())
1391
1392
1393 class ProjectService(Service.Service):
1394
1395 #----------------------------------------------------------------------------
1396 # Constants
1397 #----------------------------------------------------------------------------
1398 SHOW_WINDOW = wx.NewId() # keep this line for each subclass, need unique ID for each Service
1399 RUNPM_ID = wx.NewId()
1400 RUN_SELECTED_PM_ID = wx.NewId()
1401 RUN_CURRENT_PM_ID = wx.NewId()
1402 ADD_FILES_TO_PROJECT_ID = wx.NewId()
1403 ADD_CURRENT_FILE_TO_PROJECT_ID = wx.NewId()
1404 RENAME_ID = wx.NewId()
1405 OPEN_SELECTION_ID = wx.NewId()
1406 REMOVE_FROM_PROJECT = wx.NewId()
1407
1408
1409 #----------------------------------------------------------------------------
1410 # Overridden methods
1411 #----------------------------------------------------------------------------
1412
1413 def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT):
1414 Service.Service.__init__(self, serviceName, embeddedWindowLocation)
1415 self._runHandlers = []
1416 self._suppressOpenProjectMessages = False
1417
1418
1419 def _CreateView(self):
1420 return ProjectView(self)
1421
1422
1423 def ShowWindow(self, show = True):
1424 """ Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
1425 Service.Service.ShowWindow(self, show)
1426
1427 if show:
1428 project = self.GetView().GetDocument()
1429 if not project:
1430 self.OpenSavedProjects()
1431
1432
1433 #----------------------------------------------------------------------------
1434 # Service specific methods
1435 #----------------------------------------------------------------------------
1436
1437 def GetSuppressOpenProjectMessages(self):
1438 return self._suppressOpenProjectMessages
1439
1440
1441 def SetSuppressOpenProjectMessages(self, suppressOpenProjectMessages):
1442 self._suppressOpenProjectMessages = suppressOpenProjectMessages
1443
1444
1445 def GetRunHandlers(self):
1446 return self._runHandlers
1447
1448
1449 def AddRunHandler(self, runHandler):
1450 self._runHandlers.append(runHandler)
1451
1452
1453 def RemoveRunHandler(self, runHandler):
1454 self._runHandlers.remove(runHandler)
1455
1456
1457 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
1458 Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
1459
1460 config = wx.ConfigBase_Get()
1461
1462 projectMenu = wx.Menu()
1463
1464 ## accelTable = wx.AcceleratorTable([
1465 ## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
1466 ## ])
1467 ## frame.SetAcceleratorTable(accelTable)
1468 isProjectDocument = document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument
1469 if wx.GetApp().IsMDI() or isProjectDocument:
1470 if not menuBar.FindItemById(ProjectService.ADD_FILES_TO_PROJECT_ID):
1471 projectMenu.Append(ProjectService.ADD_FILES_TO_PROJECT_ID, _("&Add Files to Project..."), _("Adds a document to the current project"))
1472 wx.EVT_MENU(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessEvent)
1473 wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
1474 if not menuBar.FindItemById(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID):
1475 projectMenu.Append(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, _("&Add Active File to Project..."), _("Adds the active document to a project"))
1476 wx.EVT_MENU(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessEvent)
1477 wx.EVT_UPDATE_UI(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
1478 viewMenuIndex = menuBar.FindMenu(_("&View"))
1479 menuBar.Insert(viewMenuIndex + 1, projectMenu, _("&Project"))
1480 editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit")))
1481 if not menuBar.FindItemById(ProjectService.RENAME_ID):
1482 editMenu.AppendSeparator()
1483 editMenu.Append(ProjectService.RENAME_ID, _("&Rename"), _("Renames the active item"))
1484 wx.EVT_MENU(frame, ProjectService.RENAME_ID, frame.ProcessEvent)
1485 wx.EVT_UPDATE_UI(frame, ProjectService.RENAME_ID, frame.ProcessUpdateUIEvent)
1486
1487 return True
1488
1489
1490 def OnCloseFrame(self, event):
1491 if not self.GetView():
1492 return True
1493
1494 if wx.GetApp().IsMDI():
1495 # close all non-project documents first
1496 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1497 if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:
1498 if not self.GetDocumentManager().CloseDocument(document, False):
1499 return False
1500
1501 # write project config afterwards because user may change filenames on closing of new documents
1502 self.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
1503
1504 # close all project documents after closing other documents
1505 # because user may save a new document with a new name or cancel closing a document
1506 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1507 if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1508 if not document.OnSaveModified():
1509 return False
1510
1511 # This is called when any SDI frame is closed, so need to check if message window is closing or some other window
1512 elif self.GetView() == event.GetEventObject().GetView():
1513 self.SetView(None)
1514 return True
1515
1516
1517 #----------------------------------------------------------------------------
1518 # Event Processing Methods
1519 #----------------------------------------------------------------------------
1520
1521 def ProcessEventBeforeWindows(self, event):
1522 id = event.GetId()
1523 if id == wx.ID_CLOSE_ALL:
1524 self.OnFileCloseAll(event)
1525 return True
1526 return False
1527
1528
1529 def ProcessEvent(self, event):
1530 if Service.Service.ProcessEvent(self, event):
1531 return True
1532
1533 id = event.GetId()
1534 if id == ProjectService.RUN_SELECTED_PM_ID:
1535 self.OnRunProcessModel(event, runSelected=True)
1536 return True
1537 elif id == ProjectService.RUN_CURRENT_PM_ID:
1538 self.OnRunProcessModel(event, runCurrentFile=True)
1539 return True
1540 elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
1541 self.OnAddCurrentFileToProject(event)
1542 return True
1543 elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
1544 if self.GetView():
1545 return self.GetView().ProcessEvent(event)
1546 else:
1547 return False
1548 else:
1549 return False
1550
1551
1552 def ProcessUpdateUIEvent(self, event):
1553 if Service.Service.ProcessUpdateUIEvent(self, event):
1554 return True
1555
1556 id = event.GetId()
1557 if id == ProjectService.RUNPM_ID or id == ProjectService.RUN_SELECTED_PM_ID or id == ProjectService.RUN_CURRENT_PM_ID:
1558 event.Enable(self._HasOpenedProjects() and self._HasProcessModel())
1559 return True
1560 elif id == ProjectService.ADD_FILES_TO_PROJECT_ID:
1561 event.Enable(False)
1562 return True
1563 elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
1564 event.Enable(self._CanAddCurrentFileToProject())
1565 return True
1566 elif id == ProjectService.RENAME_ID:
1567 event.Enable(False)
1568 return True
1569 elif id == ProjectService.OPEN_SELECTION_ID:
1570 event.Enable(False)
1571 return True
1572 elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
1573 if self.GetView():
1574 return self.GetView().ProcessUpdateUIEvent(event)
1575 else:
1576 return False
1577 else:
1578 return False
1579
1580
1581 def OnRunProcessModel(self, event, runSelected=False, runCurrentFile=False):
1582 project = self.GetView().GetDocument()
1583
1584 if project:
1585 ext = None
1586 for template in self.GetDocumentManager().GetTemplates():
1587 if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
1588 ext = template.GetDefaultExtension()
1589 break;
1590 if not ext:
1591 return
1592
1593 files = filter(lambda f: f.endswith(ext), project.GetFiles())
1594 if not files:
1595 return
1596
1597 docs = wx.GetApp().GetDocumentManager().GetDocuments()
1598 for doc in docs:
1599 if doc.GetFilename() in files and doc.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
1600 if not doc.GetProcessModel().beginProcess:
1601 wx.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
1602 return
1603
1604 filesModified = False
1605 for doc in docs:
1606 if doc.IsModified():
1607 filesModified = True
1608 break
1609 if filesModified:
1610 frame = self.GetView().GetFrame()
1611 yesNoMsg = wx.MessageDialog(frame,
1612 _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
1613 _("Run Process"),
1614 wx.YES_NO
1615 )
1616 if yesNoMsg.ShowModal() == wx.ID_YES:
1617 wx.GetTopLevelParent(frame).OnFileSaveAll(None)
1618
1619 if runCurrentFile:
1620 fileToRun = self.GetDocumentManager().GetCurrentDocument().GetFilename()
1621 elif runSelected:
1622 fileToRun = self.GetView().GetSelectedFile()
1623 elif len(files) > 1:
1624 files.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower()))
1625 strings = map(lambda file: os.path.basename(file), files)
1626 res = wx.GetSingleChoiceIndex(_("Select a process to run:"),
1627 _("Run"),
1628 strings,
1629 project.GetFirstView()._GetParentFrame())
1630 if res == -1:
1631 return
1632 fileToRun = files[res]
1633 else:
1634 fileToRun = files[0]
1635
1636 self.RunProcessModel(fileToRun)
1637
1638
1639 def RunProcessModel(self, fileToRun):
1640 for runHandler in self.GetRunHandlers():
1641 if runHandler.RunProjectFile(fileToRun):
1642 return
1643 os.system('"' + fileToRun + '"')
1644
1645
1646 def _HasProcessModel(self):
1647 project = self.GetView().GetDocument()
1648
1649 if project:
1650 ext = None
1651 for template in self.GetDocumentManager().GetTemplates():
1652 if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
1653 ext = template.GetDefaultExtension()
1654 break;
1655 if not ext:
1656 return False
1657
1658 files = filter(lambda f: f.endswith(ext), project.GetFiles())
1659 if not files:
1660 return False
1661
1662 if len(files):
1663 return True
1664
1665 return False
1666
1667
1668 def _HasOpenedProjects(self):
1669 for document in self.GetDocumentManager().GetDocuments():
1670 if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1671 return True
1672 return False
1673
1674
1675 def _HasCurrentFile(self):
1676 currentDoc = self.GetDocumentManager().GetCurrentDocument()
1677 return currentDoc
1678
1679
1680 def _CanAddCurrentFileToProject(self):
1681 currentDoc = self.GetDocumentManager().GetCurrentDocument()
1682 if not currentDoc:
1683 return False
1684 if currentDoc.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1685 return False
1686 if not currentDoc._savedYet:
1687 return False
1688 for document in self.GetDocumentManager().GetDocuments():
1689 if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1690 return True
1691 return False # There are no documents open
1692
1693
1694 def GetFilesFromCurrentProject(self):
1695 view = self.GetView()
1696 if view:
1697 project = view.GetDocument()
1698 if project:
1699 return project.GetFiles()
1700 return None
1701
1702
1703 def GetCurrentProject(self):
1704 view = self.GetView()
1705 if view:
1706 return view.GetDocument()
1707 return None
1708
1709
1710 def FindProjectByFile(self, filename):
1711 for document in self.GetDocumentManager().GetDocuments():
1712 if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1713 if document.GetFilename() == filename:
1714 return document
1715 elif document.IsFileInProject(filename):
1716 return document
1717 return None
1718
1719
1720 def GetCurrentProjectNames(self):
1721 projects = []
1722 for document in self.GetDocumentManager().GetDocuments():
1723 if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1724 projects.append(document)
1725 if not projects:
1726 return
1727 projects.sort(lambda a, b: cmp(a.GetPrintableName().lower(), b.GetPrintableName().lower()))
1728 strings = map(lambda project: project.GetPrintableName(), projects)
1729 return strings
1730
1731 def OnAddCurrentFileToProject(self, event):
1732 if not self._CanAddCurrentFileToProject():
1733 return
1734 projects = []
1735 for document in self.GetDocumentManager().GetDocuments():
1736 if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
1737 projects.append(document)
1738 if not projects:
1739 return
1740 projects.sort(lambda a, b: cmp(a.GetPrintableName().lower(), b.GetPrintableName().lower()))
1741 strings = map(lambda project: project.GetPrintableName(), projects)
1742 res = wx.GetSingleChoiceIndex(_("Select a project to add the file to:"),
1743 _("Add to Project"),
1744 strings,
1745 self.GetDocumentManager().FindSuitableParent())
1746 if res == -1:
1747 return
1748 file = self.GetDocumentManager().GetCurrentDocument().GetFilename()
1749 projects[res].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects[res], [file]))
1750 self.GetView().Activate(True) # after add, should put focus on project editor
1751
1752
1753 def OnFileCloseAll(self, event):
1754 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1755 if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:
1756 if not self.GetDocumentManager().CloseDocument(document, False):
1757 return
1758 # document.DeleteAllViews() # Implicitly delete the document when the last view is removed
1759
1760
1761 def OpenSavedProjects(self):
1762 config = wx.ConfigBase_Get()
1763 openedDocs = False
1764 if config.ReadInt("ProjectSaveDocs", True):
1765 docString = config.Read("ProjectSavedDocs")
1766 if docString:
1767 doc = None
1768 for fileName in eval(docString):
1769 if isinstance(fileName, types.StringTypes):
1770 if os.path.exists(fileName):
1771 doc = self.GetDocumentManager().CreateDocument(fileName, wx.lib.docview.DOC_SILENT)
1772
1773 if doc:
1774 openedDocs = True
1775 expandedString = config.Read("ProjectExpandedSavedDocs")
1776 if expandedString:
1777 view = doc.GetFirstView()
1778 view.SetExpandedProjects(eval(expandedString))
1779 return openedDocs
1780
1781 #----------------------------------------------------------------------------
1782 # Icon Bitmaps - generated by encode_bitmaps.py
1783 #----------------------------------------------------------------------------
1784 from wx import ImageFromStream, BitmapFromImage
1785 import cStringIO
1786
1787
1788 def getProjectData():
1789 return \
1790 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1791 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1792 \x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
1793 \x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
1794 YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
1795 \xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
1796
1797 def getProjectBitmap():
1798 return BitmapFromImage(getProjectImage())
1799
1800 def getProjectImage():
1801 stream = cStringIO.StringIO(getProjectData())
1802 return ImageFromStream(stream)
1803
1804 def getProjectIcon():
1805 return wx.IconFromBitmap(getProjectBitmap())
1806
1807
1808 #----------------------------------------------------------------------------
1809
1810 def getBlankData():
1811 return \
1812 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
1813 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
1814 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
1815 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
1816 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
1817 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
1818 \x00\x00IEND\xaeB`\x82'
1819
1820
1821 def getBlankBitmap():
1822 return BitmapFromImage(getBlankImage())
1823
1824 def getBlankImage():
1825 stream = cStringIO.StringIO(getBlankData())
1826 return ImageFromStream(stream)
1827
1828 def getBlankIcon():
1829 return wx.IconFromBitmap(getBlankBitmap())
1830