class askdataset( Dialog ): def __init__(self, parent, h5name, title=None): self.h5name = h5name Dialog.__init__(self, parent, title=title) def body(self, parent): Tk.Label(parent, text="HDF5 File: "+self.h5name).pack() self.tree = Treeview( parent, selectmode = "browse", columns = ("path",'title',) ) root = self.tree.insert("","end",text="/", values=('/',"",), open=True) self.additems( root ) self.tree.pack(fill=Tk.BOTH, expand=1) self.tree.bind('<<TreeviewOpen>>', self.update_tree) self.tree.bind('<<TreeviewSelect>>', self.setresult) def additems( self, node ): gid = self.tree.set( node )['path'] self.tree.delete( *self.tree.get_children(node) ) with h5py.File( self.h5name, "r" ) as h5o: if gid == "/": grp = h5o else: grp = h5o[gid] if isinstance( grp, h5py.Dataset ): return for idx, item in enumerate(list(grp)): thing = grp[item] if isinstance(thing, h5py.Group): if 'title' in grp[item]: title = grp[item]['title'][()] else: title = "" elif isinstance(thing, h5py.Dataset): title = str(thing.shape) else: title = str(type(thing)) if gid != "/": fullpath = gid+"/"+item else: fullpath = item oid = self.tree.insert(node, idx, text=item, values=( fullpath, title,)) if isinstance(thing, h5py.Group): self.tree.insert( oid, "end" ) # dummy entry def update_tree( self, event ): self.tree = event.widget self.additems( self.tree.focus() ) def setresult(self, event): self.result = self.tree.set( self.tree.focus() )['path']
class DeviceToFrame(CopilotInnerFrame): def __init__(self, master, config, state): super(DeviceToFrame, self).__init__(master, config) self._state = state if self._state.action == 'copy': self._frame_lbl['text'] = 'Copy To Directory' elif self._state.action == 'delete': self._frame_lbl['text'] = 'Delete From Directory' self._next_btn['command'] = self._next_cmd self._tree = Treeview(self._master, columns=('size')) self._tree.heading('size', text='Size') self._tree.grid(row=1, column=0, columnspan=3, sticky='nsew') self._tree.configure(yscrollcommand=self._sb.set) self._sb['command'] = self._tree.yview self._item_paths = {} self._populate_tree(self._state.to_device.part().mount()) def _next_cmd(self): cur_item = self._tree.focus() cur_path = self._item_paths.get(cur_item, '') if cur_path != '': self._state.device_to_path = cur_path self._new_state_window(CopyFileFrame, self._state) def _populate_tree(self, tree_root): self._item_paths = {} def insert_path(tree, path, parent_id): dirs = [e for e in scandir(path) if e.is_dir()] dirs.sort(key=lambda e: e.name) for d in dirs: dir_name = d.name dir_id = '{}-{}'.format(parent_id, dir_name) dir_path = os.path.join(path, dir_name) tree.insert(parent_id, 'end', dir_id, text=dir_name, tags=('dir')) self._item_paths[dir_id] = dir_path try: insert_path(tree, dir_path, dir_id) except: pass insert_path(self._tree, tree_root, '') tree = self._tree tree.tag_configure('dir', font=self._config.item_font) tree.tag_configure('file', font=self._config.item_font) tree.tag_configure('file_odd', background='light grey')
class MultipleInstallPage(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.controller = controller # will do a 4x4 grid here for count in range(0, 4): Grid.rowconfigure(self, count, weight=1) Grid.columnconfigure(self, count, weight=1) self.temp_tv = Treeview(self) temp_tv = self.temp_tv temp_tv.grid(row=0, column=0, rowspan=3, columnspan=4, sticky=(N, E, W, S)) temp_tv.heading('#0', text="Choose one:") temp_tv.column("#0", minwidth=300) # adding scrollbar ysb = Scrollbar(self, orient='vertical', command=temp_tv.yview) temp_tv.configure(yscroll=ysb.set) ysb.grid(row=0, column=3, rowspan=3, sticky='nse') # Buttons for the rest ok_button = Button(self, text="Ok", command=self.ok_button_click) ok_button.grid(row=3, column=0, sticky=N + S + E + W) cancel_button = Button(self, text="Cancel", command=lambda: controller.show_frame(MainPage)) cancel_button.grid(row=3, column=3, sticky=N + S + E + W) def ok_button_click(self): # Should only do stuff is something is selected if self.temp_tv.focus() != '': installer_path = self.temp_tv.item(self.temp_tv.focus())['text'] launch_installer(installer_path) self.controller.show_frame(MainPage) else: return -1
class hey: def __init__(self): self.star1 = Toplevel() self.obj = database.Database() self.result = self.obj.getmenu() self.star1.geometry('1366x768') self.can = Canvas(self.star1, height=768, width=1366) self.can.pack() self.img = PhotoImage(file='./image/654.png') self.can.create_image(0, 0, image=self.img, anchor=NW) self.table = Treeview(self.can, columns=("#0", "#1", "#2", "#3", "#4")) self.table.heading('#0', text="Sr no.") self.table.column('#0', width=40) self.table.heading('#1', text="Name") self.table.column('#1', width=100) self.table.heading('#2', text="Amount") self.table.column('#2', width=100) self.table.heading('#3', text="edit") self.table.column('#3', width=100) self.table.heading('#4', text="delete") self.table.column('#4', width=100) for i in self.result: self.table.insert('', 'end', text=i[0], values=(i[1], i[2], "edit", "Delete")) self.table.place(x=300, y=300) self.btn = Button(self.can, text="<- Back", fg='white', bg='black', font=('monaco', 15, 'bold'), command=self.back) self.btn.place(x=810, y=540) self.table.bind("<Double-Button-1>", self.trigger) self.star1.resizable(height=False, width=False) self.star1.state("zoomed") self.star1.mainloop() def back(self): self.star1.destroy() def trigger(self, e): f = self.table.focus() x = self.table.item(f) col = self.table.identify_column(e.x) if (col == "#3"): self.star1.destroy() obj = updatemenu.UpdateMenu(x["text"]) elif (col == "#4"): self.star1.destroy() d = database.Database() d.delete(x["text"])
def select_item(self, event: tk.Event, prop_class: Union[EXIFProperty, GPSProperty], tree: ttk.Treeview): query_item: Union[Tuple, str] = tree.item(tree.focus(), option='values') if query_item == '': return col: str = tree.identify_column(getattr(event, 'x')) prop, val = query_item if col == '#1': if isinstance(prop_class, IFDPanel.EXIFProperty) and prop == prop_class.file_name: os.startfile(self.app.widget_info.cur_img_path) return # '#2' if isinstance(prop_class, IFDPanel.EXIFProperty) and prop == prop_class.file_name: val = self.app.widget_info.cur_img_path.stem tree.clipboard_clear() tree.clipboard_append(val)
class Window: def __init__(self): self.tk = Tk() self.tk.geometry('500x500') fetch = (getdata.fetch()) self.tree = Treeview(self.tk, columns=("#1", "#2", "#3", "#4")) self.tree.heading("#0", text="user id") self.tree.column("#0", width=60) self.tree.heading("#1", text="User Name") self.tree.heading("#2", text="Password") self.tree.heading("#3", text="Update") self.tree.heading("#4", text="Delete") self.data = getdata.fetch() for i in self.data: self.tree.insert('', 'end', text=i[0], values=(i[1], i[2], "update", "delete")) self.tree.place(x=0, y=0) self.tree.bind("<Double-Button-1>", self.trigger) self.tk.mainloop() def trigger(self, e): #e will identify from where the function has been triggered print(e) #d will store the object of focused element in the treeview d = self.tree.focus() #self.tree.item is use to get the data from the focused row #so thats why we pass the focused item there d x = (self.tree.item(d)) print(x) #col will identify the focused column col = self.tree.identify_column(e.x) if col == "#3": print("Update") elif col == "#4": getdata.delete(x["text"]) print("delete")
class ManagerWindow: """ 主管理界面入口类,直接无参数创建对象即可。 """ # 窗口宽高 WIN_WIDTH = 800 WIN_HEIGHT = 600 def __init__(self): # 界面根节点 self.root = Tk() # 主窗口标题 self.root.title(MANAGER_TITLE) # 读取config self.config_dict = ConfigOperation.get_dir_from_file() # 主窗口分辨率 self.root.geometry("%sx%s+%s+%s" % ( self.WIN_WIDTH, self.WIN_HEIGHT, int((self.root.winfo_screenwidth() - self.WIN_WIDTH) / 2), int((self.root.winfo_screenheight() - self.WIN_HEIGHT) / 2) )) self.root.minsize(self.WIN_WIDTH, self.WIN_HEIGHT) # 选项卡 self.tab_main = Notebook(self.root) self.tab_main.pack(expand=True, fill=BOTH) # 登录选项卡 self.frame_login = Frame(self.tab_main, bg=BG_COLOR) self.frame_login.pack(side=TOP) self.tab_main.add(self.frame_login, text=TAB_NAME_LIST["login"]["text"]) # 管理选项卡 self.frame_manage = Frame(self.tab_main, bg=BG_COLOR) self.tab_main.add(self.frame_manage, text=TAB_NAME_LIST["manage"]["text"]) # 好友选项卡 self.frame_friend = Frame(self.tab_main, bg=BG_COLOR) self.frame_friend.pack(side=TOP) self.tab_main.add(self.frame_friend, text=TAB_NAME_LIST["friends"]["text"]) # 群选项卡 self.frame_group = Frame(self.tab_main, bg=BG_COLOR) self.frame_group.pack(side=TOP) self.tab_main.add(self.frame_group, text=TAB_NAME_LIST["groups"]["text"]) # 插件选项卡 self.frame_plugin = Frame(self.tab_main, bg=BG_COLOR) self.frame_plugin.pack(side=TOP) self.tab_main.add(self.frame_plugin, text=TAB_NAME_LIST["plugins"]["text"]) # 初始化登录选项卡 self.__init_login_tab() # 初始化好友选项卡 self.__init_friend_tab() # 初始化群选项卡 self.__init_group_tab() # 初始化管理选项卡 self.__init_manage_tab() # 初始化插件选项卡 self.__init_plugin_tab() # 关闭窗口自动释放Session self.root.protocol("WM_DELETE_WINDOW", lambda: self.__on_close_root()) # 刷新显示 self.__refresh() # 运行相关线程 fetch_message_thread = FetchMessageThread() fetch_message_thread.daemon = True fetch_message_thread.start() # 运行插件初始化方法 PluginHandler.call_init() # 执行自动连接一次 self.__auto_connect() # 显示 self.root.mainloop() def __init_login_tab(self): """ 初始化登录选项卡界面 :return: 无 """ # 左边列表的frame frame_login_list = Frame(self.frame_login, bg=BG_COLOR) frame_login_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 列表,用于保存连接记录 self.treeview_login_list = Treeview( frame_login_list, columns=[ LOGIN_GUIDE["host"], LOGIN_GUIDE["port"], LOGIN_GUIDE["authkey"], LOGIN_GUIDE["qq"] ], show="headings", selectmode=BROWSE ) self.treeview_login_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_login_list.column( LOGIN_GUIDE["host"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["host"], text=LOGIN_GUIDE["host"] ) self.treeview_login_list.column( LOGIN_GUIDE["port"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["port"], text=LOGIN_GUIDE["port"] ) self.treeview_login_list.column( LOGIN_GUIDE["authkey"], width=40 ) self.treeview_login_list.heading( LOGIN_GUIDE["authkey"], text=LOGIN_GUIDE["authkey"] ) self.treeview_login_list.column( LOGIN_GUIDE["qq"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["qq"], text=LOGIN_GUIDE["qq"] ) # 设定双击事件 self.treeview_login_list.bind( "<Double-Button-1>", lambda event: self.__on_double_click_login_list_content() ) # 设定登录列表的滚动条 scrollbar_login_list = Scrollbar(frame_login_list) scrollbar_login_list.pack(fill="y", expand=True) self.treeview_login_list.config(yscrollcommand=scrollbar_login_list.set) scrollbar_login_list.config(command=self.treeview_login_list.yview) # 设置列表右键菜单 self.treeview_login_list.bind("<Button-3>", self.__show_login_list_pop_up_menu) # 登录界面显示的那一坨 frame_login_menu = Frame(self.frame_login, bg=BG_COLOR) frame_login_menu.pack(side=LEFT, padx=5, pady=5) # mirai端地址 Label(frame_login_menu, text=LOGIN_GUIDE["host"], bg=BG_COLOR).grid(row=0, sticky=E, padx=5, pady=5) self.entry_host = Entry(frame_login_menu) self.entry_host.grid(row=0, column=1, sticky=W, padx=5, pady=5) # mirai端端口号 Label(frame_login_menu, text=LOGIN_GUIDE["port"], bg=BG_COLOR).grid(row=1, sticky=E, padx=5, pady=5) self.entry_port = Entry(frame_login_menu) self.entry_port.grid(row=1, column=1, sticky=W, padx=5, pady=5) # mirai端http授权码 Label(frame_login_menu, text=LOGIN_GUIDE["authkey"], bg=BG_COLOR).grid( row=2, sticky=E, padx=5, pady=5 ) self.entry_authkey = Entry(frame_login_menu, show=PWD_CHAR_CIRCLE) self.entry_authkey.grid(row=2, column=1, sticky=W, padx=5, pady=5) # 用于激活sessioKey的qq号码 Label(frame_login_menu, text=LOGIN_GUIDE["qq"], bg=BG_COLOR).grid( row=3, sticky=E, padx=5, pady=5 ) self.entry_qq = Entry(frame_login_menu) self.entry_qq.grid(row=3, column=1, sticky=W, padx=5, pady=5) # 自动连接复选框 self.auto_connect_var = BooleanVar() self.checkbutton_auto_connect = Checkbutton( frame_login_menu, text=AUTO_CONNECT_GUIDE, onvalue=True, offvalue=False, variable=self.auto_connect_var, bg=BG_COLOR ) self.checkbutton_auto_connect.grid(row=4, column=0, padx=5, pady=5, columnspan=2) # 连接按钮 self.btn_connect = Button( frame_login_menu, text=BTN_TEXT_CONN["connect"], width=15, command=lambda: self.__on_click_connect_event(), ) self.btn_connect.grid(row=5, columnspan=2, padx=5, pady=5) # 添加到登录列表按钮 self.btn_save_login = Button( frame_login_menu, width=15, text=BTN_TEXT_ADD_LOGIN, command=lambda: self.__on_click_add_to_login_list() ) self.btn_save_login.grid(row=6, columnspan=2, padx=5, pady=5) # 状态栏 self.label_login_status_bar = Label( self.root, text=LOGIN_STATUS_BAR_TEXT["notConnect"], fg=STATUS_BAR_COLOR["normal"] ) self.label_login_status_bar.pack(side=LEFT) # 下面开始从config中将内容填充进文本框中 self.entry_host.delete(0, END) self.entry_host.insert(END, self.config_dict["lastConnection"]["host"]) self.entry_port.delete(0, END) self.entry_port.insert(END, self.config_dict["lastConnection"]["port"]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, self.config_dict["lastConnection"]["authkey"]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, self.config_dict["lastConnection"]["qq"]) # 自动连接复选框内容 self.auto_connect_var.set(self.config_dict["autoConnect"]) def __init_friend_tab(self): """ 初始化好友选项卡内容 :return: 无 """ # 创建好友列表框架 frame_friend_list = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_friend_send = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_friend_list = Treeview( frame_friend_list, columns=[ FRIEND_GUIDE["qq"], FRIEND_GUIDE["nickname"], FRIEND_GUIDE["remark"] ], show="headings", selectmode=BROWSE ) self.treeview_friend_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_friend_list.column( FRIEND_GUIDE["qq"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["qq"], text=FRIEND_GUIDE["qq"] ) self.treeview_friend_list.column( FRIEND_GUIDE["nickname"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["nickname"], text=FRIEND_GUIDE["nickname"] ) self.treeview_friend_list.column( FRIEND_GUIDE["remark"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["remark"], text=FRIEND_GUIDE["remark"] ) # 设定好友列表的滚动条 scrollbar_friend_list = Scrollbar(frame_friend_list) scrollbar_friend_list.pack(fill="y", expand=True) self.treeview_friend_list.config(yscrollcommand=scrollbar_friend_list.set) scrollbar_friend_list.config(command=self.treeview_friend_list.yview) # 刷新列表按钮 Button( frame_friend_send, text=BTN_FRIEND_REFRESH, command=lambda: self.__on_click_refresh_friend_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_friend_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_friend_send = Text(frame_friend_send, width=30, height=5) self.text_friend_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_friend_send, text=BTN_SEND, command=lambda: self.__on_click_send_friend_message() ).grid(row=3, padx=5, pady=5) def __init_group_tab(self): """ 初始化群选项卡内容 :return: 无 """ # 创建好友列表框架 frame_group_list = Frame(self.frame_group, bg=BG_COLOR) frame_group_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_group_send = Frame(self.frame_group, bg=BG_COLOR) frame_group_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_group_list = Treeview( frame_group_list, columns=[ GROUP_GUIDE["group"], GROUP_GUIDE["name"], GROUP_GUIDE["permission"] ], show="headings", selectmode=BROWSE ) self.treeview_group_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_group_list.column( GROUP_GUIDE["group"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["group"], text=GROUP_GUIDE["group"] ) self.treeview_group_list.column( GROUP_GUIDE["name"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["name"], text=GROUP_GUIDE["name"] ) self.treeview_group_list.column( GROUP_GUIDE["permission"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["permission"], text=GROUP_GUIDE["permission"] ) # 设定群列表的滚动条 scrollbar_group_list = Scrollbar(frame_group_list) scrollbar_group_list.pack(fill="y", expand=True) self.treeview_group_list.config(yscrollcommand=scrollbar_group_list.set) scrollbar_group_list.config(command=self.treeview_group_list.yview) # 刷新列表按钮 Button( frame_group_send, text=BTN_GROUP_REFRESH, command=lambda: self.__on_click_refresh_group_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_group_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_group_send = Text(frame_group_send, width=30, height=5) self.text_group_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_group_send, text=BTN_SEND, command=lambda: self.__on_click_send_group_message() ).grid(row=3, padx=5, pady=5) def __init_manage_tab(self): """ 初始化管理选项卡 :return: 无 """ f_manage = Frame(self.frame_manage, bg=BG_COLOR) f_manage.pack(padx=5, pady=5, expand=True) # 指定头指示 Label(f_manage, text=MANAGE_GUIDE["commandHead"], bg=BG_COLOR).grid( row=0, column=0, padx=5, pady=5, sticky=E ) # 指令头文本框 self.entry_command_head = Entry(f_manage) self.entry_command_head.grid(row=0, column=1, padx=5, pady=5, sticky=EW) # 调试复选框 self.debug_var = BooleanVar() checkbutton_debug = Checkbutton( f_manage, text=MANAGE_GUIDE["debug"], onvalue=True, offvalue=False, variable=self.debug_var, bg=BG_COLOR ) checkbutton_debug.grid(row=1, column=0, columnspan=3, padx=5, pady=5) # 启用机器人 self.enable_var = BooleanVar() checkbutton_enable = Checkbutton( f_manage, text=MANAGE_GUIDE["enable"], onvalue=True, offvalue=False, variable=self.enable_var, bg=BG_COLOR ) checkbutton_enable.grid(row=2, column=0, columnspan=3, padx=5, pady=5) # 配置保存 Button( f_manage, text=MANAGE_GUIDE["saveConfig"], command=self.__on_click_save_config ).grid( row=3, column=1, padx=5, pady=5, sticky=EW ) # bot管理qq列表 self.treeview_op_list = Treeview( f_manage, columns=[ MANAGE_GUIDE["botOpQQ"] ], show="headings", selectmode=BROWSE ) self.treeview_op_list.column(MANAGE_GUIDE["botOpQQ"], width=200) self.treeview_op_list.heading(MANAGE_GUIDE["botOpQQ"], text=MANAGE_GUIDE["botOpQQ"]) self.treeview_op_list.grid( row=4, column=0, columnspan=3, rowspan=10, sticky=EW ) # 列表右键 self.treeview_op_list.bind("<Button-3>", self.__show_op_list_pop_up_menu) # 添加管理标签 Label(f_manage, text=MANAGE_GUIDE["addOpQQ"], bg=BG_COLOR).grid(row=14, column=0, padx=5, pady=5) # 添加管理文本框 self.entry_add_op = Entry(f_manage) self.entry_add_op.grid(row=14, column=1, padx=5, pady=5) # 添加添加按钮 Button( f_manage, text=MANAGE_GUIDE["btnAddOpQQ"], command=lambda: self.__on_click_add_op() ).grid(row=14, column=2, padx=5, pady=5, sticky=EW) def __init_plugin_tab(self): """ 初始化插件选项卡 :return: 无 """ # 指示标签 Label(self.frame_plugin, text=PLUGIN_LABEL_TEXT, bg=BG_COLOR).pack(side=TOP) # 插件列表frame frame_plugin_list = Frame(self.frame_plugin, bg=BG_COLOR) frame_plugin_list.pack( side=TOP, expand=True, fill=BOTH, padx=5, pady=5 ) # 插件列表 self.treeview_plugin_list = Treeview( frame_plugin_list, columns=[ PLUGIN_GUIDE["pluginName"] ], show="headings", selectmode=BROWSE ) self.treeview_plugin_list.pack(fill=BOTH, expand=True, side=LEFT) self.treeview_plugin_list.column(PLUGIN_GUIDE["pluginName"]) self.treeview_plugin_list.heading(PLUGIN_GUIDE["pluginName"], text=PLUGIN_GUIDE["pluginName"]) # 设定插件列表滚动条 scrollbar_plugin_list = Scrollbar(frame_plugin_list) scrollbar_plugin_list.pack(fill="y", expand=True) self.treeview_plugin_list.config(yscrollcommand=scrollbar_plugin_list.set) scrollbar_plugin_list.config(command=self.treeview_plugin_list.yview) def __on_click_connect_event(self): """ 点击连接按钮事件 :return: 无 """ if not GlobalValues.is_connected: # 如果是要连接 # 存到全局使用变量 GlobalValues.conn_host = self.entry_host.get() GlobalValues.conn_port = self.entry_port.get() GlobalValues.conn_authkey = self.entry_authkey.get() try: # 转换为整型后保存 GlobalValues.conn_qq = int(self.entry_qq.get()) except ValueError: self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["wrongQQ"], fg=STATUS_BAR_COLOR["failed"]) return # 修改界面上的一些内容为不可修改 self.__set_login_tools_active(False) # 修改按钮内容 self.btn_connect.config(text=BTN_TEXT_CONN["disconnect"]) # 修改状态栏内容 self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["connecting"], fg=STATUS_BAR_COLOR["normal"]) # 调用连接 try: Conn.new_session_key() except ( requests.exceptions.InvalidURL, requests.exceptions.ConnectionError, ): # 连接错误 # 错误信息显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connectFailed"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except WrongAuthkeyException: # 授权码错误 # 显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["wrongAuthkey"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except BotNotExistException: # bot不存在错误 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["qqNotExist"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connected"], fg=STATUS_BAR_COLOR["passed"] ) # 修改连接状态值 GlobalValues.is_connected = True # 修改上次连接键值对 ConfigOperation.modify_dict("lastConnection", { "host": GlobalValues.conn_host, "port": GlobalValues.conn_port, "authkey": GlobalValues.conn_authkey, "qq": GlobalValues.conn_qq }) # 修改文件中自动连接开关 ConfigOperation.modify_dict("autoConnect", self.auto_connect_var.get()) else: # 如果要断开连接 # 修改文本框为可修改 self.__set_login_tools_active(True) # 修改按钮名称 self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) # 修改属性值 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["disconnectSuccess"], fg=STATUS_BAR_COLOR["normal"] ) # 释放session Conn.release_session_key() # 修改连接状态值 GlobalValues.is_connected = False def __set_login_tools_active(self, active: bool): """ 修改界面上的一些内容为不可修改 :param active: bool,如果为False则禁用掉文本框,否则启用 :return: 无 """ if active: self.entry_host.config(state=ACTIVE) self.entry_port.config(state=ACTIVE) self.entry_authkey.config(state=ACTIVE) self.entry_qq.config(state=ACTIVE) self.checkbutton_auto_connect.config(state=ACTIVE) else: self.entry_host.config(state=DISABLED) self.entry_port.config(state=DISABLED) self.entry_authkey.config(state=DISABLED) self.entry_qq.config(state=DISABLED) self.checkbutton_auto_connect.config(state=DISABLED) def __on_close_root(self): """ 关闭窗口的事件 :return: 无 """ # 如果正在连接则释放连接 if GlobalValues.is_connected: Conn.release_session_key() # 杀掉root self.root.destroy() def __refresh(self): """ 用于刷新界面,在必要时调用 :return: 无 """ def refresh_login_list(): """ 刷新登录列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_login_list.delete(*self.treeview_login_list.get_children()) # 把登录列表内容添加到显示中 for one_record in LoginListOperation.get_list_from_file(): self.treeview_login_list.insert("", index=END, values=( one_record["host"], one_record["port"], one_record["authkey"], one_record["qq"] )) def refresh_op_list(): """ 刷新bot管理员qq列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_op_list.delete(*self.treeview_op_list.get_children()) # 把内容添加到显示中 for one_record in OpListOperation.get_list(): self.treeview_op_list.insert("", index=END, values=( one_record )) def refresh_config(): """ 刷新配置 :return: 无 """ # 重新获取config self.config_dict = ConfigOperation.get_dir_from_file() # 将文件中的内容显示到界面中 self.entry_command_head.delete(0, END) self.entry_command_head.insert(END, self.config_dict["commandHead"]) # 设置复选框默认勾选 self.debug_var.set(self.config_dict["debug"]) self.enable_var.set(self.config_dict["enable"]) # 将内容设置到全局变量 GlobalValues.command_head = self.config_dict["commandHead"] GlobalValues.debug_var = self.debug_var GlobalValues.enable_var = self.enable_var def refresh_plugin_list(): # 获取插件名称 plugin_names = PluginHandler.get_plugin_name_list() # 显示 self.treeview_plugin_list.delete(*self.treeview_plugin_list.get_children()) for name in plugin_names: self.treeview_plugin_list.insert("", index=END, values=( name )) # 调用刷新登录列表 refresh_login_list() # 调用刷新op列表 refresh_op_list() # 刷新config显示 refresh_config() # 刷新插件列表显示 refresh_plugin_list() def __on_click_add_to_login_list(self): """ 将填写内容添加到列表中 :return: 无 """ # 非空检测 if [ self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ] == [""] * 4: return # 调用添加登录项方法 LoginListOperation.add_to_list( self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ) # 刷新显示 self.__refresh() def __on_double_click_login_list_content(self): """ 双击登录列表项目时,自动填充到右侧 :return: 无 """ # 获取item的值 item_list = self.treeview_login_list.item(self.treeview_login_list.focus(), "values") # 获取需要的项目并设置 self.entry_host.delete(0, END) self.entry_host.insert(END, item_list[0]) self.entry_port.delete(0, END) self.entry_port.insert(END, item_list[1]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, item_list[2]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, item_list[3]) def __show_login_list_pop_up_menu(self, event): """ 显示右键菜单 :param event: 事件 :return: 无 """ def on_delete_event(item_id): """ 删除选项的事件 :return: 无 """ # 删除该项 LoginListOperation.remove_from_list(*self.treeview_login_list.item(item_id, "values")) self.treeview_login_list.delete(item_id) self.__refresh() # 获取选择对象 iid = self.treeview_login_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if iid: self.treeview_login_list.selection_set(iid) menu_pop_up = Menu(self.treeview_login_list, tearoff=False) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event(iid) ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_refresh_friend_list_event(self): """ 点击刷新好友列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 friend_list = Conn.get_friend_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_friend_list.delete(*self.treeview_friend_list.get_children()) # 解析friend_list for friend_block in friend_list: self.treeview_friend_list.insert("", index=END, values=( friend_block["id"], friend_block["nickname"], friend_block["remark"] )) def __on_click_refresh_group_list_event(self): """ 点击刷新群列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 group_list = Conn.get_group_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_group_list.delete(*self.treeview_group_list.get_children()) # 解析group_list for group_block in group_list: self.treeview_group_list.insert("", index=END, values=( group_block["id"], group_block["name"], group_block["permission"] )) def __on_click_send_friend_message(self): """ 点击发送消息给好友按钮 :return: 无 """ # 获取到选中好友的值列表 value_list = self.treeview_friend_list.item(self.treeview_friend_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_friend_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_friend_message(qq, message_chain) self.text_friend_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_send_group_message(self): """ 点击发送消息给群按钮 :return: 无 """ # 获取到选中群的值列表 value_list = self.treeview_group_list.item(self.treeview_group_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_group_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_group_message(qq, message_chain) self.text_group_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_add_op(self): """ 点击添加op按钮事件 :return: 无 """ content = self.entry_add_op.get() # 如果添加op的文本框中没有东西,则不添加 if content == "": return # 如果转换数字出错则不添加 try: op_qq = int(content) except ValueError: return # 添加到op列表中 OpListOperation.add_to_list(op_qq) # 刷新显示 self.__refresh() def __show_op_list_pop_up_menu(self, event): """ op列表右键菜单 :return: 无 """ def on_delete_event(): """ 删除选项的事件 :return: 无 """ # 删除该项 # 注意此处的强转,由于能够保证显示出来的内容一定只含有数字,故可以直接转换 OpListOperation.remove_from_list(int(self.treeview_op_list.item(op_qq, "values")[0])) self.treeview_op_list.delete(op_qq) self.__refresh() # 获取选择对象 op_qq = self.treeview_op_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if op_qq: menu_pop_up = Menu(self.treeview_op_list, tearoff=False) self.treeview_op_list.selection_set(op_qq) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event() ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_save_config(self): """ 点击保存配置事件 :return: 无 """ content = self.entry_command_head.get() # 如果为空,则不存入,但是刷新 # 这样是为了保证点击后会显示原来的设置 if content == "": self.__refresh() return ConfigOperation.modify_dict("commandHead", content) ConfigOperation.modify_dict("debug", self.debug_var.get()) ConfigOperation.modify_dict("enable", self.enable_var.get()) # 刷新 self.__refresh() # 弹出对话框 messagebox.showinfo(message=MANAGE_GUIDE["successSaveCommandHeadMsg"]) def __auto_connect(self): if self.config_dict["autoConnect"]: self.__on_click_connect_event()
class Cerberus: def __init__(self, master, root): self.exportToCSV = False self.versionApp, self.key, self.salt = self.initApp() self.key = cerberusCryptography.getMasterKey() self.cipher_suite = Fernet(self.key) self.master = master self.master.title('Cerberus') self.windowWidth = 1060 self.windowHeight = 450 self.screenWidth = self.master.winfo_screenwidth() self.screenHeight = self.master.winfo_screenheight() self.positionRight = int(self.screenWidth / 2 - self.windowWidth / 2) self.positionDown = int(self.screenHeight / 3 - self.windowHeight / 2) self.master.geometry("{}x{}+{}+{}".format(self.windowWidth, self.windowHeight, self.positionRight, self.positionDown)) self.img = PhotoImage(data=icons.getAppIcon()) self.master.wm_iconphoto(True, self.img) self.master.resizable(0, 0) self.menubar = Menu(master) filemenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Cerberus", menu=filemenu) self.addIcon = PhotoImage(data=icons.getAddIcon()) filemenu.add_command(label="Εισαγωγή Υπηρεσίας", image=self.addIcon, compound='left', command=self.getAddNewServiceForm) self.editIcon = PhotoImage(data=icons.getEditIcon()) filemenu.add_command(label="Επεξεργασία Υπηρεσίας", image=self.editIcon, compound='left', command=self.getEditServiceForm) self.deleteIcon = PhotoImage(data=icons.getDeleteIcon()) filemenu.add_command(label="Διαγραφή Υπηρεσίας", image=self.deleteIcon, compound='left', command=self.deleteService) filemenu.add_separator() self.excelIcon = PhotoImage(data=icons.getExcelIcon()) filemenu.add_command(label="Εξαγωγή σε Excel", image=self.excelIcon, compound='left', command=self.checkPasswordToExportToCSV) filemenu.add_separator() self.exitIcon = PhotoImage(data=icons.getExitIcon()) filemenu.add_command(label="Έξοδος", image=self.exitIcon, compound='left', command=self.exitApp) settingsMenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Ρυθμίσεις", menu=settingsMenu) self.settingsIcon = PhotoImage(data=icons.getSettingsIcon()) settingsMenu.add_command(label="Επεξεργασία Στοιχείων", image=self.settingsIcon, compound='left') #command=self.getSettingsForm) aboutMenu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Βοήθεια", menu=aboutMenu) self.infoIcon = PhotoImage(data=icons.getInfoIcon()) aboutMenu.add_command(label="Περί", image=self.infoIcon, compound='left', command=self.getAboutAppForm) self.master.config(menu=self.menubar) self.copyIcon = PhotoImage(data=icons.getCopyIcon()) self.popup = Menu(root, tearoff=0) self.popup.add_command(label=" Αντιγραφή Email", image=self.copyIcon, compound='left', command=self.copyEmail) self.popup.add_command(label=" Αντιγραφή Username", image=self.copyIcon, compound='left', command=self.copyUsername) self.popup.add_command(label=" Αντιγραφή Κωδικού", image=self.copyIcon, compound='left', command=self.copyPasswd) self.popup.add_command(label=" Αντιγραφή ID", image=self.copyIcon, compound='left', command=self.copyID) self.popup.add_separator() self.popup.add_command(label=" Επεξεργασία Υπηρεσίας", image=self.editIcon, compound='left', command=self.getEditServiceForm) self.popup.add_command(label=" Διαγραφή Υπηρεσίας", image=self.deleteIcon, compound='left', command=self.deleteService) self.popup.add_separator() self.popup.add_command(label=" Έξοδος", image=self.exitIcon, compound='left', command=self.exitApp) self.frame = Frame(self.master, background="white", borderwidth=1, relief="sunken", highlightthickness=1) self.frame.pack(side="top", fill="x", padx=4, pady=4) self.search = StringVar() self.searchEntry = Entry(self.frame, textvariable=self.search, borderwidth=0, highlightthickness=0, background="white") self.searchEntry.insert(0, 'Αναζήτηση Υπηρεσίας') self.searchEntry['fg'] = 'grey' self.search.trace( "w", lambda name, index, mode, sv=self.search: self.searchService()) self.searchEntry.image = PhotoImage(data=icons.getSearchIcon()) imageLabel = Label(self.frame, image=self.searchEntry.image) imageLabel.pack(side="left") imageLabel['bg'] = 'white' self.searchEntry.pack(side="left", fill="both", expand=True) # Fix BUG with Treeview colors in Python3.7 def fixed_map(option): return [ elm for elm in style.map('Treeview', query_opt=option) if elm[:2] != ('!disabled', '!selected') ] style = ttk.Style(root) style.map('Treeview', foreground=fixed_map('foreground'), background=fixed_map('background')) # Fix BUG with Treeview colors in Python3.7 self.table = Treeview(self.master) self.table['show'] = 'headings' self.table['columns'] = ('Services', 'email', 'username', 'passwd', 'id', 'category', 'url', 'ID') self.table["displaycolumns"] = ('Services', 'email', 'username', 'passwd', 'id', 'category', 'url') for col in self.table['columns']: self.table.heading( col, command=lambda c=col: self.sortby(self.table, c, 0)) self.table.heading('Services', text='Services') self.table.column('Services', anchor='center', width=200) self.table.heading('email', text='Email') self.table.column('email', anchor='center', width=200) self.table.heading('username', text='Username') self.table.column('username', anchor='center', width=100) self.table.heading('passwd', text='Password') self.table.column('passwd', anchor='center', width=100) self.table.heading('url', text='URL') self.table.column('url', anchor='center', width=120) self.table.heading('id', text='ID') self.table.column('id', anchor='center', width=100) self.table.heading('category', text='Category') self.table.column('category', anchor='center', width=100) self.table.heading('ID', text='ID') self.table.column('ID', anchor='center', width=200) self.table.tag_configure('oddrow', background='#e6eef2') self.table.tag_configure('evenrow', background='#b3cfdd') self.table.tag_configure('focus', background='#c6b6b4') self.last_focus = None self.last_focus_tag = None self.table.focus() self.table.pack(fill=BOTH, expand=1) self.table.bind("<<TreeviewSelect>>", self.onTableSelect) self.table.bind("<ButtonRelease-1>", self.openURLService) self.table.bind("<Motion>", self.changePointerOnHover) self.table.bind("<Button-3>", self.popupMenu) self.searchEntry.bind("<FocusIn>", self.foc_in) self.searchEntry.bind("<FocusOut>", self.foc_out) self.popup.bind("<FocusOut>", self.popupFocusOut) self.master.protocol("WM_DELETE_WINDOW", self.exitApp) self.loadTable(self) self.master.bind("<Escape>", self.exitApp) def popupFocusOut(self, event=None): self.popup.unpost() def foc_in(self, *args): if self.search.get() == 'Αναζήτηση Υπηρεσίας': self.searchEntry.delete('0', 'end') self.searchEntry['fg'] = 'black' def foc_out(self, *args): if not self.search.get(): self.searchEntry.insert(0, 'Αναζήτηση Υπηρεσίας') self.searchEntry['fg'] = 'grey' self.loadTable(self) def changePointerOnHover(self, event): _iid = self.table.identify_row(event.y) if _iid != self.last_focus: if self.last_focus: self.table.item(self.last_focus, tags=[self.last_focus_tag]) self.last_focus_tag = self.table.item(_iid, "tag") self.table.item(_iid, tags=['focus']) self.last_focus = _iid curItem = self.table.item(self.table.identify('item', event.x, event.y)) if curItem['values'] != '': col = self.table.identify_column(event.x) url = curItem['values'][int(col[-1]) - 1] if col[-1] == "7" and url != '---': self.master.config(cursor="hand2") else: self.master.config(cursor="") def openURLService(self, event): curItem = self.table.item(self.table.focus()) col = self.table.identify_column(event.x) region = self.table.identify("region", event.x, event.y) if col[-1] == "7" and region != 'heading': url = curItem['values'][int(col[-1]) - 1] if url != '---': webbrowser.open_new_tab('http://' + str(url)) def onTableSelect(self, event): for item in self.table.selection(): item_text = self.table.item(item, "values") print(item_text[0]) def getSelectedService(self, event): for item in self.table.selection(): selectedRow = self.table.item(item, "value") return selectedRow def initApp(self): print("Initialize Cerberus App") try: conn = sqlite3.connect('cerberus.db') except sqlite3.Error as e: print(e) cur = conn.cursor() cur.execute( "SELECT version, masterToken, salt FROM cerberusParameters") row = cur.fetchone() cur.close() return row def copyEmail(self): for item in self.table.selection(): item_text = self.table.item(item, "values") self.master.clipboard_clear() root.clipboard_append(item_text[1]) def copyUsername(self): for item in self.table.selection(): item_text = self.table.item(item, "values") self.master.clipboard_clear() root.clipboard_append(item_text[2]) def copyPasswd(self): for item in self.table.selection(): item_text = self.table.item(item, "values") self.master.clipboard_clear() root.clipboard_append(item_text[3]) def copyID(self): for item in self.table.selection(): item_text = self.table.item(item, "values") self.master.clipboard_clear() root.clipboard_append(item_text[4]) def searchService(self): try: conn = sqlite3.connect('cerberus.db') except sqlite3.Error as e: print(e) cur = conn.cursor() if self.search.get() == 'Αναζήτηση Υπηρεσίας': pass elif self.search.get(): cur.execute( "SELECT id, name, email, username, password, value, category, url FROM service WHERE name LIKE '%" + self.search.get() + "%' or name LIKE '%" + self.search.get().upper() + "%'") # ('%'+self.search.get()+'%',),'Α') elif not self.search.get(): cur.execute( "SELECT id, name, email, username, password, value, category, url FROM service " ) rows = cur.fetchall() cur.close() for k in self.table.get_children(): self.table.delete(k) i = 1 for row in rows: if (i % 2) == 0: tag = "oddrow" else: tag = "evenrow" self.table.insert( '', 'end', values=( row[1], self.cipher_suite.decrypt(row[2]).decode("utf-8").split(), self.cipher_suite.decrypt(row[3]).decode("utf-8").split(), self.cipher_suite.decrypt(row[4]).decode("utf-8").split(), self.cipher_suite.decrypt(row[5]).decode("utf-8").split(), self.cipher_suite.decrypt(row[6]).decode("utf-8").split(), self.cipher_suite.decrypt(row[7]).decode("utf-8").split(), row[0]), tags=tag) i = i + 1 @staticmethod def exitApp(event=None): root.destroy() @staticmethod def getAboutAppForm(): import aboutApp aboutApp.aboutApp() def getAddNewServiceForm(self): self.master.withdraw() import addNewServiceForm addNewServiceForm.addNewServiceForm(self) def getEditServiceForm(self): service = self.getSelectedService(self) if service is None: messagebox.showerror( "Μήνυμα Σφάλματος", "Παρακαλώ επιλέξτε την Υπηρεσία που θέλετε να Επεξεργαστείτε.") else: self.master.withdraw() import editServiceForm editServiceForm.editServiceForm(self, service) def getSettingsForm(self): import settingsForm settingsForm.settingsForm() def sortby(self, tree, col, descending): data = [(tree.set(child, col), child) for child in tree.get_children('')] data.sort(reverse=descending) for ix, item in enumerate(data): if (ix % 2) == 0: tag = "evenrow" else: tag = "oddrow" tree.move(item[1], '', ix) tree.item(item[1], tags=tag) # switch the heading so that it will sort in the opposite direction tree.heading( col, command=lambda x=col: self.sortby(tree, col, int(not descending))) @staticmethod def loadTable(self): try: conn = sqlite3.connect('cerberus.db') except sqlite3.Error as e: print(e) cur = conn.cursor() cur.execute( "SELECT id, name, email, username, password, value, category, url value FROM service" ) rows = cur.fetchall() for row in self.table.get_children(): self.table.delete(row) i = 1 for row in rows: if (i % 2) == 0: tag = "oddrow" else: tag = "evenrow" self.table.insert( '', 'end', values=( row[1], self.cipher_suite.decrypt(row[2]).decode("utf-8").split(), self.cipher_suite.decrypt(row[3]).decode("utf-8").split(), self.cipher_suite.decrypt(row[4]).decode("utf-8").split(), self.cipher_suite.decrypt(row[5]).decode("utf-8").split(), self.cipher_suite.decrypt(row[6]).decode("utf-8").split(), self.cipher_suite.decrypt(row[7]).decode("utf-8").split(), row[0]), tags=tag) i = i + 1 conn.close() self.last_focus = None self.table.selection() def deleteService(self): service = self.getSelectedService(self) if service is None: messagebox.showerror( "Μήνυμα Σφάλματος", "Παρακαλώ επιλέξτε την Υπηρεσία που θέλετε να Διαγράξετε.") else: msgBox = messagebox.askquestion( 'Διαγραφή: {}'.format(service[0]), 'Είστε σίγουρος ότι θέλετε να διαγράψετε την Υπηρεσία: ' '{}' ' ?'.format(service[0]), icon='warning') if msgBox == 'yes': try: conn = sqlite3.connect('cerberus.db') except sqlite3.Error as e: print(e) sql = 'DELETE FROM service WHERE id=?' cur = conn.cursor() cur.execute(sql, (service[-1], )) conn.commit() conn.close() self.loadTable(self) def popupMenu(self, event): serviceId = self.table.identify_row(event.y) if serviceId: self.table.selection_set(serviceId) try: self.popup.tk_popup(event.x_root, event.y_root) finally: self.popup.grab_release() def checkPasswordToExportToCSV(self): print("Check Password..") import logInForm self.master.withdraw() logInForm.logIn(self) @staticmethod def exportToCSV(): print("Export Services to CSV...") try: conn = sqlite3.connect('cerberus.db') except sqlite3.Error as e: print(e) key = cerberusCryptography.getMasterKey() cipher_suite = Fernet(key) cur = conn.cursor() cur.execute( "SELECT category, name, email, username, password, value, url value FROM service" ) rows = cur.fetchall() csvData = [[ 'Κατηγορία', 'Υπηρεσία', 'Email', 'Όνομα Χρήστη', 'Κωδικός', 'ID', 'URL', ]] for row in rows: csvData = csvData + [[ cipher_suite.decrypt(row[0]).decode("utf-8").split(), cipher_suite.decrypt(row[1]).decode("utf-8").split(), cipher_suite.decrypt(row[2]).decode("utf-8").split(), cipher_suite.decrypt(row[3]).decode("utf-8").split(), cipher_suite.decrypt(row[4]).decode("utf-8").split(), cipher_suite.decrypt(row[5]).decode("utf-8").split(), cipher_suite.decrypt(row[6]).decode("utf-8").split(), ]] try: homeFolder = str(Path.home()) filePath = filedialog.asksaveasfile( initialdir=homeFolder, initialfile='cerberus.csv', title="Επιλογή Αρχείου", filetypes=(("csv files", "*.csv"), ("all files", "*.*"))) if filePath: try: with open(filePath.name, 'w') as csvFile: csvFile = csv.writer(csvFile, delimiter='\t') csvFile.writerows(csvData) messagebox.showinfo( "Μήνυμα Επιτυχίας", "Το αρχείο αποθηκέυτηκε με Επιτυχία στην τοποθεσία {}." .format(filePath.name)) except Exception as e: messagebox.showerror( "Μήνυμα Σφάλματος", "Δεν ήταν δυνατή η Εξαγωγή του αρχείου.") except Exception as e: print(e) messagebox.showerror("Μήνυμα Σφάλματος", "Δεν ήταν δυνατή η Εξαγωγή του αρχείου.")
class NameView(object): """Shows a treeview of unique names.""" def __init__(self, master, names): self.widget = Frame(master) self._tree = Treeview(self.widget, columns='name') self._tree.grid(row=0,column=0, sticky=(N,S,W,E)) self._tree.view = self self.widget.columnconfigure(0, weight=1) self.widget.rowconfigure(0,weight=1) self._tree.column('name', width=50) self._tree['show'] = 'tree' actions = {'edit': lambda e: self.edit(), 'search': lambda e: self.search(), 'focus_next': lambda e: self.focus_next(), 'focus_prev': lambda e: self.focus_prev(), 'select': lambda e: self._tree.selection_toggle(self._tree.focus()), 'clear_selection': lambda e: self._tree.selection_set([]) } kb.make_bindings(kb.tagview, actions, self._tree.bind) self._iids = dict() self._names = dict() logger.debug('Names: %s', names) self.widget.focus_set = self._tree.focus_set for name in sorted(names): iid = self._tree.insert('', 'end', text=name) self._names[iid] = name self._iids[name] = iid self._scroll = Scrollbar(self.widget, command=self._tree.yview) self._tree['yscrollcommand'] = self._scroll.set self._scroll.grid(row=0, column=1, sticky=(N, S)) self.widget.columnconfigure(1, weight=0) def selection(self): logger.debug('Selection: %s', self._tree.selection()) return [self._names[iid] for iid in self._tree.selection()] def edit(self): self._tree.event_generate('<<NameViewEdit>>') def search(self): if len(self._tree.selection()) == 0: self._tree.selection_add(self._tree.focus()) self._tree.event_generate('<<NameViewSearch>>') def append(self, names): logger.debug('Append names: %s', names) for name in names: if name not in self._names.values(): iid = self._tree.insert('', 'end', text=name) self._names[iid] = name self._iids[name] = iid def delete(self, name): self._tree.delete(self._iids[name]) del self._names[self._iids[name]] del self._iids[name] def _focus(self, iid): self._tree.focus(iid) self._tree.see(iid) def focus_next(self): cur_iid = self._tree.focus() next_iid = self._tree.next(cur_iid) if next_iid == '': iids = self._tree.get_children() next_iid = iids[0] self._focus(next_iid) def focus_prev(self): cur_iid = self._tree.focus() prev_iid = self._tree.prev(cur_iid) if prev_iid == '': iids = self._tree.get_children() prev_iid = iids[-1] self._focus(prev_iid) def jump_to(self, name): try: iid = self._iids[name] self._focus(iid) except KeyError: pass def get_names(self): return tuple(self._names.values()) def set(self, names): self._tree.delete(*self._iids.values()) self._iids.clear() self._names.clear() for name in sorted(names): iid = self._tree.insert('', 'end', text=name) self._names[iid] = name self._iids[name] = iid
class window: def __init__(self): self.win = Tk() height = self.win.winfo_screenheight() width = self.win.winfo_screenwidth() x = (width - 700) // 2 y = (height - 700) // 2 self.win.geometry('700x700+{}+{}'.format(str(x), str(y))) self.win.resizable(width=False, height=False) self.frame = Frame(self.win, height=700, width=700, bg="#a3c2c2") self.frame.place(x=0, y=0) self.frame1 = Frame(self.frame, bg="#e0ebeb", height=700, width=2) self.frame1.place(x=30, y=0) self.frame1 = Frame(self.frame, bg="#75a3a3", height=700, width=4) self.frame1.place(x=20, y=0) self.frame1 = Frame(self.frame, bg="#476b6b", height=700, width=6) self.frame1.place(x=10, y=0) self.frame1 = Frame(self.frame, bg="#e0ebeb", height=2, width=700) self.frame1.place(x=0, y=30) self.frame1 = Frame(self.frame, bg="#75a3a3", height=4, width=700) self.frame1.place(x=0, y=20) self.frame1 = Frame(self.frame, bg="#476b6b", height=6, width=700) self.frame1.place(x=0, y=10) self.table = Treeview(self.frame, column=("#0", "#1", "#2", "#3", "#4", "#5", "#6", "#7")) style = ttk.Style() style.theme_use("alt") ttk.Style().configure("Treeview.Heading", font=('', 14, "bold")) self.table.column("#0", width=80) self.table.column("#1", width=80) self.table.column("#2", width=80) self.table.column("#3", width=80) self.table.column("#4", width=80) self.table.column("#5", width=80) self.table.column("#6", width=80) self.table.column("#7", width=80) self.table.heading("#0", text="Sr.") self.table.heading("#1", text="Name") self.table.heading("#2", text="Gender") self.table.heading("#3", text="Email") self.table.heading("#4", text="Contact") self.table.heading("#5", text="Address") self.table.heading("#6", text="Edit") self.table.heading("#7", text="Delete") x = database_queries.database() res = x.view_receptionist() #print(res) for i in res: self.table.insert('', 'end', text=i[0], value=(i[1], i[2], i[3], i[5], i[6], "edit", "delete")) self.table.bind("<Double Button-1>", self.trigger) self.table.place(x=40, y=50, width=640) self.win.mainloop() def trigger(self, e): row = self.table.focus() t = (self.table.item(row)) col = self.table.identify_column(e.x) if col == "#6": y = edit_receptionist.window(t["text"]) print("edit") elif (col == "#7"): o = database_queries.database() o.delete(t["text"])
class AwsUploader(Frame): def __init__(self, master=None, settings=None): """ settings: ROOT_DIR: (str) path to directory for root of app SETTINGS_FILENAME: the name of the settings file """ self.aws = S3Client() master.title("AWS Manager") self.settings = (settings if settings is not None else {}) if settings: self.save_settings() Frame.__init__(self, master) self.grid() self.create_widgets() @property def root_dir(self): return self.settings['ROOT_DIR'] @property def settings_path(self): return os.path.join(self.root_dir, self.settings['SETTINGS_FILENAME']) def read_settings(self): if os.path.exists(self.settings_path): with open(self.settings_path, "r") as fp: try: settings = json.load(fp) except Exception as e: #Issue parsing the settings file. print(e) settings = self.settings.copy() else: settings = self.settings.copy() return settings def save_settings(self): settings = self.settings.copy() current_settings = self.read_settings() current_settings.update(settings) if not os.path.exists(self.root_dir): os.mkdir(self.root_dir) with open(self.settings_path, "w") as fp: json.dump(current_settings, fp) self.settings = current_settings return self.settings def create_widgets(self): #Store menu items self.FILE_MENU = Menu(self) self.FILE_MENU.add_command(label="Quit", command=self.quit) self.FILE_MENU.add_command(label="Save", command=self.save_settings) self.FILE_MENU.add_command(label="Refresh", command=self.create_widgets) self.FILE_MENU.add_command(label="Open", command=self.open_bucket) self.FILE_MENU.add_command(label="Create", command=self.create_bucket) self.FILE_MENU.add_command(label="Delete", command=self.delete_bucket_item) self.FILE_MENU.add_command(label="Upload", command=self.upload_file) self.FILE_MENU.add_command(label="Upload Dirs", command=self.upload_directory) self.FILE_MENU.add_command(label="Sync Dir", command=self.sync_directory) self.master.config(menu=self.FILE_MENU) #Store credentials #If none in environment self.LABEL_KEY = Label(self, text="AWS Key:") self.LABEL_KEY.grid(row=0, column=0) self.ENTRY_KEY = Entry(self) self.ENTRY_KEY.grid(row=0, column=1) self.LABEL_SECRET = Label(self, text="AWS Secret:") self.LABEL_SECRET.grid(row=1, column=0) self.ENTRY_SECRET = Entry(self, show=False) self.ENTRY_SECRET.grid(row=1, column=1) self.LABEL_NEW_BUCKET = Label(self, text="Bucket Name:") self.LABEL_NEW_BUCKET.grid(row=2, column=0) self.ENTRY_NEW_BUCKET = Entry(self) self.ENTRY_NEW_BUCKET.grid(row=2, column=1) #The bucket tree will contain #S3 files/directores. self.BUCKET_TREE = Treeview( self, columns=('Bucket', 'Key', 'Modified'), selectmode='extended', ) ysb = Scrollbar(self, orient='vertical', command=self.BUCKET_TREE.yview) xsb = Scrollbar(self, orient='horizontal', command=self.BUCKET_TREE.xview) self.BUCKET_TREE.configure(yscroll=ysb.set, xscroll=xsb.set) self.BUCKET_TREE.heading("#0", text="Item ID") self.BUCKET_TREE.heading("#1", text="Bucket") self.BUCKET_TREE.heading("#2", text="Key") self.BUCKET_TREE.heading("#3", text="Modified") self.BUCKET_TREE.column( 0, minwidth=100, ) #Load top level S3 directories #into the bucket tree count = 0 for bucket in self.aws.s3.buckets.all(): self.BUCKET_TREE.insert('', END, count, text=count, values=(bucket.name, bucket.name, None, bucket.name)) count += 1 self.BUCKET_TREE.grid(row=4, column=0, columnspan=5) ysb.grid(row=4, column=5, sticky='ns') xsb.grid(row=5, column=0, columnspan=5, sticky='ew') def open_bucket(self): """ Inserts all objects associated with the selected bucket as children into the treeview. """ idx = self.BUCKET_TREE.focus() if not idx: return None item = self.BUCKET_TREE.item(idx) children = self.BUCKET_TREE.get_children(idx) if children: self.BUCKET_TREE.delete(*children) bucket_name = item['values'][0] bucket = self.aws.s3.Bucket(bucket_name) count = 0 folders = {} for obj in bucket.objects.all(): child_idx = "{}_{}".format(bucket.name, count) prefix_dirname = self.aws.get_prefix_dirname(obj.key) try: parent_idx = folders[prefix_dirname] except KeyError: #Assign new top level for directory folders[prefix_dirname] = child_idx parts = prefix_dirname.split("/") parent_prefix = "/".join(parts[:-1]) try: #Get another chld for parent parent_idx = folders[parent_prefix] except KeyError: #Use top level bucket as parent #As last resort. parent_idx = idx self.BUCKET_TREE.insert(parent_idx, END, child_idx, text=child_idx, values=(bucket.name, obj.key, None, prefix_dirname)) count += 1 def delete_bucket_item(self): """ Deletes a bucket or bucket item from AWS Then removes the item from the Treeview AWS will kick an error if you try to delete a non-empty bucket. """ idx = self.BUCKET_TREE.focus() if not idx: return None item = self.BUCKET_TREE.item(idx) children = self.BUCKET_TREE.get_children(idx) if children: #Dont delete (yet) #TODO: count children and confirm Y/N print( "Skipping delete of bucket {} because it has children".format( item)) pass else: bucket_name = item['values'][0] bucket_prefix = item['values'][1] bucket = self.aws.s3.Bucket(bucket_name) print("Deleting {}".format(item)) if bucket_name == bucket_prefix: #This is a top level bucket bucket.delete() else: #This is a child object of a bucket. objs = bucket.objects.filter(Prefix=bucket_prefix) for obj in objs: obj.delete() self.BUCKET_TREE.delete(idx) def create_bucket(self): new_name = self.ENTRY_NEW_BUCKET.get() if new_name: print("Creating bucket: {}".format(new_name)) self.aws.client.create_bucket(Bucket=new_name) self.create_widgets() def upload_file(self, file_path=None, idx=None): if file_path is None: file_path = filedialog.askopenfilename( filetypes=(("All files", "*.*"), ("HTML files", "*.html;*.htm"))) file_name = os.path.basename(file_path) if not idx: idx = self.BUCKET_TREE.focus() if not idx: return None item = self.BUCKET_TREE.item(idx) bucket_name = item['values'][0] bucket_prefix = item['values'][1] if bucket_name == bucket_prefix: #upload file to bucket directly bucket_prefix = file_name else: #A file or dirname is selected, check for prefix #Getthe prefix dirname bp = item['values'][3] if not bp[-1] == "/": bp += "/" bucket_prefix = bp + file_name print("Uploading {} to {}".format(file_path, bucket_prefix)) self.aws.client.upload_file(file_path, bucket_name, bucket_prefix) self.create_widgets() def upload_directory(self, dir_path=None, idx=None): """ Recreates a directory into an AWS bucket. """ if dir_path is None: dir_path = filedialog.askdirectory() dir_path = os.path.normpath(dir_path).replace('\\', '/') parent_dir = os.path.dirname(dir_path).replace('\\', '/') if idx is None: idx = self.BUCKET_TREE.focus() if not idx: return None item = self.BUCKET_TREE.item(idx) bucket_name = item['values'][0] parent_prefix = item['values'][1] if bucket_name == parent_prefix: parent_prefix = "" for dirname, subdirs, files in os.walk(dir_path): for file in files: file_path = os.path.normpath(os.path.join(dirname, file)).replace( '\\', '/') bucket_prefix = os.path.dirname(file_path).replace( parent_dir, "/").replace('//', '/') if not bucket_prefix.endswith('/'): bucket_prefix += "/" bucket_prefix = parent_prefix + bucket_prefix + file print("Uploading {} to {}".format(bucket_prefix, bucket_name)) self.aws.client.upload_file(file_path, bucket_name, bucket_prefix) self.create_widgets() def sync_directory(self, dir_path=None, idx=None): refresh = False if dir_path is None: dir_path = filedialog.askdirectory() refresh = True if idx is None: idx = self.BUCKET_TREE.focus() if not idx: return None item = self.BUCKET_TREE.item(idx) bucket_name = item['values'][0] bucket_prefix = item['values'][3] if bucket_prefix == bucket_name: bucket_prefix = None self.aws.sync_directory( dir_path, bucket_name, key_name=bucket_prefix, ) if refresh: self.create_widgets()
class Ufd: """ Universal File Dialog - "UFD" Unopinionated, minimalist, reusable, slightly configurable, general-purpose file-dialog. """ def __init__(self, title: str = "Universal File Dialog", icon: str = "", show_hidden: bool = False, include_files: bool = True, multiselect: bool = True, select_dirs: bool = True, select_files: bool = True, unix_delimiter: bool = True, stdout: bool = False): """ Init kwargs as object attributes, save references to Tk PhotoImages, & define the widgets + layout """ if not isinstance(title, str): raise TypeError("Argument title must be type string.") self.title = title if icon: if not isinstance(icon, str): raise TypeError("Argument icon must be type string.") if not isfile(icon): raise FileNotFoundError(f"File not found: {icon}") self.icon = icon else: self.icon = "" if show_hidden: self.show_hidden = True else: self.show_hidden = False if include_files: self.include_files = True else: self.include_files = False if multiselect: self.multiselect = True else: self.multiselect = False if select_dirs: self.select_dirs = True else: self.select_dirs = False if select_files: self.select_files = True else: self.select_files = False if unix_delimiter: self.unix_delimiter = True else: self.unix_delimiter = False if stdout: self.stdout = True else: self.stdout = False # Tkinter: self.dialog = Tk() self.dialog.withdraw() self.dialog.title(self.title) self.dialog.minsize(width=300, height=200) self.dialog.geometry("500x300") self.dialog.update_idletasks() self.file_icon = PhotoImage(file=f"{dirname(__file__)}/file.gif", master=self.dialog).subsample(50) self.folder_icon = PhotoImage(file=f"{dirname(__file__)}/folder.gif", master=self.dialog).subsample(15) self.disk_icon = PhotoImage(file=f"{dirname(__file__)}/disk.gif", master=self.dialog).subsample(15) if self.icon: self.dialog.iconbitmap(self.icon) else: self.dialog.iconbitmap(f"{dirname(__file__)}/icon.ico") # Widgets: self.paneview = PanedWindow( self.dialog, sashwidth=7, bg="#cccccc", bd=0, ) self.left_pane = PanedWindow(self.paneview) self.right_pane = PanedWindow(self.paneview) self.paneview.add(self.left_pane) self.paneview.add(self.right_pane) self.treeview_x_scrollbar = Scrollbar(self.left_pane, orient="horizontal") self.treeview_y_scrollbar = Scrollbar(self.left_pane, orient="vertical") self.list_box_x_scrollbar = Scrollbar(self.right_pane, orient="horizontal") self.list_box_y_scrollbar = Scrollbar(self.right_pane, orient="vertical") # tstyle = Style().configure(".", ) self.treeview = Treeview( self.left_pane, xscrollcommand=self.treeview_x_scrollbar.set, yscrollcommand=self.treeview_y_scrollbar.set, show="tree", selectmode="browse", # style=tstyle ) self.list_box = Listbox(self.right_pane, xscrollcommand=self.list_box_x_scrollbar.set, yscrollcommand=self.list_box_y_scrollbar.set, width=34, highlightthickness=0, bd=2, relief="ridge") if self.multiselect: self.list_box.config(selectmode="extended") else: self.list_box.config(selectmode="browse") self.cancel_button = Button(self.left_pane, text="Cancel", command=self.cancel) self.submit_button = Button(self.right_pane, text="Submit", command=self.submit) self.treeview_x_scrollbar.config(command=self.treeview.xview) self.treeview_y_scrollbar.config(command=self.treeview.yview) self.list_box_x_scrollbar.config(command=self.list_box.xview) self.list_box_y_scrollbar.config(command=self.list_box.yview) #Layout: self.dialog.rowconfigure(0, weight=1) self.dialog.columnconfigure(0, weight=1) self.left_pane.grid_rowconfigure(0, weight=1) self.left_pane.grid_columnconfigure(0, weight=1) self.right_pane.grid_rowconfigure(0, weight=1) self.right_pane.grid_columnconfigure(0, weight=1) self.paneview.paneconfigure( self.left_pane, minsize=100, #Start off w/ the sash centered in the GUI: width=(self.dialog.winfo_width() / 2) - ceil( (self.paneview.cget("sashwidth") * 1.5)), ) self.paneview.paneconfigure(self.right_pane, minsize=100) self.paneview.grid(row=0, column=0, sticky="nsew") self.treeview.grid(row=0, column=0, sticky="nsew") self.treeview_y_scrollbar.grid(row=0, column=1, sticky="ns") self.treeview_x_scrollbar.grid(row=1, column=0, columnspan=2, sticky="ew") self.list_box.grid(row=0, column=0, sticky="nsew") self.list_box_y_scrollbar.grid(row=0, column=1, sticky="ns") self.list_box_x_scrollbar.grid(row=1, column=0, columnspan=2, sticky="ew") self.cancel_button.grid(row=2, column=0, sticky="w", padx=10, pady=10) self.submit_button.grid(row=2, column=0, columnspan=2, sticky="e", padx=10, pady=10) #Bindings, Protocols, & Misc: self.dialog.bind("<Control-w>", self.cancel) self.treeview.bind("<<TreeviewSelect>>", self.treeview_select) self.treeview.bind("<Double-Button-1>", self.dialog_populate) self.treeview.bind("<Return>", self.dialog_populate) self.treeview.bind("<Right>", self.dialog_populate) self.list_box.bind("<<ListboxSelect>>", self.list_box_select) self.list_box.bind("<Return>", self.submit) self.dialog.protocol("WM_DELETE_WINDOW", self.cancel) self.dialog_selection = deque() self.selection_paths = deque() for disk in self.get_disks(): self.treeview.insert( "", index="end", text=disk, image=self.disk_icon, ) self.dialog.focus() def __call__(self): """ Display dialog & return selection """ (width_offset, height_offset) = self.get_offset(self.dialog) self.dialog.geometry(f"+{width_offset}+{height_offset}") self.dialog.update_idletasks() self.dialog.deiconify() self.dialog.wait_window() for i, path in enumerate(self.dialog_selection): if self.unix_delimiter: self.dialog_selection[i] = sub("\\\\", "/", path) else: self.dialog_selection[i] = sub("/", "\\\\", path) if self.stdout: [print(item) for item in self.dialog_selection] return list(self.dialog_selection) def __str__(self): """ Return own address """ return "Universal File Dialog"\ f" @ {hex(id(self))}" def __repr__(self): """ Return full string representation of constructor signature """ return f"Ufd("\ f"title=\"{self.title}\","\ f" icon=\"{self.icon}\","\ f" show_hidden={self.show_hidden},"\ f" include_files={self.include_files},"\ f" multiselect={self.multiselect},"\ f" select_dirs={self.select_dirs},"\ f" select_files={self.select_files},"\ f" unix_delimiter={self.unix_delimiter})"\ f" stdout={self.stdout})"\ f" @ {hex(id(self))}" @staticmethod def get_offset(tk_window): """ Returns an appropriate offset for a given tkinter toplevel, such that it always is created center screen on the primary display. """ width_offset = int((tk_window.winfo_screenwidth() / 2) - (tk_window.winfo_width() / 2)) height_offset = int((tk_window.winfo_screenheight() / 2) - (tk_window.winfo_height() / 2)) return (width_offset, height_offset) @staticmethod def get_disks(): """ Returns all mounted disks (for Windows) >> ["A:", "B:", "C:"] """ if system() != "Windows": raise OSError("For use with Windows platforms.") logicaldisks = run(["wmic", "logicaldisk", "get", "name"], capture_output=True) return findall("[A-Z]:", str(logicaldisks.stdout)) @staticmethod def list_dir(path, force=False): """ Reads a directory with a shell call to dir. Truthiness of bool force determines whether hidden items are returned or not. (For Windows) """ path = sub("/", "\\\\", path) if force: dir_listing = run(["dir", path, "/b", "/a"], shell=True, capture_output=True) else: dir_listing = run(["dir", path, "/b"], shell=True, capture_output=True) output = dir_listing.stdout err = dir_listing.stderr if not output: return [] if err: err = err.decode("utf-8") raise Exception(err) str_output = output.decode("utf-8") list_output = re_split("\r\n", str_output) return sorted([item for item in list_output if item]) def climb(self, item): """ Builds & returns a complete path to root directory, including the item name itself as the path tail. An extra delimiter is appeneded for the subsequent child node, which is normalized in dialog_populate() """ item_text = self.treeview.item(item)["text"] parent = self.treeview.parent(item) path = "" parents = deque() while parent: parents.append(self.treeview.item(parent)["text"] + "/") parent = self.treeview.parent(parent) for parent in reversed(parents): path += parent path += item_text + "/" return path def dialog_populate(self, event=None): """ Dynamically populates & updates the treeview, listbox, and keeps track of the full paths corresponding to each item in the listbox """ if not self.treeview.focus(): return self.treeview.column("#0", width=1000) existing_children = self.treeview.get_children(self.treeview.focus()) [self.treeview.delete(child) for child in existing_children] self.list_box.delete(0, "end") self.selection_paths.clear() focus_item = self.treeview.focus() path = self.climb(focus_item) if self.show_hidden: children = self.list_dir(path, force=True) else: children = self.list_dir(path) for child in children: if isdir(path + child): self.treeview.insert(focus_item, index="end", text=child, image=self.folder_icon) if self.select_dirs: self.list_box.insert("end", child) self.selection_paths.append(path + child) elif isfile(path + child): if self.include_files: self.treeview.insert(focus_item, index="end", text=child, image=self.file_icon) if self.select_files: self.list_box.insert("end", child) self.list_box.itemconfig("end", {"bg": "#EAEAEA"}) self.selection_paths.append(path + child) if isfile(normpath(path)): (head, tail) = path_split(normpath(path)) head = sub("\\\\", "/", head) self.list_box.insert("end", tail) self.selection_paths.append(head + "/" + tail) self.list_box.itemconfig("end", {"bg": "#EAEAEA"}) def list_box_select(self, event=None): """ Dynamically refresh the dialog selection with what's selected in the listbox (Callback for <<ListboxSelect>>). """ self.dialog_selection.clear() for i in self.list_box.curselection(): self.dialog_selection.append(self.selection_paths[i]) def treeview_select(self, event=None): """ Dynamically refresh the dialog selection with what's selected in the treeview (Callback for <<TreeviewSelect>>). """ for i in self.list_box.curselection(): self.list_box.selection_clear(i) self.dialog_selection.clear() item = normpath(self.climb(self.treeview.focus())) self.dialog_selection.append(item) def submit(self, event=None): """ Satisfies wait_window() in self.__call__() and validates selection (Callback for <Return>, <Button-1> on file_list, submit_button) """ if self.select_dirs == False: for item in self.dialog_selection: if isdir(item): messagebox.showwarning( "Error - Invalid Selection", "Unable to select directory. Please select a file(s).") return if self.select_files == False: for item in self.dialog_selection: if isfile(item): messagebox.showwarning( "Error - Invalid Selection", "Unable to select file. Please select a folder(s)") return self.dialog.destroy() def cancel(self, event=None): """ Satisfies wait_window() in self.__call__() (Callback for <Button-1> on cancel_button) (Callback for protocol "WM_DELETE_WINDOW" on self.dialog) """ self.dialog_selection.clear() self.dialog.destroy()
class ReturnWindow: def __init__(self): self.win = Tk() self.canvas = Canvas(self.win, width=800, height=420, bg='white') self.canvas.pack(expand=YES, fill=BOTH) # show window in center of the screen width = self.win.winfo_screenwidth() height = self.win.winfo_screenheight() x = int(width / 2 - 800 / 2) y = int(height / 2 - 420 / 2) str1 = "800x420+" + str(x) + "+" + str(y) self.win.geometry(str1) # disable resize window self.win.resizable(False, False) # changing title of the window self.win.title( "| BOOK RETURNING DETAILS | LIBRARY MANAGEMENT SYSTEM |") def add_frame(self): self.frame = Frame(self.win, height=420, width=800) self.frame.place(x=0, y=0) x, y = 0, 0 self.label = Label(self.frame, text="RETURNING BOOKS", fg='black') self.label.config(font=("Poppins", 20, 'underline bold')) self.label.place(x=250, y=30) # use tree view to show details from the table self.tr = Treeview(self.frame, columns=('BOOK_ID', 'STUDENT_ID', 'ISSUE_DATE', 'RETURN_DATE'), selectmode="extended") self.tr.heading('#0', text='BOOK_ID') self.tr.column('#0', minwidth=0, width=100, stretch=NO) self.tr.heading('#1', text='STUDENT_ID') self.tr.column('#1', minwidth=0, width=100, stretch=NO) self.tr.heading('#2', text='ISSUE_DATE') self.tr.column('#2', minwidth=0, width=100, stretch=NO) self.tr.heading('#3', text='RETURN_DATE') self.tr.column('#3', minwidth=0, width=100, stretch=NO) self.tr.heading('#4', text='RETURN') self.tr.column('#4', minwidth=0, width=100, stretch=NO) # self.tr.heading('#5', text='RETURN') # self.tr.column('#5', minwidth=0, width=100, stretch=NO) j = 0 for i in Database.database.BookLend(): self.tr.insert('', index=j, text=i[0], values=(i[1], i[2], i[3], 'RETURN')) j += 1 # create action on deletion self.tr.bind('<Double-Button-1>', self.bounce) self.tr.place(x=140, y=y + 100) self.win.mainloop() def bounce(self, e): # get the value of deleted row tt = self.tr.focus() # get the column id col = self.tr.identify_column(e.x) # print(col) # print(self.tr.item(tt)) # print(self.tr.item(tt)['text']) # print(self.tr.item(tt)['values'][0]) data = ( str(self.tr.item(tt)['text']), str(self.tr.item(tt)['values'][0]), ) if col == '#4': res = messagebox.askyesno("Message", "Do you want to Return..!") if res: d, fine_days = Database.database.Return(data) if d: message = ("Book Returned successfully..! \n Fine = ", fine_days) messagebox.showinfo("Message", message) self.win.destroy() x = Thirdpage # x.add_frame() else: self.win.destroy() x = Student.Return.ReturnWindow() x.add_frame()
class MediumTreeView(Frame): def __init__(self, parent, *args, **kwargs): Frame.__init__(self, parent) self.tree = Treeview(self) self.tree['selectmode'] = "browse" self.tree['columns'] = ('ID', 'Name', 'Gram', 'Include') self.tree['height'] = 30 self.tree['show'] = "headings" self.tree.heading('ID', text="ID") self.tree.heading('Name', text="Name") self.tree.heading('Gram', text="Quantity [mmol]") self.tree.heading('Include', text="Include") self.tree.column('ID', minwidth=0, width=20) self.tree.column('Name', minwidth=100, width=100) self.tree.column('Gram', minwidth=0, width=90) self.tree.column('Include', minwidth=50, width=50) self.tree.bind('<ButtonRelease-1>', self.select_item) self.tree.grid(row=0, column=0, columnspan=4) self.run_object = kwargs.pop('run_object', None) self.medium = None self.medium_volume = None self.uptake_quantities = {} self.species_names = [] self.pie_figure, self.piechart = plt.subplots() self.pie_figure.figsize = (4, 4) self.piechart.pie([0, 0]) self.canvas = FigureCanvasTkAgg(self.pie_figure, master=self) self.canvas.draw() self.canvas.get_tk_widget().grid(row=0, column=4, padx=10) Label(self, text="Quantity:").grid(row=1, column=0) self.edit_entry = FloatEntry(self, initial_value='') self.edit_entry.grid(row=1, column=1, sticky='w') Button(self, text="Save Changes", command=self.save_changes).grid(row=1, column=2, rowspan=2) self.rad_var = IntVar() self.rad_button_exclude = Radiobutton(self, text="No", variable=self.rad_var, value=0) self.rad_button_include = Radiobutton(self, text="Yes", variable=self.rad_var, value=1) self.rad_button_include.grid(row=2, column=1, sticky='w') self.rad_button_exclude.grid(row=2, column=1, sticky='e') Label(self, text="Include:").grid(row=2, column=0) Label(self, text="Medium Name:").grid(row=3, column=0) self.name_entry = StringEntry(self, initial_value="refined_medium") self.name_entry.grid(row=3, column=1, sticky='w') Button(self, text="Test Medium", command=parent.plot).grid(row=4, column=1) Button(self, text="Save Medium", command=lambda: self.save_medium(parent.save)).grid(row=3, column=2) def plot_medium(self, individual, sub_plot): #costruct medium from treeviev if self.medium is not None: components = {} children = self.tree.get_children('') for child in children: child = self.tree.item(child) ID = child['values'][0] quant = float(child['values'][2]) flag = bool(child['values'][3]) if flag: components[ID] = quant medium = Medium.from_dict(components, self.medium_volume) #simulate medium to get the nutrition uptake for each member of the bacterial community individual.plot(True, medium=medium, sub_plot=sub_plot) uptakes = individual.get_uptakes() #calculate the relative uptake quantities self.uptake_quantities = {} for child in children: child_elements = self.tree.item(child) ID = child_elements['values'][0] name = child_elements['values'][1] quant = float(child_elements['values'][2]) flag = child_elements['values'][3] uptake_per_species = [] self.species_names = [] for n, spec in enumerate(uptakes): self.species_names.append(spec) try: uptake = uptakes[spec][ID] except: uptake = 0 try: self.uptake_quantities[ID].append(uptake) except: self.uptake_quantities[ID] = [uptake] for ID in self.uptake_quantities: total = sum(self.uptake_quantities[ID]) if total == 0: self.uptake_quantities[ID] = [ 0 for i in self.species_names ] print(ID) continue relative_quantities = [] for i in self.uptake_quantities[ID]: relative_quantities.append(i / total) self.uptake_quantities[ID] = relative_quantities def add_medium(self, medium, medium_volume): if medium is not None: self.medium = medium self.medium_volume = medium_volume self.update_treeviev() def update_treeviev(self): if self.medium is not None: for i, comp in enumerate(self.medium.get_components()): try: name = SEEDIDs.SEED_to_Names[comp.split("_")[1]] except: name = comp self.tree.insert('', i, comp, values=[ comp, name, self.medium.get_components()[comp], 1, "" ]) def select_item(self, a): try: currItem = self.tree.focus() string_qu = self.tree.item(currItem)['values'][2] include = bool(self.tree.item(currItem)['values'][3]) self.edit_entry.set(string_qu) self.rad_var.set(0 if not include else 1) self.piechart.clear() self.piechart.pie( self.uptake_quantities[self.tree.item(currItem)['values'][0]], labels=self.species_names, labeldistance=None) self.piechart.axis('equal') self.piechart.legend() self.canvas.draw() except: pass def save_changes(self): currItem = self.tree.focus() ID = self.tree.item(currItem)['values'][0] name = self.tree.item(currItem)['values'][1] exclude = 1 if self.rad_var.get() == 1 else 0 uptake = self.tree.item(currItem)['values'][4] self.tree.item( currItem, values=[ID, name, self.edit_entry.get(), exclude, uptake]) def load_medium(self, file): medium = Medium.import_medium(file) self.add_medium(medium) #saves medium to file def save_medium(self, path): if self.medium is not None: file_path = "" for x in path.split("/")[:-1]: file_path = file_path + x + "/" components = {} children = self.tree.get_children('') for child in children: child = self.tree.item(child) ID = child['values'][0] name = child['values'][1] quant = float(child['values'][2]) flag = bool(child['values'][3]) if flag: if quant > 0: components[name] = quant medium = Medium.from_dict(components, self.medium_volume) Medium.export_medium( medium, file_path + "/" + self.name_entry.get() + ".csv")
class ConfigurationControl(object): ''' classdocs ''' __root_id: str = '' __observers: List[ConfigurationControlObserver] = [] __configuration: Treeview = None __inserted: List[str] = [] def __init__(self, master: Frame): ''' Constructor ''' log_enter_func('ConfigurationControl', '__init__', {'master': master}) self.__configuration = Treeview(master=master) self.__configuration.heading('#0', text='Configuration', anchor=tkinter.W) self.__configuration.pack(fill=BOTH, side=tkinter.LEFT, expand=True) self.__configuration.bind('<<TreeviewSelect>>', self.__notifiy_observer) log_leave_func('ConfigurationControl', '__init__') def select(self, _id: str): log_enter_func('ConfigurationControl', 'select', {'_id': _id}) if not _id == None: self.__configuration.focus(_id) self.__configuration.selection_set(_id) log_leave_func('ConfigurationControl', 'select') def insert_conf(self, conf_id: str, conf_name: str, parent: str = 'confs', pos: str = 'end'): log_enter_func( 'ConfigurationControl', 'insert_conf', { 'conf_id': conf_id, 'conf_name': conf_name, 'parent': parent, 'pos': pos }) if parent == None: parent = self.__root_id log_set_var('ConfigurationControl', 'insert_conf', 'parent', parent) self.__inserted.append(conf_id) self.__configuration.insert(parent, pos, conf_id, text=conf_name) self.__configuration.item(conf_id, open=True) log_leave_func('ConfigurationControl', 'insert_conf') def __remove(self, conf_id): log_enter_func('ConfigurationControl', '__remove', {'conf_id': conf_id}) self.__configuration.delete(conf_id) log_leave_func('ConfigurationControl', '__remove') def remove_all(self): log_enter_func('ConfigurationControl', 'remove_all') for conf_id in self.__inserted: if self.__configuration.exists(conf_id): self.__remove(conf_id) self.__inserted.clear() log_leave_func('ConfigurationControl', 'remove_all') def add_obeserver(self, observer: ConfigurationControlObserver): log_enter_func('ConfigurationControl', 'add_obeserver', {'observer': observer}) self.__observers.append(observer) log_leave_func('ConfigurationControl', 'add_obeserver') def remove_observer(self, observer: ConfigurationControlObserver): log_enter_func('ConfigurationControl', 'remove_observer', {'observer': observer}) self.__observers.remove(observer) log_leave_func('ConfigurationControl', 'remove_observer') def __notifiy_observer(self, event): # @UnusedVariable log_enter_func('ConfigurationControl', '__notifiy_observer', {'event': event}) conf_id = self.__configuration.focus() if conf_id == self.__root_id or conf_id == '': conf_id = None log_set_var('ConfigurationControl', '__notifiy_observer', 'conf_id', conf_id) for observer in self.__observers: observer.on_conf_selected(conf_id) log_leave_func('ConfigurationControl', '__notifiy_observer')
class My_Tk(): def __init__(self, root, user_info=None, cookies=None, headers=None, tasklist_=None): self.tk = root self.user_info = user_info self.base_cookies = cookies self.base_headers = headers # self.tk.geometry('620x400') self.orm = {} self.val_map = {} self.create_button() self.create_heading() self.create_tv() self.tasklist_ = tasklist_ def create_button(self): frame = Frame(self.tk, width=200, height=50) frame.pack(fill=X, side=TOP) Button(frame, text='下载', width=6, command=self.download).place(x=28, y=21) # Button(frame, text='测试数据', command=self.insert_test_tree_data).pack(side=LEFT, anchor='w') Button(frame, text='清除列表', command=self.clear_tree_data).place(x=82, y=21) def get_tv(self): return self.tv def download(self): try: for k, v in self.orm.items(): button = self.orm[k][0] button_value = button.getvar(button['variable']) if button_value == '1': print(self.tv.item(k, 'values')) if self.user_info == None or len(self.user_info) == 0: messagebox.showinfo(title="提示", message="请先登录!") return else: media_type = self.tasklist_.media_type_var.get() if media_type and media_type == ".mp4": params = { 'fragmentId': self.val_map[k] + 1, 'token': self.user_info['token'], 'albumId': -8888888, 'programId': -8888888 } else: params = { 'fragmentId': self.val_map[k], 'token': self.user_info['token'], 'albumId': 0, 'programId': 0 } self.base_headers["Host"] = "api.dushu.io" response = requests.post( url="http://api.dushu.io/fragment/content", json=params, headers=self.base_headers, cookies=self.base_cookies) response_data = response.json() mediaUrls = response_data["mediaUrls"] mediaUrl = None if mediaUrls and type( mediaUrls) == list and len(mediaUrls) > 0: if len(mediaUrls) > 1: if media_type == r".mp4": for url_ in mediaUrls: if url_.find("video") != -1: mediaUrl = url_ elif media_type == r".mp3": media_type = r".mp3" for url_ in mediaUrls: if url_.find("audio") != -1: mediaUrl = url_ elif mediaUrls[0].find("audio") != -1: if media_type == '.mp4': messagebox.showinfo( title="提示", message="该资源只有音频,请在任务列表切换下载类型!") return else: mediaUrl = response_data['mediaUrls'][0] elif mediaUrls[0].find("video") != -1: mediaUrl = response_data['mediaUrls'][0] else: return else: return if media_type == '.mp3': file_name = response_data['title'] else: file_name = response_data['bookName'] print(mediaUrl) media_info_headers = {} if (mediaUrl.startswith("https")): mediaUrl = "http" + mediaUrl[5:] host_pattern = re.compile("\w+://(.*?)/.*") host_ = host_pattern.findall(mediaUrl)[0] if host_ != "cdn-ali.dushu.io": media_info_headers = { 'Host': "v-cc.dushu.io", 'Cookie': "grwng_uid=e7e51c80-ead6-43bb-9744-7531778d6c73; UM_distinctid=16be039d03e8aa-0f0e963eb0f589-621c740a-4a640-16be039d03f633; gr_user_id=ebc67f00-d109-4c29-80b0-7d631382debf", 'X-Playback-Session-Id': "A078D569-3595-4399-8240-EB42F542F073", 'Connection': "keep-alive, keep-alive", 'Accept': "*/*", 'User-Agent': "AppleCoreMedia/1.0.0.16D57 (iPhone; U; CPU OS 12_1_4 like Mac OS X; en_us)", 'Accept-Language': "en-us", 'Accept-Encoding': "gzip", 'cache-control': "no-cache" } else: media_info_headers = { 'Host': "cdn-ali.dushu.io", 'Cookie': "grwng_uid=e7e51c80-ead6-43bb-9744-7531778d6c73; UM_distinctid=16be039d03e8aa-0f0e963eb0f589-621c740a-4a640-16be039d03f633; gr_user_id=ebc67f00-d109-4c29-80b0-7d631382debf", 'X-Playback-Session-Id': "A9D630B7-54FF-4514-923C-A561AFA5C7BA", 'Range': "bytes=0-1", 'Accept': "*/*", 'User-Agent': "AppleCoreMedia/1.0.0.16D57 (iPhone; U; CPU OS 12_1_4 like Mac OS X; en_us)", 'Accept-Language': "en-us", 'Accept-Encoding': "identity", 'Connection': "keep-alive", 'cache-control': "no-cache", } media_info_headers["Range"] = "bytes=0-1" media_info_headers['Host'] = host_ media_info = requests.get(url=mediaUrl, headers=media_info_headers, cookies=self.base_cookies) file_des = self.tasklist_.download_dir.get( ) + r"\\" + file_name + media_type bytes_length = 0 if "Content-Range" in media_info.headers: range_ = media_info.headers['Content-Range'] bytes_length = range_[range_.rfind('/') + 1:] elif host_ == "cdn-ali.dushu.io": with open(file_des, "wb") as saved: saved.write(bytes(media_info.content)) return def down(): try: row = [ str(datetime.now().strftime( "%Y%m%d%H%M%S")), file_name + media_type, datetime.now().strftime( "%Y-%m-%d %H:%M:%S"), self.tasklist_.catch_progress_bar(), StringVar(value="0") ] with open(file_des, 'wb') as saved: self.tasklist_.insert_data(row) media_info_content = media_info.content play_list_pattern = re.compile( "(\w+\.mp4_[\d]+\.ts)", re.DOTALL) play_list = [] if type(media_info_content) != str: play_list = play_list_pattern.findall( str(media_info_content)) threading.Thread( target=lambda: { messagebox.showinfo( title="提示", message="请前往任务列表查看下载状态") }).start() if play_list != None and len( play_list) == 0: if int(bytes_length) <= 0: return print(type(bytes_length)) count = (int(bytes_length) + 1 - 131072) / 131072 print(count) print(type(count)) tmp = 0 for index in range(int(count)): if index == count - 1: media_info_headers[ 'Range'] = "bytes=" + str( index * 131072 ) + "-" + str(bytes_length) else: media_info_headers[ 'Range'] = "bytes=" + str( index * 131072) + "-" + str( (index + 1) * 131072 - 1) media_content = requests.get( url=mediaUrl, headers=media_info_headers, cookies=self.base_cookies) saved.write( bytes(media_content.content)) tmp = tmp + 1 print(count) if (tmp > count / 100): print(tmp) self.tasklist_.progress( row[3], index / count * 164 ) # 比其所在canvas宽度小1,百分之99即撑满整个进度条 tmp = 0 row[4].set( str(int(index / count * 100)) + "%") print("*************downloading" + str(index / count * 100) + "%************") else: for index, play_url in enumerate( play_list): tmp_media_url = mediaUrl[:mediaUrl. rfind("/" ) + 1] + play_url[ 1:] response = requests.get( url=tmp_media_url, headers=media_info_headers, cookies=self.base_cookies) if response.status_code == 200: saved.write( bytes(response.content)) self.tasklist_.progress( row[3], index / len(play_list) * 164 ) # 比其所在canvas宽度小1,百分之99即撑满整个进度条 print( "*************downloading" + str(index / len(play_list) * 100) + "%**************") row[4].set( str( int(index / len(play_list) * 100)) + "%") except BaseException as e: row[4].set("失败") row.pop(3) self.tasklist_.append_download_history(row) messagebox.showinfo("错误", message=str(e)) else: row[4].set("100%") row.pop(3) self.tasklist_.append_download_history(row) messagebox.showinfo("提示", message=file_name + "下载完成!") th = threading.Thread(target=down) th.setDaemon(True) th.start() print(self.val_map[k]) except BaseException as e: print(e) traceback.print_exc(file=open('error.txt', 'a+')) messagebox.showerror("提示", message="下载出错") print("下载出错") def create_heading(self, ): '''重新做一个treeview的头,不然滚动滚动条,看不到原先的头!!!''' heading_frame = Frame(self.tk) heading_frame.pack(fill=X) # 填充用 # button_frame = Label(heading_frame,bg='gray') # button_frame.pack(side=LEFT, expand=False) # 全选按钮 self.all_buttonvar = IntVar() self.all_button = Checkbutton(heading_frame, text='', variable=self.all_buttonvar, command=self.select_all) self.all_button.pack(side=LEFT) self.all_buttonvar.set(0) self.columns = ['no', 'name', 'author'] self.columns_header_name = ['序号', '名称', '作者'] self.header_label_widths = [40, 260, 100] self.colums_header_widths = [46, 292, 115] # 重建tree的头 for i in range(len(self.columns)): Label(heading_frame, text=self.columns_header_name[i], width=int(self.header_label_widths[i] * 0.16), anchor='center', relief=GROOVE).pack(side=LEFT) def insert_test_tree_data(self): rows = [] for i in range(30): rows.append((i + 1, 'B', 'C', 110)) self.insert_tv(rows) def clear_tree_data(self): self.init_tree() # 初始化表格 def init_tree(self): [self.tv.delete(item) for item in self.tv.get_children()] self.tv.update() for child in self.button_frame.winfo_children(): # 第一个构件是label,所以忽略 child.destroy() self.canvas.itemconfigure(self.tv_frame, height=300) # 设定窗口tv_frame的高度 self.tk.update() self.canvas.config(scrollregion=self.canvas.bbox("all")) # 滚动指定的范围 self.canvas.config(height=300) def create_tv(self): # 放置 canvas、滚动条的frame canvas_frame = Frame(self.tk, width=500, height=400) canvas_frame.pack(fill=X) # 只剩Canvas可以放置treeview和按钮,并且跟滚动条配合 self.canvas = Canvas(canvas_frame, width=400, height=500, scrollregion=(0, 0, 500, 400)) self.canvas.pack(side=LEFT, fill=BOTH, expand=1) # 滚动条 ysb = Scrollbar(canvas_frame, orient=VERTICAL, command=self.canvas.yview) self.canvas.configure(yscrollcommand=ysb.set) ysb.pack(side=RIGHT, fill=Y) # !!!!=======重点:鼠标滚轮滚动时,改变的页面是canvas 而不是treeview self.canvas.bind_all( "<MouseWheel>", lambda event: self.canvas.yview_scroll( int(-1 * (event.delta / 120)), "units")) # 想要滚动条起效,得在canvas创建一个windows(frame)!! tv_frame = Frame(self.canvas) self.tv_frame = self.canvas.create_window(0, 0, window=tv_frame, anchor='nw', width=600, height=400) # anchor该窗口在左上方 # 放置button的frame self.button_frame = Frame(tv_frame) self.button_frame.pack(side=LEFT, fill=Y) Label(self.button_frame, width=3).pack() # 填充用 # 创建treeview self.tv = Treeview(tv_frame, height=10, columns=self.columns, show='tree') # height好像设定不了行数,实际由插入的行数决定 self.tv.column("#0", width=0, stretch=0) self.tv.pack(expand=True, side=LEFT, fill=BOTH) # 设定每一列的属性 for i in range(len(self.columns)): self.tv.column(self.columns[i], width=self.colums_header_widths[i], anchor='w', stretch=False) # 设定treeview格式 # import tkinter.font as tkFont # ft = tkFont.Font(family='Fixdsys', size=20, weight=tkFont.BOLD) self.tv.tag_configure('oddrow', font='黑体 8') # 设定treeview里字体格式font=ft self.tv.tag_configure('select', background='SkyBlue', font='Arial 8') # 当对应的按钮被打勾,那么对于的行背景颜色改变! self.rowheight = 27 # 很蛋疼,好像tkinter里只能用整数! Style().configure('Treeview', rowheight=self.rowheight) # 设定每一行的高度 # 设定选中的每一行字体颜色、背景颜色 (被选中时,没有变化) Style().map("Treeview", foreground=[ ('focus', 'black'), ], background=[('active', 'white')]) self.tv.bind('<<TreeviewSelect>>', self.select_tree) # 绑定tree选中时的回调函数 def insert_tv(self, rows=None): if rows == None: rows = [] for i in range(20): item = (i + 1, 'A', "B") rows.append(item) # 清空tree、checkbutton items = self.tv.get_children() [self.tv.delete(item) for item in items] self.tv.update() for child in self.button_frame.winfo_children(): # 第一个构件是label,所以忽略 child.destroy() # 重设tree、button对应关系 self.orm = {} index = 0 for row in rows: tv_item = self.tv.insert('', index, value=row[0:3], tags=('oddrow')) # item默认状态tags import tkinter ck_button = tkinter.Checkbutton(self.button_frame, variable=IntVar()) ck_button['command'] = lambda item=tv_item: self.select_button(item ) ck_button.pack() # ck_button['fragementId']=row[3] self.orm[tv_item] = [ck_button] self.val_map[tv_item] = row[3] index = index + 1 # 每次点击插入tree,先设定全选按钮不打勾,接着打勾并且调用其函数 self.all_buttonvar.set(0) self.all_button.invoke() # 更新canvas的高度 height = (len(self.tv.get_children()) + 1) * self.rowheight # treeview实际高度 self.canvas.itemconfigure(self.tv_frame, height=height) # 设定窗口tv_frame的高度 self.tk.update() self.canvas.config(scrollregion=self.canvas.bbox("all")) # 滚动指定的范围 self.canvas.config(height=height) def select_all(self): '''全选按钮的回调函数 作用:所有多选按钮打勾、tree所有行都改变底色(被选中)''' for item, [button] in self.orm.items(): if self.all_buttonvar.get() == 1: button.select() self.tv.item(item, tags='select') else: button.deselect() self.tv.item(item, tags='oddrow') def select_button(self, item): '''多选按钮的回调函数 作用:1.根据按钮的状态,改变对应item的底色(被选中) 2.根据所有按钮被选的情况,修改all_button的状态''' button = self.orm[item][0] button_value = button.getvar(button['variable']) if button_value == '1': self.tv.item(item, tags='select') else: self.tv.item(item, tags='oddrow') self.all_button_select() # 根据所有按钮改变 全选按钮状态 def select_tree(self, event): '''tree绑定的回调函数 作用:根据所点击的item改变 对应的按钮''' select_item = self.tv.focus() button = self.orm[select_item][0] button.invoke() # 改变对应按钮的状态,而且调用其函数 def all_button_select(self): '''根据所有按钮改变 全选按钮状态 循环所有按钮,当有一个按钮没有被打勾时,全选按钮取消打勾''' for [button] in self.orm.values(): button_value = button.getvar(button['variable']) if button_value == '0': self.all_buttonvar.set(0) break else: self.all_buttonvar.set(1)
class ShowWindow: def __init__(self): self.win = Toplevel() canvas = Canvas(self.win, width=800, height=400, bg='white') canvas.pack(expand=YES, fill=BOTH) # show window in center of screen width = self.win.winfo_screenwidth() height = self.win.winfo_screenheight() x = int(width / 2 - 800 / 2) y = int(height / 2 - 400 / 2) str1 = "800x400+" + str(x) + "+" + str(y) self.win.geometry(str1) # Disable resize of the window self.win.resizable(width=False, height=False) self.win.title("truTrackerEXP | SHOW INCOME SOURCES") def add_frame(self): self.frame = Frame(self.win, width=600, height=350) self.frame.place(x=80, y=20) x, y = 70, 20 # Use treeview to show the data in forms of table # Mention number of columns self.tr = Treeview(self.frame, columns=('A', 'B', 'C', 'D'), selectmode="extended") # Heading key + text self.tr.heading('#0', text='Sr No') self.tr.column('#0', minwidth=0, width=40, stretch=NO) self.tr.heading('#1', text='Source') self.tr.column('#1', minwidth=0, width=100, stretch=NO) self.tr.heading('#2', text='Description') self.tr.column('#2', minwidth=0, width=200, stretch=NO) self.tr.heading('#3', text='Update') self.tr.column('#3', minwidth=0, width=60, stretch=NO) self.tr.heading('#4', text='Delete') self.tr.column('#4', minwidth=0, width=60, stretch=NO) j = 0 for i in db.db.show_income(): self.tr.insert('', index=j, text=i[2], values=(i[0], i[1], 'Update', 'Delete')) j += 1 # Create action on selected row self.tr.bind('<Double-Button-1>', self.actions) # Position the table on the frame self.tr.place(x=50, y=y + 50) self.win.mainloop() def actions(self, e): # Get the value of the selected row tt = self.tr.focus() # Get the column id col = self.tr.identify_column(e.x) print(compile) print(self.tr.item(tt)) tup = (self.tr.item(tt).get('text'), ) if col == '#4': res = messagebox.askyesno("Message", "Are you sure you want to delete?") if res: rs = db.db.delete_income(tup) if rs: messagebox.showinfo("Message", "Data has been deleted.") self.win.destroy() z = ShowWindow() z.add_frame() else: self.win.destroy() z = ShowWindow() z.add_frame() if col == '#3': res = income.add_income.IncomeWindow(self.tr.item(tt)) self.win.destroy() res.add_frame()
class NodeTree: def __init__(self): self._client = KazooClient(hosts='localhost:2181') # self._client = KazooClient(hosts='10.128.62.34:2181,10.128.62.34:2182,10.128.62.34:2183') self._client.start() self._selected_node = None self._win = None self._root = None self._tree_canvas = None self._tree_frame_id = None self.init_ui() self.init_tree() self._count = 0 # self.treeify() print(self._count) self._win.mainloop() def init_ui(self): self._win = tk.Tk() self._win.title("zk-client") self._win.geometry('900x700+500+300') self._win.resizable(height=False, width=False) tree_wrapper = tk.Frame(self._win, bg='red', width=300) tree_wrapper.pack(side=tk.LEFT, fill=tk.Y) canvas = self._tree_canvas = tk.Canvas(tree_wrapper, width=300, height=700, scrollregion=(0, 0, 300, 700), bg='gray') # 创建canvas canvas.place(x=0, y=0) # 放置canvas的位置 frame = tk.Frame(canvas) # 把frame放在canvas里 # frame.place(width=180, height=600) # frame的长宽,和canvas差不多的 vbar = Scrollbar(canvas, orient=tk.VERTICAL) # 竖直滚动条 vbar.place(x=281, width=20, height=700) vbar.configure(command=canvas.yview) hbar = Scrollbar(canvas, orient=tk.HORIZONTAL) # 水平滚动条 hbar.place(x=0, y=680, width=280, height=20) hbar.configure(command=canvas.xview) canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set) # 设置 canvas.bind_all( "<MouseWheel>", lambda event: canvas.yview_scroll( int(-1 * (event.delta / 120)), "units")) self._tree_frame_id = canvas.create_window( 0, 0, window=frame, anchor='nw') # create_window) self._root = Treeview(frame) # self._root.pack(expand=True, fill=tk.BOTH) # self._root.bind("<Button-1>", self.clear_pre_selected) # self._root.bind("<< TreeviewClose>>", self.clear_pre_selected) self._root.bind("<<TreeviewOpen>>", self.open_node) def adjust_size(self): self._root.update() width = self._root.winfo_width() height = self._root.winfo_height() print(width, height) self._tree_canvas.itemconfigure(self._tree_frame_id, height=height) # 设定窗口tv_frame的高度 self._tree_canvas.config(scrollregion=(0, 0, width, height)) self._tree_canvas.config( scrollregion=self._tree_canvas.bbox("all")) # 滚动指定的范围 self._tree_canvas.config(height=height) pass def init_tree(self): tops = self._client.get_children("/") for index, top in enumerate(tops): self._root.insert('', index, text=top) children = self._client.get_children("/" + top + "/") if children is not None and len(children) > 0: pass def clear_pre_selected(self, event): focus = self._root.focus() if focus == '': return children = self._root.get_children(focus) for child in children: self._root.delete(child) def open_node(self, event): iid = self._root.focus() path = self.get_current_path(iid) children = self._client.get_children(path) for index, p in enumerate(children): self._root.insert(iid, index, text=p) self.adjust_size() def get_current_path(self, item): curr_item = self._root.item(item) pid = self._root.parent(item) if pid == '': return '/' + curr_item['text'] + "/" else: return self.get_current_path(pid) + curr_item['text'] + "/" def treeify(self): self._client.start() self.treeify_recursive("/", parent='', index=0) def treeify_recursive(self, path, parent, index): self._count += 1 cd = self._client.get_children(path=path) if cd and len(cd) > 0: for i, c in enumerate(cd): tmp_path = path + c + '/' tc = self._client.get_children(tmp_path) if tc and len(tc) > 0: insert = self._root.insert(parent, i, text=c) self.treeify_recursive(path=tmp_path, parent=insert, index=i) else: self._root.insert(parent, i, text=c)
class main(): def __init__(self, tk): self.frame_lgn = Frame(lgn_Screen, width=450, height=750) self.frame_lgn.pack() #Separator self.pane_W = LabelFrame(lgn_Screen, text='Your Credentials', width=300, height=200) self.pane_W.place(x=1, y=10) #Login Entry self.usr_label = Label(lgn_Screen, text="Usuário:") self.usr_label.place(x=22, y=53) self.usr_entry = Entry(lgn_Screen, width=25) self.usr_entry.place(x=72, y=50) #Passowrd Entry self.pw_label = Label(lgn_Screen, text="Senha:") self.pw_label.place(x=30, y=103) self.pw_entry = Entry(lgn_Screen, show="*", width=25) self.pw_entry.place(x=72, y=100) def validate(): usr = str(self.usr_entry.get()) pw = str(self.pw_entry.get()) print(usr) print(pw) #Separator message self.pane_W_Text = LabelFrame(lgn_Screen, text='Your Message:', width=300, height=200) self.pane_W_Text.place(x=1, y=210) #textbox self.tb = Text(lgn_Screen, width=35, height=8, borderwidth=0) self.tb.place(x=7, y=225) #Separator data self.pane_groups = LabelFrame(lgn_Screen, text='Seus Grupos aparecerão aqui:', width=300, height=200) self.pane_groups.place(x=1, y=410) self.tvGroups = Treeview(lgn_Screen) self.tvGroups.place(x=7, y=425, width=287, height=130) #Aviso de Botão fontStyle = tkFont.Font(size=8) self.advcLbl = Label( lgn_Screen, text= "* Aviso: o botão para confirmar o grupo será \nliberado em breve!", font=fontStyle) self.advcLbl.place(x=7, y=610) def conf_Message(): msg = str(self.tb.get('1.0', 'end-1c')) print(msg) from selenium import webdriver from time import sleep from selenium.webdriver.common.keys import Keys url = "https://facebook.com/" d = webdriver.Chrome() d.get(url) sleep(2) target_user = d.find_element_by_xpath('//*[@id="email"]') target_pw = d.find_element_by_xpath('//*[@id="pass"]') target_user.click() sleep(2) target_user.send_keys(str(self.usr_entry.get())) sleep(2) target_pw.send_keys(str(self.pw_entry.get())) sleep(6) log_in = d.find_element_by_xpath('//*[@id="u_0_b"]') sleep(1) log_in.click() sleep(3) webdriver.ActionChains(d).send_keys(Keys.ESCAPE).perform() sleep(4) explore_Group = d.find_element_by_xpath( '//*[@id="navItem_1434659290104689"]/a/div') explore_Group.click() sleep(3) webdriver.ActionChains(d).send_keys(Keys.ESCAPE).perform() sleep(1) try: while True: see_more = d.find_element_by_xpath( "//*[contains(text(), 'Ver mais')]") see_more.click() sleep(2) except: pass sleep(3) groups = d.find_elements_by_class_name('_2yaa') l_groups = [] for g_names in groups: l_groups.append(str(g_names.text)) print(l_groups) group_index = [] counter = 0 for j in l_groups[:-1]: if str(j) == 'Descobrir': continue print(str(counter) + " - " + str(j)) counter += 1 self.tvGroups.insert('', 'end', text=j) #selected_Group = "" def confirmGroup(): self.cur = self.tvGroups.focus() self.selectedItem = str(self.tvGroups.item(self.cur)['text']) print(self.selectedItem) openGroup = d.find_element_by_xpath("//*[contains(text(), '" + self.selectedItem + "')]") openGroup.click() sleep(6) postit = d.find_element_by_xpath( "//*[@name='xhpc_message_text']") postit.send_keys(str(self.tb.get('1.0', 'end-1c'))) sleep(5) publish = d.find_element_by_class_name('_332r') publish.click() self.selgroup = Button(lgn_Screen, text="Confirmar", width=10, font='Verdana 8', borderwidth=0, bg='#FFFFFF', fg='#363636', command=confirmGroup) self.selgroup.place(x=175, y=570) self.cnf_Msg = Button(lgn_Screen, text="Confirmar", width=10, font='Verdana 8', borderwidth=0, bg='#FFFFFF', fg='#363636', command=conf_Message) self.cnf_Msg.place(x=175, y=370, height=20)
class Library: """ Main class. Combines GUI, functionality and Database. Args: root (instance): tkinter's root instance. """ appName = "Knihovna" appVersion = "0.2" tabList = [["Knihy", ["ID", "Název knihy", "Autor", "Ilustrátor", "Rok"]]] def __init__(self, root): """Initialises Library class. Args: root (instance): tkinter's root instance. """ self.root = root self.root.geometry('1000x500') self.root.configure(background='#bdc3c7') self.root.minsize(1000, 500) self.root.title(Library.appName + " v" + Library.appVersion) self.toplevel = None self.notebook = Autoresized_Notebook(self.root) self.tables = [] self.tabs = [] i = 0 for tab in Library.tabList: tabframe = Frame(self.notebook) self.notebook.add(tabframe, text=f"{tab[0]}") # zjistí, který tab je právě otevřený a zavolá funkci windowCreate, které předá název tabu Button(tabframe, text='+', command=lambda: self.windowCreate(), height=1).pack(fill=X) if len(tab) >= 2: columnList = "" e = 0 for columnName in tab[1]: if e != 0: columnList += ", " columnList += f"{e}" e = e + 1 # + editovací tlačítko columnList += ", " + str((int(e) + 1)) self.treeview = Treeview(tabframe, columns=(columnList), show="headings", height=10) self.treeview.bind("<ButtonRelease-1>", self.bookEditBind) f = 0 for columnName in tab[1]: self.treeview.column(f, minwidth=0, width=150, anchor=N, stretch=TRUE) self.treeview.heading(f, text=f"{columnName}", anchor=W) f = f + 1 i = i + 1 self.treeview.column(f + 1, minwidth=0, width=150, anchor=N, stretch=TRUE) self.treeview.heading(f + 1, text="jiné", anchor=W) self.updateTable() self.tables.append( self.treeview.pack(fill=X, side=TOP, expand=1)) Button(tabframe, text='Exit', command=root.destroy).pack(padx=100, pady=100) self.notebook.pack(fill=BOTH, expand=1) def windowCreate(self, id=None, deleteCallback=None): """Creates another window. Args: id (int): id of selected book (default None). deleteCallback (function): callback of inserted function. """ if (self.toplevel is not None) and self.toplevel.exists == True: return self.toplevel = Window(self.root, id, saveNewBook=self.save, deleteBook=deleteCallback) def bookEditBind(self, event): """Binds event when clicking to 'edit' book info. Args: event (instance): event. """ button = self.treeview.identify_column(event.x) region = self.treeview.identify_region(event.x, event.y) if button != '#6' or region != 'cell': return item = self.treeview.focus() id = self.treeview.item(item)['values'][0] self.windowCreate(id, self.delete) def getBooks(self): """Clears self.books, reselects book info and its metadata and reinserts itself to self.books.""" self.books = [] booksInfo = Database.select("SELECT * FROM books") for book in booksInfo: info = { "ID": book[0], "authors": [], "illustrators": [], "title": book[1], "year": book[2] } meta = Database.select( f"SELECT meta.role, meta.name FROM bookWorkers LEFT JOIN (SELECT workers.ID, (people.forename || ' ' || people.surname) as name, roles.name as role FROM workers LEFT JOIN people ON people.ID = workers.peopleID LEFT JOIN roles ON workers.roleID = roles.ID) meta ON bookWorkers.workersID = meta.ID WHERE bookID = {book[0]}" ) for person in meta: info[person[0] + "s"].append(person[1]) self.books.append(info) def updateTable(self): """Deletes data from table and calls getBooks to reinsert data.""" self.getBooks() self.treeview.delete(*self.treeview.get_children()) for book in self.books: if (len(book["authors"]) >= 2): authors = ", ".join(book["authors"]) else: authors = book["authors"][0] if (len(book["illustrators"]) >= 2): illustrators = ", ".join(book["illustrators"]) elif not book["illustrators"]: illustrators = "" else: illustrators = book["illustrators"][0] self.treeview.insert("", END, values=(book["ID"], book["title"], authors, illustrators, book["year"], "upravit")) def delete(self, id): """Deletes selected book and updates table immediately after. Args: id (int): id of selected (edited) book. """ Database.execute(f"DELETE FROM books WHERE ID = {id}") Database.execute(f"DELETE FROM bookWorkers WHERE bookID = {id}") self.updateTable() def save(self, data, id): """Saves data to Database using class of the same name. Args: data (array): example: [{'forename': 'dd', 'surname': 'dd'}], 'illustrators': [{'forename': 'dd', 'surname': 'dd'}], 'title': None, 'year': None} id (integer): id of selected book. """ bookID = Database.execute( f"INSERT INTO books (title, year) VALUES ('{data['title']}', '{data['year']}')" ) for role in data["roles"]: for person in data["roles"][role]: personID = Database.select( f"SELECT ID FROM people WHERE forename = '{person['forename']}' AND surname = '{person['surname']}'" ) if not personID: personID = Database.execute( f"INSERT INTO people (forename, surname) VALUES ('{person['forename']}', '{person['surname']}')" ) else: personID = personID[0][0] workerID = Database.select( f"SELECT ID FROM workers WHERE peopleID = '{personID}' AND roleID = (SELECT ID FROM roles WHERE name = '{role}')" ) if not workerID: workerID = Database.execute( f"INSERT INTO workers (peopleID, roleID) VALUES ({personID}, (SELECT ID FROM roles WHERE name = '{role}'))" ) else: workerID = workerID[0][0] bookWorkerID = Database.select( f"SELECT ID FROM bookWorkers WHERE workersID = '{workerID}' AND roleID = (SELECT ID FROM roles WHERE name = '{role}')" ) if not bookWorkerID: bookWorkerID = Database.execute( f"INSERT INTO bookWorkers (bookID, workersID) VALUES ('{bookID}', '{workerID}')" ) else: bookWorkerID = bookWorkerID[0][0] self.updateTable()
class NameView(object): """Shows a treeview of unique names.""" def __init__(self, master, names): self.widget = Frame(master) self._tree = Treeview(self.widget, columns='name') self._tree.grid(row=0, column=0, sticky=(N, S, W, E)) self._tree.view = self self.widget.columnconfigure(0, weight=1) self.widget.rowconfigure(0, weight=1) self._tree.column('name', width=50) self._tree['show'] = 'tree' actions = { 'edit': lambda e: self.edit(), 'search': lambda e: self.search(), 'focus_next': lambda e: self.focus_next(), 'focus_prev': lambda e: self.focus_prev(), 'select': lambda e: self._tree.selection_toggle(self._tree.focus()), 'clear_selection': lambda e: self._tree.selection_set([]) } kb.make_bindings(kb.tagview, actions, self._tree.bind) self._iids = dict() self._names = dict() logger.debug('Names: %s', names) self.widget.focus_set = self._tree.focus_set for name in sorted(names): iid = self._tree.insert('', 'end', text=name) self._names[iid] = name self._iids[name] = iid self._scroll = Scrollbar(self.widget, command=self._tree.yview) self._tree['yscrollcommand'] = self._scroll.set self._scroll.grid(row=0, column=1, sticky=(N, S)) self.widget.columnconfigure(1, weight=0) def selection(self): logger.debug('Selection: %s', self._tree.selection()) return [self._names[iid] for iid in self._tree.selection()] def edit(self): self._tree.event_generate('<<NameViewEdit>>') def search(self): if len(self._tree.selection()) == 0: self._tree.selection_add(self._tree.focus()) self._tree.event_generate('<<NameViewSearch>>') def append(self, names): logger.debug('Append names: %s', names) for name in names: if name not in self._names.values(): iid = self._tree.insert('', 'end', text=name) self._names[iid] = name self._iids[name] = iid def delete(self, name): self._tree.delete(self._iids[name]) del self._names[self._iids[name]] del self._iids[name] def _focus(self, iid): self._tree.focus(iid) self._tree.see(iid) def focus_next(self): cur_iid = self._tree.focus() next_iid = self._tree.next(cur_iid) if next_iid == '': iids = self._tree.get_children() next_iid = iids[0] self._focus(next_iid) def focus_prev(self): cur_iid = self._tree.focus() prev_iid = self._tree.prev(cur_iid) if prev_iid == '': iids = self._tree.get_children() prev_iid = iids[-1] self._focus(prev_iid) def jump_to(self, name): try: iid = self._iids[name] self._focus(iid) except KeyError: pass def get_names(self): return tuple(self._names.values()) def set(self, names): self._tree.delete(*self._iids.values()) self._iids.clear() self._names.clear() for name in sorted(names): iid = self._tree.insert('', 'end', text=name) self._names[iid] = name self._iids[name] = iid
class MainGUI: def __init__(self, master): self.parent = master # Set frame for the whole thing self.parent.title("LMS") self.frame = Frame(self.parent, width=1500, height=750) self.frame.grid(row=0, column=0) self.frame.grid_rowconfigure(0, weight=1) self.frame.grid_columnconfigure(0, weight=1) self.frame.grid_propagate(False) # Parameter Initialization self.search_string = None self.data = None self.borrowerId = None self.bookForCheckOutIsbn = None # Frame for the welcome message and header self.HeaderFrame = Frame(self.frame) self.HeaderFrame.grid(row=0, column=0, sticky=N) self.HeaderFrame.grid_rowconfigure(0, weight=1) self.HeaderFrame.grid_columnconfigure(0, weight=1) # # Label for the welcome message self.HeaderLabel = Label(self.HeaderFrame, text='What Book Do You Want?') self.HeaderLabel.grid(row=0, column=0) self.HeaderLabel.grid_rowconfigure(0, weight=10) self.HeaderLabel.grid_columnconfigure(0, weight=10) #Label for the searchbox self.SearchLabel = Label(self.HeaderFrame, text='') self.SearchLabel.grid(row=1, column=0) self.SearchLabel.grid_rowconfigure(1, weight=10) self.SearchLabel.grid_columnconfigure(0, weight=10) # Search Frame self.SearchFrame = Frame(self.frame) self.SearchFrame.grid(row=1, column=0, sticky=N) self.SearchFrame.grid_rowconfigure(1, weight=1) # self.SearchFrame.grid_columnconfigure(0, weight=1) self.SearchLabel = Label(self.SearchFrame, text='Search') self.SearchLabel.grid(row=0, column=0) self.SearchLabel.grid_rowconfigure(0, weight=1) # self.SearchLabel.grid_columnconfigure(0, weight=1) self.SearchTextBox = Entry(self.SearchFrame, text='Enter search string here...', width=70) self.SearchTextBox.grid(row=1, column=0) self.SearchTextBox.grid_rowconfigure(1, weight=1) self.SearchButton = Button(self.SearchFrame, text='Search', command=self.search) self.SearchButton.grid(row=2, column=0) self.SearchButton.grid_rowconfigure(2, weight=1) # Search Result Frame self.ActiveArea = Frame(self.frame) self.ActiveArea.grid(row=2, column=0, sticky=N) self.ActiveArea.grid_rowconfigure(2, weight=1) self.ResultTreeview = Treeview( self.ActiveArea, columns=["ISBN", "Book Title", "Author(s)", "Availability"]) self.ResultTreeview.grid(row=1, column=1) self.ResultTreeview.grid_rowconfigure(0, weight=1) self.ResultTreeview.heading('#0', text="ISBN") self.ResultTreeview.heading('#1', text="Book Title") self.ResultTreeview.heading('#2', text="Author(s)") self.ResultTreeview.heading('#3', text="Availability") self.ResultTreeview.bind('<ButtonRelease-1>', self.selectBookForCheckout) # Interaction Frame self.MajorFunctions = Frame(self.frame) self.MajorFunctions.grid(row=3, column=0, sticky=N) self.MajorFunctions.grid_rowconfigure(3, weight=1) self.checkOutBtn = Button(self.MajorFunctions, text="Check Out Book", command=self.check_out) self.checkOutBtn.grid(row=0, column=0, padx=10, pady=10) self.checkOutBtn.grid_rowconfigure(0, weight=1) self.checkOutBtn.grid_columnconfigure(0, weight=1) self.checkInBtn = Button(self.MajorFunctions, text="Check In Book", command=self.check_in) self.checkInBtn.grid(row=0, column=1, padx=10, pady=10) self.checkOutBtn.grid_rowconfigure(0, weight=1) self.checkOutBtn.grid_columnconfigure(1, weight=1) self.updateFinesBtn = Button(self.MajorFunctions, text="Updates Fines", command=self.update_fines) self.updateFinesBtn.grid(row=1, column=0, padx=10, pady=10) self.payFinesBtn = Button(self.MajorFunctions, text="Pay Fines", command=self.pay_fines) self.payFinesBtn.grid(row=1, column=1, padx=10, pady=10) self.changeDayBtn = Button(self.MajorFunctions, text="Change Day", command=self.change_day) self.changeDayBtn.grid(row=1, column=2, padx=10, pady=10) self.addBorrowerBtn = Button(self.MajorFunctions, text="Add New Borrower", command=self.add_borrower) self.addBorrowerBtn.grid(row=0, column=2, padx=10, pady=10) def change_day(self): global todays_date todays_date = todays_date + timedelta(days=1) print(todays_date) def search(self): self.search_string = self.SearchTextBox.get() cursor = cnx.cursor() cursor.execute( "select BOOK.isbn, BOOK.title, AUTHORS.fullname from BOOK join BOOK_AUTHORS on " "BOOK.isbn = BOOK_AUTHORS.isbn join AUTHORS on BOOK_AUTHORS.author_id = AUTHORS.author_id " "where BOOK.title like concat('%', '" + self.search_string + "', '%') or " "AUTHORS.fullname like concat('%', '" + self.search_string + "', '%') or " "BOOK.isbn like concat('%', '" + self.search_string + "', '%')") self.data = cursor.fetchall() self.view_data() def view_data(self): """ View data on Treeview method. """ self.ResultTreeview.delete(*self.ResultTreeview.get_children()) for elem in self.data: cursor = cnx.cursor() cursor.execute( "SELECT EXISTS(SELECT BOOK_LOANS.isbn from BOOK_LOANS where BOOK_LOANS.isbn = '" + str(elem[0]) + "')") result = cursor.fetchall() if result == [(0, )]: availability = "Available" else: cursor = cnx.cursor() cursor.execute( "SELECT BOOK_LOANS.Date_in from BOOK_LOANS where BOOK_LOANS.isbn = '" + str(elem[0]) + "'") result = cursor.fetchall() if result[-1][0] is None: availability = "Not Available" else: availability = "Available" self.ResultTreeview.insert('', 'end', text=str(elem[0]), values=(elem[1], elem[2], availability)) def selectBookForCheckout(self, a): curItem = self.ResultTreeview.focus() self.bookForCheckOutIsbn = self.ResultTreeview.item(curItem)['text'] def check_out(self): if self.bookForCheckOutIsbn is None: messagebox.showinfo("Attention!", "Select Book First!") return None self.borrowerId = simpledialog.askstring("Check Out Book", "Enter Borrower ID") cursor = cnx.cursor() cursor.execute( "SELECT EXISTS(SELECT Card_no from BORROWERS WHERE BORROWERS.Card_no = '" + str(self.borrowerId) + "')") result = cursor.fetchall() if result == [(0, )]: messagebox.showinfo("Error", "Borrower not in Database!") return None else: count = 0 cursor = cnx.cursor() cursor.execute( "SELECT BOOK_LOANS.Date_in from BOOK_LOANS WHERE BOOK_LOANS.Card_no = '" + str(self.borrowerId) + "'") result = cursor.fetchall() for elem in result: if elem[0] is None: count += 1 if count >= 3: messagebox.showinfo("Not Allowed!", "Borrower has loaned 3 books already!") return None else: cursor = cnx.cursor() cursor.execute("SET FOREIGN_KEY_CHECKS=0") cursor.execute( "INSERT INTO BOOK_LOANS (ISBN, Card_no, Date_out, Due_date) VALUES ('" + self.bookForCheckOutIsbn + "', '" + self.borrowerId + "', '" + str(todays_date) + "', '" + str(todays_date + timedelta(days=14)) + "')") cursor.execute("SET FOREIGN_KEY_CHECKS=1") cnx.commit() cursor = cnx.cursor() cursor.execute("SELECT MAX(Loan_Id) FROM BOOK_LOANS") result = cursor.fetchall() loan_id = result[0][0] cursor.execute( "INSERT INTO FINES (Loan_Id, fine_amt, paid) VALUES ('" + str(loan_id) + "', '0.00', '0')") cnx.commit() messagebox.showinfo("Done", "Book Loaned Out!") def check_in(self): self.checkInWindow = Toplevel(self.parent) self.checkInWindow.title("Check In Here") self.app = CheckIn(self.checkInWindow) def update_fines(self): cursor = cnx.cursor() cursor.execute( "SELECT BOOK_LOANS.Loan_Id, BOOK_LOANS.Date_in, BOOK_LOANS.Due_date FROM BOOK_LOANS" ) result = cursor.fetchall() for record in result: date_in = record[1] date_due = record[2] if date_in is None: date_in = todays_date diff = date_in.date() - date_due.date() if diff.days > 0: fine = int(diff.days) * 0.25 else: fine = 0 cursor = cnx.cursor() cursor.execute("UPDATE FINES SET FINES.fine_amt = '" + str(fine) + "' WHERE FINES.Loan_Id = '" + str(record[0]) + "'") cnx.commit() messagebox.showinfo("Info", "Generated Fines") def pay_fines(self): self.newPayFinesWindow = Toplevel(self.parent) self.newPayFinesWindow.title("Fine!!") self.app1 = PayFines(self.newPayFinesWindow) def add_borrower(self): self.newBorrowerWindow = Toplevel(self.parent) self.newBorrowerWindow.title("Borrowing Person New") self.newapp = BorrowingPerson(self.newBorrowerWindow)
class main: def __init__(self): self.tk = Toplevel() height = self.tk.winfo_screenheight() width = self.tk.winfo_screenwidth() y = (height - 650) // 2 x = (width - 650) // 2 self.tk.geometry('650x650+' + str(x) + '+' + str(y)) self.tk.resizable(height=False, width=False) self.tk.title("manage patient") self.f = Frame(self.tk, height="650", width="650", bg="#CEE3F6") self.f.place(x=0, y=0) self.f1 = Frame(self.f, height="100", width="650", bg="#070719") self.f1.place(x=0, y=0) self.l = Label(self.f1, text="Manage Patient", font=('cooper black', 35), fg="#CEE3F6", bg="#070719") self.l.place(x=150, y=20) self.fr = Frame(self.f, height="70", width="650", bg="#070719") self.fr.place(x=0, y=580) self.fr1 = Frame(self.f, height="10", width="650", bg="#070719") self.fr1.place(x=0, y=560) self.table = Treeview(self.f, column=("#0", "#1", "#2", "#3", "#4", "#5", "#6", "#7", "#8", "#9")) style = ttk.Style() style.theme_use("alt") ttk.Style().configure("Treeview.heading", font=('', 30)) self.table.heading("#0", text="sno") self.table.column("#0", width="30") self.table.heading("#1", text="Name") self.table.column("#1", width="60") self.table.heading("#2", text="Gender") self.table.column("#2", width="60") self.table.heading("#3", text="Age") self.table.column("#3", width="60") self.table.heading("#4", text="contact") self.table.column("#4", width="70") self.table.heading("#5", text="Address") self.table.column("#5", width="70") self.table.heading("#6", text="Email") self.table.column("#6", width="90") self.table.heading("#7", text="History") self.table.column("#7", width="70") self.table.heading("#8", text="Edit") self.table.column("#8", width="70") self.table.heading("#9", text="Delete") self.table.column("#9", width="70") self.table.place(x=0, y=200) s = database_queries.database() res = s.view_patient() print(res) for i in res: self.table.insert('', 'end', text=i[0], value=(i[1], i[2], i[3], i[4], i[5], i[6], "History", "Edit", "Delete")) self.table.bind("<Double Button>", self.trigger) self.table.place() self.tk.mainloop() def trigger(self, e): #print(e) d = self.table.focus() g = (self.table.item(d)) col = self.table.identify_column(e.x) if col == "#8": y = editp.main(g["text"]) print("edit") elif col == "#9": print("delete") f = del_appoint()
class user: def __init__(self, root, background_color, user_login, cursor): self.r = root self.bgc = background_color self.login = user_login self.cur = cursor self.cur.execute( "select client_id from client where client_login = '******';") tmp = self.cur.fetchall() self.userid = tmp[0][0] self.today_date = '{0:%Y-%m-%d %H:%M:%S} '.format( datetime.datetime.now()) ############################################################################## # 1. START # 1.1 INIT def init_start_widgets(self): self.choose_button = Button(self.r, text="Записаться", width=20, height=7, command=self.choose) self.my_workouts_button = Button(self.r, text="Мои занятия", width=20, height=7, command=self.show_my_workouts) # 1.2 PLACE def place_start(self): self.init_start_widgets() self.choose_button.place(x=200, y=240) self.my_workouts_button.place(x=400, y=240) # 1.3 REMOVE def remove_start(self): self.choose_button.destroy() self.my_workouts_button.destroy() # 1.4 COMMANDS def choose(self): self.remove_start() self.place_choose() def show_my_workouts(self): self.remove_start() self.place_my_worklouts() ############################################################################## ############################################################################## # 2. CHOOSE CLUB AND KIND OF SPORT # 2.1 INIT def init_choose_widgets(self, root): self.choose_label = Label(text='Выберите клуб и вид спорта:',\ font = 'Arial 20', bg = self.bgc) q = get_all_clubs() self.cur.execute(q) tmp = self.cur.fetchall() clubs = [] for i in range(len(tmp)): clubs.append(tmp[i][0]) self.variable_c = StringVar(root) self.variable_c.set(clubs[0]) # default value self.clubs_option_menu = OptionMenu(root, self.variable_c, *clubs) self.clubs_option_menu.config(width=20, height=3, bg=self.bgc, font=16) q = get_all_sports() self.cur.execute(q) tmp = self.cur.fetchall() kind_of_sport = [] for i in range(len(tmp)): kind_of_sport.append(tmp[i][0]) self.variable_k = StringVar(root) self.variable_k.set(kind_of_sport[0]) self.kind_of_sport_option_menu = OptionMenu(root, self.variable_k, *kind_of_sport) self.kind_of_sport_option_menu.config(width=20, height=3, bg=self.bgc, font=16) self.next_in_choose_button = Button(root, text='Далее',width=15,\ height=3,command=self.next_in_choose) self.back_to_start_button = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_start) # 2.2 PLACE def place_choose(self): self.init_choose_widgets(self.r) self.choose_label.place(x=200, y=160) self.clubs_option_menu.place(x=260, y=200) self.kind_of_sport_option_menu.place(x=260, y=300) self.next_in_choose_button.place(x=305, y=400) self.back_to_start_button.place(x=305, y=500) # 2.3 REMOVE def remove_choose(self): self.choose_label.destroy() self.clubs_option_menu.destroy() self.kind_of_sport_option_menu.destroy() self.next_in_choose_button.destroy() self.back_to_start_button.destroy() # 2.3 COMMANDS def next_in_choose(self): club = self.variable_c.get() kind_of_sport = self.variable_k.get() self.remove_choose() self.place_trainlist(club, kind_of_sport) def back_to_start(self): self.remove_choose() self.place_start() ############################################################################## ############################################################################## # 3. TRAINLIST # 3.1 INIT def init_trainlist_widgets(self, root, club, sport): headings = ["вид спорта", "тренер", "рейтинг","тип", "места", "дата",\ "длительность"] self.trains_table = Treeview(root, selectmode="browse", show='headings', height=25) self.trains_table["columns"] = headings self.trains_table["displaycolumns"] = headings for head in headings: self.trains_table.heading(head, text=head, anchor=CENTER) self.trains_table.column("вид спорта", anchor=CENTER, width=180) self.trains_table.column("тренер", anchor=CENTER, width=180) self.trains_table.column("рейтинг", anchor=CENTER, width=70) self.trains_table.column("тип", anchor=CENTER, width=40) self.trains_table.column("места", anchor=CENTER, width=60) self.trains_table.column("дата", anchor=CENTER, width=145) self.trains_table.column("длительность", anchor=CENTER, width=120) q = get_actual_workouts(self.userid, self.today_date, club, sport) self.cur.execute(q) tmp = self.cur.fetchall() self.w_ids = [] for train in tmp: train = list(train) poped = train.pop(len(train) - 1) self.w_ids.append(poped) self.trains_table.insert('', END, values=tuple(train)) self.choose_train_button = Button(root, text="Выбрать", width=15, height=3, command=self.choose_train) self.back_to_choose_button = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_choose) # 3.2 PLACE def place_trainlist(self, club, kind_of_sport): self.init_trainlist_widgets(self.r, club, kind_of_sport) self.trains_table.place(x=0, y=0) self.choose_train_button.place(x=320, y=530) self.back_to_choose_button.place(x=0, y=530) # 3.3 REMOVE def remove_trainlist(self): self.trains_table.destroy() self.choose_train_button.destroy() self.back_to_choose_button.destroy() # 3.4 COMMANDS def choose_train(self): indd = self.trains_table.focus() if indd == "": messagebox.showinfo("", "Выберите тренировку") else: ind = int(convert_base(indd[1:], to_base=10, from_base=16)) - 1 curr_workout_id = self.w_ids[ind] q = generate_insert_into_client_workout(self.userid, curr_workout_id) self.cur.execute(q) q = generate_update_for_places_count(curr_workout_id) self.cur.execute(q) self.remove_trainlist() self.place_start() messagebox.showinfo("", "Подтверждено") def back_to_choose(self): self.remove_trainlist() self.place_choose() ############################################################################## ############################################################################## # 4. MY_WORKOUTS # 4.1 INIT def init_my_workouts_widgets(self, root): self.my_workouts_label = Label(text='Мои занятия:',\ font = 'Arial 20', bg = self.bgc) self.past_workouts_button = Button(root,text="Прошедшие",width=17,height=10,\ command=self.show_past) self.future_workouts_button = Button(root,text="Предстоящие",width=17,height=10,\ command=self.show_future) self.back_to_start_button2 = Button(root, text='Назад',width=17,height=3,\ command=self.back_to_start2) # 4.2 PLACE def place_my_worklouts(self): self.init_my_workouts_widgets(self.r) self.my_workouts_label.place(x=315, y=80) self.past_workouts_button.place(x=315, y=120) self.future_workouts_button.place(x=315, y=300) self.back_to_start_button2.place(x=315, y=500) # 4.3 REMOVE def remove_my_workouts(self): self.my_workouts_label.destroy() self.past_workouts_button.destroy() self.future_workouts_button.destroy() self.back_to_start_button2.destroy() # 4.4 COMMANDS def show_past(self): self.remove_my_workouts() self.place_past_workouts() def show_future(self): self.remove_my_workouts() self.place_future_workouts() def back_to_start2(self): self.remove_my_workouts() self.place_start() ############################################################################## ############################################################################## # 5. PAST WORKOUTS # 5.1 INIT def init_past_workouts_widgets(self, root): self.past_workouts_table = Treeview(root, selectmode="browse", show='headings', height=25) headings = [ "клуб", "вид спорта", "тренер", "дата", "длительность", "ваша оценка" ] self.past_workouts_table["columns"] = headings self.past_workouts_table["displaycolumns"] = headings for head in headings: self.past_workouts_table.heading(head, text=head, anchor=CENTER) self.past_workouts_table.column("клуб", anchor=CENTER, width=115) self.past_workouts_table.column("вид спорта", anchor=CENTER, width=155) self.past_workouts_table.column("тренер", anchor=CENTER, width=165) self.past_workouts_table.column("дата", anchor=CENTER, width=135) self.past_workouts_table.column("длительность", anchor=CENTER, width=110) self.past_workouts_table.column("ваша оценка", anchor=CENTER, width=125) q = get_user_past_workouts(self.userid, self.today_date) self.cur.execute(q) tmp = self.cur.fetchall() self.w_ids_for_rating = [] for train in tmp: train = list(train) poped = train.pop(len(train) - 1) self.w_ids_for_rating.append(poped) self.past_workouts_table.insert('', END, values=tuple(train)) self.set_rating_button = Button(root,text="Поставить оценку",width=15,height=1, \ command=self.set_rating) self.back_to_my_workouts_button = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_my_workouts) self.rating_entry = Text(root, height=1.2, width=16, font='Arial 12') # 5.2 PLACE def place_past_workouts(self): self.init_past_workouts_widgets(self.r) self.past_workouts_table.place(x=0, y=0) self.set_rating_button.place(x=320, y=530) self.back_to_my_workouts_button.place(x=0, y=530) self.rating_entry.place(x=320, y=560) # 5.3 REMOVE def remove_past_workouts(self): self.past_workouts_table.destroy() self.set_rating_button.destroy() self.back_to_my_workouts_button.destroy() self.rating_entry.destroy() # 5.4 COMMANDS def set_rating(self): indd = self.past_workouts_table.focus() if indd == "": messagebox.showinfo("", "Выберите тренировку") else: ind = int(convert_base(indd[1:], to_base=10, from_base=16)) - 1 curr_workout_id = self.w_ids_for_rating[ind] q = get_current_workout_rating(self.userid, curr_workout_id) self.cur.execute(q) tmp = self.cur.fetchall() current_train_rating = tmp[0][0] if current_train_rating == " ": input_rating = self.rating_entry.get('1.0', 'end-1c') if input_rating.replace(".", "", 1).isdigit() == False: messagebox.showinfo("", "Оценка введена некоректно") elif float(input_rating) < 0 or float(input_rating) > 5: messagebox.showinfo( "", "Оценка ставиться по пятибальной шкале") else: input_rating = round(float(input_rating), 2) q = update_rating(self.userid, curr_workout_id, input_rating) self.cur.execute(q) q = get_current_coach_id_rating(curr_workout_id) self.cur.execute(q) tmp = self.cur.fetchall() tmp_coach_id = int(tmp[0][0]) tmp_coach_rating = tmp[0][1] tmp_coach_marked_w_count = tmp[0][2] new_rating = (tmp_coach_rating * tmp_coach_marked_w_count + input_rating) / (tmp_coach_marked_w_count + 1) q = update_coach_rating(tmp_coach_id, new_rating) self.cur.execute(q) self.remove_past_workouts() self.place_past_workouts() else: messagebox.showinfo( "", "Оценка уже выставлена. В соответствии с нашими правилами оценка выставляется один раз и не подлежит изменению" ) def back_to_my_workouts(self): self.remove_past_workouts() self.place_my_worklouts() ############################################################################## ############################################################################## # 6. FUTURE WORKOUTS # 6.1 INIT def init_future_workouts_widgets(self, root): self.future_workouts_table = Treeview(root, selectmode="browse", show='headings', height=25) headings = [ "клуб", "вид спорта", "тренер", "дата", "длительность", "рейтинг" ] self.future_workouts_table["columns"] = headings self.future_workouts_table["displaycolumns"] = headings for head in headings: self.future_workouts_table.heading(head, text=head, anchor=CENTER) self.future_workouts_table.column("клуб", anchor=CENTER, width=115) self.future_workouts_table.column("вид спорта", anchor=CENTER, width=155) self.future_workouts_table.column("тренер", anchor=CENTER, width=165) self.future_workouts_table.column("дата", anchor=CENTER, width=150) self.future_workouts_table.column("длительность", anchor=CENTER, width=110) self.future_workouts_table.column("рейтинг", anchor=CENTER, width=110) q = get_user_future_workouts(self.userid, self.today_date) self.cur.execute(q) tmp = self.cur.fetchall() self.w_ids_for_remove_workout = [] for train in tmp: train = list(train) poped = train.pop(len(train) - 1) self.w_ids_for_remove_workout.append(poped) self.future_workouts_table.insert('', END, values=tuple(train)) self.remove_workout_button = Button(root, text="Отменить тренировку", width=15, height=3, command=self.remove_workout) self.back_to_my_workouts_button2 = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_my_workouts2) # 6.2 PLACE def place_future_workouts(self): self.init_future_workouts_widgets(self.r) self.future_workouts_table.place(x=0, y=0) self.remove_workout_button.place(x=300, y=530) self.back_to_my_workouts_button2.place(x=0, y=530) # 6.3 REMOVE def remove_future_workouts(self): self.future_workouts_table.destroy() self.remove_workout_button.destroy() self.back_to_my_workouts_button2.destroy() # 6.4 COMMANDS def remove_workout(self): indd = self.future_workouts_table.focus() if indd == "": messagebox.showinfo("", "Выберите тренировку") else: ind = int(convert_base(indd[1:], to_base=10, from_base=16)) - 1 curr_workout_id = self.w_ids_for_remove_workout[ind] q = delete_cancel_workout(self.userid, curr_workout_id) self.cur.execute(q) q = update_places(curr_workout_id) self.cur.execute(q) self.remove_future_workouts() self.place_future_workouts() def back_to_my_workouts2(self): self.remove_future_workouts() self.place_my_worklouts()
class MainWindow: """ Класс главного окна """ def __init__(self, top=None): """ Создание всех элементов окна """ top.geometry("1200x570+120+20") top.title("Football Analyser") top.configure(background=config.background_color) top.configure(highlightbackground=config.background_color) top.configure(highlightcolor="black") self.tree_view = Treeview(top, show="headings") self.first_name_label = Label(top) self.last_name_label = Label(top) self.country_label = Label(top) self.age_label = Label(top) self.plays_label = Label(top) self.goals_label = Label(top) self.first_name_entry = Entry(top) self.last_name_entry = Entry(top) self.country_entry = Entry(top) self.age_entry = Entry(top) self.plays_entry = Entry(top) self.goals_entry = Entry(top) self.entries_list = [ self.first_name_entry, self.last_name_entry, self.country_entry, self.age_entry, self.plays_entry, self.goals_entry ] self.add_button = Button(top) self.delete_button = Button(top) self.modify_button = Button(top) self.clear_fields_button = Button(top) self.analyze_button = Button(top) self.configure_tree_view()\ .configure_labels()\ .configure_entries()\ .configure_buttons()\ .fill_on_start() def configure_tree_view(self): """ Настройка treeview для отображения всех записей """ self.tree_view.place(relx=0.008, rely=0.018, relheight=0.837, relwidth=0.754) self.tree_view["columns"] = ("First name", "Last name", "Country", "Age", "Plays", "Goals") self.tree_view.column("First name", width=200) self.tree_view.column("Last name", width=200) self.tree_view.column("Country", width=100) self.tree_view.column("Age", width=100) self.tree_view.column("Plays", width=100) self.tree_view.column("Goals", width=100) self.tree_view.heading("First name", text="First name") self.tree_view.heading("Last name", text="Last name") self.tree_view.heading("Country", text="Country") self.tree_view.heading("Age", text="Age") self.tree_view.heading("Plays", text="Plays") self.tree_view.heading("Goals", text="Goals") self.tree_view.bind("<<TreeviewSelect>>", lambda event: self.on_select_item()) return self def configure_labels(self): """ Настройка текста над полями ввода """ self.first_name_label.place(relx=0.775, rely=0.07, height=26, width=74) self.first_name_label.configure(background=config.background_color) self.first_name_label.configure(text="First name") self.last_name_label.place(relx=0.775, rely=0.193, height=26, width=73) self.last_name_label.configure(background=config.background_color) self.last_name_label.configure(text="Last name") self.country_label.place(relx=0.775, rely=0.316, height=26, width=57) self.country_label.configure(background=config.background_color) self.country_label.configure(text="Country") self.age_label.place(relx=0.775, rely=0.439, height=26, width=33) self.age_label.configure(background=config.background_color) self.age_label.configure(text="Age") self.plays_label.place(relx=0.775, rely=0.561, height=26, width=39) self.plays_label.configure(background=config.background_color) self.plays_label.configure(text="Plays") self.goals_label.place(relx=0.775, rely=0.684, height=26, width=43) self.goals_label.configure(background=config.background_color) self.goals_label.configure(text="Goals") return self def configure_entries(self): """ Настройка полей ввода """ self.first_name_entry.place(relx=0.775, rely=0.123, height=24, relwidth=0.17) self.first_name_entry.configure(font=config.font) self.last_name_entry.place(relx=0.775, rely=0.246, height=24, relwidth=0.17) self.last_name_entry.configure(font=config.font) self.country_entry.place(relx=0.775, rely=0.368, height=24, relwidth=0.17) self.country_entry.configure(font=config.font) self.age_entry.place(relx=0.775, rely=0.491, height=24, relwidth=0.17) self.age_entry.configure(font=config.font) self.plays_entry.place(relx=0.775, rely=0.614, height=24, relwidth=0.17) self.plays_entry.configure(font=config.font) self.goals_entry.place(relx=0.775, rely=0.737, height=24, relwidth=0.17) self.goals_entry.configure(font=config.font) return self def configure_buttons(self): """ Настройка кнопок """ self.add_button.place(relx=0.792, rely=0.807, height=33, width=40) self.add_button.configure(background=config.background_color) self.add_button.configure(text="Add") self.add_button.configure(command=self.add_item) self.delete_button.place(relx=0.9, rely=0.807, height=33, width=56) self.delete_button.configure(background=config.background_color) self.delete_button.configure(text="Delete") self.delete_button.configure(command=self.delete_item) self.modify_button.place(relx=0.842, rely=0.807, height=33, width=59) self.modify_button.configure(background=config.background_color) self.modify_button.configure(text="Modify") self.modify_button.configure(command=self.modify_item) self.clear_fields_button.place(relx=0.8, rely=0.895, height=33, width=166) self.clear_fields_button.configure(background=config.background_color) self.clear_fields_button.configure(text="Clear fields") self.clear_fields_button.configure(command=self.clear_all_entries) self.analyze_button.place(relx=0.225, rely=0.877, height=53, width=336) self.analyze_button.configure(background=config.background_color) self.analyze_button.configure(text="Analyze") self.analyze_button.configure(font="-size 18") self.analyze_button.configure(command=self.analyze) return self def fill_on_start(self): """ Заполнение treeview записями из базы данных """ for row in db.get_records(): self.tree_view.insert("", tk.END, values=row) return self def on_select_item(self): """ Отображение выбранной записи в полях ввода для редактирования """ values = self.tree_view.item(self.tree_view.focus())["values"] for entry, val in zip(self.entries_list, values): entry.delete(0, tk.END) entry.insert(0, val) def clear_all_entries(self): """ Очистка всех полей ввода """ for entry in self.entries_list: entry.delete(0, tk.END) def delete_item(self): """ Удаление записи """ item = self.tree_view.focus() db.delete_record(self.tree_view.index(item)) self.tree_view.delete(item) self.clear_all_entries() def add_item(self): """ Добавление записи """ try: first_name = validator.validate_text(self.first_name_entry.get()) last_name = validator.validate_text(self.last_name_entry.get()) country = validator.validate_text(self.country_entry.get()) age = validator.validate_number(self.age_entry.get()) plays = validator.validate_number(self.plays_entry.get()) goals = validator.validate_number(self.goals_entry.get()) db.insert_record({ "first_name": first_name, "last_name": last_name, "country": country, "age": age, "plays": plays, "goals": goals }) self.tree_view.insert("", tk.END, values=(first_name, last_name, country, age, plays, goals)) except ValueError: messagebox.showerror("Invalid input", "Input are not valid string or number") self.on_select_item() def modify_item(self): """ Изменение записи """ try: item = self.tree_view.focus() index = self.tree_view.index(item) first_name = validator.validate_text(self.first_name_entry.get()) last_name = validator.validate_text(self.last_name_entry.get()) country = validator.validate_text(self.country_entry.get()) age = validator.validate_number(self.age_entry.get()) plays = validator.validate_number(self.plays_entry.get()) goals = validator.validate_number(self.goals_entry.get()) db.update_record( index, (first_name, last_name, country, age, plays, goals)) self.tree_view.item(item, values=(first_name, last_name, country, age, plays, goals)) except ValueError: messagebox.showerror("Invalid input", "Input are not valid string or number") self.on_select_item() def analyze(self): """ Вызов анализа """ analyse.full_analysis() messagebox.showinfo("Done", "Файлы отчета сохранены в output и graphics")
class CopyFileFrame(CopilotInnerFrame): def __init__(self, master, config, state): super(CopyFileFrame, self).__init__(master, config) self._state = state self._item_paths = {} self._tree = Treeview(self._master, columns=('size')) self._tree.heading('size', text='Size') self._tree.grid(row=1, column=0, columnspan=3, sticky='nsew') self._tree.configure(yscrollcommand=self._sb.set) self._sb['command'] = self._tree.yview if self._state.action == 'copy': self._next_btn['text'] = 'Copy' self._frame_lbl['text'] = 'Copy File' self._populate_tree(self._config.file_root) elif self._state.action == 'delete': self._next_btn['text'] = 'Delete' self._frame_lbl['text'] = 'Delete File' self._populate_tree(self._state.to_device.part().mount()) self._next_btn['command'] = self._next_cmd def _next_cmd(self): if self._state.action == 'copy': self._copy_file() elif self._state.action == 'delete': self._delete_file() def _copy_file(self): cur_item = self._tree.focus() cur_path = self._item_paths.get(cur_item, '') if cur_path != '': new_path = os.path.join(self._state.device_to_path, os.path.basename(cur_path)) try: if os.path.exists(new_path): if ConfirmFrame.show( self._master, self._config, 'The file already exists in the destination.\n' 'Would you like to overwrite it?', 'Yes', 'No' ): shutil.copyfile(cur_path, new_path) else: shutil.copyfile(cur_path, new_path) except PermissionError: OkFrame.show( self._master, self._config, 'Error copying file:\n\nInvalid permissions' ) except Exception as e: OkFrame.show( self._master, self._config, 'An error occurred while copying the file:\n\n{}'.format(e) ) def _delete_file(self): cur_item = self._tree.focus() cur_path = self._item_paths.get(cur_item, '') if cur_path != '': disp_path = cur_path[len(self._state.to_device.part().mount()):] try: if ConfirmFrame.show( self._master, self._config, 'Are you sure you\'d like to delete this file?\n{}'.format(disp_path), 'Yes', 'No' ): os.remove(cur_path) self._tree.delete(self._tree.focus()) except PermissionError: OkFrame.show( self._master, self._config, 'Error deleting file:\n\nInvalid permissions' ) except Exception as e: OkFrame.show( self._master, self._config, 'An error occurred while deleting the file:\n\n{}'.format(e) ) def _populate_tree(self, tree_root): self._item_paths = {} def insert_path(tree, path, parent_id): dirs = [e for e in scandir(path) if e.is_dir()] dirs.sort(key=lambda e: e.name) for d in dirs: dir_name = d.name dir_id = '{}-{}'.format(parent_id, dir_name) dir_path = os.path.join(path, dir_name) tree.insert(parent_id, 'end', dir_id, text=dir_name, tags=('dir')) try: insert_path(tree, dir_path, dir_id) except: pass files = [e for e in scandir(path) if e.is_file()] files.sort(key=lambda e: e.name) for idx, f in enumerate(files): file_name = f.name file_id = '{}-{}'.format(parent_id, file_name) file_stat = f.stat() file_size = sizeof_fmt(file_stat.st_size) file_path = os.path.join(path, file_name) self._item_paths[file_id] = file_path if idx % 2 == 0: file_bg = 'file_even' else: file_bg = 'file_odd' tree.insert( parent_id, 'end', file_id, text=file_name, tags=('file', file_bg), values=(file_size) ) insert_path(self._tree, tree_root, '') tree = self._tree tree.tag_configure('dir', font=self._config.item_font) tree.tag_configure('file', font=self._config.item_font) tree.tag_configure('file_odd', background='light grey')
class Booked: """Booked class: A Booked window. - Can view your see your booking history - Can remove your booking (only future booking) - View Movie detail - See your tickets information "window": it is a Tk() object (tkinter object) that is passed around so we do not need to create it every single time old_window: reference to the tk() object (Login window) username: User's username -_-""" def __init__(self, window, old_window, username): self.username = username self.old_window = old_window self.window = window self.window.title("Booked") # Customers Options self.home = Button(self.window, text="Home", font=("Arial", 30), bd=0, bg="#CBFBB5", command=self.goto_home) self.home.grid(row=0, column=0, padx=(15, 10)) self.booking = Button(self.window, text=" Booking ", font=("Arial", 30), bd=0, bg="#CA65F5", command=self.goto_booking) self.booking.grid(row=0, column=1, padx=(0, 10)) self.booked = Button(self.window, text=" Booked ", font=("Arial", 30), bd=0, bg="#1F8BF3") self.booked.grid(row=0, column=2, padx=(0, 10)) self.user = Button(self.window, text=" User ", font=("Comic Sans", 30), bd=0, bg="#BDC3C7", command=self.goto_user) self.user.grid(row=0, column=3, padx=(0, 10)) self.sign_out = Button(self.window, text=" Sign Out ", font=("Comic Sans", 30), bd=0, bg="#FF916E", command=self.goto_sign_out) self.sign_out.grid(row=0, column=4, padx=(0, 10)) self.heading = Label(self.window, text="Your movie Tickets", font=("Arial", 20)) self.heading.grid(row=1, column=0, columnspan=20, pady=(30, 15)) # all_info structure is : name, date, time, hall, tickets, num_tickets self.all_info, self.print_info = [None, None] # Table of booked tickets self.table = Treeview(self.window) self.table.grid(row=2, column=0, columnspan=30, padx=(10, 0)) # Scroll bar for the table self.scroll_y = Scrollbar(self.window, orient="vertical", command=self.table.yview) self.scroll_y.place(x=860, y=159) self.create_table() # Creates the table # Movie Info Button self.movie_info_btn = Button(self.window, text="Movie Info", font=("Arial", 18), command=self.movie_info, bg="#F69898") self.movie_info_btn.place(x=150, y=398) # Ticket Info Button self.ticket_info_btn = Button(self.window, text="Ticket Info", font=("Arial", 18), command=self.ticket_info, bg="#788EB2") self.ticket_info_btn.place(x=360, y=398) # Remove tickets self.remove_booking_btn = Button(self.window, text="Remove Booking", font=("Arial", 18), bg="#B28078", command=self.remove_booking) self.remove_booking_btn.place(x=550, y=398) # All the widget I created, I store it here. So i can easily destroy them later. self.widgets = [self.home, self.booked, self.booking, self.user, self.sign_out, self.heading, self.table, self.scroll_y, self.movie_info_btn, self.ticket_info_btn, self.remove_booking_btn] def goto_home(self): """Takes you to the Home window""" self.destroy_all() self.window.Home(window=self.window, old_window=self.old_window, username=self.username) def goto_booking(self): """Takes you to the booking window""" self.destroy_all() self.window.Booking(window=self.window, old_window=self.old_window, username=self.username) def goto_user(self): """Takes you to the user window""" self.destroy_all() self.window.User(window=self.window, old_window=self.old_window, username=self.username, customer=True) def goto_sign_out(self): """Signs out the user and takes the user back to the Login menu. It also logs the date and the time when the user signs out""" logging.basicConfig(level=logging.INFO, filename="logging.log") logging.info(f"Username: {self.username} Sign-out {datetime.datetime.now()}") self.window.destroy() self.old_window.deiconify() def destroy_all(self): """ destroy_all() Destroys all the widget (Clears the window, so I can use the same window for adding new widgets) """ [widget.destroy() for widget in self.widgets] def remove_booking(self): """ remove_booking() ---> remove future booking - If the it is an old booking, you can not remove it - If you don't choose any tickets, you will get a message saying "Please choose the ticket first" - If you remove the tickets, it updates the database. - Updates the available seats, the cinema seats layout and remove your booking from the database""" num = self.table.focus() id = self.table.item(num)["values"] if id: year, month, day = [int(num) for num in id[2].split("-")] hour, min = [int(time) for time in id[3].split(":")] booked_date = datetime.datetime(year=year, month=month, day=day, hour=hour, minute=min) now = datetime.datetime.now() if booked_date >= now: if messagebox.askyesno("Confirm", f"Are you sure that you want to delete this ticket?" f"\n{self.print_info[id[0]]}"): global cinemaDB_path cinemaDB_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", f"{id[4]}.db")) db = sqlite3.connect(cinemaDB_path) cursor = db.cursor() cursor.execute("""SELECT sp.cinema_layout, c.user_tickets, c.num_tickets, sp.available_seats, sp.seating_planID, c.ID FROM seating_plan sp, customer_tickets c, schedule s WHERE sp.scheduleID = c.scheduleID AND sp.scheduleID = s.scheduleID AND s.date=? AND s.time=? AND s.cinema_hall=? """, (id[2], id[3], self.all_info[id[0] - 1][3])) temp = cursor.fetchone() cinema_layout = temp[0] user_tickets = temp[1] new_available_seats = temp[3] + temp[2] seating_planID = temp[4] unique_customerID = temp[5] # Update the seating plan beacuse there are free seats now updated_layout = remove_seats(list_layout=cinema_layout, user_tickets=user_tickets) # Update the database cursor.execute("""UPDATE seating_plan SET available_seats=?, cinema_layout=? WHERE seating_planID=?""", (new_available_seats, updated_layout, seating_planID)) cursor.execute("""DELETE FROM customer_tickets WHERE ID=?""", (unique_customerID,)) db.commit() self.create_table(update=True) # Updates the table else: messagebox.showwarning("Invalid", "You can not delete this ticket") else: messagebox.showinfo("Invalid", "Please choose the ticket first.") def ticket_info(self): """ticket_info() --> show the message on your tickets Movie name, location, date, time, cinema hall, number of seats, adult tickets, child tickets, seat location, cost If you don't choose any tickets, you will get a message saying "Please choose the ticket first" """ num = self.table.focus() id = self.table.item(num)["values"] if id: messagebox.showinfo("Your ticket", self.print_info[id[0]]) else: messagebox.showinfo("Invalid", "Please choose the ticket first.") def movie_info(self): """ movie_into() --> take you the movie information page If you don't choose any tickets, you will get a message saying "Please choose the ticket first" """ num = self.table.focus() id = self.table.item(num)["values"] if id: self.window.withdraw() MovieInfo(movie_name=id[1], old_window=self.window, location=id[4]) else: messagebox.showinfo("Invalid", "Please choose the ticket first.") def create_table(self, update=False): """create_table(update) --> create the table with the user booked history if the argument update=False, then the table is created from scratch if the argument update=True, then if will only update the information on the table Using method get_booked_tickets() to get the user booked information """ # all_info structure: name, date, time, hall, tickets, num_tickets self.all_info, self.print_info = get_booked_tickets(username=self.username) # Create the table from scratch if not update: heading_name = ["Num", "Movie", "Date", "Time", "Location"] # Heading for my table self.table["show"] = "headings" self.table["columns"] = list(range(len(heading_name))) for i in range(len(heading_name)): self.table.heading(i, text=heading_name[i]) for i in range(len(self.all_info)): self.table.insert("", 'end', text="L1", values=(i + 1, self.all_info[i][0], self.all_info[i][1], self.all_info[i][2], self.all_info[i][9])) # I am adjusting the table structure self.table.column(0, anchor="center", width=60) self.table.column(1, anchor="center", width=250) self.table.column(2, anchor="center", width=150) self.table.column(3, anchor="center", width=120) self.table.column(4, anchor="center") else: # Clear the table first before adding to the table for i in self.table.get_children(): self.table.delete(i) # Fill in the table with new data for i in range(len(self.all_info)): self.table.insert("", 'end', text="L1", values=(i + 1, self.all_info[i][0], self.all_info[i][1], self.all_info[i][2], self.all_info[i][9]))
class FacultyDelWindow: def __init__(self, data=''): self.data = data print(self.data) self.win = Tk() self.canvas = Canvas(self.win, width=800, height=420, bg='white') self.canvas.pack(expand=YES, fill=BOTH) # show window in center of the screen width = self.win.winfo_screenwidth() height = self.win.winfo_screenheight() x = int(width / 2 - 800 / 2) y = int(height / 2 - 420 / 2) str1 = "800x420+" + str(x) + "+" + str(y) self.win.geometry(str1) # disable resize window self.win.resizable(False, False) # changing title of the window self.win.title( "| DELETING FACULTY DETAILS | LIBRARY MANAGEMENT SYSTEM |") def add_frame(self): self.frame = Frame(self.win, height=420, width=800) self.frame.place(x=0, y=0) x, y = 0, 0 self.label = Label(self.frame, text="DELETING FACULTY DETAILS", fg='black') self.label.config(font=("Poppins", 20, 'underline bold')) self.label.place(x=190, y=35) # use tree view to show details from the table self.tr = Treeview(self.frame, columns=('FACULTY_ID', 'FACULTY_NAME', 'GENDER', 'DEPARTMENT', 'CONTACT_NO'), selectmode="extended") # heading key + text self.tr.heading('#0', text='FACULTY_ID') self.tr.column('#0', minwidth=0, width=100, stretch=NO) self.tr.heading('#1', text='FACULTY_NAME') self.tr.column('#1', minwidth=0, width=100, stretch=NO) self.tr.heading('#2', text='GENDER') self.tr.column('#2', minwidth=0, width=100, stretch=NO) self.tr.heading('#3', text='DEPARTMENT') self.tr.column('#3', minwidth=0, width=100, stretch=NO) self.tr.heading('#4', text='CONTACT_NO') self.tr.column('#4', minwidth=0, width=100, stretch=NO) self.tr.heading('#5', text='DELETE') self.tr.column('#5', minwidth=0, width=100, stretch=NO) # self.tr.heading('#6', text='DELETE') # self.tr.column('#6', minwidth=0, width=100, stretch=NO) j = 0 for i in Database.database.Faculties(): self.tr.insert('', index=j, text=i[0], values=(i[1], i[2], i[3], i[4], 'DELETE')) j += 1 # create action on deletion self.tr.bind('<Double-Button-1>', self.actions) self.tr.place(x=100, y=y + 100) self.win.mainloop() def actions(self, e): # get the value of deleted row tt = self.tr.focus() # get the column id col = self.tr.identify_column(e.x) print(col) print(self.tr.item(tt)) data = (self.tr.item(tt).get('text'), ) if col == '#5': res = messagebox.askyesno("Message", "Do you want to delete..!") if res: d = Database.database.DeleteFaculty(data) if d: messagebox.showinfo( "Message", "Faculty Details deleted successfully..!") self.win.destroy() x = Thirdpage else: self.win.destroy() x = Student.DeleteFaculty.FacultyDelWindow() x.add_frame()
class Configurator(tk.Tk): """ The main Tk window representing the main app. Attributes ---------- treeview : :py:class:`~tkinter.Treeview` The treeview widget. treeview_popup_target_id : `int` The pop target id relating to the id of the selected element. treeview_popup : :py:class:`~tkinter.Widget` The treeview popup widget. cfg_file_name : `str` The file name of the current configuration. element_dict : `dict` The dictionary of elements. Keys are the element ids. root_element : :py:class:`~enrich2.base.storemanager.StoreManager` An instance inheriting from storemanager that acts as a root object. force_recalculate :py:class:`tkinter.BooleanVar` The tkinter boolean variable for this option. component_outliers :py:class:`tkinter.BooleanVar` The tkinter boolean variable for this option. tsv_requested : :py:class:`tkinter.BooleanVar` The tkinter boolean variable for this option. treeview_buttons : `list` The ``new``, ``edit`` and ``delete`` buttons. go_button : :py:class`~tkinter.ttk.Button` The button that begins the analysis scorer_widget : :py:class:`~enrich2.gui.options_frame.ScorerScriptsDropDown` The ScorerScriptsDropDown instance associated with this app. scorer : :py:class:`~enrich2.plugins.scoring.BaseScorerPlugin` The scorer class loaded from a plugin scorer_attrs : `dict` The scoring attributes for the plugin. scorer_path : `str` The path to the currently selected scoring plugin. analysis_thread : :py:class:`~threading.Thread` The thread object that runs the computation method to prevent GUI blocking. Methods ------- create_main_frame create_menubar create_treeview_context_menu create_new_element menu_open menu_save menu_saveas menu_selectall refresh_treeview treeview_context_menu set_treeview_properties populate_tree go_button_press new_button_press edit_button_press delete_button_press delete_element apply_seqlib_fastq get_element get_focused_element get_selected_elements get_selected_scorer_class get_selected_scorer_attrs get_selected_scorer_path run_analysis set_gui_state configure_analysis refresh_plugins show_plugin_source_window See Also -------- :py:class:`~tkinter.Tk` """ def __init__(self): tk.Tk.__init__(self) self.title("Enrich 2") # Main app variables self.cfg_file_name = tk.StringVar() self.element_dict = dict() self.root_element = None self.analysis_thread = None self.plugin_source_window = None self.queue = queue.Queue() # Treeview variables self.treeview = None self.treeview_popup_target_id = None self.treeview_popup = None # analysis options self.force_recalculate = tk.BooleanVar() self.component_outliers = tk.BooleanVar() self.tsv_requested = tk.BooleanVar() # allow resizing self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) # create UI elements self.treeview_buttons = [] self.go_button = None self.scorer_widget = None self.scorer = None self.scorer_attrs = None self.scorer_path = None self.create_main_frame() self.create_menubar() self.create_treeview_context_menu() self.after(10, self.poll_logging_queue) self.plugin_source_window = SourceWindow(master=self) self.plugin_source_window.hide() self.refresh_plugins() # ---------------------------------------------------------------------- # # Creation Methods # ---------------------------------------------------------------------- # def create_treeview_context_menu(self): """ This creates the tree-like view rendering the experiment heirachy. """ self.treeview_popup = tk.Menu(self, tearoff=0) self.treeview_popup.add_command(label="Apply FASTQ...", command=self.apply_seqlib_fastq) def create_main_frame(self): """ Large function creating all the basic elements of the main app frame. Creates the treeview and associated buttons, the scoring plugin frame and the go button. """ # Frame for the Treeview and New/Edit/Delete buttons main = Frame(self, padding=(3, 3, 12, 12)) main.rowconfigure(0, weight=1) main.columnconfigure(0, weight=1) main.columnconfigure(1, weight=0) main.grid(row=0, column=0, sticky="nsew") # ------------------------------------------------------- # # Frame for the Treeview and its scrollbars tree_frame = Frame(main, padding=(3, 3, 12, 12)) tree_frame.rowconfigure(0, weight=1) tree_frame.rowconfigure(1, weight=0) tree_frame.columnconfigure(0, weight=1) tree_frame.columnconfigure(1, weight=0) tree_frame.grid(row=0, column=0, sticky="nsew") # ------------------------------------------------------- # # Treeview with column headings self.treeview = Treeview(tree_frame) self.treeview["columns"] = ("class", "barcodes", "variants") self.treeview.column("class", width=120) self.treeview.heading("class", text="Type") self.treeview.column("barcodes", width=25, stretch=tk.NO, anchor=tk.CENTER) self.treeview.heading("barcodes", text="BC") self.treeview.column("variants", width=25, stretch=tk.NO, anchor=tk.CENTER) self.treeview.heading("variants", text="V") self.treeview.grid(row=0, column=0, sticky="nsew") # Treeview context menu bindings self.treeview.bind("<Button-2>", self.treeview_context_menu) # Treeview scrollbars tree_ysb = tk.Scrollbar(tree_frame, orient="vertical", command=self.treeview.yview) tree_xsb = tk.Scrollbar(tree_frame, orient="horizontal", command=self.treeview.xview) tree_ysb.grid(row=0, column=1, sticky="nsw") tree_xsb.grid(row=1, column=0, sticky="ewn") self.treeview.config(yscroll=tree_ysb.set, xscroll=tree_xsb.set) # ------------------------------------------------------- # # Frame for New/Edit/Delete buttons button_frame = Frame(main, padding=(3, 3, 12, 12)) button_frame.grid(row=1, column=0) new_button = Button(button_frame, text="New...", command=self.new_button_press) new_button.grid(row=0, column=0) edit_button = Button(button_frame, text="Edit...", command=self.edit_button_press) edit_button.grid(row=0, column=1) delete_button = Button(button_frame, text="Delete", command=self.delete_button_press) delete_button.grid(row=0, column=2) self.treeview_buttons = [new_button, delete_button, edit_button] # ------------------------------------------------------- # # Frame for Plugin and Analysis Options right_frame = Frame(main, padding=(3, 3, 12, 12)) right_frame.rowconfigure(0, weight=1) right_frame.rowconfigure(1, weight=0) right_frame.columnconfigure(0, weight=1) right_frame.columnconfigure(1, weight=0) right_frame.grid(row=0, column=1, sticky="new") # ------------------------------------------------------- # # LabelFrame for plugin and options scoring_plugin = ScorerScriptsDropDown(right_frame, text="Scoring Options", padding=(3, 3, 12, 12)) scoring_plugin.grid(row=0, column=0, sticky="new") self.scorer_widget = scoring_plugin # ------------------------------------------------------- # # LabelFrame for Analysis Options row = 0 options_frame = LabelFrame(right_frame, text="Analysis Options", padding=(3, 3, 12, 12)) options_frame.grid(row=1, column=0, sticky="new", pady=4) # force recalculate force_recalculate = Checkbutton(options_frame, text="Force Recalculation", variable=self.force_recalculate) force_recalculate.grid(column=0, row=row, sticky="w") row += 1 # component outliers component_outliers = Checkbutton( options_frame, text="Component Outlier Statistics", variable=self.component_outliers, ) component_outliers.grid(column=0, row=row, sticky="w") row += 1 # write tsv tsv_requested = Checkbutton(options_frame, text="Write TSV Files", variable=self.tsv_requested) tsv_requested.grid(column=0, row=row, sticky="w") tsv_requested.invoke() row += 1 # ------------------------------------------------------- # # Run Analysis button frame go_button_frame = Frame(main, padding=(3, 3, 12, 12)) go_button_frame.grid(row=1, column=1) go_button = Button(go_button_frame, text="Run Analysis", command=self.go_button_press) go_button.grid(column=0, row=0) self.go_button = go_button def create_new_element(self): """ Create and return a new element based on the current selection. This element is not added to the treeview. """ element = None parent_element = self.get_focused_element() if isinstance(parent_element, Experiment): element = Condition() element.parent = parent_element elif isinstance(parent_element, Condition): element = Selection() element.parent = parent_element elif isinstance(parent_element, Selection): element = CreateSeqLibDialog(self).element_type() element.parent = parent_element elif isinstance(parent_element, SeqLib): # special case: creates a copy of the selected SeqLib as a sibling element = type(parent_element)() element.configure(parent_element.serialize()) element.parent = parent_element.parent # clear out the seqlib-specific values element.name = None element.timepoint = None element.counts_file = None element.reads = None else: raise ValueError("Unrecognized parent object " "type '{}'".format(type(parent_element))) return element def create_menubar(self): """ Creates the menubar for the main app, with associated drop down menus. """ # make platform-specific keybinds if platform.system() == "Darwin": accel_string = "Command+" accel_bind = "Command-" else: accel_string = "Ctrl+" accel_bind = "Control-" # create the menubar menubar = tk.Menu(self) # file menu filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command( label="Open...", accelerator="{}O".format(accel_string), command=self.menu_open, ) filemenu.add_command(label="Save", accelerator="{}S".format(accel_string), command=self.menu_save) filemenu.add_command( label="Save As...", accelerator="{}Shift+S".format(accel_string), command=self.menu_saveas, ) menubar.add_cascade(label="File", menu=filemenu) # edit menu filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command( label="Select All", accelerator="{}A".format(accel_string), command=self.menu_selectall, ) menubar.add_cascade(label="Edit", menu=filemenu) # tools menu filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command( label="Show Log", accelerator="{}L".format(accel_string), command=show_log_window, ) filemenu.add_command( label="Plugin Sources", accelerator="{}P".format(accel_string), command=self.show_plugin_source_window, ) filemenu.add_command( label="Refresh Plugins", accelerator="{}R".format(accel_string), command=self.refresh_plugins, ) menubar.add_cascade(label="Tools", menu=filemenu) # add the menubar self.config(menu=menubar) # add file menu keybinds self.bind("<{}o>".format(accel_bind), lambda event: self.menu_open()) self.bind("<{}s>".format(accel_bind), lambda event: self.menu_save()) self.bind("<{}Shift-s>".format(accel_bind), lambda event: self.menu_saveas()) # add edit menu keybinds self.bind("<{}a>".format(accel_bind), lambda event: self.menu_selectall()) # add show log menu keybinds # add edit menu keybinds self.bind("<{}l>".format(accel_bind), lambda event: show_log_window()) self.bind("<{}p>".format(accel_bind), lambda event: self.show_plugin_source_window()) self.bind("<{}r>".format(accel_bind), lambda event: self.refresh_plugins()) # ---------------------------------------------------------------------- # # Treeview Methods # ---------------------------------------------------------------------- # def treeview_context_menu(self, click): """ Sets the currently selected treeview object id in the variable ``treeview_popup_target_id``. Parameters ---------- click : tkinter click event """ target = self.treeview.identify_row(click.y) if target != "": self.treeview_popup_target_id = target self.treeview_popup.post(click.x_root, click.y_root) self.treeview_popup_target_id = None def apply_seqlib_fastq(self): """ Applies settings to the seqlib object by running the configuration method. """ SeqLibApplyDialog(self, self, self.treeview_popup_target_id) def new_button_press(self): """ Spawns a dialog box depending on the currently selected treeview item to create a new element. """ if self.treeview.focus() == "" and self.root_element is not None: tkinter.messagebox.showwarning(None, "No parent element selected.") else: if self.treeview.focus() == "" and self.root_element is None: element = CreateRootDialog(self).element if isinstance(element, SeqLib): EditDialog(self, self, element) self.root_element = element else: element = self.create_new_element() EditDialog(self, self, element) # refresh the treeview and re-assign treeview id's self.refresh_treeview() # select the newly added element if it was successfully added if element.treeview_id in list(self.element_dict.keys()): self.treeview.focus(element.treeview_id) self.treeview.selection_set(element.treeview_id) else: if element.parent is not None: self.treeview.focus(element.parent.treeview_id) self.treeview.selection_set(element.parent.treeview_id) del element def edit_button_press(self): """ Spawns a dialog box depending on the currently selected treeview item to edit the selected element. """ if self.treeview.focus() == "": tkinter.messagebox.showwarning(None, "No element selected.") else: EditDialog(self, self, self.get_focused_element()) def delete_button_press(self): """ Deletes the selected treeview element and it's children. """ if self.treeview.focus() == "": tkinter.messagebox.showwarning(None, "No element selected.") else: DeleteDialog(self, self) def delete_element(self, tree_id): """ Delete element with Treeview id *tree_id* from the tree, from the element dictionary, and from the associated data structure. Recursively deletes all children of *tree_id*. The tree should be refreshed using :py:meth:`refresh_tree` after each deletion. This is the responsibility of the caller. Parameters ---------- tree_id : `int` The id of the currently selected treeview element. """ if tree_id in self.element_dict: # recursively delete children if self.element_dict[tree_id].children is not None: for child in self.element_dict[tree_id].children: self.delete_element(child.treeview_id) # check if deleting the root element if self.root_element.treeview_id == tree_id: # clear the root element print("None {}".format(tree_id)) self.root_element = None else: try: # remove the element from its parent's list of children self.element_dict[tree_id].parent.remove_child_id(tree_id) except AttributeError: raise AttributeError( "Non-root element lacks proper parent") # delete the element from the dictionary del self.element_dict[tree_id] def refresh_treeview(self): """ Clears the Treeview and repopulates it with the current contents of the tree. """ # clear the entries in the Treeview for x in self.treeview.get_children(): self.treeview.delete(x) # clear the id-element dictionary # elements may be given new id's after repopulation self.element_dict.clear() # repopulate if self.root_element is not None: self.populate_tree(self.root_element) def set_treeview_properties(self, element): """ Set the information text for the Treeview *element*. Parameters ---------- element : :py:class:`~enrich2.base.storemanager.StoreManager` The storemanager object to configure. """ # set class property self.treeview.set(element.treeview_id, "class", element.treeview_class_name) # add the check marks for barcodes/variants if "variants" in element.labels: self.treeview.set(element.treeview_id, "variants", u"\u2713") else: self.treeview.set(element.treeview_id, "variants", "") if "barcodes" in element.labels: self.treeview.set(element.treeview_id, "barcodes", u"\u2713") else: self.treeview.set(element.treeview_id, "barcodes", "") self.treeview.set(element.treeview_id, "class", element.treeview_class_name) def populate_tree(self, element, parent_id=""): """ Recursively populate the Treeview. Also populates the *id_cfgstrings*. Parameters ---------- element : :py:class:`~enrich2.base.storemanager.StoreManager` The storemanager object to configure. parent_id : `int` ``treeview_id`` of element's parent. """ # insert into the Treeview element.treeview_id = self.treeview.insert(parent_id, "end", text=element.name, open=True) # add id-element pair to dictionary self.element_dict[element.treeview_id] = element # set information fields self.set_treeview_properties(element) # populate for children if element.children is not None: for child in element.children: self.populate_tree(child, parent_id=element.treeview_id) # ---------------------------------------------------------------------- # # Getter Methods # ---------------------------------------------------------------------- # def get_selected_scorer_class(self): """ Returns the currently selected scoring class object. """ return self.scorer def get_selected_scorer_attrs(self): """ Returns the currently selected scoring class attribute `dict`. """ return self.scorer_attrs def get_selected_scorer_path(self): """ Returns the currently selected scoring path. """ return self.scorer_path def get_element(self, treeview_id): """ Returns the element with *treeview_id*. Parameters ---------- treeview_id : `int` ``treeview_id`` attribute of element to get. Returns ------- :py:class:`~enrich2.base.storemanager.StoreManager` The instance with matching ``treeview_id`` """ return self.element_dict[treeview_id] def get_focused_element(self): """ Gets the focused element in the treeview. Returns ------- :py:class:`~enrich2.base.storemanager.StoreManager` Returns the element that is currently being focused in the Treeview. ``None`` if nothing is focused. """ if self.treeview.focus() != "": return self.get_element(self.treeview.focus()) else: return None def get_selected_elements(self): """ Returns a list of currently selected elements in the treeview. Returns ------- `list` Returns a list of elements that are currently selected in the Treeview. If no elements are selected, it returns an empty list. """ return [self.get_element(x) for x in self.treeview.selection()] # ---------------------------------------------------------------------- # # Menubar Methods # ---------------------------------------------------------------------- # def menu_open(self): """ Spawns an `askopenfilename` dialog to open a configuration file. """ message_title = "Open Configuration" fname = tkinter.filedialog.askopenfilename() if len(fname) > 0: # file was selected try: with open(fname, "rU") as handle: cfg = json.load(handle) except ValueError: tkinter.messagebox.showerror(message_title, "Failed to parse config file.") except IOError: tkinter.messagebox.showerror(message_title, "Could not read config file.") else: if is_experiment(cfg): obj = Experiment() elif is_selection(cfg): obj = Selection() elif is_seqlib(cfg): sltype = seqlib_type(cfg) obj = globals()[sltype]() else: tkinter.messagebox.showerror( message_title, "Unrecognized config format.") return obj.output_dir_override = False try: if isinstance(obj, Experiment) or isinstance( obj, Selection): obj.configure(cfg, init_from_gui=True) else: obj.configure(cfg) # Try load the scorer into the GUI scorer_path = cfg.get(SCORER, {}).get(SCORER_PATH, "") scorer_attrs = cfg.get(SCORER, {}).get(SCORER_OPTIONS, {}) if scorer_path: self.scorer_widget.load_from_cfg_file( scorer_path, scorer_attrs) else: log_message( logging_callback=logging.warning, msg="No plugin could be loaded from configuration.", extra={"oname": self.__class__.__name__}, ) except Exception as e: tkinter.messagebox.showerror( message_title, "Failed to load config file:\n\n{}".format(e)) else: self.root_element = obj self.cfg_file_name.set(fname) self.refresh_treeview() def menu_save(self): """ Asks the user where to save the current configuration. """ if len(self.cfg_file_name.get()) == 0: self.menu_saveas() elif self.root_element is None: tkinter.messagebox.showwarning("Save Configuration", "Cannot save empty configuration.") else: save = askyesno("Save Configuration", "Overwrite existing configuration?") if not save: return try: with open(self.cfg_file_name.get(), "w") as handle: cfg = self.root_element.serialize() # Get the currently selected scorer if not isinstance(self.root_element, SeqLib) and not isinstance( self.root_element, Condition): ( _, attrs, scorer_path, ) = self.scorer_widget.get_scorer_class_attrs_path() cfg[SCORER] = { SCORER_PATH: scorer_path, SCORER_OPTIONS: attrs } write_json(cfg, handle) except IOError: tkinter.messagebox.showerror("Save Configuration", "Failed to save config file.") else: tkinter.messagebox.showinfo( "Save Configuration", "Saved file at location:\n\n{}".format( self.cfg_file_name.get()), ) def menu_saveas(self): """ Asks the user where to save the current configuration. """ if self.root_element is None: tkinter.messagebox.showwarning("Save Configuration", "Cannot save empty configuration.") else: fname = tkinter.filedialog.asksaveasfilename() if len(fname) > 0: # file was selected try: with open(fname, "w") as handle: cfg = self.root_element.serialize() # Get the currently selected scorer if not isinstance(self.root_element, SeqLib) and not isinstance( self.root_element, Condition): ( _, attrs, scorer_path, ) = self.scorer_widget.get_scorer_class_attrs_path( ) cfg[SCORER] = { SCORER_PATH: scorer_path, SCORER_OPTIONS: attrs, } write_json(cfg, handle) except IOError: tkinter.messagebox.showerror( "Save Configuration", "Failed to save config file.") else: self.cfg_file_name.set(fname) tkinter.messagebox.showinfo( "Save Configuration", "Saved file at location:\n\n{}".format( self.cfg_file_name.get()), ) def menu_selectall(self): """ Add all elements in the Treeview to the selection. """ for k in self.element_dict.keys(): self.treeview.selection_add(k) def show_plugin_source_window(self): """ Show the pop-up window to modify plugin sources """ if not self.plugin_source_window: self.plugin_source_window = SourceWindow(master=self) else: self.plugin_source_window.toggle_show() # ---------------------------------------------------------------------- # # Run Analysis Methods # ---------------------------------------------------------------------- # def go_button_press(self): """ Starts the analysis if all elements have been properly configured. This will run the analysis in a new thread and block out GUI editing to prevent the analysis breaking. """ ( self.scorer, self.scorer_attrs, self.scorer_path, ) = self.scorer_widget.get_scorer_class_attrs_path() if self.scorer is None or self.scorer_attrs is None: tkinter.messagebox.showwarning("Incomplete Configuration", "No scoring plugin selected.") elif self.root_element is None: tkinter.messagebox.showwarning( "Incomplete Configuration", "No experimental design specified.") else: plugin, *_ = self.scorer_widget.get_selected_plugin() if plugin.md5_has_changed(): proceed = askokcancel( "Selected plugin has been modified.", "The selected plugin has been modified on disk. Do you " "want to proceed with the current version? To see changes " "click 'Cancel' and refresh plugins before proceeding.", ) if not proceed: return if askyesno( "Save Configuration?", "Would you like to save the confiugration " "file before proceeding?", ): self.menu_save() run = askyesno( "Begin Analysis?", "Click Yes when you are ready to start.\n\nThis could " "take some time so grab a cup of tea, or a beer if that's " "your thing, and enjoy the show.", ) if run: self.configure_analysis() self.set_gui_state(tk.DISABLED) thread = threading.Thread(target=self.run_analysis) thread.setDaemon(True) self.analysis_thread = thread self.analysis_thread.start() self.after(100, self.poll_analysis_thread) def poll_logging_queue(self): """ Polls the logging queue for messages to log. """ try: log = get_logging_queue(init=True).get(0) log[CALLBACK](log[MESSAGE], **log[KWARGS]) self.after(10, self.poll_logging_queue) except queue.Empty: self.after(10, self.poll_logging_queue) def poll_analysis_thread(self): """ Polls the thread to check it's state. When it is finished, all stores are closed. """ try: analysis_result = self.queue.get(0) self.handle_analysis_result(analysis_result) except queue.Empty: self.after(100, self.poll_analysis_thread) def handle_analysis_result(self, success): """ Shows the appropriate messagebox and logs exceptions upon analysis completing. Parameters ---------- success : `bool` Exception object if an error occured during analysis, otherwise None to indicate successful computation. """ log_message( logging_callback=logging.info, msg="Closing stores...", extra={"oname": self.root_element.name}, ) self.root_element.store_close(children=True) log_message( logging_callback=logging.info, msg="Stores closed.", extra={"oname": self.root_element.name}, ) if success: showinfo("Analysis completed.", "Analysis has completed successfully!") log_message( logging_callback=logging.info, msg="Completed successfully!", extra={"oname": self.root_element.name}, ) else: showwarning( "Error during analysis.", "An error occurred during the analysis. See log for details", ) log_message( logging_callback=logging.info, msg="Completed, but with errors!", extra={"oname": self.root_element.name}, ) self.set_gui_state(tk.NORMAL) def run_analysis(self): """ Runs the storemanager compute method. """ try: self.root_element.validate() self.root_element.store_open(children=True) self.root_element.calculate() if self.root_element.tsv_requested: self.root_element.write_tsv() self.queue.put(True, block=False) except Exception as exception: log_message( logging_callback=logging.exception, msg=exception, extra={"oname": self.root_element.name}, ) self.queue.put(False, block=False) finally: return def configure_analysis(self): """ Configures the attributes of the root_element by querying the GUI options. """ try: self.root_element.force_recalculate = self.force_recalculate.get() self.root_element.component_outliers = self.component_outliers.get( ) self.root_element.tsv_requested = self.tsv_requested.get() scorer_class = self.get_selected_scorer_class() scorer_class_attrs = self.get_selected_scorer_attrs() scorer_path = self.get_selected_scorer_path() self.root_element.scorer_class = scorer_class self.root_element.scorer_class_attrs = scorer_class_attrs self.root_element.scorer_path = scorer_path except Exception as e: log_message( logging_callback=logging.info, msg="An error occurred when trying to configure the " "root element.", extra={"oname": self.root_element.name}, ) log_message( logging_callback=logging.exception, msg=e, extra={"oname": self.root_element.name}, ) # ---------------------------------------------------------------------- # # GUI Modifications # ---------------------------------------------------------------------- # def set_gui_state(self, state): """ Sets the state of the `go_button`, `treeview` and `treeview_buttons`. Parameters ---------- state : `str` State to set, usually ``'normal'`` or ``'disabled'`` """ for btn in self.treeview_buttons: btn.config(state=state) self.go_button.config(state=state) if state == "normal": self.treeview.bind("<Button-2>", self.treeview_context_menu) else: self.treeview.bind("<Button-2>", lambda event: event) def refresh_plugins(self): """ Refresh the plugins by re-checking the sources file. """ if self.plugin_source_window: sources = self.plugin_source_window.sources self.scorer_widget.refresh_sources(sources)
class GUIExample(master.Subscriber): def __init__(self): #jumbonet stuff self.net = master.Master() self.net.mainloop() self.output = {} # uuid -> list of lines of output self.processes = {} # uuid/iid -> remote object #the fugly tkinter stuff self.tk = Tk() self.input = StringVar() self.selection = (None, False, False ) #process/remote, is_process, is_remote self.tv = None # treeview self.dsp_global = None self.dsp_process = None def _setup(self): tk = self.tk tk.wm_title("Jumbonet GUI Example") tk.protocol("WM_DELETE_WINDOW", self.shutdown) height = 250 # center: treeview self.tv = Treeview(tk) tv = self.tv tv.config(height=height) # treeview configuration tv["columns"] = ("process", "status") tv.column("process", width=130) tv.column("status", width=70) tv.heading("process", text="Process UUID") tv.heading("status", text="Status") tv.bind("<ButtonRelease-1>", self.row_selected) # right: log windows r_frame = Frame(tk, height=height) scroll = Scrollbar(r_frame) #the global log (top) self.dsp_global = TextDisplay(r_frame, width=70, height=20) self.dsp_global.append("Global information") #the process log (bottom) self.dsp_process = TextDisplay(r_frame, width=70, height=25) self.dsp_process.append("This shows output of the selected process") #left: entry and buttons self.input.set("") l_frame = Frame(tk, width=200, height=height) l = Label(l_frame, text="Start process here") e = Entry(l_frame, textvariable=self.input) buttons = Frame(l_frame) # buttons button_add = Button(buttons, text="Start", command=self.start_process) button_kill = Button(buttons, text="Kill", command=self.kill_process) # packing all of it # frame on left l.pack(side=TOP, fill=X) e.pack(side=TOP, fill=X) button_add.pack(side=LEFT) button_kill.pack(side=LEFT) buttons.pack(side=TOP, fill=X) # applog frame on right scroll.pack(side=RIGHT, fill=Y) self.dsp_global.pack(side=TOP, fill=X) self.dsp_process.pack(side=TOP, fill=X) # top-level pack l_frame.pack(side=LEFT, fill=Y, expand=False) tv.pack(side=LEFT, fill=Y, expand=False) r_frame.pack(side=LEFT, fill=Y, expand=False) def shutdown(self): self.net.shutdown() sys.exit(0) def row_selected(self, a): iid = self.tv.focus() log.debug("Selected: {}".format(iid)) assert (iid is not None) # is it a remote? r = self.net.remotes.get(iid) if r is not None: self.selection = (r, False, True) return # is it a process? #the process we're already showing output from? if self.selection[1] and iid == self.selection[0].uuid: #nothing to do then return # is it another process? p = self.processes[iid] if p is not None: # clear the log and display whats happening on the selected process self.dsp_process.clear() lines = self.output.get(iid) self.dsp_process.append(lines) self.selection = (p, True, False) else: self.selection = (None, False, False) def start_process(self): log.debug("Selected: {}".format(self.selection)) if not self.selection[2]: return cmd = self.input.get() if cmd == "type shell command here ": self.dsp_global.append("\nPlease type a valid shell command") return cmdargs = cmd.split(" ") r = self.selection[0] p = r.popen(cmdargs, self, listen_output=True, listen_error=True, listen_status=True) self.output[p.uuid] = list() self.processes[p.uuid] = p self.tv.insert(parent=self.selection[0].name, index="end", iid=p.uuid, text=cmd, values=(p.uuid, "Running")) self.dsp_global.append("\nStart {} as {} to {}".format( cmd, p.uuid, self.selection)) def kill_process(self): if not self.selection[1]: return p = self.selection[0] if not p.alive: self.dsp_global.append("\nCannot kill {} has alread exited".format( p.uuid)) else: self.dsp_global.append("\nKilling {}".format(self.selection)) p.kill() def _update_process_display(self, remotename, uuid, args, lines): old_output = self.output.get(uuid) old_output.extend(lines) if not self.selection[1]: return # are we showing the same process already? then add them to the log if uuid == self.selection[0].uuid: self.dsp_process.append(lines) self.dsp_process.see(END) def receive_out(self, remotename, uuid, args, lines): self._update_process_display(remotename, uuid, args, lines) def receive_err(self, remotename, uuid, args, lines): self._update_process_display(remotename, uuid, args, lines) def receive_status(self, remotename, uuid, args, exitcode): self.dsp_global.append("\nExit {} aka {} with code".format( args, uuid, exitcode)) self.tv.item(uuid, values=(uuid, "Exited ".format(exitcode))) #### these could also be used to get a nicer output for debugging complex testcases def add_host(self, remote): self.tv.insert("", END, text=remote.name, iid=remote.name, values=[], open=True) def add_process(self, remote, process): self.processes[process.uuid] = remote self.tv.insert(remote.name, END, iid=process.uuid, text=" ".join(process.args), values=(process.uuid, "Running"))
class showIncome: def __init__(self): self.win=Tk() self.canvas = Canvas(self.win, width=800, height=450, bg="white") self.canvas.pack(expand=YES, fill=BOTH) # bringing the screen in the centre width = self.win.winfo_screenwidth() height = self.win.winfo_screenheight() x = int(width / 2 - 800 / 2) y = int(height / 2 - 450 / 2) strl = "800x450+" + str(x) + "+" + str(y) self.win.geometry(strl) # disable resize of the window self.win.resizable(width=False, height=False) # change the title of the window self.win.title("WELCOME | Show income | ADMINISTRATOR") def add_frame(self): self.frame=Frame(self.win, width=600, height=350) self.frame.place(x=100, y=20) x, y= 70,20 # using treeview to show the table # mention number of columns self.tr=Treeview(self.frame, columns=('A','B','C','D'), selectmode="extended") # heading key+text self.tr.heading('#0', text='Sr no') self.tr.column('#0', minwidth=0, width=100, stretch=NO) self.tr.heading('#1', text='Source') self.tr.column('#1', minwidth=0, width=100, stretch=NO) self.tr.heading('#2', text='Income') self.tr.column('#2', minwidth=0, width=100, stretch=NO) self.tr.heading('#3', text='Update') self.tr.column('#3', minwidth=0, width=100, stretch=NO) self.tr.heading('#4', text='Delete') self.tr.column('#4', minwidth=0, width=100, stretch=NO) j=0 for i in db.db.show_income(): self.tr.insert('', index=j, text=i[0], values=(i[1], i[2], 'Update', 'Delete')) j+=1 # create an action on selected row self.tr.bind('<Double-Button-1>', self.actions) self.tr.place(x=50, y=y+50) self.win.mainloop() def actions(self,e): # get the value of selected row tt=self.tr.focus() # get the column id col=self.tr.identify_column(e.x) print(col) print(self.tr.item(tt)) tup=( self.tr.item(tt).get('text'), ) if col=='#4': res=messagebox.askyesno("Message","Do you want to delete?") if res: rs=db.db.delete_income(tup) if rs: messagebox.showinfo("Message","Message deleted") self.win.destroy() z=showIncome() z.add_frame() else: self.win.destroy() z=showIncome() z.add_frame() elif col=='#3': res=income.addIncome.IncomeWindow(self.tr.item(tt)) self.win.destroy() res.add_frame()