Exemple #1
0
class FileTree(Toplevel):
    def __init__(self, master, path):

        self.master = master
        self.path = path
        self.fileTreeWindow = Toplevel(master=self.master)
        #self.fileTreeWindow.configure(width=200)
        self.tree = Treeview(self.fileTreeWindow, height=30)
        abspath = os.path.abspath(self.path)
        self.root_node = self.tree.insert('', 'end', text=abspath, open=True)
        self.process_directory(self.root_node, abspath)
        self.tree.pack(fill='x')
        self.tree.bind('<Double-Button-1>', func=self.openFile)
        self.fileTreeWindow.mainloop()

    def process_directory(self, parent, path):
        for p in os.listdir(path):
            abspath = os.path.join(path, p)
            isdir = os.path.isdir(abspath)
            oid = self.tree.insert(parent,
                                   'end',
                                   text=p,
                                   open=False,
                                   iid=str(abspath))
            # print(oid)
            if isdir:
                self.process_directory(oid, abspath)

    def openFile(self, e):

        file_path = self.tree.identify_row(e.y)
        self.master.master.master.openFileByName(file_path)
Exemple #2
0
    def makeFileViewPanel(self):
        panel = Frame(self)
        panel.place(x=0, y=0, width=580, height=280)
        scrollBar = Scrollbar(panel)
        scrollBar.pack(side=RIGHT, fill=Y)
        global _fileViewTree
        _fileViewTree = Treeview(panel, columns=('c1', 'c2', 'c3', 'c4'), show='headings',
                                 yscrollcommand=scrollBar.set)
        _fileViewTree.column('c1', width=70, anchor='center')
        _fileViewTree.column('c2', width=70, anchor='center')
        _fileViewTree.column('c3', width=70, anchor='center')
        _fileViewTree.column('c4', width=370, anchor='center')
        _fileViewTree.heading('c1', text='Event No')
        _fileViewTree.heading('c2', text='Props')
        _fileViewTree.heading('c3', text='Alarms')
        _fileViewTree.heading('c4', text='Summary')
        _fileViewTree.pack(side=LEFT, fill=Y)
        scrollBar.config(command=_fileViewTree.yview)

        def listClick(event):
            selection = _fileViewTree.selection()
            if len(selection) != 0:
                item = _fileViewTree.focus()
                if item in selection:
                    _fileViewTree.selection_remove(item)
                    return 'continue'

        _fileViewTree.bind('<Button-1>', listClick)
Exemple #3
0
class _List(WidgetBase):
    def __init__(self, master, **options):
        super().__init__(master)
        from tkinter.ttk import Treeview
        self.widget = Treeview(self.master, show="tree", **options)
        self.widget.bind("<<TreeviewSelect>>", self.callback)
        self.value = ()

    def set_header(self, column, text):
        self.widget.heading("#" + str(column), text=text)

    def add_item(self,
                 parent="",
                 index=0,
                 id=None,
                 label="",
                 values=None,
                 **options):
        if not id is None:
            options.update(iid=id)
        if not values is None:
            options.update(values=values)
        self.widget.insert(parent=parent, index=index, text=label, **options)

    def callback(self, event):
        self.value = self.widget.selection()

    def set_selection(self, items):
        self.value = items
        self.widget.selection_set(items)

    def exist_item(self, id):
        return self.widget.exists(id)
Exemple #4
0
    def preparingOrders(self):
        self.prepare_screen = Tk()
        self.prepare_screen.title("Preparing")
        all_history = mydb.showActiveOrder(self.shop_id)
        print(all_history)
        Label(self.prepare_screen,
              text="All your orders",
              bg="yellow",
              width="300",
              height="2",
              font=("Calibri", 13)).pack()
        Label(text="").pack()
        tree = Treeview(self.prepare_screen, style="mystyle.Treeview")
        tree["columns"] = ("one", "two", "three", "four")
        #set tree columns
        tree.column("#0", width=270, minwidth=270, stretch=tk.NO)
        tree.column("one", width=150, minwidth=150, stretch=tk.NO)
        tree.column("two", width=400, minwidth=200)
        tree.column("three", width=80, minwidth=50, stretch=tk.YES)
        tree.column("four", width=80, minwidth=50, stretch=tk.YES)
        #set tree's heading
        tree.heading("#0", text="Order#", anchor=tk.W)
        tree.heading("one", text="Total Price", anchor=tk.W)
        tree.heading("two", text="Address", anchor=tk.W)
        tree.heading("three", text="Status", anchor=tk.W)
        tree.heading("four", text="Foods", anchor=tk.W)
        invoic_dict = {}
        print(all_history)
        for history in all_history:
            if ((history[0], history[1], history[2], history[4])
                    in invoic_dict.keys()):
                invoic_dict[(history[0], history[1], history[2],
                             history[4])].append(history[3])
            else:
                invoic_dict[(history[0], history[1], history[2],
                             history[4])] = []
                invoic_dict[(history[0], history[1], history[2],
                             history[4])].append(history[3])

        # print (type(list(invoic_dict.keys())))
        print(invoic_dict)

        tree.pack(side=tk.TOP, fill=tk.X)
        orders_list = []
        for key in invoic_dict.keys():
            orders_list.append(key[0])
        for i in range(len(list(invoic_dict.keys()))):
            order_number = list(invoic_dict.keys())[i][0]
            address_id = list(invoic_dict.keys())[i][2]
            foods_list = invoic_dict[list(invoic_dict.keys())[i]]
            print(foods_list)
            tree.insert("",
                        i + 1,
                        text="Order#" + str(order_number),
                        values=(list(invoic_dict.keys())[i][1],
                                self.make_address_str(address_id),
                                list(invoic_dict.keys())[i][3],
                                self.make_foods_str(foods_list)))
        tree.bind("<Double-1>", partial(self.OnDoubleClickChangeStatus, tree))
def showCatgory():
    Cat1_window = tk.Toplevel(root)
    Cat1_window.geometry('300x400')
    Cat1_window.resizable(0, 0)
    Cat1_window.title('1000萬發票 消費品項統計表')
    frame1 = Frame(Cat1_window)
    frame1.place(x=0, y=10, width=280, height=400)
    scrBar1 = tk.Scrollbar(Cat1_window)
    scrBar1.pack(side=tk.RIGHT, fill=tk.Y)
    tree1 = Treeview(Cat1_window,
                     columns=('c1', 'c2'),
                     show='headings',
                     yscrollcommand=scrBar1.set)

    tree1.column('c1', width=200, anchor='center')
    tree1.column('c2', width=80, anchor='center')
    tree1.heading('c1', text='品項')
    tree1.heading('c2', text='出現次數')
    tree1.pack(side=tk.LEFT, fill=tk.Y)

    scrBar1.config(command=tree1.yview)
    tree1.bind('<Button-1>', treeviewClick)

    sort1000 = [[v[1], v[0]] for v in Cat_1000.items()]
    sort1000.sort()
    sort1000.reverse()

    for z in sort1000:
        tree1.insert('', 'end', text=z[1], values=(z[1], z[0]))

    Cat2_window = tk.Toplevel(root)
    Cat2_window.geometry('300x400')
    Cat2_window.resizable(0, 0)
    Cat2_window.title('200萬發票 消費品項統計表')
    frame2 = Frame(Cat2_window)
    frame2.place(x=0, y=10, width=280, height=400)
    scrBar2 = tk.Scrollbar(Cat2_window)
    scrBar2.pack(side=tk.RIGHT, fill=tk.Y)
    tree2 = Treeview(Cat2_window,
                     columns=('w1', 'w2'),
                     show='headings',
                     yscrollcommand=scrBar2.set)

    tree2.column('w1', width=200, anchor='center')
    tree2.column('w2', width=80, anchor='center')
    tree2.heading('w1', text='品項')
    tree2.heading('w2', text='出現次數')
    tree2.pack(side=tk.LEFT, fill=tk.Y)

    scrBar2.config(command=tree2.yview)
    tree2.bind('<Button-1>', treeviewClick)

    sort200 = [[v[1], v[0]] for v in Cat_200.items()]
    sort200.sort()
    sort200.reverse()

    for z in sort200:
        tree2.insert('', 'end', text=z[1], values=(z[1], z[0]))
Exemple #6
0
    def define_widgets(self):
        context_menu = Menu(self.window, tearoff=0, name="contextMenu")
        context_menu.add_command(label="Copy password", command=self.password_copy)
        context_menu.add_command(label="Edit entry")
        context_menu.add_command(label="Delete entry", command=self.remove_password)

        password_label = Label(self.window, text="Enter master password", anchor=NW, font=("Arial", 16))
        password_label.grid(row=0)

        password = Entry(self.window, name="password", show="*", font=("Arial", 16))
        password.grid(row=1, pady=5)
        password.bind("<Return>", self.login)

        menu_bar = Menu(self.window, name="menuBar")
        file_menu = Menu(menu_bar, tearoff=0)
        option_menu = Menu(menu_bar, tearoff=0, name="optionMenu")

        file_menu.add_command(label="Exit", command=self.window.destroy)

        option_menu.add_command(label="Show passwords", command=self.show_passwords)
        option_menu.add_command(label="Hide passwords", command=self.hide_passwords)
        option_menu.add_separator()
        option_menu.add_command(label="Add en entry", command=self.add_entry_view)
        option_menu.add_separator()
        option_menu.add_command(label="Change master password", command=self.change_password)

        option_menu.entryconfig(1, state=DISABLED)

        menu_bar.add_cascade(label="File", menu=file_menu)
        menu_bar.add_cascade(label="Options", menu=option_menu)

        password_list = Treeview(self.window, name="passwordList", height=10)
        password_list['show'] = 'headings'
        password_list["columns"] = ("ID", "Title", "Username", "Password", "Password ")
        password_list.column("ID", stretch=False, minwidth=50, width=50)
        password_list.column("Title", stretch=False, minwidth=300, width=300)
        password_list.column("Username", stretch=False, minwidth=300, width=300)
        password_list.column("Password", stretch=False, minwidth=300, width=300)
        password_list.column("Password ", stretch=False, minwidth=300, width=300)
        password_list.heading("ID", text="ID")
        password_list.heading("Title", text="Title")
        password_list.heading("Username", text="Username")
        password_list.heading("Password", text="Password")
        password_list.heading("Password ", text="Password")
        password_list.bind("<Button-3>", self.right_click_password)
        password_list.bind("<Button-1>", self.left_click_password)

        Scrollbar(self.window, orient="vertical", command=password_list.yview, name="vScroll")

        Label(self.window, name="titleLabel", text="Enter the title", anchor="e", font=("Arial", 16), justify=RIGHT)
        Label(self.window, name="userLabel", text="Enter the username", anchor="e", font=("Arial", 16), justify=RIGHT)
        Label(self.window, name="passwordLabel", text="Enter password", anchor="e", font=("Arial", 16), justify=RIGHT)
        Entry(self.window, name="newPassword", show="*", font=("Arial", 16))
        Entry(self.window, name="newTitle", font=("Arial", 16))
        Entry(self.window, name="newUser", font=("Arial", 16))
        Button(self.window, name="newEntry", text="Create entry", command=self.add_entry)
        Button(self.window, name="cancelNewEntry", text="Cancel", command=self.display_main_view)
class PopupFrameView(Toplevel): # СОРТИРОВКА ФИЛЬМОВ;
    def __init__(self, x, y, *data):
        super().__init__()
        self.x = x
        self.y = y
        self.vr = data
        self.init_frame()
        self.db = db
        self.view = appl
        self.view_record()

    def init_frame(self):
        self.title('Просмотр записей')
        self.geometry('440x392+%d+%d' % (self.x + 180, self.y + 65))
        self.resizable(False, False)

        # НИЖНЯЯ ПАНЕЛЬ для КОЛИЧЕСТВА ЗАПИСЕЙ;
        TB_BOT = Frame(self, bg='#EDF0F5', bd=1)
        TB_BOT.pack(side=BOTTOM, fill=X)

        # ВЫВОД КОЛИЧЕСТВА ЗАПИСЕЙ на НИЖНЮЮ ПАНЕЛЬ;
        self.count = Label(TB_BOT, background='#EDF0F5', foreground='#425370')
        self.count.pack()

        _yscroll_ = Scrollbar(self)
        self.tree = Treeview(self, columns=('id', 'name'), height=18, show='headings', yscrollcommand=_yscroll_.set)
        _yscroll_.config(command=self.tree.yview)
        
        self.tree.column('id',   width=50, anchor=CENTER)
        self.tree.column('name', width=370)
        
        self.tree.heading('id',   text='№')
        self.tree.heading('name', text='Название')

        _yscroll_.pack(side=RIGHT, fill=Y)
        self.tree.pack()
        self.tree.bind('<Button-1>', lambda event: 'break' if self.tree.identify_region(event.x, event.y) == 'separator' else None)

        # УДЕРЖИВАЕМ НАШЕ ДИАЛОГОВОЕ ОКНО 'НА ВЕРХУ';
        self.grab_set()
        self.focus_set()

    def view_record(self): # ПРОСМОТР ОТСОРТИРОВАННЫХ ДАННЫХ;
        num = 0
        if (self.vr[0][0] != '' and self.vr[0][1] == '' and self.vr[0][2] == ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE mors=? ''', (self.vr[0][0], ))
        if (self.vr[0][0] == '' and self.vr[0][1] != '' and self.vr[0][2] == ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE janr=? ''', (self.vr[0][1], ))
        if (self.vr[0][0] == '' and self.vr[0][1] == '' and self.vr[0][2] != ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE flag=? ''', (self.vr[0][2], ))
        if (self.vr[0][0] != '' and self.vr[0][1] != '' and self.vr[0][2] != ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE mors=? AND janr=? AND flag=? ''', (self.vr[0][0], self.vr[0][1], self.vr[0][2]))
        [ self.tree.delete(i) for i in self.tree.get_children() ]
        for row in self.db.c.fetchall():
            [ self.tree.insert('', 'end', values=row) ]
            num += 1
        self.count['text'] = 'Количество записей: %d' % num
Exemple #8
0
        def showHistoryOfOrders():
            self.history_of_orders_screen = Tk()
            self.history_of_orders_screen.title("Hisotry of orders")
            Label(self.history_of_orders_screen,
                  text="History of orders, click on them to comment",
                  bg="yellow",
                  width="300",
                  height="2",
                  font=("Calibri", 13)).pack()
            Label(text="").pack()
            tree = Treeview(self.history_of_orders_screen,
                            style="mystyle.Treeview")
            tree["columns"] = ("one", "two", "three")
            #set tree columns
            tree.column("#0", width=270, minwidth=270, stretch=tk.NO)
            tree.column("one", width=150, minwidth=150, stretch=tk.NO)
            tree.column("two", width=400, minwidth=200)
            tree.column("three", width=80, minwidth=50, stretch=tk.YES)
            #set tree's heading
            tree.heading("#0", text="Order#", anchor=tk.W)
            tree.heading("one", text="Total Price", anchor=tk.W)
            tree.heading("two", text="Address", anchor=tk.W)
            tree.heading("three", text="Foods", anchor=tk.W)
            history_of_orders = mydb.showBuyHistory(self.user_id)
            invoic_dict = {}
            for history in history_of_orders:
                if ((history[0], history[1], history[2])
                        in invoic_dict.keys()):
                    invoic_dict[(history[0], history[1],
                                 history[2])].append(history[3])
                else:
                    invoic_dict[(history[0], history[1], history[2])] = []
                    invoic_dict[(history[0], history[1],
                                 history[2])].append(history[3])

            # print (type(list(invoic_dict.keys())))
            # print (invoic_dict)

            tree.pack(side=tk.TOP, fill=tk.X)
            orders_list = []
            for key in invoic_dict.keys():
                orders_list.append(key[0])
            for i in range(len(list(invoic_dict.keys()))):
                address_id = list(invoic_dict.keys())[i][2]
                foods_list = invoic_dict[list(invoic_dict.keys())[i]]
                print(foods_list)
                tree.insert("",
                            i + 1,
                            text="Order#" + str(i + 1),
                            values=(list(invoic_dict.keys())[i][1],
                                    self.make_address_str(address_id),
                                    self.make_foods_str(foods_list)))
            # resturant_in_treeview = tree.insert("", i+1, text=resturants[i][1], values=(resturants[i][2], resturants[i][3], make_address_str(resturants[i][4])))
            # list_of_resturant_in_treeview.append(resturant_in_treeview)
            tree.bind("<Double-1>",
                      partial(OnDoubleClickOnOrder, tree, orders_list))
Exemple #9
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 #10
0
def open_ongoing_view():
    bloc_root_buttons()
    get_list_of_bills()
    window_ongoing_bill = Toplevel()
    x = main_window_of_gui.winfo_x()
    y = main_window_of_gui.winfo_y()
    w = main_window_of_gui.winfo_width()
    h = main_window_of_gui.winfo_height()
    window_ongoing_bill.geometry("%dx%d+%d+%d" % (w, h, x, y))
    window_ongoing_bill.title("Factures en cours")
    window_ongoing_bill.wm_attributes("-topmost", 1)
    frame_for_the_list = Frame(window_ongoing_bill)
    frame_for_the_list.grid(column=0, row=0)
    tv_columns = ('work_type', 'company_name', 'comment', "start_date",
                  "end_date", "price", "payment_status")
    treeview_details_of_ongoing_bills = Treeview(frame_for_the_list,
                                                 columns=tv_columns,
                                                 show='headings')
    for column in tv_columns:
        treeview_details_of_ongoing_bills.heading(
            column,
            text=column,
            command=lambda col=column: treeview_sort_column(
                treeview_details_of_ongoing_bills, col, False))
        treeview_details_of_ongoing_bills.column(column,
                                                 anchor='center',
                                                 width=100)
    treeview_details_of_ongoing_bills.column('comment',
                                             anchor='center',
                                             width=300)
    scrollbar = Scrollbar(frame_for_the_list,
                          command=treeview_details_of_ongoing_bills.yview)
    scrollbar.pack(side=RIGHT, fill=Y)
    treeview_details_of_ongoing_bills.pack()
    for bill in LIST_OF_BILLS:
        treeview_details_of_ongoing_bills.insert(
            '',
            'end',
            text=str(bill.row_placement),
            values=(bill.work_type, bill.company_name, bill.comment,
                    bill.start_date, bill.end_date, bill.price,
                    bill.payment_status))
    treeview_details_of_ongoing_bills.bind(
        '<Double-1>',
        lambda event: doube_click_bill_line(event, window_ongoing_bill))
    treeview_details_of_ongoing_bills.configure(yscrollcommand=scrollbar.set)
    label_explanation = Label(window_ongoing_bill,
                              text="Double-click pour editer une facture.")
    label_explanation.grid(column=0, row=1)
    treeview_details_of_ongoing_bills.bind(
        "<Destroy>", toplevel_was_closed
    )  # if bind on toplevel, the destruction of all widgets in toplevel trigers the function
Exemple #11
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 #12
0
    def showRestaurantsBySearch(self, city_combo, shop_name_entry,
                                min_bill_entry):
        city_id = -1
        if (city_combo.get() == "None"):
            city_id = None
        else:
            city_id = mydb.addCity(city_combo.get())
        min_bill = min_bill_entry.get()
        if (min_bill_entry.get() == ""):
            min_bill = None
        shop_name = shop_name_entry.get()
        if (shop_name_entry.get() == ""):
            shop_name = None

        resturants = mydb.searchShop(city_id, shop_name, min_bill)
        # print (resturants)
        self.searched_resturant_screen = Tk()
        self.searched_resturant_screen.title("Results")
        tree = Treeview(self.searched_resturant_screen,
                        style="mystyle.Treeview")
        tree["columns"] = ("one", "two", "three", "four")
        #set tree columns
        tree.column("#0", width=270, minwidth=270, stretch=tk.NO)
        tree.column("one", width=150, minwidth=150, stretch=tk.NO)
        tree.column("two", width=400, minwidth=200)
        tree.column("three", width=80, minwidth=50, stretch=tk.YES)
        tree.column("four", width=80, minwidth=50, stretch=tk.YES)
        #set tree's heading
        tree.heading("#0", text="Name", anchor=tk.W)
        tree.heading("one", text="About", anchor=tk.W)
        tree.heading("two", text="min bill value", anchor=tk.W)
        tree.heading("three", text="address", anchor=tk.W)
        tree.heading("four", text="Rate", anchor=tk.W)
        list_of_resturant_in_treeview = []
        for i in range(len(resturants)):
            rate = mydb.calculateRate(resturants[i][0])
            resturant_in_treeview = tree.insert(
                "",
                i + 1,
                text=resturants[i][1],
                values=(resturants[i][2], resturants[i][3],
                        self.make_address_str(resturants[i][4]),
                        "--" if rate[0][0] == None else rate[0][0]))
            list_of_resturant_in_treeview.append(resturant_in_treeview)
        # for resturant in list_of_resturant_in_treeview:
        #     index = list_of_resturant_in_treeview.index(resturant)
        #     shop_id = resturants[index][0]
        #     shop_foods = mydb.showFoodsOfShop(shop_id)

        tree.pack(side=tk.TOP, fill=tk.X)
        tree.bind("<Double-1>", partial(self.OnDoubleClick, tree, resturants))
class SelectionFrame(Frame):
    def __init__(self, fruit_list, **kw):
        # init drop down
        super().__init__(**kw)
        self.fruit_list = fruit_list
        self.type_select = StringVar(self)
        header = Label(self)
        header.grid(row=0, column=0, columnspan=2, pady=10)
        type_options = OptionMenu(
            header, self.type_select, *models.TYPES, command=self.set_group)
        type_options.config(width=14)
        type_options.grid(row=0, column=0)
        # init start simulator button
        simulator_btn = Button(
            header, text="模拟器", command=lambda: sm.Simulator().mainloop())
        simulator_btn.grid(row=0, column=1)
        # init treeView
        self.tree = Treeview(self, columns=["名称", "效果"], show="headings")
        self.tree.column("名称", width=50, anchor='center')
        self.tree.column("效果", width=150, anchor='center')
        self.tree.heading("名称", text="名称")
        self.tree.heading("效果", text="效果")
        self.tree.grid(row=1, column=0)
        self.tree.bind("<Double-1>", self.select_item)
        self.select_item_callback = lambda x: x
        vbar = Scrollbar(self, orient=VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=vbar.set)
        vbar.grid(row=1, column=1, sticky=NS)
        # default value
        self.set_group(models.TYPES[0])

    def set_group(self, group):
        self.type_select.set(group)
        x = self.tree.get_children()
        for item in x:
            self.tree.delete(item)

        for x in self.fruit_list:
            if x.get_type() == group:
                self.tree.insert("", END, value=(x.name, x.description))

    def select_item(self, event):
        item = self.tree.selection()[0]
        name = self.tree.item(item, "value")[0]
        self.select_item_callback(
            next(filter(lambda x: x.name == name, self.fruit_list)))

    def set_select_callback(self, callback):
        self.select_item_callback = callback
Exemple #14
0
def treeview_olustur(master, columns, data, width):
    
    y_scrollbar = Scrollbar(master=master, orient="vertical")
    y_scrollbar.pack(side="right", fill="y")
    
    
    x_scrollbar = Scrollbar(master=master, orient="horizontal")
    x_scrollbar.pack(side="bottom", fill="x")
    

    treeview = Treeview(master=master, columns=columns, show="headings")
    treeview.pack(expand=True, fill="both")
    
    
    x_scrollbar["command"] = treeview.xview
    y_scrollbar["command"] = treeview.yview
    
    
    treeview["yscrollcommand"] = y_scrollbar.set
    treeview["xscrollcommand"] = x_scrollbar.set


    for i, j in enumerate(columns):
        
        treeview.column(
            column=f"#{i + 1}",  
            width=width,         
            anchor=CENTER     
        )
        
        treeview.heading(
            column=f"#{i + 1}",  
            text=j               
        )   

    
    for index, row in enumerate(data):
        treeview.insert(
            parent="",           
            index=index,         
            values=row          
        )


    
    treeview.bind(
        sequence="<Double-Button-1>", 
        func=lambda event: veriye_odaklan(treeview,master)
    )
    def display_books():
        display = Toplevel()
        w = 1300
        h = 600
        display.title('BOOK WAREHOUSE')
        x = (rootwin.winfo_screenwidth() // 2) - (w // 2)
        y = (rootwin.winfo_screenheight() // 2) - (h // 2)
        display.geometry(f'{w}x{h}+{x}+{y}')
        display.focus()
        display.iconbitmap(display, cg_logo)
        infoframe = Frame(display, width=500, height=500, bg='white')

        xscrollbar = Scrollbar(infoframe, orient=HORIZONTAL)
        xscrollbar.pack(side=BOTTOM, fill=X)

        yscrollbar = Scrollbar(infoframe, orient=VERTICAL)
        yscrollbar.pack(side=RIGHT, fill=Y)

        table = Treeview(infoframe,
                         columns=('1', '2', '3', '4', '5'),
                         xscrollcommand=xscrollbar.set,
                         yscrollcommand=yscrollbar.set)

        table.heading('1', text='TITLE')
        table.heading('2', text='AUTHOR')
        table.heading('3', text="SUBJECT")
        table.heading('4', text="SERIAL NO.")
        table.heading('5', text='QUANTITY')

        table['show'] = 'headings'

        table.pack(side=TOP, fill=BOTH, expand=1)

        xscrollbar.config(command=table.xview)
        yscrollbar.config(command=table.yview)
        infoframe.pack(side=TOP, fill=BOTH, expand=1)

        stack = library_full_data()

        for val in stack:
            table.insert('', END, values=val)

        def upbk(event):
            update_book(table, display)

        table.bind('<ButtonRelease-1>', upbk)

        display.mainloop()
Exemple #16
0
    def listVideos(self, chan, target):
        self.center = target
        #get chan id
        chanid = database.get_channel_id(chan)
        vids = database.get_channel_videos(chanid)

        tree = Treeview(self.center)
        tree["columns"] = ("one", "two")

        tree.column("#0", width=20, minwidth=10, stretch=YES)
        tree.column("one", width=390, minwidth=250, stretch=YES)
        tree.column("two", width=200, minwidth=40)

        tree.heading("#0", text="ID", anchor=W)
        tree.heading("one", text="Title", anchor=W)
        tree.heading("two", text="Date", anchor=W)
        i = 0
        tree.tag_configure('oddrow', background='#88DD88')
        tree.tag_configure('evenrow', background='#FFFFFF')

        for videodata in vids:
            foldername = "folder" + str(i)
            if i % 2 == 0:
                color = "evenrow"
            else:
                color = "oddrow"
            # tree.insert("", 1, "", text="Folder 1", values=("23-Jun-17 11:05","File folder",""))
            ts = int(videodata.publish_date)
            foldername = tree.insert("",
                                     "end",
                                     text=videodata.yt_videoid,
                                     values=(videodata.title, time.ctime(ts)),
                                     tags=(color))
            #tree.insert(folder1, "end", "", text="photo1.png", values=("23-Jun-17 11:28","PNG file","2.6 KB"))
            tree.insert(foldername,
                        "end",
                        text="desc",
                        values=(videodata.description, videodata.watched),
                        tags=(color))
            i = i + 1

        vertscroll = Scrollbar(self.center)
        vertscroll.config(command=tree.yview)
        tree.config(yscrollcommand=vertscroll.set)
        tree.bind("<Button-" + config.mousebuttons + ">",
                  self.video_action_window)
        tree.grid(row=5, columnspan=3, sticky="NSEW")
Exemple #17
0
    def setupTreeView(self):
        #probably want treeview, not listbox
        scr_w = 180
        scr_h = 10

        tabConfig = configRoot.findall('treeview/tab')
        self.tabLabelList = []
        self.headingDict = {}

        for t in tabConfig:
            tabName = t.attrib['label']
            self.tabLabelList.append(tabName)
            headingConfig = t.findall('heading')
            temp = []
            for h in headingConfig:
                temp.append(h.attrib['label'])
                self.headingDict[tabName] = temp.copy()
            temp.clear()

        print(self.headingDict)
        for tab in self.tabControl.winfo_children():
            # listbox = Listbox(tab, width = 120)
            # listbox.grid(column = 0, row = 0, padx = 20, pady = 10)
            tabText = self.tabControl.tab(tab)['text']

            treeview = Treeview(tab)
            #treeview['columns'] = ('Title', 'Author', 'Platform')
            treeview['columns'] = self.headingDict[tabText]
            treeview.heading("#0", text="ID")
            treeview.column('#0', minwidth=50, width=50, stretch=False)
            for h in treeview['columns']:
                print(h)
                treeview.heading(h, text=h)
            treeview.grid(
                column=0,
                row=0,
                sticky="NSEW",
            )
            treeview.bind("<Double-1>", self.itemSelected)
            treeview.config(height=25)

            scrollbar = Scrollbar(tab)
            scrollbar.grid(column=1, row=0, sticky="NS")
            treeview.config(yscrollcommand=scrollbar.set)
            scrollbar.config(command=treeview.yview)
Exemple #18
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 #19
0
    def showRestaurants(self, all_variables, all_address):

        address_id = -1
        for variable in all_variables:
            if (variable.get()):
                index = all_variables.index(variable)
                address_id = all_address[index][1]
                self.address_id = address_id
        resturants = mydb.searchShopByLocation(int(address_id), 100)
        # print (resturants)
        self.searched_resturant_screen = Tk()
        self.searched_resturant_screen.title("Results")
        tree = Treeview(self.searched_resturant_screen,
                        style="mystyle.Treeview")
        tree["columns"] = ("one", "two", "three", "four")
        #set tree columns
        tree.column("#0", width=270, minwidth=270, stretch=tk.NO)
        tree.column("one", width=150, minwidth=150, stretch=tk.NO)
        tree.column("two", width=400, minwidth=200)
        tree.column("three", width=400, minwidth=200, stretch=tk.YES)
        tree.column("four", width=80, minwidth=50, stretch=tk.YES)

        #set tree's heading
        tree.heading("#0", text="Name", anchor=tk.W)
        tree.heading("one", text="About", anchor=tk.W)
        tree.heading("two", text="min bill value", anchor=tk.W)
        tree.heading("three", text="address", anchor=tk.W)
        tree.heading("four", text="rate", anchor=tk.W)
        list_of_resturant_in_treeview = []
        for i in range(len(resturants)):
            rate = mydb.calculateRate(resturants[i][0])[0][0]
            resturant_in_treeview = tree.insert(
                "",
                i + 1,
                text=resturants[i][1],
                values=(resturants[i][2], resturants[i][3],
                        self.make_address_str(resturants[i][4]),
                        "-" if rate == None else rate))
            list_of_resturant_in_treeview.append(resturant_in_treeview)
        tree.pack(side=tk.TOP, fill=tk.X)
        tree.bind("<Double-1>", partial(self.OnDoubleClick, tree, resturants))
Exemple #20
0
    def print_messages(self, dataFrame):
        list_box = Treeview(self.messagesBox, columns=self.col_names, show='headings', height=19) #height is in number of rows:)
        for col in self.col_names:
            list_box.heading(col, text=col)
        list_box.grid(row=0, column=0, sticky='nsew', in_=self.messagesBox)
        list_box.tag_configure('odd', background='#f9f9f9')
        list_box.tag_configure('even', background='#DFDFDF')
        list_box.column("Timestamp", width=150)
        list_box.column("Data", width=400)
        scroll_bar = Scrollbar(self.messagesBox, orient="vertical", command=list_box.yview)
        scroll_bar.grid(row=0, column=1, sticky='ns')
        list_box.configure(yscrollcommand=scroll_bar.set)

        for index, row in dataFrame.iterrows():
            type = 'even'
            if (len(list_box.get_children()) % 2 == 1):
                type = 'odd'

            list_box.insert("", "end", values=(row.Timestamp, row.Data), tags=(type,))

        list_box.bind("<<TreeviewSelect>>", lambda event, t=list_box: self.message_click(event, t))
Exemple #21
0
def search_student():
    data = database.StudentSelect(name_student.get())
    names = data.get()
    tree = Treeview(s_select)
    tree["columns"]=("one","two","three","four","five")
    tree.column("#0", width=1)
    tree.column("one", width=70)
    tree.column("two", width=80)
    tree.column("three", width=80)
    tree.column("four", width=80)
    tree.column("five", width=40)
    tree.heading("#0",text="ID")
    tree.heading("one", text="Name",anchor=W)
    tree.heading("two", text="Family",anchor=W)
    tree.heading("three", text="Code",anchor=W)
    tree.heading("four", text="B. Date",anchor=W)
    tree.heading("five", text="Class",anchor=W)
    for name in names:
        tree.insert("", 1, text=name[0], values=(name[1],name[2],name[3], name[4], name[5]))
    tree.grid(row=1, column=0, columnspan=4, sticky=W+E)
    tree.bind("<Double-Button-1>", on_double_click)
Exemple #22
0
    def child(self):
        tree = Treeview(self, show="headings", selectmode="browse")
        headings = ['Логин', 'Ограничение']
        tree["columns"] = headings
        tree["displaycolumns"] = headings
        for h in headings:
            tree.heading(h, text=h, anchor=CENTER)
            tree.column(h, anchor=CENTER)

        with open('password.txt', 'rb') as f:
            file_load = pickle.load(f)

        data = dict(file_load)
        for login in file_load.keys():
            user_get = data.get(login)
            tree.insert('', END, values=tuple((login, user_get[2])))
            tree.bind('<Double-Button-1>', func=lambda event: self.command_limit(tree, data))

        scroll_table = Scrollbar(self, command=tree.yview)
        tree.configure(yscrollcommand=scroll_table.set)
        scroll_table.pack(side=RIGHT, fill=Y)
        tree.pack(expand=YES, fill=BOTH)
Exemple #23
0
    def make_tree(self):
        ''' Build a Tree '''
        def do_popup(event):
            ''' Bring up Pop Up menu '''
            if self.tree.focus() is not None:
                self.popup.post(event.x_root, event.y_root)

        tree = Treeview(self.root)
        tree["columns"] = ('Start', 'Execute', 'Length', 'Sector')
        tree.column("#0", width=350)
        tree.column("Start", width=70)
        tree.column("Execute", width=70)
        tree.column("Length", width=70)
        tree.column("Sector", width=70)
        tree.heading("Start", text="Start &")
        tree.heading("Execute", text="Execute &")
        tree.heading("Length", text="Length")
        tree.heading("Sector", text="Sector")
        self.make_popup(tree)
        tree.bind("<Button-3>", do_popup)
        tree.pack(fill=Y, side=LEFT)
        return tree
Exemple #24
0
 def showFoods(self):
     self.show_food_screen = Tk()
     self.show_food_screen.title("Foods")
     foods = mydb.showFoodsOfShop(self.shop_id)
     print(foods)
     Label(self.show_food_screen,
           text="All foods, double click to delete",
           bg="red",
           width="300",
           height="2",
           font=("Calibri", 13)).pack()
     Label(text="").pack()
     tree = Treeview(self.show_food_screen, style="mystyle.Treeview")
     tree["columns"] = ("one", "two", "three", "four", "five")
     #set tree columns
     tree.column("#0", width=150, minwidth=150, stretch=tk.NO)
     tree.column("one", width=400, minwidth=200)
     tree.column("two", width=80, minwidth=50, stretch=tk.YES)
     tree.column("three", width=80, minwidth=50, stretch=tk.YES)
     tree.column("four", width=80, minwidth=50, stretch=tk.YES)
     tree.column("five", width=80, minwidth=50, stretch=tk.YES)
     #set tree's heading
     tree.heading("#0", text="Name", anchor=tk.W)
     tree.heading("one", text="Price", anchor=tk.W)
     tree.heading("two", text="About", anchor=tk.W)
     tree.heading("three", text="Category", anchor=tk.W)
     tree.heading("four", text="Image", anchor=tk.W)
     tree.heading("five", text="Discount", anchor=tk.W)
     tree.pack()
     for i in range(len(foods)):
         tree.insert("",
                     i + 1,
                     text=foods[i][3],
                     values=(foods[i][1], foods[i][2],
                             mydb.showCategoryName(foods[i][6]),
                             foods[i][5], str(foods[i][4])))
     tree.bind("<Double-1>",
               partial(self.OnDoubleClickDeleteFood, tree, foods))
Exemple #25
0
def search_Student():
    names = database.Studentselect(full_name.get()).get()

    tree = Treeview(s_select)
    tree["columns"] = ("one", "two", "three", "four", "five")
    tree.column("#0", width=20, minwidth=20, stretch=NO)
    tree.column("one", width=100, minwidth=150, stretch=NO)
    tree.column("two", width=150, minwidth=200)
    tree.column("three", width=80, minwidth=50, stretch=NO)
    tree.column("four", width=80, minwidth=50, stretch=NO)
    tree.column("five", width=40, minwidth=50, stretch=NO)
    tree.heading("#0", text="ID", anchor=W)
    tree.heading("one", text="Name", anchor=W)
    tree.heading("two", text="Family", anchor=W)
    tree.heading("three", text="ID Number", anchor=W)
    tree.heading("four", text="Birth Date", anchor=W)
    tree.heading("five", text="Class Color", anchor=W)
    tree.grid(row=1, column=0, columnspan=5)
    for name in names:
        tree.insert("",
                    1,
                    text=name[0],
                    values=(name[1], name[2], name[3], name[4], name[5]))
    tree.bind("<Double-Button-1>", double_click)
Exemple #26
0
class StructEditor(tk.Frame, Subscriber, Observable):
    """Displays and allow editing of the coordinates and points of one superstructure

    Args:
        parent (tk.Frame): widget that is the parent of the editor
        structure (model.structure.Structure): the ship superstructure that will be edited
    """
    def __init__(self, parent, structure, command_stack):
        Subscriber.__init__(self, structure)
        Observable.__init__(self)
        tk.Frame.__init__(self, parent, borderwidth=4, relief="raised")
        self._structure = structure
        self._command_stack = command_stack

        self.bind("<Button-1>", self._on_click)
        self.bind("<FocusIn>", self._on_get_focus)
        self.bind("<FocusOut>", self._on_lost_focus)

        self._tree = Treeview(self,
                              columns=["#", "X", "Y"],
                              selectmode="browse")
        #kill the icon column
        self._tree.column("#0", minwidth=0, width=0)

        style = Style()
        style.configure("Treeview.Heading", font=(None, 16))

        self._tree.column("#", minwidth=20, width=40, anchor=tk.CENTER)
        self._tree.column("X", minwidth=20, width=40, anchor=tk.CENTER)
        self._tree.column("Y", minwidth=20, width=40, anchor=tk.CENTER)
        self._tree.heading("#", text="#")
        self._tree.heading("X", text="\u21d5")
        self._tree.heading("Y", text="\u21d4")
        self._tree.grid(row=0, column=POINTS_TABLE_COL, sticky=tk.N + tk.S)

        self._tree.bind("<<TreeviewSelect>>", self._on_point_selected)
        self._tree.bind("<FocusIn>", self._on_get_focus)
        self._tree.bind("<FocusOut>", self._on_lost_focus)

        scroll = Scrollbar(self, command=self._tree.yview)
        scroll.grid(row=0, column=SCROLL_COL, sticky=tk.N + tk.S)
        scroll.bind("<FocusIn>", self._on_get_focus)

        self._tree.configure(yscrollcommand=scroll.set)

        self._index_of_sel_point = -1
        self._fill_tree()

        self._edit_zone = EditZone(self, self._structure, command_stack,
                                   self._on_get_focus)
        self._edit_zone.grid(column=EDIT_ZONE_COL, row=0, sticky=tk.N)

    def _set_selection(self, new_sel_index):
        """Set the selected point to the new_sel_index

        Gives correct focus, update, etc to the editor's widgets
        if the index is outside of the self.points, does nothing
        """
        if new_sel_index >= 0 and new_sel_index <= len(self.points) - 1:
            iid = self._tree.get_children()[new_sel_index]
            self._tree.selection_set(iid)

    def _on_click(self, *_args):
        self._tree.focus_set()

    def _on_get_focus(self, *_args):
        if self._index_of_sel_point == -1:
            self._set_selection(0)
        self.configure(relief="sunken")
        self._notify("focus", {})

    def _on_lost_focus(self, event):
        if event.widget not in self.winfo_children():
            self.configure(relief="raised")

    def _on_point_selected(self, _event):
        """called back when a point is selected in the table/treeview

        Updates the editable fields
        """
        selected_iid = self._tree.selection()
        self._index_of_sel_point = self._tree.index(selected_iid)
        self._edit_zone.set_editable_point(
            self._tree.item(selected_iid)["values"][0])
        self._notify("focus", {})

    def _fill_tree(self):
        """fills the treeview with data from the structure
        """
        self._tree.delete(*self._tree.get_children())
        for point_index, point in enumerate(self._structure.points):
            self._tree.insert(
                '',
                'end',
                values=[point_index,
                        round(point[0]),
                        round(point[1])])
            if point_index == self._index_of_sel_point:
                self._set_selection(point_index)

    def _on_notification(self, observable, event_type, event_info):
        """Rebuild the treeview on structure update
        Depending on the structure state and the operation, change the selcted point
        """
        if event_type == "add_point":
            self._index_of_sel_point = event_info["index"]
            self._fill_tree()
        else:
            if self._index_of_sel_point >= len(self._structure.points):
                self._index_of_sel_point = len(self._structure.points)
                self._edit_zone.unset_point()
            self._fill_tree()
        self._notify("focus", {})

    def update_to_coord(self, point):
        """Move the selected point to the position of the given point

        Intended to be called from click on the top view
        Args:
            point (x, y): new position in funnel coordinates
        """
        if self._index_of_sel_point != -1 and self._index_of_sel_point <= len(
                self.points) - 1:
            self._command_stack.do(
                model.structure.UpdatePoint(self._structure,
                                            self._index_of_sel_point,
                                            round(point[0]), round(point[1])))
        elif self._index_of_sel_point == len(self.points) or not self.points:
            self._command_stack.do(
                model.structure.AddPoint(self._structure,
                                         self._index_of_sel_point + 1,
                                         round(point[0]), round(point[1])))
        if self._index_of_sel_point + 1 >= len(self.points):
            self.winfo_toplevel().update()
            self._index_of_sel_point = len(self.points)
        else:
            self._set_selection(self._index_of_sel_point + 1)
            self.winfo_toplevel().update()

    @property
    def points(self):
        """Pipe throught the struct's properties"""
        return self._structure.points

    @property
    def fill(self):
        """Pipe throught the struct's properties"""
        return self._structure.fill

    @property
    def selected_index(self):
        """the index in the struct's point list of the currently selected point

        Should be -1 if none selected
        """
        return self._index_of_sel_point
class DialogOpenArchive(Toplevel):
    def __init__(self,
                 parent,
                 openType,
                 filesource,
                 filenames,
                 title,
                 colHeader,
                 showAltViewButton=False):
        if isinstance(parent, Cntlr):
            cntlr = parent
            parent = parent.parent  # parent is cntlrWinMain
        else:  # parent is a Toplevel dialog
            cntlr = parent.cntlr
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)",
                                  parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)

        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame,
                                 xscrollcommand=hScrollbar.set,
                                 yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0,
                       column=0,
                       columnspan=4,
                       sticky=(N, S, E, W),
                       padx=3,
                       pady=3)
        self.treeView.focus_set()

        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                ''' take first for now
                if len(metadataFiles) != 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                '''
                metadataFile = metadataFiles[0]
                metadata = filesource.url + os.sep + metadataFile
                self.metadataFilePrefix = os.sep.join(
                    os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += "/"  # zip contents have /, never \ file seps
                self.taxonomyPkgMetaInf = '{}/META-INF/'.format(
                    os.path.splitext(os.path.basename(filesource.url))[0])

                self.taxonomyPackage = parsePackage(
                    cntlr, filesource, metadata,
                    os.sep.join(os.path.split(metadata)[:-1]) + os.sep)

                if self.taxonomyPackage["entryPoints"]:
                    # may have instance documents too
                    self.packageContainedInstances = []
                    packageContentTypeCounts = {}
                    for suffix in (".xhtml", ".htm", ".html"):
                        for potentialInstance in filesource.dir:
                            if potentialInstance.endswith(".xhtml"):
                                _type = "Inline Instance"
                                self.packageContainedInstances.append(
                                    [potentialInstance, _type])
                                packageContentTypeCounts[
                                    potentialInstance] = packageContentTypeCounts.get(
                                        potentialInstance, 0) + 1
                        if self.packageContainedInstances:
                            break
                    if self.packageContainedInstances:  # add sequences to any duplicated entry types
                        for _type, count in packageContentTypeCounts.items():
                            if count > 1:
                                _dupNo = 0
                                for i in range(
                                        len(self.packageContainedInstances)):
                                    if self.packageContainedInstances[i][
                                            0] == _type:
                                        _dupNo += 1
                                        self.packageContainedInstances[i][
                                            0] = "{} {}".format(_type, _dupNo)

                else:
                    # may be a catalog file with no entry oint names
                    openType = ARCHIVE  # no entry points to show, just archive
                    self.showAltViewButton = False
            except Exception as e:
                self.close()
                err = _(
                    "Failed to parse metadata; the underlying error was: {0}"
                ).format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                cntlr.addToLog(err)
                return

        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(None)

        if openType in (DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S, E, W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S, E, W), pady=3, padx=3)

        if self.showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y,
                                    column=0,
                                    sticky=(S, W),
                                    pady=3,
                                    padx=3)

        self.loadTreeView(openType, colHeader, title)

        self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100))
        frame.grid(row=0, column=0, sticky=(N, S, E, W))
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)

        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)

        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView,
                                   textvariable=self.toolTipText,
                                   wraplength=640,
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()

        self.wait_window(self)

    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""):
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            if openType in (PLUGIN, PACKAGE): width = 770
            else: width = 500
            self.treeView.column("#0", width=width, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            self.isRss = getattr(self.filesource, "isRss", False)
            if self.isRss:
                self.treeView.column("#0", width=350, anchor="w")
                self.treeView["columns"] = ("descr", "date", "instDoc")
                self.treeView.column("descr",
                                     width=50,
                                     anchor="center",
                                     stretch=False)
                self.treeView.heading("descr", text="Form")
                self.treeView.column("date",
                                     width=170,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("date", text="Pub Date")
                self.treeView.column("instDoc",
                                     width=200,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("instDoc", text="Instance Document")
            elif openType == PLUGIN:
                self.treeView.column("#0", width=150, anchor="w")
                self.treeView["columns"] = ("name", "vers", "descr", "license")
                self.treeView.column("name",
                                     width=150,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("name", text="Name")
                self.treeView.column("vers",
                                     width=60,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr",
                                     width=300,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license",
                                     width=60,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("license", text="License")
            elif openType == PACKAGE:
                self.treeView.column("#0", width=200, anchor="w")
                self.treeView["columns"] = ("vers", "descr", "license")
                self.treeView.column("vers",
                                     width=100,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr",
                                     width=400,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license",
                                     width=70,
                                     anchor="w",
                                     stretch=False)
                self.treeView.heading("license", text="License")
            else:
                self.treeView["columns"] = tuple()

            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename, tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    elif openType == PLUGIN:
                        name, vers, descr, license = filename[3:7]
                    elif openType == PACKAGE:
                        vers, descr, license = filename[3:6]
                    filename = filename[0]  # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(
                        path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = ""
                node = self.treeView.insert(parent,
                                            "end",
                                            "file{0}".format(i),
                                            text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc",
                                      os.path.basename(instDoc))
                elif openType == PLUGIN:
                    self.treeView.set(node, "name", name)
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                elif openType == PACKAGE:
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=200, anchor="w")
            self.treeView.heading("#0", text="Name")

            self.treeView["columns"] = ("url", )
            self.treeView.column("url", width=300, anchor="w")
            self.treeView.heading("url", text="URL")

            for fileType, fileUrl in getattr(self, "packageContainedInstances",
                                             ()):
                self.treeView.insert("",
                                     "end",
                                     fileUrl,
                                     values=fileType,
                                     text=fileUrl or urls[0][2])
            for name, urls in sorted(
                    self.taxonomyPackage["entryPoints"].items(),
                    key=lambda i: i[0][2]):
                self.treeView.insert("",
                                     "end",
                                     name,
                                     values="\n".join(url[1] for url in urls),
                                     text=name or urls[0][2])

            self.hasToolTip = True
        else:  # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType ==
                                      ENTRY_POINTS else _("Show Entries"))

    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if hasattr(self, "taxonomyPackage"):
                # load file source remappings
                self.filesource.mappedPaths = self.taxonomyPackage[
                    "remappings"]
            filename = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename, tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                # Greg Acsone reports [0] does not work for Corep 1.6 pkgs, need [1], old style packages
                filenames = []
                for _url, _type in self.packageContainedInstances:  # check if selection was an inline instance
                    if _type == epName:
                        filenames.append(_url)
                if not filenames:  # else if it's a named taxonomy entry point
                    for url in self.taxonomyPackage["entryPoints"][epName]:
                        filename = url[0]
                        if not filename.endswith("/"):
                            # check if it's an absolute URL rather than a path into the archive
                            if not isHttpUrl(
                                    filename
                            ) and self.metadataFilePrefix != self.taxonomyPkgMetaInf:
                                # assume it's a path inside the archive:
                                filename = self.metadataFilePrefix + filename
                        filenames.append(filename)
                if filenames:
                    self.filesource.select(filenames)
                    self.accepted = True
                    self.close()
                return
            elif self.openType in (PLUGIN, PACKAGE):
                filename = self.filenames[int(selection[0][4:])][2]
            if filename is not None and not filename.endswith("/"):
                if hasattr(self, "taxonomyPackage"):
                    # attempt to unmap the filename to original file
                    # will be mapped again in loading, but this allows schemaLocation to be unmapped
                    for prefix, remapping in self.taxonomyPackage[
                            "remappings"].items():
                        if isHttpUrl(remapping):
                            remapStart = remapping
                        else:
                            remapStart = self.metadataFilePrefix + remapping
                        if filename.startswith(remapStart):
                            # set unmmapped file
                            filename = prefix + filename[len(remapStart):]
                            break
                if self.openType in (PLUGIN, PACKAGE):
                    self.filesource.selection = filename
                else:
                    self.filesource.select(filename)
                self.accepted = True
                self.close()

    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()

    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"),
                              _("File"))

    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[int(tvRowId[4:])]
                        if isinstance(text, tuple):
                            text = (text[1] or "").replace("\\n", "\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    text = "{0}\n{1}".format(
                        tvRowId, "\n".join(
                            url[1] for url in
                            self.taxonomyPackage["entryPoints"][tvRowId]))
                except KeyError:
                    pass
            self.setToolTip(text)

    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
class Window:
    def fillTree(self,path, parent, list):
        for file in os.listdir(path):
            abspath = os.path.join(path,file)
            color = ""
            treelist = None
            for mini in list:
                if abspath in mini:
                    color = 'red'
                    treelist = mini
                else:
                    for lk in mini:
                        if abspath in lk:
                            color = 'purple'
            child = None
            if color == 'red':
                child = self.tree.insert(parent,'end',text=file,open=False,tags=(abspath,'red',str(treelist)),)
            elif color == 'purple':
                child = self.tree.insert(parent,'end',text=file,open=False,tags=(abspath,'purple'))
            else:
                child = self.tree.insert(parent,'end',text=file,open=False,tags=(abspath,'white'))
            if(os.path.isdir(abspath)):
                self.tree.insert(child,'end',text='',open=False)
    def __init__(self,list,dirlist):
        self.root = Tk()
        self.root.wm_title("Duplicate_Files")
        self.min = None
        self.list = list
        self.root.geometry('600x600+0+0')
        self.tree = Treeview(self.root ,height=15)
        self.tree.pack(expand='yes',fill='both')
        self.tree.heading('#0',text="files")
        self.tree.tag_configure('red',foreground='red')
        self.tree.tag_configure('purple',foreground='#cc00ff')
        self.tree.bind("<Double-1>",self.onDoubleClick)
        self.tree.bind("<<TreeviewOpen>>",self.onOpen)
        self.tree.bind("<<TreeviewClose>>",self.onClose)
        for path in dirlist:
            branch = self.tree.insert('','end',text=path,open=True,tags=(path,'white'))
            self.fillTree(path,branch,list)
        self.root.mainloop()


    def onDoubleClick(self,event):
        item = self.tree.selection()[0]
        print ("clicked" + str(self.tree.item(item,'tags')[0]))
        if str(self.tree.item(item,'tags')[1]) == "red":
            list_of_files = ast.literal_eval(str(self.tree.item(item,'tags')[2]))
            if self.min != None:
                if self.min.mini.winfo_exists():
                    self.min.mini.destroy()
            self.min = MiniWindow(self.root,list_of_files)

    def onOpen(self,event):
        item = self.tree.selection()[0]
        if self.tree.parent(item) != '':
            if len(self.tree.get_children(item))>0:
                self.tree.delete(self.tree.get_children(item))
            abspath = str(self.tree.item(item,'tags')[0])
            if(os.path.isdir(abspath)):
                self.fillTree(abspath, item,self.list)
    def onClose(self,event):
        item = self.tree.selection()[0]
        if self.tree.parent(item) != '':
            if len(self.tree.get_children(item))>0:
                self.tree.delete(self.tree.get_children(item))
Exemple #29
0
    def OnDoubleClick(self, tree, resturants, event):
        item = tree.identify('item', event.x, event.y)
        resturant_name = tree.item(item, "text")
        resturant_id = -1
        for res in resturants:
            if (res[1] == resturant_name):
                resturant_id = res[0]
        # print (resturant_id)
        foods = mydb.showFoodsOfShop(resturant_id)
        self.menu_screen = Tk()
        self.menu_screen.title(resturant_name + " Menu")
        if (len(foods) != 0):

            Label(self.menu_screen,
                  text="Resturant Menu",
                  bg="red",
                  width="300",
                  height="2",
                  font=("Calibri", 13)).pack()
            Label(text="").pack()
            tree = Treeview(self.menu_screen, style="mystyle.Treeview")
            tree["columns"] = ("one", "two", "three", "four", "five")
            #set tree columns
            tree.column("#0", width=150, minwidth=150, stretch=tk.NO)
            tree.column("one", width=400, minwidth=200)
            tree.column("two", width=80, minwidth=50, stretch=tk.YES)
            tree.column("three", width=80, minwidth=50, stretch=tk.YES)
            tree.column("four", width=80, minwidth=50, stretch=tk.YES)
            tree.column("five", width=80, minwidth=50, stretch=tk.YES)
            #set tree's heading
            tree.heading("#0", text="Name", anchor=tk.W)
            tree.heading("one", text="Price", anchor=tk.W)
            tree.heading("two", text="About", anchor=tk.W)
            tree.heading("three", text="Category", anchor=tk.W)
            tree.heading("four", text="Image", anchor=tk.W)
            tree.heading("five", text="Discount", anchor=tk.W)
            tree.pack()
            for i in range(len(foods)):
                tree.insert("",
                            i + 1,
                            text=foods[i][3],
                            values=(foods[i][1], foods[i][2],
                                    mydb.showCategoryName(foods[i][6])[0][0],
                                    foods[i][5], foods[i][4]))
            tree.bind("<Double-1>",
                      partial(self.OnDoubleClickOnFood, tree, foods))

        ######################################
        ######################################
        ######################################
        #LAST FOOD FORM THIS RESTURANT
        ######################################
        ######################################
        ######################################
        last_foods = mydb.showOrderByShop(self.user_id, resturant_id)
        last_foods = list(dict.fromkeys(last_foods))
        # print (last_foods)
        Label(self.menu_screen,
              text="Last orders from this resturant",
              bg="red",
              width="300",
              height="2",
              font=("Calibri", 13)).pack()
        Label(text="").pack()
        tree = Treeview(self.menu_screen, style="mystyle.Treeview")
        tree["columns"] = ("one", "two", "three", "four", "five")
        #set tree columns
        tree.column("#0", width=150, minwidth=150, stretch=tk.NO)
        tree.column("one", width=400, minwidth=200)
        tree.column("two", width=80, minwidth=50, stretch=tk.YES)
        tree.column("three", width=80, minwidth=50, stretch=tk.YES)
        tree.column("four", width=80, minwidth=50, stretch=tk.YES)
        tree.column("five", width=80, minwidth=50, stretch=tk.YES)
        #set tree's heading
        tree.heading("#0", text="Name", anchor=tk.W)
        tree.heading("one", text="Price", anchor=tk.W)
        tree.heading("two", text="About", anchor=tk.W)
        tree.heading("three", text="Category", anchor=tk.W)
        tree.heading("four", text="Image", anchor=tk.W)
        tree.heading("five", text="Discount", anchor=tk.W)
        tree.pack()
        for i in range(len(last_foods)):
            tree.insert("",
                        i + 1,
                        text=last_foods[i][3],
                        values=(last_foods[i][1], last_foods[i][2],
                                mydb.showCategoryName(last_foods[i][6])[0][0],
                                last_foods[i][5], last_foods[i][4]))
        tree.bind("<Double-1>",
                  partial(self.OnDoubleClickOnFood, tree, last_foods))
Exemple #30
0
class DialogOpenArchive(Toplevel):
    def __init__(self, parent, openType, filesource, filenames, title, colHeader, showAltViewButton=False):
        if isinstance(parent, Cntlr):
            cntlr = parent
            parent = parent.parent # parent is cntlrWinMain
        else: # parent is a Toplevel dialog
            cntlr = parent.cntlr
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        
        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.treeView.focus_set()
        
        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                ''' take first for now
                if len(metadataFiles) != 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                '''
                metadataFile = metadataFiles[0]
                metadata = filesource.url + os.sep + metadataFile
                self.metadataFilePrefix = os.sep.join(os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += "/"  # zip contents have /, never \ file seps
                self.taxonomyPkgMetaInf = '{}/META-INF/'.format(
                            os.path.splitext(os.path.basename(filesource.url))[0])

        
                self.taxonomyPackage = parsePackage(cntlr, filesource, metadata,
                                                    os.sep.join(os.path.split(metadata)[:-1]) + os.sep)
                
                
                if self.taxonomyPackage["entryPoints"]:
                    # may have instance documents too
                    self.packageContainedInstances = []
                    packageContentTypeCounts = {}
                    for suffix in (".xhtml", ".htm", ".html"):
                        for potentialInstance in filesource.dir:
                            if potentialInstance.endswith(".xhtml"):
                                _type = "Inline Instance"
                                self.packageContainedInstances.append([potentialInstance, _type])
                                packageContentTypeCounts[potentialInstance] = packageContentTypeCounts.get(potentialInstance, 0) + 1
                        if self.packageContainedInstances:
                            break 
                    if self.packageContainedInstances: # add sequences to any duplicated entry types
                        for _type, count in packageContentTypeCounts.items():
                            if count > 1:
                                _dupNo = 0
                                for i in range(len(self.packageContainedInstances)):
                                    if self.packageContainedInstances[i][0] == _type:
                                        _dupNo += 1
                                        self.packageContainedInstances[i][0] = "{} {}".format(_type, _dupNo)
                                    
                else:
                    # may be a catalog file with no entry oint names
                    openType = ARCHIVE  # no entry points to show, just archive
                    self.showAltViewButton = False
            except Exception as e:
                self.close()
                err = _("Failed to parse metadata; the underlying error was: {0}").format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                cntlr.addToLog(err)
                return
    
        if openType not in (PLUGIN, PACKAGE):
            cntlr.showStatus(None)
        
        if openType in (DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S,E,W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S,E,W), pady=3, padx=3)
        
        if self.showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y, column=0, sticky=(S,W), pady=3, padx=3)
        
        self.loadTreeView(openType, colHeader, title)

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=640, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        
        self.wait_window(self)

    
        
        
    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""): 
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
            if openType in (PLUGIN, PACKAGE): width = 770
            else: width = 500
            self.treeView.column("#0", width=width, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            self.isRss = getattr(self.filesource, "isRss", False)
            if self.isRss:
                self.treeView.column("#0", width=350, anchor="w")
                self.treeView["columns"] = ("descr", "date", "instDoc")
                self.treeView.column("descr", width=50, anchor="center", stretch=False)
                self.treeView.heading("descr", text="Form")
                self.treeView.column("date", width=170, anchor="w", stretch=False)
                self.treeView.heading("date", text="Pub Date")
                self.treeView.column("instDoc", width=200, anchor="w", stretch=False)
                self.treeView.heading("instDoc", text="Instance Document")
            elif openType == PLUGIN:
                self.treeView.column("#0", width=150, anchor="w")
                self.treeView["columns"] = ("name", "vers", "descr", "license")
                self.treeView.column("name", width=150, anchor="w", stretch=False)
                self.treeView.heading("name", text="Name")
                self.treeView.column("vers", width=60, anchor="w", stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr", width=300, anchor="w", stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license", width=60, anchor="w", stretch=False)
                self.treeView.heading("license", text="License")
            elif openType == PACKAGE:
                self.treeView.column("#0", width=200, anchor="w")
                self.treeView["columns"] = ("vers", "descr", "license")
                self.treeView.column("vers", width=100, anchor="w", stretch=False)
                self.treeView.heading("vers", text="Version")
                self.treeView.column("descr", width=400, anchor="w", stretch=False)
                self.treeView.heading("descr", text="Description")
                self.treeView.column("license", width=70, anchor="w", stretch=False)
                self.treeView.heading("license", text="License")
            else:
                self.treeView["columns"] = tuple()
        
            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename,tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    elif openType == PLUGIN:
                        name, vers, descr, license = filename[3:7]
                    elif openType == PACKAGE:
                        vers, descr, license = filename[3:6]
                    filename = filename[0] # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = "" 
                node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc", os.path.basename(instDoc))
                elif openType == PLUGIN:
                    self.treeView.set(node, "name", name)
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                elif openType == PACKAGE:
                    self.treeView.set(node, "vers", vers)
                    self.treeView.set(node, "descr", descr)
                    self.treeView.set(node, "license", license)
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=200, anchor="w")
            self.treeView.heading("#0", text="Name")
    
            self.treeView["columns"] = ("url",)
            self.treeView.column("url", width=300, anchor="w")
            self.treeView.heading("url", text="URL")
            
            for fileType, fileUrl in getattr(self, "packageContainedInstances", ()):
                self.treeView.insert("", "end", fileUrl, 
                                     values=fileType, 
                                     text=fileUrl or urls[0][2])
            for name, urls in sorted(self.taxonomyPackage["entryPoints"].items(), key=lambda i:i[0][2]):
                self.treeView.insert("", "end", name, 
                                     values="\n".join(url[1] for url in urls), 
                                     text=name or urls[0][2])
                
            self.hasToolTip = True
        else: # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType == ENTRY_POINTS else _("Show Entries"))

        
    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if hasattr(self, "taxonomyPackage"):
                # load file source remappings
                self.filesource.mappedPaths = self.taxonomyPackage["remappings"]
            filename = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename,tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                # Greg Acsone reports [0] does not work for Corep 1.6 pkgs, need [1], old style packages
                filenames = []
                for _url, _type in self.packageContainedInstances: # check if selection was an inline instance
                    if _type == epName:
                        filenames.append(_url)
                if not filenames: # else if it's a named taxonomy entry point
                    for url in self.taxonomyPackage["entryPoints"][epName]:
                        filename = url[0]
                        if not filename.endswith("/"):
                            # check if it's an absolute URL rather than a path into the archive
                            if not isHttpUrl(filename) and self.metadataFilePrefix != self.taxonomyPkgMetaInf:
                                # assume it's a path inside the archive:
                                filename = self.metadataFilePrefix + filename
                        filenames.append(filename)
                if filenames:
                    self.filesource.select(filenames)
                    self.accepted = True
                    self.close()
                return
            elif self.openType in (PLUGIN, PACKAGE):
                filename = self.filenames[int(selection[0][4:])][2]
            if filename is not None and not filename.endswith("/"):
                if hasattr(self, "taxonomyPackage"):
                    # attempt to unmap the filename to original file
                    # will be mapped again in loading, but this allows schemaLocation to be unmapped
                    for prefix, remapping in self.taxonomyPackage["remappings"].items():
                        if isHttpUrl(remapping):
                            remapStart = remapping
                        else:
                            remapStart = self.metadataFilePrefix + remapping
                        if filename.startswith(remapStart):
                            # set unmmapped file
                            filename = prefix + filename[len(remapStart):]
                            break
                if self.openType in (PLUGIN, PACKAGE):
                    self.filesource.selection = filename
                else:
                    self.filesource.select(filename)
                self.accepted = True
                self.close()
                        
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
        
    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"), _("File"))
        
    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM, PLUGIN, PACKAGE):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[ int(tvRowId[4:]) ]
                        if isinstance(text, tuple):
                            text = (text[1] or "").replace("\\n","\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    text = "{0}\n{1}".format(tvRowId, 
                             "\n".join(url[1] for url in self.taxonomyPackage["entryPoints"][tvRowId]))
                except KeyError:
                    pass
            self.setToolTip(text)
                
    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
class DialogPackageManager(Toplevel):
    def __init__(self, mainWin, packageNamesWithNewerFileDates):
        super(DialogPackageManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.packagesConfig = PackageManager.packagesConfig
        self.packagesConfigChanged = False
        self.packageNamesWithNewerFileDates = packageNamesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Taxonomy Packages Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find taxonomy packages:"), wraplength=64, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting taxonomy packages to add (or reload), from the local file system.  "
                                       "Select either a taxonomy package zip file, or a taxonomy manifest (.taxonomyPackage.xml) within an unzipped taxonomy package.  "), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) package, from the web or local file system.  "
                                     "URL may be either a taxonomy package zip file, or a taxonomy manifest (.taxonomyPackage.xml) within an unzipped taxonomy package.  "), wraplength=240)
        manifestNameButton = Button(buttonFrame, text=_("Manifest"), command=self.manifestName)
        ToolTip(manifestNameButton, text=_("Provide non-standard archive manifest file name pattern (e.g., *taxonomyPackage.xml).  "
                                           "Uses unix file name pattern matching.  "
                                           "Multiple manifest files are supported in archive (such as oasis catalogs).  "
                                           "(Replaces search for either .taxonomyPackage.xml or catalog.xml).  "), wraplength=240)
        self.manifestNamePattern = ""
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        manifestNameButton.grid(row=3, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=3, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (packages already known to arelle)
        packagesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(packagesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(packagesFrame, orient=HORIZONTAL)
        self.packagesView = Treeview(packagesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.packagesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.packagesView.bind('<<TreeviewSelect>>', self.packageSelect)
        hScrollbar["command"] = self.packagesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.packagesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        packagesFrame.columnconfigure(0, weight=1)
        packagesFrame.rowconfigure(0, weight=1)
        packagesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.packagesView.focus_set()

        self.packagesView.column("#0", width=120, anchor="w")
        self.packagesView.heading("#0", text=_("Name"))
        self.packagesView["columns"] = ("ver", "status", "date", "update", "descr")
        self.packagesView.column("ver", width=150, anchor="w", stretch=False)
        self.packagesView.heading("ver", text=_("Version"))
        self.packagesView.column("status", width=50, anchor="w", stretch=False)
        self.packagesView.heading("status", text=_("Status"))
        self.packagesView.column("date", width=170, anchor="w", stretch=False)
        self.packagesView.heading("date", text=_("File Date"))
        self.packagesView.column("update", width=50, anchor="w", stretch=False)
        self.packagesView.heading("update", text=_("Update"))
        self.packagesView.column("descr", width=200, anchor="w", stretch=False)
        self.packagesView.heading("descr", text=_("Description"))

        remappingsFrame = Frame(frame)
        vScrollbar = Scrollbar(remappingsFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(remappingsFrame, orient=HORIZONTAL)
        self.remappingsView = Treeview(remappingsFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.remappingsView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.remappingsView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.remappingsView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        remappingsFrame.columnconfigure(0, weight=1)
        remappingsFrame.rowconfigure(0, weight=1)
        remappingsFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.remappingsView.focus_set()
        
        self.remappingsView.column("#0", width=200, anchor="w")
        self.remappingsView.heading("#0", text=_("Prefix"))
        self.remappingsView["columns"] = ("remapping")
        self.remappingsView.column("remapping", width=500, anchor="w", stretch=False)
        self.remappingsView.heading("remapping", text=_("Remapping"))
        
        # bottom frame package info details
        packageInfoFrame = Frame(frame, width=700)
        packageInfoFrame.columnconfigure(1, weight=1)
        
        self.packageNameLabel = Label(packageInfoFrame, wraplength=600, justify="left", 
                                      font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.packageNameLabel.grid(row=0, column=0, columnspan=6, sticky=W)
        self.packageVersionHdr = Label(packageInfoFrame, text=_("version:"), state=DISABLED)
        self.packageVersionHdr.grid(row=1, column=0, sticky=W)
        self.packageVersionLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageVersionLabel.grid(row=1, column=1, columnspan=5, sticky=W)
        self.packageDescrHdr = Label(packageInfoFrame, text=_("description:"), state=DISABLED)
        self.packageDescrHdr.grid(row=2, column=0, sticky=W)
        self.packageDescrLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageDescrLabel.grid(row=2, column=1, columnspan=5, sticky=W)
        self.packagePrefixesHdr = Label(packageInfoFrame, text=_("prefixes:"), state=DISABLED)
        self.packagePrefixesHdr.grid(row=3, column=0, sticky=W)
        self.packagePrefixesLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packagePrefixesLabel.grid(row=3, column=1, columnspan=5, sticky=W)
        ToolTip(self.packagePrefixesLabel, text=_("List of prefixes that this package remaps."), wraplength=240)
        self.packageUrlHdr = Label(packageInfoFrame, text=_("URL:"), state=DISABLED)
        self.packageUrlHdr.grid(row=4, column=0, sticky=W)
        self.packageUrlLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageUrlLabel.grid(row=4, column=1, columnspan=5, sticky=W)
        ToolTip(self.packageUrlLabel, text=_("URL of taxonomy package (local file path or web loaded file)."), wraplength=240)
        self.packageDateHdr = Label(packageInfoFrame, text=_("date:"), state=DISABLED)
        self.packageDateHdr.grid(row=5, column=0, sticky=W)
        self.packageDateLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageDateLabel.grid(row=5, column=1, columnspan=5, sticky=W)
        ToolTip(self.packageDateLabel, text=_("Date of currently loaded package file (with parenthetical node when an update is available)."), wraplength=240)
        self.packageEnableButton = Button(packageInfoFrame, text=self.ENABLE, state=DISABLED, command=self.packageEnable)
        ToolTip(self.packageEnableButton, text=_("Enable/disable package."), wraplength=240)
        self.packageEnableButton.grid(row=6, column=1, sticky=E)
        self.packageMoveUpButton = Button(packageInfoFrame, text=_("Move Up"), state=DISABLED, command=self.packageMoveUp)
        ToolTip(self.packageMoveUpButton, text=_("Move package up (above other remappings)."), wraplength=240)
        self.packageMoveUpButton.grid(row=6, column=2, sticky=E)
        self.packageMoveDownButton = Button(packageInfoFrame, text=_("Move Down"), state=DISABLED, command=self.packageMoveDown)
        ToolTip(self.packageMoveDownButton, text=_("Move package down (below other remappings)."), wraplength=240)
        self.packageMoveDownButton.grid(row=6, column=3, sticky=E)
        self.packageReloadButton = Button(packageInfoFrame, text=_("Reload"), state=DISABLED, command=self.packageReload)
        ToolTip(self.packageReloadButton, text=_("Reload/update package."), wraplength=240)
        self.packageReloadButton.grid(row=6, column=4, sticky=E)
        self.packageRemoveButton = Button(packageInfoFrame, text=_("Remove"), state=DISABLED, command=self.packageRemove)
        ToolTip(self.packageRemoveButton, text=_("Remove package from packages table (does not erase the package file)."), wraplength=240)
        self.packageRemoveButton.grid(row=6, column=5, sticky=E)
        packageInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        packageInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        self.loadTreeViews()

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.packagesView.get_children(""): 
            self.packagesView.delete(previousNode)

        for i, packageInfo in enumerate(self.packagesConfig.get("packages", [])):
            name = packageInfo.get("name", "package{}".format(i))
            node = self.packagesView.insert("", "end", "_{}".format(i), text=name)
            self.packagesView.set(node, "ver", packageInfo.get("version"))
            self.packagesView.set(node, "status", packageInfo.get("status"))
            self.packagesView.set(node, "date", packageInfo.get("fileDate"))
            if name in self.packageNamesWithNewerFileDates:
                self.packagesView.set(node, "update", _("available"))
            self.packagesView.set(node, "descr", packageInfo.get("description"))
        
        # clear previous treeview entries
        for previousNode in self.remappingsView.get_children(""): 
            self.remappingsView.delete(previousNode)

        for i, remappingItem in enumerate(sorted(self.packagesConfig.get("remappings", {}).items())):
            prefix, remapping = remappingItem
            node = self.remappingsView.insert("", "end", prefix, text=prefix)
            self.remappingsView.set(node, "remapping", remapping)
            
        self.packageSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.packagesConfigChanged:
            PackageManager.packagesConfig = self.packagesConfig
            PackageManager.packagesConfigChanged = True
            self.cntlr.onPackageEnablementChanged()
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def packageSelect(self, *args):
        node = (self.packagesView.selection() or (None,))[0]
        try:
            nodeIndex = int(node[1:])
        except (ValueError, TypeError):
            nodeIndex = -1
        if 0 <= nodeIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][nodeIndex]
            self.selectedPackageIndex = nodeIndex
            name = packageInfo["name"]
            self.packageNameLabel.config(text=name)
            self.packageVersionHdr.config(state=ACTIVE)
            self.packageVersionLabel.config(text=packageInfo["version"])
            self.packageDescrHdr.config(state=ACTIVE)
            self.packageDescrLabel.config(text=packageInfo["description"])
            self.packagePrefixesHdr.config(state=ACTIVE)
            self.packagePrefixesLabel.config(text=', '.join(packageInfo["remappings"].keys()))
            self.packageUrlHdr.config(state=ACTIVE)
            self.packageUrlLabel.config(text=packageInfo["URL"])
            self.packageDateHdr.config(state=ACTIVE)
            self.packageDateLabel.config(text=packageInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.packageNamesWithNewerFileDates else ""))
            self.packageEnableButton.config(state=ACTIVE,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[packageInfo["status"]])
            self.packageMoveUpButton.config(state=ACTIVE if 0 < nodeIndex else DISABLED)
            self.packageMoveDownButton.config(state=ACTIVE if nodeIndex < (len(self.packagesConfig["packages"]) - 1) else DISABLED)
            self.packageReloadButton.config(state=ACTIVE)
            self.packageRemoveButton.config(state=ACTIVE)
        else:
            self.selectedPackageIndex = -1
            self.packageNameLabel.config(text="")
            self.packageVersionHdr.config(state=DISABLED)
            self.packageVersionLabel.config(text="")
            self.packageDescrHdr.config(state=DISABLED)
            self.packageDescrLabel.config(text="")
            self.packagePrefixesHdr.config(state=DISABLED)
            self.packagePrefixesLabel.config(text="")
            self.packageUrlHdr.config(state=DISABLED)
            self.packageUrlLabel.config(text="")
            self.packageDateHdr.config(state=DISABLED)
            self.packageDateLabel.config(text="")

            self.packageEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.packageMoveUpButton.config(state=DISABLED)
            self.packageMoveDownButton.config(state=DISABLED)
            self.packageReloadButton.config(state=DISABLED)
            self.packageRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        initialdir = self.cntlr.pluginDir # default plugin directory
        if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory
            initialdir = self.cntlr.config.setdefault("packageOpenDir", initialdir)
        filename = self.cntlr.uiFileDialog("open",
                                           parent=self,
                                           title=_("Choose taxonomy package file"),
                                           initialdir=initialdir,
                                           filetypes=[(_("Taxonomy package files (*.zip)"), "*.zip"),
                                                      (_("Manifest (*.taxonomyPackage.xml)"), "*.taxonomyPackage.xml"),
                                                      (_("Oasis Catalog (*catalog.xml)"), "*catalog.xml")],
                                           defaultextension=".zip")
        if filename:
            # check if a package is selected (any file in a directory containing an __init__.py
            self.cntlr.config["packageOpenDir"] = os.path.dirname(filename)
            packageInfo = PackageManager.packageInfo(filename, packageManifestName=self.manifestNamePattern)
            self.loadFoundPackageInfo(packageInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            packageInfo = PackageManager.packageInfo(url, packageManifestName=self.manifestNamePattern)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundPackageInfo(packageInfo, url)
                
    def manifestName(self):
        self.manifestNamePattern = simpledialog.askstring(_("Archive manifest file name pattern"),
                                                          _("Provide non-standard archive manifest file name pattern (e.g., *taxonomyPackage.xml).  \n"
                                                            "Uses unix file name pattern matching.  \n"
                                                            "Multiple manifest files are supported in archive (such as oasis catalogs).  \n"
                                                            "(If blank, search for either .taxonomyPackage.xml or catalog.xml).  "),
                                                          initialvalue=self.manifestNamePattern,
                                                          parent=self)
                
    def loadFoundPackageInfo(self, packageInfo, url):
        if packageInfo and packageInfo.get("name"):
            self.addPackageInfo(packageInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Package is not itself a taxonomy package.  "),
                                   _("File does not itself contain a manifest file: \n\n{0}\n\n  "
                                     "If opening an archive file, the manifest file search pattern currently is \"\", please press \"Manifest\" to change manifest file name pattern, e.g.,, \"*.taxonomyPackage.xml\", if needed.  ")
                                   .format(url),
                                   parent=self)
            
    def removePackageInfo(self, name, version):
        # find package entry
        packagesList = self.packagesConfig["packages"]
        j = -1
        for i, packageInfo in enumerate(packagesList):
            if packageInfo['name'] == name and packageInfo['version'] == version:
                j = i
                break
        if 0 <= j < len(packagesList):
            del self.packagesConfig["packages"][i]
            self.packagesConfigChanged = True

    def addPackageInfo(self, packageInfo):
        name = packageInfo["name"]
        version = packageInfo["version"]
        self.removePackageInfo(name, version)  # remove any prior entry for this package
        self.packageNamesWithNewerFileDates.discard(name) # no longer has an update available
        self.packagesConfig["packages"].append(packageInfo)
        PackageManager.rebuildRemappings()
        self.packagesConfigChanged = True

    def packageEnable(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex]
            if self.packageEnableButton['text'] == self.ENABLE:
                packageInfo["status"] = "enabled"
                self.packageEnableButton['text'] = self.DISABLE
            elif self.packageEnableButton['text'] == self.DISABLE:
                packageInfo["status"] = "disabled"
                self.packageEnableButton['text'] = self.ENABLE
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
            
    def packageMoveUp(self):
        if 1 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packages = self.packagesConfig["packages"]
            packageInfo = packages[self.selectedPackageIndex]
            del packages[self.selectedPackageIndex]
            packages.insert(self.selectedPackageIndex -1, packageInfo)
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
            
    def packageMoveDown(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]) - 1:
            packages = self.packagesConfig["packages"]
            packageInfo = packages[self.selectedPackageIndex]
            del packages[self.selectedPackageIndex]
            packages.insert(self.selectedPackageIndex + 1, packageInfo)
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
            
    def packageReload(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex]
            url = packageInfo.get("URL")
            if url:
                packageInfo = PackageManager.packageInfo(url, reload=True, packageManifestName=packageInfo.get("manifestName"))
                if packageInfo:
                    self.addPackageInfo(packageInfo)
                    PackageManager.rebuildRemappings()
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(packageInfo.get("name")), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Package error"),
                                           _("File or package cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def packageRemove(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex]
            self.removePackageInfo(packageInfo["name"], packageInfo["version"])
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
Exemple #32
0
class ReplayTutor2(Tutor):
    """
    ReplayTutor:  a tutor for testing/backup purposes, that re-sends messages to plugins.
    """
    def __init__(self, entity_id, api_key, logger, run_once=None, args=None):
        super().__init__(entity_id, api_key, self.main_callback, run_once=run_once)
        self.run_once = run_once
        self.logger = logger
        
        self.student_id_value = None
        self.session_id_value = None
        
        self.root = None
        self.status = None
        self.student_id = None
        self.session_id = None
        self.problem_name = None
        self.step_name = None
        self.transaction_id = None
        self.outcome = None
        self.skillbox = None
        self.button = None
        self.import_button = None
        self.kt_button = None
        self.attr_name = None
        self.attr_value = None
        self.attr_button = None
        self.skill_id = None
        self.kt_button = None
        self.response_box = None
        
        self.json_in = None
        
    def post_connect(self):
        self.send("tutorgen.add_student",{},self.new_student_callback)
    
    def setup_gui(self):
        #main window
        self.root = Tk()
        self.root.wm_title("Transaction Replay Tutor")
        self.root.minsize(400,400)
    
        #menu
        menubar = Menu(self.root)
        menubar.add_command(label="Import Datashop File", command=self.import_datashop_file)
        menubar.add_command(label="Quit", command=self.root.quit)
        self.root.config(menu=menubar)
        
        #listbox
        w = Label(self.root, text="Transaction")
        w.pack(fill=X)
        
        frame = Frame()
        scrollbar = Scrollbar(frame, orient=VERTICAL)
        
        self.treeview = Treeview(frame,yscrollcommand=scrollbar.set)
        self.treeview["columns"] = ("problem_name","step_text","transaction_text","skill_names","outcome")
        self.treeview.heading("problem_name",text="Problem Name")
        self.treeview.heading("step_text",text="Step Text")
        self.treeview.heading("transaction_text",text="Transaction Text")
        self.treeview.heading("skill_names",text="Skill Names")
        self.treeview.heading("outcome",text="Outcome")
        
        self.treeview.bind('<<TreeviewSelect>>', self.populate_form)
    
        scrollbar.config(command=self.treeview.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        self.treeview.pack(side=LEFT, fill=BOTH, expand=1)
        
        frame.pack(fill=BOTH)
        
        #spacer frame
        separator = Frame(height=2, bd=1, relief=SUNKEN)
        separator.pack(fill=X, padx=5, pady=5)
        
        #student id
        w = Label(self.root, text="Student ID")
        w.pack(fill=X)
        self.student_id = Entry(self.root,state=DISABLED)
        self.student_id.pack(fill=X)
        
        #ssession id
        w = Label(self.root, text="Session ID")
        w.pack(fill=X)
        self.session_id = Entry(self.root,state=DISABLED)
        self.session_id.pack(fill=X)
        
        bigframe = Frame()
        bigframe.pack(fill=X,padx =5, ipady=5)
        leftframe = Frame(bigframe)
        leftframe.pack(side=LEFT,fill=X,expand=1)
        rightframe= Frame(bigframe)
        rightframe.pack(side=RIGHT,fill=X,expand=1)
        
        #Entry fields
        ##problem name
        w = Label(leftframe, text="Problem Name")
        w.pack(fill=X)
        self.problem_name = Entry(leftframe)
        self.problem_name.pack(fill=X)
        
        ##step name
        w = Label(leftframe, text="Step Name")
        w.pack(fill=X)
        self.step_name = Entry(leftframe)
        self.step_name.pack(fill=X)
        
        ##Transaction ID
        w = Label(leftframe, text="Transaction ID")
        w.pack(fill=X)
        self.transaction_id = Entry(leftframe)
        self.transaction_id.pack(fill=X)
        
        ##Outcome
        w = Label(leftframe, text="Outcome")
        w.pack(fill=X)
        self.outcome = Entry(leftframe)
        self.outcome.pack(fill=X)
        
        ##skill names
        w = Label(rightframe, text="Skill Models and Names")
        w.pack(fill=X)
        self.skillbox = Text(rightframe,height=8)
        self.skillbox.pack()
        
        #Submit button
        self.button = Button(self.root, text="Send", command=self.submit_transaction, state=DISABLED)
        self.button.pack()

        #Load button
        self.import_button = Button(self.root, text="Import", command=self.import_datashop_file)
        self.import_button.pack()

        #spacer frame
        separator = Frame(height=2, bd=1, relief=SUNKEN)
        separator.pack(fill=X, padx=5, pady=5)
        
        bigframe = Frame()
        bigframe.pack(fill=X)
        leftframe = Frame(bigframe,bd=1)
        leftframe.pack(side=LEFT,expand=1, padx =5, ipady=5)
        rightframe= Frame(bigframe,bd=1)
        rightframe.pack(side=RIGHT,expand=1, padx =5, ipady=5)
        
        #student attribute
        w = Label(leftframe, text="Student Attribute")
        w.pack(fill=X)
        self.attr_name = Entry(leftframe)
        self.attr_name.pack(fill=X)
        
        w = Label(leftframe, text="Value")
        w.pack(fill=X)
        self.attr_value = Entry(leftframe)
        self.attr_value.pack(fill=X)
        
        self.attr_button = Button(leftframe, text="Set", command=self.set_attribute, state=DISABLED)
        self.attr_button.pack()
        
        b = Button(leftframe, text="Get", command=self.get_attribute)
        b.pack()
        
        b = Button(leftframe, text="Add Problem", command=self.add_problem)
        b.pack()
        
        #kt_trace
        w = Label(rightframe, text="Skill ID")
        w.pack(fill=X)
        self.skill_id = Entry(rightframe)
        self.skill_id.pack(fill=X)
        
        self.kt_button = Button(rightframe, text="Trace", command=self.kt_trace, state=DISABLED)
        self.kt_button.pack()
        
        b = Button(rightframe, text="Reset", command=self.kt_reset)
        b.pack()
        
        #response box
        w = Label(self.root, text="Responses")
        w.pack(fill=X)
        self.response_box = Text(height=8)
        self.response_box.pack()
        
        #status
        self.status = Label(text="Status: Idle", bd=1, relief=SUNKEN, anchor=W)
        self.status.pack(side=BOTTOM, fill=X)
    
    def main_loop(self):
        
        again = True
        
        
        if not self.callback():
            again = False

        responses = self._poll_responses()

        if not self._dispatch_responses(responses):
            again = False

        if again:
            self.root.after(self.poll_wait, self.main_loop)
        else:
            raise Exception("Error in main loop")
    
    def import_datashop_file(self):
        
        filename = filedialog.askopenfilename()
        
        with open(filename,"r") as filein:
            header_line = filein.readline()
            headers = header_line.split("\t")
        
        filelen = file_len(filename)       
        count =0
        
        with open(filename,"r") as filein:
            filein.readline() #skip header line
            while 1:
                line = filein.readline()
                if not line:
                    break
                
                rt.status.config(text="Status: Importing Datashop file... " + str(count) + " / " + str(filelen))
                rt.status.update_idletasks()
                
                count+=1
                
                values = line.split("\t")
                transaction = dict(zip(headers,values))
                
                skills = get_skills(transaction)
                
                #("problem_name","step_text","transaction_text","skill_names","outcome")
                rt.treeview.insert("","end",text= "Transaction", values=(transaction["Problem Name"],transaction["Step Name"],transaction["Transaction Id"],json.dumps(skills),transaction["Outcome"]))
        
        rt.status.config(text="Status: Idle")
        rt.status.update_idletasks()
        
        print("file " + filename)
    def add_problem(self):
        mid = self.send("tutorgen.add_problem",{
            "problem_name":"some problem",
            "problem_text":"some problem text",
        }, self.transaction_response_callback)
        
        print(str(mid) + str(datetime.now()))
        
    def kt_trace(self):
        correct=False
        if self.outcome.get().lower() == "correct":
            correct = True
            
        mid = self.send("tutorgen.kt_trace",{
            "student_id":self.student_id.get(),
            "correct":correct,
            "skill_id":self.skill_id.get(),
        }, self.transaction_response_callback)
        
        print(str(mid) + str(datetime.now()))
        
    def kt_reset(self):
        mid = self.send("tutorgen.kt_reset",{
            "student_id":self.student_id.get(),
            "skill_id":self.skill_id.get(),
        }, self.transaction_response_callback)
        
        print(str(mid) + str(datetime.now()))
    
    def set_attribute(self):
        mid = self.send("tutorgen.set_attribute",{
            "student_id":self.student_id.get(),
            "attribute_name":self.attr_name.get(),
            "attribute_value":self.attr_value.get(),
        }, self.transaction_response_callback)
        self.attr_name.delete(0,END)
        self.attr_value.delete(0,END)
        
        print(str(mid) + str(datetime.now()))
        
    def get_attribute(self):
        mid = self.send("tutorgen.get_attribute",{
            "student_id":self.student_id.get(),
            "attribute_name":self.attr_name.get(),
        }, self.transaction_response_callback)
        
        print(str(mid) + str(datetime.now()))
    
    def populate_form(self,evt):
        w = evt.widget
        item = w.selection()[0]
        values = w.item(item)["values"]

        self.problem_name.delete(0,END)
        self.problem_name.insert(INSERT,values[0])
        
        self.step_name.delete(0,END)
        self.step_name.insert(INSERT,values[1])
        
        self.transaction_id.delete(0,END)
        self.transaction_id.insert(INSERT,values[2])
        
        self.skillbox.delete("0.0",END)
        self.json_in = json.loads(values[3]) #save for later
        json_out = json.dumps(self.json_in, sort_keys=True,indent=4, separators=(',', ': '))
        self.skillbox.insert("0.0",json_out)
        
        self.outcome.delete(0,END)
        self.outcome.insert(INSERT,values[4])
       
    def new_student_callback(self,response):
        self.student_id_value = response["student_id"]
        self.session_id_value = response["session_id"]

        self.student_id.config(state=NORMAL)
        self.student_id.insert(INSERT,str(self.student_id_value))

        self.session_id.config(state=NORMAL)
        self.session_id.insert(INSERT,str(self.session_id_value))
        
        self.button.config(state=NORMAL)
        self.import_button.config(state=NORMAL)
        self.attr_button.config(state=NORMAL)
        self.kt_button.config(state=NORMAL)
    
    def transaction_response_callback(self,response):         
        #messagebox.showinfo("info", "Got a response: " + json.dumps(response, sort_keys=True,indent=4, separators=(',', ': ')))
        self.response_box.insert(END,"\n==========================================")
        self.response_box.insert(END,json.dumps(response, sort_keys=True,indent=4, separators=(',', ': ')))
        
    def submit_transaction(self):
        
        skill_ids = {}
        skill_names = {}
        for skill_model, skill_name in self.json_in.items():
            skill_ids[skill_name] = ""
            skill_names[skill_model] = skill_name
        transaction = {
            "problem_name":self.problem_name.get(),
            "step_text":self.step_name.get(),
            "transaction_text":self.transaction_id.get(),
            "session_id":self.session_id.get(),
            'skill_ids': skill_ids,
            'skill_names': skill_names,
            'student_id':self.student_id.get(),
            'outcome': self.outcome.get(),
            }
        print(transaction)
        self.send_transaction(transaction, self.transaction_response_callback)
    
    def main_callback(self):
        return True
class ElementListWidget(Frame):
	def __init__(self, parent, label, columns, showError):
		Frame.__init__(self, parent)
		
		self.showError = showError
		
		self.columnconfigure(0, weight = 1)
		self.rowconfigure(1, weight = 1)
		
		
		# Название таблицы
		self.titleLabel = Label(self, text = label)
		self.titleLabel.grid(column = 0, row = 0, sticky = W + E)
		
		
		# Таблица значений
		columns = ("Метка", "№") + columns
		self.tree = Treeview(self, columns = columns, displaycolumns = columns,
							 selectmode = "browse")
		self.tree.grid(column = 0, row = 1, sticky = W + N + E + S)
		
		# Настраиваем внешний вид таблицы (первые колонки)
		self.tree.column("#0", width = 0, stretch = 0)	# Прячем колонку с иконкой
		
		self.tree.column( columns[0], anchor = W, width = 150)
		self.tree.heading(columns[0], anchor = W, text = columns[0])
		
		self.tree.column( columns[1], anchor = E, width = 80)
		self.tree.heading(columns[1], anchor = E, text = columns[1])
		
		self.tree.bind("<<TreeviewSelect>>", self.onSelectionChanged)
		
		
		# Панель с кнопками
		self.buttonPanel = Frame(self)
		self.buttonPanel.grid(column = 0, row = 2, sticky = W + E)
		
		self.buttonPanel.columnconfigure(0, weight = 1)
		self.buttonPanel.columnconfigure(3, minsize = emptySpaceSize, weight = 0)
		self.buttonPanel.columnconfigure(6, minsize = emptySpaceSize, weight = 0)
		self.buttonPanel.columnconfigure(9, weight = 1)
		
		# Кнопки добавления/удаления элемента
		self.buttonAdd = Button(self.buttonPanel, text = "+", width = 3,
								command = self.onButtonAddClicked)
		self.buttonAdd.grid(column = 1, row = 0)
		
		self.buttonRemove = Button(self.buttonPanel, text = "-", width = 3, state = DISABLED,
								   command = self.onButtonRemoveClicked)
		self.buttonRemove.grid(column = 2, row = 0)
		
		# Кнопки перемещения элемента
		self.buttonUp = Button(self.buttonPanel, text = "↑", width = 3, state = DISABLED,
							   command = self.onButtonUpClicked)
		self.buttonUp.grid(column = 4, row = 0)
		
		self.buttonDown = Button(self.buttonPanel, text = "↓", width = 3, state = DISABLED,
								 command = self.onButtonDownClicked)
		self.buttonDown.grid(column = 5, row = 0)
		
		# Кнопки применить/отменить (для выбранного элемента)
		self.buttonCancel = Button(self.buttonPanel, text = "✗", width = 3,
								   command = self.updateSelectedFrame)
		self.buttonCancel.grid(column = 7, row = 0)
		
		self.buttonApply = Button(self.buttonPanel, text = "✓", width = 3,
								  command = self.onButtonApplyClicked)
		self.buttonApply.grid(column = 8, row = 0)
		
		
		# Редактирование выделенного элемента
		self.i     = StringVar()
		self.label = (StringVar(), StringVar())
		
		self.selectedFrame = Frame(self)
		self.selectedFrame.grid(column = 0, row = 3, sticky = W + E)
		
		# Номер
		Label(self.selectedFrame, text = "№:") \
			.grid(column = 0, row = 0)
		Label(self.selectedFrame, textvariable = self.i, width = 3, justify = RIGHT) \
			.grid(column = 1, row = 0)
		
		# Пустое пространство
		self.selectedFrame.columnconfigure(2, minsize = emptySpaceSize, weight = 0)
		
		# Метка
		Entry(self.selectedFrame, textvariable = self.label[0]) \
			.grid(column = 3, row = 0, sticky = W + E)
		
		Entry(self.selectedFrame, textvariable = self.label[1], bg = defaultValueBG) \
			.grid(column = 4, row = 0, sticky = W + E)
		
		# Виджет для элементов классов-потомков
		self.detailFrame = Frame(self.selectedFrame)
		self.detailFrame.grid(column = 3, row = 1, columnspan = 2, sticky = W + N + E + S)
		
		self.selectedFrame.columnconfigure(3, weight = 1)
		self.selectedFrame.columnconfigure(4, weight = 1)
		self.selectedFrame.rowconfigure(1, weight = 1)
	
	
	def onButtonUpClicked(self):
		item = self.selectedItem()
		if item is None: return
		
		prev = self.tree.prev(item)
		if prev != "":
			parent, index = self.tree.parent(item), self.tree.index(item)
			self.tree.move(item, parent, index - 1)
			
			# Корректируем номера элементов
			self.tree.set(item, "№", index - 1)
			self.tree.set(prev, "№", index)
			
			self.updateSelectedFrame(item)
	
	
	def onButtonDownClicked(self):
		item = self.selectedItem()
		if item is None: return
		
		next = self.tree.next(item)
		if next != "":
			parent, index = self.tree.parent(item), self.tree.index(item)
			self.tree.move(item, parent, index + 1)
			
			# Корректируем номера элементов
			self.tree.set(item, "№", index + 1)
			self.tree.set(next, "№", index)
			
			self.updateSelectedFrame(item)
	
	
	def onButtonAddClicked(self):
		pass
	
	
	def onButtonRemoveClicked(self):
		item = self.selectedItem()
		if item is None: return
		
		next = self.tree.next(item)
		self.tree.delete(item)
		
		while next != "":
			i = int(self.tree.set(next, "№"))
			self.tree.set(next, "№", i - 1)
			next = self.tree.next(next)
		
		self.onSelectionChanged()
	
	
	def onButtonApplyClicked(self, item = None):
		if item is None: item = self.selectedItem()
		if item is None: return None
		
		label = self.label[0].get()
		self.tree.set(item, "Метка", label)
		
		return item
	
	
	def onSelectionChanged(self, event = None):
		item = self.selectedItem()
		
		# Обновляем состояние кнопок
		state = DISABLED if item is None else NORMAL
		for x in (self.buttonRemove, self.buttonUp, self.buttonDown):
			x["state"] = state
		
		self.updateSelectedFrame(item)
	
	
	def selectedItem(self):
		selection = self.tree.selection()
		return None if type(selection) == type("") else selection[0]
	
	
	def clear(self):
		for item in self.tree.get_children():
			self.tree.delete(item)
	
	
	def updateSelectedFrame(self, item = None, values = None):
		if item is None: item = self.selectedItem()
		values = None
		
		if item is None:
			i     = ""
			label = ""
		else:
			if values is None: values = self.tree.set(item)
			
			i     = values["№"]
			label = values["Метка"]
		
		self.i.set(i)
		self.label[0].set(label)
		
		return (item, values)
	
	
	def addElement(self, values):
		self.tree.insert(parent = "", index = END, values = values)
	
	
	def setDefaultElement(self, label):
		self.label[1].set(label)
	
	
	def elementsCount(self):
		return len(self.tree.get_children())
	
	
	def elements(self, transform):
		return [ transform(item) for item in self.tree.get_children() ]
class DialogPluginManager(Toplevel):
    def __init__(self, mainWin, modulesWithNewerFileDates):
        super(DialogPluginManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.pluginConfig = PluginManager.pluginConfig
        self.pluginConfigChanged = False
        self.uiClassMethodsChanged = False
        self.modulesWithNewerFileDates = modulesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Plug-in Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240)
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (plugins already known to arelle)
        modulesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL)
        self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect)
        hScrollbar["command"] = self.modulesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.modulesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        modulesFrame.columnconfigure(0, weight=1)
        modulesFrame.rowconfigure(0, weight=1)
        modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.modulesView.focus_set()

        self.modulesView.column("#0", width=120, anchor="w")
        self.modulesView.heading("#0", text=_("Name"))
        self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license")
        self.modulesView.column("author", width=100, anchor="w", stretch=False)
        self.modulesView.heading("author", text=_("Author"))
        self.modulesView.column("ver", width=50, anchor="w", stretch=False)
        self.modulesView.heading("ver", text=_("Version"))
        self.modulesView.column("status", width=50, anchor="w", stretch=False)
        self.modulesView.heading("status", text=_("Status"))
        self.modulesView.column("date", width=70, anchor="w", stretch=False)
        self.modulesView.heading("date", text=_("File Date"))
        self.modulesView.column("update", width=50, anchor="w", stretch=False)
        self.modulesView.heading("update", text=_("Update"))
        self.modulesView.column("descr", width=200, anchor="w", stretch=False)
        self.modulesView.heading("descr", text=_("Description"))
        self.modulesView.column("license", width=70, anchor="w", stretch=False)
        self.modulesView.heading("license", text=_("License"))

        classesFrame = Frame(frame)
        vScrollbar = Scrollbar(classesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL)
        self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.classesView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.classesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.classesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        classesFrame.columnconfigure(0, weight=1)
        classesFrame.rowconfigure(0, weight=1)
        classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.classesView.focus_set()
        
        self.classesView.column("#0", width=200, anchor="w")
        self.classesView.heading("#0", text=_("Class"))
        self.classesView["columns"] = ("modules")
        self.classesView.column("modules", width=500, anchor="w", stretch=False)
        self.classesView.heading("modules", text=_("Modules"))
        
        # bottom frame module info details
        moduleInfoFrame = Frame(frame, width=700)
        moduleInfoFrame.columnconfigure(1, weight=1)
        
        self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", 
                                     font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W)
        self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED)
        self.moduleAuthorHdr.grid(row=1, column=0, sticky=W)
        self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W)
        self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED)
        self.moduleDescrHdr.grid(row=2, column=0, sticky=W)
        self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W)
        self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED)
        self.moduleClassesHdr.grid(row=3, column=0, sticky=W)
        self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED)
        self.moduleUrlHdr.grid(row=4, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240)
        self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED)
        self.moduleDateHdr.grid(row=5, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240)
        self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED)
        self.moduleLicenseHdr.grid(row=6, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W)
        self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable)
        ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240)
        self.moduleEnableButton.grid(row=7, column=1, sticky=E)
        self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload)
        ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240)
        self.moduleReloadButton.grid(row=7, column=2, sticky=E)
        self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove)
        ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240)
        self.moduleRemoveButton.grid(row=7, column=3, sticky=E)
        moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        moduleInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        self.loadTreeViews()

        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        frame.columnconfigure(1, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.modulesView.get_children(""): 
            self.modulesView.delete(previousNode)

        for i, moduleItem in enumerate(sorted(self.pluginConfig.get("modules", {}).items())):
            moduleInfo = moduleItem[1]
            name = moduleInfo.get("name", moduleItem[0])
            node = self.modulesView.insert("", "end", name, text=name)
            self.modulesView.set(node, "author", moduleInfo.get("author"))
            self.modulesView.set(node, "ver", moduleInfo.get("version"))
            self.modulesView.set(node, "status", moduleInfo.get("status"))
            self.modulesView.set(node, "date", moduleInfo.get("fileDate"))
            if name in self.modulesWithNewerFileDates:
                self.modulesView.set(node, "update", _("available"))
            self.modulesView.set(node, "descr", moduleInfo.get("description"))
            self.modulesView.set(node, "license", moduleInfo.get("license"))
        
        # clear previous treeview entries
        for previousNode in self.classesView.get_children(""): 
            self.classesView.delete(previousNode)

        for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())):
            className, moduleList = classItem
            node = self.classesView.insert("", "end", className, text=className)
            self.classesView.set(node, "modules", ', '.join(moduleList))
            
        self.moduleSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged:  # may require reloading UI
            if messagebox.askyesno(_("User interface plug-in change"),
                                   _("A change in plug-in class methods may have affected the menus "
                                     "of the user interface.  It may be necessary to restart Arelle to "
                                     "access the menu entries or the changes to their plug-in methods.  \n\n"
                                     "Should Arelle restart with changed user interface language, "
                                     "(if there are any unsaved changes they would be lost!)?"),
                                   parent=self):
                self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True]))
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def moduleSelect(self, *args):
        node = (self.modulesView.selection() or (None,))[0]
        moduleInfo = self.pluginConfig.get("modules", {}).get(node)
        if moduleInfo:
            self.selectedModule = node
            name = moduleInfo["name"]
            self.moduleNameLabel.config(text=name)
            self.moduleAuthorHdr.config(state=ACTIVE)
            self.moduleAuthorLabel.config(text=moduleInfo["author"])
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo["description"])
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"]))
            self.moduleUrlHdr.config(state=ACTIVE)
            self.moduleUrlLabel.config(text=moduleInfo["moduleURL"])
            self.moduleDateHdr.config(state=ACTIVE)
            self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.modulesWithNewerFileDates else ""))
            self.moduleLicenseHdr.config(state=ACTIVE)
            self.moduleLicenseLabel.config(text=moduleInfo["license"])
            self.moduleEnableButton.config(state=ACTIVE,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[moduleInfo["status"]])
            self.moduleReloadButton.config(state=ACTIVE)
            self.moduleRemoveButton.config(state=ACTIVE)
        else:
            self.selectedModule = None
            self.moduleNameLabel.config(text="")
            self.moduleAuthorHdr.config(state=DISABLED)
            self.moduleAuthorLabel.config(text="")
            self.moduleDescrHdr.config(state=DISABLED)
            self.moduleDescrLabel.config(text="")
            self.moduleClassesHdr.config(state=DISABLED)
            self.moduleClassesLabel.config(text="")
            self.moduleUrlHdr.config(state=DISABLED)
            self.moduleUrlLabel.config(text="")
            self.moduleDateHdr.config(state=DISABLED)
            self.moduleDateLabel.config(text="")
            self.moduleLicenseHdr.config(state=DISABLED)
            self.moduleLicenseLabel.config(text="")
            self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.moduleReloadButton.config(state=DISABLED)
            self.moduleRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        filename = self.cntlr.uiFileDialog("open",
                                           owner=self,
                                           title=_("Choose plug-in module file"),
                                           initialdir=self.cntlr.config.setdefault("pluginOpenDir","."),
                                           filetypes=[(_("Python files"), "*.py")],
                                           defaultextension=".py")
        if filename:
            self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename)
            moduleInfo = PluginManager.moduleModuleInfo(filename)
            self.loadFoundModuleInfo(moduleInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            moduleInfo = PluginManager.moduleModuleInfo(url)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundModuleInfo(moduleInfo, url)
                
    def loadFoundModuleInfo(self, moduleInfo, url):
        if moduleInfo and moduleInfo.get("name"):
            self.addPluginConfigModuleInfo(moduleInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Module is not a plug-in"),
                                   _("File does not contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}")
                                   .format(url),
                                   parent=self)
            
    def removePluginConfigModuleInfo(self, name):
        moduleInfo = self.pluginConfig["modules"].get(name)
        if moduleInfo:
            for classMethod in moduleInfo["classMethods"]:
                classMethods = self.pluginConfig["classes"].get(classMethod)
                if classMethods and name in classMethods:
                    classMethods.remove(name)
                    if not classMethods: # list has become unused
                        del self.pluginConfig["classes"][classMethod] # remove class
                    if classMethod.startswith("CntlrWinMain.Menu"):
                        self.uiClassMethodsChanged = True  # may require reloading UI
            del self.pluginConfig["modules"][name]
            self.pluginConfigChanged = True

    def addPluginConfigModuleInfo(self, moduleInfo):
        name = moduleInfo["name"]
        self.removePluginConfigModuleInfo(name)  # remove any prior entry for this module
        self.modulesWithNewerFileDates.discard(name) # no longer has an update available
        self.pluginConfig["modules"][name] = moduleInfo
        # add classes
        for classMethod in moduleInfo["classMethods"]:
            classMethods = self.pluginConfig["classes"].setdefault(classMethod, [])
            if name not in classMethods:
                classMethods.append(name)
            if classMethod.startswith("CntlrWinMain.Menu"):
                self.uiClassMethodsChanged = True  # may require reloading UI
        self.pluginConfigChanged = True

    def moduleEnable(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][self.selectedModule]
            if self.moduleEnableButton['text'] == self.ENABLE:
                moduleInfo["status"] = "enabled"
                self.moduleEnableButton['text'] = self.DISABLE
            elif self.moduleEnableButton['text'] == self.DISABLE:
                moduleInfo["status"] = "disabled"
                self.moduleEnableButton['text'] = self.ENABLE
            self.pluginConfigChanged = True
            self.loadTreeViews()
            
    def moduleReload(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL")
            if url:
                moduleInfo = PluginManager.moduleModuleInfo(url, reload=True)
                if moduleInfo:
                    self.addPluginConfigModuleInfo(moduleInfo)
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Module error"),
                                           _("File or module cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def moduleRemove(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            self.removePluginConfigModuleInfo(self.selectedModule)
            self.pluginConfigChanged = True
            self.loadTreeViews()
Exemple #35
0
tree_columns = ['Colours', 'Hash', 'RGB']

tree_data = (('red', '#FF0000', (255, 0, 0)), ('yellow', '#FFFF00', (255, 255,
                                                                     0)),
             ('blue', '#0000FF', (0, 0, 255)), ('green', '#00FF00', (0, 255,
                                                                     0)),
             ('magenta', '#FF00FF', (255, 0, 255)), ('cyan', '#00FFFF',
                                                     (0, 255, 255)))

fr0 = Frame(root)
fr0.grid(column=0, row=0, sticky='nsew')

# create Treeview widget
tree = Treeview(fr0, column=tree_columns, show='headings')
tree.grid(column=0, row=0, sticky='nsew')
tree.bind("<ButtonRelease-1>", select_item)

# insert header and data
for col in tree_columns:
    tree.heading(col, text=col.title())

for item in tree_data:
    itemID = tree.insert('', 'end', values=item)

# display selection
lvar = StringVar()
lbl = Label(fr0, textvariable=lvar, text="Ready")
lbl.grid(column=0, row=1, sticky='nsew')

root.mainloop()
Exemple #36
0
class DialogOpenArchive(Toplevel):
    def __init__(self, mainWin, openType, filesource, filenames, title, colHeader, showAltViewButton=False):
        parent = mainWin.parent
        super(DialogOpenArchive, self).__init__(parent)
        self.parent = parent
        self.showAltViewButton = showAltViewButton
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))
        self.accepted = False

        self.transient(self.parent)
        
        frame = Frame(self)

        treeFrame = Frame(frame, width=500)
        vScrollbar = Scrollbar(treeFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(treeFrame, orient=HORIZONTAL)
        self.treeView = Treeview(treeFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set)
        self.treeView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.treeView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.treeView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        treeFrame.columnconfigure(0, weight=1)
        treeFrame.rowconfigure(0, weight=1)
        treeFrame.grid(row=0, column=0, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.treeView.focus_set()
        
        mainWin.showStatus(_("loading archive {0}").format(filesource.url))
        self.filesource = filesource
        self.filenames = filenames
        self.selection = filesource.selection
        self.hasToolTip = False
        selectedNode = None

        if openType == ENTRY_POINTS:
            try:
                metadataFiles = filesource.taxonomyPackageMetadataFiles
                if len(metadataFiles) > 1:
                    raise IOError(_("Taxonomy package contained more than one metadata file: {0}.")
                                  .format(', '.join(metadataFiles)))
                metadataFile = metadataFiles[0]
                metadata = filesource.file(filesource.url + os.sep + metadataFile)[0]
                self.metadataFilePrefix = os.sep.join(os.path.split(metadataFile)[:-1])
                if self.metadataFilePrefix:
                    self.metadataFilePrefix += os.sep
        
                self.nameToUrls, self.remappings = parseTxmyPkg(mainWin, metadata)
            except Exception as e:
                self.close()
                err = _("Failed to parse metadata; the underlying error was: {0}").format(e)
                messagebox.showerror(_("Malformed taxonomy package"), err)
                mainWin.addToLog(err)
                return
    
        mainWin.showStatus(None)
        
        if openType == DISCLOSURE_SYSTEM:
            y = 3
        else:
            y = 1

        okButton = Button(frame, text=_("OK"), command=self.ok)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        okButton.grid(row=y, column=2, sticky=(S,E,W), pady=3)
        cancelButton.grid(row=y, column=3, sticky=(S,E,W), pady=3, padx=3)
        
        if showAltViewButton:
            self.altViewButton = Button(frame, command=self.showAltView)
            self.altViewButton.grid(row=y, column=0, sticky=(S,W), pady=3, padx=3)
        
        self.loadTreeView(openType, colHeader, title)

        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.toolTipText = StringVar()
        if self.hasToolTip:
            self.treeView.bind("<Motion>", self.motion, '+')
            self.treeView.bind("<Leave>", self.leave, '+')
            self.toolTipText = StringVar()
            self.toolTip = ToolTip(self.treeView, 
                                   textvariable=self.toolTipText, 
                                   wraplength=640, 
                                   follow_mouse=True,
                                   state="disabled")
            self.toolTipRowId = None

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeView(self, openType, title, colHeader):
        self.title(title)
        self.openType = openType
        selectedNode = None

        # clear previous treeview entries
        for previousNode in self.treeView.get_children(""): 
            self.treeView.delete(previousNode)

        # set up treeView widget and tabbed pane
        if openType in (ARCHIVE, DISCLOSURE_SYSTEM):
            self.treeView.column("#0", width=500, anchor="w")
            self.treeView.heading("#0", text=colHeader)
            try:
                self.isRss = self.filesource.isRss
                if self.isRss:
                    self.treeView.column("#0", width=350, anchor="w")
                    self.treeView["columns"] = ("descr", "date", "instDoc")
                    self.treeView.column("descr", width=50, anchor="center", stretch=False)
                    self.treeView.heading("descr", text="Form")
                    self.treeView.column("date", width=170, anchor="w", stretch=False)
                    self.treeView.heading("date", text="Pub Date")
                    self.treeView.column("instDoc", width=200, anchor="w", stretch=False)
                    self.treeView.heading("instDoc", text="Instance Document")
            except AttributeError:
                self.isRss = False
                self.treeView["columns"] = tuple()
        
            loadedPaths = []
            for i, filename in enumerate(self.filenames):
                if isinstance(filename,tuple):
                    if self.isRss:
                        form, date, instDoc = filename[2:5]
                    filename = filename[0] # ignore tooltip
                    self.hasToolTip = True
                if filename.endswith("/"):
                    filename = filename[:-1]
                path = filename.split("/")
                if not self.isRss and len(path) > 1 and path[:-1] in loadedPaths:
                    parent = "file{0}".format(loadedPaths.index(path[:-1]))
                else:
                    parent = "" 
                node = self.treeView.insert(parent, "end", "file{0}".format(i), text=path[-1])
                if self.isRss:
                    self.treeView.set(node, "descr", form)
                    self.treeView.set(node, "date", date)
                    self.treeView.set(node, "instDoc", os.path.basename(instDoc))
                if self.selection == filename:
                    selectedNode = node
                loadedPaths.append(path)

        elif openType == ENTRY_POINTS:
            self.treeView.column("#0", width=150, anchor="w")
            self.treeView.heading("#0", text="Name")
    
            self.treeView["columns"] = ("url",)
            self.treeView.column("url", width=350, anchor="w")
            self.treeView.heading("url", text="URL")
            
            for name, urls in self.nameToUrls.items():
                displayUrl = urls[1] # display the canonical URL
                self.treeView.insert("", "end", name, values=[displayUrl], text=name)
                
            self.hasToolTip = True
        else: # unknown openType
            return None
        if selectedNode:
            self.treeView.see(selectedNode)
            self.treeView.selection_set(selectedNode)

        if self.showAltViewButton:
            self.altViewButton.config(text=_("Show Files") if openType == ENTRY_POINTS else _("Show Entries"))

        
    def ok(self, event=None):
        selection = self.treeView.selection()
        if len(selection) > 0:
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                filename = self.filenames[int(selection[0][4:])]
                if isinstance(filename,tuple):
                    if self.isRss:
                        filename = filename[4]
                    else:
                        filename = filename[0]
                if not filename.endswith("/"):
                    self.filesource.select(filename)
                    self.accepted = True
                    self.close()
            elif self.openType == ENTRY_POINTS:
                epName = selection[0]
                #index 0 is the remapped Url, as opposed to the canonical one used for display
                urlOrFile = self.nameToUrls[epName][0]
                
                # load file source remappings
                self.filesource.mappedPaths = \
                    dict((prefix, 
                          remapping if isHttpUrl(remapping)
                          else (self.filesource.baseurl + os.sep + self.metadataFilePrefix +remapping.replace("/", os.sep)))
                          for prefix, remapping in self.remappings.items())
    
                if not urlOrFile.endswith("/"):
                    # check if it's an absolute URL rather than a path into the archive
                    if isHttpUrl(urlOrFile):
                        self.filesource.select(urlOrFile)  # absolute path selection
                    else:
                        # assume it's a path inside the archive:
                        self.filesource.select(self.metadataFilePrefix + urlOrFile)
                    self.accepted = True
                    self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
        
    def showAltView(self, event=None):
        if self.openType == ENTRY_POINTS:
            self.loadTreeView(ARCHIVE, _("Select Entry Point"), _("File"))
        else:
            self.loadTreeView(ENTRY_POINTS, _("Select Archive File"), _("File"))
        
    def leave(self, *args):
        self.toolTipRowId = None

    def motion(self, *args):
        tvRowId = self.treeView.identify_row(args[0].y)
        if tvRowId != self.toolTipRowId:
            text = None
            if self.openType in (ARCHIVE, DISCLOSURE_SYSTEM):
                self.toolTipRowId = tvRowId
                if tvRowId and len(tvRowId) > 4:
                    try:
                        text = self.filenames[ int(tvRowId[4:]) ]
                        if isinstance(text, tuple):
                            text = text[1].replace("\\n","\n")
                    except (KeyError, ValueError):
                        pass
            elif self.openType == ENTRY_POINTS:
                try:
                    epUrl = self.nameToUrls[tvRowId][1]
                    text = "{0}\n{1}".format(tvRowId, epUrl)
                except KeyError:
                    pass
            self.setToolTip(text)
                
    def setToolTip(self, text):
        self.toolTip._hide()
        if text:
            self.toolTipText.set(text)
            self.toolTip.configure(state="normal")
            self.toolTip._schedule()
        else:
            self.toolTipText.set("")
            self.toolTip.configure(state="disabled")
class Expenses(Frame):

    # Creates the first option menus in the expense window
    def createOptionButtons(self):
        self.master.title("Expenses")

        # Creates the add item to inventory button
        addItem = Button(root, text="Add item to inventory", command=lambda: self.sequence(self.addItem))#addItem(master)))  # This button will send to the user to the add item page
        addItem.place(x = 130, y = 100)

        # Creates the view items in inventory button
        inventoryButton = Button(root, text="View items in inventory", command=lambda: self.sequence(self.viewInveroty))  # This button will send the user to the view inventory page
        inventoryButton.place(x = 130, y = 150)

        # Create the total cost button
        totalCost = Button(root, text="Total Cost", command=lambda: self.sequence(self.viewTotalCost))
        totalCost.place(x = 130, y = 200)

        # Creates the back button
        backButton = Button(root, text="Back", command=returnHome)  # This button will return the user to the main page. Still working on it.
        backButton.place(x = 50, y = 350)

    # Creates the add item to inventory button and entries
    def addItem(self):
        self.master.title("Add new item")  # Changes the title of the page to Add New Item

        # Creates a label called nameOfItems and an entry called itemName
        nameOfItem = Label(root, text="Item Name: ")
        nameOfItem.place(x = 110, y = 100)
        self.itemName = Entry(root)       # This will allow the user to enter the name of the item that they will be adding
        self.itemName.place(x = 190, y = 100)

        # Creates the label called itemTypeLabel and a drop down menu called itemTypeChoice
        itemTypeLabel = Label(root, text = "Item's type: ")
        itemTypeLabel.place(x = 110, y = 160)
        self.itemTypeChoice = StringVar(root)       # This makes itemTypeChoice a permanent String
        self.itemTypeChoice.set("Tree")             # Tree is set to the default string of itemTypeChoice
        typeChoices = OptionMenu(root, self.itemTypeChoice, "Tree", "Animal", "Machine")    # Drop down menu is created and options Tree, Animal, and Machine are added to the menu
        typeChoices.place(x = 190, y = 160)


        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.createOptionButtons))
        backButton.place(x = 50, y = 350)
        # Next button
        nextButton = Button(root, text = "Next", command=self.saveNameAndType) #This button will send the user to the add inventory page
        nextButton.place(x = 350, y = 350)

    # Function that creates a new item object and assigns it a name and the type
    def saveNameAndType(self):
        name = self.itemName.get()
        self.item = Inventory(name)
        itemType = self.itemTypeChoice.get()
        self.item.itemType = itemType
        self.sequence(self.addToInventory)

    # Creates the add to inventory options
    def addToInventory(self):
        self.master.title("Add %s to %s inventory" % (self.item.name, self.item.itemType))

        # This assigns the variables month, day, and year to be value holder for integer values
        # They are also set to be values of the class expenses (by using self) so that they can
        # be used in the function updateDay and SaveDate
        self.month = IntVar(self)
        self.day = IntVar(self)
        self.year = IntVar(self)

        # This trace function is used to keep track of when the selected months and years change. This is
        # done to adjust the days of the month according to the month or the year
        self.month.trace('w', self.updateDay)
        self.year.trace('w', self.updateDay)

        numMonths = self.nums(1, 12)  # Runs the nums function that creates a list from 1 to 12
        numYears = self.nums(2015, 2030)  # Runs the nums function that creates a list from 2015 to 2030

        # This creates the drop down menu and assigns the options is the menu. The day menu is left empty and
        # is assigned in the updateDay function
        self.optionmenu_month = OptionMenu(root, self.month, *numMonths)
        self.optionmenu_day = OptionMenu(root, self.day, '')
        self.optionmenu_year = OptionMenu(root, self.year, *numYears)

        # Sets the default value of the month and year options to 1 and 2015 respectively
        self.month.set(numMonths[0])
        self.year.set(numYears[0])

        self.optionmenu_month.place(x = 100, y = 120)
        self.optionmenu_day.place(x = 150, y = 120)
        self.optionmenu_year.place(x = 200, y = 120)


        datePurchased = Label(root, text = "Date Purchased")
        datePurchased.place(x = 150, y = 95)

        quantityPurchasedLabel = Label(root, text="Amount purchased:")
        quantityPurchasedLabel.place(x = 50, y = 180)
        self.quantityPurchasedEntry = Entry(root, bd=5) # Creates input box for user to insert the amount of items purchased
        self.quantityPurchasedEntry.place(x = 180, y = 180)

        pricePaidLabe = Label(root, text="Price paid for all: ")
        pricePaidLabe.place(x = 50, y = 210)
        self.pricePaidEntry = Entry(root, bd=5) # Creates input box for user to insert the price paid for the item
        self.pricePaidEntry.place(x = 180, y = 210)


        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.addItem))
        backButton.place(x = 50, y = 350)

        nextButton = Button(root, text = "Next", command=self.saveQuanAndPrice)
        nextButton.place(x = 350, y = 350)

    # This function will update the days of the month according to the selected month and year
    def updateDay(self, *args):
        # The .get() will obtain the selected month and year values from the drop down menu above
        month = self.month.get()
        year = self.year.get()

        # Creates a loop which chooses the last day of the month according to the month or the year
        if month == 1 or month  == 3 or month  == 5 or month  == 7 or month  == 8 or month  == 10 or month  == 12:
            lastDay = 31
        elif month  == 4 or month  == 6 or month  == 9 or month  == 11:
            lastDay = 30
        # This elif loop uses the leap year formula at account for leap years
        elif month  == 2:
            if (year % 4) == 0:
                if (year % 100) == 0:
                    if (year % 400) == 0:
                        lastDay = 29
                    else:
                        lastDay = 28
                else:
                    lastDay = 29
            else:
                lastDay = 28

        numDays = self.nums(1,lastDay)

        # Assigns menu to the day drop down menu and deletes all of the options in the menu
        menu = self.optionmenu_day['menu']
        menu.delete(0, 'end')

        # Loop for generating the new day menu
        for day in numDays:
            menu.add_command(label=day, command=lambda d = day: self.day.set(d))
        self.day.set(1)

    # Function that creates the range of numbers for the drop down menu
    def nums(self, numStart, numEnd):
        num = range(numStart, numEnd + 1)
        return num

    # Function that assigns the price and quantity to an item
    def saveQuanAndPrice(self):
        self.item.price = self.pricePaidEntry.get()
        self.item.quantity = self.quantityPurchasedEntry.get()
        self.saveDate()
        self.sequence(self.confirmation)

    # Function that assigns the purchase date to an item
    def saveDate(self):
        self.item.purchaseMonth = self.month.get()
        self.item.purchaseDay = self.day.get()
        self.item.purchaseYear = self.year.get()
        self.item.purchaseDate = ("%s/%s/%s" % (self.item.purchaseMonth, self.item.purchaseDay, self.item.purchaseYear))

    # Function that displays the user inputted information
    def confirmation(self):
        self.master.title("Confirm %s information" % self.item.name)
        name = Label(root, text="Name of item: ")
        name.place(x = 100, y = 50)
        itemName = Label(root, text=self.item.name)
        itemName.place(x = 100, y = 65)

        type = Label(root, text="%s type: " % self.item.name)
        type.place(x = 100, y = 90)
        itemType = Label(root, text=self.item.itemType)
        itemType.place(x = 100, y = 105)

        quantity = Label(root, text="How many %s were bought?" % self.item.name)
        quantity.place(x = 100, y = 130)
        itemQuantity = Label(root, text=self.item.quantity)
        itemQuantity.place(x = 100, y = 145)

        price = Label(root, text="How much did the %s %s cost?" % (self.item.quantity, self.item.name))
        price.place(x = 100, y = 170)
        itemPrice = Label(root, text=self.item.price)
        itemPrice.place(x = 100, y = 185)

        date = Label(root, text="When were %s bought?" % self.item.name)
        date.place(x = 100, y = 210)
        itemDate = Label(root, text=self.item.purchaseDate)
        itemDate.place(x = 100, y = 225)


        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.addToInventory))
        backButton.place(x = 50, y = 350)

        startOverButton = Button(root, text = "Start Over", command=lambda: self.sequence(self.createOptionButtons))
        startOverButton.place(x = 200, y = 350)

        confirmButton = Button(root, text = "Confirm", command=lambda: self.sequence(self.addToDatabase))
        confirmButton.place(x = 320, y = 350)

    # Adds the item to the database
    def addToDatabase(self):
        self.inventoryDB.insertInvetory(self.item)
        return self.successful()

    # Displays a success message when the item is added
    def successful(self):
        self.master.title("%s was added successfully!" % self.item.name)

        succMessage = Message(root, text = "%s was successfully added to the %s list!" % (self.item.name, self.item.itemType))
        succMessage.place(x = 150, y = 150)

        startOverButton = Button(root, text = "Start Over", command=lambda: self.sequence(self.createOptionButtons))#self.saveNameAndType(itemName)))#(self.saveNameAndType(itemName)))  # (itemName)))# lambda: self.sequence(self.test))  #This button will send the user to the add inventory page
        startOverButton.place(x = 150, y = 350)

    # Used to view the inventory
    def viewInveroty(self):
        # Creates the label called chooseTypeLabel and a drop down menu called chooseItemType
        chooseTypeLabel = Label(root, text = "Item's type: ")
        chooseTypeLabel.place(x = 110, y = 160)
        self.chooseItemType = StringVar(root)       # The drop down menu is created and assigned to chooseItemType
        self.chooseItemType.set("Tree")             # Tree is set to the default option in the drop down menu
        typeChoices = OptionMenu(root, self.chooseItemType, "Tree", "Animal", "Machine", "All")    # Options Tree, Animal, Machine, and ALL are added to the drop down menu
        typeChoices.place(x = 190, y = 160)

        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.createOptionButtons))  # This button will return the user to the expenses option page
        backButton.place(x = 50, y = 350)

        nextButton = Button(root, text = "Next", command=lambda: self.sequence(self.displayGeneralInventory))#self.saveNameAndType(itemName)))#(self.saveNameAndType(itemName)))  # (itemName)))# lambda: self.sequence(self.test))  #This button will send the user to the add inventory page
        nextButton.place(x = 350, y = 350)

    # Used to create the inventory table
    def displayGeneralInventory(self):
        # This creates a table using the function Treeview
        self.tree = Treeview(height="20", columns=("Name", "Current Quantity"))
        self.tree.pack()
        self.tree.heading('#1', text = "Name", anchor = CENTER)
        self.tree.heading('#2', text = "Current Quantity", anchor = CENTER)
        self.tree.column('#1', minwidth=0, width = 100)
        self.tree.column('#2', minwidth=0, width = 100)
        self.tree.column('#0', minwidth=0, width = 0)

        itemType = self.chooseItemType.get()

        if(itemType == "All"):
            self.obtainData("Tree")
            self.obtainData("Animal")
            self.obtainData("Machine")

        else:
            self.obtainData(itemType)

    # Adds database data to the inventory table
    def obtainData(self, type):
        for row in (self.inventoryDB.getOverviewInventory(type)):
            name = row[0]
            totalQuantity = row[1]

            # Inserts data into the table. Each entry is tagged with the name and the type
            # This is done in order to make identifying the entries easier for when detailed
            # tables are requested
            self.tree.insert("", "end", values = (name,totalQuantity), tag= [name, type])

        # Creates a bak function that is used in the displayGeneralInventory functions
        self.backFunction = self.displayGeneralInventory

        # Binds a double click function to the Treeview table. If an entry is double clicked,
        # the function displayGeneralInventory is ran
        self.tree.bind("<Double-1>", self.displayDetailedInventory)

        backButton = Button(root, text="Back", command=lambda: self.sequence(self.viewInveroty))  # This button will return the user to the main page. Still working on it.
        backButton.place(x = 50, y = 350)

    # Creates table when an entry is double clicked
    def displayDetailedInventory(self, event):
        # The selected item's tag are extracted and assigned to name and type
        itemSelected = self.tree.selection()
        name = self.tree.item(itemSelected,"tag")[0]
        type = self.tree.item(itemSelected, "tag")[1]

        for child in root.winfo_children():
            child.destroy()

        self.createDisplayTable()

        self.obtainDetailedData(name, type)

    # Adds detailed database data to the inventory table
    def obtainDetailedData(self,name, type):
        for row in (self.inventoryDB.getDetailedInventory(type, name)):
            name = row[0]
            purchaseDate = row[1]
            Quantity = row[3]
            Price = row[4]
            self.tree.insert("", "end", values = (name,purchaseDate,Quantity, Price))

        backButton = Button(root, text="Back", command=lambda: self.sequence(self.backFunction))
        backButton.place(x = 50, y = 350)

    # Creates the view total cost by month and year buttons
    def viewTotalCost(self):
        viewMonth = Button(root, text="View by month", command=lambda: self.sequence(self.viewByMonth))
        viewMonth.place(x = 120, y = 100)

        viewYear = Button(root, text="View by year", command=lambda: self.sequence(self.viewByYear))
        viewYear.place(x = 120, y = 150)

        backButton = Button(root, text="Back", command=lambda: self.sequence(self.createOptionButtons))#displayGeneralInventory))  # This button will return the user to the main page. Still working on it.
        backButton.place(x = 50, y = 350)

    # Creates the options for the user to select a month and year
    def viewByMonth(self):
        monthLabel = Label(root, text="Month")
        yearLabel = Label(root, text="Year")

        self.month = IntVar(self)
        self.year = IntVar(self)

        numMonths = self.nums(1, 12)
        numYears = self.nums(2015, 2030)

        self.optionmenu_month = OptionMenu(root, self.month, *numMonths)
        self.optionmenu_year = OptionMenu(root, self.year, *numYears)

        self.month.set(numMonths[0])
        self.year.set(numYears[0])

        self.optionmenu_month.place(x = 100, y = 100)
        self.optionmenu_year.place(x = 150, y = 100)

        monthLabel.place(x = 100, y = 140)
        yearLabel.place(x = 150, y = 140)

        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.viewTotalCost))  # This button will return the user to the expenses option page
        backButton.place(x = 50, y = 350)

        nextButton = Button(root, text = "Next", command= self.viewTotalCostMonth)#self.viewTotalCostMonth)#self.saveNameAndType(itemName)))#(self.saveNameAndType(itemName)))  # (itemName)))# lambda: self.sequence(self.test))  #This button will send the user to the add inventory page
        nextButton.place(x = 350, y = 350)

    # Creates database table and inserts the respective values by month and year
    def viewTotalCostMonth(self):
        self.createDisplayTable()

        self.totalPrice = 0
        month = self.month.get()
        year = self.year.get()

        self.lengthMonth = len(str(month))
        self.searchDate = str(month) + "/" + str(year)

        InventoryDB = getDatabaseConnection()
        database = InventoryDB.cursor()

        self.insertData("DetailedTreeInventory", "Tree", database, "Month")
        self.insertData("DetailedAnimalInventory", "Animal", database, "Month")
        self.insertData("DetailedMachineInventory", "Machine", database, "Month")

        InventoryDB.close()

        totalPriceLabel = Label(root, text=("Total price for " + calendar.month_name[month] + " in " + str(year) + " is: " + str(self.totalPrice)))
        totalPriceLabel.place(x = 100, y = 350)

        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.viewByMonth))  # This button will return the user to the expenses option page
        backButton.place(x = 50, y = 350)

    # Creates the option for the user to select the year
    def viewByYear(self):
        yearLabel = Label(root, text="Year")

        self.year = IntVar(self)

        numYears = self.nums(2015, 2030)

        self.optionmenu_year = OptionMenu(root, self.year, *numYears)

        self.year.set(numYears[0])

        self.optionmenu_year.place(x = 100, y = 100)
        yearLabel.place(x = 100, y = 140)


        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.viewTotalCost))  # This button will return the user to the expenses option page
        backButton.place(x = 50, y = 350)

        nextButton = Button(root, text = "Next", command= self.viewTotalCostYear)#self.viewTotalCostMonth)#self.saveNameAndType(itemName)))#(self.saveNameAndType(itemName)))  # (itemName)))# lambda: self.sequence(self.test))  #This button will send the user to the add inventory page
        nextButton.place(x = 350, y = 350)

    # Creates database table and inserts the respective values by year
    def viewTotalCostYear(self):
        self.createDisplayTable()

        self.totalPrice = 0
        year = self.year.get()

        InventoryDB = getDatabaseConnection()
        database = InventoryDB.cursor()

        self.insertData("DetailedTreeInventory", "Tree", database, "Year")
        self.insertData("DetailedAnimalInventory", "Animal", database, "Year")
        self.insertData("DetailedMachineInventory", "Machine", database, "Year")

        totalPriceLabel = Label(root, text="Total price for " + str(year) + " is: " + str(self.totalPrice))
        totalPriceLabel.place(x = 100, y = 350)

        backButton = Button(root, text = "Back", command=lambda: self.sequence(self.viewByYear))  # This button will return the user to the expenses option page
        backButton.place(x = 50, y = 350)

    # Inserts the detailed values into the detailed table
    def insertData(self, table, type, database, yearOrMonth):
        if yearOrMonth == "Year":
            for row in database.execute("SELECT * FROM %s" % table ):
                itemdate = row[1]

                if ( str(self.year.get()) == itemdate[-4:]):
                    name = row[0]
                    purchaseDate = row[1]
                    Quantity = row[3]
                    Price = row[4]

                    self.tree.insert("", "end", values = (name,purchaseDate,Quantity, Price),tag = [name, type] )
                    self.totalPrice = self.totalPrice + Price

                self.backFunction = self.viewTotalCostYear

        else:
            for row in database.execute("SELECT * FROM %s" % table ):
                itemdate = row[1]

                if (self.searchDate == (itemdate[0:(self.lengthMonth + 1)] + itemdate[-4:])):
                    name = row[0]
                    purchaseDate = row[1]
                    Quantity = row[3]
                    Price = row[4]

                    self.tree.insert("", "end", values = (name,purchaseDate,Quantity, Price), tag = [name, type])
                    self.totalPrice = self.totalPrice + Price

                self.backFunction = self.viewTotalCostMonth

        # If entry is double clicked, the table will acknoledge the click and display the detailed table
        self.tree.bind("<Double-1>", self.displayDetailedInventory)

    def createDisplayTable(self):
        for child in root.winfo_children():
            child.destroy()

        self.tree = Treeview(height="15", columns=("Name", "Purchase Date", "Quantity", "Price"))#, "Description"))
        self.tree.pack()
        self.tree.heading('#1', text = "Name",          anchor = CENTER)
        self.tree.heading('#2', text = "Purchase Date", anchor = CENTER)
        self.tree.heading('#3', text = "Quantity",      anchor = CENTER)
        self.tree.heading('#4', text = "Price",         anchor = CENTER)
        self.tree.column('#1', minwidth=0, width = 95)
        self.tree.column('#2', minwidth=0, width = 95)
        self.tree.column('#3', minwidth=0, width = 95)
        self.tree.column('#4', minwidth=0, width = 95)
        self.tree.column('#0', minwidth=0, width = 0)

    # This is a helper function that will delete the current widgets of the frame
    def sequence(self, run):
        for child in root.winfo_children():
            child.destroy()
        run()

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.place();
        self.inventoryDB = InventoryDatabase()
        # self.inventoryDB.createTable()
        self.createOptionButtons()
Exemple #38
0
save_button.pack(side=LEFT, after=open_button, padx=10, pady=10)
quit_button.pack(side=LEFT, after=save_button, padx=10, pady=10)
filter_label.pack(side=LEFT, after=quit_button, padx=0, pady=10)
fitler_entry.pack(side=LEFT,
                  after=filter_label,
                  padx=20,
                  pady=10,
                  fill=X,
                  expand=YES)
toolbar.pack(side=TOP, fill=X)

# 数据包列表区
packet_list_frame = Frame()
packet_list_sub_frame = Frame(packet_list_frame)
packet_list_tree = Treeview(packet_list_sub_frame, selectmode='browse')
packet_list_tree.bind('<<TreeviewSelect>>', on_click_packet_list_tree)
# 数据包列表垂直滚动条
packet_list_vscrollbar = Scrollbar(packet_list_sub_frame,
                                   orient="vertical",
                                   command=packet_list_tree.yview)
packet_list_vscrollbar.pack(side=RIGHT, fill=Y, expand=YES)
packet_list_tree.configure(yscrollcommand=packet_list_vscrollbar.set)
packet_list_sub_frame.pack(side=TOP, fill=BOTH, expand=YES)
# 数据包列表水平滚动条
packet_list_hscrollbar = Scrollbar(packet_list_frame,
                                   orient="horizontal",
                                   command=packet_list_tree.xview)
packet_list_hscrollbar.pack(side=BOTTOM, fill=X, expand=YES)
packet_list_tree.configure(xscrollcommand=packet_list_hscrollbar.set)
# 数据包列表区列标题
packet_list_tree["columns"] = ("No.", "Time", "Source", "Destination",
class MainWindow(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.eventHandler = EventHandler(self)
        self.parent = parent
        self.initUI()

    def initUI(self):

        self.parent.title("File synchronizer")

        Style().configure("TButton", padding=(0, 5, 0, 5), font="serif 10")

        # 3X3 Grid
        self.columnconfigure(0, pad=3, weight=1)
        self.columnconfigure(1, pad=3)
        self.columnconfigure(2, pad=3, weight=1)
        self.rowconfigure(0, pad=3)
        self.rowconfigure(1, pad=3, weight=1)
        self.rowconfigure(2, pad=3)

        ltf = Frame(self)
        ltf.grid(row=0, column=0, sticky=W + E)
        # 1X4 Grid
        ltf.columnconfigure(0, pad=3)
        ltf.columnconfigure(1, pad=3, weight=1)
        ltf.columnconfigure(2, pad=3, weight=1)
        ltf.columnconfigure(3, pad=3)
        ltf.rowconfigure(0, pad=3, weight=1)
        llabel = Label(ltf, text="Direcotry:")
        llabel.grid(row=0, column=0, sticky=W + E)
        self.leftDir = Entry(ltf)
        self.leftDir.bind("<Return>", self.eventHandler.leftDirChanged)
        self.leftDir.grid(row=0, column=1, columnspan=2, sticky=W + E)
        # Left browse button
        lBtn = Button(ltf, text="browse...", command=self.eventHandler.chooseLeftDirectory)
        lBtn.grid(row=0, column=3, sticky=E)

        rtf = Frame(self)
        rtf.grid(row=0, column=2, sticky=W + E)
        # 1X4 Grid
        rtf.columnconfigure(0, pad=3)
        rtf.columnconfigure(1, pad=3, weight=1)
        rtf.columnconfigure(2, pad=3, weight=1)
        rtf.columnconfigure(3, pad=3)
        rtf.rowconfigure(0, pad=3, weight=1)
        rlabel = Label(rtf, text="Direcotry:")
        rlabel.grid(row=0, column=0, sticky=W + E)
        self.rightDir = Entry(rtf)
        self.rightDir.bind("<Return>", self.eventHandler.rightDirChanged)
        self.rightDir.grid(row=0, column=1, columnspan=2, sticky=W + E)
        # Right browse button
        rBtn = Button(rtf, text="browse...", command=self.eventHandler.chooseRightDirectory)
        rBtn.grid(row=0, column=3, sticky=E)

        # Left TreeView frame
        ltf1 = Frame(self)
        ltf1.grid(row=1, column=0, sticky=N + S + W + E)
        # 2 X 2 Grid
        ltf1.columnconfigure(0, pad=3, weight=1)
        ltf1.columnconfigure(1, pad=3)
        ltf1.rowconfigure(0, pad=3, weight=1)
        ltf1.rowconfigure(1, pad=3)
        self.ltree = Treeview(ltf1, columns=("fullpath", "type", "size"), displaycolumns="size")
        self.ltree.grid(row=0, column=0, sticky=E + W + S + N)
        lysb = ttk.Scrollbar(ltf1, orient=VERTICAL, command=self.ltree.yview)
        lysb.grid(row=0, column=1, sticky=NS)
        lxsb = ttk.Scrollbar(ltf1, orient=HORIZONTAL, command=self.ltree.xview)
        lxsb.grid(row=1, column=0, columnspan=3, sticky=EW)
        self.ltree["yscroll"] = lysb.set
        self.ltree["xscroll"] = lxsb.set
        self.ltree.heading("#0", text="Directory Structure", anchor="w")
        self.ltree.heading("size", text="File Size", anchor="w")
        self.ltree.column("size", stretch=0, width=100)
        self.ltree.bind("<<TreeviewOpen>>", self.eventHandler.openTree)

        # Right TreeView frame
        rtf1 = Frame(self)
        rtf1.grid(row=1, column=2, sticky=N + S + W + E)
        # 2 X 2 Grid
        rtf1.columnconfigure(0, pad=3, weight=1)
        rtf1.columnconfigure(1, pad=3)
        rtf1.rowconfigure(0, pad=3, weight=1)
        rtf1.rowconfigure(1, pad=3)
        self.rtree = Treeview(rtf1, columns=("fullpath", "type", "size"), displaycolumns="size")
        self.rtree.grid(row=0, column=0, sticky=E + W + S + N)
        rysb = ttk.Scrollbar(rtf1, orient=VERTICAL, command=self.ltree.yview)
        rysb.grid(row=0, column=1, sticky=NS)
        rxsb = ttk.Scrollbar(rtf1, orient=HORIZONTAL, command=self.ltree.xview)
        rxsb.grid(row=1, column=0, columnspan=3, sticky=EW)
        self.rtree["yscroll"] = rysb.set
        self.rtree["xscroll"] = rxsb.set
        self.rtree.heading("#0", text="Directory Structure", anchor="w")
        self.rtree.heading("size", text="File Size", anchor="w")
        self.rtree.column("size", stretch=0, width=100)
        self.rtree.bind("<<TreeviewOpen>>", self.eventHandler.openTree)

        # Command Button frame
        btnf = Frame(self)
        btnf.grid(row=1, column=1, sticky=W + E + N + S)
        btnf.columnconfigure(0, pad=3, weight=1)
        btnf.rowconfigure(0, pad=3, weight=1)
        btnf.rowconfigure(1, pad=3, weight=1)
        btnf.rowconfigure(2, pad=3, weight=1)
        btnf.rowconfigure(3, pad=3, weight=1)
        btnf.rowconfigure(4, pad=3, weight=1)
        btnf.rowconfigure(5, pad=3, weight=1)
        btnf.rowconfigure(6, pad=3, weight=1)
        btnf.rowconfigure(7, pad=3, weight=1)
        l2rBtn = Button(btnf, text="Left >> Right", command=self.eventHandler.left2RightSynch)
        l2rBtn.grid(row=1, column=0, sticky=W + E)

        syncBtn = Button(btnf, text="<< Sync >>", command=self.eventHandler.leftRightSynch)
        syncBtn.grid(row=3, column=0, sticky=W + E)

        r2lBtn = Button(btnf, text="Left << Right", command=self.eventHandler.right2LeftSynch)
        r2lBtn.grid(row=5, column=0, sticky=W + E)

        closeBtn = Button(self, text="Close", command=self.eventHandler.quit)
        closeBtn.grid(row=2, column=2, sticky=E)

        self.pack(fill=BOTH, expand=1)
class DialogPluginManager(Toplevel):
    def __init__(self, mainWin, modulesWithNewerFileDates):
        super(DialogPluginManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.pluginConfig = PluginManager.pluginConfig
        self.pluginConfigChanged = False
        self.uiClassMethodsChanged = False
        self.modelClassesChanged = False
        self.disclosureSystemTypesChanged = False
        self.hostSystemFeaturesChanged = False
        self.modulesWithNewerFileDates = modulesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Plug-in Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240)
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (plugins already known to arelle)
        modulesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL)
        self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect)
        hScrollbar["command"] = self.modulesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.modulesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        modulesFrame.columnconfigure(0, weight=1)
        modulesFrame.rowconfigure(0, weight=1)
        modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.modulesView.focus_set()

        self.modulesView.column("#0", width=120, anchor="w")
        self.modulesView.heading("#0", text=_("Name"))
        self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license")
        self.modulesView.column("author", width=100, anchor="w", stretch=False)
        self.modulesView.heading("author", text=_("Author"))
        self.modulesView.column("ver", width=50, anchor="w", stretch=False)
        self.modulesView.heading("ver", text=_("Version"))
        self.modulesView.column("status", width=50, anchor="w", stretch=False)
        self.modulesView.heading("status", text=_("Status"))
        self.modulesView.column("date", width=70, anchor="w", stretch=False)
        self.modulesView.heading("date", text=_("File Date"))
        self.modulesView.column("update", width=50, anchor="w", stretch=False)
        self.modulesView.heading("update", text=_("Update"))
        self.modulesView.column("descr", width=200, anchor="w", stretch=False)
        self.modulesView.heading("descr", text=_("Description"))
        self.modulesView.column("license", width=70, anchor="w", stretch=False)
        self.modulesView.heading("license", text=_("License"))

        classesFrame = Frame(frame)
        vScrollbar = Scrollbar(classesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL)
        self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.classesView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.classesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.classesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        classesFrame.columnconfigure(0, weight=1)
        classesFrame.rowconfigure(0, weight=1)
        classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.classesView.focus_set()
        
        self.classesView.column("#0", width=200, anchor="w")
        self.classesView.heading("#0", text=_("Class"))
        self.classesView["columns"] = ("modules",)
        self.classesView.column("modules", width=500, anchor="w", stretch=False)
        self.classesView.heading("modules", text=_("Modules"))
        
        # bottom frame module info details
        moduleInfoFrame = Frame(frame, width=700)
        moduleInfoFrame.columnconfigure(1, weight=1)
        
        self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", 
                                     font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W)
        self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED)
        self.moduleAuthorHdr.grid(row=1, column=0, sticky=W)
        self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W)
        self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED)
        self.moduleDescrHdr.grid(row=2, column=0, sticky=W)
        self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W)
        self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED)
        self.moduleClassesHdr.grid(row=3, column=0, sticky=W)
        self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED)
        self.moduleUrlHdr.grid(row=4, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240)
        self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED)
        self.moduleDateHdr.grid(row=5, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240)
        self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED)
        self.moduleLicenseHdr.grid(row=6, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W)
        self.moduleImportsHdr = Label(moduleInfoFrame, text=_("imports:"), state=DISABLED)
        self.moduleImportsHdr.grid(row=7, column=0, sticky=W)
        self.moduleImportsLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleImportsLabel.grid(row=7, column=1, columnspan=3, sticky=W)
        self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable)
        ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240)
        self.moduleEnableButton.grid(row=8, column=1, sticky=E)
        self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload)
        ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240)
        self.moduleReloadButton.grid(row=8, column=2, sticky=E)
        self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove)
        ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240)
        self.moduleRemoveButton.grid(row=8, column=3, sticky=E)
        moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        moduleInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        enableDisableFrame = Frame(frame)
        enableDisableFrame.grid(row=3, column=1, sticky=(S,W), pady=3)
        enableAllButton = Button(enableDisableFrame, text=_("Enable All"), command=self.enableAll)
        ToolTip(enableAllButton, text=_("Enable all plug ins."), wraplength=240)
        disableAllButton = Button(enableDisableFrame, text=_("Disable All"), command=self.disableAll)
        ToolTip(disableAllButton, text=_("Disable all plug ins."), wraplength=240)
        enableAllButton.grid(row=1, column=1)
        disableAllButton.grid(row=1, column=2)
        
        self.loadTreeViews()

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.modulesView.get_children(""): 
            self.modulesView.delete(previousNode)
            
        def loadSubtree(parentNode, moduleItems):
            for moduleItem in sorted(moduleItems, key=lambda item: item[0]):
                moduleInfo = moduleItem[1]
                if parentNode or not moduleInfo.get("isImported"):
                    nodeName = moduleItem[0]
                    if parentNode:
                        nodeName = parentNode + GROUPSEP + nodeName
                    name = moduleInfo.get("name", nodeName)
                    node = self.modulesView.insert(parentNode, "end", nodeName, text=name)
                    self.modulesView.set(node, "author", moduleInfo.get("author"))
                    self.modulesView.set(node, "ver", moduleInfo.get("version"))
                    self.modulesView.set(node, "status", moduleInfo.get("status"))
                    self.modulesView.set(node, "date", moduleInfo.get("fileDate"))
                    if name in self.modulesWithNewerFileDates:
                        self.modulesView.set(node, "update", _("available"))
                    self.modulesView.set(node, "descr", moduleInfo.get("description"))
                    self.modulesView.set(node, "license", moduleInfo.get("license"))
                    if moduleInfo.get("imports"):
                        loadSubtree(node, [(importModuleInfo["name"],importModuleInfo)
                                           for importModuleInfo in moduleInfo["imports"]])
            
        loadSubtree("", self.pluginConfig.get("modules", {}).items())
        
        # clear previous treeview entries
        for previousNode in self.classesView.get_children(""): 
            self.classesView.delete(previousNode)

        for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())):
            className, moduleList = classItem
            node = self.classesView.insert("", "end", className, text=className)
            self.classesView.set(node, "modules", ', '.join(moduleList))
            
        self.moduleSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged:  # may require reloading UI
            affectedItems = ""
            if self.uiClassMethodsChanged:
                affectedItems += _("menus of the user interface")
            if self.modelClassesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("model objects of the processor")
            if self.disclosureSystemTypesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("disclosure system types")
            if self.hostSystemFeaturesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("host system features")
            if messagebox.askyesno(_("User interface plug-in change"),
                                   _("A change in plug-in class methods may have affected {0}.  " 
                                     "Please restart Arelle to due to these changes.  \n\n"
                                     "Should Arelle restart itself now "
                                     "(if there are any unsaved changes they would be lost!)?"
                                     ).format(affectedItems),
                                   parent=self):
                self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True]))
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def moduleSelect(self, *args):
        node = (self.modulesView.selection() or (None,))[0]
        if node:
            node = node.rpartition(GROUPSEP)[2] # drop leading path names for module name
        moduleInfo = self.pluginConfig.get("modules", {}).get(node)
        if moduleInfo:
            self.selectedModule = node
            name = moduleInfo["name"]
            self.moduleNameLabel.config(text=name)
            self.moduleAuthorHdr.config(state=ACTIVE)
            self.moduleAuthorLabel.config(text=moduleInfo["author"])
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo["description"])
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"]))
            self.moduleUrlHdr.config(state=ACTIVE)
            self.moduleUrlLabel.config(text=moduleInfo["moduleURL"])
            self.moduleDateHdr.config(state=ACTIVE)
            self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.modulesWithNewerFileDates else ""))
            self.moduleLicenseHdr.config(state=ACTIVE)
            self.moduleLicenseLabel.config(text=moduleInfo["license"])
            if moduleInfo.get("imports"):
                self.moduleImportsHdr.config(state=ACTIVE)
                _text = ", ".join(mi["name"] for mi in moduleInfo["imports"][:3])
                if len(moduleInfo["imports"]) >= 3:
                    _text += ", ..."
                self.moduleImportsLabel.config(text=_text)
            _buttonState = DISABLED if moduleInfo.get("isImported") else ACTIVE
            self.moduleEnableButton.config(state=_buttonState,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[moduleInfo["status"]])
            self.moduleReloadButton.config(state=_buttonState)
            self.moduleRemoveButton.config(state=_buttonState)
        else:
            self.selectedModule = None
            self.moduleNameLabel.config(text="")
            self.moduleAuthorHdr.config(state=DISABLED)
            self.moduleAuthorLabel.config(text="")
            self.moduleDescrHdr.config(state=DISABLED)
            self.moduleDescrLabel.config(text="")
            self.moduleClassesHdr.config(state=DISABLED)
            self.moduleClassesLabel.config(text="")
            self.moduleUrlHdr.config(state=DISABLED)
            self.moduleUrlLabel.config(text="")
            self.moduleDateHdr.config(state=DISABLED)
            self.moduleDateLabel.config(text="")
            self.moduleLicenseHdr.config(state=DISABLED)
            self.moduleLicenseLabel.config(text="")
            self.moduleImportsHdr.config(state=DISABLED)
            self.moduleImportsLabel.config(text="")
            self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.moduleReloadButton.config(state=DISABLED)
            self.moduleRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        initialdir = self.cntlr.pluginDir # default plugin directory
        if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory
            initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir)
        filename = self.cntlr.uiFileDialog("open",
                                           parent=self,
                                           title=_("Choose plug-in module file"),
                                           initialdir=initialdir,
                                           filetypes=[(_("Python files"), "*.py")],
                                           defaultextension=".py")
        if filename:
            # check if a package is selected (any file in a directory containing an __init__.py
            #if (os.path.basename(filename) == "__init__.py" and os.path.isdir(os.path.dirname(filename)) and
            #    os.path.isfile(filename)):
            #    filename = os.path.dirname(filename) # refer to the package instead
            self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename)
            moduleInfo = PluginManager.moduleModuleInfo(filename)
            self.loadFoundModuleInfo(moduleInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            moduleInfo = PluginManager.moduleModuleInfo(url)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundModuleInfo(moduleInfo, url)
                
    def loadFoundModuleInfo(self, moduleInfo, url):
        if moduleInfo and moduleInfo.get("name"):
            self.addPluginConfigModuleInfo(moduleInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Module is not itself a plug-in or in a directory with package __init__.py plug-in.  "),
                                   _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}")
                                   .format(url),
                                   parent=self)
        
    def checkIfImported(self, moduleInfo):
        if moduleInfo.get("isImported"):
            messagebox.showwarning(_("Plug-in is imported by a parent plug-in.  "),
                                   _("Plug-in has a parent, please request operation on the parent: \n\n{0}")
                                   .format(moduleInfo.get("name")),
                                   parent=self)
            return True
        return False
    
    def removePluginConfigModuleInfo(self, name):
        moduleInfo = self.pluginConfig["modules"].get(name)
        if moduleInfo:
            if self.checkIfImported(moduleInfo):
                return;
            def _removePluginConfigModuleInfo(moduleInfo):
                _name = moduleInfo.get("name")
                if _name:
                    for classMethod in moduleInfo["classMethods"]:
                        classMethods = self.pluginConfig["classes"].get(classMethod)
                        if classMethods and _name in classMethods:
                            classMethods.remove(_name)
                            if not classMethods: # list has become unused
                                del self.pluginConfig["classes"][classMethod] # remove class
                            if classMethod.startswith("CntlrWinMain.Menu"):
                                self.uiClassMethodsChanged = True  # may require reloading UI
                            elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                                self.modelClassesChanged = True # model object factor classes changed
                            elif classMethod == "DisclosureSystem.Types":
                                self.disclosureSystemTypesChanged = True # disclosure system types changed
                            elif classMethod.startswith("Proxy."):
                                self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed
                    for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                        _removePluginConfigModuleInfo(importModuleInfo)
                    self.pluginConfig["modules"].pop(_name, None)
            _removePluginConfigModuleInfo(moduleInfo)
            self.pluginConfigChanged = True

    def addPluginConfigModuleInfo(self, moduleInfo):
        if self.checkIfImported(moduleInfo):
            return;
        name = moduleInfo.get("name")
        self.removePluginConfigModuleInfo(name)  # remove any prior entry for this module
        def _addPlugin(moduleInfo):
            _name = moduleInfo.get("name")
            if _name:
                self.modulesWithNewerFileDates.discard(_name) # no longer has an update available
                self.pluginConfig["modules"][_name] = moduleInfo
                # add classes
                for classMethod in moduleInfo["classMethods"]:
                    classMethods = self.pluginConfig["classes"].setdefault(classMethod, [])
                    if name not in classMethods:
                        classMethods.append(_name)
                    if classMethod.startswith("CntlrWinMain.Menu"):
                        self.uiClassMethodsChanged = True  # may require reloading UI
                    elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                        self.modelClassesChanged = True # model object factor classes changed
                    elif classMethod == "DisclosureSystem.Types":
                        self.disclosureSystemTypesChanged = True # disclosure system types changed
                    elif classMethod.startswith("Proxy."):
                        self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed
            for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                _addPlugin(importModuleInfo)
        _addPlugin(moduleInfo)
        self.pluginConfigChanged = True

    def moduleEnable(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][self.selectedModule]
            if self.checkIfImported(moduleInfo):
                return;
            def _moduleEnable(moduleInfo):
                if self.moduleEnableButton['text'] == self.ENABLE:
                    moduleInfo["status"] = "enabled"
                elif self.moduleEnableButton['text'] == self.DISABLE:
                    moduleInfo["status"] = "disabled"
                for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                    _moduleEnable(importModuleInfo)
            _moduleEnable(moduleInfo)
            if self.moduleEnableButton['text'] == self.ENABLE:
                self.moduleEnableButton['text'] = self.DISABLE
            elif self.moduleEnableButton['text'] == self.DISABLE:
                self.moduleEnableButton['text'] = self.ENABLE
            self.pluginConfigChanged = True
            self.loadTreeViews()
            
    def moduleReload(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL")
            if url:
                moduleInfo = PluginManager.moduleModuleInfo(url, reload=True)
                if moduleInfo:
                    if self.checkIfImported(moduleInfo):
                        return;
                    self.addPluginConfigModuleInfo(moduleInfo)
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo["name"]), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Module error"),
                                           _("File or module cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def moduleRemove(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            self.removePluginConfigModuleInfo(self.selectedModule)
            self.pluginConfigChanged = True
            self.loadTreeViews()
                    
    def enableAll(self):
        self.enableDisableAll(True)
                    
    def disableAll(self):
        self.enableDisableAll(False)
                    
    def enableDisableAll(self, doEnable):
        for module in self.pluginConfig["modules"]:
            if not module.get("isImported"):
                moduleInfo = self.pluginConfig["modules"][module]
                def _enableDisableAll(moduleInfo):
                    if doEnable:
                        moduleInfo["status"] = "enabled"
                    else:
                        moduleInfo["status"] = "disabled"
                    for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                        _enableDisableAll(importModuleInfo)
                _enableDisableAll(moduleInfo)
                if doEnable:
                    self.moduleEnableButton['text'] = self.DISABLE
                else:
                    self.moduleEnableButton['text'] = self.ENABLE
        self.pluginConfigChanged = True
        self.loadTreeViews()