123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- import tkinter as tk
- from tkinter import ttk
- from tkinter import messagebox as msg
- import tkinter.font as font
- import abc
- import conf
- from tool.type_ import *
- from sql.db import DB
- from sql.user import creat_new_user, del_user, find_user_by_name
- from sql.garbage import creat_new_garbage, del_garbage_not_use, del_garbage_not_use_many
- from equipment.scan_user import write_uid_qr, write_all_uid_qr
- from equipment.scan_garbage import write_gid_qr
- from core.user import User
- from core.garbage import GarbageBag
- from tk_event import TkEventBase, TkEventMain, TkThreading
- class AdminStationException(Exception):
- ...
- class CreatGarbageError(AdminStationException):
- ...
- class CreatUserError(AdminStationException):
- ...
- class AdminEventBase(TkEventBase):
- def __init__(self, station, db: DB, title: str = 'unknown'):
- self.station: AdminStationBase = station
- self._db: DB = db
- self._title = title
- def get_title(self) -> str:
- return self._title
- def is_end(self) -> bool:
- raise AdminStationException
- def done_after_event(self):
- raise AdminStationException
- class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
- def __init__(self, db: DB):
- self._admin: Optional[User] = None
- self._db = db
- super(AdminStationBase, self).__init__()
- def creat_garbage(self, path: str, num: int = 1) -> List[tuple[str, Optional[GarbageBag]]]:
- re = []
- for _ in range(num):
- gar = creat_new_garbage(self._db)
- if gar is None:
- raise CreatGarbageError
- res = write_gid_qr(gar.get_gid(), path, self._db)
- re.append(res)
- return re
- def creat_user(self, name: uname_t, passwd: passwd_t, phone: str, manager: bool) -> Optional[User]:
- user = creat_new_user(name, passwd, phone, manager, self._db)
- if user is None:
- raise CreatUserError
- return user
- def creat_user_from_list(self, user_list: List[Tuple[uname_t, passwd_t, str]], manager: bool) -> List[User]:
- re = []
- for i in user_list:
- user = creat_new_user(i[0], i[1], i[2], manager, self._db)
- if user is None:
- raise CreatUserError
- re.append(user)
- return re
- def get_gid_qrcode(self, gid: gid_t, path: str) -> Tuple[str, Optional[GarbageBag]]:
- return write_gid_qr(gid, path, self._db)
- def get_all_gid_qrcode(self, path: str, where: str = "") -> List[str]:
- return write_all_uid_qr(path, self._db, where=where)
- def get_uid_qrcode(self, uid: uid_t, path: str) -> Tuple[str, Optional[User]]:
- return write_uid_qr(uid, path, self._db)
- def get_all_uid_qrcode(self, path: str, where: str = "") -> List[str]:
- return write_all_uid_qr(path, self._db, where=where)
- def del_garbage(self, gid: gid_t) -> bool:
- return del_garbage_not_use(gid, self._db)
- def del_garbage_many(self, from_: gid_t, to_: gid_t) -> int:
- return del_garbage_not_use_many(from_, to_, self._db)
- def del_user(self, uid: uid_t) -> bool:
- return del_user(uid, self._db)
- @abc.abstractmethod
- def login_call(self):
- ...
- def login(self, user: User) -> bool:
- if user is not None and user.is_manager():
- self._admin = user
- return True
- else:
- return False
- @abc.abstractmethod
- def show_loading(self, title: str):
- ...
- @abc.abstractmethod
- def stop_loading(self):
- ...
- @abc.abstractmethod
- def set_after_run(self, ms, func, *args):
- ...
- class AdminStation(AdminStationBase):
- def set_after_run(self, ms, func, *args): # super.__init__可能会调用
- self.init_after_run_list.append((ms, func, args))
- def __conf_set_after_run(self):
- for ms, func, args in self.init_after_run_list:
- self._window.after(ms, func, *args)
- def set_after_run_now(self, ms, func, *args):
- self._window.after(ms, func, *args)
- def __init__(self, db: DB, refresh_delay: int = conf.tk_refresh_delay):
- self.init_after_run_list: List[Tuple[int, Callable, Tuple]] = []
- super().__init__(db)
- self.refresh_delay = refresh_delay
- self._window = tk.Tk()
- self.login_window = None
- self._sys_height = self._window.winfo_screenheight()
- self._sys_width = self._window.winfo_screenwidth()
- self._win_height = int(self._sys_height * (2 / 3))
- self._win_width = int(self._sys_width * (2 / 3))
- self._full_screen = False
- self.__conf_windows()
- self.__conf_font_size()
- self.__show_login_window()
- self.__conf_set_after_run()
- def __conf_windows(self):
- self._window.title('HGSSystem: Manage Station')
- self._window.geometry(f'{self._win_width}x{self._win_height}')
- self._window['bg'] = "#F0FFF0"
- self._window.resizable(False, False)
- self._window.protocol("WM_DELETE_WINDOW", lambda: self.main_exit())
- def __conf_creak_tk(self):
- self._frame_list: List[AdminMenu] = []
- self._program_frame: List[AdminProgram] = []
- self._msg_frame = tk.Frame(self._window)
- self._msg_label = tk.Label(self._msg_frame), tk.Label(self._msg_frame), tk.StringVar(), tk.StringVar()
- self._msg_hide = tk.Button(self._msg_frame)
- self._loading_frame = tk.Frame(self._window)
- self._loading_title: Tuple[tk.Label, tk.Variable] = tk.Label(self._loading_frame), tk.StringVar()
- self._loading_pro = ttk.Progressbar(self._loading_frame)
- def __conf_font_size(self, n: int = 1):
- self._login_title_font_size = int(12 * n)
- self._login_btn_font_size = int(11 * n)
- def __show_login_window(self):
- self.login_window: Optional[tk.Toplevel] = tk.Toplevel()
- self.login_window.title("HGSSystem Login")
- height = int(self._sys_height * (1 / 6))
- width = int(height * 2)
- if width > self._sys_width:
- width = int(self._sys_width * (2 / 3))
- height = int(width / 2)
- self.login_window.geometry(f'{width}x{height}')
- self.login_window['bg'] = "#d1d9e0"
- self.login_window.resizable(False, False)
- self.login_window.protocol("WM_DELETE_WINDOW", lambda: self.login_exit())
- self._login_name = [tk.Label(self.login_window), tk.Entry(self.login_window), tk.StringVar()]
- self._login_passwd = [tk.Label(self.login_window), tk.Entry(self.login_window), tk.StringVar()]
- self._login_btn = [tk.Button(self.login_window), tk.Button(self.login_window)]
- self.__conf_login_window()
- self.hide_main()
- def __conf_login_window(self):
- title_font = self.__make_font(size=self._login_title_font_size, weight="bold")
- btn_font = self.__make_font(size=self._login_btn_font_size, weight="bold")
- for lb, text in zip([self._login_name[0], self._login_passwd[0]], ["User:", "Passwd:"]):
- lb['bg'] = "#d1d9e0" # 蜜瓜绿
- lb['font'] = title_font
- lb['text'] = text
- lb['anchor'] = 'e'
- for lb, var in zip([self._login_name[1], self._login_passwd[1]], [self._login_name[2], self._login_passwd[2]]):
- lb['font'] = title_font
- lb['textvariable'] = var
- self._login_name[0].place(relx=0.00, rely=0.20, relwidth=0.35, relheight=0.15)
- self._login_passwd[0].place(relx=0.00, rely=0.40, relwidth=0.35, relheight=0.15)
- self._login_name[1].place(relx=0.40, rely=0.20, relwidth=0.45, relheight=0.15)
- self._login_passwd[1]['show'] = "*"
- self._login_passwd[1].place(relx=0.40, rely=0.40, relwidth=0.45, relheight=0.15)
- self._login_btn[0]['bg'] = "#a1afc9"
- self._login_btn[0]['font'] = btn_font
- self._login_btn[0]['text'] = 'Login'
- self._login_btn[0]['command'] = lambda: self.login_call()
- self._login_btn[0].place(relx=0.50, rely=0.70, relwidth=0.16, relheight=0.15)
- self._login_btn[1]['bg'] = "#a1afc9"
- self._login_btn[1]['font'] = btn_font
- self._login_btn[1]['text'] = 'Exit'
- self._login_btn[1]['command'] = lambda: self.login_exit()
- self._login_btn[1].place(relx=0.70, rely=0.70, relwidth=0.16, relheight=0.15)
- def login_call(self):
- event = LoginEvent(self, self._db).start(self._login_name[2].get(),
- self._login_passwd[2].get())
- self.push_event(event)
- def login(self, user: User):
- if super(AdminStation, self).login(user):
- self.login_window.destroy()
- self.login_window = None
- self.show_main()
- else:
- msg.showerror("Login error", "Please, try again")
- self._login_name[2].set('')
- self._login_passwd[2].set('')
- def login_exit(self):
- if not msg.askokcancel('Sure?', 'Exit manager system.'):
- return
- if self.login_window is not None:
- self.login_window.destroy()
- self.exit_win()
- def main_exit(self):
- if not msg.askokcancel('Sure?', 'Exit manager system.'):
- return
- self.exit_win()
- def hide_main(self):
- self._window.withdraw()
- def show_main(self):
- self._window.update()
- self._window.deiconify()
- def show_loading(self, title: str):
- ...
- def stop_loading(self):
- ...
- @staticmethod
- def __make_font(family: str = 'noto', **kwargs):
- return font.Font(family=conf.font_d[family], **kwargs)
- def mainloop(self):
- self._window.mainloop()
- def exit_win(self):
- self._window.destroy()
- class LoginEvent(AdminEventBase):
- def __init__(self, station: AdminStationBase, db: DB):
- super().__init__(station, db, "Ranking")
- self.thread: Optional[TkThreading] = None
- def login(self, name, passwd):
- return find_user_by_name(name, passwd, self._db)
- def start(self, name, passwd):
- self.thread = TkThreading(self.login, name, passwd)
- return self
- def is_end(self) -> bool:
- return not self.thread.is_alive()
- def done_after_event(self):
- self.station.login(self.thread.wait_event())
- class AdminMenu(metaclass=abc.ABCMeta):
- @abc.abstractmethod
- def get_menu_frame(self, station: AdminStation) -> tk.Frame:
- ...
- class AdminProgram(metaclass=abc.ABCMeta):
- @abc.abstractmethod
- def get_admin_frame(self, station: AdminStation) -> tk.Frame:
- ...
- if __name__ == '__main__':
- mysql_db = DB()
- station_ = AdminStation(mysql_db)
- station_.mainloop()
|