1 #!/usr/bin/env python
   2 
   3 """
   4 This sample comes from an IBM developerWorks article at
   5 http://www-106.ibm.com/developerworks/library/l-wxpy/index.html
   6 
   7 This small program was adapted to demonstrate the current guide lines
   8 on http://wiki.wxpython.org/index.cgi/wxPython_20Style_20Guide.
   9 Changes are noted in readme.txt.
  10 """
  11 
  12 import sys, os
  13 import wx
  14 
  15 
  16 # Process the command line.  Not much to do;
  17 # just get the name of the project file if it's given. Simple.
  18 projfile = 'Unnamed'
  19 if len(sys.argv) > 1:
  20     projfile = sys.argv[1]
  21 
  22 
  23 def MsgDlg(window, string, caption='wxProject', style=wx.YES_NO|wx.CANCEL):
  24     """Common MessageDialog."""
  25     dlg = wx.MessageDialog(window, string, caption, style)
  26     result = dlg.ShowModal()
  27     dlg.Destroy()
  28     return result
  29 
  30 
  31 class main_window(wx.Frame):
  32     """wxProject MainFrame."""
  33     def __init__(self, parent, title):
  34         """Create the wxProject MainFrame."""
  35         wx.Frame.__init__(self, parent, title=title, size=(500, 500),
  36                           style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
  37 
  38 
  39         # Set up menu bar for the program.
  40         self.mainmenu = wx.MenuBar()                  # Create menu bar.
  41 
  42         # Make the 'Project' menu.
  43         menu = wx.Menu()
  44 
  45         item = menu.Append(wx.ID_OPEN, '&Open', 'Open project')  # Append a new menu
  46         self.Bind(wx.EVT_MENU, self.OnProjectOpen, item)  # Create and assign a menu event.
  47 
  48         item = menu.Append(wx.ID_NEW, '&New', 'New project')
  49         self.Bind(wx.EVT_MENU, self.OnProjectNew, item)
  50 
  51         item = menu.Append(wx.ID_EXIT, 'E&xit', 'Exit program')
  52         self.Bind(wx.EVT_MENU, self.OnProjectExit, item)
  53 
  54         self.mainmenu.Append(menu, '&Project')  # Add the project menu to the menu bar.
  55 
  56         # Make the 'File' menu.
  57         menu = wx.Menu()
  58 
  59         item = menu.Append(wx.ID_ANY, '&Add', 'Add file to project')
  60         self.Bind(wx.EVT_MENU, self.OnFileAdd, item)
  61 
  62         item = menu.Append(wx.ID_ANY, '&Remove', 'Remove file from project')
  63         self.Bind(wx.EVT_MENU, self.OnFileRemove, item)
  64 
  65         item = menu.Append(wx.ID_ANY, '&Open', 'Open file for editing')
  66         self.Bind(wx.EVT_MENU, self.OnFileOpen, item)
  67 
  68         item = menu.Append(wx.ID_ANY, '&Save', 'Save file')
  69         self.Bind(wx.EVT_MENU, self.OnFileSave, item)
  70 
  71         self.mainmenu.Append(menu, '&File') # Add the file menu to the menu bar.
  72 
  73         # Attach the menu bar to the window.
  74         self.SetMenuBar(self.mainmenu)
  75 
  76         # Create the splitter window.
  77         splitter = wx.SplitterWindow(self, style=wx.NO_3D|wx.SP_3D)
  78         splitter.SetMinimumPaneSize(1)
  79 
  80         # Create the tree on the left.
  81         self.tree = wx.TreeCtrl(splitter, style=wx.TR_DEFAULT_STYLE)
  82         self.tree.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTreeLabelEdit)
  83         self.tree.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTreeLabelEditEnd)
  84         self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTreeItemActivated)
  85 
  86         # Create the editor on the right.
  87         self.editor = wx.TextCtrl(splitter, style=wx.TE_MULTILINE)
  88         self.editor.Enable(0)
  89 
  90         # Install the tree and the editor.
  91         splitter.SplitVertically(self.tree, self.editor)
  92         splitter.SetSashPosition(180, True)
  93 
  94         # Some global state variables.
  95         self.projectdirty = False
  96         self.root = None
  97         self.close = False
  98 
  99         self.Bind(wx.EVT_CLOSE, self.OnProjectExit)
 100 
 101         self.Show(True)
 102 
 103     # ----------------------------------------------------------------------------------------
 104     # Some nice little handlers.
 105     # ----------------------------------------------------------------------------------------
 106 
 107     def project_open(self, project_file):
 108         """Open and process a wxProject file."""
 109         try:
 110             input = open(project_file, 'r')
 111             self.tree.DeleteAllItems()
 112 
 113             self.project_file = project_file
 114             name = input.readline().replace ('\n', '')
 115             self.SetTitle(name)
 116 
 117             # create the file elements in the tree control.
 118             self.root = self.tree.AddRoot(name)
 119             self.activeitem = self.root
 120             for line in input:
 121                 self.tree.AppendItem(self.root, line.replace ('\n', ''))
 122             input.close()
 123             self.tree.Expand(self.root)
 124 
 125             self.editor.Clear()
 126             self.editor.Enable(False)
 127 
 128             self.projectdirty = False
 129         except IOError:
 130             pass
 131 
 132     def project_save(self):
 133         """Save a wxProject file."""
 134         try:
 135             output = open(self.project_file, 'w+')
 136             output.write(self.tree.GetItemText(self.root) + '\n')
 137             count = self.tree.GetChildrenCount(self.root)  # collect all file (tree) items.
 138             iter = 0
 139             child = ''
 140             for i in range(count):
 141                if i == 0:
 142                   child, cookie = self.tree.GetFirstChild(self.root)
 143                else:
 144                   child, cookie = self.tree.GetNextChild(self.root, cookie)
 145                output.write(self.tree.GetItemText(child) + '\n')
 146             output.close()
 147             self.projectdirty = False
 148         except IOError:
 149             MsgDlg(self, 'There was an error saving the new project file.', 'Error!', wx.OK)
 150 
 151     def CheckProjectDirty(self):
 152         """Were the current project changed? If so, save it before."""
 153         open_it = True
 154         if self.projectdirty:
 155             # save the current project file first.
 156             result = MsgDlg(self, 'The project has been changed.  Save?')
 157             if result == wx.ID_YES:
 158                 self.project_save()
 159             if result == wx.ID_CANCEL:
 160                 open_it = False
 161         return open_it
 162 
 163     def CheckTreeRootItem(self):
 164         """Is there any root item?"""
 165         if not self.root:
 166             MsgDlg(self, 'Please create or open a project before.', 'Error!', wx.OK)
 167             return False
 168         return True
 169 
 170     # ----------------------------------------------------------------------------------------
 171     # Event handlers from here on out.
 172     # ----------------------------------------------------------------------------------------
 173 
 174     def OnProjectOpen(self, event):
 175         """Open a wxProject file."""
 176         open_it = self.CheckProjectDirty()
 177         if open_it:
 178             dlg = wx.FileDialog(self, 'Choose a project to open', '.', '', '*.wxp', wx.OPEN)
 179             if dlg.ShowModal() == wx.ID_OK:
 180                 self.project_open(dlg.GetPath())
 181             dlg.Destroy()
 182 
 183     def OnProjectNew(self, event):
 184         """Create a new wxProject."""
 185         open_it = self.CheckProjectDirty()
 186         if open_it:
 187             dlg = wx.TextEntryDialog(self, 'Name for new project:', 'New Project',
 188                                      'New project', wx.OK|wx.CANCEL)
 189             if dlg.ShowModal() == wx.ID_OK:
 190                 newproj = dlg.GetValue()
 191                 dlg.Destroy()
 192                 dlg = wx.FileDialog(self, 'Place to store new project.', '.', '', '*.wxp', wx.SAVE)
 193                 if dlg.ShowModal() == wx.ID_OK:
 194                     try:
 195                         # save the project file.
 196                         proj = open(dlg.GetPath(), 'w')
 197                         proj.write(newproj + '\n')
 198                         proj.close()
 199                         self.project_open(dlg.GetPath())
 200                     except IOError:
 201                         MsgDlg(self, 'There was an error saving the new project file.', 'Error!', wx.OK)
 202             dlg.Destroy()
 203 
 204     def SaveCurrentFile(self):
 205         """Check and save current file."""
 206         go_ahead = True
 207         if self.root:
 208             if self.activeitem != self.root:
 209                 if self.editor.IsModified():  # Save modified file before
 210                     result = MsgDlg(self, 'The edited file has changed.  Save it?')
 211                     if result == wx.ID_YES:
 212                         self.editor.SaveFile(self.tree.GetItemText(self.activeitem))
 213                     if result == wx.ID_CANCEL:
 214                         go_ahead = False
 215                 if go_ahead:
 216                     self.tree.SetItemBold(self.activeitem, 0)
 217         return go_ahead
 218 
 219     def OnProjectExit(self, event):
 220         """Quit the program."""
 221         if not self.close:
 222             self.close = True
 223             if not self.SaveCurrentFile():
 224                 self.close = False
 225             if self.projectdirty and self.close:
 226                 result = MsgDlg(self, 'The project has been changed.  Save?')
 227                 if result == wx.ID_YES:
 228                     self.project_save()
 229                 if result == wx.ID_CANCEL:
 230                     self.close = False
 231             if self.close:
 232                 self.Close()
 233         else:
 234             event.Skip()
 235 
 236     def OnFileAdd(self, event):
 237         """Adds a file to the current project."""
 238         if not self.CheckTreeRootItem():
 239             return
 240 
 241         dlg = wx.FileDialog(self, 'Choose a file to add.', '.', '', '*.*', wx.OPEN)
 242         if dlg.ShowModal() == wx.ID_OK:
 243             path = os.path.split(dlg.GetPath())
 244             self.tree.AppendItem(self.root, path[1])
 245             self.tree.Expand(self.root)
 246             self.project_save()
 247 
 248     def OnFileRemove(self, event):
 249         """Removes a file to the current project."""
 250         if not self.CheckTreeRootItem():
 251             return
 252         item = self.tree.GetSelection()
 253         if item != self.root:
 254             self.tree.Delete(item)
 255             self.project_save()
 256 
 257     def OnFileOpen(self, event):
 258         """Opens current selected file."""
 259         if self.root:
 260             item = self.tree.GetSelection()
 261             if item != self.root:
 262                 self.OnTreeItemActivated(None, item)
 263                 return
 264         MsgDlg(self, 'There is no file to load.', 'Error!', wx.OK)
 265 
 266     def OnFileSave(self, event):
 267         """Saves current selected file."""
 268         if self.root:
 269             if self.activeitem != self.root:
 270                 self.editor.SaveFile(self.tree.GetItemText(self.activeitem))
 271                 return
 272         MsgDlg(self, 'There is no file to save.', 'Error!', wx.OK)
 273 
 274 
 275     def OnTreeLabelEdit(self, event):
 276         """Edit tree label (only root label can be edited)."""
 277         item = event.GetItem()
 278         if item != self.root:
 279             event.Veto()
 280 
 281     def OnTreeLabelEditEnd(self, event):
 282         """End editing the tree label."""
 283         self.projectdirty = True
 284 
 285 
 286     def OnTreeItemActivated(self, event, item=None):
 287         """Tree item was activated: try to open this file."""
 288         go_ahead = self.SaveCurrentFile()
 289 
 290         if go_ahead:
 291             if event:
 292                 item = event.GetItem()
 293             self.activeitem = item
 294             if item != self.root:
 295                 # load the current selected file
 296                 self.tree.SetItemBold(item, 1)
 297                 self.editor.Enable(1)
 298                 self.editor.LoadFile(self.tree.GetItemText(item))
 299                 self.editor.SetInsertionPoint(0)
 300                 self.editor.SetFocus()
 301             else:
 302                 self.editor.Clear()
 303                 self.editor.Enable(0)
 304 
 305 
 306 class App(wx.App):
 307     """wxProject Application."""
 308     def OnInit(self):
 309         """Create the wxProject Application."""
 310         frame = main_window(None, 'wxProject - ' + projfile)
 311         if projfile != 'Unnamed':
 312             frame.project_open(projfile)
 313         return True
 314 
 315 
 316 if __name__ == '__main__':
 317     app = App(0)
 318     app.MainLoop()

This file is also in the doc package in wxPython:

"wxPythonx.y Docs and Demos/samples/wxProject/wxProject.py"

WxProject (last edited 2010-01-20 16:54:49 by s235-200)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.