Skip to content

Commit 1b74bc0

Browse files
authored
Merge pull request #20 from whellcome/1.2-dev
TreeviewDataFrame behavior encapsulated
2 parents 1d0226a + 34fe420 commit 1b74bc0

File tree

1 file changed

+36
-54
lines changed

1 file changed

+36
-54
lines changed

code/export-msaccess-sql.py

Lines changed: 36 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import tkinter as tk
2+
from tkinter import ttk, filedialog, messagebox
23
import webbrowser
3-
from tkinter import filedialog, messagebox
4-
from tkinter import ttk
5-
64
import pandas as pd
75
import win32com.client
86

@@ -90,7 +88,6 @@ def insert(self, parent, index, iid=None, **kw):
9088
def set(self, item, column=None, value=None):
9189
"""
9290
Enhanced set method for synchronization with a DataFrame.
93-
9491
:param item: The item ID (iid) in the Treeview.
9592
:param column: The column name to retrieve or update.
9693
:param value: The value to set; if None, retrieves the current value.
@@ -109,6 +106,8 @@ def set(self, item, column=None, value=None):
109106
self.df.loc[item, column] = value
110107
if is_filtered:
111108
self.filtered_df.loc[item, column] = value
109+
ind = self.cget("columns").index(column) if not column else 0
110+
self.all_checked_update(ind)
112111
return result
113112

114113
def item(self, item, option=None, **kw):
@@ -123,6 +122,7 @@ def item(self, item, option=None, **kw):
123122
self.df.loc[item] = updates
124123
if is_filtered:
125124
self.filtered_df.loc[item] = updates
125+
self.all_checked_update()
126126
return result
127127

128128
def delete(self, *items, inplace=False):
@@ -168,9 +168,20 @@ def filter_event_evoke(self):
168168
"""Filter updated event."""
169169
self.event_generate("<<TreeFilterUpdated>>")
170170

171-
def all_checked(self, column):
171+
def all_checked_event_evoke(self):
172+
self.event_generate("<<TreeCheckAllUpdated>>")
173+
174+
def is_all_checked(self, column):
172175
df = self.filtered_df if len(self.filtered_df) else self.df
173-
return not len(df[df.iloc[:, column] == " "])
176+
return not len(df[df.iloc[:, column] == self.svars["flag_symbol"]["uncheck"]])
177+
178+
def all_checked_update(self, column = 0):
179+
if column:
180+
self.svars['check_all'][column].set(self.is_all_checked(column))
181+
else:
182+
for i in range(1,len(self.cget("columns"))):
183+
self.svars['check_all'][i].set(self.is_all_checked(i))
184+
self.all_checked_event_evoke()
174185

175186
def filter_widget(self, parent):
176187
widget_frame = ttk.Frame(parent, width=150, borderwidth=1, relief="solid", padding=(2, 2))
@@ -184,12 +195,14 @@ def apply_filter():
184195
if len(self.filtered_df) == len(self.df):
185196
self.filtered_df = pd.DataFrame()
186197
self.filter_event_evoke()
198+
self.all_checked_update()
187199

188200
def clear_filter():
189201
self.rebuild_tree()
190202
filter_entry.delete(0, tk.END)
191203
self.filtered_df = pd.DataFrame()
192204
self.filter_event_evoke()
205+
self.all_checked_update()
193206

194207
self.render(ttk.Button(widget_frame, text="Filter", command=apply_filter),
195208
dict(row=0, column=2, padx=5, pady=5))
@@ -199,16 +212,16 @@ def clear_filter():
199212

200213
def checkbox_widget(self, parent):
201214

202-
def toggle_all(ind):
203-
checked = self.svars['check_all'][ind].get()
215+
def toggle_all(index: int):
216+
checked = self.svars['check_all'][index].get()
204217
if not checked:
205-
self.svars['check_all'][ind].set(False)
218+
self.svars['check_all'][index].set(False)
206219
for item in self.get_children():
207220
values = list(self.item(item, "values"))
208221
if checked:
209-
values[ind] = self.svars['flag_symbol']['check']
222+
values[index] = self.svars['flag_symbol']['check']
210223
else:
211-
values[ind] = self.svars['flag_symbol']['uncheck']
224+
values[index] = self.svars['flag_symbol']['uncheck']
212225
self.item(item, values=values)
213226

214227
widget_frame = ttk.Frame(parent, padding=(2, 2))
@@ -256,7 +269,9 @@ def __init__(self, render_params=None, *args, **options):
256269
self.frame1 = ttk.Frame(self, width=100, borderwidth=1, relief="solid", padding=(2, 2))
257270
self.tree = TreeviewDataFrame(self.frame1, columns=("table", "export", "data"), show="headings")
258271
self.tree.bind("<<TreeFilterUpdated>>", self.on_filter_updated)
272+
self.tree.bind("<<TreeCheckAllUpdated>>", self.on_check_all_updated)
259273
self.tree.bind("<<TreeToggleCell>>", self.on_toggle_cell)
274+
260275
self.scrollbar = ttk.Scrollbar(self.frame1, orient="vertical", command=self.tree.yview)
261276
self.tree.configure(yscrollcommand=self.scrollbar.set)
262277
self.create_widgets()
@@ -285,15 +300,6 @@ def recreate_widgets(self):
285300
self.render(self.tree.checkbox_widget(self.frame0),
286301
dict(row=4, column=0, columnspan=3, padx=5, pady=5, sticky="e"))
287302

288-
# self.render(tk.Label(self.frame0, text=" ", width=43),
289-
# dict(row=1, column=0, columnspan=2, pady=5))
290-
# self.svars['check_all'] = tk.IntVar(value=0)
291-
# self.render(ttk.Checkbutton(self.frame0, text="Check all to Export", variable=self.svars['check_all'],
292-
# command=self.toggle_all_export), dict(row=1, column=2, padx=20))
293-
# self.svars['check_all_upload'] = tk.IntVar(value=0)
294-
# self.render(ttk.Checkbutton(self.frame0, text="Check all to Upload", variable=self.svars['check_all_upload'],
295-
# command=self.toggle_all_upload, ), dict(row=1, column=3, padx=20))
296-
297303
def make_tree(self):
298304
self.tree.heading("table", text="Table")
299305
self.tree.heading("export", text="Export Table")
@@ -312,50 +318,26 @@ def make_tree(self):
312318
)
313319
style.configure("Treeview", rowheight=25)
314320
self.tree.tag_configure("normal")
315-
self.tree.tag_configure("export", background="#fff0f0")
321+
self.tree.tag_configure("selected", background="#fff0f0")
316322

317-
def update_data_column(self):
323+
def update_column_style(self):
318324
"""..."""
319325
for item_id in self.tree.get_children():
320-
if self.tree.set(item_id, "export") == "✔":
321-
self.tree.item(item_id, tags=("export",))
326+
if "✔" in self.tree.item(item_id, "values"):
327+
self.tree.item(item_id, tags=("selected",))
322328
else:
323329
self.tree.item(item_id, tags=("normal",))
324330

325331
def on_filter_updated(self, event):
326-
self.svars['check_all'].set(self.tree.all_checked(1))
327-
self.svars['check_all_upload'].set(self.tree.all_checked(2))
332+
pass
333+
334+
def on_check_all_updated(self, event):
335+
self.update_column_style()
328336

329337
def on_toggle_cell(self, event):
330338
"""Handles cell clicks to change flags."""
331-
self.update_data_column()
332-
# self.svars['check_all'].set(self.tree.all_checked(1))
333-
# self.svars['check_all_upload'].set(self.tree.all_checked(2))
334-
335-
def toggle_all_export(self):
336-
checked = self.svars['check_all'].get()
337-
if not checked:
338-
self.svars['check_all_upload'].set(False)
339-
for item in self.tree.get_children():
340-
values = list(self.tree.item(item, "values"))
341-
if checked:
342-
values[1] = "✔"
343-
else:
344-
values[1] = " "
345-
values[2] = " "
346-
self.tree.item(item, values=values)
347-
348-
def toggle_all_upload(self):
349-
checked = self.svars['check_all_upload'].get()
350-
for item in self.tree.get_children():
351-
values = list(self.tree.item(item, "values"))
352-
if checked:
353-
values[2] = "✔" if values[1] == "✔" else " "
354-
else:
355-
values[2] = " "
356-
self.tree.item(item, values=values)
357-
if not self.svars['check_all'].get():
358-
self.svars['check_all_upload'].set(False)
339+
self.update_column_style()
340+
359341

360342
def btn_run(self):
361343
"""

0 commit comments

Comments
 (0)