class TableView(Frame):
    OPTIONS = {'font': ('bold', 11)}

    def __init__(self, window, **kwargs):
        super().__init__(window, **kwargs)
        self.tree = Treeview(self, selectmode='browse')
        self.tree.column("#0", width=100, minwidth=75, stretch=NO)
        self.tree.heading("#0", text='row', anchor='center')
        self.scroll = Scrollbar(self, command=self.tree.yview)
        self.tree.config(yscrollcommand=self.scroll.set)
        self.scroll.pack(side=RIGHT, fill=Y)
        self.tree.pack(expand=True, side=LEFT, fill=BOTH)

    def create_columns(self, *columns):
        for column in columns:
            self.tree.column(f"{column}", width=150, minwidth=150, stretch=YES)

    def create_heading(self, *columns):
        for index, column in enumerate(columns):
            self.tree.heading(f"#{index+1}", text=f"{column}", anchor='center')

    def fill_row(self, *args):
        if args:
            self.tree.delete(*self.tree.get_children())
            for index, contact in enumerate(args):
                self.tree.insert("",
                                 'end',
                                 contact.id,
                                 text=f"{index+1}",
                                 values=list(contact.informations.values()))
        else:
            return
class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)

        self.tree = Treeview(self)

        self.tree["columns"] = ("item1", "item2")
        self.tree.heading("item1", text="Column 1")
        self.tree.heading("item2", text="Column 2")

        self.tree.insert("", 0, text="Item 1", values=("Value 1", "Value 2"))

        row2 = self.tree.insert("", 1, "row2", text="Item 2")
        self.tree.insert(row2,
                         "end",
                         "item1",
                         text="Item 1",
                         values=("3", "7"))
        self.tree.insert(row2,
                         "end",
                         "item2",
                         text="Item 2",
                         values=("2", "5"))

        self.tree.pack(expand=1, fill="both")

        self.delete = Button(self, text="Delete Row", command=self.on_delete)
        self.delete.pack(side="bottom")

    def on_delete(self):
        try:
            selected_item = self.tree.selection()[0]
            self.tree.delete(selected_item)
        except IndexError:
            pass
Exemple #3
0
def set_table(table: Treeview, data_list: list):
    """
    :param table: A Tkinter table object will be fill in data.
    :param data_list: The list of data, each data should be a tuple.
    """
    table.delete(*table.get_children())
    for i in reversed(data_list):
        table.insert('', 0, text=i[0], values=i)
Exemple #4
0
 def clear_primitive_multi_list_box(
         self, primitive_multi_list_box: ttk.Treeview) -> None:
     """
     Clears all entries of a primitive-type (str, int, etc.) storing multi list box.
     :param primitive_multi_list_box: the multi list box to be cleared
     :return: void
     """
     primitive_multi_list_box.delete(
         *primitive_multi_list_box.get_children())
Exemple #5
0
class TreeFrame(LabelFrame):
    def __init__(self, root, model: ManageUIModel):
        super().__init__(root, text="Records", padding=10)
        self.model = model
        self.packed = False

        self._edit_img = load_image("edit", width=16, color=(38, 158, 54))

        cols = ["timestamp"]
        # cols=["timestamp", "source", "hash"]

        self.tree = Treeview(self, padding=5, columns=cols)
        self.tree.heading("timestamp", text="Timestamp")
        # self.tree.heading("source", text="Data Source")
        # self.tree.heading("hash", text="Hash")
        self.tree.pack(fill=BOTH, expand=True)

        self.frm_src_btns = Frame(self, padding=5)
        self.frm_src_btns.pack(fill=X)

        def show_rebuilder():
            RebuildDialog.create_dialog(self.model.var_metarecord.get())

        self.btn_src_add = Button(self.frm_src_btns, text="Import Previous Backups", command=show_rebuilder)
        self.btn_src_add.pack(side=LEFT)

        def show_clean():
            CleanDialog.create_dialog(self.model.var_metarecord.get())

        self.btn_src_add = Button(self.frm_src_btns, text="Remove Redundant Files", command=show_clean)
        self.btn_src_add.pack(side=LEFT)

        self.model.var_metarecord.trace_add(self._metarecord_changed)

    def do_pack(self):
        if not self.packed:
            self.pack(side=TOP, anchor=N, fill=BOTH, expand=True)
            self.packed = True

    def do_unpack(self):
        if self.packed:
            self.pack_forget()
            self.packed = False

    def _metarecord_changed(self, var, oldval, newval):
        self.tree.delete(*self.tree.get_children())
        if newval is not None:
            self._setup_tree(newval)
            self.do_pack()
        else:
            self.do_unpack()

    def _setup_tree(self, mr: MetaRecord):
        for r in mr.records:
            val = self.tree.insert("", END, text=r.name, values=[r.timestamp])
Exemple #6
0
class ContactsListView(Frame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)

        self.search_text = StringVar()
        self.console_text = StringVar()

        # Treeview setup
        col_ids = ("first_name", "surname", "phone", "email", "last_edited")
        self.contacts_list = Treeview(self, columns=col_ids, show='headings')
        for col_id, text in zip(
                col_ids,
            ["First name", "Surname", "Phone", "Email", "Last edited"]):
            self.contacts_list.column(col_id, stretch=True, width=160)
            self.contacts_list.heading(col_id, text=text)

        # Search panel
        search_panel = Frame(self)
        search_entry = Entry(search_panel, textvariable=self.search_text)
        self.search_btn = Button(search_panel, text="Search")
        search_entry.pack(side=LEFT)
        self.search_btn.pack(side=LEFT)

        # Controls
        self.add_btn = Button(self, text="Add")
        self.edit_btn = Button(self, text="Edit")
        self.delete_btn = Button(self, text="Delete")
        self.console = Label(self, textvariable=self.console_text)

        # Layout
        search_panel.pack()
        self.contacts_list.pack()
        self.console.pack()
        self.delete_btn.pack(side=RIGHT)
        self.edit_btn.pack(side=RIGHT)
        self.add_btn.pack(side=RIGHT)

    def set(self, contacts):
        self.contacts_list.delete(*self.contacts_list.get_children())
        for contact_fields in contacts:
            rowid, values = str(contact_fields[0]), contact_fields[1:]
            self.contacts_list.insert('', 'end', text=rowid, values=values)
        self.log()

    def get_selected_contacts_ids(self):
        focused_rows = self.contacts_list.selection()
        return map(lambda focus: self.contacts_list.item(focus)['text'],
                   focused_rows)

    def log(self, message=''):
        self.console_text.set(message)
Exemple #7
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']
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 #9
0
class DisplayLogs(tk.Frame):

    def __init__(self, parent, controller):

        self.parent = parent
        self.controller = controller

        tk.Frame.__init__(self, parent)

        self.status2 = tk.Label(self, text="Logs", font=LARGE_FONT)
        self.status2.grid(row = 0, column = 0)

        # Player list table
        columns = ['log']
        self.loggings = Treeview(self, columns=columns, show="headings")
        self.loggings.column("log", width=415)

        for col in columns[1:]:
            self.loggings.column(col, width=1)
            self.loggings.heading(col, text=col)

        #loggings.bind('<<TreeviewSelect>>', select_router)
        self.loggings.grid(row=1,column=0)

        # LOAD IN TABLE
        txt = open("./data/gui_logs.txt", "r", encoding="latin-1")

        #self.playerlist = []
        for aline in txt:
            values2 = aline.strip("\n").split(",")
            self.loggings.insert('', 'end', values=values2)

        self.update_logs()

    # Continuously updates log table
    def update_logs(self):
        for i in self.loggings.get_children():
            self.loggings.delete(i)

        txt = open("./data/gui_logs.txt", "r", encoding="latin-1")

        self.playerlist = []
        for aline in txt:
            values2 = aline.strip("\n").split(",")
            self.loggings.insert('', 'end', values=values2)
        txt.close()
        self.loggings.yview_moveto(1)
        self.after(100, self.update_logs)
    def set_primitive_multi_list_box_elements(
            multi_list_box: ttk.Treeview,
            list_of_elements: List[tuple]) -> None:
        """
        Sets a list of elements(tuples) to be displayed by a multi list box.
        This clears the multi list box beforehand!
        :param multi_list_box: the multi list box widget to be manipulated
        :param list_of_elements: List of elements, which are themselves tuples of primitive
                data types.
        :return: void
        """
        multi_list_box.delete(*multi_list_box.get_children())

        for element in list_of_elements:
            TkValueSetter.add_primitive_multi_list_box_element(
                multi_list_box, element)
Exemple #11
0
class DataTree(Frame):
    def __init__(self, master):
        Frame.__init__(self, master, bg="black")
        scroll = Scrollbar(self)

        self.tree = Treeview(self, yscrollcommand=scroll.set)
        scroll.config(command=self.tree.yview)

        self.items = []

        self.tree.pack(side=LEFT, fill=BOTH, expand=1)
        scroll.pack(side=LEFT, fill=Y)

    def update(self, files):
        self.files = files

        # reversing, since removing a node with children removes the children as
        # well. there might be a cleaner way to do this by clearing each of the
        # file nodes, but that might add more burden to the garbage collector
        # down the line.
        for item in reversed(self.items):
            self.tree.delete(item)

        self.items = []

        for (i, datafile) in enumerate(self.files):
            self.add_file(datafile, i)

    def add_file(self, f, f_id):
        file_id = self.tree.insert("", "end", text=f.name)
        self.items.append(file_id)

        self.add_node(file_id, f.data, f_id)

    def add_node(self, p, node, f_id):
        if node.name != '':
            node_id = self.tree.insert(p, "end", text=node.name,
                                       values=(f_id, node.path))
            self.items.append(node_id)
        else:
            node_id = p

        if node.is_grp:
            for child in node.children:
                self.add_node(node_id, child, f_id)
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 #13
0
class ResultForm(tk.Frame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        self.header_label = tk.Label(self, text="All your saved passwords:", font=("roboto slab", 12, "bold"))
        self.header_label.grid(row=0, column=0, pady=(0, 5), sticky=tk.W)

        self.scrollbar_y = tk.Scrollbar(self, orient=tk.VERTICAL)
        self.tree = Treeview(self, columns=("Place", "Password"), yscrollcommand=self.scrollbar_y.set)
        self.scrollbar_y.config(command=self.tree.yview)
        self.scrollbar_y.grid(row=1, column=1, sticky="nsew")

        self.tree.heading("Place", text="Place")
        self.tree.heading("Password", text="Password")

        self.tree.column("#0", minwidth=0, width=0)
        self.tree.column("#1", width=175)
        self.tree.column("#2", width=175)

        self.style = Style()
        # noinspection SpellCheckingInspection
        self.style.configure("Treeview", rowheight=15)
        # noinspection SpellCheckingInspection
        self.style.configure("Treeview.Heading", font=("roboto slab", 10, "bold"), foreground="#a6a6a6")

        self.tree.grid(row=1, column=0)

        self.instruction_label = tk.Label(self, text="* First select an item, then choose from below",
                                          font=("roboto slab", 8, "italic"))
        self.instruction_label.grid(row=2, column=0, sticky=tk.W)

    def insert_to_tree(self, values):
        for value in values:
            self.tree.insert("", tk.END, value=value)

    def empty_tree(self):
        if self.tree.get_children():
            self.tree.delete(*self.tree.get_children())

    def return_selected_item_values(self):
        """Returns the values of the highlighted item inside TreeView"""
        highlighted_item = self.tree.selection()
        if highlighted_item:
            return tuple(self.tree.item(highlighted_item)["values"])
Exemple #14
0
class GUI:
    def __init__(self):
        self.window = Tk()
        self.window.geometry('800x600')
        self.txt = Entry(self.window, width=20)
        self.txt.grid(column=1, row=0)
        self.tree = Treeview(self.window, selectmode='browse')
        self.db = Database()
        self.lbl_url = Label(self.window, text="Введите URL")
        self.lbl_tab = Label(self.window, text="Данные из базы")

    def load_into_db(self):
        res = f'{self.txt.get()}'
        self.db.write_db(Parser(res))
        messagebox.showinfo('TAGS', str(Parser(res).tags()))

    def load_from_db(self):
        self.tree.delete(*self.tree.get_children())
        for row in self.db.read_db():
            self.tree.insert("", 'end', text=row)

    def wind(self):
        self.lbl_url.place(x=375, y=15)
        self.lbl_tab.place(x=360, y=120)
        btn = Button(self.window,
                     text="Загрузить в базу",
                     command=self.load_into_db)
        btn.grid(column=2, row=0)
        btn1 = Button(self.window,
                      text="Показать из базы",
                      command=self.load_from_db)
        btn1.grid(column=2, row=0)
        self.tree.place(x=25, y=150, width=750, height=300)
        scroll = Scrollbar(self.window,
                           orient="vertical",
                           command=self.tree.yview)
        scroll.place(x=775, y=200, height=150)
        self.tree.configure(yscrollcommand=scroll.set)
        self.txt.place(x=150, y=50, width=500, height=35)
        btn.place(x=450, y=500)
        btn1.place(x=150, y=500)
        self.window.mainloop()
Exemple #15
0
class Window(Tk):
    def __init__(self):
        super().__init__()
        self.title('Treepace Tree Transformation GUI Demo')
        self.geometry('640x400')
        self.resizable(False, False)
        self.tree_frame = Frame()
        self.tree_button = Button(self.tree_frame, text="Load tree",
                                  command=self.load)
        self.tree_button.pack(expand=True, fill=BOTH)
        self.tree_text = Text(self.tree_frame, width=20)
        self.tree_text.pack(expand=True, fill=BOTH)
        self.tree_text.insert('1.0', DEFAULT_TREE)
        self.tree_frame.pack(side=LEFT, expand=True, fill=BOTH)
        
        self.program_frame = Frame()
        self.program_button = Button(self.program_frame, text="Transform",
                                     command=self.transform)
        self.program_button.pack(expand=True, fill=BOTH)
        self.program_text = Text(self.program_frame, width=60, height=8)
        self.program_text.pack(expand=True, fill=BOTH)
        self.program_text.insert('1.0', DEFAULT_PROGRAM)
        self.tv = Treeview(self.program_frame)
        self.tv.pack(expand=True, fill=BOTH)
        self.program_frame.pack(side=LEFT, expand=True, fill=BOTH)

        GuiNode.tv = self.tv
        self.load()
    
    def load(self):
        if self.tv.exists('root'):
            self.tv.delete('root')
        program = self.tree_text.get('1.0', END)
        self.tree = Tree.load(program, IndentedText, GuiNode)
    
    def transform(self):
        try:
            self.tree.transform(self.program_text.get('1.0', END))
        except Exception as e:
            messagebox.showerror("Transformation error", e)
Exemple #16
0
    def update_data(self, table: ttk.Treeview):
        work_dict = jk.get_launch_data()
        sorted_date = sorted(work_dict, reverse=True)

        if len(sorted_date) > len(
                self.fold_iid):  # if we have new date in launches
            items = table.get_children()
            for item in items:
                table.delete(item)
            self.fold_iid = {}  # will be contain datetime:item-id as k:v
            self.get_data(table)
        else:
            for date in sorted_date:
                items = table.get_children(
                    self.fold_iid[date])  # number of items in folder
                values = work_dict[date]  # number of values in current date
                if len(values) > len(items):
                    for item in items:
                        table.delete(item)
                    for value in values:
                        table.insert(self.fold_iid[date], 'end', values=value)
        self.after(1000, self.update_data, table)
Exemple #17
0
class BlackWhite:
    def __init__(self):
        self.win = Tk()
        self.win.title("White/Black List")
        self.win.geometry('{}x{}'.format(800, 450))
        self.canvas = Canvas(self.win, bg='#36393F')
        self.frame = Frame(self.canvas, bg='#36393F', width=600, height=340)
        self.userSelected = StringVar()
        self.whitebox = Treeview(self.frame,
                                 columns=1,
                                 show="headings",
                                 height="5")
        self.blackbox = Treeview(self.frame,
                                 columns=1,
                                 show="headings",
                                 height="5")
        self.userList = Combobox(self.frame,
                                 width=20,
                                 textvariable=self.userSelected,
                                 state="readonly")
        self.user = db.getName()

    def main(self):
        self.canvas.pack(expand=TRUE, fill=BOTH)
        self.frame.pack(expand=TRUE)

        Button(self.frame,
               text="Add",
               font='Arial 10 bold',
               bg='#36393F',
               fg="#f7cc35",
               command=self.addWhite).grid(row=0, column=0)
        Button(self.frame,
               text="Remove",
               font='Arial 10 bold',
               bg='#36393F',
               fg="#f7cc35",
               command=self.removeWhite).grid(row=1, column=0, padx=10)

        self.whitebox.grid(row=0, column=1, rowspan=2)
        self.whitebox.heading(1, text="WhiteBox")
        self.whitebox.column(1, width=100)

        self.blackbox.grid(row=0, column=2, rowspan=2)
        self.blackbox.heading(1, text="BlackBox")
        self.blackbox.column(1, width=100)

        Button(self.frame,
               text="Add",
               font='Arial 10 bold',
               bg='#36393F',
               fg="#f7cc35",
               command=self.addBlack).grid(row=0, column=3)
        Button(self.frame,
               text="Remove",
               font='Arial 10 bold',
               bg='#36393F',
               fg="#f7cc35",
               command=self.removeBlack).grid(row=1, column=3, padx=10)

        db.cursor.execute(
            "SELECT whitelisted FROM white_list WHERE whitelister = '%s'" %
            self.user)
        for row in db.cursor.fetchall():
            self.whitebox.insert('', END, values=row)

        db.cursor.execute(
            "SELECT blacklisted FROM black_list WHERE blacklister = '%s'" %
            self.user)
        for row in db.cursor.fetchall():
            self.blackbox.insert('', END, values=row)

        self.userList.grid(row=2, column=0, columnspan=4, pady=10)
        self.userList['values'] = inputUsers()
        self.userList.current(0)

        self.win.mainloop()

    def addWhite(self):
        # add selected user from combobox to whitebox
        self.whitebox.insert('', END, values=self.userSelected.get())

        # add to white_list table
        db.cursor.execute("INSERT INTO white_list VALUES(%s, %s)",
                          (self.user, self.userSelected.get()))

    def removeWhite(self):
        for selected_item in self.whitebox.selection():
            whitelisted = self.whitebox.item(selected_item, 'values')[0]
            self.whitebox.delete(selected_item)
        db.cursor.execute(
            "DELETE FROM white_list WHERE whitelister = %s AND whitelisted = %s",
            (self.user, whitelisted))

    def addBlack(self):
        self.blackbox.insert('', END, values=self.userSelected.get())

        db.cursor.execute("INSERT INTO black_list VALUES(%s, %s)",
                          (self.user, self.userSelected.get()))

    def removeBlack(self):
        for selected_item in self.blackbox.selection():
            blacklisted = self.blackbox.item(selected_item, 'values')[0]
            self.blackbox.delete(selected_item)
        db.cursor.execute(
            "DELETE FROM black_list WHERE blacklister = %s AND blacklisted = %s",
            (self.user, blacklisted))
Exemple #18
0
class DebitList(Frame, MoneySubject, MoneyObserver):
    def __init__(self, parent):

        super().__init__(parent)
        MoneySubject.__init__(self)
        MoneyObserver.__init__(self)
        self.initUI()

    def initUI(self):

        self.records = []

        self.debitList = Treeview(self, height=15)
        columns = ("Amount", "Desc")
        self.debitList["columns"] = columns
        self.debitList.column("#0", width=70, minwidth=70, stretch=NO)
        self.debitList.column("Amount", width=70, stretch=NO)
        self.debitList.column("Desc", width=250, stretch=NO)
        self.debitList.heading("#0", text="Date", anchor=W)
        for field in columns:
            self.debitList.heading(field, text=field, anchor=W)

        self.debitList.pack(side=LEFT)
        self.pack()

        self.debitList.bind("<Delete>", self.keydown)

    def keydown(self, e):
        item = self.debitList.selection()
        parent = self.debitList.parent(item)
        if item != () and parent != '':
            values = self.debitList.item(item)['values']
            amount = float(values[0][1:])
            self.moneyNotify({"debit": -amount})
            self.debitList.delete(item)
            self.records.remove({
                "debit": amount,
                "desc": str(values[1]),
                "date": parent
            })

    def reset(self):
        self.records = []
        for child in self.debitList.get_children():
            self.debitList.delete(child)

    def export(self):

        return self.records

    def restore(self, debits, startDate):

        self.reset()
        self.setStartDate(startDate)
        dateTable = {}
        for d in range(7):
            day = startDate + timedelta(days=d)
            dateStr = day.strftime("%d/%m")
            dateTable[dateStr] = day
        for debit in debits:
            debit["date"] = dateTable[debit["date"]]
            self.moneyUpdate(debit)
            self.moneyNotify(debit)

    def moneyUpdate(self, monies):
        if "debit" in monies:
            dateStr = monies["date"].strftime("%d/%m")

            toSave = monies
            toSave["date"] = dateStr
            self.records.append(toSave)

            values = (f"${monies['debit']}", monies["desc"])
            self.debitList.insert(dateStr, "end", text="", values=values)

    def setStartDate(self, startDate):

        for d in range(7):
            day = startDate + timedelta(days=d)
            dateStr = day.strftime("%d/%m")
            self.debitList.insert("",
                                  "end",
                                  id=dateStr,
                                  text=dateStr,
                                  values=("", ""))
Exemple #19
0
class IncomeEntry(Frame, MoneySubject):
    def __init__(self, parent):

        super().__init__(parent)
        MoneySubject.__init__(self)
        self.parent = parent
        self.initUI()

    def initUI(self):

        self.entries = {}
        self.records = []
        titleFrame = Frame(self, borderwidth=1)
        titleFrame.pack(fill=BOTH, expand=True)

        lbl = Label(titleFrame, text="Incomes:", font=("Ubuntu", 20))
        lbl.pack(side=LEFT)

        entryFrame = Frame(self, borderwidth=1)

        for data in [("Hours", 3), ("Rate", 5), ("Desc", 15)]:
            dataFrame = Frame(entryFrame, borderwidth=2)
            lbl = Label(dataFrame, text=data[0], font=("Ubuntu", 10))
            lbl.pack()
            entry = Entry(dataFrame, width=data[1])
            entry.pack()
            self.entries[data[0]] = entry

            dataFrame.pack(side=LEFT)

        okButton = Button(entryFrame, text="Submit", command=self.submitIncome)
        okButton.pack(side=LEFT)
        entryFrame.pack(fill=BOTH, expand=True)

        self.incomeList = Treeview(self, height=3)
        columns = ("Hours", "Rate", "Desc", "Total")
        self.incomeList["columns"] = columns
        self.incomeList.column("#0", width=0, minwidth=0, stretch=NO)
        for field in columns:

            self.incomeList.column(field, width=100, stretch=NO)
            self.incomeList.heading(field, text=field, anchor=W)

        self.incomeList.pack(side=LEFT)

        self.pack(fill=BOTH, expand=False)

        self.incomeList.bind("<Delete>", self.keydown)

    def keydown(self, e):
        item = self.incomeList.selection()
        if item != ():
            values = self.incomeList.item(item)['values']
            hours = float(values[0])
            rate = float(values[1])
            desc = str(values[2])
            amt = hours * rate
            self.moneyNotify({"income": -amt})
            self.incomeList.delete(item)
            self.records.remove({"hours": hours, "rate": rate, "desc": desc})

    def _emitIncome(self, hours, rate, desc):
        values = (hours, rate, desc, f"${hours*rate:.2f}")
        self.incomeList.insert("", "end", text="", values=values)
        self.records.append({"hours": hours, "rate": rate, "desc": desc})
        self.moneyNotify({"income": hours * rate})

    def submitIncome(self):
        # consume input in entry boxes and store in tree
        hours = float(self.entries["Hours"].get())
        rate = float(self.entries["Rate"].get())
        desc = self.entries["Desc"].get()
        self._emitIncome(hours, rate, desc)
        for entry in self.entries.values():
            entry.delete(0, 'end')

    def clear(self):

        for child in self.incomeList.get_children():
            self.incomeList.delete(child)

        self.records = []

    def export(self):
        return self.records

    def restore(self, incomes, startDate):
        self.clear()
        for income in incomes:
            self._emitIncome(income["hours"], income["rate"], income["desc"])
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() ]
Exemple #21
0
class DosyaArayici(Tk):
    def __init__(self):
        super(DosyaArayici, self).__init__()
        self.pathIndexed = False
        self.indexedFiles = []
        # results = { fileName: {"wordScore" : Number, "lModScore": Number}}
        self.results = {}
        self.searchFilter = {
            "code": [
                "text/javascript", "application/javascript", "text/css",
                "text/x-python", "text/x-c", "text/x-java-source", "java",
                "application/java-vm", "text/html"
            ],
            "text": ["application/rtf", "text/plain"]
        }
        self.paginationIndices = (0, 10)

        # UI settings
        self.title("YAZ104")
        self.geometry("900x700+300+100")
        self.configure(background="grey")
        self.grid_columnconfigure(0, weight=1)

        # UI vars
        self.mPadding = 65
        self.pageNumber = StringVar()
        self.directory = StringVar()
        self.searchDepth = StringVar()
        self.searchBar = StringVar()
        self.weight1 = StringVar()
        self.weight2 = StringVar()
        self.wordCb = IntVar()
        self.lmodCb = IntVar()
        self.passedTime = StringVar()
        self.numOfFiles = StringVar()
        self.font = ("Courier", 15)

        # First label
        Label(self, text="Dosya Arayıcı", font=("Courier", 20),
              bg="grey").grid(row=0, column=0)

        # Seperator
        Frame(self, bg="black", height=5, width=700).grid(row=1,
                                                          column=0,
                                                          sticky="EW")

        # Path
        self.ui_path = Frame(self, background="grey")
        self.ui_path.grid(row=2, column=0, sticky="W", padx=50)

        Label(self.ui_path,
              text="Başlangıç Dizini:",
              bg="grey",
              font=self.font).grid(row=0, column=0, sticky="NW", pady=8)
        self.directory.set("path/to/search")

        self.directory.trace_add("write", self.UI_pathChange)
        Entry(self.ui_path, width=30, fg="black",
              textvariable=self.directory).grid(row=0,
                                                column=2,
                                                padx=70,
                                                pady=5)

        # Depth
        self.ui_depth = Frame(self.ui_path, background="grey")
        self.ui_depth.grid(row=1, column=0, sticky="w")

        Label(self.ui_depth, text="Derinlik:", bg="grey",
              font=self.font).grid(row=0, column=0, sticky="SW", pady=5)
        self.searchDepth.set("1")
        Entry(self.ui_depth,
              width=3,
              fg="black",
              textvariable=self.searchDepth).grid(row=0, column=1)

        # Create indices
        Button(self.ui_path,
               text="İndex Oluştur",
               command=self.UI_indexOlustur,
               highlightbackground='#3E4149').grid(row=1,
                                                   column=2,
                                                   padx=70,
                                                   pady=5)

        # Seperator
        Frame(self, bg="black", height=5, width=700).grid(row=3,
                                                          column=0,
                                                          sticky="EW")

        # Main Body
        self.searchBar.set("kelime1 kelime2 kelime3")
        Entry(self, width=30, fg="black",
              textvariable=self.searchBar).grid(row=4,
                                                column=0,
                                                padx=self.mPadding,
                                                pady=10,
                                                sticky="W")

        # Filtreler framei
        self.filters = Frame(self, background="grey")
        self.filters.grid(row=5,
                          column=0,
                          padx=self.mPadding,
                          pady=5,
                          sticky="NWE")
        self.filters.grid_columnconfigure(0, weight=1)
        self.filters.grid_columnconfigure(1, weight=1)
        self.filters.grid_columnconfigure(2, weight=1)
        self.filters.grid_columnconfigure(3, weight=1)

        Label(self.filters, text="Sıralama kriteri", bg="grey",
              font=self.font).grid(row=0, column=0, sticky='NW')
        Label(self.filters, text="Ağırlıklar", bg="grey",
              font=self.font).grid(row=0, column=1, sticky='N')
        Label(self.filters, text="Filtre", bg="grey",
              font=self.font).grid(row=0, column=2, sticky='N')

        # Sorting filters
        self.wordCb.set(False)
        self.lmodCb.set(False)
        Checkbutton(self.filters,
                    text="Kelime uzaklığı",
                    background="grey",
                    fg="black",
                    font=self.font,
                    variable=self.wordCb,
                    onvalue=1,
                    offvalue=0,
                    height=2).grid(row=1, column=0, sticky="w")
        Checkbutton(self.filters,
                    text="Erişim zamanı",
                    background="grey",
                    fg="black",
                    font=self.font,
                    variable=self.lmodCb,
                    onvalue=1,
                    offvalue=0,
                    height=2).grid(row=2, column=0, sticky="w")

        # Weights
        self.weight1.set("1")
        self.weight2.set("1")
        Entry(self.filters, width=3, fg="black",
              textvariable=self.weight1).grid(row=1, column=1)
        Entry(self.filters, width=3, fg="black",
              textvariable=self.weight2).grid(row=2, column=1)

        # ListBox for filters
        self.listBox = Listbox(self.filters,
                               selectmode=MULTIPLE,
                               bg="#e3e3e3",
                               fg="black",
                               width=13,
                               height=3)
        self.listBox.insert(0, "Düz metin")
        self.listBox.insert(1, "Program kodu")
        self.listBox.selection_clear(0, END)
        self.listBox.selection_set(0, 1)
        self.listBox.grid(row=1, column=2)

        # Search button
        Button(self.filters,
               text="Ara",
               command=self.UI_search,
               highlightbackground='#3E4149',
               width=9).grid(row=1, column=3)

        # List and pagination
        self.files = Frame(self, background="grey")
        self.files.grid(row=6, column=0)

        # search time
        self.passedTime.set("Süre: 0")
        self.numOfFiles.set("Dosya sayısı: 0")
        Label(self.files,
              textvariable=self.passedTime,
              bg="grey",
              font=self.font).grid(row=0, column=0, sticky='NE')
        Label(self.files,
              textvariable=self.numOfFiles,
              bg="grey",
              font=self.font).grid(row=0, column=0, sticky='NW')

        # treeView
        self.resultView = Treeview(self.files, height=14)
        self.resultView["columns"] = ("Path", "size", "word score",
                                      "lmod score")
        self.resultView.column("#0",
                               width=30,
                               minwidth=30,
                               stretch=YES,
                               anchor=W)
        self.resultView.column("Path",
                               width=600,
                               minwidth=550,
                               stretch=NO,
                               anchor=W)
        self.resultView.column("size",
                               width=40,
                               minwidth=35,
                               stretch=NO,
                               anchor=W)
        self.resultView.column("word score",
                               width=80,
                               minwidth=80,
                               stretch=NO,
                               anchor=E)
        self.resultView.column("lmod score",
                               width=80,
                               minwidth=80,
                               stretch=NO,
                               anchor=E)

        self.resultView.heading("#0", text="#", anchor=W)
        self.resultView.heading("Path", text="Mutlak patika", anchor=W)
        self.resultView.heading("size", text="Boyut", anchor=W)
        self.resultView.heading("word score", text="Kelime Puani", anchor=W)
        self.resultView.heading("lmod score", text="Erişim Puani", anchor=W)

        self.resultView.grid(row=1, column=0)

        self.pagination = Frame(self.files, background="grey")
        self.pagination.grid(row=2, column=0, sticky="ES", pady=5)

        self.pageNumber.set("1")

        Label(self.pagination, text="Sayfa:", bg="grey",
              font=self.font).grid(row=0, column=0, padx=2)
        Entry(self.pagination,
              width=5,
              font=self.font,
              fg="black",
              textvariable=self.pageNumber,
              state='readonly',
              justify=CENTER).grid(row=0, column=2, padx=2)

        self.pageDown = Button(self.pagination,
                               text="Önceki",
                               highlightbackground='#3E4149',
                               command=self.UI_pageDown,
                               state=DISABLED,
                               width=5,
                               height=2)
        self.pageDown.grid(row=0, column=1, padx=2)

        self.pageUp = Button(self.pagination,
                             text="Sonraki",
                             highlightbackground='#3E4149',
                             command=self.UI_pageUp,
                             state=DISABLED,
                             width=5,
                             height=2)
        self.pageUp.grid(row=0, column=3, padx=2)

        # init
        self.createTables()
        self.searcher = Searcher(self.words, self.files)

    def __del__(self):
        self.close()

    def close(self):
        if hasattr(self, 'content'):
            self.words.close()

    # --------------------
    # CRAWLER
    # --------------------

    # shelve veritabanı oluşturma
    def createTables(self):
        # files = {path: fileContent}
        self.files = shelve.open('files.db', writeback=True, flag='n')
        # words = {
        #     word: [
        #         {path : [indices] },
        #         {path2: [indices2] }
        #     ],
        #     word2: [
        #         {path3 : [indices3] },
        #         {path2: [indices4] }
        #     ]
        # }
        self.words = shelve.open('words.db', writeback=True, flag='n')

    # filtreleri almak
    def getSelectedFilters(self):
        selection = self.listBox.curselection()
        sFilter = []
        for i in selection:
            if i == 0:
                for i in self.searchFilter["text"]:
                    sFilter.append(i)
            if i == 1:
                for i in self.searchFilter["code"]:
                    sFilter.append(i)
        return sFilter

    # dosya indexli mi
    def isIndexed(self, file):
        if file in self.indexedFiles:
            with open(file, "r") as f:
                content = f.read()
                f.close()
                if content != self.files[file]:
                    return False
            return True
        else:
            return False

    # İndexlenmemiş dosyayı veri tabanına kaydetme
    def indexFile(self, file, path):
        fullPath = path + os.path.sep + file
        if self.isIndexed(fullPath):
            print("Skipping ", file, ", Already indexed")
            return False

        print("INDEXING: ", file)

        with open(fullPath, "r") as f:
            try:
                # read content
                content = f.read()
            except UnicodeDecodeError:
                messagebox.showwarning("Decode hatası",
                                       "{} dosyası okunamadı".format(fullPath))
                return False
            # update files db
            self.files.update({fullPath: content})
            # split content to words
            splitted = content.split()
            for word in splitted:
                # calculate indices
                indices = [i for i, x in enumerate(splitted) if x == word]
                # update index dict
                if word in self.words.keys():
                    new = {fullPath: indices}
                    if new not in self.words[word]:
                        self.words[word].append(new)
                else:
                    self.words.update({word: [{fullPath: indices}]})
            self.indexedFiles.append(fullPath)
            f.close()
        return True

    # os.walk() metodunun herhangi bir depth parametresi var mı diye araştırırken buldum.
    # Sorunumu tam olarak çözdüğü için kullanmak istedim.
    # kaynak: https://stackoverflow.com/questions/229186/os-walk-without-digging-into-directories-below
    def walklevel(self, some_dir, level=1):
        some_dir = some_dir.rstrip(os.path.sep)
        try:
            assert os.path.isdir(some_dir)
        except AssertionError:
            messagebox.showerror("Patika Hatası",
                                 "Belirtilen patika bulunamadı")
        num_sep = some_dir.count(os.path.sep)
        for root, dirs, files in os.walk(some_dir):
            yield root, dirs, files
            num_sep_this = root.count(os.path.sep)
            if num_sep + level <= num_sep_this:
                del dirs[:]

    # Dosyaları tarayan ana fonksiyon
    def fileIndexer(self):
        self.words.clear()
        targetDir = self.directory.get()
        numOfIndexedFiles = 0
        try:
            depth = int(self.searchDepth.get())
        except Exception:
            messagebox.showerror("Hata",
                                 "Lütfen derinlik için bir tamsayı girin")
            return

        for path, dirs, files in self.walklevel(targetDir, depth):
            for file in files:
                f = self.indexFile(file, path)
                if f:
                    numOfIndexedFiles += 1

        self.pathIndexed = True
        messagebox.showinfo(
            "tamamlandı", "İndexleme tamamlandı. {} dosya indexlendi".format(
                numOfIndexedFiles))

    # --------------------
    # UI FONKSİYONLARI
    # --------------------
    def UI_indexOlustur(self):
        self.fileIndexer()

    # Girdi olan ağırlıkları alan fonksiyon
    def getWeights(self):
        try:
            w1 = int(self.weight1.get())
        except Exception:
            w1 = None

        try:
            w2 = int(self.weight2.get())
        except Exception:
            w2 = None

        return (w1, w2)

    # TreeView'i gğncelleyen fonksiyon
    def ui_insert_resultView(self):
        # resultView'i temizle
        self.resultView.delete(*self.resultView.get_children())
        # sıralama ölçütlerini al
        wordOrd = self.wordCb.get()
        lmodOrd = self.lmodCb.get()
        ind = 1
        # indexleri al
        pInd1, pInd2 = self.paginationIndices
        # sıralama ölçeklerine göre sırala
        # (Her iki ölçüt de seçildiğinde kararsız davranıyor)
        if wordOrd and lmodOrd:
            sort = sorted(self.results,
                          key=lambda x:
                          (self.results[x]['word'], self.results[x]['lmod']),
                          reverse=True)
            for path in sort[pInd1:pInd2]:
                size = os.stat(path).st_size
                self.resultView.insert(
                    "",
                    ind,
                    text=str(ind + pInd1),
                    values=(path, size, self.results[path]['word'],
                            str(self.results[path]['lmod'])[0:5]))
                ind += 1
        elif wordOrd:
            sort = sorted(self.results,
                          key=lambda x: (self.results[x]['word']),
                          reverse=True)
            for path in sort[pInd1:pInd2]:
                size = os.stat(path).st_size
                self.resultView.insert(
                    "",
                    ind,
                    text=str(ind + pInd1),
                    values=(path, size, self.results[path]['word'],
                            str(self.results[path]['lmod'])[0:5]))
                ind += 1
        elif lmodOrd:
            sort = sorted(self.results,
                          key=lambda x: (self.results[x]['lmod']),
                          reverse=True)
            for path in sort[pInd1:pInd2]:
                size = os.stat(path).st_size
                self.resultView.insert(
                    "",
                    ind,
                    text=str(ind + pInd1),
                    values=(path, size, self.results[path]['word'],
                            str(self.results[path]['lmod'])[0:5]))
                ind += 1

    #
    def UI_search(self):
        start = time.time()
        # path girilmiş mi
        if self.pathIndexed:
            # bir sıralama ölçütü seçilmiş mi
            wordOrd = self.wordCb.get()
            lmodOrd = self.lmodCb.get()
            if wordOrd or lmodOrd:
                w1, w2 = self.getWeights()
                # her iki siralama olcutu secilmis mi secilmisse weightler girilmis mi
                if self.wordCb.get() and self.lmodCb.get(
                ) and not w1 and not w2:
                    messagebox.showerror(
                        "Hata", "En az 1 sayısal değerde agırlık girin")
                    return
                # Kategori secimini kontrol et
                FILTERS = self.getSelectedFilters()
                if len(FILTERS) <= 0:
                    messagebox.showerror("Hata",
                                         "En az 1 dosya kategorisi seçin")
                    return
                else:
                    # search kelimesini al
                    q = self.searchBar.get()
                    if len(q) <= 0:
                        messagebox.showwarning(
                            "Hata", "Aramak istediğiniz kelimeyi girin")
                        return
                    # " isaretine gore inputu ayarla
                    if '"' in q:
                        q = q.split('"')
                        q = [w.strip() for w in q if len(w) > 0]
                    else:
                        q = q.split()
                    # ayarlanan inputu searcher'a gonder
                    self.results = self.searcher.query(q, FILTERS, (w1, w2))
                    # sonuclari degerlendir
                    if self.results:
                        self.ui_insert_resultView()
                        if len(self.results.keys()) > 10:
                            self.pageUp.config(state=NORMAL)
                        else:
                            self.pageUp.config(state=DISABLED)
                        end = time.time()
                        c = end - start
                        minutes = c // 60 % 60
                        seconds = c % 60
                        self.numOfFiles.set("Dosya sayisi: " +
                                            str(len(self.results.keys())))
                        self.passedTime.set("Sure: {}".format(minutes +
                                                              (seconds / 100)))
                        print("Sure: {}".format(minutes + (seconds / 100)))
                    else:
                        messagebox.showwarning(
                            "Uyarı", "Aradığınız kelimeler bulunamadı")
                        return
            else:
                messagebox.showerror("Hata", "Bir siralama olcutu belirtin")
                return
        else:
            messagebox.showerror("Hata", "Önce indexleme yapmak zorundasınız")
            return

    # Path enrtybox değiştiği zaman indexleme zorunluluğu getir.
    def UI_pathChange(self, mode, a, c):
        self.pathIndexed = False

    # pagination için buton fonksiyonları
    def UI_pageUp(self):
        maxInd = len(self.results)
        print(maxInd)
        ind1, ind2 = self.paginationIndices
        ind1 += 10
        ind2 += 10
        print(ind2)
        if ind2 >= maxInd:
            ind2 = maxInd
            self.pageUp.config(state=DISABLED)
            print("DISABLED")
        self.paginationIndices = (ind1, ind2)
        self.pageDown.config(state=NORMAL)
        self.pageNumber.set(str(int(self.pageNumber.get()) + 1))
        self.ui_insert_resultView()

    def UI_pageDown(self):
        minInd = 0
        ind1, ind2 = self.paginationIndices
        ind1 -= 10
        ind2 -= 10
        if ind1 <= minInd:
            ind1 = minInd
            self.pageDown.config(state=DISABLED)
        if ind2 < 10:
            ind2 = 10
        self.paginationIndices = (ind1, ind2)
        self.pageUp.config(state=NORMAL)
        self.pageNumber.set(str(int(self.pageNumber.get()) - 1))
        self.ui_insert_resultView()
    def setUI(self):
        self.photo = ImageTk.PhotoImage(Image.open('淘宝&天猫.jpg').resize((320,320),Image.ANTIALIAS))
        self.photoLabel = Label( self, image=self.photo, width=320, height=320 )
        # start_button = Button( self, text=u"开始", width=4, height=6, command=self.start_crawl )
        # stop_button = Button( self, text=u"停止", width=4, height=6, command=self.stop_crawl )
        # setting_button = Button( self, text=u"设置", width=4, height=6, command=self.setup_config )
        # directory_button = Button( self, text=u"目录", width=4, height=6, command=self.open_finder )

        start_button = Button(self, text=u"开始", width=7, height=2, command=self.start_crawl,state=ACTIVE)
        stop_button = Button(self, text=u"暂停", width=7, height=2, command=self.stop_crawl,state=ACTIVE)
        setting_button = Button(self, text=u"设置", width=7, height=2, command=self.setup_config,state=ACTIVE)
        directory_button = Button(self, text=u"查询", width=7, height=2,command=self.robo3t,state=ACTIVE)

        returnImg = Image.open('返回.jpg').resize((30, 30), Image.ANTIALIAS)
        self.returnPhoto = ImageTk.PhotoImage(returnImg)

        return_button = Button(self,width=30,height=30,command=self.returnPrimary,image=self.returnPhoto,text = u'返回',state=ACTIVE)
        return_button.place(x=2,y=2)



        # 无需设置修改
        if self.startFlag == 1:
            time.sleep( 1 )
            print( "******" )
            self.downloadSpeed = random.randint( SpeedLimited - 100, SpeedLimited )

        self.downloadingSpeed = Label( self, text=u"下载速度:" + str( self.downloadSpeed ) + 'kb / s')

        # 需要用设置修改
        self.threadingNum = Label( self, text=u"线程数:" + str( self.ThreadNum ) )
        self.delayTime = Label( self, text=u"下载延时:" + str( self.DelayTime ) )
        self.crawlTimeLabel = Label( self, text=u"爬取时间:" + str( self.CrawlTime ) )

        # self.photoLabel.grid( row=0, rowspan=4, pady=20, padx=20 )
        # start_button.grid( row=0, column=1, padx=60 )
        # setting_button.grid( row=2, column=1, padx=60 )
        # stop_button.grid( row=1, column=1, padx=60 )
        # directory_button.grid( row=3, column=1, padx=60 )
        #
        # self.downloadingSpeed.grid( row=0, column=2, padx=60, sticky=W )
        # self.threadingNum.grid( row=1, column=2, padx=60, sticky=W )
        # self.delayTime.grid( row=2, column=2, padx=60, sticky=W )
        # self.crawlTimeLabel.grid( row=3, column=2, padx=60, sticky=W )

        self.photoLabel.place(x=20, y=20)
        start_button.place(x=420, y=65)
        setting_button.place(x=540, y=65)
        stop_button.place(x=420, y=180)
        directory_button.place(x=540, y=180)

        self.downloadingSpeed.place(x=680, y=65)
        self.threadingNum.place(x=680, y=120)
        self.delayTime.place(x=680, y=175)
        self.crawlTimeLabel.place(x=680, y=230)



        bottomFrame = Frame( self, width=80 )
        # bottomFrame.grid( row=5, column=0, columnspan=3, padx=24 )

        bottomFrame.place(x=35, y=390)


        scrollBar = Scrollbar( bottomFrame )
        scrollBar.pack( side=RIGHT, fill=Y )

        # 进度条位置
        self.ProgressBar = Progressbar( self, orient="horizontal", length=320, mode='determinate' )

        # self.ProgressBar.grid( row=4, column=2, columnspan=2, sticky=W + E)
        self.ProgressBar.place(x=400, y=300)

        tree = Treeview( bottomFrame, column=('c1', 'c2', 'c3', 'c4', 'c5', 'c6'), show="headings",
                         yscrollcommand=scrollBar.set )
        tree.column( 'c1', width=220, anchor='center' )
        tree.column( 'c2', width=80, anchor='center' )
        tree.column( 'c3', width=80, anchor='center' )
        tree.column( 'c4', width=80, anchor='center' )
        tree.column( 'c5', width=120, anchor='center' )
        tree.column( 'c6', width=120, anchor='center' )
        # 设置每列表头标题文本
        tree.heading( 'c1', text='标题' )
        tree.heading( 'c2', text='日期' )
        tree.heading( 'c3', text='作者' )
        tree.heading( 'c4', text='浏览量' )
        tree.heading( 'c5', text='关键词' )
        tree.heading( 'c6', text='链接' )

        tree.pack( side=LEFT, fill="both" )

        scrollBar.config( command=tree.yview )

        items = tree.get_children()
        for item in items:
            tree.delete( item )
Exemple #23
0
class ViewStudentList(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.controller = controller

        self.student_tree = Treeview(self,
                                     columns=('#1', '#2', '#3', '#4', '#5',
                                              '#6'))

        self.student_tree.heading('#1', text='Student Name')
        self.student_tree.heading('#2', text='Subject Name')
        self.student_tree.heading('#3', text='IA1 Marks')
        self.student_tree.heading('#4', text='IA2 Marks')
        self.student_tree.heading('#5', text='IA3 Marks')
        self.student_tree.heading('#6', text='External Marks')

        self.student_tree.column('#1', stretch=YES, width=95)
        self.student_tree.column('#2', stretch=YES, width=205)
        self.student_tree.column('#3', stretch=YES, width=70)
        self.student_tree.column('#4', stretch=YES, width=70)
        self.student_tree.column('#5', stretch=YES, width=70)
        self.student_tree.column('#6', stretch=YES, width=90)

        self.student_tree.grid(row=2,
                               column=0,
                               columnspan=10,
                               padx=10,
                               pady=10,
                               sticky='nsew')
        self.student_tree['show'] = 'headings'

        student_usn = get_student_usns()

        option = []

        for name in student_usn:
            option.append(name)

        options = list(set(option))  #to obtain only unique events
        self.variable = StringVar(self)
        self.variable.set(options[0])
        self.variable.trace("w", self.update_table)

        self.select = OptionMenu(self,
                                 self.variable,
                                 *options,
                                 options[0],
                                 command=self.get_value).grid(row=1,
                                                              column=2,
                                                              padx=10,
                                                              pady=10)

        Label(self, text=" Student USN", font=10).grid(row=1,
                                                       column=0,
                                                       padx=10,
                                                       pady=10,
                                                       sticky="W")

        back_btn = Button(self,
                          text="Back",
                          command=lambda: controller.show_frame(Main),
                          width=30,
                          fg="#000fc0")
        back_btn.grid(row=3, column=0, padx=20, pady=20, sticky="W")

        heading_label = Label(self, text="View Student Details", font=MED_FONT)
        heading_label.grid(row=0, column=0, padx=5, pady=5, sticky="W")

    def update_table(self, *args):
        self.student_tree.delete(*self.student_tree.get_children())
        student_usn = self.variable.get()

        student_list = view_students([
            student_usn,
        ])

        for students in student_list:
            self.student_tree.insert("",
                                     'end',
                                     values=[
                                         students.student_name,
                                         students.subject_name,
                                         students.internal_assessment_1_marks,
                                         students.internal_assessment_2_marks,
                                         students.internal_assessment_3_marks,
                                         students.external_marks
                                     ])

    def get_value(self, value):
        self.id = value
class ComponentsDumpWindow(Toplevel):
	def __init__(self, application, barNumber = None, **kwargs):
		Toplevel.__init__(self)
		
		self.application = application
		self.barNumber = barNumber
		
		
		self.fromLabel = Label(self)
		self.fromLabel.grid(column = 0, row = 0)
		
		self.fromVar = StringVar()
		self.fromEntry = Entry(self, textvariable = self.fromVar, justify = RIGHT)
		self.fromEntry.grid(column = 1, row = 0, sticky = W + E)
		self.columnconfigure(1, weight = 1)
		
		
		self.toLabel = Label(self)
		self.toLabel.grid(column = 2, row = 0)
		
		self.toVar = StringVar()
		self.toEntry = Entry(self, textvariable = self.toVar, justify = RIGHT)
		self.toEntry.grid(column = 3, row = 0, sticky = W + E)
		self.columnconfigure(3, weight = 1)
		
		
		self.stepLabel = Label(self, text = "dx:")
		self.stepLabel.grid(column = 4, row = 0)
		
		self.stepVar = StringVar()
		self.stepEntry = Entry(self, textvariable = self.stepVar, justify = RIGHT)
		self.stepEntry.grid(column = 5, row = 0, sticky = W + E)
		self.columnconfigure(5, weight = 1)
		
		
		self.calculateButton = Button(self, text = "Рассчитать",
									  command = self.onCalculateButtonClicked)
		self.calculateButton.grid(column = 6, row = 0, columnspan = 2)
		
		
		# Таблица рассчитанных значений
		columns = ("№ стержня", "x", "Nx", "U", "σ")
		
		self.tree = Treeview(self, columns = columns, displaycolumns = columns)
		self.tree.grid(column = 0, row = 1, columnspan = 7, sticky = W + N + E + S)
		self.tree.column("#0", width = 0, stretch = 0)
		
		# Настройки отображения таблицы
		self.tree.column(columns[0], anchor = CENTER)
		self.tree.heading(columns[0], text = columns[0], anchor = CENTER)
		
		for x in columns[1:]:
			self.tree.column(x, anchor = E)
			self.tree.heading(x, text = x, anchor = E)
		
		self.rowconfigure(1, weight = 1)
		
		
		self.bind("<Destroy>", self.onWindowDestroy)
		
		
		self.updateTitles()
		self.onConstructionChanged(False)
	
	
	def updateTitles(self):
		if self.barNumber is None:
			titleDescStr = ""
			xDescStr     = "global"
		else:
			titleDescStr = "%sСтержень (%d)" % (self.application.nameDelim, self.barNumber)
			xDescStr     = "local"
		
		self.title("%s%sКомпоненты%s" \
				   % (self.application.name, self.application.nameDelim, titleDescStr))
		
		self.fromLabel["text"] = "От x(" + xDescStr + "):"
		self.toLabel["text"] = "До x(" + xDescStr + "):"
	
	
	def onWindowDestroy(self, event):
		self.application.onWindowDestroy(self)
	
	
	def onCalculateButtonClicked(self):
		try:
			self.calculate()
		except Exception as e:
			self.showError(e)
	
	
	def onConstructionChanged(self, constructed = True):
		if not constructed:
			for var in self.fromVar, self.toVar, self.stepVar:
				var.set("0")
			return
		
		try:
			self.calculate()
		except Exception:
			self.clear()
	
	
	def onPointCalculated(self, barNumber, x, N, U, Sigma):
		if self.barNumber is not None and barNumber != self.barNumber:
			return
		
		self.tree.insert(parent = "", index = "end",
						 values = ("—" if barNumber is None else str(barNumber),
								   "%.14f" % x, "%.14f" % N,
								   "%.14f" % U, "%.14f" % Sigma))
	
	
	def clear(self):
		self.tree.delete(*self.tree.get_children())
	
	
	def calculate(self):
		self.clear()
		
		if self.barNumber not in range(0, self.application.logic.barsCount()):
			self.barNumber = None
			self.updateTitles()
		
		for var in self.fromVar, self.toVar, self.stepVar:
			try:
				float(var.get())
			except ValueError:
				var.set("0")
		
		xFrom = float(self.fromVar.get())
		xTo = float(self.toVar.get())
		xStep = float(self.stepVar.get())
		
		self.application.logic.calculateComponents(xFrom, xTo, xStep, barNumber = self.barNumber,
												   onPointCalculated = self.onPointCalculated)
	
	
	def showError(self, message):
		tkinter.messagebox.showerror("Ошибка", message)
Exemple #25
0
class NameView(object):
    """Shows a treeview of unique names."""

    def __init__(self, master, names):
        self.widget = Frame(master)
        self._tree = Treeview(self.widget, columns='name')
        self._tree.grid(row=0,column=0, sticky=(N,S,W,E))
        self._tree.view = self
        self.widget.columnconfigure(0, weight=1)
        self.widget.rowconfigure(0,weight=1)
        self._tree.column('name', width=50)
        self._tree['show'] = 'tree'
        actions = {'edit': lambda e: self.edit(),
                'search': lambda e: self.search(),
                'focus_next': lambda e: self.focus_next(),
                'focus_prev': lambda e: self.focus_prev(),
                'select': lambda e: self._tree.selection_toggle(self._tree.focus()),
                'clear_selection': lambda e: self._tree.selection_set([])
                }
        kb.make_bindings(kb.tagview, actions, self._tree.bind)
        self._iids = dict()
        self._names = dict()
        logger.debug('Names: %s', names)
        self.widget.focus_set = self._tree.focus_set
        for name in sorted(names):
            iid = self._tree.insert('', 'end', text=name)
            self._names[iid] = name
            self._iids[name] = iid
        self._scroll = Scrollbar(self.widget, command=self._tree.yview)
        self._tree['yscrollcommand'] = self._scroll.set
        self._scroll.grid(row=0, column=1, sticky=(N, S))
        self.widget.columnconfigure(1, weight=0)


    def selection(self):
        logger.debug('Selection: %s', self._tree.selection())
        return [self._names[iid] for iid in self._tree.selection()]

    def edit(self):
        self._tree.event_generate('<<NameViewEdit>>')

    def search(self):
        if len(self._tree.selection()) == 0:
            self._tree.selection_add(self._tree.focus())
        self._tree.event_generate('<<NameViewSearch>>')

    def append(self, names):
        logger.debug('Append names: %s', names)
        for name in names:
            if name not in self._names.values():
                iid = self._tree.insert('', 'end', text=name)
                self._names[iid] = name
                self._iids[name] = iid

    def delete(self, name):
        self._tree.delete(self._iids[name])
        del self._names[self._iids[name]]
        del self._iids[name]

    def _focus(self, iid):
        self._tree.focus(iid)
        self._tree.see(iid)

    def focus_next(self):
        cur_iid = self._tree.focus()
        next_iid = self._tree.next(cur_iid)
        if next_iid == '':
            iids = self._tree.get_children()
            next_iid = iids[0]
        self._focus(next_iid)

    def focus_prev(self):
        cur_iid = self._tree.focus()
        prev_iid = self._tree.prev(cur_iid)
        if prev_iid == '':
            iids = self._tree.get_children()
            prev_iid = iids[-1]
        self._focus(prev_iid)

    def jump_to(self, name):
        try:
            iid = self._iids[name]
            self._focus(iid)
        except KeyError:
            pass

    def get_names(self):
        return tuple(self._names.values())

    def set(self, names):
        self._tree.delete(*self._iids.values())
        self._iids.clear()
        self._names.clear()
        for name in sorted(names):
            iid = self._tree.insert('', 'end', text=name)
            self._names[iid] = name
            self._iids[name] = iid
Exemple #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
Exemple #27
0
class Tree(LibraryListener):
    def __init__(self, config, master):
        self.views = config['views']
        self.library = None
        self.__make_widgets(master)

    def __make_widgets(self, root):
        self.tree = Treeview(root)

    def on_library_change(self, library):
        self.library = library
        self.__make_root_nodes()

    def __make_root_nodes(self):
        for i in self.tree.get_children():
            self.tree.delete(i)
        root_nodes = self.query_library({}, self.views[0])
        for node in root_nodes:
            child = self.tree.insert("", "end", self.__make_node_id(None, self.views[0], node), text=node,
                                     tags=self.views[0])
            self.fetch_children(child)

    @staticmethod
    def __make_node_id(parent_node, node_type, node_value):
        node_id = {}
        if parent_node:
            node_id = copy(parent_node)
        node_id[node_type] = node_value
        return node_id

    def can_be_expanded(self, node_type):
        return node_type != self.views[len(self.views) - 1]

    def get_child_node_type(self, node_type):
        return self.views[self.views.index(node_type) + 1]

    def query_library(self, node_id, view):
        return self.library.aggregate(node_id, view)

    def __has_children(self, node):
        return len(self.children(node)) > 0

    def fetch_children(self, node):
        if not self.__has_children(node):
            node_type = self.tree.item(node, "tags")[0]
            if self.can_be_expanded(node_type):
                children_node_type = self.get_child_node_type(node_type)
                node_id = literal_eval(node)
                nodes = self.query_library(node_id, children_node_type)
                for child_node in nodes:
                    self.tree.insert(node, "end", self.__make_node_id(node_id, children_node_type, child_node),
                                     text=child_node, tags=children_node_type)

    def delete_children(self, parent_node):
        children = self.children(parent_node)
        for node in children:
            self.tree.delete(node)

    @property
    def selected_node(self):
        if len(self.tree.selection()):
            return self.tree.selection()[0]

    def children(self, node):
        return self.tree.get_children(node)
Exemple #28
0
class show:
    def __init__(self):
        self.window=Tk()
        self.window.title("Show | Sales Products")
        self.window.iconbitmap('shop.ico')
        self.window.geometry("1365x670+0+0")
        self.window.maxsize(1365,670)
        self.window.minsize(1365,670)
        # self.window.resizable(width=False,height=False)
    def add_background(self):
        self.image = Image.open("images/back.jpg")
        self.image = self.image.resize((1365, 700), Image.ANTIALIAS)
        self.img = ImageTk.PhotoImage(self.image)
        self.li = Label(image = self.img, text="TALHA")
        self.li.image = self.img
        self.li.pack()
        self.Menubar()

    def Menubar(self):
        self.menubar = Menu()
        self.menuitems_add = Menu(self.menubar, tearoff=0,bg="blue",fg="white")
        self.menuitems_add.add_command(label="Add Products", command=self.add_products)
        # self.menuitems.add_separator()

        self.menuitems_sales = Menu(self.menubar, tearoff=0,bg="blue",fg="white")
        self.menuitems_sales.add_command(label="Sale Products", command=self.sales_products)

        self.menuitems_customer = Menu(self.menubar, tearoff=0, bg="blue", fg="white")
        self.menuitems_customer.add_command(label="Add Customer", command=self.add_customer)
        self.menuitems_customer.add_command(label="Show Customer Records", command=self.customer_record)

        self.menuitems_reports = Menu(self.menubar, tearoff=0, bg="blue", fg="white")
        self.menuitems_reports.add_command(label="Check Products Quantity", command=self.check_products_quantity)
        self.menuitems_reports.add_command(label="Check Profit/Loss", command=self.check_profit_loss)
        self.menuitems_reports.add_command(label="Check Sales Products", command=self.check_products_sales)
        self.menuitems_reports.add_command(label="Check Sent Amount Details", command=self.check_amount)

        self.menubar.add_cascade(label="Add Products", menu=self.menuitems_add)
        self.menubar.add_cascade(label="Sales Products", menu=self.menuitems_sales)
        self.menubar.add_cascade(label="Customer", menu=self.menuitems_customer)
        self.menubar.add_cascade(label="Reports", menu=self.menuitems_reports)
        self.menubar.add_cascade(label="Exit", command=quit)
        self.window.config(menu=self.menubar)

    def add_table(self):
        self.l1=Label(self.window,text="**Sales Details**",font="Courier 25 bold",bg="black",fg="white",width=61)
        self.l1.place(x=82,y=20)

        self.l1 = Label(self.window, text="Developed by : Muhammad Talha | NTU", font="Courier 10 bold")
        self.l1.place(x=470, y=610)

        self.l1 = Label(self.window, text="Enter Product Name:", font="courier 16 bold",bg="blue",fg="white")
        self.l1.place(x=280, y=90)

        self.Entry_reg = Entry(self.window, font="courior 14 bold")
        self.Entry_reg.place(x=550, y=90, height=30)

        self.b1 = Button(self.window, text="Search", font="Times 13 bold",fg="white",bg="blue",width=10)
        self.b1.place(x=790, y=90)
        self.b1.bind('<Button-1>', self.search_product)


        # for Style Table
        style = Style()
        style.configure("mystyle.Treeview", highlightthickness=0, bd=0,
                        font=('courier 12 bold'),rowheight=43)  # Modify the font of the body
        style.configure("mystyle.Treeview.Heading", font=('Times 15 bold'),foreground="black")  # Modify the font of the headings
        # style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})])  # Remove the borders
        # import TreeViewe
        self.tr=Treeview(self.window,columns=('A','B','C','D','E'),selectmode="extended",style='mystyle.Treeview')
        # heading key+text
        self.tr.heading("#0", text="Sr.No")
        self.tr.column("#0", minwidth=0, width=85, stretch=NO)

        self.tr.heading("#1",text="Product Name")
        self.tr.column("#1",minwidth=0,width=160,stretch=NO)

        self.tr.heading("#2", text="Product Catagory")
        self.tr.column("#2", minwidth=0, width=200, stretch=NO)

        self.tr.heading("#3", text="Quantity")
        self.tr.column("#3", minwidth=0, width=175, stretch=NO)

        self.tr.heading("#4", text="Price Per Product")
        self.tr.column("#4", minwidth=0, width=175, stretch=NO)

        self.tr.heading("#5", text="Sales Price")
        self.tr.column("#5", minwidth=0, width=160, stretch=NO)

        j=1
        for i in Database.show_sales_details():
            self.tr.insert('',index=j,text=j,values=(i[1],i[2],i[3],i[4],i[5]))
            j+=1

        self.Entry_reg.bind('<KeyRelease>', self.remove)

        self.sb = Scrollbar(self.tr)
        self.sb.place(x=935,y=2,height=452,width=22,bordermode=OUTSIDE)
        self.sb.config(command=self.tr.yview)
        self.tr.config(yscrollcommand=self.sb.set)
        self.tr.place(x=170,y=150)

        # to excel file
        self.b1 = Button(self.window, text="Save to Excel", font="Times 12 bold",bg="blue",fg="white",width=20,
        )
        self.b1.place(x=938, y=610)
        self.b1.bind('<Button-1>', self.excel)


        self.window.mainloop()


    def remove(self,event):
        for row in self.tr.get_children():
            self.tr.delete(row)
        j = 1
        for i in Database.show_sales_details():
            self.tr.insert('', index=j, text=j, values=(i[1], i[2], i[3], i[4], i[5]))
            j += 1

    def search_product(self,event):
        try:
            data = (self.Entry_reg.get(),)
            if self.Entry_reg.get() == "":
                msg.showwarning("Message ! ", "please insert product name !")
            else:
                j = 1
                D = Database.search_details_sales_table(data)
                if D:
                    for row in self.tr.get_children():
                        self.tr.delete(row)
                    self.Entry_reg.delete(0, END)
                    for i in D:
                        self.tr.insert('', index=j, text=j, values=(i[1],i[2],i[3],i[4],i[5]))
                        j += 1
                else:
                    msg.showwarning("Message!", "No result Found!")

        except:
            msg.showwarning("Error!", "Something went wrong! please contact with developer !!!")
    def excel(self,event):
        try:
            x=Database.show_sales_details()
            p_name=[]
            p_catagory=[]
            p_quantity=[]
            price=[]
            p_sales_price=[]
            for i in range(len(x)):
                z=x.__getitem__(i)
                p_name.append(z[1])
                p_catagory.append(z[2])
                p_quantity.append(z[3])
                price.append(z[4])
                p_sales_price.append(z[5])

            products = pd.DataFrame({
                "Product Name": p_name,
                "Product Catagory":p_catagory,
                "Quantity":p_quantity,
                "Price Per Product":price,
                "Sales Price":p_sales_price
            })

            with pd.ExcelWriter("Excel Files/Sales_Products_Records.xlsx") as writer:
                products.to_excel(writer, sheet_name="Sales_Products", index=False)
            msg.showinfo("Message ! ", "Your data has been inserted Susccessfully !")
        except:
            msg.showwarning("Message!","Something Went Wrong!please contact with developer!!!")

    def add_products(self):
        self.window.destroy()
        home = Home.data()
        home.add_background()
        home.add_frame()

    def sales_products(self):
        self.window.destroy()
        showP = Showing_Records.show()
        showP.add_background()
        showP.add_table()
    def check_products_quantity(self):
        self.window.destroy()
        showP = Check_Products_Quantity.show()
        showP.add_background()
        showP.add_table()
    def check_products_sales(self):
        pass

    def check_amount(self):
        self.window.destroy()
        showP = Check_Amount_Details.show()
        showP.add_background()
        showP.add_table()
    def check_profit_loss(self):
        self.window.destroy()
        showP = Check_Profit_Loss_GUI.show()
        showP.add_background()
        showP.add_table()
    def add_customer(self):
        self.window.destroy()
        home = Add_Customer.data()
        home.add_background()
        home.add_frame()
    def customer_record(self):
        self.window.destroy()
        showP = Customer_Records.show()
        showP.add_background()
        showP.add_table()
Exemple #29
0
class Ufd:
    """
        Universal File Dialog - "UFD"
        
        Unopinionated, minimalist, reusable, slightly configurable,
        general-purpose file-dialog.
    """
    def __init__(self,
                 title: str = "Universal File Dialog",
                 icon: str = "",
                 show_hidden: bool = False,
                 include_files: bool = True,
                 multiselect: bool = True,
                 select_dirs: bool = True,
                 select_files: bool = True,
                 unix_delimiter: bool = True,
                 stdout: bool = False):
        """
            Init kwargs as object attributes, save references to 
            Tk PhotoImages, & define the widgets + layout
        """

        if not isinstance(title, str):
            raise TypeError("Argument title must be type string.")

        self.title = title

        if icon:
            if not isinstance(icon, str):
                raise TypeError("Argument icon must be type string.")

            if not isfile(icon):
                raise FileNotFoundError(f"File not found: {icon}")

            self.icon = icon

        else:
            self.icon = ""

        if show_hidden:
            self.show_hidden = True
        else:
            self.show_hidden = False

        if include_files:
            self.include_files = True
        else:
            self.include_files = False

        if multiselect:
            self.multiselect = True
        else:
            self.multiselect = False

        if select_dirs:
            self.select_dirs = True
        else:
            self.select_dirs = False

        if select_files:
            self.select_files = True
        else:
            self.select_files = False

        if unix_delimiter:
            self.unix_delimiter = True
        else:
            self.unix_delimiter = False

        if stdout:
            self.stdout = True
        else:
            self.stdout = False

        # Tkinter:
        self.dialog = Tk()
        self.dialog.withdraw()
        self.dialog.title(self.title)
        self.dialog.minsize(width=300, height=200)
        self.dialog.geometry("500x300")
        self.dialog.update_idletasks()

        self.file_icon = PhotoImage(file=f"{dirname(__file__)}/file.gif",
                                    master=self.dialog).subsample(50)

        self.folder_icon = PhotoImage(file=f"{dirname(__file__)}/folder.gif",
                                      master=self.dialog).subsample(15)

        self.disk_icon = PhotoImage(file=f"{dirname(__file__)}/disk.gif",
                                    master=self.dialog).subsample(15)

        if self.icon:
            self.dialog.iconbitmap(self.icon)
        else:
            self.dialog.iconbitmap(f"{dirname(__file__)}/icon.ico")

        # Widgets:
        self.paneview = PanedWindow(
            self.dialog,
            sashwidth=7,
            bg="#cccccc",
            bd=0,
        )

        self.left_pane = PanedWindow(self.paneview)
        self.right_pane = PanedWindow(self.paneview)
        self.paneview.add(self.left_pane)
        self.paneview.add(self.right_pane)

        self.treeview_x_scrollbar = Scrollbar(self.left_pane,
                                              orient="horizontal")
        self.treeview_y_scrollbar = Scrollbar(self.left_pane,
                                              orient="vertical")
        self.list_box_x_scrollbar = Scrollbar(self.right_pane,
                                              orient="horizontal")
        self.list_box_y_scrollbar = Scrollbar(self.right_pane,
                                              orient="vertical")

        # tstyle = Style().configure(".", )

        self.treeview = Treeview(
            self.left_pane,
            xscrollcommand=self.treeview_x_scrollbar.set,
            yscrollcommand=self.treeview_y_scrollbar.set,
            show="tree",
            selectmode="browse",
            # style=tstyle
        )

        self.list_box = Listbox(self.right_pane,
                                xscrollcommand=self.list_box_x_scrollbar.set,
                                yscrollcommand=self.list_box_y_scrollbar.set,
                                width=34,
                                highlightthickness=0,
                                bd=2,
                                relief="ridge")

        if self.multiselect:
            self.list_box.config(selectmode="extended")
        else:
            self.list_box.config(selectmode="browse")

        self.cancel_button = Button(self.left_pane,
                                    text="Cancel",
                                    command=self.cancel)

        self.submit_button = Button(self.right_pane,
                                    text="Submit",
                                    command=self.submit)

        self.treeview_x_scrollbar.config(command=self.treeview.xview)
        self.treeview_y_scrollbar.config(command=self.treeview.yview)
        self.list_box_x_scrollbar.config(command=self.list_box.xview)
        self.list_box_y_scrollbar.config(command=self.list_box.yview)

        #Layout:
        self.dialog.rowconfigure(0, weight=1)
        self.dialog.columnconfigure(0, weight=1)

        self.left_pane.grid_rowconfigure(0, weight=1)
        self.left_pane.grid_columnconfigure(0, weight=1)
        self.right_pane.grid_rowconfigure(0, weight=1)
        self.right_pane.grid_columnconfigure(0, weight=1)

        self.paneview.paneconfigure(
            self.left_pane,
            minsize=100,
            #Start off w/ the sash centered in the GUI:
            width=(self.dialog.winfo_width() / 2) - ceil(
                (self.paneview.cget("sashwidth") * 1.5)),
        )
        self.paneview.paneconfigure(self.right_pane, minsize=100)

        self.paneview.grid(row=0, column=0, sticky="nsew")

        self.treeview.grid(row=0, column=0, sticky="nsew")
        self.treeview_y_scrollbar.grid(row=0, column=1, sticky="ns")
        self.treeview_x_scrollbar.grid(row=1,
                                       column=0,
                                       columnspan=2,
                                       sticky="ew")

        self.list_box.grid(row=0, column=0, sticky="nsew")
        self.list_box_y_scrollbar.grid(row=0, column=1, sticky="ns")
        self.list_box_x_scrollbar.grid(row=1,
                                       column=0,
                                       columnspan=2,
                                       sticky="ew")

        self.cancel_button.grid(row=2, column=0, sticky="w", padx=10, pady=10)
        self.submit_button.grid(row=2,
                                column=0,
                                columnspan=2,
                                sticky="e",
                                padx=10,
                                pady=10)

        #Bindings, Protocols, & Misc:
        self.dialog.bind("<Control-w>", self.cancel)
        self.treeview.bind("<<TreeviewSelect>>", self.treeview_select)
        self.treeview.bind("<Double-Button-1>", self.dialog_populate)
        self.treeview.bind("<Return>", self.dialog_populate)
        self.treeview.bind("<Right>", self.dialog_populate)
        self.list_box.bind("<<ListboxSelect>>", self.list_box_select)
        self.list_box.bind("<Return>", self.submit)
        self.dialog.protocol("WM_DELETE_WINDOW", self.cancel)

        self.dialog_selection = deque()
        self.selection_paths = deque()

        for disk in self.get_disks():
            self.treeview.insert(
                "",
                index="end",
                text=disk,
                image=self.disk_icon,
            )

        self.dialog.focus()

    def __call__(self):
        """
            Display dialog & return selection
        """

        (width_offset, height_offset) = self.get_offset(self.dialog)
        self.dialog.geometry(f"+{width_offset}+{height_offset}")
        self.dialog.update_idletasks()
        self.dialog.deiconify()

        self.dialog.wait_window()

        for i, path in enumerate(self.dialog_selection):
            if self.unix_delimiter:
                self.dialog_selection[i] = sub("\\\\", "/", path)
            else:
                self.dialog_selection[i] = sub("/", "\\\\", path)

        if self.stdout:
            [print(item) for item in self.dialog_selection]

        return list(self.dialog_selection)

    def __str__(self):
        """
            Return own address
        """

        return "Universal File Dialog"\
        f" @ {hex(id(self))}"

    def __repr__(self):
        """
            Return full string representation of constructor signature
        """

        return f"Ufd("\
        f"title=\"{self.title}\","\
        f" icon=\"{self.icon}\","\
        f" show_hidden={self.show_hidden},"\
        f" include_files={self.include_files},"\
        f" multiselect={self.multiselect},"\
        f" select_dirs={self.select_dirs},"\
        f" select_files={self.select_files},"\
        f" unix_delimiter={self.unix_delimiter})"\
        f" stdout={self.stdout})"\
        f" @ {hex(id(self))}"

    @staticmethod
    def get_offset(tk_window):
        """
            Returns an appropriate offset for a given tkinter toplevel,
            such that it always is created center screen on the primary display.
        """

        width_offset = int((tk_window.winfo_screenwidth() / 2) -
                           (tk_window.winfo_width() / 2))

        height_offset = int((tk_window.winfo_screenheight() / 2) -
                            (tk_window.winfo_height() / 2))

        return (width_offset, height_offset)

    @staticmethod
    def get_disks():
        """
            Returns all mounted disks (for Windows)

            >> ["A:", "B:", "C:"]
        """

        if system() != "Windows":
            raise OSError("For use with Windows platforms.")

        logicaldisks = run(["wmic", "logicaldisk", "get", "name"],
                           capture_output=True)

        return findall("[A-Z]:", str(logicaldisks.stdout))

    @staticmethod
    def list_dir(path, force=False):
        """
            Reads a directory with a shell call to dir.
            Truthiness of bool force determines whether 
            hidden items are returned or not. (For Windows)
        """

        path = sub("/", "\\\\", path)

        if force:
            dir_listing = run(["dir", path, "/b", "/a"],
                              shell=True,
                              capture_output=True)

        else:
            dir_listing = run(["dir", path, "/b"],
                              shell=True,
                              capture_output=True)

        output = dir_listing.stdout
        err = dir_listing.stderr

        if not output:
            return []

        if err:
            err = err.decode("utf-8")
            raise Exception(err)

        str_output = output.decode("utf-8")
        list_output = re_split("\r\n", str_output)

        return sorted([item for item in list_output if item])

    def climb(self, item):
        """
            Builds & returns a complete path to root directory,
            including the item name itself as the path tail.
            An extra delimiter is appeneded for the subsequent
            child node, which is normalized in dialog_populate()
        """

        item_text = self.treeview.item(item)["text"]
        parent = self.treeview.parent(item)
        path = ""
        parents = deque()

        while parent:
            parents.append(self.treeview.item(parent)["text"] + "/")
            parent = self.treeview.parent(parent)

        for parent in reversed(parents):
            path += parent

        path += item_text + "/"
        return path

    def dialog_populate(self, event=None):
        """
            Dynamically populates & updates the treeview, listbox,
            and keeps track of the full paths corresponding to each
            item in the listbox
        """
        if not self.treeview.focus():
            return

        self.treeview.column("#0", width=1000)

        existing_children = self.treeview.get_children(self.treeview.focus())
        [self.treeview.delete(child) for child in existing_children]

        self.list_box.delete(0, "end")
        self.selection_paths.clear()

        focus_item = self.treeview.focus()
        path = self.climb(focus_item)

        if self.show_hidden:
            children = self.list_dir(path, force=True)
        else:
            children = self.list_dir(path)

        for child in children:
            if isdir(path + child):

                self.treeview.insert(focus_item,
                                     index="end",
                                     text=child,
                                     image=self.folder_icon)

                if self.select_dirs:
                    self.list_box.insert("end", child)
                    self.selection_paths.append(path + child)

            elif isfile(path + child):

                if self.include_files:
                    self.treeview.insert(focus_item,
                                         index="end",
                                         text=child,
                                         image=self.file_icon)

                if self.select_files:
                    self.list_box.insert("end", child)
                    self.list_box.itemconfig("end", {"bg": "#EAEAEA"})
                    self.selection_paths.append(path + child)

        if isfile(normpath(path)):
            (head, tail) = path_split(normpath(path))
            head = sub("\\\\", "/", head)

            self.list_box.insert("end", tail)
            self.selection_paths.append(head + "/" + tail)
            self.list_box.itemconfig("end", {"bg": "#EAEAEA"})

    def list_box_select(self, event=None):
        """
            Dynamically refresh the dialog selection with
            what's selected in the listbox
            (Callback for <<ListboxSelect>>).
        """

        self.dialog_selection.clear()

        for i in self.list_box.curselection():
            self.dialog_selection.append(self.selection_paths[i])

    def treeview_select(self, event=None):
        """
            Dynamically refresh the dialog selection with
            what's selected in the treeview
            (Callback for <<TreeviewSelect>>).
        """

        for i in self.list_box.curselection():
            self.list_box.selection_clear(i)

        self.dialog_selection.clear()

        item = normpath(self.climb(self.treeview.focus()))
        self.dialog_selection.append(item)

    def submit(self, event=None):
        """
            Satisfies wait_window() in self.__call__() and validates selection

            (Callback for <Return>, <Button-1> on file_list, submit_button)
        """

        if self.select_dirs == False:
            for item in self.dialog_selection:
                if isdir(item):
                    messagebox.showwarning(
                        "Error - Invalid Selection",
                        "Unable to select directory. Please select a file(s).")
                    return

        if self.select_files == False:
            for item in self.dialog_selection:
                if isfile(item):
                    messagebox.showwarning(
                        "Error - Invalid Selection",
                        "Unable to select file. Please select a folder(s)")
                    return

        self.dialog.destroy()

    def cancel(self, event=None):
        """
            Satisfies wait_window() in self.__call__() 

            (Callback for <Button-1> on cancel_button)
            (Callback for protocol "WM_DELETE_WINDOW" on self.dialog)
        """

        self.dialog_selection.clear()
        self.dialog.destroy()
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")
Exemple #31
0
class AutoCorrectConfig(Frame):
    """Configuration window for autocorrect."""
    def __init__(self, master, app, **kwargs):
        Frame.__init__(self, master, padding=4, **kwargs)
        self.rowconfigure(2, weight=1)
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)

        self.tree = Treeview(self,
                             columns=('replace', 'by'),
                             show='',
                             selectmode='browse')
        scroll_x = AutoScrollbar(self,
                                 orient='horizontal',
                                 command=self.tree.xview)
        scroll_y = AutoScrollbar(self,
                                 orient='vertical',
                                 command=self.tree.yview)
        self.tree.configure(xscrollcommand=scroll_x.set,
                            yscrollcommand=scroll_y.set)

        self.reset()

        self.replace = StringVar(self)
        self.by = StringVar(self)

        add_trace(self.replace, 'write', self._trace_replace)
        add_trace(self.by, 'write', self._trace_by)

        b_frame = Frame(self)
        self.b_add = Button(b_frame, text=_('New'), command=self.add)
        self.b_rem = Button(b_frame, text=_('Delete'), command=self.remove)
        self.b_add.state(('disabled', ))
        self.b_rem.state(('disabled', ))
        self.b_add.pack(pady=4, fill='x')
        self.b_rem.pack(pady=4, fill='x')
        Button(b_frame, text=_('Reset'), command=self.reset).pack(pady=8,
                                                                  fill='x')

        Label(self, text=_('Replace')).grid(row=0,
                                            column=0,
                                            sticky='w',
                                            pady=4)
        Label(self, text=_('By')).grid(row=0, column=1, sticky='w', pady=4)
        Entry(self, textvariable=self.replace).grid(row=1,
                                                    column=0,
                                                    sticky='ew',
                                                    pady=4,
                                                    padx=(0, 4))
        Entry(self, textvariable=self.by).grid(row=1,
                                               column=1,
                                               sticky='ew',
                                               pady=4)
        self.tree.grid(row=2, columnspan=2, sticky='ewsn', pady=(4, 0))
        scroll_x.grid(row=3, columnspan=2, sticky='ew', pady=(0, 4))
        scroll_y.grid(row=2, column=2, sticky='ns', pady=(4, 0))
        b_frame.grid(row=1, rowspan=2, padx=(4, 0), sticky='nw', column=3)

        self.tree.bind('<<TreeviewSelect>>', self._on_treeview_select)

    def _trace_by(self, *args):
        key = self.replace.get().strip()
        val = self.by.get().strip()
        self.by.set(val)
        if key in self.tree.get_children(''):
            if val != self.tree.set(key, 'by'):
                self.b_add.state(('!disabled', ))
            else:
                self.b_add.state(('disabled', ))
        else:
            self.b_add.state(('!disabled', ))
        if not val:
            self.b_add.state(('disabled', ))

    def _trace_replace(self, *args):
        key = self.replace.get().strip()
        val = self.by.get().strip()
        self.replace.set(key)
        if not key:
            self.b_add.state(('disabled', ))
            self.b_rem.state(('disabled', ))
        else:
            self.b_add.state(('!disabled', ))
            sel = self.tree.selection()
            if key in self.tree.get_children(''):
                if key not in sel:
                    self.tree.selection_set(key)
                self.b_add.configure(text=_('Replace'))
                self.b_rem.state(('!disabled', ))
                if val != self.tree.set(key, 'by'):
                    self.b_add.state(('!disabled', ))
                else:
                    self.b_add.state(('disabled', ))
            else:
                self.b_rem.state(('disabled', ))
                self.b_add.configure(text=_('New'))
                if sel:
                    self.tree.selection_remove(*sel)
        if not val:
            self.b_add.state(('disabled', ))

    def _on_treeview_select(self, event):
        sel = self.tree.selection()
        if sel:
            key, val = self.tree.item(sel[0], 'values')
            self.replace.set(key)
            self.by.set(val)

    def reset(self):
        self.tree.delete(*self.tree.get_children(''))
        keys = list(AUTOCORRECT.keys())
        keys.sort()
        for key in keys:
            self.tree.insert('', 'end', key, values=(key, AUTOCORRECT[key]))

    def add(self):
        key = self.replace.get().strip()
        val = self.by.get().strip()
        if key in self.tree.get_children(''):
            self.tree.item(key, values=(key, val))
        elif key and val:
            self.tree.insert('', 'end', key, values=(key, val))

    def remove(self):
        key = self.replace.get()
        if key in self.tree.get_children(''):
            self.tree.delete(key)

    def ok(self):
        keys = self.tree.get_children('')
        AUTOCORRECT.clear()
        for key in keys:
            AUTOCORRECT[key] = self.tree.set(key, 'by')
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 #33
0
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.customTransformsChanged = 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")
        addSelectLocalButton = Button(buttonFrame,
                                      text=_("Select"),
                                      command=self.selectLocally)
        ToolTip(
            addSelectLocalButton,
            text=_(
                "Select python module files from the local plugin directory."),
            wraplength=240)
        addBrowseLocalButton = Button(buttonFrame,
                                      text=_("Browse"),
                                      command=self.browseLocally)
        ToolTip(
            addBrowseLocalButton,
            text=
            _("File chooser allows browsing and 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)
        addSelectLocalButton.grid(row=1, column=0, pady=4)
        addBrowseLocalButton.grid(row=2, column=0, pady=4)
        addWebButton.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 (plugins already known to arelle)
        modulesFrame = Frame(frame, width=720)
        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=60, 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.moduleVersionHdr = Label(moduleInfoFrame,
                                      text=_("version:"),
                                      state=DISABLED)
        self.moduleVersionHdr.grid(row=4, column=0, sticky=W)
        self.moduleVersionLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleVersionLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleVersionLabel,
                text=_("Version of plug-in module."),
                wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame,
                                  text=_("URL:"),
                                  state=DISABLED)
        self.moduleUrlHdr.grid(row=5, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame,
                                    wraplength=600,
                                    justify="left")
        self.moduleUrlLabel.grid(row=5, 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=6, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame,
                                     wraplength=600,
                                     justify="left")
        self.moduleDateLabel.grid(row=6, 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=7, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleLicenseLabel.grid(row=7, column=1, columnspan=3, sticky=W)
        self.moduleImportsHdr = Label(moduleInfoFrame,
                                      text=_("imports:"),
                                      state=DISABLED)
        self.moduleImportsHdr.grid(row=8, column=0, sticky=W)
        self.moduleImportsLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleImportsLabel.grid(row=8, 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=9, 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=9, 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=9, 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):
        # check for orphaned classes (for which there is no longer a corresponding module)
        _moduleNames = self.pluginConfig.get("modules", {}).keys()
        _orphanedClassNames = set()
        for className, moduleList in self.pluginConfig.get("classes",
                                                           {}).items():
            for _moduleName in moduleList.copy():
                if _moduleName not in _moduleNames:  # it's orphaned
                    moduleList.remove(_moduleName)
                    self.pluginConfigChanged = True
            if not moduleList:  # now orphaned
                _orphanedClassNames.add(className)
                self.pluginConfigChanged = True
        for _orphanedClassName in _orphanedClassNames:
            del self.pluginConfig["classes"][_orphanedClassName]

        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged or self.modelClassesChanged or self.customTransformsChanged 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.customTransformsChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("custom transforms")
            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.get("author"))
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo.get("description"))
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(
                text=', '.join(moduleInfo["classMethods"]))
            self.moduleVersionHdr.config(state=ACTIVE)
            self.moduleVersionLabel.config(text=moduleInfo.get("version"))
            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.get("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.moduleVersionHdr.config(state=DISABLED)
            self.moduleVersionLabel.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 selectLocally(self):
        choices = []  # list of tuple of (file name, description)

        def sortOrder(key):
            return {
                "EdgarRenderer": "1",
                "validate": "2",
                "xbrlDB": "3"
            }.get(key, "4") + key.lower()

        def selectChoices(dir, indent=""):
            dirHasEntries = False
            for f in sorted(os.listdir(dir), key=sortOrder):
                if f not in (".", "..", "__pycache__", "__init__.py"):
                    fPath = os.path.join(dir, f)
                    fPkgInit = os.path.join(fPath, "__init__.py")
                    dirInsertPoint = len(choices)
                    moduleInfo = None
                    if ((os.path.isdir(fPath) and os.path.exists(fPkgInit)) or
                        ((os.path.isfile(fPath) and f.endswith(".py")))):
                        moduleInfo = PluginManager.moduleModuleInfo(fPath)
                        if moduleInfo:
                            choices.append((
                                indent + f,
                                "name: {}\ndescription: {}\nversion: {}\nlicense: {}"
                                .format(moduleInfo["name"],
                                        moduleInfo.get("description"),
                                        moduleInfo.get("version"),
                                        moduleInfo.get("license")), fPath,
                                moduleInfo["name"], moduleInfo.get("version"),
                                moduleInfo.get("description"),
                                moduleInfo.get("license")))
                            dirHasEntries = True
                    if os.path.isdir(fPath) and f not in ("DQC_US_Rules", ):
                        if selectChoices(fPath, indent=indent +
                                         "   ") and not moduleInfo:
                            choices.insert(dirInsertPoint,
                                           (indent + f, None, None, None, None,
                                            None, None))
            return dirHasEntries

        selectChoices(self.cntlr.pluginDir)
        selectedPath = DialogOpenArchive.selectPlugin(self, choices)
        if selectedPath:
            moduleInfo = PluginManager.moduleModuleInfo(
                selectedPath[len(self.cntlr.pluginDir) + 1:])
            self.loadFoundModuleInfo(moduleInfo, selectedPath)

    def browseLocally(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 checkClassMethodsChanged(self, moduleInfo):
        for classMethod in moduleInfo["classMethods"]:
            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 == "ModelManager.LoadCustomTransforms":
                self.customTransformsChanged = True
            elif classMethod == "DisclosureSystem.Types":
                self.disclosureSystemTypesChanged = True  # disclosure system types changed
            elif classMethod.startswith("Proxy."):
                self.hostSystemFeaturesChanged = True  # system features (e.g., proxy) changed

    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:
                    self.checkClassMethodsChanged(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
                    for importModuleInfo in moduleInfo.get(
                            "imports", EMPTYLIST):
                        _removePluginConfigModuleInfo(importModuleInfo)
                    self.pluginConfig["modules"].pop(_name, None)

            _removePluginConfigModuleInfo(moduleInfo)
            if not self.pluginConfig["modules"] and self.pluginConfig[
                    "classes"]:
                self.pluginConfig["classes"].clear()  # clean orphan classes
            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)
                self.checkClassMethodsChanged(moduleInfo)
            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"
                self.checkClassMethodsChanged(moduleInfo)
                for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                    _moduleEnable(
                        importModuleInfo)  # set status on nested moduleInfo
                    if importModuleInfo['name'] in self.pluginConfig[
                            "modules"]:  # set status on top level moduleInfo
                        _moduleEnable(self.pluginConfig["modules"][
                            importModuleInfo['name']])

            _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"]:
            moduleInfo = self.pluginConfig["modules"][module]
            if not moduleInfo.get("isImported"):

                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()
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
class CopyFileFrame(CopilotInnerFrame):
    def __init__(self, master, config, state):
        super(CopyFileFrame, self).__init__(master, config)

        self._state = state

        self._item_paths = {}

        self._tree = Treeview(self._master, columns=('size'))
        self._tree.heading('size', text='Size')
        self._tree.grid(row=1, column=0, columnspan=3, sticky='nsew')
        self._tree.configure(yscrollcommand=self._sb.set)
        self._sb['command'] = self._tree.yview

        if self._state.action == 'copy':
            self._next_btn['text'] = 'Copy'
            self._frame_lbl['text'] = 'Copy File'
            self._populate_tree(self._config.file_root)
        elif self._state.action == 'delete':
            self._next_btn['text'] = 'Delete'
            self._frame_lbl['text'] = 'Delete File'
            self._populate_tree(self._state.to_device.part().mount())

        self._next_btn['command'] = self._next_cmd

    def _next_cmd(self):
        if self._state.action == 'copy':
            self._copy_file()
        elif self._state.action == 'delete':
            self._delete_file()

    def _copy_file(self):
        cur_item = self._tree.focus()
        cur_path = self._item_paths.get(cur_item, '')
        if cur_path != '':
            new_path = os.path.join(self._state.device_to_path, os.path.basename(cur_path))
            try:
                if os.path.exists(new_path):
                    if ConfirmFrame.show(
                        self._master, self._config,
                        'The file already exists in the destination.\n'
                        'Would you like to overwrite it?',
                        'Yes', 'No'
                    ):
                        shutil.copyfile(cur_path, new_path)
                else:
                    shutil.copyfile(cur_path, new_path)
            except PermissionError:
                OkFrame.show(
                    self._master, self._config,
                    'Error copying file:\n\nInvalid permissions'
                )
            except Exception as e:
                OkFrame.show(
                    self._master, self._config,
                    'An error occurred while copying the file:\n\n{}'.format(e)
                )

    def _delete_file(self):
        cur_item = self._tree.focus()
        cur_path = self._item_paths.get(cur_item, '')
        if cur_path != '':
            disp_path = cur_path[len(self._state.to_device.part().mount()):]
            try:
                if ConfirmFrame.show(
                    self._master, self._config,
                    'Are you sure you\'d like to delete this file?\n{}'.format(disp_path),
                    'Yes', 'No'
                ):
                    os.remove(cur_path)
                    self._tree.delete(self._tree.focus())
            except PermissionError:
                OkFrame.show(
                    self._master, self._config,
                    'Error deleting file:\n\nInvalid permissions'
                )
            except Exception as e:
                OkFrame.show(
                    self._master, self._config,
                    'An error occurred while deleting the file:\n\n{}'.format(e)
                )

    def _populate_tree(self, tree_root):
        self._item_paths = {}

        def insert_path(tree, path, parent_id):
            dirs = [e for e in scandir(path) if e.is_dir()]
            dirs.sort(key=lambda e: e.name)

            for d in dirs:
                dir_name = d.name
                dir_id = '{}-{}'.format(parent_id, dir_name)
                dir_path = os.path.join(path, dir_name)
                tree.insert(parent_id, 'end', dir_id, text=dir_name, tags=('dir'))
                try:
                    insert_path(tree, dir_path, dir_id)
                except:
                    pass

            files = [e for e in scandir(path) if e.is_file()]
            files.sort(key=lambda e: e.name)

            for idx, f in enumerate(files):
                file_name = f.name
                file_id = '{}-{}'.format(parent_id, file_name)
                file_stat = f.stat()
                file_size = sizeof_fmt(file_stat.st_size)
                file_path = os.path.join(path, file_name)
                self._item_paths[file_id] = file_path

                if idx % 2 == 0:
                    file_bg = 'file_even'
                else:
                    file_bg = 'file_odd'

                tree.insert(
                    parent_id,
                    'end',
                    file_id,
                    text=file_name,
                    tags=('file', file_bg),
                    values=(file_size)
                )

        insert_path(self._tree, tree_root, '')

        tree = self._tree
        tree.tag_configure('dir', font=self._config.item_font)
        tree.tag_configure('file', font=self._config.item_font)
        tree.tag_configure('file_odd', background='light grey')
Exemple #36
0
class Search(Module):
    def __init__(self, app):
        self.app = app
        self.window = None

        self.context_size = 3
        self.results = []
        self.regex = StringVar(self.app)

        # if anything ever changes the contents of any intervals
        # it should call SearchModule.loadIntervals()
        self.intervals = []
        self.loadIntervals()

    def handleClose(self, event=None):
        self.window.destroy()
        self.window = None

    def createWindow(self):
        self.window = Toplevel(self.app)
        self.window.title('Search')
        self.window.protocol("WM_DELETE_WINDOW", self.handleClose)
        self.input = Entry(self.window, textvariable=self.regex)
        self.input.grid(row=0, column=0)
        self.input.bind('<Return>', self.search)
        self.input.bind('<Escape>', lambda ev: self.window.focus())
        self.searchButton = Button(self.window,
                                   text='Search',
                                   command=self.search,
                                   takefocus=0)
        self.searchButton.grid(row=0, column=1)
        self.resultCount = Label(self.window, text='0 results')
        self.resultCount.grid(row=0, column=2)
        cols = ('File', 'Tier', 'Time', 'Text')
        self.scroll = Scrollbar(self.window, orient='vertical')
        self.resultList = Treeview(self.window,
                                   columns=cols,
                                   show="headings",
                                   yscrollcommand=self.scroll.set,
                                   selectmode='browse')
        self.scroll.config(command=self.resultList.yview)
        for col in cols:
            self.resultList.heading(col, text=col)
        self.resultList.grid(row=2, column=0, columnspan=3, sticky='news')
        self.resultList.bind('<Double-1>', self.onClick)
        Grid.rowconfigure(self.window, 2, weight=1)
        Grid.columnconfigure(self.window, 0, weight=1)
        self.scroll.grid(row=2, column=3, sticky='ns')

    def openSearch(self):
        if self.window == None:
            self.createWindow()
        self.window.lift()
        self.input.focus()

    def loadIntervals(self):
        filecount = len(self.app.Data.getTopLevel('files'))
        self.intervals = []
        for f in range(filecount):
            filename = self.app.Data.getFileLevel('name', f)
            tg = self.app.Data.checkFileLevel('.TextGrid',
                                              f,
                                              shoulderror=False)
            if tg:
                grid = self.app.TextGrid.fromFile(tg)
                for tier in grid:
                    if TextGrid.isIntervalTier(tier):
                        for el in tier:
                            if el.mark:
                                self.intervals.append(
                                    (el, tier.name, filename))

    def search(self, event=None):
        if self.regex.get() == '':
            self.results = []
        else:
            pat = re.compile(self.regex.get(),
                             re.IGNORECASE | re.MULTILINE | re.DOTALL)
            self.results = []
            for i in self.intervals:
                s = pat.search(i[0].mark)
                if s:
                    disp = i[0].mark
                    a = max(0, s.start() - self.context_size)
                    b = min(s.end() + self.context_size, len(disp))
                    self.results.append(i +
                                        (('...' if a > 0 else '') + disp[a:b] +
                                         ('...' if b < len(disp) else ''), ))
        self.resultCount.configure(text='%s results' % len(self.results))
        for kid in self.resultList.get_children():
            self.resultList.delete(kid)
        for row, res in enumerate(self.results):
            ls = (res[2], res[1], '%s-%s' % (res[0].minTime, res[0].maxTime),
                  res[3])
            self.resultList.insert('', 'end', iid=str(row), values=ls)

    def onClick(self, event=None):
        self.jumpTo(int(self.resultList.selection()[0]))

    def jumpTo(self, index):
        self.app.filesJumpTo(self.results[index][2])
        self.app.TextGrid.selectedTier.set(self.results[index][1])
        self.app.TextGrid.start = self.results[index][0].minTime
        self.app.TextGrid.end = self.results[index][0].maxTime
        for i, f in enumerate(self.app.TextGrid.frameTier):
            if f.time >= self.results[index][0].minTime:
                self.app.frameSV.set(str(i))
                self.app.framesJumpTo()
                break
        self.app.TextGrid.fillCanvases()

    def reset(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::reset')

    def update(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::update')

    def grid(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::grid')

    def grid_remove(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::grid_remove')
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 #38
0
class Gr():
    def __init__(self,root,data,SCRY=None):
        self.data=data
        self.columns=[x for x in range(1,8)]+['day']
        root.rowconfigure(1,weight=1)
        root.columnconfigure(0,weight=1)
        root.columnconfigure(1,weight=1)
        root.columnconfigure(2,weight=1)
        f=Frame(root)
        f.columnconfigure(0,weight=1)
        f.rowconfigure(1,weight=1)
        self.v=Combobox(root)
        self.v.grid(row=0,column=0)
        self.v.bind('<<ComboboxSelected>>',self.select_ver)
        f.grid(row=1,column=0,columnspan=3,sticky=N+S)
        self.tree=Treeview(f,
                columns=self.columns,
                displaycolumns=['day']+self.columns[:-1],
                show='headings')
        #self.tree.tag_configure('odd',background='white')
        #self.tree.tag_configure('even',background='gray')
        self.tree.tag_configure('dif',foreground='brown')
        self.tree.tag_configure('work',background='white')
        self.tree.tag_configure('short',background='#F5EFE0')
        self.tree.tag_configure('rest',background='#E0B0B0')
        self.tree.tag_configure('holyday',background='#E7B7A4')
        for c in self.columns:
            self.tree.heading(c,text=c)
            self.tree.column(c,width=65,anchor='center')
        self.tree.column('day',width=30)
        scrX=Scrollbar(f,orient='horizontal',command=self.tree.xview)
        self.tree['xscrollcommand']=scrX.set
        if not SCRY:
            self.scrY=Scrollbar(f,orient='vertical',command=self.yview)
            self.tree['yscrollcommand']=self.scrY.set
        else:
            self.tree['yscrollcommand']=SCRY.set
        self.tree.grid(row=1,column=0,sticky=N+S)
        if not SCRY:
            self.scrY.grid(row=1,column=1,sticky=N+S)
        scrX.grid(row=2,column=0,sticky=E+W)
    def set(self,y,m):
        self.y=y
        self.m=m
        self.show()
    def yview(self,*args):
        self.tree.yview(*args)
        self.yview2(*args)
    def yview2(self,*args):
        pass
    def show(self):
        d=self.data[self.y][self.m]
        V=list(d['degur'].keys())
        self.v['values']=V
        self.v.set(V[0])
        self.select_ver()
    def select_ver(self,*e):
        self.tree.delete(*self.tree.get_children())
        d=self.data[self.y][self.m]
        offset=d['offset']
        v=self.v.get()
        col=[]
        for i,deg in enumerate(d['degurs']):
            self.tree.heading(i+1,text=deg)
            col.append(i+1)
        self.tree.configure(displaycolumns=['day']+col)
        items=dict()

        if 'табель' in d['degur']:
            a=[''.join(x) for x in zip(*[[x for x in d['degur']['план'][j]] \
                    for j in d['degurs']])]
            b=[''.join(x) for x in zip(*[[x for x in d['degur']['табель'][j]] \
                    for j in d['degurs']])]
            c=[x!=y for x,y  in zip(a,b)]
        else:
            c=[False]*32

        for i in range(1,d['days']+1):
            tag = (i+offset) % 7 in [0,6] and 'rest' or 'work'
            if i in d['holydays'] : tag='holyday'
            elif i in d['restdays'] : tag='rest'
            elif i in d['shortdays'] : tag='short'
            elif i in d['workdays'] : tag='work'
            if c[i]: tag=[tag,'dif']
            ii=self.tree.insert('','end',values=['-','-','-','-','-'],tag=tag)
            self.tree.set(ii,column='day',value=i)
            items[i]=ii

        
        for j,s in d['degur'][v].items(): # j-degur
            if not s: continue
            for i,val in enumerate(s[1:-1]):
                if val=='J':
                    val='до'
                elif val=='j':
                    val='од'
                elif val=='a':
                    val='10'
                self.tree.set(items[i+1],column=d['degurs'].index(j)+1,value=val)
            if s[0]=='Н':
                if s[1]=='-':
                    self.tree.set(items[1],column=d['degurs'].index(j)+1,value='Н(8)')
                else:
                    self.tree.set(items[1],column=d['degurs'].index(j)+1,value='!')
            if s[-2]=='Н':
                if s[-1]=='-':
                    self.tree.set(items[len(s)-2],column=d['degurs'].index(j)+1,value='Н(4)')
                else:
                    self.tree.set(items[len(s)-2],column=d['degurs'].index(j)+1,value='!')
        self.calc(self.y,self.m)
    def calc(self,y,m):
        d=self.data[y][m]
        offset=d['offset']
        WH=0
        for i in range(1,d['days']+1):
            if i in d['holydays']: wh=0
            elif i in d['restdays'] : wh=0
            elif i in d['shortdays'] : wh=7
            elif i in d['workdays'] : wh=8
            elif (i+offset) % 7 in [0,6]: wh=0
            else: wh=8
            WH+=wh
Exemple #39
0
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.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)
        
        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)

        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 or self.modelClassesChanged or self.disclosureSystemTypesChanged:  # may require reloading UI
            affectedItems = ""
            if self.uiClassMethodsChanged:
                affectedItems += _("menus of the user interface")
            if self.modelClassesChanged:
                if self.uiClassMethodsChanged:
                    affectedItems += _(" and ")
                affectedItems += _("model objects of the processor")
            if (self.uiClassMethodsChanged or self.modelClassesChanged):
                affectedItems += _(" and ")
            if self.disclosureSystemTypesChanged:
                if (self.uiClassMethodsChanged or self.modelClassesChanged):
                    affectedItems += _(" and ")
                affectedItems += _("disclosure system types")
            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]
        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):
        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.isdir(os.path.dirname(filename)) and
                os.path.isfile(os.path.join(os.path.dirname(filename), "__init__.py"))):
                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 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
                    elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                        self.modelClassesChanged = True # model object factor classes changed
                    elif classMethod == "DisclosureSystem.Types":
                        self.disclosureSystemTypesChanged = True # disclosure system types changed
            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
            elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                self.modelClassesChanged = True # model object factor classes changed
            elif classMethod == "DisclosureSystem.Types":
                self.disclosureSystemTypesChanged = True # disclosure system types changed
        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()
                    
    def enableAll(self):
        self.enableDisableAll(True)
                    
    def disableAll(self):
        self.enableDisableAll(False)
                    
    def enableDisableAll(self, doEnable):
        for module in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][module]
            if doEnable:
                moduleInfo["status"] = "enabled"
                self.moduleEnableButton['text'] = self.DISABLE
            else:
                moduleInfo["status"] = "disabled"
                self.moduleEnableButton['text'] = self.ENABLE
        self.pluginConfigChanged = True
        self.loadTreeViews()
            
Exemple #40
0
class BioInfo(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.wm_title("BioInfo : comparaison des listes")
        self.resizable(width=FALSE, height=FALSE)
        self.SortDir = False

        # Lists Types
        self.typeList1 = None
        self.typeList2 = None

        # Frame content
        self.frameContent = Frame(self)
        self.frameContent.pack(side=TOP, fill=X)

        # ScrollBar
        scrollbar = Scrollbar(self.frameContent, orient=VERTICAL)
        scrollbar.pack(side=RIGHT, fill=Y)

        # Result Content
        self.dataCols = ('microArn_A', 'microArn_B', 'FoldC', 'p-Value', 'Note')
        self.tree = Treeview(self.frameContent, columns=self.dataCols, show = 'headings', yscrollcommand=scrollbar.set)

        # configure column headings
        for c in self.dataCols:
            self.tree.heading(c, text=c, command=lambda c=c: self.columnSort(c, self.SortDir))
            self.tree.column(c, width=10)

        self.tree.pack(side=LEFT, fill=X, expand="yes")

        scrollbar.config(command=self.tree.yview)

        # Frame Lists
        self.frameLists = Frame(self)
        self.frameLists.pack(side=LEFT)

        # Frame Forms
        self.frameForms = Frame(self)
        self.frameForms.pack(side=LEFT, padx=20)

        #Liste n°1 selection
        self.frameList1 = Frame(self.frameLists)
        self.frameList1.pack()

        self.typeListStr1 = StringVar(self.frameList1)
        self.typeListStr1.set(str(ListBioType.TypeA))

        self.buttonTypeList1 = OptionMenu(self.frameList1, self.typeListStr1, str(ListBioType.TypeA), str(ListBioType.TypeB)).pack(side=LEFT)

        self.entrylist1 = Entry(self.frameList1, width=30)
        self.entrylist1.pack(side=LEFT)

        self.buttonBrowseList1 = Button(self.frameList1, text="Parcourir", command=self.load_fileList1, width=10)
        self.buttonBrowseList1.pack(side=LEFT, padx=5)

        # List n°2 selection
        self.frameList2 = Frame(self.frameLists)
        self.frameList2.pack(side=BOTTOM)

        self.typeListStr2 = StringVar(self.frameList2)
        self.typeListStr2.set(str(ListBioType.TypeB))

        self.buttonTypeList2 = OptionMenu(self.frameList2, self.typeListStr2, str(ListBioType.TypeA), str(ListBioType.TypeB)).pack(side=LEFT)

        self.entrylist2 = Entry(self.frameList2, width=30)
        self.entrylist2.pack(side=LEFT)

        self.buttonBrowseList2 = Button(self.frameList2, text="Parcourir", command=self.load_fileList2, width=10)
        self.buttonBrowseList2.pack(side=LEFT, padx=5)

        # Form pValue
        self.framePVal = Frame(self.frameForms)
        self.framePVal.pack()

        Label(self.framePVal, text="pValue").pack(side=LEFT)
        self.entryPVal = Entry(self.framePVal, width=6)
        self.entryPVal.pack(side=LEFT)

        # Form foldC
        self.frameFoldC = Frame(self.frameForms)
        self.frameFoldC.pack()

        Label(self.frameFoldC, text="foldCh").pack(side=LEFT)
        self.entryFoldC = Entry(self.frameFoldC, width=6)
        self.entryFoldC.pack(side=LEFT)

        # Form note
        self.frameNote = Frame(self.frameForms)
        self.frameNote.pack()

        Label(self.frameNote, text="note    ").pack(side=LEFT)
        self.entryNote = Entry(self.frameNote, width=6)
        self.entryNote.pack(side=LEFT)

        # Bouton comparer
        self.buttonComparer = Button(self, text="Comparer", command=self.compare, width=10, state=DISABLED)
        self.buttonComparer.pack(fill= X, expand="yes", padx=20, pady=(10,0))

        #Bouton exporter
        self.buttonExport = Button(self, text="Exporter", command=self.export, width=10, state=DISABLED)
        self.buttonExport.pack(fill= X, expand="yes", padx=20)

        # Réinitialiser
        self.buttonReset = Button(self, text="Réinitialiser", command=self.reset, width=10)
        self.buttonReset.pack(fill= X, expand="yes", padx=20, pady=(0,10))

        # file members
        self.list1 = None
        self.list2 = None

    def load_fileList1(self):
        fname = askopenfilename(filetypes=(("CSV files", "*.csv"),
                                           ("All files", "*.*") ))
        if fname:
            self.entrylist1.delete(0, END)
            self.list1 = fname
            self.entrylist1.insert(0,fname)

            self.buttonComparer.config(state=NORMAL)


    def load_fileList2(self):
        fname = askopenfilename(filetypes=(("CSV files", "*.csv"),
                                           ("All files", "*.*") ))
        if fname:
            self.entrylist2.delete(0, END)
            self.list2 = fname
            self.entrylist2.insert(0,fname)

            self.buttonComparer.config(state=NORMAL)

        else:
            showerror("Erreur : fichier B", "La liste B est introuvable")


    def resetTree (self):
        for i in self.tree.get_children():
            self.tree.delete(i)

    def reset(self):
        self.list1 = None
        self.entrylist1.delete(0, END)

        self.list2 = None
        self.entrylist2.delete(0, END)

        self.entryPVal.delete(0,END)
        self.entryFoldC.delete(0, END)
        self.entryNote.delete(0, END)

        self.typeList1 = None
        self.typeList2 = None

        self.buttonExport.config(state=DISABLED)
        self.buttonComparer.config(state=DISABLED)

        self.resetTree()

    def isValidfoldC(self, s):
        try:
            float(s)
            return True
        except ValueError:
            return False

    def isValidPValue(self, s):
        try:
            f = float(s)
            if f >= 0 and f <= 1:
                return True
            else:
                return False
        except:
            return False

    def isValidNote (self, s):
        try:
            f = int(s)
            return True
        except:
            return False

    def compare(self):
        self.buttonExport.config(state=NORMAL)

        # Détermination type Listes

        # List 1

        if self.typeListStr1.get() == str(ListBioType.TypeA):
            self.typeList1 = ListBioType.TypeA
        elif self.typeListStr1.get() == str(ListBioType.TypeB):
            self.typeList1 = ListBioType.TypeB
        else:
            self.typeList1 = None

        # List 2
        if self.typeListStr2.get() == str(ListBioType.TypeA):
            self.typeList2 = ListBioType.TypeA
        elif self.typeListStr2.get() == str(ListBioType.TypeB):
            self.typeList2 = ListBioType.TypeB
        else:
            self.typeList2 = None


        if not self.isValidfoldC(self.entryFoldC.get()) and not self.entryFoldC.get() == "":
            showerror("Erreur : foldC","La valeur fold Change n'est pas un nombre")

        elif not self.isValidPValue(self.entryPVal.get()) and not self.entryPVal.get() == "":
            showerror("Erreur : pValue","La valeur pValue n'est pas un nombre compris entre 0 et 1")

        elif not self.isValidNote(self.entryNote.get()) and not self.entryNote.get() == "":
            showerror("Erreur : note", "La valeur note n'est pas un nombre entier")

        # (List A and No List) or (No List and List A)
        elif ((self.list1 is not None and self.typeList1 == ListBioType.TypeA) and (self.list2 is None)) or\
             ((self.list2 is not None and self.typeList2 == ListBioType.TypeA) and (self.list1 is None)):

            self.resetTree()

            try:
                listComp = ListComparator(self.list1, self.list2, self.entryPVal.get(), self.entryFoldC.get(), self.entryNote.get())
                for e in listComp.getFilterListA():
                    self.tree.insert('', 'end', values=e)

            except IndexError:
                showerror("Erreur : liste A invalide", "Le fichier liste A n'est pas un fichier valide")


        # (List B and No List) or (No List and List B)
        elif ((self.list1 is not None and self.typeList1 == ListBioType.TypeB) and (self.list2 is None)) or\
             ((self.list2 is not None and self.typeList2 == ListBioType.TypeB) and (self.list1 is None)):

            self.resetTree()

            try:
                listComp = ListComparator(self.list1, self.list2, self.entryPVal.get(), self.entryFoldC.get())
                for e in listComp.getFilterListB():
                    self.tree.insert('', 'end', values=e)
            
            except IndexError:
                showerror("Erreur : liste A invalide", "Le fichier liste A n'est pas un fichier valide")

        # (List A and List B) or (List B and List A)
        elif ((self.list1 is not None and self.typeList1 == ListBioType.TypeA) and \
             (self.list2 is not None and self.typeList2 == ListBioType.TypeB)) or \
             ((self.list1 is not None and self.typeList1 == ListBioType.TypeB) and \
             (self.list2 is not None and self.typeList2 == ListBioType.TypeA)):

            self.resetTree()

            listA = ""
            listB = ""
            if self.typeList1 == ListBioType.TypeA:
                listA = self.list1
            else:
                listA = self.list2

            if self.typeList1 == ListBioType.TypeB:
                listB = self.list1
            else:
                listB = self.list2
            try:
                listComp = ListComparator(listA, listB, self.entryPVal.get(), self.entryFoldC.get(), self.entryNote.get())
                for e in listComp.getDiffAandB():
                    self.tree.insert('', 'end', values=e)

            except IndexError:
                showerror("Erreur : liste A ou B invalide", "Le fichier liste A ou B n'est pas un fichier valide")

        # (List A and List A)
        elif ((self.list1 is not None and self.typeList1 == ListBioType.TypeA) and \
             (self.list2 is not None and self.typeList2 == ListBioType.TypeA)):

            self.resetTree()

            try:
                listComp = ListComparator(self.list1, self.list2, self.entryPVal.get(), self.entryFoldC.get(), self.entryNote.get())
                for e in listComp.getDiffAandA():
                    self.tree.insert('', 'end', values=e)

            except IndexError:
                showerror("Erreur : liste A ou B invalide", "Le fichier liste A ou B n'est pas un fichier valide")

        # (List B and List B)
        elif ((self.list1 is not None and self.typeList1 == ListBioType.TypeB) and \
             (self.list2 is not None and self.typeList2 == ListBioType.TypeB)):

            self.resetTree()

            try:
                listComp = ListComparator(self.list1, self.list2, self.entryPVal.get(), self.entryFoldC.get())
                for e in listComp.getDiffBandB():
                    self.tree.insert('', 'end', values=e)

            except IndexError:
                showerror("Erreur : liste A ou B invalide", "Le fichier liste A ou B n'est pas un fichier valide")
        else:
            showerror("Erreur : Combinaisons de listes invalides", "Votre choix de types de listes ne correspond à aucune combinaison possible, contacter le developpeur")


    def export(self):
        if len(self.tree.get_children()) == 0:
            showinfo("Export", "Il n'y a rien à exporter")
            return

        fname = asksaveasfilename(filetypes=(("CSV files", "*.csv"),
                                             ("All files", "*.*") ))

        if fname:
            resExp = []
            for it in self.tree.get_children():
                resExp.append(self.tree.item(it)["values"])

            expTabToCSV = TreeExportator(resExp, fname)
            expTabToCSV.export()

            showinfo("Export", "Exportation au format CSV réussi")

    def columnSort (self, col, descending=False):
        data = [(self.tree.set(child, col), child) for child in self.tree.get_children('')]

        data.sort(reverse=descending)
        for indx, item in enumerate(data):
            self.tree.move(item[1], '', indx)

        # reverse sort direction for next sort operation
        self.SortDir = not descending
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")
Exemple #42
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")
Exemple #43
0
class MainFrame(Frame):
    """ Główna ramka aplikacji
    """

    def __init__(self, ui: SharedrawUI):
        Frame.__init__(self, ui.root)
        self.parent = ui.root
        self.ui = ui

        self.parent.title("Sharedraw [%s:%s, id: %s]" % (self.ui.peer_pool.ip, self.ui.peer_pool.port, own_id))
        self.drawer = Drawer(self.parent, WIDTH, HEIGHT, self.save)
        self.clients_table = Treeview(self.parent, columns=('R', 'G', 'from'))
        self.clients_table.heading('#0', text='Id')
        self.clients_table.heading('R', text='R')
        self.clients_table.heading('G', text='G')
        self.clients_table.heading('from', text='Otrzymano od:')
        self.clients_table.pack()
        self.token_owner_label = MutableLabel(self.parent, 'Posiadacz tokena: %s', lambda s: s if s else 'Nikt', None)
        self.token_owner_label.pack()
        self.locked_label = MutableLabel(self.parent, 'Tablica %s', lambda b: 'zablokowana' if b else 'odblokowana',
                                         False)
        self.locked_label.pack()
        # Przycisk czyszczenia
        self.clean_btn = self._create_button(text="Czyść", func=self.clean)
        # Przycisk podłączenia
        self.connect_btn = self._create_button(text="Podłącz", func=self.connect)
        # Przycisk żądania przejęcia na własność
        self.req_btn = self._create_button(text="Chcę przejąć tablicę", func=self._make_request)
        # Rezygnacja z posiadania blokady
        self.resign_btn = self._create_button(text='Zrezygnuj z blokady', func=self._resign)

    def _create_button(self, text: str, func):
        """ Tworzy nowy przycisk w bieżącej ramce
        :param text: tekst przycisku
        :param func: funkcja wywoływana po naciśnięciu
        :return: przycisk
        """
        btn = Button(self.parent, text=text, command=func)
        btn.pack()
        return btn

    def save(self):
        """ Wysyła komunikat o zmianie obrazka do innych klientów
        :return:
        """
        if self.drawer.changed_pxs:
            msg = PaintMessage(self.drawer.changed_pxs, self.drawer.color)
            self.ui.peer_pool.send(msg)
            # Reset listy punktów
            self.drawer.changed_pxs = []

    def clean(self):
        """ Czyści obrazek oraz wysyła komunikat o wyczyszczeniu
        :return:
        """
        self.drawer.clean_img()
        msg = CleanMessage(own_id)
        self.ui.peer_pool.send(msg)

    def _make_request(self):
        """ Żąda przejęcia tablicy na własność
        :return:
        """
        clients_info = self.ui.om.claim_ownership()
        self.update_clients_info(clients_info)

    def _resign(self):
        clients_info = self.ui.om.resign()
        self.update_clients_info(clients_info)

    def connect(self):
        """ Uruchamia okno dialogowe do podłączenia się z innym klientem
        :return:
        """
        d = ConnectDialog(self.ui)
        self.parent.wait_window(d.top)

    def update_clients_info(self, clients: ClientsTable):
        # Aktualizacja listy klientów
        for ch in self.clients_table.get_children():
            self.clients_table.delete(ch)
        for client in clients.clients:
            self.clients_table.insert('', 'end', text=client.id,
                                      values=(client.requested, client.granted, client.received_from_id))
        # Aktualizacja info o właścicielu tokena i blokadzie
        self.locked_label.update_text(clients.locked)
        self.token_owner_label.update_text(clients.token_owner)
        # Aktualizacja blokady
        has_token = clients.token_owner == own_id
        self.__set_lock_state(clients.locked, has_token)
        # Aktualizacja przycisków
        # jeśli zablokowaliśmy, to nie możemy tego zrobić drugi raz
        is_locker = (has_token and clients.locked)
        # tak samo jeśli już zażądaliśmy
        has_requested = clients.find_self().has_requested()
        self.__set_button_enabled(self.req_btn, not (is_locker or has_requested))
        # jeśli nie zablokowaliśmy, to nie możemy rezygnować
        self.__set_button_enabled(self.resign_btn, is_locker)
        # Możemy się podłączyć, tylko, jeśli nie jesteśmy do nikogo podłączeni
        self.__set_button_enabled(self.connect_btn, len(clients.clients) <= 1)
        # Przycisk czyść aktywny jeśli możemy rysować
        self.__set_button_enabled(self.clean_btn, has_token or not clients.locked)

    @staticmethod
    def __set_button_enabled(btn: Button, enabled: bool):
        btn.configure(state=(NORMAL if enabled else DISABLED))

    def __set_lock_state(self, locked: bool, has_token: bool):
        self.drawer.locked = locked and not has_token
        # Dodatkowo ustawiamy kolor tła, żeby było ładnie widać
        if locked:
            if has_token:
                color = '#66FF66'
            else:
                color = '#FF9999'
        else:
            color = '#FFFFFF'
        self.parent.configure(bg=color)
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()