diff --git a/Application/freeze.py b/Application/freeze.py index aff8af1..aab4512 100644 --- a/Application/freeze.py +++ b/Application/freeze.py @@ -15,7 +15,7 @@ shutil.rmtree('tkintertableapp', ignore_errors=True) path=os.path.abspath('../') -version = '1.0.0' +version = '1.3.1' f = Freezer('tkintertableapp', excludes=('wx')) f.addScript(os.path.join(path, "TablesApp.py")) @@ -29,7 +29,7 @@ datadir = 'tkintertableapp/mpl-data' shutil.copytree(mpldir, datadir) -#add resource files +#add resource files shutil.copy('logo.ico', 'tkintertableapp') shutil.copy('../sample.table', 'tkintertableapp') @@ -38,7 +38,6 @@ f = zipfile.ZipFile("tkintertableapp-"+version+".zip", "w") for dirpath, dirnames, filenames in os.walk('tkintertableapp'): for fname in filenames: - fullname = os.path.join(dirpath, fname) + fullname = os.path.join(dirpath, fname) f.write(fullname) f.close() - diff --git a/description.txt b/description.txt index 1a3839f..9dcbfb2 100644 --- a/description.txt +++ b/description.txt @@ -2,20 +2,16 @@ Description ----------- This package allows interactive spreadsheet-style tables to be added into a Tkinter application. -Tkinter is the standard GUI toolkit for python. A sample application using these classes -is included in the distribution. +Tkinter is the standard GUI toolkit for Python. A sample application using these classes +is included in the distribution. Now works with Python 3. Installation ------------ -pip install tkintertable or easy_install tkintertable +pip install tkintertable You can clone the current source using git clone https://github.com/dmnfarrell/tkintertable.git https://github.com/dmnfarrell/tkintertable/wiki for more info. - - - - diff --git a/setup.py b/setup.py index 4b40484..090dd27 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name = 'tkintertable', - version = '1.3', + version = '1.3.1', description = 'Extendable table class for Tkinter', long_description = long_description, url='https://github.com/dmnfarrell/tkintertable', diff --git a/tkintertable/Filtering.py b/tkintertable/Filtering.py index 0923ab1..02e17c5 100644 --- a/tkintertable/Filtering.py +++ b/tkintertable/Filtering.py @@ -27,7 +27,7 @@ except: from Tkinter import * from ttk import * -import Pmw +#import Pmw from types import * import re @@ -177,35 +177,36 @@ def __init__(self, parent, index, fields): self.index = index self.filtercol=StringVar() initial = fields[0] - filtercolmenu = Pmw.OptionMenu(self, - labelpos = 'w', - label_text = 'Column:', - menubutton_textvariable = self.filtercol, - items = fields, - initialitem = initial, - menubutton_width = 10) + filtercolmenu = Combobox(self, + #labelpos = 'w', + #label_text = 'Column:', + textvariable = self.filtercol, + values = fields, + #initialitem = initial, + width = 10) filtercolmenu.grid(row=0,column=1,sticky='news',padx=2,pady=2) self.operator=StringVar() - operatormenu = Pmw.OptionMenu(self, - menubutton_textvariable = self.operator, - items = self.operators, - initialitem = 'contains', - menubutton_width = 8) + operatormenu = Combobox(self, + textvariable = self.operator, + values = self.operators, + #initialitem = 'contains', + width = 8) operatormenu.grid(row=0,column=2,sticky='news',padx=2,pady=2) self.filtercolvalue=StringVar() valsbox=Entry(self,textvariable=self.filtercolvalue,width=20) valsbox.grid(row=0,column=3,sticky='news',padx=2,pady=2) valsbox.bind("", self.parent.callback) self.booleanop=StringVar() - booleanopmenu = Pmw.OptionMenu(self, - menubutton_textvariable = self.booleanop, - items = self.booleanops, - initialitem = 'AND', - menubutton_width = 6) + self.booleanop.set('AND') + booleanopmenu = Combobox(self, + textvariable = self.booleanop, + values = self.booleanops, + #initialitem = 'AND', + width = 6) booleanopmenu.grid(row=0,column=0,sticky='news',padx=2,pady=2) #disable the boolean operator if it's the first filter - if self.index == 0: - booleanopmenu.component('menubutton').configure(state=DISABLED) + #if self.index == 0: + # booleanopmenu.component('menubutton').configure(state=DISABLED) cbutton=Button(self,text='-', command=self.close) cbutton.grid(row=0,column=5,sticky='news',padx=2,pady=2) return diff --git a/tkintertable/Prefs.py b/tkintertable/Prefs.py index 315647d..7b9f970 100644 --- a/tkintertable/Prefs.py +++ b/tkintertable/Prefs.py @@ -74,9 +74,7 @@ def get(self,key): if key in self.prefs: return self.prefs[key] - else: - pass - return + return def delete(self,key): diff --git a/tkintertable/TableModels.py b/tkintertable/TableModels.py index 200805a..3a665a4 100644 --- a/tkintertable/TableModels.py +++ b/tkintertable/TableModels.py @@ -159,6 +159,7 @@ def getDefaultTypes(self): def getData(self): """Return the current data for saving""" + data = copy.deepcopy(self.data) data['colors'] = self.colors data['columnnames'] = self.columnNames @@ -177,6 +178,7 @@ def getData(self): def getAllCells(self): """Return a dict of the form rowname: list of cell contents Useful for a simple table export for example""" + records={} for row in range(len(self.reclist)): recdata=[] @@ -187,6 +189,7 @@ def getAllCells(self): def getColCells(self, colIndex): """Get the viewable contents of a col into a list""" + collist = [] if self.getColumnType(colIndex) == 'Link': return ['xxxxxx'] diff --git a/tkintertable/Tables.py b/tkintertable/Tables.py index 14f25b7..033a0bd 100644 --- a/tkintertable/Tables.py +++ b/tkintertable/Tables.py @@ -1191,6 +1191,7 @@ def clear(): def convertFormulae(self, rows, cols=None): """Convert the formulas in the cells to their result values""" + if len(self.multiplerowlist) == 0 or len(self.multiplecollist) == 0: return None @@ -1206,11 +1207,13 @@ def convertFormulae(self, rows, cols=None): def paste(self, event=None): """Copy from clipboard""" + print (self.parentframe.clipboard_get()) return def copyCell(self, rows, cols=None): """Copy cell contents to a temp internal clipboard""" + row = rows[0]; col = cols[0] #absrow = self.get_AbsoluteRow(row) self.clipboard = copy.deepcopy(self.model.getCellRecord(row, col)) @@ -1218,6 +1221,7 @@ def copyCell(self, rows, cols=None): def pasteCell(self, rows, cols=None): """Paste cell from internal clipboard""" + row = rows[0]; col = cols[0] #absrow = self.get_AbsoluteRow(row) val = self.clipboard @@ -1227,6 +1231,7 @@ def pasteCell(self, rows, cols=None): def copyColumns(self): """Copy current selected cols""" + M = self.model coldata = {} for col in self.multiplecollist: @@ -1236,6 +1241,7 @@ def copyColumns(self): def pasteColumns(self, coldata): """Paste new cols, overwrites existing names""" + M = self.model for name in coldata: if name not in M.columnNames: @@ -1920,23 +1926,20 @@ def close_prefsdialog(): #fonts fts = self.getFonts() - - def setFont(): - self.thefont = self.fontbox.getcurselection() + self.fontvar = StringVar() + self.fontvar.set(self.prefs.get('celltextfont')) + def setFont(*args): + self.thefont = self.fontvar.get() return - import Pmw - self.fontbox = Pmw.ScrolledListBox(frame2, - items=(fts), - labelpos='w', - label_text='Font:', - listbox_height = 6, - selectioncommand = setFont, - usehullsize = 1, - hull_width = 200, - hull_height = 80) - self.fontbox.setvalue(self.prefs.get('celltextfont')) - self.fontbox.grid(row=row,column=0, columnspan=2, sticky='nes', padx=3,pady=2) + self.fontbox = Combobox(frame2, + values=(fts), + text='Font:', + height = 6, + textvariable=self.fontvar) + self.fontvar.trace('w', setFont) + Label(frame2,text='Font:').grid(row=row,column=0,padx=3,pady=2) + self.fontbox.grid(row=row,column=1, columnspan=2, sticky='nes', padx=3,pady=2) row=row+1 lblfontsize=Label(frame2,text='Text Size:') @@ -2020,11 +2023,11 @@ def loadPrefs(self, prefs=None): 'rowselectedcolor': self.rowselectedcolor, 'rowheaderwidth': self.rowheaderwidth} - for prop in defaultprefs.keys(): - try: - print(self.prefs.get(prop)) - except: - self.prefs.set(prop, defaultprefs[prop]) + for prop in defaultprefs: + if not prop in self.prefs.prefs: + #print (defaultprefs[prop]) + if defaultprefs[prop] != 'None': + self.prefs.set(prop, defaultprefs[prop]) self.defaultprefs = defaultprefs @@ -2077,7 +2080,7 @@ def savePrefs(self): self.prefs.set('linewidth', self.linewidthvar.get()) self.linewidth = self.linewidthvar.get() self.prefs.set('celltextsize', self.celltextsizevar.get()) - self.prefs.set('celltextfont', self.fontbox.getcurselection()) + self.prefs.set('celltextfont', self.fontvar.get()) self.prefs.set('cellbackgr', self.cellbackgr) self.prefs.set('grid_color', self.grid_color) self.prefs.set('rowselectedcolor', self.rowselectedcolor) @@ -2548,6 +2551,7 @@ class RowHeader(Canvas): takes it's size and rendering from the parent table This also handles row/record selection as opposed to cell selection""" + def __init__(self, parent=None, table=None, width=40): Canvas.__init__(self, parent, bg='gray75', width=width, height=None) @@ -2628,6 +2632,7 @@ def handle_left_release(self,event): def handle_left_ctrl_click(self, event): """Handle ctrl clicks - for multiple row selections""" + rowclicked = self.table.get_row_clicked(event) multirowlist = self.table.multiplerowlist if 0 <= rowclicked < self.table.rows: @@ -2652,6 +2657,7 @@ def handle_right_click(self,event): def handle_mouse_drag(self, event): """Handle mouse moved with button held down, multiple selections""" + if hasattr(self, 'cellentry'): self.cellentry.destroy() rowover = self.table.get_row_clicked(event) @@ -2680,6 +2686,7 @@ def handle_mouse_drag(self, event): def drawSelectedRows(self, rows=None): """Draw selected rows, accepts a list or integer""" + self.delete('rect') if type(rows) is not list: rowlist=[] @@ -2694,6 +2701,7 @@ def drawSelectedRows(self, rows=None): def drawRect(self, row=None, tag=None, color=None, outline=None, delete=1): """Draw a rect representing row selection""" + if tag==None: tag='rect' if color==None: @@ -2716,6 +2724,7 @@ def drawRect(self, row=None, tag=None, color=None, outline=None, delete=1): class AutoScrollbar(Scrollbar): """a scrollbar that hides itself if it's not needed. only works if you use the grid geometry manager.""" + def set(self, lo, hi): if float(lo) <= 0.0 and float(hi) >= 1.0: # grid_remove is currently missing from Tkinter! diff --git a/tkintertable/Tables_IO.py b/tkintertable/Tables_IO.py index 4efeda4..d872ecb 100644 --- a/tkintertable/Tables_IO.py +++ b/tkintertable/Tables_IO.py @@ -30,7 +30,7 @@ import tkFileDialog as filedialog import tkSimpleDialog as simpledialog import tkMessageBox as messagebox -import Pmw + import os, csv class TableImporter: @@ -39,7 +39,7 @@ class TableImporter: def __init__(self): """Setup globals""" #self.separator = ',' - self.separator_list = {',':',',' ':'space','\t':'tab','blank':' ',':':':'} + self.separator_list = [',',' ','\t',':'] self.var_sep = StringVar() self.var_sep.set(',') return @@ -53,29 +53,20 @@ def import_Dialog(self, parent): self.xsize = 450 self.ysize = 370 top=self.master.winfo_toplevel() - #rootx=top.winfo_rootx() - #rooty=top.winfo_rooty() self.master.geometry('400x400+200+200') - self.sep_choice = Pmw.OptionMenu( - parent = self.master,labelpos = 'w', - label_text = 'Record separator:', - menubutton_textvariable = self.var_sep, - items = self.separator_list.keys(), - initialitem = ',', - menubutton_width = 4, - command= self.update_display) - - self.sep_choice.grid(row=0,column=0,sticky='nw',padx=2,pady=2) + self.sep_choice = Combobox(self.master, + text = 'Record separator:', + textvariable = self.var_sep, + values = self.separator_list, + width = 4) + self.var_sep.trace('w', self.update_display) + Label(self.master,text='separator:').grid(row=0,column=0,sticky='nw',padx=2,pady=2) + self.sep_choice.grid(row=0,column=1,sticky='nw',padx=2,pady=2) #place for text preview frame - - self.textframe=Pmw.ScrolledFrame(self.master, - labelpos = 'n', label_text = 'Preview', - usehullsize = 1, - hull_width = 450, - hull_height = 300) + self.textframe = Frame(self.master) self.textframe.grid(row=1,column=0,columnspan=5,sticky='news',padx=2,pady=2) - self.previewarea = Text(self.textframe.interior(), bg='white', width=400, height=500) + self.previewarea = Text(self.textframe, bg='white', width=400, height=500) self.previewarea.pack(fill=BOTH, expand=1) #buttons self.openButton = Button(self.master, text = 'Open File', @@ -92,6 +83,7 @@ def import_Dialog(self, parent): return self.master def do_openFile(self): + self.datafile = self.open_File(self.parent) self.update_display() return @@ -110,11 +102,12 @@ def open_File(self, parent): datafile = filename.name return datafile - def update_display(self,evt=None): + def update_display(self, *args): """Preview loaded file""" + sep = self.var_sep.get() self.previewarea.delete(1.0, END) - reader = csv.reader(open(self.datafile, "rb"), delimiter=sep) + reader = csv.reader(open(self.datafile, "r"), delimiter=sep) for row in reader: self.previewarea.insert(END,row) self.previewarea.insert(END,'\n') @@ -122,7 +115,7 @@ def update_display(self,evt=None): def do_ModelImport(self): """imports and places the result in self.modeldata""" - + self.data = self.ImportTableModel(self.datafile) self.close() return @@ -137,7 +130,7 @@ def ImportTableModel(self, filename): except: sep = ',' #takes first row as field names - dictreader = csv.DictReader(open(filename, "rb"), delimiter=sep) + dictreader = csv.DictReader(open(filename, "r"), delimiter=sep) dictdata = {} count=0 for rec in dictreader: diff --git a/tkintertable/Testing.py b/tkintertable/Testing.py index 5ce917d..b2c3279 100644 --- a/tkintertable/Testing.py +++ b/tkintertable/Testing.py @@ -171,21 +171,6 @@ def test4(): #createTable(model) return -def test5(): - """frame placement""" - import Pmw - t=Toplevel() - app = App(t) - master = app.main - w = Pmw.Group(master, - tag_text='Show/Hide') - w.pack(fill=BOTH) - f=Frame(master) - f.pack(fill=BOTH) - table = TableCanvas(w) - table.createTableFrame() - return - def GUITests(): """Run standard tests""" root = Tk()