Exemple #1
0
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']
Exemple #2
0
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')
Exemple #3
0
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
Exemple #4
0
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"])
Exemple #5
0
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')
 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)
Exemple #7
0
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")
Exemple #8
0
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()
Exemple #9
0
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("Μήνυμα Σφάλματος",
                                 "Δεν ήταν δυνατή η Εξαγωγή του αρχείου.")
Exemple #10
0
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"])
Exemple #12
0
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()
Exemple #13
0
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")
Exemple #16
0
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')
Exemple #17
0
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)
Exemple #18
0
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()
Exemple #19
0
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)
Exemple #20
0
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)
Exemple #21
0
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()
Exemple #22
0
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
Exemple #23
0
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)
Exemple #24
0
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()
Exemple #25
0
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()
Exemple #26
0
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")
Exemple #27
0
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]))
Exemple #29
0
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()
Exemple #30
0
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)
Exemple #31
0
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()