2eeaec1909
"Closing view crashes Python" plus some new features: New feature added to the IDE is 'Extensions'. Under Tools|Options|Extensions, you can add calls to external programs. For example you can add a "Notepad" extension (under windows) that will exec Notepad on the currently open file. A new "Notepad" menu item will appear under the Tools menu. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34638 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2240 lines
89 KiB
Python
2240 lines
89 KiB
Python
#----------------------------------------------------------------------------
|
|
# Name: ProjectEditor.py
|
|
# Purpose: IDE-style Project Editor for wx.lib.pydocview
|
|
#
|
|
# Author: Peter Yared, Morgan Hua
|
|
#
|
|
# Created: 8/15/03
|
|
# CVS-ID: $Id$
|
|
# Copyright: (c) 2003, 2004, 2005 ActiveGrid, Inc.
|
|
# License: wxWindows License
|
|
#----------------------------------------------------------------------------
|
|
|
|
import wx.lib.docview
|
|
import wx.lib.pydocview
|
|
import types
|
|
import os
|
|
import os.path
|
|
import wx
|
|
from wxPython.lib.rcsizer import RowColSizer
|
|
import time
|
|
import Service
|
|
import sys
|
|
import activegrid.util.xmlutils
|
|
import UICommon
|
|
import Wizard
|
|
import SVNService
|
|
from IDE import ACTIVEGRID_BASE_IDE
|
|
if not ACTIVEGRID_BASE_IDE:
|
|
import ProcessModelEditor
|
|
from SVNService import SVN_INSTALLED
|
|
|
|
_ = wx.GetTranslation
|
|
|
|
if wx.Platform == '__WXMSW__':
|
|
_WINDOWS = True
|
|
else:
|
|
_WINDOWS = False
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Constants
|
|
#----------------------------------------------------------------------------
|
|
SPACE = 10
|
|
HALF_SPACE = 5
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# XML Marshalling Methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def load(fileObject):
|
|
return activegrid.util.xmlutils.defaultLoad(fileObject, knownTypes={"projectmodel" : ProjectModel})
|
|
|
|
def save(fileObject, projectModel):
|
|
activegrid.util.xmlutils.defaultSave(fileObject, projectModel, prettyPrint=True, knownTypes={"projectmodel" : ProjectModel})
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Classes
|
|
#----------------------------------------------------------------------------
|
|
|
|
class ProjectModel:
|
|
__xmlname__ = "projectmodel"
|
|
__xmlrename__ = { "_files":"files"}
|
|
|
|
|
|
def __init__(self):
|
|
self._files = []
|
|
|
|
def initialize(self):
|
|
pass
|
|
|
|
|
|
class ProjectDocument(wx.lib.docview.Document):
|
|
|
|
|
|
def __init__(self):
|
|
wx.lib.docview.Document.__init__(self)
|
|
self._projectModel = ProjectModel()
|
|
|
|
|
|
def GetModel(self):
|
|
return self._projectModel
|
|
|
|
|
|
def OnCreate(self, path, flags):
|
|
projectService = wx.GetApp().GetService(ProjectService)
|
|
if projectService.GetView():
|
|
# All project documents share the same view.
|
|
view = projectService.GetView()
|
|
self.AddView(view)
|
|
|
|
if view.GetDocument():
|
|
# All project documents need to share the same command processor,
|
|
# to enable redo/undo of cross project document commands
|
|
cmdProcessor = view.GetDocument().GetCommandProcessor()
|
|
if cmdProcessor:
|
|
self.SetCommandProcessor(cmdProcessor)
|
|
else:
|
|
view = self.GetDocumentTemplate().CreateView(self, flags)
|
|
projectService.SetView(view)
|
|
|
|
|
|
return view
|
|
|
|
|
|
def LoadObject(self, fileObject):
|
|
self._projectModel = activegrid.tool.ProjectEditor.load(fileObject)
|
|
self._projectModel._files = self.RelativeToAbsPath(self._projectModel._files)
|
|
return True
|
|
|
|
|
|
def SaveObject(self, fileObject):
|
|
absPath = self._projectModel._files
|
|
self._projectModel._files = self.AbsToRelativePath(absPath) # temporarily change it to relative paths for saving
|
|
activegrid.tool.ProjectEditor.save(fileObject, self._projectModel)
|
|
self._projectModel._files = absPath # swap it back to absolute path
|
|
return True
|
|
|
|
|
|
def AbsToRelativePath(self, paths):
|
|
curPath = os.path.dirname(self.GetFilename())
|
|
curPathLen = len(curPath)
|
|
|
|
newFilePaths = []
|
|
for path in paths:
|
|
if path.startswith(curPath):
|
|
path = "." + path[curPathLen:] # use relative path
|
|
if os.sep != '/':
|
|
path = path.replace(os.sep, '/', -1) # always save out with '/' as path separator for cross-platform compatibility.
|
|
else:
|
|
pass # use absolute path
|
|
newFilePaths.append(path)
|
|
return newFilePaths
|
|
|
|
|
|
def RelativeToAbsPath(self, paths):
|
|
newFilePaths = []
|
|
for path in paths:
|
|
if path.startswith("."): # relative to project file
|
|
curPath = os.path.dirname(self.GetFilename())
|
|
path = os.path.normpath(os.path.join(curPath, path))
|
|
newFilePaths.append(path)
|
|
return newFilePaths
|
|
|
|
|
|
def OnOpenDocument(self, filename):
|
|
view = self.GetFirstView()
|
|
frame = view.GetFrame()
|
|
|
|
if not os.path.exists(filename):
|
|
wx.GetApp().CloseSplash()
|
|
msgTitle = wx.GetApp().GetAppName()
|
|
if not msgTitle:
|
|
msgTitle = _("File Error")
|
|
wx.MessageBox(_("Could not find '%s'.") % filename,
|
|
msgTitle,
|
|
wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP,
|
|
frame)
|
|
return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
|
|
|
|
fileObject = file(filename, 'r')
|
|
try:
|
|
self.LoadObject(fileObject)
|
|
except:
|
|
wx.GetApp().CloseSplash()
|
|
msgTitle = wx.GetApp().GetAppName()
|
|
if not msgTitle:
|
|
msgTitle = _("File Error")
|
|
wx.MessageBox(_("Could not open '%s'. %s") % (wx.lib.docview.FileNameFromPath(filename), sys.exc_value),
|
|
msgTitle,
|
|
wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP,
|
|
frame)
|
|
return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed
|
|
|
|
self.Modify(False)
|
|
self.SetFilename(filename, True)
|
|
view.AddProjectToView(self)
|
|
self.SetDocumentModificationDate()
|
|
self.UpdateAllViews()
|
|
self._savedYet = True
|
|
view.Activate(True)
|
|
return True
|
|
|
|
|
|
def AddFile(self, file):
|
|
return self.AddFiles([file])
|
|
|
|
|
|
def AddFiles(self, files):
|
|
notAlreadyThereFiles = filter(lambda x: x not in self._projectModel._files, files) # Filter to the files that are not already in the project
|
|
if len(notAlreadyThereFiles) == 0:
|
|
self.UpdateAllViews(hint = ("select", self, files))
|
|
return False
|
|
else:
|
|
self._projectModel._files = self._projectModel._files + notAlreadyThereFiles
|
|
self.UpdateAllViews(hint = ("add", self, notAlreadyThereFiles))
|
|
self.Modify(True)
|
|
return True
|
|
|
|
|
|
def RemoveFile(self, file):
|
|
return self.RemoveFiles([file])
|
|
|
|
|
|
def RemoveFiles(self, files):
|
|
for file in files:
|
|
self._projectModel._files.remove(file)
|
|
self.UpdateAllViews(hint = ("remove", self, files))
|
|
self.Modify(True)
|
|
return True
|
|
|
|
|
|
def RenameFile(self, oldFile, newFile, isProject = False):
|
|
try:
|
|
if oldFile == newFile:
|
|
return False
|
|
|
|
# projects don't have to exist yet, so not required to rename old file,
|
|
# but files must exist, so we'll try to rename and allow exceptions to occur if can't.
|
|
if not isProject or (isProject and os.path.exists(oldFile)):
|
|
os.rename(oldFile, newFile)
|
|
|
|
if isProject:
|
|
documents = self.GetDocumentManager().GetDocuments()
|
|
for document in documents:
|
|
if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFile): # If the renamed document is open, update it
|
|
document.SetFilename(newFile)
|
|
document.SetTitle(wx.lib.docview.FileNameFromPath(newFile))
|
|
document.UpdateAllViews(hint = ("rename", document, newFile))
|
|
else:
|
|
self.RemoveFile(oldFile)
|
|
self.AddFile(newFile)
|
|
documents = self.GetDocumentManager().GetDocuments()
|
|
for document in documents:
|
|
if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFile): # If the renamed document is open, update it
|
|
document.SetFilename(newFile, notifyViews = True)
|
|
document.UpdateAllViews(hint = ("rename", document, newFile))
|
|
return True
|
|
except OSError, (code, message):
|
|
msgTitle = wx.GetApp().GetAppName()
|
|
if not msgTitle:
|
|
msgTitle = _("File Error")
|
|
wx.MessageBox("Could not rename '%s'. '%s'" % (wx.lib.docview.FileNameFromPath(oldFile), message),
|
|
msgTitle,
|
|
wx.OK | wx.ICON_EXCLAMATION,
|
|
self.GetFirstView().GetFrame())
|
|
return False
|
|
|
|
|
|
def GetFiles(self):
|
|
return self._projectModel._files
|
|
|
|
|
|
def IsFileInProject(self, filename):
|
|
return filename in self.GetFiles()
|
|
|
|
|
|
class NewProjectWizard(Wizard.BaseWizard):
|
|
|
|
WIZTITLE = _("New Project Wizard")
|
|
|
|
def __init__(self, parent):
|
|
self._parent = parent
|
|
self._fullProjectPath = None
|
|
Wizard.BaseWizard.__init__(self, parent, self.WIZTITLE)
|
|
self._projectLocationPage = self.CreateProjectLocation(self)
|
|
wx.wizard.EVT_WIZARD_PAGE_CHANGING(self, self.GetId(), self.OnWizPageChanging)
|
|
|
|
|
|
def CreateProjectLocation(self,wizard):
|
|
page = Wizard.TitledWizardPage(wizard, _("Project File Location"))
|
|
|
|
page.GetSizer().Add(wx.StaticText(page, -1, _("\nSelect the directory and filename for the project.\n\n")))
|
|
self._projectName, self._dirCtrl, sizer, self._fileValidation = UICommon.CreateDirectoryControl(page, _("File Name:"), _("Directory:"), _("agp"), startingDirectory=os.getcwd())
|
|
page.GetSizer().Add(sizer, 1, flag=wx.EXPAND)
|
|
|
|
wizard.Layout()
|
|
wizard.FitToPage(page)
|
|
return page
|
|
|
|
|
|
def RunWizard(self, existingTables = None, existingRelationships = None):
|
|
status = wx.wizard.Wizard.RunWizard(self, self._projectLocationPage)
|
|
if status:
|
|
docManager = wx.GetApp().GetTopWindow().GetDocumentManager()
|
|
if os.path.exists(self._fullProjectPath):
|
|
# What if the document is already open and we're overwriting it?
|
|
documents = docManager.GetDocuments()
|
|
for document in documents:
|
|
if os.path.normcase(document.GetFilename()) == os.path.normcase(self._fullProjectPath): # If the renamed document is open, update it
|
|
document.DeleteAllViews()
|
|
break
|
|
os.remove(self._fullProjectPath)
|
|
|
|
for template in docManager.GetTemplates():
|
|
if template.GetDocumentType() == ProjectDocument:
|
|
doc = template.CreateDocument(self._fullProjectPath, flags = wx.lib.docview.DOC_NEW)
|
|
doc.OnSaveDocument(self._fullProjectPath)
|
|
view = doc.GetFirstView()
|
|
view.AddProjectToView(doc)
|
|
break
|
|
|
|
self.Destroy()
|
|
return status
|
|
|
|
|
|
def OnWizPageChanging(self, event):
|
|
if event.GetDirection(): # It's going forwards
|
|
if event.GetPage() == self._projectLocationPage:
|
|
if not self._fileValidation():
|
|
event.Veto()
|
|
return
|
|
self._fullProjectPath = os.path.join(self._dirCtrl.GetValue(),UICommon.MakeNameEndInExtension(self._projectName.GetValue(),'.agp'))
|
|
|
|
|
|
|
|
def OnShowCreatePages(self):
|
|
self.Hide()
|
|
import DataModelEditor
|
|
requestedPos = self.GetPositionTuple()
|
|
projectService = wx.GetApp().GetService(ProjectService)
|
|
projectView = projectService.GetView()
|
|
|
|
wiz = DataModelEditor.ImportExportWizard(projectView.GetFrame(), pos=requestedPos)
|
|
if wiz.RunWizard(dontDestroy=True):
|
|
self._schemaName.SetValue(wiz.GetSchemaFileName())
|
|
wiz.Destroy()
|
|
self.Show(True)
|
|
|
|
|
|
class ProjectTemplate(wx.lib.docview.DocTemplate):
|
|
|
|
|
|
def CreateDocument(self, path, flags):
|
|
if path:
|
|
return wx.lib.docview.DocTemplate.CreateDocument(self, path, flags)
|
|
else:
|
|
wiz = NewProjectWizard(wx.GetApp().GetTopWindow())
|
|
wiz.RunWizard()
|
|
wiz.Destroy()
|
|
return None # never return the doc, otherwise docview will think it is a new file and rename it
|
|
|
|
|
|
class ProjectAddFilesCommand(wx.lib.docview.Command):
|
|
|
|
|
|
def __init__(self, projectDoc, files):
|
|
wx.lib.docview.Command.__init__(self, canUndo = True)
|
|
self._projectDoc = projectDoc
|
|
self._files = files
|
|
|
|
|
|
def GetName(self):
|
|
if len(self._files) == 1:
|
|
return _("Add File %s") % os.path.basename(self._files[0])
|
|
else:
|
|
return _("Add Files")
|
|
|
|
|
|
def Do(self):
|
|
return self._projectDoc.AddFiles(self._files)
|
|
|
|
|
|
def Undo(self):
|
|
return self._projectDoc.RemoveFiles(self._files)
|
|
|
|
|
|
class ProjectRemoveFilesCommand(wx.lib.docview.Command):
|
|
|
|
|
|
def __init__(self, files):
|
|
wx.lib.docview.Command.__init__(self, canUndo = True)
|
|
self._files = files
|
|
|
|
|
|
def GetName(self):
|
|
if len(self._files) == 1:
|
|
return _("Remove File %s") % os.path.basename((self._files[0])[1])
|
|
else:
|
|
return _("Remove Files")
|
|
|
|
|
|
def Do(self):
|
|
status = False
|
|
projects = []
|
|
for data in self._files:
|
|
proj, filename = data
|
|
if proj not in projects:
|
|
projects.append(proj)
|
|
for project in projects:
|
|
files = []
|
|
for data in self._files:
|
|
proj, filename = data
|
|
if project == proj:
|
|
files.append(filename)
|
|
status = project.RemoveFiles(files) or status
|
|
return status
|
|
|
|
|
|
def Undo(self):
|
|
status = False
|
|
projects = []
|
|
for data in self._files:
|
|
proj, filename = data
|
|
if proj not in projects:
|
|
projects.append(proj)
|
|
for project in projects:
|
|
files = []
|
|
for data in self._files:
|
|
proj, filename = data
|
|
if project == proj:
|
|
files.append(filename)
|
|
status = project.AddFiles(files) or status
|
|
return status
|
|
|
|
|
|
class ProjectRenameFileCommand(wx.lib.docview.Command):
|
|
|
|
|
|
def __init__(self, projectDoc, oldFile, newFile, isProject = False):
|
|
wx.lib.docview.Command.__init__(self, canUndo = True)
|
|
self._projectDoc = projectDoc
|
|
self._oldFile = oldFile
|
|
self._newFile = newFile
|
|
self._isProject = isProject
|
|
|
|
|
|
def GetName(self):
|
|
return _("Rename File %s to %s") % (os.path.basename(self._oldFile), os.path.basename(self._newFile))
|
|
|
|
|
|
def Do(self):
|
|
return self._projectDoc.RenameFile(self._oldFile, self._newFile, self._isProject)
|
|
|
|
|
|
def Undo(self):
|
|
return self._projectDoc.RenameFile(self._newFile, self._oldFile, self._isProject)
|
|
|
|
|
|
class ProjectTreeCtrl(wx.TreeCtrl):
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Overridden Methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def __init__(self, parent, id, style):
|
|
wx.TreeCtrl.__init__(self, parent, id, style = style)
|
|
|
|
templates = wx.GetApp().GetDocumentManager().GetTemplates()
|
|
iconList = wx.ImageList(16, 16, initialCount = len(templates))
|
|
self._iconIndexLookup = []
|
|
for template in templates:
|
|
icon = template.GetIcon()
|
|
if icon:
|
|
if icon.GetHeight() != 16 or icon.GetWidth() != 16:
|
|
icon.SetHeight(16)
|
|
icon.SetWidth(16)
|
|
if wx.GetApp().GetDebug():
|
|
print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName
|
|
iconIndex = iconList.AddIcon(icon)
|
|
self._iconIndexLookup.append((template, iconIndex))
|
|
|
|
icon = getBlankIcon()
|
|
if icon.GetHeight() != 16 or icon.GetWidth() != 16:
|
|
icon.SetHeight(16)
|
|
icon.SetWidth(16)
|
|
if wx.GetApp().GetDebug():
|
|
print "Warning: getBlankIcon isn't 16x16, not crossplatform"
|
|
self._blankIconIndex = iconList.AddIcon(icon)
|
|
self.AssignImageList(iconList)
|
|
|
|
|
|
def OnCompareItems(self, item1, item2):
|
|
return cmp(self.GetItemText(item1).lower(), self.GetItemText(item2).lower())
|
|
|
|
|
|
def AppendItem(self, parent, filepath):
|
|
item = wx.TreeCtrl.AppendItem(self, parent, filepath)
|
|
|
|
found = False
|
|
template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filepath)
|
|
if not template and parent == self.GetRootItem(): # If the parent is a root it's a new project
|
|
template = wx.GetApp().GetDocumentManager().FindTemplateForPath('.agp')
|
|
if template:
|
|
for t, iconIndex in self._iconIndexLookup:
|
|
if t is template:
|
|
self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Normal)
|
|
self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Expanded)
|
|
self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected)
|
|
found = True
|
|
break
|
|
|
|
if not found:
|
|
self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Normal)
|
|
self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Expanded)
|
|
self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected)
|
|
|
|
return item
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Client Data
|
|
#----------------------------------------------------------------------------
|
|
|
|
def SetData(self, item, longFilename, projectDoc=None):
|
|
self.SetPyData(item, (longFilename, projectDoc))
|
|
|
|
|
|
def GetData(self, item):
|
|
""" returns longFilename and optional
|
|
"""
|
|
data = self.GetPyData(item)
|
|
if not data:
|
|
return (None, None)
|
|
return data
|
|
|
|
|
|
def GetLongFilename(self, item):
|
|
return self.GetData(item)[0]
|
|
|
|
|
|
def GetProjectDoc(self, item):
|
|
return self.GetData(item)[1]
|
|
|
|
|
|
class ProjectView(wx.lib.docview.View):
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Overridden methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def __init__(self, service = None):
|
|
wx.lib.docview.View.__init__(self)
|
|
self._service = service # not used, but kept to match other Services
|
|
self._treeCtrl = None
|
|
self._editingSoDontKillFocus = False
|
|
self._checkEditMenu = True
|
|
|
|
|
|
def Destroy(self):
|
|
projectService = wx.GetApp().GetService(ProjectService)
|
|
if projectService:
|
|
projectService.SetView(None)
|
|
wx.lib.docview.View.Destroy(self)
|
|
|
|
|
|
def GetDocument(self):
|
|
if not self._treeCtrl:
|
|
return None
|
|
|
|
items = self._treeCtrl.GetSelections()
|
|
if not items: # No selection, so just return first project
|
|
item = self._treeCtrl.GetFirstVisibleItem()
|
|
if item.IsOk():
|
|
return self._GetItemProject(item)
|
|
else:
|
|
return None
|
|
|
|
for item in items:
|
|
project = self._GetItemProject(item)
|
|
if project:
|
|
return project
|
|
|
|
return None
|
|
|
|
|
|
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
|
|
return wx.GetApp().GetDocumentManager()
|
|
|
|
|
|
def OnChangeFilename(self):
|
|
if self.GetFrame():
|
|
title = _("Projects")
|
|
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName():
|
|
title = title + " - " + wx.GetApp().GetAppName()
|
|
self.GetFrame().SetTitle(title)
|
|
project = self.GetDocument()
|
|
if project:
|
|
projectItem = self._GetProjectItem(project)
|
|
name = self._treeCtrl.GetItemText(self._GetProjectItem(project))
|
|
name2 = self._MakeProjectName(project)
|
|
if name != name2:
|
|
self._treeCtrl.SetItemText(projectItem, name2)
|
|
self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem())
|
|
|
|
|
|
def Activate(self, activate = True):
|
|
if not wx.GetApp().IsMDI():
|
|
if activate and not self.IsShown():
|
|
self.Show()
|
|
|
|
if self.IsShown():
|
|
wx.lib.docview.View.Activate(self, activate = activate)
|
|
if activate and self._treeCtrl:
|
|
self._treeCtrl.SetFocus()
|
|
|
|
|
|
def OnCreate(self, doc, flags):
|
|
config = wx.ConfigBase_Get()
|
|
if wx.GetApp().IsMDI():
|
|
self._embeddedWindow = wx.GetApp().GetTopWindow().GetEmbeddedWindow(wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT)
|
|
self.SetFrame(self._embeddedWindow)
|
|
frame = self._embeddedWindow
|
|
else:
|
|
self._embeddedWindow = None
|
|
pos = config.ReadInt("ProjectFrameXLoc", -1), config.ReadInt("ProjectFrameYLoc", -1)
|
|
# make sure frame is visible
|
|
screenWidth = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
|
|
screenHeight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
|
|
if pos[0] < 0 or pos[0] >= screenWidth or pos[1] < 0 or pos[1] >= screenHeight:
|
|
pos = wx.DefaultPosition
|
|
|
|
size = wx.Size(config.ReadInt("ProjectFrameXSize", -1), config.ReadInt("ProjectFrameYSize", -1))
|
|
|
|
title = _("Projects")
|
|
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName():
|
|
title = title + " - " + wx.GetApp().GetAppName()
|
|
|
|
frame = wx.GetApp().CreateDocumentFrame(self, doc, 0, title = title, pos = pos, size = size)
|
|
if config.ReadInt("ProjectFrameMaximized", False):
|
|
frame.Maximize(True)
|
|
|
|
sizer = wx.BoxSizer()
|
|
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)
|
|
self._treeCtrl.AddRoot(_("Projects"))
|
|
wx.EVT_TREE_BEGIN_DRAG(self._treeCtrl, self._treeCtrl.GetId(), self.OnBeginDrag)
|
|
wx.EVT_TREE_END_DRAG(self._treeCtrl, self._treeCtrl.GetId(), self.OnEndDrag)
|
|
|
|
if self._embeddedWindow:
|
|
sizer.Add(self._treeCtrl)
|
|
sizer.Fit(frame)
|
|
else:
|
|
sizer.Add(self._treeCtrl, 1, wx.EXPAND, 0)
|
|
frame.SetSizer(sizer)
|
|
frame.Layout()
|
|
self.Activate()
|
|
|
|
if wx.GetApp().IsMDI():
|
|
wx.EVT_SET_FOCUS(self._treeCtrl, self.OnFocus)
|
|
wx.EVT_KILL_FOCUS(self._treeCtrl, self.OnKillFocus)
|
|
|
|
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
|
|
wx.EVT_TREE_ITEM_ACTIVATED(self._treeCtrl, self._treeCtrl.GetId(), self.OnOpenSelectionSDI)
|
|
else:
|
|
wx.EVT_TREE_ITEM_ACTIVATED(self._treeCtrl, self._treeCtrl.GetId(), self.OnOpenSelection)
|
|
wx.EVT_TREE_BEGIN_LABEL_EDIT(self._treeCtrl, self._treeCtrl.GetId(), self.OnBeginLabelEdit)
|
|
wx.EVT_TREE_END_LABEL_EDIT(self._treeCtrl, self._treeCtrl.GetId(), self.OnEndLabelEdit)
|
|
wx.EVT_RIGHT_DOWN(self._treeCtrl, self.OnRightClick)
|
|
wx.EVT_KEY_DOWN(self._treeCtrl, self.OnKeyPressed)
|
|
# wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason
|
|
|
|
# drag-and-drop support
|
|
dt = ProjectFileDropTarget(self)
|
|
self._treeCtrl.SetDropTarget(dt)
|
|
|
|
return True
|
|
|
|
|
|
def OnBeginDrag(self, event):
|
|
item = event.GetItem()
|
|
if item.IsOk():
|
|
if item == self._treeCtrl.GetRootItem():
|
|
return
|
|
self._draggingItem = item
|
|
event.Allow()
|
|
|
|
|
|
def OnEndDrag(self, event):
|
|
item = event.GetItem()
|
|
if item.IsOk():
|
|
# don't allow object to be dragged to itself
|
|
if item == self._draggingItem:
|
|
return
|
|
|
|
rootItem = self._treeCtrl.GetRootItem()
|
|
|
|
# don't let object replace root view
|
|
if item == rootItem:
|
|
wx.MessageBox(_("Cannot replace root view with item."))
|
|
return
|
|
|
|
# don't allow object to be dragged to a direct descendant
|
|
ancestor = self._treeCtrl.GetItemParent(item)
|
|
while ancestor != rootItem:
|
|
if ancestor == self._draggingItem:
|
|
wx.MessageBox(_("Cannot make item direct descendant of self."))
|
|
return
|
|
else:
|
|
ancestor = self._treeCtrl.GetItemParent(ancestor)
|
|
|
|
if self._treeCtrl.GetItemParent(item) == self._treeCtrl.GetItemParent(self._draggingItem):
|
|
# put it in same folder as it was originally, no-op.
|
|
return
|
|
if item == self._treeCtrl.GetItemParent(self._draggingItem):
|
|
# put it in same folder as it was originally, no-op.
|
|
return
|
|
|
|
self.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self, item, self._draggingItem))
|
|
|
|
|
|
def WriteProjectConfig(self):
|
|
frame = self.GetFrame()
|
|
config = wx.ConfigBase_Get()
|
|
if frame and not self._embeddedWindow:
|
|
if not frame.IsMaximized():
|
|
config.WriteInt("ProjectFrameXLoc", frame.GetPositionTuple()[0])
|
|
config.WriteInt("ProjectFrameYLoc", frame.GetPositionTuple()[1])
|
|
config.WriteInt("ProjectFrameXSize", frame.GetSizeTuple()[0])
|
|
config.WriteInt("ProjectFrameYSize", frame.GetSizeTuple()[1])
|
|
config.WriteInt("ProjectFrameMaximized", frame.IsMaximized())
|
|
|
|
if config.ReadInt("ProjectSaveDocs", True):
|
|
projectFileNames = []
|
|
projectExpanded = []
|
|
if self._treeCtrl:
|
|
for projectItem in self._GetChildItems(self._treeCtrl.GetRootItem()):
|
|
project = self._GetItemProject(projectItem)
|
|
if not project.OnSaveModified():
|
|
return
|
|
if project.GetDocumentSaved(): # Might be a new document and "No" selected to save it
|
|
projectFileNames.append(str(project.GetFilename()))
|
|
projectExpanded.append(self._treeCtrl.IsExpanded(projectItem))
|
|
config.Write("ProjectSavedDocs", projectFileNames.__repr__())
|
|
config.Write("ProjectExpandedSavedDocs", projectExpanded.__repr__())
|
|
|
|
|
|
def OnClose(self, deleteWindow = True):
|
|
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
|
|
self.WriteProjectConfig()
|
|
project = self.GetDocument()
|
|
if not project:
|
|
return True
|
|
if not self.GetDocument().Close():
|
|
return True
|
|
self.Activate(False)
|
|
if project:
|
|
projectItem = self._GetProjectItem(project)
|
|
if projectItem:
|
|
self._treeCtrl.Delete(projectItem)
|
|
# We don't need to delete the window since it is a floater/embedded
|
|
return True
|
|
|
|
|
|
def _GetParentFrame(self):
|
|
return wx.GetTopLevelParent(self.GetFrame())
|
|
|
|
|
|
def OnUpdate(self, sender = None, hint = None):
|
|
wx.lib.docview.View.OnUpdate(self, sender, hint)
|
|
if hint:
|
|
if hint[0] == "add":
|
|
projectItem = self._GetProjectItem(hint[1])
|
|
files = hint[2]
|
|
self._treeCtrl.UnselectAll()
|
|
self._treeCtrl.Expand(projectItem)
|
|
item = None
|
|
for file in files:
|
|
item = self._treeCtrl.AppendItem(projectItem, os.path.basename(file))
|
|
self._treeCtrl.SetData(item, file)
|
|
self._treeCtrl.SelectItem(item)
|
|
self._treeCtrl.EnsureVisible(item)
|
|
self._treeCtrl.SortChildren(projectItem)
|
|
if item:
|
|
self._treeCtrl.EnsureVisible(item) # need to be called after SortChildren
|
|
elif hint[0] == "remove":
|
|
projectItem = self._GetProjectItem(hint[1])
|
|
files = hint[2]
|
|
self._treeCtrl.UnselectAll()
|
|
children = self._GetChildItems(projectItem)
|
|
for child in children:
|
|
if self._GetItemFile(child) in files:
|
|
self._treeCtrl.Delete(child)
|
|
elif hint[0] == "select":
|
|
projectItem = self._GetProjectItem(hint[1])
|
|
files = hint[2]
|
|
self._treeCtrl.UnselectAll()
|
|
children = self._GetChildItems(projectItem)
|
|
for child in children:
|
|
if self._GetItemFile(child) in files:
|
|
self._treeCtrl.SelectItem(child)
|
|
self._treeCtrl.EnsureVisible(child)
|
|
elif hint[0] == "rename":
|
|
projectItem = self._GetProjectItem(hint[1])
|
|
self._treeCtrl.SetItemText(projectItem, os.path.basename(hint[2]))
|
|
|
|
|
|
def ProcessEvent(self, event):
|
|
id = event.GetId()
|
|
if id == ProjectService.ADD_FILES_TO_PROJECT_ID:
|
|
self.OnAddFileToProject(event)
|
|
return True
|
|
elif id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID:
|
|
self.OnAddDirToProject(event)
|
|
return True
|
|
elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
|
|
return False # Implement this one in the service
|
|
elif id == ProjectService.RENAME_ID:
|
|
self.OnRename(event)
|
|
return True
|
|
elif id == ProjectService.DELETE_FILE_ID:
|
|
self.OnDeleteFile(event)
|
|
return True
|
|
elif id == wx.ID_CUT:
|
|
self.OnCut(event)
|
|
return True
|
|
elif id == wx.ID_COPY:
|
|
self.OnCopy(event)
|
|
return True
|
|
elif id == wx.ID_PASTE:
|
|
self.OnPaste(event)
|
|
return True
|
|
elif (id == wx.ID_CLEAR
|
|
or id == ProjectService.REMOVE_FROM_PROJECT):
|
|
self.OnClear(event)
|
|
return True
|
|
elif id == wx.ID_SELECTALL:
|
|
self.OnSelectAll(event)
|
|
return True
|
|
elif id == ProjectService.OPEN_SELECTION_ID:
|
|
self.OnOpenSelection(event)
|
|
return True
|
|
elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
|
|
self.OnProperties(event)
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def ProcessUpdateUIEvent(self, event):
|
|
# Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here
|
|
if self._checkEditMenu:
|
|
doc = self.GetDocument()
|
|
if doc and not doc.GetCommandProcessor().GetEditMenu():
|
|
doc.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame()))
|
|
self._checkEditMenu = False
|
|
|
|
id = event.GetId()
|
|
if (id == wx.ID_CUT
|
|
or id == wx.ID_COPY
|
|
or id == ProjectService.RENAME_ID
|
|
or id == ProjectService.ADD_FILES_TO_PROJECT_ID
|
|
or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID
|
|
or id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID):
|
|
event.Enable(self._HasSelection())
|
|
return True
|
|
elif id == ProjectService.DELETE_FILE_ID:
|
|
event.Enable(len(self.GetSelectedFiles()) > 0)
|
|
return True
|
|
elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
|
|
event.Enable(False)
|
|
return True
|
|
elif id == wx.ID_PASTE:
|
|
event.Enable(self.CanPaste())
|
|
return True
|
|
elif id == wx.ID_SELECTALL:
|
|
event.Enable(self._HasFiles())
|
|
return True
|
|
elif (id == wx.ID_CLEAR
|
|
or id == ProjectService.REMOVE_FROM_PROJECT
|
|
or id == ProjectService.OPEN_SELECTION_ID):
|
|
event.Enable(self._HasFilesSelected())
|
|
return True
|
|
elif (id == wx.ID_PREVIEW
|
|
or id == wx.ID_PRINT):
|
|
event.Enable(False)
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Display Methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def IsShown(self):
|
|
if not self.GetFrame():
|
|
return False
|
|
return self.GetFrame().IsShown()
|
|
|
|
|
|
def Hide(self):
|
|
self.Show(False)
|
|
|
|
|
|
def Show(self, show = True):
|
|
self.GetFrame().Show(show)
|
|
if wx.GetApp().IsMDI():
|
|
mdiParentFrame = wx.GetApp().GetTopWindow()
|
|
mdiParentFrame.ShowEmbeddedWindow(self.GetFrame(), show)
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Methods for ProjectDocument and ProjectService to call
|
|
#----------------------------------------------------------------------------
|
|
|
|
def SetExpandedProjects(self, expandedProjects):
|
|
self._treeCtrl.UnselectAll()
|
|
firstItem = None
|
|
for i, item in enumerate(self._GetChildItems(self._treeCtrl.GetRootItem())):
|
|
if i == 0:
|
|
firstItem = item
|
|
|
|
if expandedProjects[i]:
|
|
self._treeCtrl.Expand(item)
|
|
else:
|
|
self._treeCtrl.Collapse(item)
|
|
|
|
if firstItem:
|
|
self._treeCtrl.EnsureVisible(firstItem)
|
|
|
|
|
|
def GetSelectedFile(self):
|
|
for item in self._treeCtrl.GetSelections():
|
|
return self._GetItemFile(item)
|
|
|
|
|
|
def GetSelectedFiles(self):
|
|
filenames = []
|
|
for item in self._treeCtrl.GetSelections():
|
|
filename = self._GetItemFile(item)
|
|
if filename and filename not in filenames:
|
|
filenames.append(filename)
|
|
return filenames
|
|
|
|
|
|
def GetSelectedProjects(self):
|
|
filenames = []
|
|
for item in self._treeCtrl.GetSelections():
|
|
if self._IsItemProject(item):
|
|
filename = self._treeCtrl.GetLongFilename(item)
|
|
if filename and filename not in filenames:
|
|
filenames.append(filename)
|
|
return filenames
|
|
|
|
|
|
def AddProjectToView(self, document):
|
|
rootItem = self._treeCtrl.GetRootItem()
|
|
projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document))
|
|
self._treeCtrl.SetData(projectItem, document.GetFilename(), document)
|
|
for file in document.GetFiles():
|
|
fileItem = self._treeCtrl.AppendItem(projectItem, os.path.basename(file))
|
|
self._treeCtrl.SetData(fileItem, file)
|
|
self._treeCtrl.SortChildren(rootItem)
|
|
self._treeCtrl.SortChildren(projectItem)
|
|
self._treeCtrl.UnselectAll()
|
|
self._treeCtrl.Expand(projectItem)
|
|
self._treeCtrl.SelectItem(projectItem)
|
|
if self._embeddedWindow:
|
|
document.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame()))
|
|
|
|
|
|
def HasFocus(self):
|
|
winWithFocus = wx.Window.FindFocus()
|
|
if not winWithFocus:
|
|
return False
|
|
while winWithFocus:
|
|
if winWithFocus == self._treeCtrl:
|
|
return True
|
|
winWithFocus = winWithFocus.GetParent()
|
|
return False
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Control events
|
|
#----------------------------------------------------------------------------
|
|
|
|
def OnProperties(self, event):
|
|
items = self._treeCtrl.GetSelections()
|
|
if not items:
|
|
return
|
|
item = items[0]
|
|
if self._IsItemProject(item):
|
|
projectPropertiesDialog = ProjectPropertiesDialog(wx.GetApp().GetTopWindow(), self._GetItemProject(item).GetFilename())
|
|
if projectPropertiesDialog.ShowModal() == wx.ID_OK:
|
|
pass # Handle OK
|
|
projectPropertiesDialog.Destroy()
|
|
elif self._IsItemFile(item):
|
|
filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService)
|
|
filePropertiesService.ShowPropertiesDialog(self._GetItemFile(item))
|
|
|
|
|
|
def OnAddFileToProject(self, event):
|
|
if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__":
|
|
allfilter = ''
|
|
descr = ''
|
|
for temp in self.GetDocumentManager()._templates:
|
|
if temp.IsVisible():
|
|
if len(descr) > 0:
|
|
descr = descr + _('|')
|
|
allfilter = allfilter + _(';')
|
|
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
|
|
allfilter = allfilter + temp.GetFileFilter()
|
|
descr = _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter, allfilter, descr) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
|
|
else:
|
|
descr = _("*.*")
|
|
|
|
startDirectory = os.path.dirname(self.GetDocument().GetFilename())
|
|
|
|
if True or _WINDOWS:
|
|
dialog = wx.FileDialog(self.GetFrame(), _("Add Files"), startDirectory, "", descr, wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE)
|
|
if dialog.ShowModal() != wx.ID_OK:
|
|
return
|
|
paths = dialog.GetPaths()
|
|
dialog.Destroy()
|
|
else:
|
|
paths = wx.FileSelector(_("Add Files"), startDirectory, "", wildcard = descr, flags = wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE, parent=self.GetFrame())
|
|
if type(paths) == types.StringType:
|
|
paths = [paths]
|
|
if len(paths):
|
|
self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), paths))
|
|
self.Activate(True) # after add, should put focus on project editor
|
|
|
|
|
|
def OnAddDirToProject(self, event):
|
|
frame = wx.Dialog(None, -1, _("Add Directory Files to Project"), size= (320,200))
|
|
contentSizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
flexGridSizer = wx.FlexGridSizer(cols = 2, vgap=HALF_SPACE, hgap=HALF_SPACE)
|
|
flexGridSizer.Add(wx.StaticText(frame, -1, _("Directory:")), 0, wx.ALIGN_CENTER_VERTICAL, 0)
|
|
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
dirCtrl = wx.TextCtrl(frame, -1, os.path.dirname(self.GetDocument().GetFilename()), size=(250,-1))
|
|
dirCtrl.SetToolTipString(dirCtrl.GetValue())
|
|
lineSizer.Add(dirCtrl, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
|
|
findDirButton = wx.Button(frame, -1, _("Browse..."))
|
|
lineSizer.Add(findDirButton, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, HALF_SPACE)
|
|
flexGridSizer.Add(lineSizer, 1, wx.EXPAND)
|
|
|
|
def OnBrowseButton(event):
|
|
dlg = wx.DirDialog(frame, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE)
|
|
dir = dirCtrl.GetValue()
|
|
if len(dir):
|
|
dlg.SetPath(dir)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
dirCtrl.SetValue(dlg.GetPath())
|
|
dirCtrl.SetToolTipString(dirCtrl.GetValue())
|
|
dirCtrl.SetInsertionPointEnd()
|
|
|
|
dlg.Destroy()
|
|
wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton)
|
|
|
|
visibleTemplates = []
|
|
for template in self.GetDocumentManager()._templates:
|
|
if template.IsVisible():
|
|
visibleTemplates.append(template)
|
|
|
|
choices = []
|
|
allfilter = ''
|
|
descr = ''
|
|
for template in visibleTemplates:
|
|
if len(descr) > 0:
|
|
descr = descr + _('|')
|
|
allfilter = allfilter + _(';')
|
|
descr = template.GetDescription() + _(" (") + template.GetFileFilter() + _(")")
|
|
choices.append(descr)
|
|
allfilter = allfilter + template.GetFileFilter()
|
|
choices.insert(0, _("All (%s)") % allfilter) # first item
|
|
choices.append(_("Any (*.*)")) # last item
|
|
filterChoice = wx.Choice(frame, -1, size=(250, -1), choices=choices)
|
|
filterChoice.SetSelection(0)
|
|
filterChoice.SetToolTipString(_("Select file type filter."))
|
|
flexGridSizer.Add(wx.StaticText(frame, -1, _("Files of type:")), 0, wx.ALIGN_CENTER_VERTICAL)
|
|
flexGridSizer.Add(filterChoice, 1, wx.EXPAND)
|
|
|
|
contentSizer.Add(flexGridSizer, 0, wx.ALL|wx.EXPAND, SPACE)
|
|
|
|
subfolderCtrl = wx.CheckBox(frame, -1, _("Add files from subdirectories"))
|
|
subfolderCtrl.SetValue(True)
|
|
contentSizer.Add(subfolderCtrl, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, SPACE)
|
|
|
|
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
findBtn = wx.Button(frame, wx.ID_OK, _("Add"))
|
|
findBtn.SetDefault()
|
|
buttonSizer.Add(findBtn, 0, wx.RIGHT, HALF_SPACE)
|
|
buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0)
|
|
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
|
|
|
|
frame.SetSizer(contentSizer)
|
|
frame.Fit()
|
|
|
|
status = frame.ShowModal()
|
|
|
|
passedCheck = False
|
|
while status == wx.ID_OK and not passedCheck:
|
|
if not os.path.exists(dirCtrl.GetValue()):
|
|
dlg = wx.MessageDialog(frame,
|
|
_("'%s' does not exist.") % dirCtrl.GetValue(),
|
|
_("Find in Directory"),
|
|
wx.OK | wx.ICON_EXCLAMATION
|
|
)
|
|
dlg.ShowModal()
|
|
dlg.Destroy()
|
|
|
|
status = frame.ShowModal()
|
|
else:
|
|
passedCheck = True
|
|
|
|
if status == wx.ID_OK:
|
|
frame.Destroy()
|
|
|
|
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
|
|
|
doc = self.GetDocument()
|
|
searchSubfolders = subfolderCtrl.IsChecked()
|
|
dirString = dirCtrl.GetValue()
|
|
|
|
if os.path.isfile(dirString):
|
|
# If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter.
|
|
# We'll assume they know what they're doing.
|
|
paths = [dirString]
|
|
else:
|
|
paths = []
|
|
|
|
index = filterChoice.GetSelection()
|
|
lastIndex = filterChoice.GetCount()-1
|
|
if index and index != lastIndex: # if not All or Any
|
|
template = visibleTemplates[index-1]
|
|
|
|
# do search in files on disk
|
|
for root, dirs, files in os.walk(dirString):
|
|
if not searchSubfolders and root != dirString:
|
|
break
|
|
|
|
for name in files:
|
|
if index == 0: # All
|
|
for template in visibleTemplates:
|
|
if template.FileMatchesTemplate(name):
|
|
filename = os.path.join(root, name)
|
|
|
|
# if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
|
|
if doc.IsFileInProject(filename):
|
|
break
|
|
|
|
paths.append(filename)
|
|
break
|
|
elif index == lastIndex: # Any
|
|
filename = os.path.join(root, name)
|
|
# if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
|
|
if not doc.IsFileInProject(filename):
|
|
paths.append(filename)
|
|
else: # use selected filter
|
|
if template.FileMatchesTemplate(name):
|
|
filename = os.path.join(root, name)
|
|
# if already in project, don't add it, otherwise undo will remove it from project even though it was already in it.
|
|
if not doc.IsFileInProject(filename):
|
|
paths.append(filename)
|
|
|
|
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
|
|
|
|
doc.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc, paths))
|
|
self.Activate(True) # after add, should put focus on project editor
|
|
else:
|
|
frame.Destroy()
|
|
|
|
|
|
def DoAddFilesToProject(self, filenames):
|
|
# method used by Drag-n-Drop to add files to current Project
|
|
self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), filenames))
|
|
|
|
|
|
def DoSelectFiles(self, filenames):
|
|
# method used by Drag-n-Drop to select files in current Project
|
|
self._treeCtrl.UnselectAll()
|
|
for file in filenames:
|
|
item = self._GetFileItem(longFileName=file)
|
|
if item:
|
|
self._treeCtrl.SelectItem(item, True)
|
|
self._treeCtrl.EnsureVisible(item)
|
|
|
|
|
|
def DoSelectProject(self, x, y):
|
|
# method used by Drag-n-Drop to set current Project based on cursor position
|
|
item, flag = self._treeCtrl.HitTest((x,y))
|
|
if not item:
|
|
return False
|
|
|
|
project = self._GetItemProject(item)
|
|
if not project:
|
|
return False
|
|
|
|
projectItem = self._GetProjectItem(project)
|
|
self._treeCtrl.UnselectAll()
|
|
self._treeCtrl.SelectItem(projectItem)
|
|
return True
|
|
|
|
|
|
def OnFocus(self, event):
|
|
wx.GetApp().GetDocumentManager().ActivateView(self)
|
|
event.Skip()
|
|
|
|
|
|
def OnKillFocus(self, event):
|
|
# Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame
|
|
# wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame
|
|
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
|
|
childFrame = wx.GetApp().GetTopWindow().GetActiveChild()
|
|
if childFrame:
|
|
childFrame.Activate()
|
|
event.Skip()
|
|
|
|
|
|
def OnRightClick(self, event):
|
|
self.Activate(True)
|
|
if not self._treeCtrl.GetSelections():
|
|
return
|
|
if len(self._treeCtrl.GetSelections()) == 1 and self._IsItemRoot(self._treeCtrl.GetSelections()[0]):
|
|
return # Don't do a menu if it's just the root item selected
|
|
menu = wx.Menu()
|
|
if self._HasFilesSelected(): # Files context
|
|
menu.Append(ProjectService.OPEN_SELECTION_ID, _("&Open"), _("Opens the selection"))
|
|
menu.Enable(ProjectService.OPEN_SELECTION_ID, True)
|
|
wx.EVT_MENU(self._GetParentFrame(), ProjectService.OPEN_SELECTION_ID, self.OnOpenSelection)
|
|
itemIDs = [None]
|
|
for item in self._treeCtrl.GetSelections():
|
|
if self._IsItemProcessModelFile(item):
|
|
itemIDs = [None, ProjectService.RUN_SELECTED_PM_ID, None]
|
|
break
|
|
else: # Project context
|
|
itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None]
|
|
menuBar = self._GetParentFrame().GetMenuBar()
|
|
itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT]
|
|
svnIDs = [SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID]
|
|
if SVN_INSTALLED:
|
|
itemIDs = itemIDs + [None, SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID]
|
|
globalIDs = [wx.ID_UNDO, wx.ID_REDO, wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS]
|
|
itemIDs = itemIDs + [None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, ProjectService.RENAME_ID, ProjectService.DELETE_FILE_ID, None, wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID]
|
|
for itemID in itemIDs:
|
|
if not itemID:
|
|
menu.AppendSeparator()
|
|
else:
|
|
if itemID == ProjectService.RUN_SELECTED_PM_ID:
|
|
menu.Append(ProjectService.RUN_SELECTED_PM_ID, _("Run Process"))
|
|
wx.EVT_MENU(self._GetParentFrame(), ProjectService.RUN_SELECTED_PM_ID, self.OnRunSelectedPM)
|
|
elif itemID == ProjectService.REMOVE_FROM_PROJECT:
|
|
menu.Append(ProjectService.REMOVE_FROM_PROJECT, _("Remove Selected Files from Project"))
|
|
wx.EVT_MENU(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self.OnClear)
|
|
wx.EVT_UPDATE_UI(self._GetParentFrame(), ProjectService.REMOVE_FROM_PROJECT, self._GetParentFrame().ProcessUpdateUIEvent)
|
|
else:
|
|
svnService = wx.GetApp().GetService(SVNService.SVNService)
|
|
item = menuBar.FindItemById(itemID)
|
|
if item:
|
|
if itemID in svnIDs:
|
|
if SVN_INSTALLED and svnService:
|
|
wx.EVT_MENU(self._GetParentFrame(), itemID, svnService.ProcessEvent)
|
|
elif itemID in globalIDs:
|
|
pass
|
|
else:
|
|
wx.EVT_MENU(self._treeCtrl, itemID, self.ProcessEvent)
|
|
menu.Append(itemID, item.GetLabel())
|
|
self._treeCtrl.PopupMenu(menu, wx.Point(event.GetX(), event.GetY()))
|
|
menu.Destroy()
|
|
|
|
|
|
def OnRunSelectedPM(self, event):
|
|
projectService = wx.GetApp().GetService(ProjectService)
|
|
if projectService:
|
|
projectService.OnRunProcessModel(event, runSelected=True)
|
|
|
|
|
|
def OnRename(self, event):
|
|
if self._treeCtrl.GetSelections():
|
|
self._treeCtrl.EditLabel(self._treeCtrl.GetSelections()[0])
|
|
|
|
|
|
def OnBeginLabelEdit(self, event):
|
|
self._editingSoDontKillFocus = True
|
|
item = event.GetItem()
|
|
if not self._IsItemFile(item) and not self._IsItemProject(item):
|
|
event.Veto()
|
|
|
|
|
|
def OnEndLabelEdit(self, event):
|
|
self._editingSoDontKillFocus = False
|
|
item = event.GetItem()
|
|
newName = event.GetLabel()
|
|
if not newName or (not self._IsItemFile(item) and not self._IsItemProject(item)):
|
|
event.Veto()
|
|
return
|
|
if self._IsItemFile(item):
|
|
oldFile = self._GetItemFile(item)
|
|
newFile = os.path.join(os.path.split(oldFile)[0], newName)
|
|
project = self._GetItemProject(item)
|
|
if not project.GetCommandProcessor().Submit(ProjectRenameFileCommand(project, oldFile, newFile)):
|
|
event.Veto()
|
|
return
|
|
self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(self._treeCtrl.GetSelections()[0]))
|
|
elif self._IsItemProject(item):
|
|
oldFile = self._GetItemProject(item).GetFilename()
|
|
newFile = os.path.join(os.path.split(oldFile)[0], newName)
|
|
project = self._GetItemProject(item)
|
|
if not project.GetCommandProcessor().Submit(ProjectRenameFileCommand(project, oldFile, newFile, True)):
|
|
event.Veto()
|
|
return
|
|
self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem())
|
|
|
|
|
|
def CanPaste(self):
|
|
# wxBug: Should be able to use IsSupported/IsSupportedFormat here
|
|
#fileDataObject = wx.FileDataObject()
|
|
#hasFilesInClipboard = wx.TheClipboard.IsSupportedFormat(wx.FileDataObject)
|
|
if not wx.TheClipboard.IsOpened():
|
|
if wx.TheClipboard.Open():
|
|
fileDataObject = wx.FileDataObject()
|
|
hasFilesInClipboard = wx.TheClipboard.GetData(fileDataObject)
|
|
wx.TheClipboard.Close()
|
|
else:
|
|
hasFilesInClipboard = False
|
|
return hasFilesInClipboard
|
|
|
|
|
|
def OnCut(self, event):
|
|
self.OnCopy(event)
|
|
self.OnClear(event)
|
|
|
|
|
|
def OnCopy(self, event):
|
|
fileDataObject = wx.FileDataObject()
|
|
items = self._treeCtrl.GetSelections()
|
|
for item in items:
|
|
if self._IsItemFile(item):
|
|
file = self._treeCtrl.GetLongFilename(item)
|
|
fileDataObject.AddFile(file)
|
|
if len(fileDataObject.GetFilenames()) > 0 and wx.TheClipboard.Open():
|
|
wx.TheClipboard.SetData(fileDataObject)
|
|
wx.TheClipboard.Close()
|
|
|
|
|
|
def OnPaste(self, event):
|
|
if wx.TheClipboard.Open():
|
|
fileDataObject = wx.FileDataObject()
|
|
if wx.TheClipboard.GetData(fileDataObject):
|
|
self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), fileDataObject.GetFilenames()))
|
|
wx.TheClipboard.Close()
|
|
|
|
|
|
def OnClear(self, event):
|
|
items = self._treeCtrl.GetSelections()
|
|
files = []
|
|
for item in items:
|
|
if self._IsItemFile(item):
|
|
files.append((self._GetItemProject(item), self._GetItemFile(item)))
|
|
self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files))
|
|
|
|
|
|
def OnDeleteFile(self, event):
|
|
yesNoMsg = wx.MessageDialog(self.GetFrame(),
|
|
_("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"),
|
|
_("Delete File"),
|
|
wx.YES_NO|wx.ICON_QUESTION)
|
|
if yesNoMsg.ShowModal() == wx.ID_NO:
|
|
return
|
|
|
|
items = self._treeCtrl.GetSelections()
|
|
files = []
|
|
delFiles = []
|
|
for item in items:
|
|
if self._IsItemFile(item):
|
|
filename = self._GetItemFile(item)
|
|
files.append((self._GetItemProject(item), filename))
|
|
if filename not in delFiles:
|
|
delFiles.append(filename)
|
|
|
|
# remove selected files from projects
|
|
projects = []
|
|
for data in files:
|
|
proj, filename = data
|
|
if proj not in projects:
|
|
projects.append(proj)
|
|
for project in projects:
|
|
filenames = []
|
|
for data in files:
|
|
proj, filename = data
|
|
if project == proj:
|
|
filenames.append(filename)
|
|
project.RemoveFiles(filenames)
|
|
|
|
# remove selected files from file system
|
|
for filename in delFiles:
|
|
if os.path.exists(filename):
|
|
try:
|
|
os.remove(filename)
|
|
except:
|
|
wx.MessageBox("Could not delete '%s'. %s" % (os.path.basename(filename), sys.exc_value),
|
|
_("Delete File"),
|
|
wx.OK | wx.ICON_EXCLAMATION)
|
|
|
|
|
|
def OnKeyPressed(self, event):
|
|
key = event.KeyCode()
|
|
if key == wx.WXK_DELETE:
|
|
self.OnClear(event)
|
|
else:
|
|
event.Skip()
|
|
|
|
|
|
def OnSelectAll(self, event):
|
|
project = self.GetDocument()
|
|
if project:
|
|
self._treeCtrl.UnselectAll()
|
|
for child in self._GetChildItems(self._GetProjectItem(project)):
|
|
self._treeCtrl.SelectItem(child)
|
|
|
|
|
|
def OnOpenSelectionSDI(self, event):
|
|
# Do a call after so that the second mouseclick on a doubleclick doesn't reselect the project window
|
|
wx.CallAfter(self.OnOpenSelection, None)
|
|
|
|
|
|
def OnOpenSelection(self, event):
|
|
doc = None
|
|
try:
|
|
items = self._treeCtrl.GetSelections()
|
|
for item in items:
|
|
if self._IsItemFile(item):
|
|
filepath = self._GetItemFile(item)
|
|
if not os.path.exists(filepath):
|
|
msgTitle = wx.GetApp().GetAppName()
|
|
if not msgTitle:
|
|
msgTitle = _("File Not Found")
|
|
yesNoMsg = wx.MessageDialog(self.GetFrame(),
|
|
_("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)),
|
|
msgTitle,
|
|
wx.YES_NO|wx.ICON_QUESTION
|
|
)
|
|
if yesNoMsg.ShowModal() == wx.ID_NO:
|
|
continue
|
|
findFile = wx.FileDialog(self.GetFrame(),
|
|
_("Choose a file"),
|
|
wx.lib.docview.PathOnly(filepath),
|
|
wx.lib.docview.FileNameFromPath(filepath),
|
|
style = wx.OPEN
|
|
)
|
|
if findFile.ShowModal() == wx.ID_OK and findFile.GetPath():
|
|
newpath = findFile.GetPath()
|
|
else:
|
|
newpath = None
|
|
findFile.Destroy()
|
|
if newpath:
|
|
# update Project Model with new location
|
|
project = self._GetItemProject(item)
|
|
project.RemoveFile(filepath)
|
|
project.AddFile(newpath)
|
|
filepath = newpath
|
|
|
|
doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT)
|
|
if not doc:
|
|
shortFilename = self._treeCtrl.GetItemText(item)
|
|
if shortFilename.endswith(".agp"):
|
|
projItem = self._GetProjectItem(shortFilename=shortFilename)
|
|
self._treeCtrl.UnselectAll()
|
|
if not self._treeCtrl.IsExpanded(projItem):
|
|
self._treeCtrl.Expand(projItem)
|
|
if not self._treeCtrl.IsVisible(projItem):
|
|
self._treeCtrl.EnsureVisible(projItem)
|
|
if not self._treeCtrl.IsSelected(projItem):
|
|
self._treeCtrl.SelectItem(projItem)
|
|
|
|
except IOError, (code, message):
|
|
msgTitle = wx.GetApp().GetAppName()
|
|
if not msgTitle:
|
|
msgTitle = _("File Error")
|
|
wx.MessageBox("Could not open '%s'." % wx.lib.docview.FileNameFromPath(filepath),
|
|
msgTitle,
|
|
wx.OK | wx.ICON_EXCLAMATION,
|
|
self.GetFrame())
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Convenience methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def _HasFiles(self):
|
|
if not self._treeCtrl:
|
|
return False
|
|
return self._treeCtrl.GetCount() > 1 # 1 item = root item, don't count as having files
|
|
|
|
|
|
def _HasSelection(self):
|
|
if not self._treeCtrl:
|
|
return False
|
|
|
|
items = self._treeCtrl.GetSelections()
|
|
if items:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def _HasFilesSelected(self):
|
|
if not self._treeCtrl:
|
|
return False
|
|
items = self._treeCtrl.GetSelections()
|
|
if not items:
|
|
return False
|
|
for item in items:
|
|
if not self._IsItemFile(item):
|
|
return False
|
|
return True
|
|
|
|
|
|
def _MakeProjectName(self, project):
|
|
return project.GetPrintableName()
|
|
|
|
|
|
# Return the tree item for a project
|
|
def _GetProjectItem(self, project=None, shortFilename=None):
|
|
rootItem = self._treeCtrl.GetRootItem()
|
|
(child, cookie) = self._treeCtrl.GetFirstChild(rootItem)
|
|
while child.IsOk():
|
|
if project:
|
|
if self._treeCtrl.GetProjectDoc(child) == project:
|
|
return child
|
|
elif shortFilename:
|
|
if self._treeCtrl.GetItemText(child) == shortFilename:
|
|
return child
|
|
(child, cookie) = self._treeCtrl.GetNextChild(rootItem, cookie)
|
|
return None
|
|
|
|
|
|
# Returns the project for an item, either for a project item or a file that is part of a project
|
|
def _GetItemProject(self, item):
|
|
if self._IsItemRoot(item):
|
|
return None
|
|
if self._IsItemProject(item):
|
|
return self._treeCtrl.GetProjectDoc(item)
|
|
if self._IsItemFile(item):
|
|
return self._treeCtrl.GetProjectDoc(self._treeCtrl.GetItemParent(item))
|
|
return None
|
|
|
|
|
|
def _GetItemFile(self, item):
|
|
if self._IsItemFile(item):
|
|
return self._treeCtrl.GetLongFilename(item)
|
|
else:
|
|
return None
|
|
|
|
|
|
def _GetFileItem(self, shortFileName = None, longFileName = None):
|
|
""" Returns the tree item for a file given the short (display) or long (fullpath) file name. """
|
|
|
|
rootItem = self._treeCtrl.GetRootItem()
|
|
(project, cookie) = self._treeCtrl.GetFirstChild(rootItem)
|
|
while project.IsOk():
|
|
(child, cookie2) = self._treeCtrl.GetFirstChild(project)
|
|
while child.IsOk():
|
|
if shortFileName:
|
|
if self._treeCtrl.GetItemText(child) == shortFileName:
|
|
return child
|
|
else:
|
|
if self._treeCtrl.GetLongFilename(child) == longFileName:
|
|
return child
|
|
(child, cookie2) = self._treeCtrl.GetNextChild(project, cookie2)
|
|
(project, cookie) = self._treeCtrl.GetNextChild(rootItem, cookie)
|
|
return None
|
|
|
|
|
|
def _IsItemRoot(self, item):
|
|
return item == self._treeCtrl.GetRootItem()
|
|
|
|
|
|
def _IsItemProject(self, item):
|
|
return self._treeCtrl.GetProjectDoc(item) != None
|
|
|
|
|
|
def _IsItemFile(self, item):
|
|
return self._treeCtrl.GetProjectDoc(item) == None
|
|
|
|
|
|
def _IsItemProcessModelFile(self, item):
|
|
if ACTIVEGRID_BASE_IDE:
|
|
return False
|
|
|
|
if self._IsItemFile(item):
|
|
filename = self._treeCtrl.GetLongFilename(item)
|
|
ext = None
|
|
for template in self.GetDocumentManager().GetTemplates():
|
|
if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
|
|
ext = template.GetDefaultExtension()
|
|
break;
|
|
if not ext:
|
|
return False
|
|
|
|
if filename.endswith(ext):
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def _GetChildItems(self, parentItem):
|
|
children = []
|
|
(child, cookie) = self._treeCtrl.GetFirstChild(parentItem)
|
|
while child.IsOk():
|
|
children.append(child)
|
|
(child, cookie) = self._treeCtrl.GetNextChild(parentItem, cookie)
|
|
return children
|
|
|
|
|
|
|
|
class ProjectFileDropTarget(wx.FileDropTarget):
|
|
|
|
def __init__(self, view):
|
|
wx.FileDropTarget.__init__(self)
|
|
self._view = view
|
|
|
|
|
|
def OnDropFiles(self, x, y, filenames):
|
|
if self._view.DoSelectProject(x, y):
|
|
self._view.DoAddFilesToProject(filenames)
|
|
self._view.DoSelectFiles(filenames)
|
|
return True
|
|
return False
|
|
|
|
|
|
def OnDragOver(self, x, y, default):
|
|
if self._view.DoSelectProject(x,y):
|
|
return wx.DragCopy
|
|
return wx.DragNone
|
|
|
|
|
|
class ProjectPropertiesDialog(wx.Dialog):
|
|
|
|
|
|
def __init__(self, parent, filename):
|
|
wx.Dialog.__init__(self, parent, -1, _("Project Properties"), size = (310, 330))
|
|
|
|
filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService)
|
|
|
|
notebook = wx.Notebook(self, -1)
|
|
tab = wx.Panel(notebook, -1)
|
|
|
|
gridSizer = RowColSizer()
|
|
|
|
gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0)
|
|
if os.path.isfile(filename):
|
|
gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1]), row=0, col=1)
|
|
|
|
gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0)
|
|
gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.split(filename)[0])), flag=wx.BOTTOM, border=SPACE, row=1, col=1)
|
|
|
|
gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0)
|
|
gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1)
|
|
|
|
lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion
|
|
lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND)
|
|
gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2)
|
|
|
|
gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0)
|
|
gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1)
|
|
|
|
gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0)
|
|
gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1)
|
|
|
|
gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0)
|
|
gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1)
|
|
|
|
else:
|
|
gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1] + ' ' + _("[new project]")), row=0, col=1)
|
|
|
|
# add a border around the inside of the tab
|
|
spacerGrid = wx.BoxSizer(wx.VERTICAL)
|
|
spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE);
|
|
tab.SetSizer(spacerGrid)
|
|
notebook.AddPage(tab, _("General"))
|
|
if wx.Platform == "__WXMSW__":
|
|
notebook.SetPageSize((310,200))
|
|
|
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
|
|
sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
|
|
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
self.Layout()
|
|
|
|
|
|
class ProjectOptionsPanel(wx.Panel):
|
|
|
|
|
|
def __init__(self, parent, id):
|
|
wx.Panel.__init__(self, parent, id)
|
|
self._useSashMessageShown = False
|
|
config = wx.ConfigBase_Get()
|
|
self._projSaveDocsCheckBox = wx.CheckBox(self, -1, _("Remember open projects"))
|
|
self._projSaveDocsCheckBox.SetValue(config.ReadInt("ProjectSaveDocs", True))
|
|
projectBorderSizer = wx.BoxSizer(wx.VERTICAL)
|
|
projectSizer = wx.BoxSizer(wx.VERTICAL)
|
|
projectSizer.Add(self._projSaveDocsCheckBox, 0, wx.ALL, HALF_SPACE)
|
|
if not ACTIVEGRID_BASE_IDE:
|
|
self._projShowWelcomeCheckBox = wx.CheckBox(self, -1, _("Show Welcome Dialog"))
|
|
self._projShowWelcomeCheckBox.SetValue(config.ReadInt("RunWelcomeDialog", True))
|
|
projectSizer.Add(self._projShowWelcomeCheckBox, 0, wx.ALL, HALF_SPACE)
|
|
projectBorderSizer.Add(projectSizer, 0, wx.ALL, SPACE)
|
|
self.SetSizer(projectBorderSizer)
|
|
self.Layout()
|
|
parent.AddPage(self, _("Project"))
|
|
|
|
def OnUseSashSelect(self, event):
|
|
if not self._useSashMessageShown:
|
|
msgTitle = wx.GetApp().GetAppName()
|
|
if not msgTitle:
|
|
msgTitle = _("Document Options")
|
|
wx.MessageBox("Project window embedded mode changes will not appear until the application is restarted.",
|
|
msgTitle,
|
|
wx.OK | wx.ICON_INFORMATION,
|
|
self.GetParent())
|
|
self._useSashMessageShown = True
|
|
|
|
|
|
def OnOK(self, optionsDialog):
|
|
config = wx.ConfigBase_Get()
|
|
config.WriteInt("ProjectSaveDocs", self._projSaveDocsCheckBox.GetValue())
|
|
if not ACTIVEGRID_BASE_IDE:
|
|
config.WriteInt("RunWelcomeDialog", self._projShowWelcomeCheckBox.GetValue())
|
|
|
|
|
|
class ProjectService(Service.Service):
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Constants
|
|
#----------------------------------------------------------------------------
|
|
SHOW_WINDOW = wx.NewId() # keep this line for each subclass, need unique ID for each Service
|
|
RUNPM_ID = wx.NewId()
|
|
RUN_SELECTED_PM_ID = wx.NewId()
|
|
RUN_CURRENT_PM_ID = wx.NewId()
|
|
ADD_FILES_TO_PROJECT_ID = wx.NewId()
|
|
ADD_CURRENT_FILE_TO_PROJECT_ID = wx.NewId()
|
|
RENAME_ID = wx.NewId()
|
|
OPEN_SELECTION_ID = wx.NewId()
|
|
REMOVE_FROM_PROJECT = wx.NewId()
|
|
DELETE_FILE_ID = wx.NewId()
|
|
ADD_ALL_FILES_TO_PROJECT_ID = wx.NewId()
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Overridden methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT):
|
|
Service.Service.__init__(self, serviceName, embeddedWindowLocation)
|
|
self._runHandlers = []
|
|
self._suppressOpenProjectMessages = False
|
|
|
|
|
|
def _CreateView(self):
|
|
return ProjectView(self)
|
|
|
|
|
|
def ShowWindow(self, show = True):
|
|
""" Force showing of saved projects on opening, otherwise empty Project Window is disconcerting for user """
|
|
Service.Service.ShowWindow(self, show)
|
|
|
|
if show:
|
|
project = self.GetView().GetDocument()
|
|
if not project:
|
|
self.OpenSavedProjects()
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Service specific methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def GetSuppressOpenProjectMessages(self):
|
|
return self._suppressOpenProjectMessages
|
|
|
|
|
|
def SetSuppressOpenProjectMessages(self, suppressOpenProjectMessages):
|
|
self._suppressOpenProjectMessages = suppressOpenProjectMessages
|
|
|
|
|
|
def GetRunHandlers(self):
|
|
return self._runHandlers
|
|
|
|
|
|
def AddRunHandler(self, runHandler):
|
|
self._runHandlers.append(runHandler)
|
|
|
|
|
|
def RemoveRunHandler(self, runHandler):
|
|
self._runHandlers.remove(runHandler)
|
|
|
|
|
|
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
|
|
Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
|
|
|
|
projectMenu = wx.Menu()
|
|
|
|
## accelTable = wx.AcceleratorTable([
|
|
## eval(_("wx.ACCEL_CTRL, ord('R'), ProjectService.RUN_ID"))
|
|
## ])
|
|
## frame.SetAcceleratorTable(accelTable)
|
|
isProjectDocument = document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument
|
|
if wx.GetApp().IsMDI() or isProjectDocument:
|
|
if not menuBar.FindItemById(ProjectService.ADD_FILES_TO_PROJECT_ID):
|
|
projectMenu.Append(ProjectService.ADD_FILES_TO_PROJECT_ID, _("Add &Files to Project..."), _("Adds a document to the current project"))
|
|
wx.EVT_MENU(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessEvent)
|
|
wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
|
|
if not menuBar.FindItemById(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID):
|
|
projectMenu.Append(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project"))
|
|
wx.EVT_MENU(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessEvent)
|
|
wx.EVT_UPDATE_UI(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
|
|
if not menuBar.FindItemById(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID):
|
|
projectMenu.Append(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, _("&Add Active File to Project..."), _("Adds the active document to a project"))
|
|
wx.EVT_MENU(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessEvent)
|
|
wx.EVT_UPDATE_UI(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessUpdateUIEvent)
|
|
viewMenuIndex = menuBar.FindMenu(_("&View"))
|
|
menuBar.Insert(viewMenuIndex + 1, projectMenu, _("&Project"))
|
|
editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit")))
|
|
if not menuBar.FindItemById(ProjectService.RENAME_ID):
|
|
editMenu.Append(ProjectService.RENAME_ID, _("&Rename"), _("Renames the active item"))
|
|
wx.EVT_MENU(frame, ProjectService.RENAME_ID, frame.ProcessEvent)
|
|
wx.EVT_UPDATE_UI(frame, ProjectService.RENAME_ID, frame.ProcessUpdateUIEvent)
|
|
if not menuBar.FindItemById(ProjectService.DELETE_FILE_ID):
|
|
editMenu.Append(ProjectService.DELETE_FILE_ID, _("Delete File"), _("Delete the file from the project and file system."))
|
|
wx.EVT_MENU(frame, ProjectService.DELETE_FILE_ID, frame.ProcessEvent)
|
|
wx.EVT_UPDATE_UI(frame, ProjectService.DELETE_FILE_ID, frame.ProcessUpdateUIEvent)
|
|
|
|
return True
|
|
|
|
|
|
def OnCloseFrame(self, event):
|
|
if not self.GetView():
|
|
return True
|
|
|
|
if wx.GetApp().IsMDI():
|
|
# close all non-project documents first
|
|
for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
|
|
if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:
|
|
if not self.GetDocumentManager().CloseDocument(document, False):
|
|
return False
|
|
|
|
# write project config afterwards because user may change filenames on closing of new documents
|
|
self.GetView().WriteProjectConfig() # Called onCloseWindow in all of the other services but needed to be factored out for ProjectService since it is called elsewhere
|
|
|
|
# close all project documents after closing other documents
|
|
# because user may save a new document with a new name or cancel closing a document
|
|
for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
|
|
if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
if not document.OnSaveModified():
|
|
return False
|
|
|
|
# This is called when any SDI frame is closed, so need to check if message window is closing or some other window
|
|
elif self.GetView() == event.GetEventObject().GetView():
|
|
self.SetView(None)
|
|
return True
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Event Processing Methods
|
|
#----------------------------------------------------------------------------
|
|
|
|
def ProcessEventBeforeWindows(self, event):
|
|
id = event.GetId()
|
|
|
|
if id == wx.ID_CLOSE_ALL:
|
|
self.OnFileCloseAll(event)
|
|
return True
|
|
|
|
elif id == wx.ID_CLOSE:
|
|
document = self.GetDocumentManager().GetCurrentDocument()
|
|
if document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
self.OnProjectClose(event)
|
|
return True
|
|
else:
|
|
return False
|
|
return False
|
|
|
|
|
|
def ProcessUpdateUIEventBeforeWindows(self, event):
|
|
id = event.GetId()
|
|
|
|
if id == wx.ID_CLOSE_ALL:
|
|
for document in self.GetDocumentManager().GetDocuments():
|
|
if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:
|
|
event.Enable(True)
|
|
return True
|
|
|
|
event.Enable(False)
|
|
return True
|
|
|
|
elif id == wx.ID_CLOSE:
|
|
document = self.GetDocumentManager().GetCurrentDocument()
|
|
if document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
projectFilenames = self.GetView().GetSelectedProjects()
|
|
if projectFilenames and len(projectFilenames):
|
|
event.Enable(True)
|
|
else:
|
|
event.Enable(False)
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def ProcessEvent(self, event):
|
|
if Service.Service.ProcessEvent(self, event):
|
|
return True
|
|
|
|
id = event.GetId()
|
|
if id == ProjectService.RUN_SELECTED_PM_ID:
|
|
self.OnRunProcessModel(event, runSelected=True)
|
|
return True
|
|
elif id == ProjectService.RUN_CURRENT_PM_ID:
|
|
self.OnRunProcessModel(event, runCurrentFile=True)
|
|
return True
|
|
elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
|
|
self.OnAddCurrentFileToProject(event)
|
|
return True
|
|
elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
|
|
if self.GetView():
|
|
return self.GetView().ProcessEvent(event)
|
|
else:
|
|
return False
|
|
else:
|
|
return False
|
|
|
|
|
|
def ProcessUpdateUIEvent(self, event):
|
|
if Service.Service.ProcessUpdateUIEvent(self, event):
|
|
return True
|
|
|
|
id = event.GetId()
|
|
if (id == ProjectService.RUNPM_ID
|
|
or id == ProjectService.RUN_SELECTED_PM_ID
|
|
or id == ProjectService.RUN_CURRENT_PM_ID):
|
|
event.Enable(self._HasOpenedProjects() and self._HasProcessModel())
|
|
return True
|
|
elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID:
|
|
event.Enable(self._CanAddCurrentFileToProject())
|
|
return True
|
|
elif (id == ProjectService.ADD_FILES_TO_PROJECT_ID
|
|
or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID
|
|
or id == ProjectService.RENAME_ID
|
|
or id == ProjectService.OPEN_SELECTION_ID
|
|
or id == ProjectService.DELETE_FILE_ID):
|
|
event.Enable(False)
|
|
return True
|
|
elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID:
|
|
if self.GetView():
|
|
return self.GetView().ProcessUpdateUIEvent(event)
|
|
else:
|
|
return False
|
|
else:
|
|
return False
|
|
|
|
|
|
def OnRunProcessModel(self, event, runSelected=False, runCurrentFile=False):
|
|
project = self.GetView().GetDocument()
|
|
|
|
if project:
|
|
ext = None
|
|
for template in self.GetDocumentManager().GetTemplates():
|
|
if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
|
|
ext = template.GetDefaultExtension()
|
|
break;
|
|
if not ext:
|
|
return
|
|
|
|
files = filter(lambda f: f.endswith(ext), project.GetFiles())
|
|
if not files:
|
|
return
|
|
|
|
docs = wx.GetApp().GetDocumentManager().GetDocuments()
|
|
for doc in docs:
|
|
if doc.GetFilename() in files and doc.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
|
|
if not doc.GetProcessModel().beginProcess:
|
|
wx.MessageBox(_("Cannot run process. No begin action found."), _("Run Process"))
|
|
return
|
|
|
|
filesModified = False
|
|
for doc in docs:
|
|
if doc.IsModified():
|
|
filesModified = True
|
|
break
|
|
if filesModified:
|
|
frame = self.GetView().GetFrame()
|
|
yesNoMsg = wx.MessageDialog(frame,
|
|
_("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"),
|
|
_("Run Process"),
|
|
wx.YES_NO|wx.ICON_QUESTION
|
|
)
|
|
if yesNoMsg.ShowModal() == wx.ID_YES:
|
|
wx.GetTopLevelParent(frame).OnFileSaveAll(None)
|
|
|
|
if runCurrentFile:
|
|
fileToRun = self.GetDocumentManager().GetCurrentDocument().GetFilename()
|
|
elif runSelected:
|
|
fileToRun = self.GetView().GetSelectedFile()
|
|
elif len(files) > 1:
|
|
files.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower()))
|
|
strings = map(lambda file: os.path.basename(file), files)
|
|
res = wx.GetSingleChoiceIndex(_("Select a process to run:"),
|
|
_("Run"),
|
|
strings,
|
|
project.GetFirstView()._GetParentFrame())
|
|
if res == -1:
|
|
return
|
|
fileToRun = files[res]
|
|
else:
|
|
fileToRun = files[0]
|
|
|
|
self.RunProcessModel(fileToRun)
|
|
|
|
|
|
def RunProcessModel(self, fileToRun):
|
|
for runHandler in self.GetRunHandlers():
|
|
if runHandler.RunProjectFile(fileToRun):
|
|
return
|
|
os.system('"' + fileToRun + '"')
|
|
|
|
|
|
def _HasProcessModel(self):
|
|
project = self.GetView().GetDocument()
|
|
|
|
if project:
|
|
ext = None
|
|
for template in self.GetDocumentManager().GetTemplates():
|
|
if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
|
|
ext = template.GetDefaultExtension()
|
|
break;
|
|
if not ext:
|
|
return False
|
|
|
|
files = filter(lambda f: f.endswith(ext), project.GetFiles())
|
|
if not files:
|
|
return False
|
|
|
|
if len(files):
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def _HasOpenedProjects(self):
|
|
for document in self.GetDocumentManager().GetDocuments():
|
|
if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
return True
|
|
return False
|
|
|
|
|
|
def _HasCurrentFile(self):
|
|
currentDoc = self.GetDocumentManager().GetCurrentDocument()
|
|
return currentDoc
|
|
|
|
|
|
def _CanAddCurrentFileToProject(self):
|
|
currentDoc = self.GetDocumentManager().GetCurrentDocument()
|
|
if not currentDoc:
|
|
return False
|
|
if currentDoc.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
return False
|
|
if not currentDoc._savedYet:
|
|
return False
|
|
for document in self.GetDocumentManager().GetDocuments():
|
|
if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
return True
|
|
return False # There are no documents open
|
|
|
|
|
|
def GetFilesFromCurrentProject(self):
|
|
view = self.GetView()
|
|
if view:
|
|
project = view.GetDocument()
|
|
if project:
|
|
return project.GetFiles()
|
|
return None
|
|
|
|
|
|
def GetCurrentProject(self):
|
|
view = self.GetView()
|
|
if view:
|
|
return view.GetDocument()
|
|
return None
|
|
|
|
|
|
def FindProjectByFile(self, filename):
|
|
for document in self.GetDocumentManager().GetDocuments():
|
|
if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
if document.GetFilename() == filename:
|
|
return document
|
|
elif document.IsFileInProject(filename):
|
|
return document
|
|
return None
|
|
|
|
|
|
def GetCurrentProjectNames(self):
|
|
projects = []
|
|
for document in self.GetDocumentManager().GetDocuments():
|
|
if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
projects.append(document)
|
|
if not projects:
|
|
return
|
|
projects.sort(lambda a, b: cmp(a.GetPrintableName().lower(), b.GetPrintableName().lower()))
|
|
strings = map(lambda project: project.GetPrintableName(), projects)
|
|
return strings
|
|
|
|
|
|
def OnAddCurrentFileToProject(self, event):
|
|
if not self._CanAddCurrentFileToProject():
|
|
return
|
|
projects = []
|
|
for document in self.GetDocumentManager().GetDocuments():
|
|
if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument:
|
|
projects.append(document)
|
|
if not projects:
|
|
return
|
|
projects.sort(lambda a, b: cmp(a.GetPrintableName().lower(), b.GetPrintableName().lower()))
|
|
strings = map(lambda project: project.GetPrintableName(), projects)
|
|
res = wx.GetSingleChoiceIndex(_("Select a project to add the file to:"),
|
|
_("Add to Project"),
|
|
strings,
|
|
self.GetDocumentManager().FindSuitableParent())
|
|
if res == -1:
|
|
return
|
|
file = self.GetDocumentManager().GetCurrentDocument().GetFilename()
|
|
projects[res].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects[res], [file]))
|
|
self.GetView().Activate(True) # after add, should put focus on project editor
|
|
|
|
|
|
def OnProjectClose(self, event):
|
|
projectFilenames = self.GetView().GetSelectedProjects()
|
|
for filename in projectFilenames:
|
|
doc = self.FindProjectByFile(filename)
|
|
if doc:
|
|
self.GetDocumentManager().CloseDocument(doc, False)
|
|
|
|
|
|
def OnFileCloseAll(self, event):
|
|
for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
|
|
if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument:
|
|
if not self.GetDocumentManager().CloseDocument(document, False):
|
|
return
|
|
# document.DeleteAllViews() # Implicitly delete the document when the last view is removed
|
|
|
|
|
|
def OpenSavedProjects(self):
|
|
config = wx.ConfigBase_Get()
|
|
openedDocs = False
|
|
if config.ReadInt("ProjectSaveDocs", True):
|
|
docString = config.Read("ProjectSavedDocs")
|
|
if docString:
|
|
doc = None
|
|
for fileName in eval(docString):
|
|
if isinstance(fileName, types.StringTypes):
|
|
if os.path.exists(fileName):
|
|
doc = self.GetDocumentManager().CreateDocument(fileName, wx.lib.docview.DOC_SILENT)
|
|
|
|
if doc:
|
|
openedDocs = True
|
|
expandedString = config.Read("ProjectExpandedSavedDocs")
|
|
if expandedString:
|
|
view = doc.GetFirstView()
|
|
view.SetExpandedProjects(eval(expandedString))
|
|
return openedDocs
|
|
|
|
|
|
class ProjectEditorMoveCommand(wx.lib.docview.Command):
|
|
|
|
def __init__(self, view, newPositionItem, item):
|
|
wx.lib.docview.Command.__init__(self, canUndo = True)
|
|
self._view = view
|
|
self._item = item
|
|
self._file = view._treeCtrl.GetLongFilename(item)
|
|
if view._IsItemFile(item):
|
|
self._projectOld = view._GetItemProject(item)
|
|
else: # view._IsItemProject(item):
|
|
self._projectOld = None
|
|
self._projectNew = view._GetItemProject(newPositionItem)
|
|
|
|
|
|
def GetName(self):
|
|
return _("Move File %s") % os.path.basename(self._file)
|
|
|
|
|
|
def Do(self):
|
|
if self._projectOld:
|
|
self._projectOld.RemoveFile(self._file)
|
|
if self._projectNew:
|
|
self._projectNew.AddFile(self._file)
|
|
return True
|
|
|
|
|
|
def Undo(self):
|
|
if self._projectNew:
|
|
self._projectNew.RemoveFile(self._file)
|
|
if self._projectOld:
|
|
self._projectOld.AddFile(self._file)
|
|
return True
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Icon Bitmaps - generated by encode_bitmaps.py
|
|
#----------------------------------------------------------------------------
|
|
from wx import ImageFromStream, BitmapFromImage
|
|
import cStringIO
|
|
|
|
|
|
def getProjectData():
|
|
return \
|
|
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
|
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
|
\x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\
|
|
\x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\
|
|
YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\
|
|
\xc0gn\xdc\x8d\x07\xab"<iG\x8e\xa9\r\x00\x00\x00\x00IEND\xaeB`\x82'
|
|
|
|
def getProjectBitmap():
|
|
return BitmapFromImage(getProjectImage())
|
|
|
|
def getProjectImage():
|
|
stream = cStringIO.StringIO(getProjectData())
|
|
return ImageFromStream(stream)
|
|
|
|
def getProjectIcon():
|
|
return wx.IconFromBitmap(getProjectBitmap())
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
def getBlankData():
|
|
return \
|
|
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
|
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
|
\x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
|
|
\xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
|
|
9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
|
|
\x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
|
|
\x00\x00IEND\xaeB`\x82'
|
|
|
|
|
|
def getBlankBitmap():
|
|
return BitmapFromImage(getBlankImage())
|
|
|
|
def getBlankImage():
|
|
stream = cStringIO.StringIO(getBlankData())
|
|
return ImageFromStream(stream)
|
|
|
|
def getBlankIcon():
|
|
return wx.IconFromBitmap(getBlankBitmap())
|
|
|