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