Package tkintertable :: Module TablesApp
[hide private]
[frames] | no frames]

Source Code for Module tkintertable.TablesApp

  1  #!/usr/bin/env python 
  2  """ 
  3      Sample App to illustrate table functionality. 
  4      Created January 2008 
  5      Copyright (C) Damien Farrell 
  6   
  7      This program is free software; you can redistribute it and/or 
  8      modify it under the terms of the GNU General Public License 
  9      as published by the Free Software Foundation; either version 2 
 10      of the License, or (at your option) any later version. 
 11   
 12      This program is distributed in the hope that it will be useful, 
 13      but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15      GNU General Public License for more details. 
 16   
 17      You should have received a copy of the GNU General Public License 
 18      along with this program; if not, write to the Free Software 
 19      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 20  """ 
 21   
 22  from Tkinter import * 
 23  import Pmw 
 24  import tkFileDialog, tkMessageBox, tkSimpleDialog 
 25  import re 
 26  import os 
 27  import time 
 28  import pickle 
 29  from Custom import MyTable 
 30  from TableModels import TableModel 
 31  from Tables_IO import TableImporter 
 32  from Prefs import Preferences 
 33   
34 -class TablesApp(Frame):
35 """ 36 Tables app 37 """
38 - def __init__(self,parent=None,data=None,datafile=None):
39 "Initialize the application." 40 self.parent=parent 41 42 #If there is data to be loaded, show the dialog first 43 if not self.parent: 44 Frame.__init__(self) 45 self.tablesapp_win=self.master 46 47 else: 48 self.tablesapp_win=Toplevel() 49 50 # Get platform into a variable 51 import platform 52 self.currplatform=platform.system() 53 if not hasattr(self,'defaultsavedir'): 54 self.defaultsavedir = os.getcwd() 55 56 self.preferences=Preferences('TablesApp',{'check_for_update':1}) 57 self.loadprefs() 58 self.tablesapp_win.title('Tables Application') 59 self.tablesapp_win.geometry('+200+200') 60 self.x_size=800 61 self.y_size=600 62 self.createMenuBar() 63 self.apptoolBar = ToolBar(self.tablesapp_win, self) 64 self.apptoolBar.pack(fill=BOTH, expand=NO) 65 #add find bar 66 #self.createSearchBar() 67 68 if data != None: 69 self.data = data 70 self.new_project(data) 71 elif datafile != None: 72 self.open_project(datafile) 73 else: 74 self.new_project() 75 76 self.tablesapp_win.protocol('WM_DELETE_WINDOW',self.quit) 77 return
78
79 - def createMenuBar(self):
80 """Create the menu bar for the application. """ 81 self.menu=Menu(self.tablesapp_win) 82 self.proj_menu={'01New':{'cmd':self.new_project}, 83 '02Open':{'cmd':self.open_project}, 84 '03Close':{'cmd':self.close_project}, 85 '04Save':{'cmd':self.save_project}, 86 '05Save As':{'cmd':self.save_as_project}, 87 '06Preferences..':{'cmd':self.showPrefsDialog}, 88 '08Quit':{'cmd':self.quit}} 89 if self.parent: 90 self.proj_menu['08Return to Database']={'cmd':self.return_data} 91 self.proj_menu=self.create_pulldown(self.menu,self.proj_menu) 92 self.menu.add_cascade(label='Project',menu=self.proj_menu['var']) 93 94 self.records_menu={'01Add Row':{'cmd':self.add_Row}, 95 '02Delete Row':{'cmd':self.delete_Row}, 96 '03Add Column':{'cmd':self.add_Column}, 97 '04Delete Column':{'cmd':self.delete_Column}, 98 '05Auto Add Rows':{'cmd':self.autoAdd_Rows}, 99 '06Auto Add Columns':{'cmd':self.autoAdd_Columns}, 100 '07Find':{'cmd':self.createSearchBar}, 101 } 102 self.records_menu=self.create_pulldown(self.menu,self.records_menu) 103 self.menu.add_cascade(label='Records',menu=self.records_menu['var']) 104 105 self.sheet_menu={'01Add Sheet':{'cmd':self.add_Sheet}, 106 '02Remove Sheet':{'cmd':self.delete_Sheet}, 107 '03Copy Sheet':{'cmd':self.copy_Sheet}, 108 '04Rename Sheet':{'cmd':self.rename_Sheet}, 109 } 110 self.sheet_menu=self.create_pulldown(self.menu,self.sheet_menu) 111 self.menu.add_cascade(label='Sheet',menu=self.sheet_menu['var']) 112 113 self.IO_menu={'01Import from csv file':{'cmd':self.import_cvs}, 114 '02Export to csv file':{'cmd':self.export_cvs}, 115 } 116 117 self.IO_menu=self.create_pulldown(self.menu,self.IO_menu) 118 self.menu.add_cascade(label='Import/Export',menu=self.IO_menu['var']) 119 120 121 self.view_menu = Menu(self.menu, tearoff=0) 122 self.view_menu.add_radiobutton(label="Normal View", state=ACTIVE,command=self.normal_view) 123 self.view_menu.add_radiobutton(label="Page View", command=self.page_view) 124 self.menu.add_cascade(label='View',menu=self.view_menu) 125 126 # 127 # Help menu 128 # 129 self.help_menu={'01Online Help':{'cmd':self.online_documentation}, 130 '02About':{'cmd':self.about_Tables}} 131 self.help_menu=self.create_pulldown(self.menu,self.help_menu) 132 self.menu.add_cascade(label='Help',menu=self.help_menu['var']) 133 134 self.tablesapp_win.config(menu=self.menu) 135 136 return
137
138 - def create_pulldown(self,menu,dict):
139 # 140 # Create a pulldown in var from the info in dict 141 # 142 var=Menu(menu,tearoff=0) 143 items=dict.keys() 144 items.sort() 145 for item in items: 146 if item[-3:]=='sep': 147 var.add_separator() 148 else: 149 # 150 # Do we have a command? 151 # 152 command=None 153 if dict[item].has_key('cmd'): 154 command=dict[item]['cmd'] 155 # 156 # Put the command in there 157 # 158 if dict[item].has_key('sc'): 159 var.add_command(label='%-25s %9s' %(item[2:],dict[item]['sc']),command=command) 160 else: 161 var.add_command(label='%-25s' %(item[2:]),command=command) 162 dict['var']=var 163 return dict
164
165 - def createSearchBar(self, event=None):
166 """Add a find entry box""" 167 frame = Frame(self.tablesapp_win) 168 row=0 169 def close(): 170 frame.destroy()
171 self.findtext=StringVar() 172 self.findbox=Entry(frame,textvariable=self.findtext,width=30,bg='white') 173 self.findbox.grid(row=row,column=1,sticky='news',columnspan=2,padx=2,pady=2) 174 self.findbox.bind('<Return>',self.do_find_text) 175 Label(frame,text='Find:').grid(row=row,column=0,sticky='ew') 176 self.findagainbutton=Button(frame,text='Find Again', command=self.do_find_again) 177 self.findagainbutton.grid(row=row,column=3,sticky='news',padx=2,pady=2) 178 self.cbutton=Button(frame,text='Close', command=close) 179 self.cbutton.grid(row=row,column=4,sticky='news',padx=2,pady=2) 180 frame.pack(fill=BOTH, expand=NO) 181 return
182 183
184 - def loadprefs(self):
185 """Setup default prefs file if any of the keys are not present""" 186 defaultprefs = {'textsize':14, 187 'windowwidth': 800 ,'windowheight':600} 188 for prop in defaultprefs.keys(): 189 try: 190 self.preferences.get(prop) 191 except: 192 self.preferences.set(prop, defaultprefs[prop]) 193 194 return
195
196 - def showPrefsDialog(self):
197 self.prefswindow = self.currenttable.showtablePrefs() 198 199 return
200 201
202 - def new_project(self, data=None):
203 """Create a new table, with model and add the frame""" 204 if hasattr(self,'currenttable'): 205 self.notebook.destroy() 206 self.currenttable.destroy() 207 208 #Create the sheets dict 209 self.sheets = {} 210 self.notebook = Pmw.NoteBook(self.tablesapp_win, raisecommand=self.setcurrenttable) 211 self.notebook.pack(fill='both', expand=1, padx=4, pady=4) 212 if data !=None: 213 for s in data.keys(): 214 sdata = data[s] 215 try: 216 self.add_Sheet(s ,sdata) 217 except: 218 print 'skipping' 219 else: 220 #do the table adding stuff for the initial sheet 221 self.add_Sheet('sheet1') 222 self.notebook.setnaturalsize() 223 return
224
225 - def open_project(self, filename=None):
226 if filename == None: 227 filename=tkFileDialog.askopenfilename(defaultextension='.tbleprj"', 228 initialdir=os.getcwd(), 229 filetypes=[("Pickle file","*.tbleprj"), 230 ("All files","*.*")], 231 parent=self.tablesapp_win) 232 if os.path.isfile(filename): 233 fd=open(filename) 234 data=pickle.load(fd) 235 fd.close() 236 self.new_project(data) 237 self.filename=filename 238 return
239
240 - def save_project(self):
241 if not hasattr(self, 'filename'): 242 self.save_as_project() 243 elif self.filename == None: 244 self.save_as_project() 245 else: 246 self.do_save_project(self.filename) 247 248 return
249
250 - def save_as_project(self):
251 """Save as a new filename""" 252 filename=tkFileDialog.asksaveasfilename(parent=self.tablesapp_win, 253 defaultextension='.tblprj', 254 initialdir=self.defaultsavedir, 255 filetypes=[("TableApp project","*.tblprj"), 256 ("All files","*.*")]) 257 if not filename: 258 print 'Returning' 259 return 260 self.filename=filename 261 self.do_save_project(self.filename) 262 return
263
264 - def do_save_project(self, filename):
265 """Get model dicts and write all to pickle file""" 266 data={} 267 for s in self.sheets.keys(): 268 currtable = self.sheets[s] 269 model = currtable.getModel() 270 data[s] = model.getData() 271 272 fd=open(filename,'w') 273 pickle.dump(data,fd) 274 fd.close() 275 return
276
277 - def close_project(self):
278 if hasattr(self,'currenttable'): 279 #self.notebook.destroy() 280 self.currenttable.destroy() 281 return
282
283 - def import_cvs(self):
284 importer = TableImporter() 285 #datafile = importer.open_File(self.tablesapp_win) 286 287 #just use the dialog to load and import the file 288 importdialog = importer.import_Dialog(self.tablesapp_win) 289 self.tablesapp_win.wait_window(importdialog) 290 model = TableModel() 291 model.importDict(importer.data) 292 sheetdata = {} 293 sheetdata['sheet1'] = model.getData() 294 self.new_project(sheetdata) 295 return
296
297 - def export_cvs(self):
298 exporter = TableExporter() 299 exporter.ExportTableData(self.currenttable) 300 return
301 302
303 - def add_Sheet(self, sheetname=None, sheetdata=None):
304 """Add a new sheet - handles all the table creation stuff""" 305 def checksheet_name(name): 306 if name == '': 307 tkMessageBox.showwarning("Whoops", "Name should not be blank.") 308 return 0 309 if self.sheets.has_key(name): 310 tkMessageBox.showwarning("Name exists", "Sheet name already exists!") 311 return 0
312 noshts = len(self.notebook.pagenames()) 313 if sheetname == None: 314 sheetname = tkSimpleDialog.askstring("New sheet name?", "Enter sheet name:", 315 initialvalue='sheet'+str(noshts+1)) 316 checksheet_name(sheetname) 317 page = self.notebook.add(sheetname) 318 #Create the table and model if data present 319 if sheetdata != None: 320 model = TableModel(sheetdata) 321 self.currenttable = MyTable(page, model) 322 else: 323 self.currenttable = MyTable(page) 324 325 #Load preferences into table 326 self.currenttable.loadPrefs(self.preferences) 327 #This handles all the canvas and header in the frame passed to constructor 328 self.currenttable.createTableFrame() 329 #add the table to the sheet dict 330 self.sheets[sheetname] = self.currenttable 331 self.saved = 0 332 return sheetname 333
334 - def delete_Sheet(self):
335 """Delete a sheet""" 336 s = self.notebook.getcurselection() 337 self.notebook.delete(s) 338 del self.sheets[s] 339 return
340
341 - def copy_Sheet(self, newname=None):
342 """Copy a sheet""" 343 newdata = self.currenttable.getModel().getData().copy() 344 if newname==None: 345 self.add_Sheet(None, newdata) 346 else: 347 self.add_Sheet(newname, newdata) 348 return
349
350 - def rename_Sheet(self):
351 """Rename a sheet""" 352 s = self.notebook.getcurselection() 353 newname = tkSimpleDialog.askstring("New sheet name?", "Enter new sheet name:", 354 initialvalue=s) 355 if newname == None: 356 return 357 self.copy_Sheet(newname) 358 self.delete_Sheet() 359 return
360
361 - def setcurrenttable(self, event):
362 """Set the currenttable so that menu items work with visible sheet""" 363 try: 364 s = self.notebook.getcurselection() 365 self.currenttable = self.sheets[s] 366 except: 367 pass 368 return
369
370 - def add_Row(self):
371 """Add a new row""" 372 self.currenttable.add_Row() 373 self.saved = 0 374 return
375
376 - def delete_Row(self):
377 """Delete currently selected row""" 378 self.currenttable.delete_Row() 379 self.saved = 0 380 return
381
382 - def add_Column(self):
383 """Add a new column""" 384 self.currenttable.add_Column() 385 self.saved = 0 386 return
387
388 - def delete_Column(self):
389 """Delete currently selected column in table""" 390 self.currenttable.delete_Column() 391 self.saved = 0 392 return
393
394 - def autoAdd_Rows(self):
395 """Auto add x rows""" 396 self.currenttable.autoAdd_Rows() 397 self.saved = 0 398 return
399
400 - def autoAdd_Columns(self):
401 """Auto add x rows""" 402 self.currenttable.autoAdd_Columns() 403 self.saved = 0 404 return
405
406 - def findValue(self):
407 self.currenttable.findValue() 408 return
409
410 - def do_find_text(self, event=None):
411 """Find the text in the table""" 412 if not hasattr(self,'currenttable'): 413 return 414 import string 415 if string.strip(self.findtext.get())=='': 416 return 417 searchstring=self.findtext.get() 418 if self.currenttable!=None: 419 self.currenttable.findValue(searchstring) 420 return
421
422 - def do_find_again(self, event=None):
423 """Find again""" 424 if not hasattr(self,'currenttable'): 425 return 426 searchstring=self.findtext.get() 427 if self.currenttable!=None: 428 self.currenttable.findValue(searchstring, findagain=1) 429 return
430
431 - def plot(self, event=None):
432 self.currenttable.plot_Selected() 433 return
434
435 - def plotSetup(self, event=None):
436 self.currenttable.plotSetup() 437 return
438
439 - def normal_view(self,event=None):
440 self.currenttable.paging_Off() 441 return
442
443 - def page_view(self,event=None):
444 self.currenttable.paging = 1 445 self.currenttable.redrawTable() 446 return
447
448 - def about_Tables(self):
449 self.ab_win=Toplevel() 450 self.ab_win.geometry('+100+350') 451 self.ab_win.title('About TablesApp') 452 453 import Table_images 454 logo = Table_images.tableapp_logo() 455 label = Label(self.ab_win,image=logo) 456 label.image = logo 457 label.grid(row=0,column=0,sticky='news',padx=4,pady=4) 458 459 text=['Tables Sample App ','Shows the use of Tablecanvas class for tkinter', 460 'Copyright (C) Damien Farrell 2008', 'This program is free software; you can redistribute it and/or', 461 'modify it under the terms of the GNU General Public License', 462 'as published by the Free Software Foundation; either version 2', 463 'of the License, or (at your option) any later version.'] 464 row=1 465 for line in text: 466 tmp=Label(self.ab_win,text=line) 467 tmp.grid(row=row,column=0,sticky='news',padx=4) 468 row=row+1 469 return
470
471 - def online_documentation(self,event=None):
472 """Open the online documentation""" 473 import webbrowser 474 link='http://sourceforge.net/projects/tkintertable/' 475 webbrowser.open(link,autoraise=1) 476 return
477
478 - def quit(self):
479 self.tablesapp_win.destroy() 480 481 return
482
483 -class ToolBar(Frame):
484 """Uses the parent instance to provide the functions"""
485 - def __init__(self, parent=None, parentapp=None):
486 Frame.__init__(self, parent, width=600, height=40) 487 import Table_images 488 self.parentframe = parent 489 self.parentapp = parentapp 490 #add buttons 491 img = Table_images.new_proj() 492 self.add_button('New Project', self.parentapp.new_project, img) 493 img = Table_images.open_proj() 494 self.add_button('Open Project', self.parentapp.open_project, img) 495 img = Table_images.save_proj() 496 self.add_button('Save Project', self.parentapp.save_project, img) 497 img = Table_images.add_row() 498 self.add_button('Add record', self.parentapp.add_Row, img) 499 img = Table_images.add_col() 500 self.add_button('Add col', self.parentapp.add_Column, img) 501 img = Table_images.del_row() 502 self.add_button('Delete record', self.parentapp.delete_Row, img) 503 img = Table_images.del_col() 504 self.add_button('Delete col', self.parentapp.delete_Column, img) 505 img = Table_images.plot() 506 self.add_button('Plot', self.parentapp.plot, img) 507 img = Table_images.plotprefs() 508 self.add_button('Plot Prefs', self.parentapp.plotSetup, img) 509 510 return
511
512 - def add_button(self, name, callback, img=None):
513 if img==None: 514 b = Button(self, text=name, command=callback, 515 relief=GROOVE) 516 else: 517 b = Button(self, text=name, command=callback, 518 relief=GROOVE, 519 image=img) 520 b.image = img 521 b.pack(side=LEFT, padx=2, pady=2, ipadx=3, ipady=3) 522 523 return
524 525 # Main function, run when invoked as a stand-alone Python program. 526
527 -def main():
528 "Run the application" 529 import sys, os 530 from optparse import OptionParser 531 parser = OptionParser() 532 parser.add_option("-f", "--file", dest="tablefile", 533 help="Open a table file", metavar="FILE") 534 opts, remainder = parser.parse_args() 535 if opts.tablefile != None: 536 app=TablesApp(datafile=opts.tablefile) 537 else: 538 app=TablesApp() 539 app.mainloop() 540 return
541 542 if __name__ == '__main__': 543 main() 544