11import tkinter as tk
2+ from tkinter import ttk , filedialog , messagebox
23import webbrowser
3- from tkinter import filedialog , messagebox
4- from tkinter import ttk
5-
64import pandas as pd
75import 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