def Tabella(master): if len(GLOBE.titolo) == 0: return righe = len(list(GLOBE.titolo.keys())) colonne = len(list(GLOBE.titolo.get(list(GLOBE.titolo.keys())[0]).keys())) - 1 tabella = Sheet(master, data = [[f"Row {r}, Column {c}" for c in range(colonne)] for r in range(righe)], height = 400, width = 1550) tabella.headers((f"Header{c}" for c in range(colonne))) key_titolo = list(GLOBE.titolo.keys()) key_isin = GLOBE.titolo.get(key_titolo[0]).keys() header = list(key_isin) index = 0 for i in header: #mi crea gli header della tabella tabella.headers(i.capitalize(), index) # tabella.column_width(column = index, width = 150) index = index + 1 if index == colonne: break for j in range(len(key_titolo)): #mi riempe le celle della tabella for k in range(len(header) - 1): tabella.set_cell_data(j, k, value = GLOBE.titolo.get(key_titolo[j]).get(header[k])) tabella.set_all_cell_sizes_to_text() tabella.grid(row = 0, column = 0, sticky = "nswe")
class CustomizedSheet(Tk): def __init__(self, records, headers, title, rows=None): Tk.__init__(self) self.title(title) self.state("zoomed") self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.data = [["Row {r} Column {c}" for c in range(100)] for r in range(5000)] self.sdem = Sheet(self, width=1000, height=700, align="w", header_align="center", row_index_align="center", show=True, column_width=230, row_index_width=50, data_reference=records, headers=headers) self.sdem.enable_bindings( ("single", "drag_select", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize")) self.sdem.edit_bindings(True) self.sdem.grid(row=0, column=0, sticky="nswe") if rows is not None: for row_no in rows: for col in range(0, len(headers)): self.sdem.highlight_cells(row=row_no, column=col, bg="#EC7063", fg="black")
class demo(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.grid_columnconfigure(0, weight = 1) self.grid_rowconfigure(0, weight = 1) self.frame = tk.Frame(self) self.frame.grid_columnconfigure(0, weight = 1) self.frame.grid_rowconfigure(0, weight = 1) self.sheet = Sheet(self.frame, data = [[f"Row {r}, Column {c}\nnewline1\nnewline2" for c in range(50)] for r in range(500)]) self.sheet.enable_bindings() self.frame.grid(row = 0, column = 0, sticky = "nswe") self.sheet.grid(row = 0, column = 0, sticky = "nswe")
def auto_organize_dialog(self, moved_files): # noqa dialog = Dialogs.create_dialog( on_close_callback=self.on_auto_organize_dialog_close, title='Auto Organize') label = tk.Label( dialog, text='Following files were moved / renamed -', ) label.grid(row=0, column=0, sticky='w', ipadx=10, ipady=10) dialog.columnconfigure(0, weight=1) # show a dialog with the output. sheet = Sheet( Dialogs.dialog, header_font=(self.header_font, self.header_font_size, "bold"), font=(self.content_font, self.content_font_size, "normal"), align='w', row_height="1", # str value for row height in number of lines. row_index_align="w", auto_resize_default_row_index=False, row_index_width=40, header_align='center', empty_horizontal=0, empty_vertical=0, ) sheet.headers(['Source', '', 'Destination']) target_parent = os.path.dirname(self.impartus.download_dir) for row, (source, destination) in enumerate(moved_files.items()): source = source[len(target_parent) + 1:] destination = destination[len(target_parent) + 1:] sheet.insert_row([source, Icons.MOVED_TO, destination]) sheet.set_all_column_widths() sheet.grid(row=1, column=0, sticky='nsew') ok_button = tk.Button(dialog, text='OK', command=self.on_auto_organize_dialog_close) ok_button.grid(row=2, column=0, padx=10, pady=10)
class SheetTable(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.state("zoomed") self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.sheet_demo = Sheet(self, width=1000, height=700, align="w", header_align="center", row_index_align="center", column_width=180, row_index_width=50, total_rows=5000, total_columns=100, headers=[f"Header {c}" for c in range(100)]) self.sheet_demo.enable_bindings( ("single", "drag_select", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "edit_bindings")) self.sheet_demo.grid(row=0, column=0, sticky="nswe") self.sheet_demo.highlight_cells(row=0, column=0, bg="orange", fg="blue") self.sheet_demo.highlight_cells(row=0, bg="orange", fg="blue", canvas="row_index") self.sheet_demo.highlight_cells(column=0, bg="orange", fg="blue", canvas="header") """_________________________ EXAMPLES _________________________ """ """_____________________________________________________________"""
class edit_oder_demo(tk.Tk): def __init__(self, oid): # oid will be set in edit_order() function in crud_main_window.py to be called from fill_data_from_db() self.oid = oid tk.Tk.__init__(self) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.frame = tk.Frame(self) self.fill_data_from_db() self.frame.grid_columnconfigure(0, weight=1) self.frame.grid_rowconfigure(0, weight=1) self.sheet = Sheet( self.frame, page_up_down_select_row=True, # empty_vertical = 0, column_width=120, startup_select=(0, 1, "rows"), headers=headers, data=data, height=500, # height and width arguments are optional width=550, # For full startup arguments see DOCUMENTATION.md ) self.sheet.enable_bindings(( "single_select", # "single_select" or "toggle_select" "drag_select", # enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", # "row_width_resize", # "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", # "rc_insert_column", # "rc_delete_column", "rc_insert_row", "rc_delete_row", # "hide_columns", "copy", # "cut", # "paste", # "delete", "undo", "edit_cell")) self.frame.grid(row=0, column=0, sticky="nswe") self.sheet.grid(row=0, column=0, sticky="nswe") # __________ DISPLAY SUBSET OF COLUMNS __________ # self.sheet.display_subset_of_columns(indexes=[0, 1, 2], enable=True) # __________ BINDING A FUNCTIONS TO USER ACTIONS __________ self.sheet.extra_bindings([ ("end_edit_cell", self.end_edit_cell), ("begin_rc_delete_row", self.row_delete), ("end_insert_row", self.end_insert_row), ]) # __________ GETTING FULL SHEET DATA __________ # self.all_data = self.sheet.get_sheet_data() # __________ GETTING CELL DATA __________ # print (self.sheet.get_cell_data(0, 0)) # __________ GETTING ROW DATA __________ # print (self.sheet.get_row_data(0)) # only accessible by index # __________ GETTING COLUMN DATA __________ # print (self.sheet.get_column_data(0)) # only accessible by index def end_insert_row(self, event): print("cell inserted") try: oi = ORDERITEM(**{'oid': self.oid}) db_session.add(oi) db_session.commit() self.sheet.set_cell_data(event[1], 1, value=self.oid) self.sheet.set_cell_data(event[1], 0, value=oi.iid) self.sheet.dehighlight_rows(rows=[event[0]]) except Exception as e: self.sheet.highlight_rows(rows=[event[0]], fg='red', bg='red') e.with_traceback() def end_edit_cell(self, event): print("cell edited") ORDERITEM.query.filter_by(**{ "iid": self.sheet.get_cell_data(event[0], 0) }).update( {headers[event[1]]: self.sheet.get_cell_data(event[0], event[1])}) db_session.commit() def row_delete(self, event): print("row deleted") print({"iid": self.sheet.get_cell_data(event[1][0], 0)}) ORDERITEM.query.filter_by( **{ "iid": self.sheet.get_cell_data(event[1][0], 0) }).delete() db_session.commit() def fill_data_from_db(self): data.clear() ois = ORDERITEM.query.filter_by(oid=self.oid) k = [[ i.to_dict(rules=('-ORDER1', '-PRODUCT')).get(z) or 0 for z in headers ] for i in ois] data.extend(k)
text1 = Text(frame1) registerGUIElement('text1', text1) text1.grid(row=0, column=0) fs1 = FontSelect(frame1) registerGUIElement('fs1', fs1) fs1.grid(row=0, column=1) tv1 = ttk.Treeview(frame1, columns=['header1', 'header2', 'header3', 'header4']) registerGUIElement('tv1', tv1) tv1.grid(row=0, column=2) sheet1 = Sheet(frame1, data=[['No data']], headers=['Sin Encabezados']) registerGUIElement('sheet1', sheet1) sheet1.grid(row=1, column=0) chk1 = Checkbutton(frame1, text='Check me if you can!!') registerGUIElement('chk1', chk1) chk1_var = IntVar() chk1.config(variable=chk1_var) chk1.grid(row=1, column=1) scale1 = Scale(frame1, from_=0, to=50) registerGUIElement('scale1', scale1) scale1_var = DoubleVar() scale1.config(variable=scale1_var) scale1.grid(row=1, column=2) list1 = ScrollableListbox(frame1, 1,
class columnselection(tk.Frame): def __init__(self,parent,C): tk.Frame.__init__(self,parent) self.C = C self.parent_cols = [] self.rowlen = 0 self.grid_rowconfigure(0,weight=1) self.grid_rowconfigure(1,weight=1) self.grid_columnconfigure(1,weight=1) self.flattened_choices = flattened_base_ids_choices(self,command=self.flattened_mode_toggle) self.flattened_choices.grid(row=1,column=0,pady=(0,5),sticky="wnse") self.flattened_selector = flattened_column_selector(self) self.selector = id_and_parent_column_selector(self) self.selector.grid(row=1,column=0,sticky="wnse") self.sheetdisplay = Sheet(self, theme = self.C.theme, header_font = ("Calibri", 13, "normal"), outline_thickness=1) self.sheetdisplay.enable_bindings("enable_all") self.sheetdisplay.extra_bindings([("row_index_drag_drop", self.drag_row), ("column_header_drag_drop", self.drag_col), ("ctrl_x", self.reset_selectors), ("delete_key", self.reset_selectors), ("rc_delete_column", self.reset_selectors), ("rc_delete_row", self.reset_selectors), ("rc_insert_column", self.reset_selectors), ("rc_insert_row", self.reset_selectors), ("ctrl_v", self.reset_selectors), ("ctrl_z", self.reset_selectors), ("edit_cell", self.edit_cell_in_sheet) ]) self.sheetdisplay.grid(row=0,column=1,rowspan=3,sticky="nswe") self.cont_ = button(self, text="Build tree with selections ", style="TF.Std.TButton",command=self.try_to_build_tree) self.cont_.grid(row=2,column=0,sticky="wns",padx=10,pady=(10, 50)) self.cont_.config(width=40) self.flattened_selector.grid(row=0,column=0,pady=(0,9),sticky="nswe") self.selector.grid_forget() self.selector.grid(row=0,column=0,sticky="nswe") self.flattened_selector.grid_forget() def flattened_mode_toggle(self): x = self.flattened_choices.get_choices()[0] if x: self.flattened_selector.grid(row=0,column=0,pady=(0,9),sticky="nswe") self.selector.grid_forget() else: self.selector.grid(row=0,column=0,sticky="nswe") self.flattened_selector.grid_forget() def drag_col(self, event): colsiter = sorted(event[1]) c = event[3] stins = colsiter[0] endins = colsiter[-1] + 1 self.selector.set_columns([h for h in self.sheetdisplay.get_sheet_data()[0]]) self.flattened_selector.set_columns([h for h in self.sheetdisplay.get_sheet_data()[0]]) self.selector.detect_id_col() self.selector.detect_par_cols() def drag_row(self, event): rowsiter = sorted(event[1]) r = event[3] stins = rowsiter[0] endins = rowsiter[-1] + 1 self.selector.set_columns([h for h in self.sheetdisplay.get_sheet_data()[0]]) self.flattened_selector.set_columns([h for h in self.sheetdisplay.get_sheet_data()[0]]) self.selector.detect_id_col() self.selector.detect_par_cols() def reset_selectors(self, event = None): idcol = self.selector.get_id_col() parcols = self.selector.get_par_cols() ancparcols = self.flattened_selector.get_par_cols() self.selector.set_columns([h for h in self.sheetdisplay.get_sheet_data()[0]] if self.sheetdisplay.get_sheet_data() else []) self.flattened_selector.set_columns([h for h in self.sheetdisplay.get_sheet_data()[0]] if self.sheetdisplay.get_sheet_data() else []) try: if idcol is not None and self.sheetdisplay.get_sheet_data(): self.selector.set_id_col(idcol) except: pass try: if parcols and self.sheetdisplay.get_sheet_data(): self.selector.set_par_cols(parcols) except: pass try: if ancparcols and self.sheetdisplay.get_sheet_data(): self.flattened_selector.set_par_cols(ancparcols) except: pass def edit_cell_in_sheet(self, event = None): idcol = self.selector.get_id_col() parcols = self.selector.get_par_cols() ancparcols = self.flattened_selector.get_par_cols() if event[1] == idcol or event[1] in parcols or event[1] in ancparcols or event[0] == 0: self.reset_selectors() def enable_widgets(self): self.selector.enable_me() self.flattened_selector.enable_me() self.flattened_choices.enable_me() self.cont_.config(state="normal") self.sheetdisplay.basic_bindings(True) self.sheetdisplay.enable_bindings("enable_all") self.sheetdisplay.extra_bindings([("row_index_drag_drop", self.drag_row), ("column_header_drag_drop", self.drag_col), ("ctrl_x", self.ctrl_x_in_sheet), ("delete_key", self.del_in_sheet), ("rc_delete_column", self.del_in_sheet), ("rc_delete_row", self.del_in_sheet), ("rc_insert_column", self.reset_selectors), ("rc_insert_row", self.reset_selectors), ("ctrl_v", self.ctrl_v_in_sheet), ("ctrl_z", self.ctrl_z_in_sheet), ("edit_cell", self.edit_cell_in_sheet) ]) def disable_widgets(self): self.selector.disable_me() self.flattened_selector.disable_me() self.flattened_choices.disable_me() self.cont_.config(state="disabled") self.sheetdisplay.basic_bindings(False) self.sheetdisplay.disable_bindings("disable_all") self.sheetdisplay.extra_bindings("unbind_all") self.sheetdisplay.unbind("<Delete>") def populate(self, columns, non_tsrgn_xl_file = False): self.sheetdisplay.deselect("all") self.non_tsrgn_xl_file = non_tsrgn_xl_file self.rowlen = len(columns) self.selector.set_columns([h for h in self.C.treeframe.sheet[0]]) self.flattened_selector.set_columns([h for h in self.C.treeframe.sheet[0]]) self.C.treeframe.sheet = self.sheetdisplay.set_sheet_data(data = self.C.treeframe.sheet, redraw=True) self.sheetdisplay.headers(newheaders=0) if len(self.C.treeframe.sheet) < 3000: self.sheetdisplay.set_all_cell_sizes_to_text() self.selector.detect_id_col() self.selector.detect_par_cols() self.flattened_selector.detect_par_cols() self.C.show_frame("columnselection") def try_to_build_tree(self): baseids, order, delcols = self.flattened_choices.get_choices() if baseids: hiers = list(self.flattened_selector.get_par_cols()) if len(hiers) < 2: return else: hiers = list(self.selector.get_par_cols()) if not hiers: return idcol = self.selector.get_id_col() if idcol in hiers or idcol is None: return self.C.status_bar.change_text("Loading... ") self.C.disable_at_start() self.C.treeframe.sheet = self.sheetdisplay.get_sheet_data() if baseids: if order == "Order: Base → Top": idcol = hiers.pop(0) elif order == "Order: Top → Base": idcol = hiers.pop(len(hiers) - 1) self.C.treeframe.sheet[:] = [row + list(repeat("",self.rowlen - len(row))) if len(row) < self.rowlen else row for row in self.C.treeframe.sheet] self.C.treeframe.sheet, self.rowlen, idcol, newpc = self.C.treeframe.treebuilder.convert_flattened_to_normal(data = self.C.treeframe.sheet, idcol = idcol, parcols = hiers, rowlen = self.rowlen, order = order, delcols = delcols, warnings = self.C.treeframe.warnings) hiers = [newpc] self.C.treeframe.headers = [Header(name) for name in self.C.treeframe.fix_heads(self.C.treeframe.sheet.pop(0),self.rowlen)] self.C.treeframe.ic = idcol self.C.treeframe.hiers = hiers self.C.treeframe.pc = hiers[0] self.C.treeframe.row_len = int(self.rowlen) self.C.treeframe.set_metadata(headers = True) self.C.treeframe.sheet, self.C.treeframe.nodes, self.C.treeframe.warnings = self.C.treeframe.treebuilder.build(self.C.treeframe.sheet, self.C.treeframe.new_sheet, self.C.treeframe.row_len, self.C.treeframe.ic, self.C.treeframe.hiers, self.C.treeframe.nodes, self.C.treeframe.warnings) self.C.treeframe.populate(non_tsrgn_xl_file = self.non_tsrgn_xl_file) self.C.treeframe.show_warnings(str(self.C.open_dict['filepath']),str(self.C.open_dict['sheet']))
def set_display_widgets(self, subjects, root_url, anchor): """ Create the table/sheet. Fill in the data for table content, Set the buttons and their states. """ cs = self.colorscheme sheet = Sheet( anchor, frame_bg=cs['table']['bg'], table_bg=cs['table']['bg'], table_fg=cs['table']['fg'], table_grid_fg=cs['table']['grid'], top_left_bg=cs['header']['bg'], top_left_fg=cs['header']['bg'], header_bg=cs['header']['bg'], header_fg=cs['header']['fg'], header_font=(self.conf.get("content_font"), 12, "bold"), font=(self.conf.get('content_font'), 14, "normal"), align='center', header_grid_fg=cs['table']['grid'], index_grid_fg=cs['table']['grid'], header_align='center', empty_horizontal=0, empty_vertical=0, header_border_fg=cs['table']['grid'], index_border_fg=cs['table']['grid'], ) self.sheet = sheet sheet.enable_bindings( ("single_select", "column_select", "column_width_resize", "row_height_resize", "rc_select")) self.set_headers() indexes = [x for x, v in self.columns.items() if v['show']] sheet.display_columns(indexes=indexes, enable=True) anchor.columnconfigure(0, weight=1) anchor.rowconfigure(0, weight=1) row = 0 for subject in subjects: videos = self.impartus.get_videos(root_url, subject) slides = self.impartus.get_slides(root_url, subject) video_slide_mapping = self.impartus.map_slides_to_videos( videos, slides) videos = {x['ttid']: x for x in videos} for ttid, video_metadata in videos.items(): video_metadata = Utils.add_fields(video_metadata, video_slide_mapping) video_metadata = Utils.sanitize(video_metadata) video_path = self.impartus.get_mkv_path(video_metadata) slides_path = self.impartus.get_slides_path(video_metadata) video_exists = os.path.exists(video_path) slides_exist = video_slide_mapping.get(ttid) slides_exist_on_disk, slides_path = self.impartus.slides_exist_on_disk( slides_path) metadata = { 'video_metadata': video_metadata, 'video_path': video_path, 'video_exists': video_exists, 'slides_exist': slides_exist, 'slides_exist_on_disk': slides_exist_on_disk, 'slides_url': video_slide_mapping.get(ttid), 'slides_path': slides_path, } row_items = list() button_states = list() for col, item in self.columns.items(): text = '' if item['type'] == 'auto': text = row if item['type'] == 'data': text = video_metadata[item['mapping']] # title case text = text.strip().title() if item.get( 'title_case') else text # truncate long fields if item['truncate'] and len(text) > self.conf.get( 'max_content_chars'): text = '{}..'.format( text[0:self.conf.get('max_content_chars')]) elif item['type'] == 'progressbar': value = 100 if video_exists else 0 text = self.progress_bar_text(value) elif item['type'] == 'button': button_states.append( self.get_button_state(self.names[col], video_exists, slides_exist, slides_exist_on_disk)) text = item.get('text') elif item['type'] == 'state': text = button_states.pop(0) elif item['type'] == 'metadata': text = metadata row_items.append(text) sheet.insert_row(values=row_items, idx='end') row += 1 self.reset_column_sizes() self.decorate() sheet.extra_bindings('column_select', self.sort_table) sheet.extra_bindings('cell_select', self.on_click_button_handler) # update button status self.set_button_status() sheet.grid(row=0, column=0, sticky='nsew')
class EmailTab(tk.Frame): def __init__(self, master): self.emailHandler = EmailSheetHandler(FILENAME) tk.Frame.__init__(self, master) self.grid_columnconfigure(0, weight = 1) self.grid_rowconfigure(0, weight = 1) self.frame = ttk.Frame(self, height=450, width=400) self.frame.grid_columnconfigure(0, weight = 1) self.frame.grid_rowconfigure(0, weight = 1) self.sheet = Sheet(self.frame, page_up_down_select_row = True, #empty_vertical = 0, column_width = 300, startup_select = (0,1,"rows"), data=self.populate_sheet(), total_columns = 3, #if you want to set empty sheet dimensions at startup height = 450, #height and width arguments are optional width = 600 #For full startup arguments see DOCUMENTATION.md ) self.sheet.enable_bindings(("single_select", #"single_select" or "toggle_select" "drag_select", #enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "edit_cell")) self.sheet.extra_bindings("end_edit_cell", self.end_edit_cell) self.frame.grid(row = 0, column = 0, sticky = "nsw") self.sheet.grid(row = 0, column = 0, sticky = "nw") self.email_button_frame = ttk.Frame(self.frame, padding=(3,3,12,12), borderwidth=5, width=100, heigh=200) self.email_add_button = tk.Button(self.email_button_frame, text="Add email", command=self.add_email) self.email_merge_button = tk.Button(self.email_button_frame, text="Merge email (with file)", command=self.merge_mails) self.email_update_button = tk.Button(self.email_button_frame, text="Update file with table", command=self.email_file_update ) self.email_button_frame.grid(row=0, column=2, sticky="nswe") self.email_add_button.grid(row=1, column=1) self.email_merge_button.grid(row=2, column=1) self.email_update_button.grid(row=3, column=1) # print(self.sheet.get_sheet_data(get_index=0, get_header=0)) def end_edit_cell(self, event): print(event) print(self.sheet.get_cell_data(event[0], event[1 ])) def add_email(self): package = [] AddDialogue(package, "Add Email", "Add Email") print("Rsult: ", package) self.emailHandler.append_to_file(package) self.update_table() def email_file_update(self): self.emailHandler.update_email_file(self.sheet.get_sheet_data()) def update_table(self): data = self.populate_sheet() self.sheet.set_sheet_data(data) def merge_mails(self): file = filedialog.askopenfile().name print(file) # TODO: handle merge print(self.emailHandler.validate(file)) def populate_sheet(self): self.data = [] try: with open(FILENAME, 'r') as f: L = f.readlines() self.data = [i.strip("\n").split(",") for i in L] # for i in self.data: i.append("50") return self.data except FileNotFoundError: return self.data
def start_gui(hostname, total_mem, patterns): global combo_pattern, root_window, sheet_proc, sheet_proc_last_row, proc_mem_plot global root_window ############################################################################### # root window ############################################################################### root_window = tk.Tk() root_window.geometry('1200x400+20+20') root_window.title('Process Memory Monitor ' + VERSION + ' - ' + hostname) root_window_icon = tk.PhotoImage(file=str(__icon__)) root_window.iconphoto(True, root_window_icon) root_window.grid_columnconfigure(0, weight=0) root_window.grid_columnconfigure(1, weight=0) root_window.grid_columnconfigure(2, weight=0) root_window.grid_columnconfigure(3, weight=1) cur_grid_row = 0 label_pattern = ttk.Label(root_window, text="Command Pattern", width=LABEL_WIDTH, anchor='w') label_pattern.grid(row=cur_grid_row, column=0, sticky='w', padx=10, pady=10) combo_pattern = ttk.Combobox(root_window, width=COMBO_WIDTH) combo_pattern['values'] = [] combo_pattern.grid(row=cur_grid_row, column=1, sticky='w', pady=10) cur_grid_row = cur_grid_row + 1 # sheet for pattern sheet_proc = Sheet(root_window, default_row_index="numbers", total_rows=200, total_columns=5) sheet_proc.enable_bindings(( "single_select", # "single_select" or "toggle_select" "drag_select", # enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", #"column_select", "row_select", "column_width_resize", "double_click_column_resize", "arrowkeys", #"row_height_resize", #"double_click_row_resize", "right_click_popup_menu", "rc_select", #"rc_insert_column", #"rc_delete_column", #"rc_insert_row", #"rc_delete_row", "copy", "cut", "paste", "delete", "undo", "edit_cell")) sheet_proc.grid(row=cur_grid_row, columnspan=4, sticky='nswe') root_window.grid_rowconfigure(cur_grid_row, weight=1) sheet_proc.set_cell_data(0, SHEET_PID_COL, 'PID') sheet_proc.set_cell_data(0, SHEET_CPU_COL, '%CPU') sheet_proc.set_cell_data(0, SHEET_RSS_COL, 'RSS(GB)') sheet_proc.set_cell_data(0, SHEET_CMD_COL, 'CMD') sheet_proc.set_cell_data(0, SHEET_LAST_UPDATED_COL, 'Last Updated') sheet_proc.column_width(column=SHEET_PID_COL, width=150) sheet_proc.column_width(column=SHEET_CPU_COL, width=100) sheet_proc.column_width(column=SHEET_RSS_COL, width=100) sheet_proc.column_width(column=SHEET_CMD_COL, width=450) sheet_proc.column_width(column=SHEET_LAST_UPDATED_COL, width=200) cur_grid_row = cur_grid_row + 1 sheet_proc_last_row = 0 # command buttons button_plot = ttk.Button(root_window, text="Plot", command=show_plot_window) button_plot.grid(row=cur_grid_row, column=1, pady=10) cur_grid_row = cur_grid_row + 1 proc_mem_plot = ProcMemPlot(hostname) proc_mem_plot.total_mem = total_mem combo_pattern['values'] = patterns if len(patterns) > 0: combo_pattern.current(0) root_window.after(DEFAULT_REFRESH_INTERVAL * 1000, refresh_database) root_window.mainloop()
class TechnicianScreen(design.Page): def __init__(self, app, root, id, *args, **kwargs): design.Page.__init__(self, app, root, *args, **kwargs) self.height = 600 self.width = 1050 self.id = id self.status = [] self.title = "Technician schedule" self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) #self.configure(bg="white") self.cols = pd.read_csv("techissue.csv") self.cols = self.cols.loc[self.cols.ID == self.id, :] self.Cols = self.cols[[ "ID", "customerName", "product", "issue", "location", "crit", "issueID" ]] self.row_count = len(self.cols) #print(self.row_coun t) self.data = [self.Cols.iloc[i] for i in range(self.row_count)] labelTop = tk.Label(self, text="Issue status", font=('Times New Roman', 14)) labelTop.grid(column=0, row=0) labelTop.place(relx=0.830, rely=0.075) for i in range(self.row_count): self.var = tk.StringVar() if self.cols.iloc[i, 5] == "**": self.comboExample = ttk.Combobox( self, textvariable=self.var, values=["treated", "not treated", "becomes normal"]) if self.cols.iloc[i, 5] == "*": self.comboExample = ttk.Combobox( self, textvariable=self.var, values=["treated", "not treated"]) self.status.append(self.var) self.comboExample.grid(column=0, row=i + 1) self.comboExample.place(relx=0.830, rely=0.120 + (i * 0.04), relheight=0.04, relwidth=0.140) self.comboExample.current(1) self.sdem = Sheet( self, align="w", header_align="center", row_index_align="center", show=True, column_width=140, row_index_width=50, data_reference=self.data, headers=[ "ID", "customerName", "product", "issue", "location", "crit", "issueID" ], ) self.sdem.enable_bindings( ("single", "drag_select", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize")) self.sdem.edit_bindings(True) self.sdem.grid(row=0, column=0, sticky="nswe") self.sdem.place(relx=0.05, rely=0.067, relheight=0.751, relwidth=0.780) self.sdem.highlight_cells(row=0, column=0, bg="orange", fg="blue") self.sdem.highlight_cells(row=0, bg="orange", fg="blue", canvas="row_index") self.sdem.highlight_cells(column=0, bg="orange", fg="blue", canvas="header") self.send = Button(self, text="send", font=('Times New Roman', 15), bg='orange', fg='blue', padx=5, command=self.save).place(relx=0.880, rely=0.85) def save(self): self.dff = pd.read_csv("customerissue.csv") count1 = len(self.dff) for i in range(self.row_count): if self.status[i].get() == "treated": for j in range(count1): if self.dff.iloc[j]["ID"] == self.cols.iloc[i]["issueID"]: self.dff.iat[j, 5] = "2" if self.status[i].get() == "not treated": for j in range(count1): if self.dff.iloc[j]["ID"] == self.cols.iloc[i]["issueID"]: self.dff.iat[j, 5] = "0" self.dff.to_csv('customerissue.csv', mode='w', index=False, header=[ "name", "product", "issue", "place", "time", "taken", "coordinate", "ID" ]) self.df = pd.read_csv("techissue.csv") count = len(self.df) self.df = self.df.loc[self.df.ID != self.id, :] self.df.to_csv('techissue.csv', mode='w', index=False, header=[ "ID", "customerName", "product", "issue", "location", "crit", "issueID" ]) print(self.dff) print(self.df) print("")
def __init__(self, customer_id, account_id=False): self.customer_id = customer_id """ Window Configuration """ self.transroot = Tk() self.window_height = 700 #Window Height self.window_width = 1100 #Window Width self.screen_width = self.transroot.winfo_screenwidth() #Screen Width self.screen_height = self.transroot.winfo_screenheight() #Screen Height self.x_cordinate = int((self.screen_width/2) - (self.window_width/2)) self.y_cordinate = int((self.screen_height/2) - (self.window_height/2)) self.transroot.geometry("{}x{}+{}+{}".format(self.window_width, self.window_height, self.x_cordinate, 5)) #Implement and Center Window based on Device Screen self.transroot.config(bg='#00bd56') #Window Background self.transroot.overrideredirect(True) #Remove Window Status Bar self.transroot.resizable(False, False) #Disable Resizing Window """ Image Declaration """ imgTambah = PhotoImage(file='tampilan/images/tambah-btn.png') imgTampil = PhotoImage(file='tampilan/images/tampil-btn.png') imgExit = PhotoImage(file='tampilan/images/exit-btn.png') #Dashboard Icon Navbar dashimage = Image.open('tampilan/images/dashboard.png') dashImage = dashimage.resize((38, 38), Image.ANTIALIAS) dashboardIMG = ImageTk.PhotoImage(dashImage) #Account Icon Navbar checkImg = Image.open('tampilan/images/checkingicon.png') chImage = checkImg.resize((35, 35), Image.ANTIALIAS) accountImage = ImageTk.PhotoImage(chImage) #Transaction Icon Navbar saveImg = Image.open('tampilan/images/transfer.png') sImage = saveImg.resize((30, 30), Image.ANTIALIAS) transImage = ImageTk.PhotoImage(sImage) #Logout Icon Navbar logoutImg = Image.open('tampilan/images/logout.png') logImage = logoutImg.resize((30, 30), Image.ANTIALIAS) logoutImage = ImageTk.PhotoImage(logImage) #Dashboard Info Background Icon Navbar cusInfoImg = Image.open('tampilan/images/info-bg.png') cInfoImg = cusInfoImg.resize((180, 180), Image.ANTIALIAS) cIImg = ImageTk.PhotoImage(cInfoImg) #Account Info siIMG = Image.open('tampilan/images/savingicon.png') ssImg = siIMG.resize((80, 80), Image.ANTIALIAS) savIMG = ImageTk.PhotoImage(ssImg) #Balance Info chIMG = Image.open('tampilan/images/checkingicon.png') chsImg = chIMG.resize((80, 80), Image.ANTIALIAS) cheIMG = ImageTk.PhotoImage(chsImg) ############################################################################## ############ SIDEBAR CONTENT ########## ############################################################################## navbarLabel = Label( self.transroot, bg='#e5e5e5', width=30, height=self.window_height ) navbarLabel.place(x=0,y=0) #Dashboard Icon Navbar dashboardNavIcon = Label( self.transroot, image=dashboardIMG, bg='#e5e5e5', cursor='hand2' ) dashboardNavIcon.place(x=15,y=25) dashboardNavIcon.bind("<Button>",self.bindingToDashboard) #Dashboard Label Navbar dashboardNavLabel = Label( self.transroot, text="DASHBOARD", font=( 'Segoe UI', 16, BOLD ), bg='#e5e5e5', fg='#23374d', cursor='hand2' ) dashboardNavLabel.place(x=55, y=25) dashboardNavLabel.bind("<Button>",self.bindingToDashboard) #Account Icon Navbar accNavIcon = Label( self.transroot, image=accountImage, bg='#e5e5e5', cursor='hand2' ) accNavIcon.place(x=15,y=80) accNavIcon.bind("<Button>",self.bindingToAccount) #Account Label Navbar accNavLabel = Label( self.transroot, text="ACCOUNT", font=( 'Segoe UI', 16, BOLD ), bg='#e5e5e5', fg='#23374d', cursor='hand2' ) accNavLabel.place(x=55, y=80) accNavLabel.bind("<Button>",self.bindingToAccount) #Transaction Icon Navbar transNavIcon = Label( self.transroot, image=transImage, bg='#e5e5e5', cursor='hand2' ) transNavIcon.place(x=15,y=140) transNavIcon.bind("<Button>",self.bindingToTranscation) #Transaction Label Navbar transNavLabel = Label( self.transroot, text="TRANSACTION", font=( 'Segoe UI', 16, BOLD ), bg='#e5e5e5', fg='#23374d', cursor='hand2' ) transNavLabel.place(x=55, y=140) transNavLabel.bind("<Button>",self.bindingToTranscation) #Logout Icon Navbar logoutNavIcon = Label( self.transroot, image=logoutImage, bg='#e5e5e5', cursor='hand2' ) logoutNavIcon.place(x=10,y=650) logoutNavIcon.bind("<Button>",self.doLogout) #Logout Label Navbar logoutNavLabel = Label( self.transroot, text="LOGOUT", font=( 'Segoe UI', 16, BOLD ), bg='#e5e5e5', fg='#23374d', cursor='hand2' ) logoutNavLabel.place(x=50, y=650) logoutNavLabel.bind("<Button>",self.doLogout) ############################################################################## ############ DASHBOARD CONTENT ########## ############################################################################## #Customer Page Title cusTitle = Label( self.transroot, text="Customer's Transaction History", font=( 'Segoe UI', 20, BOLD ), bg='#00bd56', fg='#e5e5e5' ) cusTitle.place(x =450, y=20) self.clickedAccount = StringVar() ac = Account() self.accounts = ac.getAccountsByCustomerId(self.customer_id) self.opt = [] self.opt_id = [] account_on_opt = 0 for ac in self.accounts: self.opt.append(str(ac.getType())+str(ac.getId())) self.opt_id.append(ac.getId()) accountOption = self.opt if account_id!=False: optidx = self.opt_id.index(account_id) else: optidx = 0 self.clickedAccount.set(self.opt[optidx]) # Create Dropdown menu accountType = OptionMenu( self.transroot, self.clickedAccount , *accountOption) accountType.config( width=53, height=2, font=( 'normal', 10, BOLD ) ) accountType.place(x=280,y=85) #Show Account Button Property showButton = Button( self.transroot, image=imgTampil, border=0, bg='#00bd56', activebackground='#00bd56', command=self.showTransaction, cursor='hand2' ) showButton.place(x=710, y=80) #Add Account Button Property addCButton = Button( self.transroot, image=imgTambah, border=0, bg='#00bd56', activebackground='#00bd56', command=self.addTransaction, cursor='hand2' ) addCButton.place(x=850, y=80) if account_id != False: t = DataTransaction() transactions = t.getTransactionsByAccountId(account_id) headerLabel = ["Account Id","Date/Time","Transaction Type","Amount", "Note"] if transactions != []: datas = [(str(dt.getAccountId()), str(dt.getTime()), str(dt.getType()), str(dt.getAmount()), str(dt.getNote())) for dt in transactions] else: datas = [] #Account Table frame = Frame(self.transroot) frame.grid_columnconfigure(0, weight = 1) frame.grid_rowconfigure(0, weight = 1) sheet = Sheet(frame, page_up_down_select_row = True, column_width = 120, startup_select = (0,1,"rows"), data = datas, headers = [f"{c}" for c in headerLabel], theme = "light green", height = 480, width = 700 ) sheet.enable_bindings(( "single_select", "drag_select", "select_all", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "copy", "cut", "paste", "delete", "undo" )) frame.place(x=280,y=150) sheet.grid(row = 0, column = 0, sticky = "nswe") #Exit Button Property exitButton = Button( self.transroot, image=imgExit, border=0, bg='#00bd56', activebackground='#00bd56', command=self.transroot.destroy, cursor='hand2' ) exitButton.place(x=980, y=650) self.transroot.mainloop()
class demo(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.data = [["Average Motor Stator Current", 0], ["Average Motor Phase Voltage", 0], ["Target Torque", 0], ["Motor Actual Torque ", 0], ["Steering Angle", 0], ["Proportional Speed Limit ", 0], ["Motor RPM ", 0], ["Calculated Battery Current ", 0], ["Controller Capacitor Voltage", 0], ["Throttle input ", 0], ["Motor Temp ", 0], ["Controller Temperature ", 0], ["Distance travelled ", 0], ["Forward switch ", 0], ["Reverse Switch ", 0], ["Seat Switch ", 0]] self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.frame = tk.Frame(self) self.frame.grid_columnconfigure(0, weight=1) self.frame.grid_rowconfigure(0, weight=1) self.sheet = Sheet( self.frame, page_up_down_select_row=True, #empty_vertical = 0, column_width=150, startup_select=(0, 1, "rows"), data=self.data, theme="black", height=400, #height and width arguments are optional width=360, #For full startup arguments see DOCUMENTATION.md ) self.sheet.enable_bindings(( "single_select", #"single_select" or "toggle_select" "drag_select", #enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", # "row_width_resize", # "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "hide_columns", "copy", "cut", "paste", "delete", "undo", "edit_cell")) self.frame.grid(row=0, column=0, sticky="nswe") self.sheet.grid(row=0, column=0, sticky="nswe") self.sheet.headers( (f"Header {c}" for c in range(2))) #any iterable works self.sheet.headers("CAN Data", 0) self.sheet.headers("CAN Values", 1) def all_extra_bindings(self, event): print(event) def begin_edit_cell(self, event): print(event) # event[2] is keystroke return event[ 2] # return value is the text to be put into cell edit window def end_edit_cell(self, event): print(event) def window_resized(self, event): pass #print (event) def mouse_motion(self, event): region = self.sheet.identify_region(event) row = self.sheet.identify_row(event, allow_end=False) column = self.sheet.identify_column(event, allow_end=False) print(region, row, column) def deselect(self, event): print(event, self.sheet.get_selected_cells()) def rc(self, event): print(event) def cell_select(self, response): #print (response) pass def shift_select_cells(self, response): print(response) def drag_select_cells(self, response): pass #print (response) def ctrl_a(self, response): print(response) def row_select(self, response): print(response) def shift_select_rows(self, response): print(response) def drag_select_rows(self, response): pass #print (response) def column_select(self, response): print(response) #for i in range(50): # self.sheet.create_dropdown(i, response[1], values=[f"{i}" for i in range(200)], set_value="100", # destroy_on_select = False, destroy_on_leave = False, see = False) #print (self.sheet.get_cell_data(0, 0)) #self.sheet.refresh() def shift_select_columns(self, response): print(response) def drag_select_columns(self, response): pass # print (response) def null_print(self): print("NULL Printing\n")
class Content: def __init__(self, app: tk.Tk, login: LoginForm, toolbar: Toolbar, menubar: Menubar, impartus: Impartus): self.app = app self.login = login self.toolbar = toolbar self.menubar = menubar self.impartus = impartus conf = Config.load(ConfigType.IMPARTUS) self.content_font = conf.get('content_font').get(platform.system()) self.content_font_size = conf.get('content_font_size') self.header_font = conf.get('header_font').get(platform.system()) self.header_font_size = conf.get('header_font_size') self.frame_content = None self.sheet = None self.videos = None self.video_slide_mapping = None self.expected_real_paths_differ = False self.all_captions_found = True self.offline_video_ttid_mapping = None # sort options self.sort_by = None self.sort_order = None # threads for downloading videos / slides. self.threads = None self.logger = logging.getLogger(self.__class__.__name__) def _init_content(self): if self.frame_content: self.frame_content.destroy() self.frame_content = self.add_content_frame(self.app) self.sheet = Sheet( self.frame_content, header_font=(self.header_font, self.header_font_size, "bold"), font=(self.content_font, self.content_font_size, "normal"), align='w', row_height="1", # str value for row height in number of lines. row_index_align="w", auto_resize_default_row_index=False, row_index_width=40, header_align='center', empty_horizontal=0, empty_vertical=0, ) self.sheet.enable_bindings(( "single_select", "column_select", "column_width_resize", "double_click_column_resize", "edit_cell", "copy", )) self.sheet.grid(row=0, column=0, sticky='nsew') self.set_headers() self.set_display_columns() self.frame_content.columnconfigure(0, weight=1) self.frame_content.rowconfigure(0, weight=1) self.sheet.extra_bindings('column_select', self.sort_table) self.sheet.extra_bindings('cell_select', self.on_click_button_handler) # sort options self.sort_by = None self.sort_order = None # threads for downloading videos / slides. self.threads = dict() def add_content_frame(self, anchor) -> tk.Frame: # noqa frame_content = tk.Frame(anchor, padx=0, pady=0) frame_content.grid(row=2, column=0, sticky='nsew') return frame_content def set_headers(self, sort_by=None, sort_order=None): """ Set the table headers. """ # set column title to reflect sort status headers = list() for name, value in Columns.display_columns.items(): if value.get('sortable'): if name == sort_by: sort_icon = Icons.SORT_DESC if sort_order == 'desc' else Icons.SORT_ASC else: sort_icon = Icons.UNSORTED text = '{} {}'.format(value['display_name'], sort_icon) else: text = value['display_name'] if value.get('editable'): text = '{} {}'.format(Icons.EDITABLE, text) headers.append(text) self.sheet.headers(headers) def set_display_widgets(self): """ Create the table/sheet. Fill in the data for table content, Set the buttons and their states. """ self.fetch_content() self.fill_content() def on_click_button_handler(self, args): """ On click handler for all the buttons, calls the corresponding function as defined by self.button_columns """ (event, row, col) = args real_col = self.get_real_col(col) self.sheet.highlight_rows(rows=[row], redraw=False) self.sheet.highlight_columns(columns=[col], redraw=False) # is subject field col_name = Columns.column_names[real_col] if Columns.all_columns[col_name].get('editable'): old_value = self.sheet.get_cell_data(row, real_col) self.sheet.create_text_editor(row=row, column=real_col, text=old_value, set_data_ref_on_destroy=False, binding=partial( self.end_edit_cell, old_value)) # not a button. if Columns.all_columns[col_name].get('type') != 'button': self.sheet.refresh() return state_button_col_name, state_button_col_num = self.get_state_button( col_name) state = self.sheet.get_cell_data(row, state_button_col_num) if state == 'False': # data read from sheet is all string. self.sheet.refresh() return # disable the button if it is one of the Download buttons, to prevent a re-download. if col_name == 'download_video': self.sheet.set_cell_data(row, real_col, Icons.PAUSE_DOWNLOAD, redraw=False) elif col_name == 'download_slides': cs = Config.load( ConfigType.COLORSCHEMES)[Variables().colorscheme_var().get()] self.disable_button(row, real_col, cs) func_name = Columns.all_columns[col_name]['function'] getattr(self, func_name)(row, real_col) def get_state_button(self, button_name): # noqa if Columns.all_columns[button_name].get('state'): state_col_name = Columns.all_columns[button_name].get('state') state_col_number = Columns.column_names.index(state_col_name) return state_col_name, state_col_number else: return None, None def end_edit_cell(self, old_value, event=None): row, col = (event[0], event[1]) new_value = self.sheet.get_text_editor_value( event, r=row, c=col, set_data_ref_on_destroy=True, move_down=False, redraw=True, recreate=True) # empty value or escape pressed. if not new_value or new_value == '': return # no changes made. if old_value == new_value: return col_name = Columns.column_names[self.get_real_col(col)] columns_item = Columns.data_columns[col_name] orig_values_col_name = columns_item.get('original_values_col') original_value = self.sheet.get_cell_data( row, Columns.column_names.index(orig_values_col_name)) for i, data in enumerate( self.sheet.get_column_data( Columns.column_names.index(orig_values_col_name))): if data == original_value: self.sheet.set_cell_data(i, col, new_value) self.expected_real_paths_differ = True Mappings.update_mappings(orig_values_col_name, original_value, new_value) self.reset_column_sizes() self.sheet.deselect(row=row, column=col, redraw=False) self.sheet.refresh() if self.expected_real_paths_differ or not self.all_captions_found: self.toolbar.auto_organize_button.config(state='normal') self.menubar.actions_menu.entryconfig(Labels.AUTO_ORGANIZE, state='normal') def reset_column_sizes(self): """ Adjust column sizes after data has been filled. """ # resize cells self.sheet.set_all_column_widths() # reset column widths to fill the screen pad = 5 column_widths = self.sheet.get_column_widths() table_width = self.sheet.RI.current_width + sum(column_widths) + len( column_widths) + pad diff_width = self.frame_content.winfo_width() - table_width # adjust extra width only to top N data columns n = 3 column_states = [ v.get() for v in Variables().display_columns_vars().values() ] count = 0 for k, v in enumerate(column_states): if Columns.column_names[k] == 'downloaded': break count += v # range(0..count) is all data columns. data_col_widths = {k: v for k, v in enumerate(column_widths[:count])} top_n_cols = sorted(data_col_widths, key=data_col_widths.get, reverse=True)[:n] for i in top_n_cols: self.sheet.column_width(i, column_widths[i] + diff_width // n) def get_index(self, row): """ Find the values stored in the hidden column named 'Index', given a row record. In case the row value has been updated due to sorting the table, Index field helps identify the new location of the associated record. """ # find where is the Index column index_col = Columns.column_names.index('index') # original row value as per the index column return int(self.sheet.get_cell_data(row, index_col)) def get_row_after_sort(self, index_value): # find the new correct location of the row_index col_index = Columns.column_names.index('index') col_data = self.sheet.get_column_data(col_index) return col_data.index(str(index_value)) def progress_bar_text(self, value, processed=False): """ return progress bar text, calls the unicode/ascii implementation. """ conf = Config.load(ConfigType.IMPARTUS) if conf.get('progress_bar') == 'unicode': text = self.progress_bar_text_unicode(value) else: text = self.progress_bar_text_ascii(value) pad = ' ' * 2 if 0 < value < 100: percent_text = '{:2d}%'.format(value) status = percent_text elif value == 0: status = '{}{}{}'.format(pad, Icons.VIDEO_NOT_DOWNLOADED, pad) else: # 100 % if processed: status = '{}{}{}'.format(pad, Icons.VIDEO_DOWNLOADED, pad) else: status = '{}{}{}'.format(pad, Icons.VIDEO_PROCESSING, pad) return '{} {}{}'.format(text, status, pad) def progress_bar_text_ascii(self, value): # noqa """ progress bar implementation with ascii characters. """ bars = 50 ascii_space = " " if value > 0: progress_text = '{}'.format('❘' * (value * bars // 100)) empty_text = '{}'.format(ascii_space * (bars - len(progress_text))) full_text = '{}{} '.format(progress_text, empty_text) else: full_text = '{}'.format(ascii_space * bars) return full_text def progress_bar_text_unicode(self, value): # noqa """ progress bar implementation with unicode blocks. """ chars = ['▏', '▎', '▍', '▌', '▋', '▊', '▉', '█'] # 1 full unicode block = 8 percent values # => 13 unicode blocks needed to represent counter 100. unicode_space = ' ' if value > 0: # progress_text: n characters, empty_text: 13-n characters progress_text = '{}{}'.format(chars[-1] * (value // 8), chars[value % 8]) empty_text = '{}'.format(unicode_space * (13 - len(progress_text))) full_text = '{}{}'.format(progress_text, empty_text) else: # all 13 unicode whitespace. full_text = '{} '.format(unicode_space * 13) return full_text def progress_bar_callback(self, count, row, col, processed=False): """ Callback function passed to the backend, where it computes the download progress. Every time the function is called, it will update the progress bar value. """ updated_row = self.get_row_after_sort(row) new_text = self.progress_bar_text(count, processed) if new_text != self.sheet.get_cell_data(updated_row, col): self.sheet.set_cell_data(updated_row, col, new_text, redraw=True) def get_real_col(self, col): # noqa """ with configurable column list, the col number returned by tksheet may not be the same as column no from self.all_columns/self.display_columns. Use self.display_column_vars to identify and return the correct column. """ # find n-th visible column, where n=col i = 0 for c, state in enumerate(Variables().display_columns_vars().values()): if state.get() == 1: if i == col: return c i += 1 def fetch_content(self): self.videos = dict() self.video_slide_mapping = dict() self.expected_real_paths_differ = False self.offline_video_ttid_mapping = None root_url = self.login.url_box.get() subject_dicts = self.impartus.get_subjects(root_url) has_flipped_lectures = False for subject_dict in subject_dicts: videos_by_subject = self.impartus.get_lectures( root_url, subject_dict) flipped_videos_by_subject = self.impartus.get_flipped_lectures( root_url, subject_dict) if len(flipped_videos_by_subject): has_flipped_lectures = True all_videos_by_subject = [ *videos_by_subject, *flipped_videos_by_subject ] slides = self.impartus.get_slides(root_url, subject_dict) mapping_dict = self.impartus.map_slides_to_videos( all_videos_by_subject, slides) for key, val in mapping_dict.items(): self.video_slide_mapping[key] = val self.videos[subject_dict.get('subjectId')] = { x['ttid']: x for x in all_videos_by_subject } state = 'normal' if has_flipped_lectures else 'disabled' self.toolbar.flipped_video_quality_dropdown.configure(state=state) self.menubar.main_menu.entryconfig(Labels.VIDEO, state=state) def fill_content(self): # A mapping dict containing previously downloaded, and possibly moved around / renamed videos. # extract their ttid and map those to the correct records, to avoid forcing the user to re-download. self.offline_video_ttid_mapping = self.impartus.get_mkv_ttid_map() row = 0 sheet_rows = list() for subject_id, videos in self.videos.items(): for ttid, video_metadata in videos.items(): video_metadata = Utils.add_new_fields(video_metadata, self.video_slide_mapping) video_path = self.impartus.get_mkv_path(video_metadata) if not os.path.exists(video_path): # or search from the downloaded videos, using video_ttid_map video_path_moved = self.offline_video_ttid_mapping.get( str(ttid)) if video_path_moved: # For now, use the offline path if a video found. Also set the flag to enable move/rename button video_path = video_path_moved self.expected_real_paths_differ = True captions_path = self.impartus.get_captions_path(video_metadata) if not os.path.exists(captions_path): self.all_captions_found = False slides_path = self.impartus.get_slides_path(video_metadata) video_exists_on_disk = video_path and os.path.exists( video_path) slides_exist_on_server = self.video_slide_mapping.get(ttid) slides_exist_on_disk, slides_path = self.impartus.slides_exist_on_disk( slides_path) metadata = { 'video_metadata': video_metadata, 'video_path': video_path, 'video_exists_on_disk': video_exists_on_disk, 'slides_exist_on_server': slides_exist_on_server, 'slides_exist_on_disk': slides_exist_on_disk, 'slides_url': self.video_slide_mapping.get(ttid), 'slides_path': slides_path, 'captions_path': captions_path, } row_items = list() button_states = list() # data items for col, (key, item) in enumerate(Columns.all_columns.items()): text = '' if item['type'] == 'data': text = video_metadata[key] # title case if item.get('title_case'): text = " ".join(text.splitlines()).strip().title() elif item['type'] == 'auto': text = row elif item['type'] == 'progressbar': if video_exists_on_disk: text = self.progress_bar_text(100, processed=True) else: text = self.progress_bar_text(0) elif item['type'] == 'button': button_states.append( self.get_button_state(key, video_exists_on_disk, slides_exist_on_server, slides_exist_on_disk)) text = item.get('text') elif item['type'] == 'button_state': text = button_states.pop(0) elif item['type'] == 'metadata': text = metadata elif item['type'] == 'original_value': text = video_metadata[key] row_items.append(text) row += 1 sheet_rows.append(row_items) self._init_content() self.sheet.insert_rows(sheet_rows, idx='end') self.reset_column_sizes() self.decorate() # update button status self.set_button_status(redraw=True) self.sheet.grid(row=0, column=0, sticky='nsew') def sort_table(self, args): """ Sorts the table content. """ col = args[1] real_col = self.get_real_col(col) self.sheet.deselect("all") col_name = Columns.column_names[real_col] if not Columns.all_columns[col_name].get('sortable'): return sort_by = col_name if sort_by == self.sort_by: sort_order = 'asc' if self.sort_order == 'desc' else 'desc' else: sort_order = 'desc' self.sort_by = sort_by self.sort_order = sort_order reverse = True if sort_order == 'desc' else False table_data = self.sheet.get_sheet_data() table_data.sort(key=lambda x: x[real_col], reverse=reverse) self.set_headers(sort_by, sort_order) self.set_button_status() self.sheet.refresh() def save_captions_if_needed(self, video_metadata, root_url, captions_path): chat_msgs = self.impartus.get_chats(video_metadata, root_url) date_format = "%Y-%m-%d %H:%M:%S" start_epoch = int( datetime.strptime(video_metadata['startTime'], date_format).timestamp()) try: vtt_content = Captions.get_vtt(chat_msgs, start_epoch) Captions.save_vtt(vtt_content, captions_path) except CaptionsNotFound as ex: self.logger.info( "no lecture chat found for {}".format(captions_path)) return return True def _download_video(self, video_metadata, filepath, captions_path, root_url, row, col, pause_ev, resume_ev): # noqa """ Download a video in a thread. Update the UI upon completion. """ # create a new Impartus session reusing existing token. imp = Impartus(self.impartus.token) pb_col = Columns.column_names.index('downloaded') # # voodoo alert: # It is possible for user to sort the table while download is in progress. # In such a case, the row index supplied to the function call won't match the row index # required to update the correct progressbar/open/play buttons, which now exists at a new # location. # The hidden column index keeps the initial row index, and remains unchanged. # Use row_index to identify the new correct location of the progress bar. row_index = self.get_index(row) imp.process_video(video_metadata, filepath, root_url, pause_ev, resume_ev, partial(self.progress_bar_callback, row=row_index, col=pb_col), video_quality=Variables().lecture_quality_var()) # also download lecture chats, and create a webvtt subtitles file. self.save_captions_if_needed(video_metadata, root_url, captions_path) # download complete, enable open / play buttons updated_row = self.get_row_after_sort(row_index) # update progress bar status to complete. self.progress_bar_callback(row=row_index, col=pb_col, count=100, processed=True) self.sheet.set_cell_data(updated_row, Columns.column_names.index('download_video'), Icons.DOWNLOAD_VIDEO) self.disable_button(updated_row, Columns.column_names.index('download_video')) # enable buttons. self.enable_button(updated_row, Columns.column_names.index('open_folder')) self.enable_button(updated_row, Columns.column_names.index('play_video')) def add_slides(self, row, col): # noqa conf = Config.load(ConfigType.IMPARTUS) file_types = [(str(ext).upper(), '*.{}'.format(ext)) for ext in conf.get('allowed_ext')] filepaths = tkinter.filedialog.askopenfilenames(filetypes=file_types) data = self.read_metadata(row) slides_folder_path = os.path.dirname(data.get('video_path')) for filepath in filepaths: shutil.copy(filepath, slides_folder_path) def pause_resume_button_click(self, row, col, pause_event, resume_event): row_index = self.get_index(row) updated_row = self.get_row_after_sort(row_index) if pause_event.is_set(): self.sheet.set_cell_data(updated_row, col, Icons.PAUSE_DOWNLOAD, redraw=True) resume_event.set() pause_event.clear() else: self.sheet.set_cell_data(updated_row, col, Icons.RESUME_DOWNLOAD, redraw=True) pause_event.set() resume_event.clear() def download_video(self, row, col): """ callback function for Download button. Creates a thread to download the request video. """ data = self.read_metadata(row) video_metadata = data.get('video_metadata') filepath = data.get('video_path') captions_path = data.get('captions_path') root_url = self.login.url_box.get() real_row = self.get_index(row) if self.threads.get(real_row): pause_ev = self.threads.get(real_row)['pause_event'] resume_ev = self.threads.get(real_row)['resume_event'] self.pause_resume_button_click(row, col, pause_ev, resume_ev) return from threading import Event pause_event = Event() resume_event = Event() # note: args is a tuple. thread = threading.Thread(target=self._download_video, args=( video_metadata, filepath, captions_path, root_url, row, col, pause_event, resume_event, )) self.threads[real_row] = { 'thread': thread, 'pause_event': pause_event, 'resume_event': resume_event, } thread.start() def _download_slides(self, ttid, file_url, filepath, root_url, row): """ Download a slide doc in a thread. Update the UI upon completion. """ # create a new Impartus session reusing existing token. imp = Impartus(self.impartus.token) if imp.download_slides(ttid, file_url, filepath, root_url): # download complete, enable show slides buttons self.enable_button(row, Columns.column_names.index('show_slides')) else: tkinter.messagebox.showerror( 'Error', 'Error downloading slides, see console logs for details.') self.enable_button(row, Columns.column_names.index('download_slides')) def download_slides(self, row, col): # noqa """ callback function for Download button. Creates a thread to download the request video. """ data = self.read_metadata(row) video_metadata = data.get('video_metadata') ttid = video_metadata['ttid'] file_url = data.get('slides_url') filepath = data.get('slides_path') root_url = self.login.url_box.get() # note: args is a tuple. thread = threading.Thread(target=self._download_slides, args=( ttid, file_url, filepath, root_url, row, )) # self.threads.append(thread) thread.start() def read_metadata(self, row): """ We saved a hidden column 'metadata' containing metadata for each record. Extract it, and eval it as python dict. """ metadata_col = Columns.column_names.index('metadata') data = self.sheet.get_cell_data(row, metadata_col) return ast.literal_eval(data) def open_folder(self, row, col): # noqa """ fetch video_path's folder from metadata column's cell and open system launcher with it. """ data = self.read_metadata(row) video_folder_path = os.path.dirname(data.get('video_path')) Utils.open_file(video_folder_path) def play_video(self, row, col): # noqa """ fetch video_path from metadata column's cell and open system launcher with it. """ data = self.read_metadata(row) Utils.open_file(data.get('video_path')) def show_slides(self, row, col): # noqa """ fetch slides_path from metadata column's cell and open system launcher with it. """ data = self.read_metadata(row) Utils.open_file(data.get('slides_path')) def auto_organize(self): self.toolbar.auto_organize_button.config(state='disabled') self.menubar.actions_menu.entryconfig(Labels.AUTO_ORGANIZE, state='disabled') moved_files = dict() conf = Config.load(ConfigType.IMPARTUS) for subject_id, videos in self.videos.items(): for ttid, video_metadata in videos.items(): video_metadata = Utils.add_new_fields(video_metadata, self.video_slide_mapping) # for videos expected_video_path = self.impartus.get_mkv_path( video_metadata) real_video_path = self.offline_video_ttid_mapping.get( str(ttid)) if real_video_path and \ pathlib.PurePath(expected_video_path) != pathlib.PurePath(real_video_path) \ and os.path.exists(real_video_path): Utils.move_and_rename_file(real_video_path, expected_video_path) self.logger.info('moved {} -> {}'.format( real_video_path, expected_video_path)) moved_files[real_video_path] = expected_video_path # also update the offline_video_ttid_mapping self.offline_video_ttid_mapping[str( ttid)] = expected_video_path # also check any slides. for ext in conf.get('allowed_ext'): slides_path = '{}.{}'.format( real_video_path[:-len(".mkv")], ext) if os.path.exists(slides_path): expected_slides_path = '{}.{}'.format( expected_video_path[:-len(".mkv")], ext) Utils.move_and_rename_file(slides_path, expected_slides_path) self.logger.info('moved {} -> {}'.format( slides_path, expected_slides_path)) moved_files[slides_path] = expected_slides_path # is the folder empty, remove it.? [also any empty parent folders] old_video_dir = os.path.dirname(real_video_path) sys_name = platform.system() if conf.get('ignore_files').get(sys_name): ignore_files = conf.get('ignore_files')[sys_name] else: ignore_files = [] while True: dir_files = [ x for x in os.listdir(old_video_dir) if x not in ignore_files ] if len(dir_files) > 0: break for file in ignore_files: filepath = os.path.join(old_video_dir, file) if os.path.exists(filepath): os.unlink(filepath) os.rmdir(old_video_dir) self.logger.info('removed empty directory: {}'.format( old_video_dir)) # parent path. old_video_dir = Path(old_video_dir).parent.absolute() # captions expected_captions_path = self.impartus.get_captions_path( video_metadata) if not os.path.exists(expected_captions_path): if self.save_captions_if_needed(video_metadata, self.login.url_box.get(), expected_captions_path): self.logger.info('downloaded captions: {}'.format( expected_captions_path)) self.all_captions_found = True if len(moved_files) > 0: self.auto_organize_dialog(moved_files) self.expected_real_paths_differ = False def set_display_columns(self): column_states = [ i for i, v in enumerate(Variables().display_columns_vars().values()) if v.get() == 1 ] self.sheet.display_columns(indexes=column_states, enable=True, redraw=False) self.reset_column_sizes() self.sheet.refresh() def odd_even_color(self, cs: Dict, redraw=False): """ Apply odd/even colors for table for better looking UI. """ num_rows = self.sheet.total_rows() self.sheet.highlight_rows(list(range(0, num_rows, 2)), bg=cs['even_row']['bg'], fg=cs['even_row']['fg'], redraw=redraw) self.sheet.highlight_rows(list(range(1, num_rows, 2)), bg=cs['odd_row']['bg'], fg=cs['odd_row']['fg'], redraw=redraw) def progress_bar_color(self, cs: Dict, redraw=True): """ Set progress bar color. """ col = Columns.column_names.index('downloaded') num_rows = self.sheet.total_rows() for row in range(num_rows): odd_even_bg = cs['odd_row']['bg'] if row % 2 else cs['even_row'][ 'bg'] self.sheet.highlight_cells(row, col, fg=cs['progressbar']['fg'], bg=odd_even_bg, redraw=redraw) def set_button_status(self, redraw=False): """ reads the states of the buttons from the hidden state columns, and sets the button states appropriately. """ col_indexes = [ x for x, v in enumerate(Columns.all_columns.values()) if v['type'] == 'button_state' ] num_buttons = len(col_indexes) for row, row_item in enumerate(self.sheet.get_sheet_data()): for col in col_indexes: # data set via sheet.insert_row retains tuple/list's element data type, # data set via sheet.set_cell_data makes everything a string. # Consider everything coming out of a sheet as string to avoid any issues. state = str(row_item[col]) if state == 'True': self.enable_button(row, col - num_buttons, redraw=redraw) elif state == 'False': self.disable_button(row, col - num_buttons, redraw=redraw) return def get_button_state(self, key, video_exists_on_disk, slides_exist_on_server, slides_exist_on_disk): # noqa """ Checks to identify when certain buttons should be enabled/disabled. """ state = True if key == 'download_video' and video_exists_on_disk: state = False elif key == 'open_folder' and not video_exists_on_disk: state = False elif key == 'play_video' and not video_exists_on_disk: state = False elif key == 'download_slides' and (slides_exist_on_disk or not slides_exist_on_server): state = False elif key == 'show_slides' and not slides_exist_on_disk: state = False return state def disable_button(self, row, col, redraw=False): """ Disable a button given it's row/col position. """ cs = Config.load( ConfigType.COLORSCHEMES)[Variables().colorscheme_var().get()] self.sheet.highlight_cells(row, col, bg=cs['disabled']['bg'], fg=cs['disabled']['fg'], redraw=redraw) # update state field. state_button_col_name, state_button_col_num = self.get_state_button( Columns.column_names[col]) self.sheet.set_cell_data(row, state_button_col_num, False, redraw=redraw) def enable_button(self, row, col, redraw=False): """ Enable a button given it's row/col position. """ cs = Config.load( ConfigType.COLORSCHEMES)[Variables().colorscheme_var().get()] odd_even_bg = cs['odd_row']['bg'] if row % 2 else cs['even_row']['bg'] odd_even_fg = cs['odd_row']['fg'] if row % 2 else cs['even_row']['fg'] self.sheet.highlight_cells(row, col, bg=odd_even_bg, fg=odd_even_fg, redraw=redraw) # update state field. state_button_col_name, state_button_col_num = self.get_state_button( Columns.column_names[col]) self.sheet.set_cell_data(row, state_button_col_num, True, redraw=redraw) def set_readonly_columns(self, redraw=False): readonly_cols = [ i for i, (k, v) in enumerate(Columns.all_columns.items()) if not v.get('editable') ] self.sheet.readonly_columns(columns=readonly_cols, readonly=True, redraw=redraw) def set_colorscheme(self, cs): if self.frame_content: self.frame_content.configure(bg=cs['root']['bg']) if self.sheet: self.sheet.set_options(frame_bg=cs['table']['bg'], table_bg=cs['table']['bg'], table_fg=cs['table']['fg'], header_bg=cs['header']['bg'], header_fg=cs['header']['fg'], header_grid_fg=cs['table']['grid'], index_grid_fg=cs['table']['grid'], header_border_fg=cs['table']['grid'], index_border_fg=cs['table']['grid'], table_grid_fg=cs['table']['grid'], top_left_bg=cs['header']['bg'], top_left_fg=cs['header']['bg']) self.odd_even_color(cs, redraw=False) self.progress_bar_color(cs, redraw=False) self.set_button_status(redraw=False) self.set_readonly_columns(redraw=False) self.sheet.refresh() def decorate(self): """ calls multiple ui related tweaks. """ self.align_columns() cs = Config.load( ConfigType.COLORSCHEMES)[Variables().colorscheme_var().get()] self.set_colorscheme(cs) self.odd_even_color(cs) self.progress_bar_color(cs) def align_columns(self): # data and progressbar west/left aligned, button center aligned. self.sheet.align_columns([ Columns.column_names.index(k) for k in Columns.data_columns.keys() ], align='w') self.sheet.align_columns([ Columns.column_names.index(k) for k in Columns.progressbar_column.keys() ], align='w') self.sheet.align_columns([ Columns.column_names.index(k) for k in Columns.button_columns.keys() ], align='center') def show_video_callback(self, impartus: Impartus, event=None): # noqa if threading.activeCount( ) > 1: # 1. main thread, 2,3... download threads. response = tk.messagebox.askquestion( 'Download(s) in progress!', "Reloading the content will lose the downloads in progress.\n" + "Do you want to continue?", icon='warning') if response != 'yes': return self.toolbar.reload_button.config(state='disabled') self.menubar.actions_menu.entryconfig(Labels.RELOAD, state='disabled') self.toolbar.auto_organize_button.config(state='disabled') self.menubar.actions_menu.entryconfig(Labels.AUTO_ORGANIZE, state='disabled') self.toolbar.frame_toolbar.grid(row=1, column=0, sticky='ew') self.login.authenticate(impartus) self.set_display_widgets() self.toolbar.reload_button.config(state='normal') self.menubar.actions_menu.entryconfig(Labels.RELOAD, state='normal') if self.expected_real_paths_differ or not self.all_captions_found: auto_organize_button_state = 'normal' else: auto_organize_button_state = 'disabled' self.toolbar.auto_organize_button.config( state=auto_organize_button_state) self.menubar.actions_menu.entryconfig(Labels.AUTO_ORGANIZE, state=auto_organize_button_state) def on_auto_organize_dialog_close(self): self.login.authenticate(self.impartus) Dialogs.on_dialog_close() self.show_video_callback(self.impartus) def auto_organize_dialog(self, moved_files): # noqa dialog = Dialogs.create_dialog( on_close_callback=self.on_auto_organize_dialog_close, title='Auto Organize') label = tk.Label( dialog, text='Following files were moved / renamed -', ) label.grid(row=0, column=0, sticky='w', ipadx=10, ipady=10) dialog.columnconfigure(0, weight=1) # show a dialog with the output. sheet = Sheet( Dialogs.dialog, header_font=(self.header_font, self.header_font_size, "bold"), font=(self.content_font, self.content_font_size, "normal"), align='w', row_height="1", # str value for row height in number of lines. row_index_align="w", auto_resize_default_row_index=False, row_index_width=40, header_align='center', empty_horizontal=0, empty_vertical=0, ) sheet.headers(['Source', '', 'Destination']) target_parent = os.path.dirname(self.impartus.download_dir) for row, (source, destination) in enumerate(moved_files.items()): source = source[len(target_parent) + 1:] destination = destination[len(target_parent) + 1:] sheet.insert_row([source, Icons.MOVED_TO, destination]) sheet.set_all_column_widths() sheet.grid(row=1, column=0, sticky='nsew') ok_button = tk.Button(dialog, text='OK', command=self.on_auto_organize_dialog_close) ok_button.grid(row=2, column=0, padx=10, pady=10)
class product_demo(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.frame = tk.Frame(self) self.fill_data_from_db() self.frame.grid_columnconfigure(0, weight=1) self.frame.grid_rowconfigure(0, weight=1) self.sheet = Sheet( self.frame, page_up_down_select_row=True, # empty_vertical = 0, headers=headers, column_width=120, startup_select=(0, 1, "rows"), data=data, height=500, # height and width arguments are optional width=500 # For full startup arguments see DOCUMENTATION.md ) self.sheet.enable_bindings(( "single_select", # "single_select" or "toggle_select" "drag_select", # enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", # "row_width_resize", # "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", # "rc_insert_column", # "rc_delete_column", # "rc_insert_row", "rc_delete_row", # "hide_columns", "copy", # "cut", # "paste", # "delete", "undo", "edit_cell")) self.frame.grid(row=0, column=0, sticky="nswe") self.sheet.grid(row=0, column=0, sticky="nswe") # __________ DISPLAY SUBSET OF COLUMNS __________ self.sheet.display_subset_of_columns(indexes=[0, 1, 2], enable=True) # __________ BINDING A FUNCTIONS TO USER ACTIONS __________ self.sheet.extra_bindings([("end_edit_cell", self.end_edit_cell), ("begin_rc_delete_row", self.row_delete)]) # __________ GETTING FULL SHEET DATA __________ # self.all_data = self.sheet.get_sheet_data() # __________ GETTING CELL DATA __________ # print (self.sheet.get_cell_data(0, 0)) # __________ GETTING ROW DATA __________ # print (self.sheet.get_row_data(0)) # only accessible by index # __________ GETTING COLUMN DATA __________ # print (self.sheet.get_column_data(0)) # only accessible by index def end_edit_cell(self, event): print("cell edited") print(event) PRODUCT.query.filter_by(**{ "pid": self.sheet.get_cell_data(event[0], 0) }).update( {headers[event[1]]: self.sheet.get_cell_data(event[0], event[1])}) db_session.commit() def row_delete(self, event): print("row deleted") print(event) print({"pid": self.sheet.get_cell_data(event[1][0], 0)}) PRODUCT.query.filter_by(**{ "pid": self.sheet.get_cell_data(event[1][0], 0) }).delete() db_session.commit() def fill_data_from_db(self): data.clear() ps = PRODUCT.query.all() k = [[i.to_dict(rules=('-ORDERITEM', )).get(z) for z in headers] for i in ps] data.extend(k)
class TableLastOut(): def __init__(self): text_customer_latest = Label( root, text="List Pelanggan Urut Terakhir Keluar", font="ROBOTO 13") text_customer_latest.grid(row=8, column=0, columnspan=2, padx=5, pady=(80, 10)) self.frame = tableFrameLatest self.frame.grid_columnconfigure(0, weight=1) self.frame.grid_rowconfigure(0, weight=1) self.sheet = Sheet( self.frame, page_up_down_select_row=True, # empty_vertical = 0, column_width=120, startup_select=(0, 1, "rows"), # row_height = "4", # default_row_index = "numbers", # default_header = "both", # empty_horizontal = 0, # show_vertical_grid = False, # show_horizontal_grid = False, # auto_resize_default_row_index = False, # header_height = "3", # row_index_width = 100, # align = "e", # header_align = "w", # row_index_align = "w", data=sorted(list_last_out, key=lambda x: x[2], reverse=TRUE), # to set sheet data at startup headers=["No Plat Polisi", "Masuk", "Keluar", "Biaya"], # set_all_heights_and_widths = True, #to fit all cell sizes to text at start up # headers = 0, #to set headers as first row at startup # headers = [f"Column {c}\nnewline1\nnewline2" for c in range(30)], # theme = "light green", # row_index = 0, #to set row_index as first column at startup # total_rows = 2000, #if you want to set empty sheet dimensions at startup # total_columns = 30, #if you want to set empty sheet dimensions at startup height=200, # height and width arguments are optional width=500 # For full startup arguments see DOCUMENTATION.md ) # self.sheet.hide("row_index") # self.sheet.hide("header") # self.sheet.hide("top_left") self.sheet.enable_bindings(( "single_select", # "single_select" or "toggle_select" "drag_select", # enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", # "row_width_resize", # "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "hide_columns", "copy", "cut", "paste", "delete", "undo", "edit_cell")) # self.sheet.disable_bindings() #uses the same strings # self.sheet.enable_bindings() self.frame.grid(row=9, column=0, columnspan=2, sticky="nswe", padx=5) self.sheet.grid(row=9, column=0, columnspan=2, sticky="nswe", padx=5) def set_data(self): self.sheet.set_sheet_data( sorted(list_last_out, key=lambda x: x[2], reverse=TRUE))
class Application: def __init__(self, master): self.master = master self.now = datetime.now() # self.master.wm_iconbitmap("logo.ico") self.master.eval('tk::PlaceWindow . center') self.master.minsize(400, 300) self.master.grid_columnconfigure(0, weight=1) self.master.grid_rowconfigure(0, weight=1) style = ttk.Style(self.master) style.configure("Placeholder.TEntry", foreground="#d5d5d5") self.master.title("Query thông tin sản phẩm") self.savedKw = str(Path.home()) + os.path.sep + "savedkw.txt" self.master_data = {} self.selected_sheets_data = [] self.data_to_fill = [] self.menubar_items = ["File", "Xem", "Công cụ", "Giúp đỡ"] self.sheet = None self.gspread_sheet = None self.url_input = None self.sheet_list = [] self.sheet_titles = [] self.highlighted_index = [] # self.url_gsheet = "https://docs.google.com/spreadsheets/d/10oJamLk0Bj4ffcDbnu9-96-dn7Tf7TM0EnJ2-emSp9c/edit#gid=1900586655" self.url_gsheet = "Reason Code CB" self.error_load_sheet = False self.current_words = [] self.toggle_theme = IntVar() self.toggle_theme.set(0) self.toggle_compact = IntVar() self.toggle_compact.set(0) self.logging = [] self.current_log = [] self.area_filter_value = IntVar() self.sheet_filter_value = IntVar() self.create_widgets() def get_data_to_fill(self, selected_sheets): for selected_sheet in selected_sheets: self.selected_sheets_data.append(self.master_data[selected_sheet]) self.sheet_titles.append(self.master_data[selected_sheet][0]) for each_sheet in self.selected_sheets_data: self.data_to_fill = self.data_to_fill + each_sheet def get_gsheet_value(self, gsheet_url): scope = [ "https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive" ] creds = ServiceAccountCredentials.from_json_keyfile_name( "creds.json", scope) # creds = ServiceAccountCredentials.from_json_keyfile_dict(creds_dict, scope) self.data_to_fill = [] self.error_load_sheet = False try: client = gspread.authorize(creds) if "http" in gsheet_url: self.gspread_sheet = client.open_by_url(gsheet_url) else: self.gspread_sheet = client.open(gsheet_url) worksheets = self.gspread_sheet.worksheets() for worksheet in worksheets: worksheet_name = worksheet.title worksheet_values = self.gspread_sheet.worksheet( worksheet_name).get_all_values() self.sheet_list.append(worksheet_name) self.master_data[worksheet_name] = worksheet_values self.get_data_to_fill(self.sheet_list) except (ServerNotFoundError, Exception) as e: self.error_load_sheet = True self.cell_value_label.configure(text="Có lỗi xảy ra, hãy thử lại", anchor="w") self.data_to_fill = [[]] except SpreadsheetNotFound as notfound: self.error_load_sheet = True self.cell_value_label.configure( text="File spreadsheet không tồn tại", anchor="w") self.data_to_fill = [[]] class AutocompleteEntry(ttk.Entry): def __init__(self, autocompleteList, placeholder, *args, **kwargs): # Custom matches function if 'matchesFunction' in kwargs: self.matchesFunction = kwargs['matchesFunction'] del kwargs['matchesFunction'] else: def matches(fieldValue, acListEntry): pattern = re.compile('.*' + re.escape(fieldValue) + '.*', re.IGNORECASE) return re.match(pattern, acListEntry) self.matchesFunction = matches ttk.Entry.__init__(self, *args, style="Placeholder.TEntry", **kwargs) self.autocompleteList = autocompleteList self.placeholder = placeholder self.focus() self.insert("0", self.placeholder) self.bind("<FocusIn>", self.clear_placeholder) self.bind("<FocusOut>", self.add_placeholder) self.var = self["textvariable"] if self.var == '': self.var = self["textvariable"] = StringVar() self.var.trace('w', self.changed) self.bind("<Right>", self.selection) self.bind("<Up>", self.moveUp) self.bind("<Down>", self.moveDown) self.bind("<Escape>", self.hide) self.listboxUp = False def clear_placeholder(self, e): if self["style"] == "Placeholder.TEntry": self.delete("0", "end") self["style"] = "TEntry" def add_placeholder(self, e): if not self.get(): self.insert("0", self.placeholder) self["style"] = "Placeholder.TEntry" def changed(self, name, index, mode): if self.var.get() == '': if self.listboxUp: self.listbox.destroy() self.listboxUp = False else: words = self.comparison() self.listboxLength = len(words) if words: if not self.listboxUp: self.listbox = Listbox(width=self["width"], height=self.listboxLength) self.listbox.bind("<<ListboxSelect>>", self.clickItem) self.listbox.bind("<Right>", self.selection) self.listbox.place(x=self.winfo_x(), y=self.winfo_y() + self.winfo_height()) self.listboxUp = True self.listbox.delete(0, END) for w in words: self.listbox.insert(END, w) else: if self.listboxUp: self.listbox.destroy() self.listboxUp = False def clickItem(self, event): if self.listboxUp: index = int(self.listbox.curselection()[0]) self.var.set(self.listbox.get(index)) self.listbox.destroy() self.listboxUp = False self.icursor(END) def selection(self, event): if self.listboxUp and self.listbox.curselection() != (): self.var.set(self.listbox.get(ACTIVE)) self.listbox.destroy() self.listboxUp = False self.icursor(END) else: if self.listboxUp: self.listbox.destroy() self.listboxUp = False self.icursor(END) def hide(self, event): if self.listboxUp: self.listbox.destroy() self.listboxUp = False def moveUp(self, event): if self.listboxUp: if self.listbox.curselection() == (): index = '-2' else: index = self.listbox.curselection()[-1] if index != END: self.listbox.selection_clear(first=index) index = str(int(index) - 1) self.listbox.see(index) # Scroll! self.listbox.selection_set(first=index) self.listbox.activate(index) def moveDown(self, event): if self.listboxUp: if self.listbox.curselection() == (): index = '-1' else: index = self.listbox.curselection()[-1] if index != END: self.listbox.selection_clear(first=index) index = str(int(index) + 1) self.listbox.see(index) # Scroll! self.listbox.selection_set(first=index) self.listbox.activate(index) def comparison(self): return [ w for w in self.autocompleteList if self.matchesFunction(self.var.get(), w) ] def get_saved_keywords(self): try: with open(self.savedKw, "r", encoding="utf-8") as f: lines = f.readlines() for line in lines: self.current_words.append(line.replace("\n", "")) except FileNotFoundError as fe: pass def save_keywords(self, keyword): if keyword not in self.current_words and keyword != "": with open(self.savedKw, "a", encoding="utf-8") as f: f.write(f"{keyword}\n") def search_keyword(self, event): self.search_bar.selection(event) kw = self.search_bar.get() result = [] titles = [] for each_sheet in self.selected_sheets_data: search_result = [ row for row in each_sheet if kw.lower() in str(row).lower() ] if len(search_result) > 0: search_result.insert(0, each_sheet[0]) titles.append(each_sheet[0]) # search_result = list(set(search_result)) result = result + search_result self.sheet.set_sheet_data(result, reset_col_positions=False) self.dehighlight_current_titles() self.highlight_sheet_title(result, titles) if kw != "": self.save_keywords(kw) log_output = "Đã tìm từ khóa: {}\n".format(kw) self.logging.append(log_output) if len(result) > 0 and kw not in self.current_words: self.current_words.append(kw) def highlight_sheet_title(self, current_data, titles): for index, value in enumerate(current_data): for i in titles: if i == value: for i in range(len(i)): self.sheet.highlight_cells(row=index, column=i, bg="#ed4337", fg="white") self.highlighted_index.append(index) self.sheet.refresh() def dehighlight_current_titles(self, indexes): for r in self.highlighted_index: for c in range(50): self.sheet.dehighlight_cells(row=r, column=c) self.sheet.refresh() def load_data(self): self.sheet.set_sheet_data([[]], reset_col_positions=True) for i in self.menubar_items: self.menubar.entryconfig(i, state="disabled") self.cell_value_label.configure(text="Đang tải dữ liệu file ...", anchor="w") self.get_gsheet_value(self.url_gsheet) self.toggle_compact.set(0) self.sheet.set_sheet_data(self.data_to_fill, reset_col_positions=True) if not self.error_load_sheet: self.cell_value_label.configure(text="---", anchor="w") for i in self.menubar_items: self.menubar.entryconfig(i, state="normal") self.highlight_sheet_title(self.data_to_fill, self.sheet_titles) def load_data_in_thread(self): t = Thread(target=self.load_data) t.start() def cell_select(self, response): self.cell_value_label.config( text=self.sheet.get_cell_data(response[1], response[2])) def load_another_gsheet(self): self.load_new_wd = Toplevel() self.load_new_wd.title("Nhập tên hoặc url của spreadsheet") self.load_new_wd.grab_set() self.load_new_wd.resizable(False, False) self.load_new_wd.grid_columnconfigure(0, weight=1) self.load_new_wd.grid_rowconfigure(0, weight=1) sub_frame = Frame(self.load_new_wd) sub_frame.grid(row=0, column=0, sticky="nsew", padx=1, pady=1) self.url_input = ttk.Entry(sub_frame, width=100) self.url_input.focus() self.url_input.grid(row=0, column=0, ipady=5, sticky="we", padx=5, pady=5) self.url_input.bind("<Return>", self.get_new_gsheet_data) sub_frame.grid_columnconfigure(0, weight=1) sub_frame.grid_rowconfigure(1, weight=1) def get_new_gsheet_data(self, event): if self.url_gsheet.strip() != "": self.url_gsheet = self.url_input.get() self.load_new_wd.destroy() self.load_data_in_thread() def switch_theme(self): mode = self.toggle_theme.get() if mode == 0: self.sheet.change_theme("light") else: self.sheet.change_theme("dark") def switch_compact(self): mode = self.toggle_compact.get() len_shd = len(self.data_to_fill) if mode == 0: self.sheet.set_column_widths([120 for c in range(len_shd)]) else: self.sheet.set_column_widths([30 for c in range(len_shd)]) self.sheet.refresh() def filter_sheet(self): self.filter_wd = Toplevel() self.filter_wd.title("Filter dữ liệu") self.filter_wd.maxsize(400, 200) self.filter_wd.grab_set() self.filter_wd.grid_columnconfigure(0, weight=1) self.filter_wd.grid_rowconfigure(0, weight=1) nb = ttk.Notebook(self.filter_wd) nb.grid(row=0, column=0, sticky="nswe") area_filter = Frame(self.filter_wd, padx=1, pady=1) sheet_filter = Frame(self.filter_wd, padx=1, pady=1) area_filter.grid(row=0, column=0, sticky="nsew", padx=1, pady=1) sheet_filter.grid(row=0, column=0, sticky="nsew", padx=1, pady=1) nb.add(area_filter, text="Filter theo vùng") nb.add(sheet_filter, text="Filter theo sheet") radiobtn1 = Radiobutton(area_filter, text="Shopee C2C", variable=self.area_filter_value, value=1) radiobtn1.grid(row=0, column=0) radiobtn2 = Radiobutton(area_filter, text="Shopee Mall", variable=self.area_filter_value, value=2) radiobtn2.grid(row=1, column=0) radiobtn3 = Radiobutton(area_filter, text="Note", variable=self.area_filter_value, value=3) radiobtn3.grid(row=1, column=0) for sheet_name in self.sheet_list: ttk.Checkbutton(sheet_filter, text=sheet_name).grid(sticky="w") nb.grid_columnconfigure(0, weight=1) nb.grid_rowconfigure(0, weight=1) sheet_filter.grid_columnconfigure(0, weight=1) sheet_filter.grid_rowconfigure(0, weight=1) # def get_logging(self): # if len(self.current_log) < len(self.logging): # self.log_entry.config(state=NORMAL) # self.log_entry.insert(INSERT, self.logging[len(self.logging) - 1]) # self.log_entry.see(END) # self.log_entry.config(state=DISABLED) # self.current_log.append(self.logging[len(self.logging) - 1]) # self.log_entry.after(1000, self.get_logging) def open_console(self): self.console_wd = Toplevel() self.console_wd.title("Console log") # self.console_wd.grab_set() self.console_wd.minsize(500, 200) self.console_wd.resizable(False, False) self.console_wd.grid_columnconfigure(0, weight=1) self.console_wd.grid_rowconfigure(0, weight=1) sub_frame = Frame(self.console_wd) sub_frame.grid(row=0, column=0, sticky="nsew", padx=1, pady=1) self.log_entry = ScrolledText(sub_frame) self.log_entry.grid(row=0, column=0, sticky="nswe", padx=5, pady=5) self.log_entry.insert( INSERT, "Console log của app được mở vào lúc {}\n\n".format(self.now)) # self.get_logging() sub_frame.grid_columnconfigure(0, weight=1) sub_frame.grid_rowconfigure(0, weight=1) def create_menu_bar(self): self.menubar = Menu(self.master) filemenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label=self.menubar_items[0], menu=filemenu) filemenu.add_command(label="Reload dữ liệu", command=self.load_data_in_thread) filemenu.add_command(label="Thoát", command=self.master.quit) viewmenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label=self.menubar_items[1], menu=viewmenu) viewmenu.add_command(label="Filter dữ liệu", command=self.filter_sheet) viewmenu.add_checkbutton(label="Đổi theme trắng/đen", variable=self.toggle_theme, command=self.switch_theme) viewmenu.add_checkbutton(label="Chế độ compact", variable=self.toggle_compact, command=self.switch_compact) toolmenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label=self.menubar_items[2], menu=toolmenu) toolmenu.add_command(label="Load dữ liệu khác", command=self.load_another_gsheet) helpmenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label=self.menubar_items[3], menu=helpmenu) helpmenu.add_command(label="Console log", command=self.open_console) self.master.config(menu=self.menubar) def create_widgets(self): self.get_saved_keywords() #--------CREATE MENU BAR---------- self.create_menu_bar() #--------CREATE NAVIGATION FRAME---------- self.main_frame = Frame(self.master) self.main_frame.grid(row=0, column=0, sticky="nsew", padx=1, pady=1) #--------CREATE SEARCH BAR AND SEARCH BUTTON WIDGET---------- self.search_bar = self.AutocompleteEntry(self.current_words, "Nhập từ khóa cần tìm", self.main_frame) self.search_bar.grid(row=0, column=0, ipady=5, sticky="we", padx=5, pady=5) self.search_bar.bind("<Return>", self.search_keyword) #--------CREATE CELL DETAIL VALUE LABEL---------- self.cell_value_label = Label(self.main_frame, text="---", anchor="w") self.cell_value_label.grid(row=1, column=0, padx=5, sticky="nw") self.main_frame.grid_columnconfigure(0, weight=1) self.main_frame.grid_rowconfigure(2, weight=1) #--------CREATE SHEET WIDGET---------- self.sheet = Sheet(self.main_frame, align="w") self.sheet.enable_bindings( ("single_select", "drag_select", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "rc_select", "copy", "paste", "undo")) self.sheet.extra_bindings([("cell_select", self.cell_select)]) self.sheet.grid(row=2, column=0, sticky="nswe", padx=5, pady=5) self.load_data_in_thread()
text='Quit', command=master.quit).grid(row=4, column=0, sticky='nswe', pady=4) search_button = tk.Button(master, text='Start Search', command=start_search) search_button.grid(row=4, column=1, sticky='nswe', pady=4) tk.Label(master, text="Click any cell to open URL").grid(row=6, column=0) ignored_label_text = tk.StringVar() ignored_label = tk.Label(master, textvariable=ignored_label_text) ignored_label.grid(row=6, column=1) tk.Label(master, text="").grid(row=7, column=0) sheet = Sheet(master, headers=['Name', 'Address', 'URL', 'Vaccine Types', 'Distance (miles)', 'Staleness (mins)']) sheet.enable_bindings() sheet.extra_bindings('cell_select', func=cell_selected) sheet.grid(row=8, column=0, columnspan=2, sticky='nswe') for x in range(2): tk.Grid.columnconfigure(master, x, weight=1) for y in range(6): tk.Grid.rowconfigure(master, y, weight=1) master.mainloop()
def __init__(self, customer_id): self.customer_id = customer_id ''' DATA ''' akun = DataAkun() self.akun = akun.getAccountsByCustomerId(customer_id) """ Window Configuration """ self.aroot = Tk() self.window_height = 700 #Window Height self.window_width = 1100 #Window Width self.screen_width = self.aroot.winfo_screenwidth() #Screen Width self.screen_height = self.aroot.winfo_screenheight() #Screen Height self.x_cordinate = int((self.screen_width / 2) - (self.window_width / 2)) self.y_cordinate = int((self.screen_height / 2) - (self.window_height / 2)) self.aroot.geometry("{}x{}+{}+{}".format( self.window_width, self.window_height, self.x_cordinate, 5)) #Implement and Center Window based on Device Screen self.aroot.config(bg='#00bd56') #Window Background self.aroot.overrideredirect(True) #Remove Window Status Bar self.aroot.resizable(False, False) #Disable Resizing Window """ Image Declaration """ imgTambah = PhotoImage(file='tampilan/images/tambah-btn.png') imgHapus = PhotoImage(file='tampilan/images/hapus-btn.png') imgExit = PhotoImage(file='tampilan/images/exit-btn.png') #Dashboard Icon Navbar dashimage = Image.open('tampilan/images/dashboard.png') dashImage = dashimage.resize((38, 38), Image.ANTIALIAS) dashboardIMG = ImageTk.PhotoImage(dashImage) #Account Icon Navbar checkImg = Image.open('tampilan/images/checkingicon.png') chImage = checkImg.resize((35, 35), Image.ANTIALIAS) accountImage = ImageTk.PhotoImage(chImage) #Transaction Icon Navbar saveImg = Image.open('tampilan/images/transfer.png') sImage = saveImg.resize((30, 30), Image.ANTIALIAS) transImage = ImageTk.PhotoImage(sImage) #Logout Icon Navbar logoutImg = Image.open('tampilan/images/logout.png') logImage = logoutImg.resize((30, 30), Image.ANTIALIAS) logoutImage = ImageTk.PhotoImage(logImage) #Dashboard Info Background Icon Navbar cusInfoImg = Image.open('tampilan/images/info-bg.png') cInfoImg = cusInfoImg.resize((180, 180), Image.ANTIALIAS) cIImg = ImageTk.PhotoImage(cInfoImg) #Account Info siIMG = Image.open('tampilan/images/savingicon.png') ssImg = siIMG.resize((80, 80), Image.ANTIALIAS) savIMG = ImageTk.PhotoImage(ssImg) #Balance Info chIMG = Image.open('tampilan/images/checkingicon.png') chsImg = chIMG.resize((80, 80), Image.ANTIALIAS) cheIMG = ImageTk.PhotoImage(chsImg) ############################################################################## ############ SIDEBAR CONTENT ########## ############################################################################## navbarLabel = Label(self.aroot, bg='#e5e5e5', width=30, height=self.window_height) navbarLabel.place(x=0, y=0) #Dashboard Icon Navbar dashboardNavIcon = Label(self.aroot, image=dashboardIMG, bg='#e5e5e5', cursor='hand2') dashboardNavIcon.place(x=15, y=25) dashboardNavIcon.bind("<Button>", self.bindingToDashboard) #Dashboard Label Navbar dashboardNavLabel = Label(self.aroot, text="DASHBOARD", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') dashboardNavLabel.place(x=55, y=25) dashboardNavLabel.bind("<Button>", self.bindingToDashboard) #Account Icon Navbar accNavIcon = Label(self.aroot, image=accountImage, bg='#e5e5e5', cursor='hand2') accNavIcon.place(x=15, y=80) accNavIcon.bind("<Button>", self.bindingToAccount) #Account Label Navbar accNavLabel = Label(self.aroot, text="ACCOUNT", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') accNavLabel.place(x=55, y=80) accNavLabel.bind("<Button>", self.bindingToAccount) #Transaction Icon Navbar transNavIcon = Label(self.aroot, image=transImage, bg='#e5e5e5', cursor='hand2') transNavIcon.place(x=15, y=140) transNavIcon.bind("<Button>", self.bindingToTranscation) #Transaction Label Navbar transNavLabel = Label(self.aroot, text="TRANSACTION", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') transNavLabel.place(x=55, y=140) transNavLabel.bind("<Button>", self.bindingToTranscation) #Logout Icon Navbar logoutNavIcon = Label(self.aroot, image=logoutImage, bg='#e5e5e5', cursor='hand2') logoutNavIcon.place(x=10, y=650) logoutNavIcon.bind("<Button>", self.doLogout) #Logout Label Navbar logoutNavLabel = Label(self.aroot, text="LOGOUT", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') logoutNavLabel.place(x=50, y=650) logoutNavLabel.bind("<Button>", self.doLogout) ############################################################################## ############ DASHBOARD CONTENT ########## ############################################################################## #Customer Page Title cusTitle = Label(self.aroot, text="Customer's Account", font=('Segoe UI', 20, BOLD), bg='#00bd56', fg='#e5e5e5') cusTitle.place(x=500, y=20) #Add Account Button Property addCButton = Button(self.aroot, image=imgTambah, border=0, bg='#00bd56', activebackground='#00bd56', command=self.tambahAkun, cursor='hand2') addCButton.place(x=960, y=550) headerLabel = ["Account Type", "Balance"] data = [] for raw in self.akun: tmpData = (raw.getType(), raw.getBalance()) data.append(tmpData) #Account Table frame = Frame(self.aroot) frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(0, weight=1) sheet = Sheet( frame, page_up_down_select_row=True, column_width=120, startup_select=(0, 1, "rows"), data= data, # [[f"{data_example[1][1]}" for c in range(4)] for r in range(5)], headers=[f"{c}" for c in headerLabel], theme="light green", height=480, width=700) sheet.enable_bindings( ("single_select", "drag_select", "select_all", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "copy", "cut", "paste", "delete", "undo")) frame.place(x=250, y=100) sheet.grid(row=0, column=0, sticky="nswe") #Hapus Account Button Property hapusButton = Button(self.aroot, image=imgHapus, border=0, bg='#00bd56', activebackground='#00bd56', command=self.hapusAkun, cursor='hand2') hapusButton.place(x=960, y=600) #Exit Button Property exitButton = Button(self.aroot, image=imgExit, border=0, bg='#00bd56', activebackground='#00bd56', command=self.aroot.destroy, cursor='hand2') exitButton.place(x=970, y=650) self.aroot.mainloop()
def __init__(self): """ Window Configuration """ self.loan = Tk() self.window_height = 700 #Window Height self.window_width = 1100 #Window Width self.screen_width = self.loan.winfo_screenwidth() #Screen Width self.screen_height = self.loan.winfo_screenheight() #Screen Height self.x_cordinate = int((self.screen_width / 2) - (self.window_width / 2)) self.y_cordinate = int((self.screen_height / 2) - (self.window_height / 2)) self.loan.geometry("{}x{}+{}+{}".format( self.window_width, self.window_height, self.x_cordinate, 5)) #Implement and Center Window based on Device Screen self.loan.config(bg='#23374d') #Window Background self.loan.overrideredirect(True) #Remove Window Status Bar self.loan.resizable(False, False) #Disable Resizing Window """ Image Declaration """ imgExit = PhotoImage(file='tampilan/images/exit-btn.png') #Dashboard Icon Navbar dashimage = Image.open('tampilan/images/dashboard.png') dashImage = dashimage.resize((38, 38), Image.ANTIALIAS) dashboardIMG = ImageTk.PhotoImage(dashImage) #Customer Icon Navbar cImage = Image.open('tampilan/images/customersicon.png') cuImage = cImage.resize((50, 50), Image.ANTIALIAS) cusImage = ImageTk.PhotoImage(cuImage) #Saving Icon Navbar saveImg = Image.open('tampilan/images/savingicon.png') sImage = saveImg.resize((30, 30), Image.ANTIALIAS) savingImage = ImageTk.PhotoImage(sImage) #Checking Icon Navbar checkImg = Image.open('tampilan/images/checkingicon.png') chImage = checkImg.resize((30, 30), Image.ANTIALIAS) checkImage = ImageTk.PhotoImage(chImage) #Loan Icon Navbar loanImg = Image.open('tampilan/images/loanicon.png') lImage = loanImg.resize((30, 30), Image.ANTIALIAS) loanImage = ImageTk.PhotoImage(lImage) #Logout Icon Navbar logoutImg = Image.open('tampilan/images/logout.png') logImage = logoutImg.resize((30, 30), Image.ANTIALIAS) logoutImage = ImageTk.PhotoImage(logImage) ############################################################################## ############ SIDEBAR ########## ############################################################################## navbarLabel = Label(self.loan, bg='#e5e5e5', width=30, height=self.window_height) navbarLabel.place(x=0, y=0) #Dashboard Icon Navbar dashboardNavIcon = Label(self.loan, image=dashboardIMG, bg='#e5e5e5', cursor='hand2') dashboardNavIcon.place(x=15, y=23) dashboardNavIcon.bind("<Button>", self.bindingToDashboard) #Dashboard Label Navbar dashboardNavLabel = Label(self.loan, text="DASHBOARD", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') dashboardNavLabel.place(x=65, y=25) dashboardNavLabel.bind("<Button>", self.bindingToDashboard) #Customer Icon Navbar allcusicon = Label(self.loan, image=cusImage, bg='#e5e5e5', cursor='hand2') allcusicon.place(x=10, y=73) allcusicon.bind("<Button>", self.bindingToCustomer) #Customer Label Navbar cusNavLabel = Label(self.loan, text="CUSTOMER", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') cusNavLabel.place(x=65, y=80) cusNavLabel.bind("<Button>", self.bindingToCustomer) #Saving Account Icon Navbar savingNavIcon = Label(self.loan, image=savingImage, bg='#e5e5e5', cursor='hand2') savingNavIcon.place(x=15, y=155) savingNavIcon.bind("<Button>", self.bindingToSavingAccount) #Saving Account Label Navbar savingNavLabel = Label(self.loan, text="SAVING \n ACCOUNT", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') savingNavLabel.place(x=55, y=140) savingNavLabel.bind("<Button>", self.bindingToSavingAccount) #Checking Account Icon Navbar checkNavIcon = Label(self.loan, image=checkImage, bg='#e5e5e5', cursor='hand2') checkNavIcon.place(x=15, y=245) checkNavIcon.bind("<Button>", self.bindingToCheckingAccount) #Checking Account Label Navbar checkNavLabel = Label(self.loan, text="CHECKING \n ACCOUNT", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') checkNavLabel.place(x=55, y=230) checkNavLabel.bind("<Button>", self.bindingToCheckingAccount) #Loan Account Icon Navbar loanNavIcon = Label(self.loan, image=loanImage, bg='#e5e5e5', cursor='hand2') loanNavIcon.place(x=15, y=335) loanNavIcon.bind("<Button>", self.bindingToLoanAccount) #Loan Account Label Navbar loanNavLabel = Label(self.loan, text="LOAN \n ACCOUNT", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') loanNavLabel.place(x=55, y=320) loanNavLabel.bind("<Button>", self.bindingToLoanAccount) #Logout Icon Navbar logoutNavIcon = Label(self.loan, image=logoutImage, bg='#e5e5e5', cursor='hand2') logoutNavIcon.place(x=10, y=650) logoutNavIcon.bind("<Button>", self.doLogout) #Logout Label Navbar logoutNavLabel = Label(self.loan, text="LOGOUT", font=('Segoe UI', 16, BOLD), bg='#e5e5e5', fg='#23374d', cursor='hand2') logoutNavLabel.place(x=50, y=650) logoutNavLabel.bind("<Button>", self.doLogout) #Customer Page Title cusTitle = Label(self.loan, text="Loan Account Bank", font=('Segoe UI', 20, BOLD), bg='#23374d', fg='#e5e5e5') cusTitle.place(x=550, y=20) #Exit Button Property exitButton = Button(self.loan, image=imgExit, border=0, bg='#23374d', activebackground='#23374d', command=self.loan.destroy, cursor='hand2') exitButton.place(x=980, y=650) ############################################################################## ############ LOAN ACCOUNT CONTENT ########## ############################################################################## loanAccount = DataLoanAccount() tmpData = loanAccount.getAllLoans() customer = DataCustomer() datas = [] for dt in tmpData: tmpCustomer = customer.getCustomerById(dt.getId()) tmpDt = (tmpCustomer.getName(), dt.getBalance()) datas.append(tmpDt) headerLabel = ["Customer Name", "Account Balance"] #Account Table frame = Frame(self.loan) frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(0, weight=1) sheet = Sheet( frame, page_up_down_select_row=True, column_width=120, startup_select=(0, 1, "rows"), data= datas, #[[f"{data_example[1][1]}" for c in range(2)] for r in range(5)], headers=[f"{c}" for c in headerLabel], theme="light green", height=480, width=700) sheet.enable_bindings( ("single_select", "drag_select", "select_all", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "copy", "cut", "paste", "delete", "undo")) frame.place(x=280, y=150) sheet.grid(row=0, column=0, sticky="nswe") self.loan.mainloop()
class demo(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.frame = tk.Frame(self) self.frame.grid_columnconfigure(0, weight=1) self.frame.grid_rowconfigure(0, weight=1) self.sheet = Sheet( self.frame, page_up_down_select_row=True, #empty_vertical = 0, column_width=120, startup_select=(0, 1, "rows"), #row_height = "4", #default_row_index = "numbers", #default_header = "both", #empty_horizontal = 0, #show_vertical_grid = False, #show_horizontal_grid = False, #auto_resize_default_row_index = False, #header_height = "3", #row_index_width = 100, #align = "center", #header_align = "w", #row_index_align = "w", data=[[ f"Row {r}, Column {c}\nnewline1\nnewline2" for c in range(50) ] for r in range(1000)], #to set sheet data at startup #headers = [f"Column {c}\nnewline1\nnewline2" for c in range(30)], #row_index = [f"Row {r}\nnewline1\nnewline2" for r in range(2000)], #set_all_heights_and_widths = True, #to fit all cell sizes to text at start up #headers = 0, #to set headers as first row at startup #headers = [f"Column {c}\nnewline1\nnewline2" for c in range(30)], #theme = "light green", #row_index = 0, #to set row_index as first column at startup #total_rows = 2000, #if you want to set empty sheet dimensions at startup #total_columns = 30, #if you want to set empty sheet dimensions at startup height=500, #height and width arguments are optional width=1200 #For full startup arguments see DOCUMENTATION.md ) #self.sheet.hide("row_index") #self.sheet.hide("header") #self.sheet.hide("top_left") self.sheet.enable_bindings(( "single_select", #"single_select" or "toggle_select" "drag_select", #enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", #"row_width_resize", #"column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "copy", "cut", "paste", "delete", "undo", "edit_cell")) #self.sheet.disable_bindings() #uses the same strings #self.sheet.enable_bindings() self.frame.grid(row=0, column=0, sticky="nswe") self.sheet.grid(row=0, column=0, sticky="nswe") """_________________________ EXAMPLES _________________________ """ """_____________________________________________________________""" # __________ CHANGING THEME __________ #self.sheet.change_theme("light green") # __________ HIGHLIGHT / DEHIGHLIGHT CELLS __________ self.sheet.highlight_cells(row=5, column=5, bg="#ed4337", fg="white") self.sheet.highlight_cells(row=5, column=1, bg="#ed4337", fg="white") self.sheet.highlight_cells(row=5, bg="#ed4337", fg="white", canvas="row_index") self.sheet.highlight_cells(column=0, bg="#ed4337", fg="white", canvas="header") #self.sheet.highlight_rows(6, "green") #self.sheet.highlight_columns(4, "yellow") # __________ DISPLAY SUBSET OF COLUMNS __________ #self.sheet.display_subset_of_columns(indexes = [1, 0, 2, 10, 15, 20, 25, 35, 30, 36, 39, 9, 5, 11, 12, 43, 45], enable = True) #any order # __________ DATA AND DISPLAY DIMENSIONS __________ #self.sheet.total_rows(4) #will delete rows if set to less than current data rows #self.sheet.total_columns(2) #will delete columns if set to less than current data columns #self.sheet.sheet_data_dimensions(total_rows = 4, total_columns = 2) #self.sheet.sheet_display_dimensions(total_rows = 4, total_columns = 6) #currently resets widths and heights #self.sheet.set_sheet_data_and_display_dimensions(total_rows = 4, total_columns = 2) #currently resets widths and heights # __________ SETTING OR RESETTING TABLE DATA __________ #.set_sheet_data() function returns the object you use as argument #verify checks if your data is a list of lists, raises error if not #self.data = self.sheet.set_sheet_data([[f"Row {r} Column {c}" for c in range(30)] for r in range(2000)], verify = False) # __________ SETTING ROW HEIGHTS AND COLUMN WIDTHS __________ #self.sheet.set_cell_data(0, 0, "\n".join([f"Line {x}" for x in range(500)])) #self.sheet.set_column_data(1, ("" for i in range(2000))) #self.sheet.row_index((f"Row {r}" for r in range(2000))) #any iterable works #self.sheet.row_index("\n".join([f"Line {x}" for x in range(500)]), 2) #self.sheet.column_width(column = 0, width = 300) #self.sheet.row_height(row = 0, height = 60) #self.sheet.set_column_widths([120 for c in range(30)]) #self.sheet.set_row_heights([30 for r in range(2000)]) #self.sheet.set_all_column_widths() #self.sheet.set_all_row_heights() #self.sheet.set_all_cell_sizes_to_text() # __________ BINDING A FUNCTIONS TO USER ACTIONS __________ #self.sheet.extra_bindings([("cell_select", self.cell_select), # ("begin_edit_cell", self.begin_edit_cell), # ("end_edit_cell", self.end_edit_cell), # ("shift_cell_select", self.shift_select_cells), # ("drag_select_cells", self.drag_select_cells), # ("ctrl_a", self.ctrl_a), # ("row_select", self.row_select), # ("shift_row_select", self.shift_select_rows), # ("drag_select_rows", self.drag_select_rows), # ("column_select", self.column_select) # ("shift_column_select", self.shift_select_columns), # ("drag_select_columns", self.drag_select_columns), # ("deselect", self.deselect) # ]) #self.sheet.extra_bindings("bind_all", self.all_extra_bindings) #self.sheet.extra_bindings("begin_edit_cell", self.begin_edit_cell) #self.sheet.extra_bindings([("cell_select", None)]) #unbind cell select #self.sheet.extra_bindings("unbind_all") #remove all functions set by extra_bindings() # __________ BINDING NEW RIGHT CLICK FUNCTION __________ #self.sheet.bind("<3>", self.rc) # __________ SETTING HEADERS __________ #self.sheet.headers((f"Header {c}" for c in range(30))) #any iterable works #self.sheet.headers("Change header example", 2) #print (self.sheet.headers()) #print (self.sheet.headers(index = 2)) # __________ SETTING ROW INDEX __________ #self.sheet.row_index((f"Row {r}" for r in range(2000))) #any iterable works #self.sheet.row_index("Change index example", 2) #print (self.sheet.row_index()) #print (self.sheet.row_index(index = 2)) # __________ INSERTING A ROW __________ #self.sheet.insert_row(values = (f"my new row here {c}" for c in range(30)), idx = 0) # a filled row at the start #self.sheet.insert_row() # an empty row at the end # __________ INSERTING A COLUMN __________ #self.sheet.insert_column(values = (f"my new col here {r}" for r in range(2050)), idx = 0) # a filled column at the start #self.sheet.insert_column() # an empty column at the end # __________ SETTING A COLUMNS DATA __________ # any iterable works #self.sheet.set_column_data(0, values = (0 for i in range(2050))) # __________ SETTING A ROWS DATA __________ # any iterable works #self.sheet.set_row_data(0, values = (0 for i in range(35))) # __________ SETTING A CELLS DATA __________ #self.sheet.set_cell_data(1, 2, "NEW VALUE") # __________ GETTING FULL SHEET DATA __________ #self.all_data = self.sheet.get_sheet_data() # __________ GETTING CELL DATA __________ #print (self.sheet.get_cell_data(0, 0)) # __________ GETTING ROW DATA __________ #print (self.sheet.get_row_data(0)) # only accessible by index # __________ GETTING COLUMN DATA __________ #print (self.sheet.get_column_data(0)) # only accessible by index # __________ GETTING SELECTED __________ #print (self.sheet.get_currently_selected()) #print (self.sheet.get_selected_cells()) #print (self.sheet.get_selected_rows()) #print (self.sheet.get_selected_columns()) #print (self.sheet.get_selection_boxes()) #print (self.sheet.get_selection_boxes_with_types()) # __________ SETTING SELECTED __________ #self.sheet.deselect("all") #self.sheet.create_selection_box(0, 0, 2, 2, type_ = "cells") #type here is "cells", "cols" or "rows" #self.sheet.set_currently_selected(0, 0) #self.sheet.set_currently_selected("row", 0) #self.sheet.set_currently_selected("column", 0) # __________ CHECKING SELECTED __________ #print (self.sheet.cell_selected(0, 0)) #print (self.sheet.row_selected(0)) #print (self.sheet.column_selected(0)) #print (self.sheet.anything_selected()) #print (self.sheet.all_selected()) # __________ HIDING THE ROW INDEX AND HEADERS __________ #self.sheet.hide("row_index") #self.sheet.hide("top_left") #self.sheet.hide("header") # __________ ADDITIONAL BINDINGS __________ #self.sheet.bind("<Motion>", self.mouse_motion) """ UNTIL DOCUMENTATION IS COMPLETE, PLEASE BROWSE THE FILE _tksheet.py FOR A FULL LIST OF FUNCTIONS AND THEIR PARAMETERS """ def all_extra_bindings(self, event): print(event) def begin_edit_cell(self, event): print(event) # event[2] is keystroke return event[ 2] # return value is the text to be put into cell edit window def end_edit_cell(self, event): print(event) def window_resized(self, event): pass #print (event) def mouse_motion(self, event): region = self.sheet.identify_region(event) row = self.sheet.identify_row(event, allow_end=False) column = self.sheet.identify_column(event, allow_end=False) print(region, row, column) def deselect(self, event): print(event, self.sheet.get_selected_cells()) def rc(self, event): print(event) def cell_select(self, response): #print (response) pass def shift_select_cells(self, response): print(response) def drag_select_cells(self, response): pass #print (response) def ctrl_a(self, response): print(response) def row_select(self, response): print(response) def shift_select_rows(self, response): print(response) def drag_select_rows(self, response): pass #print (response) def column_select(self, response): print(response) #for i in range(50): # self.sheet.create_dropdown(i, response[1], values=[f"{i}" for i in range(200)], set_value="100", # destroy_on_select = False, destroy_on_leave = False, see = False) #print (self.sheet.get_cell_data(0, 0)) #self.sheet.refresh() def shift_select_columns(self, response): print(response) def drag_select_columns(self, response): pass
btn1.configure(text='Push Me!') btn2 = Button(frame1) registerGUIElement('btn2', btn2) btn2.configure(text='Another one!') btn2.configure(bg='red') btn2.configure(fg='white') btn2.configure(font='JohnDoe 24 bold') sheet1 = Sheet(frame1, data=[[1, 2, 3], [4, 5, 6]]) registerGUIElement('sheet1', sheet1) btn1.bind('<Button-1>', onBtnClicked) #Hay que poner codigo para grid?? #frame1.grid(column=0,row=0,columnspan=4,rowspan=4,sticky="nsew") frame1.pack(anchor="sw") txt1.grid(column=1, row=0, rowspan=2) btn1.grid(column=2, row=0, rowspan=2) btn2.grid(column=0, row=3, columnspan=3, sticky="nsew") sheet1.grid(column=0, row=4, columnspan=4, sticky="nsew") print(frame1.grid_slaves()) root.config(menu=main_menu) import tkinter.font import pprint pprint.pprint(tkinter.font.families()) root.winfo_children()[0].after(20, __collectValues) root.mainloop() print(getValues())