Exemple #1
0
    def __init__(self, parent, tree: ttk.Treeview) -> None:
        Frame.__init__(self, parent)
        self.parent = parent

        self.values = tree.item(tree.selection())["values"]
        self.old = tree.item(tree.selection())["values"]

        self.initUI()
Exemple #2
0
class hey:
    def __init__(self):
        self.star1 = Toplevel()
        self.obj = database.Database()
        self.result = self.obj.getmenu()
        self.star1.geometry('1366x768')
        self.can = Canvas(self.star1, height=768, width=1366)
        self.can.pack()
        self.img = PhotoImage(file='./image/654.png')
        self.can.create_image(0, 0, image=self.img, anchor=NW)
        self.table = Treeview(self.can, columns=("#0", "#1", "#2", "#3", "#4"))
        self.table.heading('#0', text="Sr no.")
        self.table.column('#0', width=40)
        self.table.heading('#1', text="Name")
        self.table.column('#1', width=100)
        self.table.heading('#2', text="Amount")
        self.table.column('#2', width=100)
        self.table.heading('#3', text="edit")
        self.table.column('#3', width=100)
        self.table.heading('#4', text="delete")
        self.table.column('#4', width=100)
        for i in self.result:
            self.table.insert('',
                              'end',
                              text=i[0],
                              values=(i[1], i[2], "edit", "Delete"))
        self.table.place(x=300, y=300)
        self.btn = Button(self.can,
                          text="<- Back",
                          fg='white',
                          bg='black',
                          font=('monaco', 15, 'bold'),
                          command=self.back)
        self.btn.place(x=810, y=540)
        self.table.bind("<Double-Button-1>", self.trigger)
        self.star1.resizable(height=False, width=False)
        self.star1.state("zoomed")
        self.star1.mainloop()

    def back(self):
        self.star1.destroy()

    def trigger(self, e):
        f = self.table.focus()
        x = self.table.item(f)
        col = self.table.identify_column(e.x)
        if (col == "#3"):
            self.star1.destroy()
            obj = updatemenu.UpdateMenu(x["text"])
        elif (col == "#4"):
            self.star1.destroy()
            d = database.Database()
            d.delete(x["text"])
Exemple #3
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)
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
 def select_item(self, event: tk.Event,
                 prop_class: Union[EXIFProperty, GPSProperty], tree: ttk.Treeview):
     query_item: Union[Tuple, str] = tree.item(tree.focus(), option='values')
     if query_item == '':
         return
     col: str = tree.identify_column(getattr(event, 'x'))
     prop, val = query_item
     if col == '#1':
         if isinstance(prop_class, IFDPanel.EXIFProperty) and prop == prop_class.file_name:
             os.startfile(self.app.widget_info.cur_img_path)
         return
     # '#2'
     if isinstance(prop_class, IFDPanel.EXIFProperty) and prop == prop_class.file_name:
         val = self.app.widget_info.cur_img_path.stem
     tree.clipboard_clear()
     tree.clipboard_append(val)
Exemple #6
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 #7
0
class Window:
    def __init__(self):

        self.tk = Tk()
        self.tk.geometry('500x500')
        fetch = (getdata.fetch())
        self.tree = Treeview(self.tk, columns=("#1", "#2", "#3", "#4"))
        self.tree.heading("#0", text="user id")
        self.tree.column("#0", width=60)
        self.tree.heading("#1", text="User Name")
        self.tree.heading("#2", text="Password")
        self.tree.heading("#3", text="Update")
        self.tree.heading("#4", text="Delete")
        self.data = getdata.fetch()
        for i in self.data:
            self.tree.insert('',
                             'end',
                             text=i[0],
                             values=(i[1], i[2], "update", "delete"))
        self.tree.place(x=0, y=0)

        self.tree.bind("<Double-Button-1>", self.trigger)

        self.tk.mainloop()

    def trigger(self, e):
        #e will identify from where the function has been triggered
        print(e)
        #d will store the object of focused element in the treeview
        d = self.tree.focus()
        #self.tree.item is use to get the data from the focused row
        #so thats why we pass the focused item there d
        x = (self.tree.item(d))
        print(x)
        #col will identify the focused column
        col = self.tree.identify_column(e.x)
        if col == "#3":

            print("Update")
        elif col == "#4":
            getdata.delete(x["text"])
            print("delete")
Exemple #8
0
class MultipleInstallPage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.controller = controller
        # will do a 4x4 grid here
        for count in range(0, 4):
            Grid.rowconfigure(self, count, weight=1)
            Grid.columnconfigure(self, count, weight=1)
        self.temp_tv = Treeview(self)
        temp_tv = self.temp_tv
        temp_tv.grid(row=0,
                     column=0,
                     rowspan=3,
                     columnspan=4,
                     sticky=(N, E, W, S))
        temp_tv.heading('#0', text="Choose one:")
        temp_tv.column("#0", minwidth=300)

        # adding scrollbar

        ysb = Scrollbar(self, orient='vertical', command=temp_tv.yview)
        temp_tv.configure(yscroll=ysb.set)
        ysb.grid(row=0, column=3, rowspan=3, sticky='nse')

        # Buttons for the rest

        ok_button = Button(self, text="Ok", command=self.ok_button_click)
        ok_button.grid(row=3, column=0, sticky=N + S + E + W)

        cancel_button = Button(self,
                               text="Cancel",
                               command=lambda: controller.show_frame(MainPage))
        cancel_button.grid(row=3, column=3, sticky=N + S + E + W)

    def ok_button_click(self):
        # Should only do stuff is something is selected
        if self.temp_tv.focus() != '':
            installer_path = self.temp_tv.item(self.temp_tv.focus())['text']
            launch_installer(installer_path)
            self.controller.show_frame(MainPage)
        else:
            return -1
Exemple #9
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 MediumTreeView(Frame):
    def __init__(self, parent, *args, **kwargs):
        Frame.__init__(self, parent)
        self.tree = Treeview(self)
        self.tree['selectmode'] = "browse"
        self.tree['columns'] = ('ID', 'Name', 'Gram', 'Include')
        self.tree['height'] = 30
        self.tree['show'] = "headings"
        self.tree.heading('ID', text="ID")
        self.tree.heading('Name', text="Name")
        self.tree.heading('Gram', text="Quantity [mmol]")
        self.tree.heading('Include', text="Include")
        self.tree.column('ID', minwidth=0, width=20)
        self.tree.column('Name', minwidth=100, width=100)
        self.tree.column('Gram', minwidth=0, width=90)
        self.tree.column('Include', minwidth=50, width=50)
        self.tree.bind('<ButtonRelease-1>', self.select_item)
        self.tree.grid(row=0, column=0, columnspan=4)
        self.run_object = kwargs.pop('run_object', None)

        self.medium = None
        self.medium_volume = None
        self.uptake_quantities = {}
        self.species_names = []

        self.pie_figure, self.piechart = plt.subplots()
        self.pie_figure.figsize = (4, 4)
        self.piechart.pie([0, 0])
        self.canvas = FigureCanvasTkAgg(self.pie_figure, master=self)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(row=0, column=4, padx=10)

        Label(self, text="Quantity:").grid(row=1, column=0)
        self.edit_entry = FloatEntry(self, initial_value='')
        self.edit_entry.grid(row=1, column=1, sticky='w')
        Button(self, text="Save Changes",
               command=self.save_changes).grid(row=1, column=2, rowspan=2)

        self.rad_var = IntVar()
        self.rad_button_exclude = Radiobutton(self,
                                              text="No",
                                              variable=self.rad_var,
                                              value=0)
        self.rad_button_include = Radiobutton(self,
                                              text="Yes",
                                              variable=self.rad_var,
                                              value=1)
        self.rad_button_include.grid(row=2, column=1, sticky='w')
        self.rad_button_exclude.grid(row=2, column=1, sticky='e')
        Label(self, text="Include:").grid(row=2, column=0)
        Label(self, text="Medium Name:").grid(row=3, column=0)
        self.name_entry = StringEntry(self, initial_value="refined_medium")
        self.name_entry.grid(row=3, column=1, sticky='w')

        Button(self, text="Test Medium", command=parent.plot).grid(row=4,
                                                                   column=1)
        Button(self,
               text="Save Medium",
               command=lambda: self.save_medium(parent.save)).grid(row=3,
                                                                   column=2)

    def plot_medium(self, individual, sub_plot):
        #costruct medium from treeviev
        if self.medium is not None:
            components = {}
            children = self.tree.get_children('')
            for child in children:
                child = self.tree.item(child)
                ID = child['values'][0]
                quant = float(child['values'][2])
                flag = bool(child['values'][3])
                if flag:
                    components[ID] = quant
            medium = Medium.from_dict(components, self.medium_volume)

            #simulate medium to get the nutrition uptake for each member of the bacterial community
            individual.plot(True, medium=medium, sub_plot=sub_plot)
            uptakes = individual.get_uptakes()

            #calculate the relative uptake quantities
            self.uptake_quantities = {}
            for child in children:
                child_elements = self.tree.item(child)
                ID = child_elements['values'][0]
                name = child_elements['values'][1]
                quant = float(child_elements['values'][2])
                flag = child_elements['values'][3]

                uptake_per_species = []
                self.species_names = []

                for n, spec in enumerate(uptakes):
                    self.species_names.append(spec)
                    try:
                        uptake = uptakes[spec][ID]
                    except:
                        uptake = 0

                    try:
                        self.uptake_quantities[ID].append(uptake)
                    except:
                        self.uptake_quantities[ID] = [uptake]

            for ID in self.uptake_quantities:
                total = sum(self.uptake_quantities[ID])
                if total == 0:
                    self.uptake_quantities[ID] = [
                        0 for i in self.species_names
                    ]
                    print(ID)
                    continue
                relative_quantities = []
                for i in self.uptake_quantities[ID]:
                    relative_quantities.append(i / total)
                self.uptake_quantities[ID] = relative_quantities

    def add_medium(self, medium, medium_volume):
        if medium is not None:
            self.medium = medium
            self.medium_volume = medium_volume
            self.update_treeviev()

    def update_treeviev(self):
        if self.medium is not None:
            for i, comp in enumerate(self.medium.get_components()):
                try:
                    name = SEEDIDs.SEED_to_Names[comp.split("_")[1]]
                except:
                    name = comp
                self.tree.insert('',
                                 i,
                                 comp,
                                 values=[
                                     comp, name,
                                     self.medium.get_components()[comp], 1, ""
                                 ])

    def select_item(self, a):
        try:
            currItem = self.tree.focus()
            string_qu = self.tree.item(currItem)['values'][2]
            include = bool(self.tree.item(currItem)['values'][3])
            self.edit_entry.set(string_qu)
            self.rad_var.set(0 if not include else 1)

            self.piechart.clear()
            self.piechart.pie(
                self.uptake_quantities[self.tree.item(currItem)['values'][0]],
                labels=self.species_names,
                labeldistance=None)
            self.piechart.axis('equal')
            self.piechart.legend()
            self.canvas.draw()
        except:
            pass

    def save_changes(self):
        currItem = self.tree.focus()
        ID = self.tree.item(currItem)['values'][0]
        name = self.tree.item(currItem)['values'][1]
        exclude = 1 if self.rad_var.get() == 1 else 0
        uptake = self.tree.item(currItem)['values'][4]
        self.tree.item(
            currItem,
            values=[ID, name, self.edit_entry.get(), exclude, uptake])

    def load_medium(self, file):
        medium = Medium.import_medium(file)
        self.add_medium(medium)

    #saves medium to file
    def save_medium(self, path):
        if self.medium is not None:
            file_path = ""
            for x in path.split("/")[:-1]:
                file_path = file_path + x + "/"

            components = {}
            children = self.tree.get_children('')
            for child in children:
                child = self.tree.item(child)
                ID = child['values'][0]
                name = child['values'][1]
                quant = float(child['values'][2])
                flag = bool(child['values'][3])
                if flag:
                    if quant > 0:
                        components[name] = quant
            medium = Medium.from_dict(components, self.medium_volume)
            Medium.export_medium(
                medium, file_path + "/" + self.name_entry.get() + ".csv")
Exemple #11
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 #12
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
Exemple #13
0
class GUI:
    def __init__(self):
        self.root = Tk()
        self.right_frame = Frame(self.root)
        self.left_frame = Frame(self.root)
        self.image = None
        self.scrollbarx = Scrollbar(self.left_frame, orient=HORIZONTAL)
        self.scrollbary = Scrollbar(self.left_frame, orient=VERTICAL)
        self.tree = None
        self.files = {}
        self.tree_index = None
        self.selected_item = None

        self.test_data_creator = TestDataCreator()
        self.char_images = []
        self.index = 0
        self.panel = None

        self.buttons = {}

    def create_root(self):
        self.root.title('Data Creator')
        w = 720
        h = 450
        sw = self.root.winfo_screenwidth()
        sh = self.root.winfo_screenheight()
        x = (sw - w) / 2
        y = (sh - h) / 2
        self.root.geometry('%dx%d+%d+%d' % (w, h, x, y))
        self.root.resizable(False, False)
        self.add_left_frame()
        self.add_buttons()

        self.left_frame.pack(side=LEFT)
        self.right_frame.pack(side=RIGHT)

    def add_buttons(self):
        self.panel = Label(self.right_frame, image=self.image)
        self.panel.pack(side=TOP)

        digit_frame = Frame(self.right_frame)
        for i in [str(i) for i in range(10)]:
            button_digit = Button(digit_frame, text=i, width=3)
            button_digit.bind('<Button-1>', self.button_click)
            button_digit.pack(side=LEFT, padx=2.)
        digit_frame.pack(pady=5)

        alpha_frame = Frame(self.right_frame)
        for i in ['A', 'B', 'E', 'K', 'M', 'H', 'O', 'P', 'C', 'T', 'Y', 'X']:
            button_alpha = Button(alpha_frame, text=i, width=3)
            button_alpha.bind('<Button-1>', self.button_click)
            button_alpha.pack(side=LEFT, padx=2.)
        alpha_frame.pack(pady=5)

        button_nothing = Button(self.right_frame, text='-', width=10)
        button_nothing.bind('<Button-1>', self.button_click)
        button_nothing.pack()

    def create_tree(self):
        if self.tree:
            self.tree.destroy()

        style = Style(self.left_frame)
        style.configure('Calendar.Treeview', rowheight=50)
        self.tree = Treeview(self.left_frame,
                             columns='#1',
                             height=400,
                             selectmode="extended",
                             yscrollcommand=self.scrollbary.set,
                             xscrollcommand=self.scrollbarx.set,
                             style='Calendar.Treeview')

        self.scrollbary.config(command=self.tree.yview)
        self.scrollbary.pack(side=RIGHT, fill=Y)
        self.scrollbarx.config(command=self.tree.xview)
        self.scrollbarx.pack(side=BOTTOM, fill=X)

        self.tree.heading('#0', text='image', anchor=CENTER)
        self.tree.heading('#1', text='file_name')

        self.tree.column('#0', width=80, anchor=CENTER)
        if self.files:
            for key in self.files:
                self.tree.insert("", 'end', values=key, image=self.files[key])
        self.tree.pack(side=BOTTOM)

    def add_left_frame(self):
        load_button = Button(self.left_frame,
                             text="load files",
                             command=self.load_files)
        load_button.pack(side=TOP, anchor=NW, pady=5)
        start_button = Button(self.left_frame,
                              text='Start recognition',
                              command=self.run)
        start_button.pack(side=TOP, anchor=NW)
        self.create_tree()

    def load_files(self):
        file_names = fd.askopenfilenames(
            filetypes=[('Image file',
                        '*.png'), ('Image file',
                                   '*.jpg'), ('Image file', '*.jpeg')])
        for file in file_names:
            self.files[file] = ImageTk.PhotoImage(
                Image.open(file).resize((60, 40)))
        self.create_tree()

    def button_click(self, event):
        image_name = event.widget.cget('text')
        if image_name != '-':
            self.test_data_creator.multiply_image(self.char_images[self.index],
                                                  image_name)

        self.index += 1
        if self.index >= len(self.char_images):
            del self.files[self.selected_item]
            mb.showinfo("Recognition", "Characters are over!")
            self.image = None
            self.create_tree()
        else:
            self.image = ImageTk.PhotoImage(
                Image.fromarray(self.char_images[self.index].image).resize(
                    (120, 200)))
        self.panel.configure(image=self.image)

    def run(self):
        index = self.tree.selection()

        if not index:
            mb.showinfo("Choice image", "Not selected item")
            return
        index = index[0]
        self.selected_item = ' '.join(self.tree.item(index)['values'])
        self.char_images = self.test_data_creator.start(self.selected_item)
        self.index = 0
        if not self.char_images:
            mb.showerror("Recognition", "Car numbers not recognized")
            del self.files[self.selected_item]
            self.create_tree()
            self.image = None
        else:
            self.image = ImageTk.PhotoImage(
                Image.fromarray(self.char_images[self.index].image).resize(
                    (120, 200)))
            self.panel.configure(image=self.image)
Exemple #14
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)
                 text=col.title(),
                 command=lambda c=col: sort_by(tree, c, 0))
    #tree.column(col,stretch=True)
    #tree.column(col,width=font.nametofont('TkHeadingFont').measure(col.title()),
    #stretch=False)
    tree.column(
        col,
        width=font.Font(family=font_family, size=font_size,
                        weight='bold').measure(col.title()) + 10,
        stretch=False)
    #print(tree.column(col))

# insert data row by row, then measure each items' width
for ix, item in enumerate(tree_data):
    item_ID = tree.insert('', 'end', values=item)
    tree.item(item_ID, tags=item_ID)
    tree.tag_configure(item_ID, background=backg[ix % 2])

    for indx, val in enumerate(item):
        #ilen = font.Font(family="Segoe UI", size=10, weight="normal").measure(val)
        ilen = font.nametofont('TkDefaultFont').measure(val)
        if tree.column(tree_columns[indx], width=None) < ilen + 10:
            tree.column(tree_columns[indx], width=ilen + 10)
        # you should see the widths adjust
        #print('col',tree.column(tree_columns[indx]),ilen)

# display selection
lvar = StringVar()
lbl = Label(fr0, textvariable=lvar, text="Ready")
lbl.grid(column=0, row=1, sticky='nsew')
Exemple #16
0
class FacultyDelWindow:
    def __init__(self, data=''):
        self.data = data
        print(self.data)
        self.win = Tk()
        self.canvas = Canvas(self.win, width=800, height=420, bg='white')
        self.canvas.pack(expand=YES, fill=BOTH)

        # show window in center of the screen
        width = self.win.winfo_screenwidth()
        height = self.win.winfo_screenheight()
        x = int(width / 2 - 800 / 2)
        y = int(height / 2 - 420 / 2)
        str1 = "800x420+" + str(x) + "+" + str(y)
        self.win.geometry(str1)

        # disable resize window
        self.win.resizable(False, False)

        # changing title of the window
        self.win.title(
            "| DELETING FACULTY DETAILS | LIBRARY MANAGEMENT SYSTEM |")

    def add_frame(self):

        self.frame = Frame(self.win, height=420, width=800)
        self.frame.place(x=0, y=0)

        x, y = 0, 0

        self.label = Label(self.frame,
                           text="DELETING FACULTY DETAILS",
                           fg='black')
        self.label.config(font=("Poppins", 20, 'underline bold'))
        self.label.place(x=190, y=35)

        # use tree view to show details from the table
        self.tr = Treeview(self.frame,
                           columns=('FACULTY_ID', 'FACULTY_NAME', 'GENDER',
                                    'DEPARTMENT', 'CONTACT_NO'),
                           selectmode="extended")

        # heading key + text

        self.tr.heading('#0', text='FACULTY_ID')
        self.tr.column('#0', minwidth=0, width=100, stretch=NO)
        self.tr.heading('#1', text='FACULTY_NAME')
        self.tr.column('#1', minwidth=0, width=100, stretch=NO)
        self.tr.heading('#2', text='GENDER')
        self.tr.column('#2', minwidth=0, width=100, stretch=NO)
        self.tr.heading('#3', text='DEPARTMENT')
        self.tr.column('#3', minwidth=0, width=100, stretch=NO)
        self.tr.heading('#4', text='CONTACT_NO')
        self.tr.column('#4', minwidth=0, width=100, stretch=NO)
        self.tr.heading('#5', text='DELETE')
        self.tr.column('#5', minwidth=0, width=100, stretch=NO)
        # self.tr.heading('#6', text='DELETE')
        # self.tr.column('#6', minwidth=0, width=100, stretch=NO)

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

        # create action on deletion
        self.tr.bind('<Double-Button-1>', self.actions)
        self.tr.place(x=100, y=y + 100)

        self.win.mainloop()

    def actions(self, e):
        # get the value of deleted row
        tt = self.tr.focus()

        # get the column id
        col = self.tr.identify_column(e.x)
        print(col)
        print(self.tr.item(tt))

        data = (self.tr.item(tt).get('text'), )

        if col == '#5':
            res = messagebox.askyesno("Message", "Do you want  to delete..!")
            if res:
                d = Database.database.DeleteFaculty(data)
                if d:
                    messagebox.showinfo(
                        "Message", "Faculty Details deleted successfully..!")
                    self.win.destroy()
                    x = Thirdpage
            else:
                self.win.destroy()
                x = Student.DeleteFaculty.FacultyDelWindow()
                x.add_frame()
Exemple #17
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 #18
0
class My_Tk():
    def __init__(self,
                 root,
                 user_info=None,
                 cookies=None,
                 headers=None,
                 tasklist_=None):
        self.tk = root
        self.user_info = user_info
        self.base_cookies = cookies
        self.base_headers = headers
        # self.tk.geometry('620x400')
        self.orm = {}
        self.val_map = {}
        self.create_button()
        self.create_heading()
        self.create_tv()
        self.tasklist_ = tasklist_

    def create_button(self):
        frame = Frame(self.tk, width=200, height=50)
        frame.pack(fill=X, side=TOP)

        Button(frame, text='下载', width=6, command=self.download).place(x=28,
                                                                       y=21)
        # Button(frame, text='测试数据', command=self.insert_test_tree_data).pack(side=LEFT, anchor='w')
        Button(frame, text='清除列表', command=self.clear_tree_data).place(x=82,
                                                                       y=21)

    def get_tv(self):
        return self.tv

    def download(self):
        try:
            for k, v in self.orm.items():
                button = self.orm[k][0]
                button_value = button.getvar(button['variable'])
                if button_value == '1':
                    print(self.tv.item(k, 'values'))
                    if self.user_info == None or len(self.user_info) == 0:
                        messagebox.showinfo(title="提示", message="请先登录!")
                        return
                    else:
                        media_type = self.tasklist_.media_type_var.get()
                        if media_type and media_type == ".mp4":
                            params = {
                                'fragmentId': self.val_map[k] + 1,
                                'token': self.user_info['token'],
                                'albumId': -8888888,
                                'programId': -8888888
                            }
                        else:
                            params = {
                                'fragmentId': self.val_map[k],
                                'token': self.user_info['token'],
                                'albumId': 0,
                                'programId': 0
                            }
                        self.base_headers["Host"] = "api.dushu.io"
                        response = requests.post(
                            url="http://api.dushu.io/fragment/content",
                            json=params,
                            headers=self.base_headers,
                            cookies=self.base_cookies)
                        response_data = response.json()
                        mediaUrls = response_data["mediaUrls"]
                        mediaUrl = None
                        if mediaUrls and type(
                                mediaUrls) == list and len(mediaUrls) > 0:
                            if len(mediaUrls) > 1:
                                if media_type == r".mp4":
                                    for url_ in mediaUrls:
                                        if url_.find("video") != -1:
                                            mediaUrl = url_
                                elif media_type == r".mp3":
                                    media_type = r".mp3"
                                    for url_ in mediaUrls:
                                        if url_.find("audio") != -1:
                                            mediaUrl = url_
                            elif mediaUrls[0].find("audio") != -1:
                                if media_type == '.mp4':
                                    messagebox.showinfo(
                                        title="提示",
                                        message="该资源只有音频,请在任务列表切换下载类型!")
                                    return
                                else:
                                    mediaUrl = response_data['mediaUrls'][0]

                            elif mediaUrls[0].find("video") != -1:
                                mediaUrl = response_data['mediaUrls'][0]
                            else:
                                return
                        else:
                            return
                        if media_type == '.mp3':
                            file_name = response_data['title']
                        else:
                            file_name = response_data['bookName']
                        print(mediaUrl)

                        media_info_headers = {}
                        if (mediaUrl.startswith("https")):
                            mediaUrl = "http" + mediaUrl[5:]

                        host_pattern = re.compile("\w+://(.*?)/.*")
                        host_ = host_pattern.findall(mediaUrl)[0]
                        if host_ != "cdn-ali.dushu.io":
                            media_info_headers = {
                                'Host': "v-cc.dushu.io",
                                'Cookie':
                                "grwng_uid=e7e51c80-ead6-43bb-9744-7531778d6c73; UM_distinctid=16be039d03e8aa-0f0e963eb0f589-621c740a-4a640-16be039d03f633; gr_user_id=ebc67f00-d109-4c29-80b0-7d631382debf",
                                'X-Playback-Session-Id':
                                "A078D569-3595-4399-8240-EB42F542F073",
                                'Connection': "keep-alive, keep-alive",
                                'Accept': "*/*",
                                'User-Agent':
                                "AppleCoreMedia/1.0.0.16D57 (iPhone; U; CPU OS 12_1_4 like Mac OS X; en_us)",
                                'Accept-Language': "en-us",
                                'Accept-Encoding': "gzip",
                                'cache-control': "no-cache"
                            }
                        else:
                            media_info_headers = {
                                'Host': "cdn-ali.dushu.io",
                                'Cookie':
                                "grwng_uid=e7e51c80-ead6-43bb-9744-7531778d6c73; UM_distinctid=16be039d03e8aa-0f0e963eb0f589-621c740a-4a640-16be039d03f633; gr_user_id=ebc67f00-d109-4c29-80b0-7d631382debf",
                                'X-Playback-Session-Id':
                                "A9D630B7-54FF-4514-923C-A561AFA5C7BA",
                                'Range': "bytes=0-1",
                                'Accept': "*/*",
                                'User-Agent':
                                "AppleCoreMedia/1.0.0.16D57 (iPhone; U; CPU OS 12_1_4 like Mac OS X; en_us)",
                                'Accept-Language': "en-us",
                                'Accept-Encoding': "identity",
                                'Connection': "keep-alive",
                                'cache-control': "no-cache",
                            }
                            media_info_headers["Range"] = "bytes=0-1"

                        media_info_headers['Host'] = host_

                        media_info = requests.get(url=mediaUrl,
                                                  headers=media_info_headers,
                                                  cookies=self.base_cookies)
                        file_des = self.tasklist_.download_dir.get(
                        ) + r"\\" + file_name + media_type
                        bytes_length = 0
                        if "Content-Range" in media_info.headers:
                            range_ = media_info.headers['Content-Range']
                            bytes_length = range_[range_.rfind('/') + 1:]
                        elif host_ == "cdn-ali.dushu.io":
                            with open(file_des, "wb") as saved:
                                saved.write(bytes(media_info.content))
                                return

                        def down():

                            try:
                                row = [
                                    str(datetime.now().strftime(
                                        "%Y%m%d%H%M%S")),
                                    file_name + media_type,
                                    datetime.now().strftime(
                                        "%Y-%m-%d %H:%M:%S"),
                                    self.tasklist_.catch_progress_bar(),
                                    StringVar(value="0")
                                ]
                                with open(file_des, 'wb') as saved:

                                    self.tasklist_.insert_data(row)
                                    media_info_content = media_info.content
                                    play_list_pattern = re.compile(
                                        "(\w+\.mp4_[\d]+\.ts)", re.DOTALL)
                                    play_list = []
                                    if type(media_info_content) != str:
                                        play_list = play_list_pattern.findall(
                                            str(media_info_content))

                                    threading.Thread(
                                        target=lambda: {
                                            messagebox.showinfo(
                                                title="提示",
                                                message="请前往任务列表查看下载状态")
                                        }).start()
                                    if play_list != None and len(
                                            play_list) == 0:
                                        if int(bytes_length) <= 0:
                                            return
                                        print(type(bytes_length))
                                        count = (int(bytes_length) + 1 -
                                                 131072) / 131072
                                        print(count)
                                        print(type(count))
                                        tmp = 0
                                        for index in range(int(count)):
                                            if index == count - 1:
                                                media_info_headers[
                                                    'Range'] = "bytes=" + str(
                                                        index * 131072
                                                    ) + "-" + str(bytes_length)
                                            else:
                                                media_info_headers[
                                                    'Range'] = "bytes=" + str(
                                                        index *
                                                        131072) + "-" + str(
                                                            (index + 1) *
                                                            131072 - 1)
                                            media_content = requests.get(
                                                url=mediaUrl,
                                                headers=media_info_headers,
                                                cookies=self.base_cookies)
                                            saved.write(
                                                bytes(media_content.content))
                                            tmp = tmp + 1
                                            print(count)
                                            if (tmp > count / 100):
                                                print(tmp)
                                                self.tasklist_.progress(
                                                    row[3], index / count * 164
                                                )  # 比其所在canvas宽度小1,百分之99即撑满整个进度条
                                                tmp = 0
                                            row[4].set(
                                                str(int(index / count * 100)) +
                                                "%")
                                            print("*************downloading" +
                                                  str(index / count * 100) +
                                                  "%************")
                                    else:
                                        for index, play_url in enumerate(
                                                play_list):
                                            tmp_media_url = mediaUrl[:mediaUrl.
                                                                     rfind("/"
                                                                           ) +
                                                                     1] + play_url[
                                                                         1:]
                                            response = requests.get(
                                                url=tmp_media_url,
                                                headers=media_info_headers,
                                                cookies=self.base_cookies)
                                            if response.status_code == 200:
                                                saved.write(
                                                    bytes(response.content))
                                                self.tasklist_.progress(
                                                    row[3], index /
                                                    len(play_list) * 164
                                                )  # 比其所在canvas宽度小1,百分之99即撑满整个进度条
                                                print(
                                                    "*************downloading"
                                                    +
                                                    str(index /
                                                        len(play_list) * 100) +
                                                    "%**************")
                                                row[4].set(
                                                    str(
                                                        int(index /
                                                            len(play_list) *
                                                            100)) + "%")

                            except BaseException as e:
                                row[4].set("失败")
                                row.pop(3)
                                self.tasklist_.append_download_history(row)
                                messagebox.showinfo("错误", message=str(e))
                            else:
                                row[4].set("100%")
                                row.pop(3)
                                self.tasklist_.append_download_history(row)
                                messagebox.showinfo("提示",
                                                    message=file_name +
                                                    "下载完成!")

                        th = threading.Thread(target=down)
                        th.setDaemon(True)
                        th.start()

                        print(self.val_map[k])
        except BaseException as e:
            print(e)
            traceback.print_exc(file=open('error.txt', 'a+'))
            messagebox.showerror("提示", message="下载出错")
            print("下载出错")

    def create_heading(self, ):
        '''重新做一个treeview的头,不然滚动滚动条,看不到原先的头!!!'''
        heading_frame = Frame(self.tk)
        heading_frame.pack(fill=X)

        # 填充用
        # button_frame = Label(heading_frame,bg='gray')
        # button_frame.pack(side=LEFT, expand=False)
        # 全选按钮
        self.all_buttonvar = IntVar()
        self.all_button = Checkbutton(heading_frame,
                                      text='',
                                      variable=self.all_buttonvar,
                                      command=self.select_all)
        self.all_button.pack(side=LEFT)
        self.all_buttonvar.set(0)

        self.columns = ['no', 'name', 'author']
        self.columns_header_name = ['序号', '名称', '作者']
        self.header_label_widths = [40, 260, 100]
        self.colums_header_widths = [46, 292, 115]

        # 重建tree的头
        for i in range(len(self.columns)):
            Label(heading_frame,
                  text=self.columns_header_name[i],
                  width=int(self.header_label_widths[i] * 0.16),
                  anchor='center',
                  relief=GROOVE).pack(side=LEFT)

    def insert_test_tree_data(self):
        rows = []
        for i in range(30):
            rows.append((i + 1, 'B', 'C', 110))
        self.insert_tv(rows)

    def clear_tree_data(self):
        self.init_tree()

    # 初始化表格
    def init_tree(self):
        [self.tv.delete(item) for item in self.tv.get_children()]
        self.tv.update()
        for child in self.button_frame.winfo_children():  # 第一个构件是label,所以忽略
            child.destroy()

        self.canvas.itemconfigure(self.tv_frame, height=300)  # 设定窗口tv_frame的高度
        self.tk.update()
        self.canvas.config(scrollregion=self.canvas.bbox("all"))  # 滚动指定的范围
        self.canvas.config(height=300)

    def create_tv(self):
        # 放置 canvas、滚动条的frame
        canvas_frame = Frame(self.tk, width=500, height=400)
        canvas_frame.pack(fill=X)

        # 只剩Canvas可以放置treeview和按钮,并且跟滚动条配合
        self.canvas = Canvas(canvas_frame,
                             width=400,
                             height=500,
                             scrollregion=(0, 0, 500, 400))
        self.canvas.pack(side=LEFT, fill=BOTH, expand=1)
        # 滚动条
        ysb = Scrollbar(canvas_frame,
                        orient=VERTICAL,
                        command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=ysb.set)
        ysb.pack(side=RIGHT, fill=Y)
        # !!!!=======重点:鼠标滚轮滚动时,改变的页面是canvas 而不是treeview
        self.canvas.bind_all(
            "<MouseWheel>", lambda event: self.canvas.yview_scroll(
                int(-1 * (event.delta / 120)), "units"))

        # 想要滚动条起效,得在canvas创建一个windows(frame)!!
        tv_frame = Frame(self.canvas)
        self.tv_frame = self.canvas.create_window(0,
                                                  0,
                                                  window=tv_frame,
                                                  anchor='nw',
                                                  width=600,
                                                  height=400)  # anchor该窗口在左上方

        # 放置button的frame
        self.button_frame = Frame(tv_frame)
        self.button_frame.pack(side=LEFT, fill=Y)
        Label(self.button_frame, width=3).pack()  # 填充用

        # 创建treeview
        self.tv = Treeview(tv_frame,
                           height=10,
                           columns=self.columns,
                           show='tree')  # height好像设定不了行数,实际由插入的行数决定
        self.tv.column("#0", width=0, stretch=0)
        self.tv.pack(expand=True, side=LEFT, fill=BOTH)
        # 设定每一列的属性
        for i in range(len(self.columns)):
            self.tv.column(self.columns[i],
                           width=self.colums_header_widths[i],
                           anchor='w',
                           stretch=False)

        # 设定treeview格式
        # import tkinter.font as tkFont
        # ft = tkFont.Font(family='Fixdsys', size=20, weight=tkFont.BOLD)
        self.tv.tag_configure('oddrow', font='黑体 8')  # 设定treeview里字体格式font=ft
        self.tv.tag_configure('select', background='SkyBlue',
                              font='Arial 8')  # 当对应的按钮被打勾,那么对于的行背景颜色改变!
        self.rowheight = 27  # 很蛋疼,好像tkinter里只能用整数!
        Style().configure('Treeview', rowheight=self.rowheight)  # 设定每一行的高度

        # 设定选中的每一行字体颜色、背景颜色 (被选中时,没有变化)
        Style().map("Treeview",
                    foreground=[
                        ('focus', 'black'),
                    ],
                    background=[('active', 'white')])
        self.tv.bind('<<TreeviewSelect>>', self.select_tree)  # 绑定tree选中时的回调函数

    def insert_tv(self, rows=None):
        if rows == None:
            rows = []
            for i in range(20):
                item = (i + 1, 'A', "B")
                rows.append(item)

        # 清空tree、checkbutton
        items = self.tv.get_children()
        [self.tv.delete(item) for item in items]
        self.tv.update()
        for child in self.button_frame.winfo_children():  # 第一个构件是label,所以忽略
            child.destroy()

        # 重设tree、button对应关系
        self.orm = {}
        index = 0
        for row in rows:
            tv_item = self.tv.insert('',
                                     index,
                                     value=row[0:3],
                                     tags=('oddrow'))  # item默认状态tags

            import tkinter
            ck_button = tkinter.Checkbutton(self.button_frame,
                                            variable=IntVar())
            ck_button['command'] = lambda item=tv_item: self.select_button(item
                                                                           )
            ck_button.pack()
            # ck_button['fragementId']=row[3]
            self.orm[tv_item] = [ck_button]
            self.val_map[tv_item] = row[3]
            index = index + 1

        # 每次点击插入tree,先设定全选按钮不打勾,接着打勾并且调用其函数
        self.all_buttonvar.set(0)
        self.all_button.invoke()

        # 更新canvas的高度
        height = (len(self.tv.get_children()) +
                  1) * self.rowheight  # treeview实际高度
        self.canvas.itemconfigure(self.tv_frame,
                                  height=height)  # 设定窗口tv_frame的高度
        self.tk.update()
        self.canvas.config(scrollregion=self.canvas.bbox("all"))  # 滚动指定的范围
        self.canvas.config(height=height)

    def select_all(self):
        '''全选按钮的回调函数
           作用:所有多选按钮打勾、tree所有行都改变底色(被选中)'''
        for item, [button] in self.orm.items():
            if self.all_buttonvar.get() == 1:
                button.select()
                self.tv.item(item, tags='select')
            else:
                button.deselect()
                self.tv.item(item, tags='oddrow')

    def select_button(self, item):
        '''多选按钮的回调函数
            作用:1.根据按钮的状态,改变对应item的底色(被选中)
                 2.根据所有按钮被选的情况,修改all_button的状态'''
        button = self.orm[item][0]
        button_value = button.getvar(button['variable'])
        if button_value == '1':
            self.tv.item(item, tags='select')
        else:
            self.tv.item(item, tags='oddrow')
        self.all_button_select()  # 根据所有按钮改变 全选按钮状态

    def select_tree(self, event):
        '''tree绑定的回调函数
           作用:根据所点击的item改变 对应的按钮'''
        select_item = self.tv.focus()
        button = self.orm[select_item][0]
        button.invoke()  # 改变对应按钮的状态,而且调用其函数

    def all_button_select(self):
        '''根据所有按钮改变 全选按钮状态
            循环所有按钮,当有一个按钮没有被打勾时,全选按钮取消打勾'''
        for [button] in self.orm.values():
            button_value = button.getvar(button['variable'])
            if button_value == '0':
                self.all_buttonvar.set(0)
                break
        else:
            self.all_buttonvar.set(1)
class TestcaseSelector:

    def start(self):

        # Create TK window
        self.root = Tk()

        # Create Style object for TK window
        self.root.style = Style()
        # Set default frame size to 800x640
        self.root.geometry('800x640')
        # Set Treeview row height to 40 so there's no overlap
        self.root.style.configure('Treeview',rowheight=40)

        # Set title and window size
        self.root.wm_title("Select Testcases to Run")

        # Create a frame for the treeview
        self.testcase_frame = Frame(self.root)

        # Create scrollbar for treeview
        scrollbar = Scrollbar(self.root)
        scrollbar.pack(side=RIGHT,fill=Y)

        # Create Treeview
        self.treeView = Treeview(self.testcase_frame)
        self.treeView.pack(expand=1,fill=BOTH)

        # Attach scrollbar to Treeview
        self.treeView.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.treeView.yview)

        # Get testcase name dictionary to use for filling out treeview
        testcase_dictionary = get_testcase_name_dictonary()
        self.testcase_data = {}
        self.testcase_run_data = {}

        for key in testcase_dictionary.keys():
            subsection = testcase_dictionary[key]

            self.testcase_data[key] = subsection

            s_p = self.treeView.insert('', END, text=key)

            for test in subsection:
                testcase_name = test._testMethodName
                testcase_name = testcase_name
                self.treeView.insert(s_p, END, text=testcase_name)

                self.testcase_run_data[testcase_name] = test

        self.webData = self.testcase_run_data

        # Create buttons for cancel and run tests
        run_button = Button(self.testcase_frame, text="Run", fg="green",command=self._save_selection,width=25,height=5)
        run_button.pack(side=LEFT,expand=1,fill=BOTH)
        quit_button = Button(self.testcase_frame, text="Cancel", fg="red", command=self.treeView.quit,width=25,height=5)
        quit_button.pack(side=RIGHT,expand=1,fill=BOTH)

        # Pack the rest of the frame and tell it to scale on both x and y axis
        self.testcase_frame.pack(expand=1,fill=BOTH)

    def get_tests_from_selected_names(self,names):
        ret_tests = {}
        for name in names:
            ret_tests[name] = self.webData[name]

        return ret_tests

    def _save_selection(self):
        selected_tests = self.treeView.selection()

        output=[]
        for selection in selected_tests:
            item_text = self.treeView.item(selection,'text')
            if 'test_' in item_text:
                if item_text not in output:
                    output.append(item_text)
                else:
                    pass
            elif 'Tests' in item_text:
                for test in self.testcase_data[item_text]:
                    output.append(test._testMethodName)
                # output = output + self.testSectionData[item_text]

        self.testcases = self.get_tests_from_selected_names(output)
        self.root.quit()

    def get_testcases(self):
        self.start()
        self.root.mainloop()
        self.root.destroy()

        # Try/Except to fail gracefully
        try:
            return self.testcases
        except:
            exit(0)
Exemple #20
0
class Cerberus:
    def __init__(self, master, root):
        self.exportToCSV = False
        self.versionApp, self.key, self.salt = self.initApp()

        self.key = cerberusCryptography.getMasterKey()
        self.cipher_suite = Fernet(self.key)

        self.master = master
        self.master.title('Cerberus')
        self.windowWidth = 1060
        self.windowHeight = 450
        self.screenWidth = self.master.winfo_screenwidth()
        self.screenHeight = self.master.winfo_screenheight()
        self.positionRight = int(self.screenWidth / 2 - self.windowWidth / 2)
        self.positionDown = int(self.screenHeight / 3 - self.windowHeight / 2)
        self.master.geometry("{}x{}+{}+{}".format(self.windowWidth,
                                                  self.windowHeight,
                                                  self.positionRight,
                                                  self.positionDown))

        self.img = PhotoImage(data=icons.getAppIcon())
        self.master.wm_iconphoto(True, self.img)

        self.master.resizable(0, 0)

        self.menubar = Menu(master)
        filemenu = Menu(self.menubar, tearoff=0)

        self.menubar.add_cascade(label="Cerberus", menu=filemenu)
        self.addIcon = PhotoImage(data=icons.getAddIcon())
        filemenu.add_command(label="Εισαγωγή Υπηρεσίας",
                             image=self.addIcon,
                             compound='left',
                             command=self.getAddNewServiceForm)
        self.editIcon = PhotoImage(data=icons.getEditIcon())
        filemenu.add_command(label="Επεξεργασία Υπηρεσίας",
                             image=self.editIcon,
                             compound='left',
                             command=self.getEditServiceForm)
        self.deleteIcon = PhotoImage(data=icons.getDeleteIcon())
        filemenu.add_command(label="Διαγραφή Υπηρεσίας",
                             image=self.deleteIcon,
                             compound='left',
                             command=self.deleteService)
        filemenu.add_separator()
        self.excelIcon = PhotoImage(data=icons.getExcelIcon())
        filemenu.add_command(label="Εξαγωγή σε Excel",
                             image=self.excelIcon,
                             compound='left',
                             command=self.checkPasswordToExportToCSV)
        filemenu.add_separator()
        self.exitIcon = PhotoImage(data=icons.getExitIcon())
        filemenu.add_command(label="Έξοδος",
                             image=self.exitIcon,
                             compound='left',
                             command=self.exitApp)

        settingsMenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Ρυθμίσεις", menu=settingsMenu)
        self.settingsIcon = PhotoImage(data=icons.getSettingsIcon())
        settingsMenu.add_command(label="Επεξεργασία Στοιχείων",
                                 image=self.settingsIcon,
                                 compound='left')
        #command=self.getSettingsForm)

        aboutMenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Βοήθεια", menu=aboutMenu)
        self.infoIcon = PhotoImage(data=icons.getInfoIcon())
        aboutMenu.add_command(label="Περί",
                              image=self.infoIcon,
                              compound='left',
                              command=self.getAboutAppForm)

        self.master.config(menu=self.menubar)

        self.copyIcon = PhotoImage(data=icons.getCopyIcon())
        self.popup = Menu(root, tearoff=0)
        self.popup.add_command(label=" Αντιγραφή Email",
                               image=self.copyIcon,
                               compound='left',
                               command=self.copyEmail)
        self.popup.add_command(label=" Αντιγραφή Username",
                               image=self.copyIcon,
                               compound='left',
                               command=self.copyUsername)
        self.popup.add_command(label=" Αντιγραφή Κωδικού",
                               image=self.copyIcon,
                               compound='left',
                               command=self.copyPasswd)
        self.popup.add_command(label=" Αντιγραφή ID",
                               image=self.copyIcon,
                               compound='left',
                               command=self.copyID)
        self.popup.add_separator()
        self.popup.add_command(label=" Επεξεργασία Υπηρεσίας",
                               image=self.editIcon,
                               compound='left',
                               command=self.getEditServiceForm)
        self.popup.add_command(label=" Διαγραφή Υπηρεσίας",
                               image=self.deleteIcon,
                               compound='left',
                               command=self.deleteService)
        self.popup.add_separator()
        self.popup.add_command(label=" Έξοδος",
                               image=self.exitIcon,
                               compound='left',
                               command=self.exitApp)

        self.frame = Frame(self.master,
                           background="white",
                           borderwidth=1,
                           relief="sunken",
                           highlightthickness=1)
        self.frame.pack(side="top", fill="x", padx=4, pady=4)

        self.search = StringVar()

        self.searchEntry = Entry(self.frame,
                                 textvariable=self.search,
                                 borderwidth=0,
                                 highlightthickness=0,
                                 background="white")
        self.searchEntry.insert(0, 'Αναζήτηση Υπηρεσίας')
        self.searchEntry['fg'] = 'grey'
        self.search.trace(
            "w",
            lambda name, index, mode, sv=self.search: self.searchService())

        self.searchEntry.image = PhotoImage(data=icons.getSearchIcon())
        imageLabel = Label(self.frame, image=self.searchEntry.image)
        imageLabel.pack(side="left")
        imageLabel['bg'] = 'white'

        self.searchEntry.pack(side="left", fill="both", expand=True)

        # Fix BUG with Treeview colors in Python3.7
        def fixed_map(option):
            return [
                elm for elm in style.map('Treeview', query_opt=option)
                if elm[:2] != ('!disabled', '!selected')
            ]

        style = ttk.Style(root)
        style.map('Treeview',
                  foreground=fixed_map('foreground'),
                  background=fixed_map('background'))
        # Fix BUG with Treeview colors in Python3.7

        self.table = Treeview(self.master)
        self.table['show'] = 'headings'
        self.table['columns'] = ('Services', 'email', 'username', 'passwd',
                                 'id', 'category', 'url', 'ID')
        self.table["displaycolumns"] = ('Services', 'email', 'username',
                                        'passwd', 'id', 'category', 'url')

        for col in self.table['columns']:
            self.table.heading(
                col, command=lambda c=col: self.sortby(self.table, c, 0))

        self.table.heading('Services', text='Services')
        self.table.column('Services', anchor='center', width=200)

        self.table.heading('email', text='Email')
        self.table.column('email', anchor='center', width=200)

        self.table.heading('username', text='Username')
        self.table.column('username', anchor='center', width=100)

        self.table.heading('passwd', text='Password')
        self.table.column('passwd', anchor='center', width=100)

        self.table.heading('url', text='URL')
        self.table.column('url', anchor='center', width=120)

        self.table.heading('id', text='ID')
        self.table.column('id', anchor='center', width=100)

        self.table.heading('category', text='Category')
        self.table.column('category', anchor='center', width=100)

        self.table.heading('ID', text='ID')
        self.table.column('ID', anchor='center', width=200)

        self.table.tag_configure('oddrow', background='#e6eef2')
        self.table.tag_configure('evenrow', background='#b3cfdd')
        self.table.tag_configure('focus', background='#c6b6b4')
        self.last_focus = None
        self.last_focus_tag = None
        self.table.focus()
        self.table.pack(fill=BOTH, expand=1)
        self.table.bind("<<TreeviewSelect>>", self.onTableSelect)
        self.table.bind("<ButtonRelease-1>", self.openURLService)
        self.table.bind("<Motion>", self.changePointerOnHover)
        self.table.bind("<Button-3>", self.popupMenu)
        self.searchEntry.bind("<FocusIn>", self.foc_in)
        self.searchEntry.bind("<FocusOut>", self.foc_out)
        self.popup.bind("<FocusOut>", self.popupFocusOut)
        self.master.protocol("WM_DELETE_WINDOW", self.exitApp)

        self.loadTable(self)

        self.master.bind("<Escape>", self.exitApp)

    def popupFocusOut(self, event=None):
        self.popup.unpost()

    def foc_in(self, *args):
        if self.search.get() == 'Αναζήτηση Υπηρεσίας':
            self.searchEntry.delete('0', 'end')
            self.searchEntry['fg'] = 'black'

    def foc_out(self, *args):
        if not self.search.get():
            self.searchEntry.insert(0, 'Αναζήτηση Υπηρεσίας')
            self.searchEntry['fg'] = 'grey'
            self.loadTable(self)

    def changePointerOnHover(self, event):
        _iid = self.table.identify_row(event.y)

        if _iid != self.last_focus:
            if self.last_focus:
                self.table.item(self.last_focus, tags=[self.last_focus_tag])

            self.last_focus_tag = self.table.item(_iid, "tag")
            self.table.item(_iid, tags=['focus'])
            self.last_focus = _iid

        curItem = self.table.item(self.table.identify('item', event.x,
                                                      event.y))
        if curItem['values'] != '':
            col = self.table.identify_column(event.x)
            url = curItem['values'][int(col[-1]) - 1]

            if col[-1] == "7" and url != '---':
                self.master.config(cursor="hand2")
            else:
                self.master.config(cursor="")

    def openURLService(self, event):
        curItem = self.table.item(self.table.focus())
        col = self.table.identify_column(event.x)
        region = self.table.identify("region", event.x, event.y)

        if col[-1] == "7" and region != 'heading':
            url = curItem['values'][int(col[-1]) - 1]
            if url != '---':
                webbrowser.open_new_tab('http://' + str(url))

    def onTableSelect(self, event):
        for item in self.table.selection():
            item_text = self.table.item(item, "values")
            print(item_text[0])

    def getSelectedService(self, event):
        for item in self.table.selection():
            selectedRow = self.table.item(item, "value")
            return selectedRow

    def initApp(self):
        print("Initialize Cerberus App")
        try:
            conn = sqlite3.connect('cerberus.db')
        except sqlite3.Error as e:
            print(e)

        cur = conn.cursor()
        cur.execute(
            "SELECT version, masterToken, salt FROM cerberusParameters")
        row = cur.fetchone()
        cur.close()

        return row

    def copyEmail(self):
        for item in self.table.selection():
            item_text = self.table.item(item, "values")
            self.master.clipboard_clear()
            root.clipboard_append(item_text[1])

    def copyUsername(self):
        for item in self.table.selection():
            item_text = self.table.item(item, "values")
            self.master.clipboard_clear()
            root.clipboard_append(item_text[2])

    def copyPasswd(self):
        for item in self.table.selection():
            item_text = self.table.item(item, "values")
            self.master.clipboard_clear()
            root.clipboard_append(item_text[3])

    def copyID(self):
        for item in self.table.selection():
            item_text = self.table.item(item, "values")
            self.master.clipboard_clear()
            root.clipboard_append(item_text[4])

    def searchService(self):
        try:
            conn = sqlite3.connect('cerberus.db')
        except sqlite3.Error as e:
            print(e)

        cur = conn.cursor()

        if self.search.get() == 'Αναζήτηση Υπηρεσίας':
            pass
        elif self.search.get():
            cur.execute(
                "SELECT id, name, email, username, password, value, category, url FROM service WHERE name LIKE '%"
                + self.search.get() + "%' or name LIKE '%" +
                self.search.get().upper() +
                "%'")  # ('%'+self.search.get()+'%',),'Α')
        elif not self.search.get():
            cur.execute(
                "SELECT id, name, email, username, password, value, category, url FROM service "
            )

        rows = cur.fetchall()
        cur.close()

        for k in self.table.get_children():
            self.table.delete(k)

        i = 1
        for row in rows:
            if (i % 2) == 0:
                tag = "oddrow"
            else:
                tag = "evenrow"

            self.table.insert(
                '',
                'end',
                values=(
                    row[1],
                    self.cipher_suite.decrypt(row[2]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[3]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[4]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[5]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[6]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[7]).decode("utf-8").split(),
                    row[0]),
                tags=tag)
            i = i + 1

    @staticmethod
    def exitApp(event=None):
        root.destroy()

    @staticmethod
    def getAboutAppForm():
        import aboutApp
        aboutApp.aboutApp()

    def getAddNewServiceForm(self):
        self.master.withdraw()
        import addNewServiceForm
        addNewServiceForm.addNewServiceForm(self)

    def getEditServiceForm(self):
        service = self.getSelectedService(self)

        if service is None:
            messagebox.showerror(
                "Μήνυμα Σφάλματος",
                "Παρακαλώ επιλέξτε την Υπηρεσία που θέλετε να Επεξεργαστείτε.")
        else:
            self.master.withdraw()
            import editServiceForm
            editServiceForm.editServiceForm(self, service)

    def getSettingsForm(self):
        import settingsForm
        settingsForm.settingsForm()

    def sortby(self, tree, col, descending):
        data = [(tree.set(child, col), child)
                for child in tree.get_children('')]
        data.sort(reverse=descending)
        for ix, item in enumerate(data):
            if (ix % 2) == 0:
                tag = "evenrow"
            else:
                tag = "oddrow"
            tree.move(item[1], '', ix)
            tree.item(item[1], tags=tag)
        # switch the heading so that it will sort in the opposite direction
        tree.heading(
            col,
            command=lambda x=col: self.sortby(tree, col, int(not descending)))

    @staticmethod
    def loadTable(self):
        try:
            conn = sqlite3.connect('cerberus.db')
        except sqlite3.Error as e:
            print(e)

        cur = conn.cursor()
        cur.execute(
            "SELECT id, name, email, username, password, value, category, url value FROM service"
        )

        rows = cur.fetchall()

        for row in self.table.get_children():
            self.table.delete(row)

        i = 1
        for row in rows:
            if (i % 2) == 0:
                tag = "oddrow"
            else:
                tag = "evenrow"

            self.table.insert(
                '',
                'end',
                values=(
                    row[1],
                    self.cipher_suite.decrypt(row[2]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[3]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[4]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[5]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[6]).decode("utf-8").split(),
                    self.cipher_suite.decrypt(row[7]).decode("utf-8").split(),
                    row[0]),
                tags=tag)

            i = i + 1

        conn.close()

        self.last_focus = None
        self.table.selection()

    def deleteService(self):
        service = self.getSelectedService(self)

        if service is None:
            messagebox.showerror(
                "Μήνυμα Σφάλματος",
                "Παρακαλώ επιλέξτε την Υπηρεσία που θέλετε να Διαγράξετε.")
        else:
            msgBox = messagebox.askquestion(
                'Διαγραφή: {}'.format(service[0]),
                'Είστε σίγουρος ότι θέλετε να διαγράψετε την Υπηρεσία: '
                '{}'
                ' ?'.format(service[0]),
                icon='warning')
            if msgBox == 'yes':
                try:
                    conn = sqlite3.connect('cerberus.db')
                except sqlite3.Error as e:
                    print(e)
                sql = 'DELETE FROM service WHERE id=?'
                cur = conn.cursor()
                cur.execute(sql, (service[-1], ))
                conn.commit()
                conn.close()
                self.loadTable(self)

    def popupMenu(self, event):
        serviceId = self.table.identify_row(event.y)
        if serviceId:
            self.table.selection_set(serviceId)
            try:
                self.popup.tk_popup(event.x_root, event.y_root)
            finally:
                self.popup.grab_release()

    def checkPasswordToExportToCSV(self):
        print("Check Password..")
        import logInForm
        self.master.withdraw()
        logInForm.logIn(self)

    @staticmethod
    def exportToCSV():
        print("Export Services to CSV...")
        try:
            conn = sqlite3.connect('cerberus.db')
        except sqlite3.Error as e:
            print(e)

        key = cerberusCryptography.getMasterKey()
        cipher_suite = Fernet(key)

        cur = conn.cursor()
        cur.execute(
            "SELECT category, name, email, username, password, value, url value FROM service"
        )

        rows = cur.fetchall()

        csvData = [[
            'Κατηγορία',
            'Υπηρεσία',
            'Email',
            'Όνομα Χρήστη',
            'Κωδικός',
            'ID',
            'URL',
        ]]

        for row in rows:
            csvData = csvData + [[
                cipher_suite.decrypt(row[0]).decode("utf-8").split(),
                cipher_suite.decrypt(row[1]).decode("utf-8").split(),
                cipher_suite.decrypt(row[2]).decode("utf-8").split(),
                cipher_suite.decrypt(row[3]).decode("utf-8").split(),
                cipher_suite.decrypt(row[4]).decode("utf-8").split(),
                cipher_suite.decrypt(row[5]).decode("utf-8").split(),
                cipher_suite.decrypt(row[6]).decode("utf-8").split(),
            ]]

        try:
            homeFolder = str(Path.home())
            filePath = filedialog.asksaveasfile(
                initialdir=homeFolder,
                initialfile='cerberus.csv',
                title="Επιλογή Αρχείου",
                filetypes=(("csv files", "*.csv"), ("all files", "*.*")))
            if filePath:
                try:
                    with open(filePath.name, 'w') as csvFile:
                        csvFile = csv.writer(csvFile, delimiter='\t')
                        csvFile.writerows(csvData)
                    messagebox.showinfo(
                        "Μήνυμα Επιτυχίας",
                        "Το αρχείο αποθηκέυτηκε με Επιτυχία στην τοποθεσία {}."
                        .format(filePath.name))
                except Exception as e:
                    messagebox.showerror(
                        "Μήνυμα Σφάλματος",
                        "Δεν ήταν δυνατή η Εξαγωγή του αρχείου.")
        except Exception as e:
            print(e)
            messagebox.showerror("Μήνυμα Σφάλματος",
                                 "Δεν ήταν δυνατή η Εξαγωγή του αρχείου.")
Exemple #21
0
class ManagerWindow:
    """
    主管理界面入口类,直接无参数创建对象即可。
    """

    # 窗口宽高
    WIN_WIDTH = 800
    WIN_HEIGHT = 600

    def __init__(self):
        # 界面根节点
        self.root = Tk()

        # 主窗口标题
        self.root.title(MANAGER_TITLE)

        # 读取config
        self.config_dict = ConfigOperation.get_dir_from_file()

        # 主窗口分辨率
        self.root.geometry("%sx%s+%s+%s" % (
            self.WIN_WIDTH,
            self.WIN_HEIGHT,
            int((self.root.winfo_screenwidth() - self.WIN_WIDTH) / 2),
            int((self.root.winfo_screenheight() - self.WIN_HEIGHT) / 2)
        ))
        self.root.minsize(self.WIN_WIDTH, self.WIN_HEIGHT)

        # 选项卡
        self.tab_main = Notebook(self.root)
        self.tab_main.pack(expand=True, fill=BOTH)

        # 登录选项卡
        self.frame_login = Frame(self.tab_main, bg=BG_COLOR)
        self.frame_login.pack(side=TOP)
        self.tab_main.add(self.frame_login, text=TAB_NAME_LIST["login"]["text"])

        # 管理选项卡
        self.frame_manage = Frame(self.tab_main, bg=BG_COLOR)
        self.tab_main.add(self.frame_manage, text=TAB_NAME_LIST["manage"]["text"])

        # 好友选项卡
        self.frame_friend = Frame(self.tab_main, bg=BG_COLOR)
        self.frame_friend.pack(side=TOP)
        self.tab_main.add(self.frame_friend, text=TAB_NAME_LIST["friends"]["text"])

        # 群选项卡
        self.frame_group = Frame(self.tab_main, bg=BG_COLOR)
        self.frame_group.pack(side=TOP)
        self.tab_main.add(self.frame_group, text=TAB_NAME_LIST["groups"]["text"])

        # 插件选项卡
        self.frame_plugin = Frame(self.tab_main, bg=BG_COLOR)
        self.frame_plugin.pack(side=TOP)
        self.tab_main.add(self.frame_plugin, text=TAB_NAME_LIST["plugins"]["text"])

        # 初始化登录选项卡
        self.__init_login_tab()

        # 初始化好友选项卡
        self.__init_friend_tab()

        # 初始化群选项卡
        self.__init_group_tab()

        # 初始化管理选项卡
        self.__init_manage_tab()

        # 初始化插件选项卡
        self.__init_plugin_tab()

        # 关闭窗口自动释放Session
        self.root.protocol("WM_DELETE_WINDOW", lambda: self.__on_close_root())

        # 刷新显示
        self.__refresh()

        # 运行相关线程
        fetch_message_thread = FetchMessageThread()
        fetch_message_thread.daemon = True
        fetch_message_thread.start()

        # 运行插件初始化方法
        PluginHandler.call_init()

        # 执行自动连接一次
        self.__auto_connect()

        # 显示
        self.root.mainloop()

    def __init_login_tab(self):
        """
        初始化登录选项卡界面

        :return: 无
        """
        # 左边列表的frame
        frame_login_list = Frame(self.frame_login, bg=BG_COLOR)
        frame_login_list.pack(
            side=LEFT,
            expand=True,
            fill=BOTH,
            padx=5,
            pady=5
        )

        # 列表,用于保存连接记录
        self.treeview_login_list = Treeview(
            frame_login_list,
            columns=[
                LOGIN_GUIDE["host"],
                LOGIN_GUIDE["port"],
                LOGIN_GUIDE["authkey"],
                LOGIN_GUIDE["qq"]
            ],
            show="headings",
            selectmode=BROWSE
        )
        self.treeview_login_list.pack(
            expand=True,
            fill=BOTH,
            side=LEFT
        )
        self.treeview_login_list.column(
            LOGIN_GUIDE["host"],
            width=0
        )
        self.treeview_login_list.heading(
            LOGIN_GUIDE["host"],
            text=LOGIN_GUIDE["host"]
        )
        self.treeview_login_list.column(
            LOGIN_GUIDE["port"],
            width=0
        )
        self.treeview_login_list.heading(
            LOGIN_GUIDE["port"],
            text=LOGIN_GUIDE["port"]
        )
        self.treeview_login_list.column(
            LOGIN_GUIDE["authkey"],
            width=40
        )
        self.treeview_login_list.heading(
            LOGIN_GUIDE["authkey"],
            text=LOGIN_GUIDE["authkey"]
        )
        self.treeview_login_list.column(
            LOGIN_GUIDE["qq"],
            width=0
        )
        self.treeview_login_list.heading(
            LOGIN_GUIDE["qq"],
            text=LOGIN_GUIDE["qq"]
        )

        # 设定双击事件
        self.treeview_login_list.bind(
            "<Double-Button-1>",
            lambda event: self.__on_double_click_login_list_content()
        )

        # 设定登录列表的滚动条
        scrollbar_login_list = Scrollbar(frame_login_list)
        scrollbar_login_list.pack(fill="y", expand=True)
        self.treeview_login_list.config(yscrollcommand=scrollbar_login_list.set)
        scrollbar_login_list.config(command=self.treeview_login_list.yview)

        # 设置列表右键菜单
        self.treeview_login_list.bind("<Button-3>", self.__show_login_list_pop_up_menu)

        # 登录界面显示的那一坨
        frame_login_menu = Frame(self.frame_login, bg=BG_COLOR)
        frame_login_menu.pack(side=LEFT, padx=5, pady=5)

        # mirai端地址
        Label(frame_login_menu, text=LOGIN_GUIDE["host"], bg=BG_COLOR).grid(row=0, sticky=E, padx=5, pady=5)
        self.entry_host = Entry(frame_login_menu)
        self.entry_host.grid(row=0, column=1, sticky=W, padx=5, pady=5)

        # mirai端端口号
        Label(frame_login_menu, text=LOGIN_GUIDE["port"], bg=BG_COLOR).grid(row=1, sticky=E, padx=5, pady=5)
        self.entry_port = Entry(frame_login_menu)
        self.entry_port.grid(row=1, column=1, sticky=W, padx=5, pady=5)

        # mirai端http授权码
        Label(frame_login_menu, text=LOGIN_GUIDE["authkey"], bg=BG_COLOR).grid(
            row=2,
            sticky=E,
            padx=5,
            pady=5
        )
        self.entry_authkey = Entry(frame_login_menu, show=PWD_CHAR_CIRCLE)
        self.entry_authkey.grid(row=2, column=1, sticky=W, padx=5, pady=5)

        # 用于激活sessioKey的qq号码
        Label(frame_login_menu, text=LOGIN_GUIDE["qq"], bg=BG_COLOR).grid(
            row=3,
            sticky=E,
            padx=5,
            pady=5
        )
        self.entry_qq = Entry(frame_login_menu)
        self.entry_qq.grid(row=3, column=1, sticky=W, padx=5, pady=5)

        # 自动连接复选框
        self.auto_connect_var = BooleanVar()
        self.checkbutton_auto_connect = Checkbutton(
            frame_login_menu,
            text=AUTO_CONNECT_GUIDE,
            onvalue=True,
            offvalue=False,
            variable=self.auto_connect_var,
            bg=BG_COLOR
        )
        self.checkbutton_auto_connect.grid(row=4, column=0, padx=5, pady=5, columnspan=2)

        # 连接按钮
        self.btn_connect = Button(
            frame_login_menu,
            text=BTN_TEXT_CONN["connect"],
            width=15,
            command=lambda: self.__on_click_connect_event(),
        )
        self.btn_connect.grid(row=5, columnspan=2, padx=5, pady=5)

        # 添加到登录列表按钮
        self.btn_save_login = Button(
            frame_login_menu,
            width=15,
            text=BTN_TEXT_ADD_LOGIN,
            command=lambda: self.__on_click_add_to_login_list()
        )
        self.btn_save_login.grid(row=6, columnspan=2, padx=5, pady=5)

        # 状态栏
        self.label_login_status_bar = Label(
            self.root,
            text=LOGIN_STATUS_BAR_TEXT["notConnect"],
            fg=STATUS_BAR_COLOR["normal"]
        )
        self.label_login_status_bar.pack(side=LEFT)

        # 下面开始从config中将内容填充进文本框中
        self.entry_host.delete(0, END)
        self.entry_host.insert(END, self.config_dict["lastConnection"]["host"])
        self.entry_port.delete(0, END)
        self.entry_port.insert(END, self.config_dict["lastConnection"]["port"])
        self.entry_authkey.delete(0, END)
        self.entry_authkey.insert(END, self.config_dict["lastConnection"]["authkey"])
        self.entry_qq.delete(0, END)
        self.entry_qq.insert(END, self.config_dict["lastConnection"]["qq"])

        # 自动连接复选框内容
        self.auto_connect_var.set(self.config_dict["autoConnect"])

    def __init_friend_tab(self):
        """
        初始化好友选项卡内容

        :return: 无
        """

        # 创建好友列表框架
        frame_friend_list = Frame(self.frame_friend, bg=BG_COLOR)
        frame_friend_list.pack(
            side=LEFT,
            expand=True,
            fill=BOTH,
            padx=5,
            pady=5
        )

        # 创建消息测试发送框架
        frame_friend_send = Frame(self.frame_friend, bg=BG_COLOR)
        frame_friend_send.pack(
            side=LEFT,
            padx=5,
            pady=5
        )

        # 设置列表
        self.treeview_friend_list = Treeview(
            frame_friend_list,
            columns=[
                FRIEND_GUIDE["qq"],
                FRIEND_GUIDE["nickname"],
                FRIEND_GUIDE["remark"]
            ],
            show="headings",
            selectmode=BROWSE
        )
        self.treeview_friend_list.pack(
            expand=True,
            fill=BOTH,
            side=LEFT
        )
        self.treeview_friend_list.column(
            FRIEND_GUIDE["qq"],
            width=0
        )
        self.treeview_friend_list.heading(
            FRIEND_GUIDE["qq"],
            text=FRIEND_GUIDE["qq"]
        )
        self.treeview_friend_list.column(
            FRIEND_GUIDE["nickname"],
            width=0
        )
        self.treeview_friend_list.heading(
            FRIEND_GUIDE["nickname"],
            text=FRIEND_GUIDE["nickname"]
        )
        self.treeview_friend_list.column(
            FRIEND_GUIDE["remark"],
            width=0
        )
        self.treeview_friend_list.heading(
            FRIEND_GUIDE["remark"],
            text=FRIEND_GUIDE["remark"]
        )

        # 设定好友列表的滚动条
        scrollbar_friend_list = Scrollbar(frame_friend_list)
        scrollbar_friend_list.pack(fill="y", expand=True)
        self.treeview_friend_list.config(yscrollcommand=scrollbar_friend_list.set)
        scrollbar_friend_list.config(command=self.treeview_friend_list.yview)

        # 刷新列表按钮
        Button(
            frame_friend_send,
            text=BTN_FRIEND_REFRESH,
            command=lambda: self.__on_click_refresh_friend_list_event()
        ).grid(row=0, padx=5, pady=5)

        # 发送纯文本窗口标题
        Label(frame_friend_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5)

        # 发送纯文本窗口
        self.text_friend_send = Text(frame_friend_send, width=30, height=5)
        self.text_friend_send.grid(row=2, padx=5, pady=5)

        # 发送按钮
        Button(
            frame_friend_send,
            text=BTN_SEND,
            command=lambda: self.__on_click_send_friend_message()
        ).grid(row=3, padx=5, pady=5)

    def __init_group_tab(self):
        """
        初始化群选项卡内容

        :return: 无
        """

        # 创建好友列表框架
        frame_group_list = Frame(self.frame_group, bg=BG_COLOR)
        frame_group_list.pack(
            side=LEFT,
            expand=True,
            fill=BOTH,
            padx=5,
            pady=5
        )

        # 创建消息测试发送框架
        frame_group_send = Frame(self.frame_group, bg=BG_COLOR)
        frame_group_send.pack(
            side=LEFT,
            padx=5,
            pady=5
        )

        # 设置列表
        self.treeview_group_list = Treeview(
            frame_group_list,
            columns=[
                GROUP_GUIDE["group"],
                GROUP_GUIDE["name"],
                GROUP_GUIDE["permission"]
            ],
            show="headings",
            selectmode=BROWSE
        )
        self.treeview_group_list.pack(
            expand=True,
            fill=BOTH,
            side=LEFT
        )
        self.treeview_group_list.column(
            GROUP_GUIDE["group"],
            width=0
        )
        self.treeview_group_list.heading(
            GROUP_GUIDE["group"],
            text=GROUP_GUIDE["group"]
        )
        self.treeview_group_list.column(
            GROUP_GUIDE["name"],
            width=0
        )
        self.treeview_group_list.heading(
            GROUP_GUIDE["name"],
            text=GROUP_GUIDE["name"]
        )
        self.treeview_group_list.column(
            GROUP_GUIDE["permission"],
            width=0
        )
        self.treeview_group_list.heading(
            GROUP_GUIDE["permission"],
            text=GROUP_GUIDE["permission"]
        )

        # 设定群列表的滚动条
        scrollbar_group_list = Scrollbar(frame_group_list)
        scrollbar_group_list.pack(fill="y", expand=True)
        self.treeview_group_list.config(yscrollcommand=scrollbar_group_list.set)
        scrollbar_group_list.config(command=self.treeview_group_list.yview)

        # 刷新列表按钮
        Button(
            frame_group_send,
            text=BTN_GROUP_REFRESH,
            command=lambda: self.__on_click_refresh_group_list_event()
        ).grid(row=0, padx=5, pady=5)

        # 发送纯文本窗口标题
        Label(frame_group_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5)

        # 发送纯文本窗口
        self.text_group_send = Text(frame_group_send, width=30, height=5)
        self.text_group_send.grid(row=2, padx=5, pady=5)

        # 发送按钮
        Button(
            frame_group_send,
            text=BTN_SEND,
            command=lambda: self.__on_click_send_group_message()
        ).grid(row=3, padx=5, pady=5)

    def __init_manage_tab(self):
        """
        初始化管理选项卡

        :return: 无
        """

        f_manage = Frame(self.frame_manage, bg=BG_COLOR)
        f_manage.pack(padx=5, pady=5, expand=True)

        # 指定头指示
        Label(f_manage, text=MANAGE_GUIDE["commandHead"], bg=BG_COLOR).grid(
            row=0,
            column=0,
            padx=5,
            pady=5,
            sticky=E
        )

        # 指令头文本框
        self.entry_command_head = Entry(f_manage)
        self.entry_command_head.grid(row=0, column=1, padx=5, pady=5, sticky=EW)

        # 调试复选框
        self.debug_var = BooleanVar()
        checkbutton_debug = Checkbutton(
            f_manage,
            text=MANAGE_GUIDE["debug"],
            onvalue=True,
            offvalue=False,
            variable=self.debug_var,
            bg=BG_COLOR
        )
        checkbutton_debug.grid(row=1, column=0, columnspan=3, padx=5, pady=5)

        # 启用机器人
        self.enable_var = BooleanVar()
        checkbutton_enable = Checkbutton(
            f_manage,
            text=MANAGE_GUIDE["enable"],
            onvalue=True,
            offvalue=False,
            variable=self.enable_var,
            bg=BG_COLOR
        )
        checkbutton_enable.grid(row=2, column=0, columnspan=3, padx=5, pady=5)

        # 配置保存
        Button(
            f_manage,
            text=MANAGE_GUIDE["saveConfig"],
            command=self.__on_click_save_config
        ).grid(
            row=3,
            column=1,
            padx=5,
            pady=5,
            sticky=EW
        )

        # bot管理qq列表
        self.treeview_op_list = Treeview(
            f_manage,
            columns=[
                MANAGE_GUIDE["botOpQQ"]
            ],
            show="headings",
            selectmode=BROWSE
        )
        self.treeview_op_list.column(MANAGE_GUIDE["botOpQQ"], width=200)
        self.treeview_op_list.heading(MANAGE_GUIDE["botOpQQ"], text=MANAGE_GUIDE["botOpQQ"])
        self.treeview_op_list.grid(
            row=4,
            column=0,
            columnspan=3,
            rowspan=10,
            sticky=EW
        )

        # 列表右键
        self.treeview_op_list.bind("<Button-3>", self.__show_op_list_pop_up_menu)

        # 添加管理标签
        Label(f_manage, text=MANAGE_GUIDE["addOpQQ"], bg=BG_COLOR).grid(row=14, column=0, padx=5, pady=5)

        # 添加管理文本框
        self.entry_add_op = Entry(f_manage)
        self.entry_add_op.grid(row=14, column=1, padx=5, pady=5)

        # 添加添加按钮
        Button(
            f_manage,
            text=MANAGE_GUIDE["btnAddOpQQ"],
            command=lambda: self.__on_click_add_op()
        ).grid(row=14, column=2, padx=5, pady=5, sticky=EW)

    def __init_plugin_tab(self):
        """
        初始化插件选项卡

        :return: 无
        """

        # 指示标签
        Label(self.frame_plugin, text=PLUGIN_LABEL_TEXT, bg=BG_COLOR).pack(side=TOP)

        # 插件列表frame
        frame_plugin_list = Frame(self.frame_plugin, bg=BG_COLOR)
        frame_plugin_list.pack(
            side=TOP,
            expand=True,
            fill=BOTH,
            padx=5,
            pady=5
        )

        # 插件列表
        self.treeview_plugin_list = Treeview(
            frame_plugin_list,
            columns=[
                PLUGIN_GUIDE["pluginName"]
            ],
            show="headings",
            selectmode=BROWSE
        )
        self.treeview_plugin_list.pack(fill=BOTH, expand=True, side=LEFT)
        self.treeview_plugin_list.column(PLUGIN_GUIDE["pluginName"])
        self.treeview_plugin_list.heading(PLUGIN_GUIDE["pluginName"], text=PLUGIN_GUIDE["pluginName"])

        # 设定插件列表滚动条
        scrollbar_plugin_list = Scrollbar(frame_plugin_list)
        scrollbar_plugin_list.pack(fill="y", expand=True)
        self.treeview_plugin_list.config(yscrollcommand=scrollbar_plugin_list.set)
        scrollbar_plugin_list.config(command=self.treeview_plugin_list.yview)

    def __on_click_connect_event(self):
        """
        点击连接按钮事件

        :return: 无
        """

        if not GlobalValues.is_connected:
            # 如果是要连接

            # 存到全局使用变量
            GlobalValues.conn_host = self.entry_host.get()
            GlobalValues.conn_port = self.entry_port.get()
            GlobalValues.conn_authkey = self.entry_authkey.get()
            try:
                # 转换为整型后保存
                GlobalValues.conn_qq = int(self.entry_qq.get())
            except ValueError:
                self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["wrongQQ"], fg=STATUS_BAR_COLOR["failed"])
                return

            # 修改界面上的一些内容为不可修改
            self.__set_login_tools_active(False)

            # 修改按钮内容
            self.btn_connect.config(text=BTN_TEXT_CONN["disconnect"])

            # 修改状态栏内容
            self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["connecting"], fg=STATUS_BAR_COLOR["normal"])

            # 调用连接
            try:
                Conn.new_session_key()
            except (
                requests.exceptions.InvalidURL,
                requests.exceptions.ConnectionError,
            ):
                # 连接错误

                # 错误信息显示到状态栏
                self.label_login_status_bar.config(
                    text=LOGIN_STATUS_BAR_TEXT["connectFailed"],
                    fg=STATUS_BAR_COLOR["failed"]
                )

                # 修改文本框为可修改
                self.__set_login_tools_active(True)
                self.btn_connect.config(text=BTN_TEXT_CONN["connect"])
                return
            except WrongAuthkeyException:
                # 授权码错误

                # 显示到状态栏
                self.label_login_status_bar.config(
                    text=LOGIN_STATUS_BAR_TEXT["wrongAuthkey"],
                    fg=STATUS_BAR_COLOR["failed"]
                )

                # 修改文本框为可修改
                self.__set_login_tools_active(True)
                self.btn_connect.config(text=BTN_TEXT_CONN["connect"])
                return

            except BotNotExistException:
                # bot不存在错误
                self.label_login_status_bar.config(
                    text=LOGIN_STATUS_BAR_TEXT["qqNotExist"],
                    fg=STATUS_BAR_COLOR["failed"]
                )

                # 修改文本框为可修改
                self.__set_login_tools_active(True)
                self.btn_connect.config(text=BTN_TEXT_CONN["connect"])
                return

            self.label_login_status_bar.config(
                text=LOGIN_STATUS_BAR_TEXT["connected"],
                fg=STATUS_BAR_COLOR["passed"]
            )

            # 修改连接状态值
            GlobalValues.is_connected = True

            # 修改上次连接键值对
            ConfigOperation.modify_dict("lastConnection", {
                "host": GlobalValues.conn_host,
                "port": GlobalValues.conn_port,
                "authkey": GlobalValues.conn_authkey,
                "qq": GlobalValues.conn_qq
            })

            # 修改文件中自动连接开关
            ConfigOperation.modify_dict("autoConnect", self.auto_connect_var.get())

        else:
            # 如果要断开连接

            # 修改文本框为可修改
            self.__set_login_tools_active(True)

            # 修改按钮名称
            self.btn_connect.config(text=BTN_TEXT_CONN["connect"])

            # 修改属性值
            self.label_login_status_bar.config(
                text=LOGIN_STATUS_BAR_TEXT["disconnectSuccess"],
                fg=STATUS_BAR_COLOR["normal"]
            )

            # 释放session
            Conn.release_session_key()

            # 修改连接状态值
            GlobalValues.is_connected = False

    def __set_login_tools_active(self, active: bool):
        """
        修改界面上的一些内容为不可修改

        :param active: bool,如果为False则禁用掉文本框,否则启用
        :return: 无
        """
        if active:
            self.entry_host.config(state=ACTIVE)
            self.entry_port.config(state=ACTIVE)
            self.entry_authkey.config(state=ACTIVE)
            self.entry_qq.config(state=ACTIVE)
            self.checkbutton_auto_connect.config(state=ACTIVE)
        else:
            self.entry_host.config(state=DISABLED)
            self.entry_port.config(state=DISABLED)
            self.entry_authkey.config(state=DISABLED)
            self.entry_qq.config(state=DISABLED)
            self.checkbutton_auto_connect.config(state=DISABLED)

    def __on_close_root(self):
        """
        关闭窗口的事件
        :return: 无
        """

        # 如果正在连接则释放连接
        if GlobalValues.is_connected:
            Conn.release_session_key()

        # 杀掉root
        self.root.destroy()

    def __refresh(self):
        """
        用于刷新界面,在必要时调用

        :return: 无
        """

        def refresh_login_list():
            """
            刷新登录列表

            :return: 无
            """

            # 删除目前表中的所有内容
            self.treeview_login_list.delete(*self.treeview_login_list.get_children())

            # 把登录列表内容添加到显示中
            for one_record in LoginListOperation.get_list_from_file():
                self.treeview_login_list.insert("", index=END, values=(
                    one_record["host"],
                    one_record["port"],
                    one_record["authkey"],
                    one_record["qq"]
                ))

        def refresh_op_list():
            """
            刷新bot管理员qq列表

            :return: 无
            """

            # 删除目前表中的所有内容
            self.treeview_op_list.delete(*self.treeview_op_list.get_children())

            # 把内容添加到显示中
            for one_record in OpListOperation.get_list():
                self.treeview_op_list.insert("", index=END, values=(
                    one_record
                ))

        def refresh_config():
            """
            刷新配置

            :return: 无
            """
            # 重新获取config
            self.config_dict = ConfigOperation.get_dir_from_file()

            # 将文件中的内容显示到界面中
            self.entry_command_head.delete(0, END)
            self.entry_command_head.insert(END, self.config_dict["commandHead"])

            # 设置复选框默认勾选
            self.debug_var.set(self.config_dict["debug"])
            self.enable_var.set(self.config_dict["enable"])

            # 将内容设置到全局变量
            GlobalValues.command_head = self.config_dict["commandHead"]
            GlobalValues.debug_var = self.debug_var
            GlobalValues.enable_var = self.enable_var

        def refresh_plugin_list():
            # 获取插件名称
            plugin_names = PluginHandler.get_plugin_name_list()

            # 显示
            self.treeview_plugin_list.delete(*self.treeview_plugin_list.get_children())
            for name in plugin_names:
                self.treeview_plugin_list.insert("", index=END, values=(
                    name
                ))

        # 调用刷新登录列表
        refresh_login_list()

        # 调用刷新op列表
        refresh_op_list()

        # 刷新config显示
        refresh_config()

        # 刷新插件列表显示
        refresh_plugin_list()

    def __on_click_add_to_login_list(self):
        """
        将填写内容添加到列表中
        :return: 无
        """

        # 非空检测
        if [
            self.entry_host.get(),
            self.entry_port.get(),
            self.entry_authkey.get(),
            self.entry_qq.get()
        ] == [""] * 4:
            return

        # 调用添加登录项方法
        LoginListOperation.add_to_list(
            self.entry_host.get(),
            self.entry_port.get(),
            self.entry_authkey.get(),
            self.entry_qq.get()
        )

        # 刷新显示
        self.__refresh()

    def __on_double_click_login_list_content(self):
        """
        双击登录列表项目时,自动填充到右侧

        :return: 无
        """

        # 获取item的值
        item_list = self.treeview_login_list.item(self.treeview_login_list.focus(), "values")

        # 获取需要的项目并设置
        self.entry_host.delete(0, END)
        self.entry_host.insert(END, item_list[0])
        self.entry_port.delete(0, END)
        self.entry_port.insert(END, item_list[1])
        self.entry_authkey.delete(0, END)
        self.entry_authkey.insert(END, item_list[2])
        self.entry_qq.delete(0, END)
        self.entry_qq.insert(END, item_list[3])

    def __show_login_list_pop_up_menu(self, event):
        """
        显示右键菜单

        :param event: 事件
        :return: 无
        """
        def on_delete_event(item_id):
            """
            删除选项的事件

            :return: 无
            """

            # 删除该项
            LoginListOperation.remove_from_list(*self.treeview_login_list.item(item_id, "values"))
            self.treeview_login_list.delete(item_id)
            self.__refresh()

        # 获取选择对象
        iid = self.treeview_login_list.identify_row(event.y)

        # 如果有选择,则弹出右键菜单
        if iid:
            self.treeview_login_list.selection_set(iid)
            menu_pop_up = Menu(self.treeview_login_list, tearoff=False)
            menu_pop_up.add_command(
                label=POP_UP_MENU_DELETE_STR,
                command=lambda: on_delete_event(iid)
            )
            menu_pop_up.post(event.x_root, event.y_root)

    def __on_click_refresh_friend_list_event(self):
        """
        点击刷新好友列表事件

        :return: 无
        """
        try:
            # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框
            friend_list = Conn.get_friend_list()
        except:
            messagebox.showerror(message=REFRESH_ERROR_MSG)
            return

        # 删除列表内容
        self.treeview_friend_list.delete(*self.treeview_friend_list.get_children())

        # 解析friend_list
        for friend_block in friend_list:
            self.treeview_friend_list.insert("", index=END, values=(
                friend_block["id"],
                friend_block["nickname"],
                friend_block["remark"]
            ))

    def __on_click_refresh_group_list_event(self):
        """
        点击刷新群列表事件

        :return: 无
        """
        try:
            # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框
            group_list = Conn.get_group_list()
        except:
            messagebox.showerror(message=REFRESH_ERROR_MSG)
            return

        # 删除列表内容
        self.treeview_group_list.delete(*self.treeview_group_list.get_children())

        # 解析group_list
        for group_block in group_list:
            self.treeview_group_list.insert("", index=END, values=(
                group_block["id"],
                group_block["name"],
                group_block["permission"]
            ))

    def __on_click_send_friend_message(self):
        """
        点击发送消息给好友按钮

        :return: 无
        """

        # 获取到选中好友的值列表
        value_list = self.treeview_friend_list.item(self.treeview_friend_list.focus(), "values")

        try:
            # 获取qq并发送消息
            qq = value_list[0]
            message_chain = MessageChain()
            text = self.text_friend_send.get(1.0, END)
            if text == "\n":
                return
            message_chain.add_plain_text(text)
            Conn.send_friend_message(qq, message_chain)
            self.text_friend_send.delete(1.0, END)
        except:
            messagebox.showerror(message=SEND_ERROR_MSG)
            return

    def __on_click_send_group_message(self):
        """
        点击发送消息给群按钮

        :return: 无
        """

        # 获取到选中群的值列表
        value_list = self.treeview_group_list.item(self.treeview_group_list.focus(), "values")

        try:
            # 获取qq并发送消息
            qq = value_list[0]
            message_chain = MessageChain()
            text = self.text_group_send.get(1.0, END)
            if text == "\n":
                return
            message_chain.add_plain_text(text)
            Conn.send_group_message(qq, message_chain)
            self.text_group_send.delete(1.0, END)
        except:
            messagebox.showerror(message=SEND_ERROR_MSG)
            return



    def __on_click_add_op(self):
        """
        点击添加op按钮事件

        :return: 无
        """

        content = self.entry_add_op.get()

        # 如果添加op的文本框中没有东西,则不添加
        if content == "":
            return

        # 如果转换数字出错则不添加
        try:
            op_qq = int(content)
        except ValueError:
            return

        # 添加到op列表中
        OpListOperation.add_to_list(op_qq)

        # 刷新显示
        self.__refresh()

    def __show_op_list_pop_up_menu(self, event):
        """
        op列表右键菜单

        :return: 无
        """

        def on_delete_event():
            """
            删除选项的事件

            :return: 无
            """

            # 删除该项
            # 注意此处的强转,由于能够保证显示出来的内容一定只含有数字,故可以直接转换
            OpListOperation.remove_from_list(int(self.treeview_op_list.item(op_qq, "values")[0]))
            self.treeview_op_list.delete(op_qq)
            self.__refresh()

        # 获取选择对象
        op_qq = self.treeview_op_list.identify_row(event.y)

        # 如果有选择,则弹出右键菜单
        if op_qq:
            menu_pop_up = Menu(self.treeview_op_list, tearoff=False)
            self.treeview_op_list.selection_set(op_qq)
            menu_pop_up.add_command(
                label=POP_UP_MENU_DELETE_STR,
                command=lambda: on_delete_event()
            )
            menu_pop_up.post(event.x_root, event.y_root)

    def __on_click_save_config(self):
        """
        点击保存配置事件

        :return: 无
        """

        content = self.entry_command_head.get()

        # 如果为空,则不存入,但是刷新
        # 这样是为了保证点击后会显示原来的设置
        if content == "":
            self.__refresh()
            return

        ConfigOperation.modify_dict("commandHead", content)
        ConfigOperation.modify_dict("debug", self.debug_var.get())
        ConfigOperation.modify_dict("enable", self.enable_var.get())

        # 刷新
        self.__refresh()

        # 弹出对话框
        messagebox.showinfo(message=MANAGE_GUIDE["successSaveCommandHeadMsg"])

    def __auto_connect(self):
        if self.config_dict["autoConnect"]:
            self.__on_click_connect_event()
class window:
    def __init__(self):

        self.win = Tk()
        height = self.win.winfo_screenheight()
        width = self.win.winfo_screenwidth()
        x = (width - 700) // 2
        y = (height - 700) // 2
        self.win.geometry('700x700+{}+{}'.format(str(x), str(y)))
        self.win.resizable(width=False, height=False)

        self.frame = Frame(self.win, height=700, width=700, bg="#a3c2c2")
        self.frame.place(x=0, y=0)

        self.frame1 = Frame(self.frame, bg="#e0ebeb", height=700, width=2)
        self.frame1.place(x=30, y=0)
        self.frame1 = Frame(self.frame, bg="#75a3a3", height=700, width=4)
        self.frame1.place(x=20, y=0)
        self.frame1 = Frame(self.frame, bg="#476b6b", height=700, width=6)
        self.frame1.place(x=10, y=0)

        self.frame1 = Frame(self.frame, bg="#e0ebeb", height=2, width=700)
        self.frame1.place(x=0, y=30)
        self.frame1 = Frame(self.frame, bg="#75a3a3", height=4, width=700)
        self.frame1.place(x=0, y=20)
        self.frame1 = Frame(self.frame, bg="#476b6b", height=6, width=700)
        self.frame1.place(x=0, y=10)

        self.table = Treeview(self.frame,
                              column=("#0", "#1", "#2", "#3", "#4", "#5", "#6",
                                      "#7"))
        style = ttk.Style()
        style.theme_use("alt")
        ttk.Style().configure("Treeview.Heading", font=('', 14, "bold"))

        self.table.column("#0", width=80)
        self.table.column("#1", width=80)
        self.table.column("#2", width=80)
        self.table.column("#3", width=80)
        self.table.column("#4", width=80)
        self.table.column("#5", width=80)
        self.table.column("#6", width=80)
        self.table.column("#7", width=80)

        self.table.heading("#0", text="Sr.")
        self.table.heading("#1", text="Name")
        self.table.heading("#2", text="Gender")
        self.table.heading("#3", text="Email")
        self.table.heading("#4", text="Contact")
        self.table.heading("#5", text="Address")
        self.table.heading("#6", text="Edit")
        self.table.heading("#7", text="Delete")

        x = database_queries.database()
        res = x.view_receptionist()
        #print(res)
        for i in res:
            self.table.insert('',
                              'end',
                              text=i[0],
                              value=(i[1], i[2], i[3], i[5], i[6], "edit",
                                     "delete"))

        self.table.bind("<Double Button-1>", self.trigger)
        self.table.place(x=40, y=50, width=640)

        self.win.mainloop()

    def trigger(self, e):
        row = self.table.focus()
        t = (self.table.item(row))
        col = self.table.identify_column(e.x)
        if col == "#6":
            y = edit_receptionist.window(t["text"])

            print("edit")
        elif (col == "#7"):
            o = database_queries.database()
            o.delete(t["text"])
Exemple #23
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))
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 #25
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')
Exemple #26
0
class MainGUI:
    def __init__(self, master):
        self.parent = master
        # Set frame for the whole thing
        self.parent.title("LMS")
        self.frame = Frame(self.parent, width=1500, height=750)
        self.frame.grid(row=0, column=0)
        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_columnconfigure(0, weight=1)
        self.frame.grid_propagate(False)

        # Parameter Initialization
        self.search_string = None
        self.data = None
        self.borrowerId = None
        self.bookForCheckOutIsbn = None

        # Frame for the welcome message and header
        self.HeaderFrame = Frame(self.frame)
        self.HeaderFrame.grid(row=0, column=0, sticky=N)
        self.HeaderFrame.grid_rowconfigure(0, weight=1)
        self.HeaderFrame.grid_columnconfigure(0, weight=1)

        # # Label for the welcome message
        self.HeaderLabel = Label(self.HeaderFrame,
                                 text='What Book Do You Want?')
        self.HeaderLabel.grid(row=0, column=0)
        self.HeaderLabel.grid_rowconfigure(0, weight=10)
        self.HeaderLabel.grid_columnconfigure(0, weight=10)

        #Label for the searchbox
        self.SearchLabel = Label(self.HeaderFrame, text='')
        self.SearchLabel.grid(row=1, column=0)
        self.SearchLabel.grid_rowconfigure(1, weight=10)
        self.SearchLabel.grid_columnconfigure(0, weight=10)

        # Search Frame
        self.SearchFrame = Frame(self.frame)
        self.SearchFrame.grid(row=1, column=0, sticky=N)
        self.SearchFrame.grid_rowconfigure(1, weight=1)
        # self.SearchFrame.grid_columnconfigure(0, weight=1)
        self.SearchLabel = Label(self.SearchFrame, text='Search')
        self.SearchLabel.grid(row=0, column=0)
        self.SearchLabel.grid_rowconfigure(0, weight=1)
        # self.SearchLabel.grid_columnconfigure(0, weight=1)
        self.SearchTextBox = Entry(self.SearchFrame,
                                   text='Enter search string here...',
                                   width=70)
        self.SearchTextBox.grid(row=1, column=0)
        self.SearchTextBox.grid_rowconfigure(1, weight=1)
        self.SearchButton = Button(self.SearchFrame,
                                   text='Search',
                                   command=self.search)
        self.SearchButton.grid(row=2, column=0)
        self.SearchButton.grid_rowconfigure(2, weight=1)

        # Search Result Frame
        self.ActiveArea = Frame(self.frame)
        self.ActiveArea.grid(row=2, column=0, sticky=N)
        self.ActiveArea.grid_rowconfigure(2, weight=1)
        self.ResultTreeview = Treeview(
            self.ActiveArea,
            columns=["ISBN", "Book Title", "Author(s)", "Availability"])
        self.ResultTreeview.grid(row=1, column=1)
        self.ResultTreeview.grid_rowconfigure(0, weight=1)
        self.ResultTreeview.heading('#0', text="ISBN")
        self.ResultTreeview.heading('#1', text="Book Title")
        self.ResultTreeview.heading('#2', text="Author(s)")
        self.ResultTreeview.heading('#3', text="Availability")
        self.ResultTreeview.bind('<ButtonRelease-1>',
                                 self.selectBookForCheckout)

        # Interaction Frame
        self.MajorFunctions = Frame(self.frame)
        self.MajorFunctions.grid(row=3, column=0, sticky=N)
        self.MajorFunctions.grid_rowconfigure(3, weight=1)
        self.checkOutBtn = Button(self.MajorFunctions,
                                  text="Check Out Book",
                                  command=self.check_out)
        self.checkOutBtn.grid(row=0, column=0, padx=10, pady=10)
        self.checkOutBtn.grid_rowconfigure(0, weight=1)
        self.checkOutBtn.grid_columnconfigure(0, weight=1)
        self.checkInBtn = Button(self.MajorFunctions,
                                 text="Check In Book",
                                 command=self.check_in)
        self.checkInBtn.grid(row=0, column=1, padx=10, pady=10)
        self.checkOutBtn.grid_rowconfigure(0, weight=1)
        self.checkOutBtn.grid_columnconfigure(1, weight=1)
        self.updateFinesBtn = Button(self.MajorFunctions,
                                     text="Updates Fines",
                                     command=self.update_fines)
        self.updateFinesBtn.grid(row=1, column=0, padx=10, pady=10)
        self.payFinesBtn = Button(self.MajorFunctions,
                                  text="Pay Fines",
                                  command=self.pay_fines)
        self.payFinesBtn.grid(row=1, column=1, padx=10, pady=10)
        self.changeDayBtn = Button(self.MajorFunctions,
                                   text="Change Day",
                                   command=self.change_day)
        self.changeDayBtn.grid(row=1, column=2, padx=10, pady=10)
        self.addBorrowerBtn = Button(self.MajorFunctions,
                                     text="Add New Borrower",
                                     command=self.add_borrower)
        self.addBorrowerBtn.grid(row=0, column=2, padx=10, pady=10)

    def change_day(self):
        global todays_date
        todays_date = todays_date + timedelta(days=1)
        print(todays_date)

    def search(self):
        self.search_string = self.SearchTextBox.get()
        cursor = cnx.cursor()
        cursor.execute(
            "select BOOK.isbn, BOOK.title, AUTHORS.fullname from BOOK join BOOK_AUTHORS on "
            "BOOK.isbn = BOOK_AUTHORS.isbn join AUTHORS on BOOK_AUTHORS.author_id = AUTHORS.author_id "
            "where BOOK.title like concat('%', '" + self.search_string +
            "', '%') or "
            "AUTHORS.fullname like concat('%', '" + self.search_string +
            "', '%') or "
            "BOOK.isbn like concat('%', '" + self.search_string + "', '%')")

        self.data = cursor.fetchall()
        self.view_data()

    def view_data(self):
        """
        View data on Treeview method.
        """
        self.ResultTreeview.delete(*self.ResultTreeview.get_children())
        for elem in self.data:
            cursor = cnx.cursor()
            cursor.execute(
                "SELECT EXISTS(SELECT BOOK_LOANS.isbn from BOOK_LOANS where BOOK_LOANS.isbn = '"
                + str(elem[0]) + "')")
            result = cursor.fetchall()
            if result == [(0, )]:
                availability = "Available"
            else:
                cursor = cnx.cursor()
                cursor.execute(
                    "SELECT BOOK_LOANS.Date_in from BOOK_LOANS where BOOK_LOANS.isbn = '"
                    + str(elem[0]) + "'")
                result = cursor.fetchall()
                if result[-1][0] is None:
                    availability = "Not Available"
                else:
                    availability = "Available"
            self.ResultTreeview.insert('',
                                       'end',
                                       text=str(elem[0]),
                                       values=(elem[1], elem[2], availability))

    def selectBookForCheckout(self, a):
        curItem = self.ResultTreeview.focus()
        self.bookForCheckOutIsbn = self.ResultTreeview.item(curItem)['text']

    def check_out(self):
        if self.bookForCheckOutIsbn is None:
            messagebox.showinfo("Attention!", "Select Book First!")
            return None
        self.borrowerId = simpledialog.askstring("Check Out Book",
                                                 "Enter Borrower ID")
        cursor = cnx.cursor()
        cursor.execute(
            "SELECT EXISTS(SELECT Card_no from BORROWERS WHERE BORROWERS.Card_no = '"
            + str(self.borrowerId) + "')")
        result = cursor.fetchall()

        if result == [(0, )]:
            messagebox.showinfo("Error", "Borrower not in Database!")
            return None
        else:
            count = 0
            cursor = cnx.cursor()
            cursor.execute(
                "SELECT BOOK_LOANS.Date_in from BOOK_LOANS WHERE BOOK_LOANS.Card_no = '"
                + str(self.borrowerId) + "'")
            result = cursor.fetchall()
            for elem in result:
                if elem[0] is None:
                    count += 1
            if count >= 3:
                messagebox.showinfo("Not Allowed!",
                                    "Borrower has loaned 3 books already!")
                return None
            else:
                cursor = cnx.cursor()
                cursor.execute("SET FOREIGN_KEY_CHECKS=0")
                cursor.execute(
                    "INSERT INTO BOOK_LOANS (ISBN, Card_no, Date_out, Due_date) VALUES ('"
                    + self.bookForCheckOutIsbn + "', '" + self.borrowerId +
                    "', '" + str(todays_date) + "', '" +
                    str(todays_date + timedelta(days=14)) + "')")
                cursor.execute("SET FOREIGN_KEY_CHECKS=1")
                cnx.commit()
                cursor = cnx.cursor()
                cursor.execute("SELECT MAX(Loan_Id) FROM BOOK_LOANS")
                result = cursor.fetchall()
                loan_id = result[0][0]
                cursor.execute(
                    "INSERT INTO FINES (Loan_Id, fine_amt, paid) VALUES ('" +
                    str(loan_id) + "', '0.00', '0')")
                cnx.commit()
                messagebox.showinfo("Done", "Book Loaned Out!")

    def check_in(self):
        self.checkInWindow = Toplevel(self.parent)
        self.checkInWindow.title("Check In Here")
        self.app = CheckIn(self.checkInWindow)

    def update_fines(self):
        cursor = cnx.cursor()
        cursor.execute(
            "SELECT BOOK_LOANS.Loan_Id, BOOK_LOANS.Date_in, BOOK_LOANS.Due_date FROM BOOK_LOANS"
        )
        result = cursor.fetchall()
        for record in result:
            date_in = record[1]
            date_due = record[2]
            if date_in is None:
                date_in = todays_date
            diff = date_in.date() - date_due.date()
            if diff.days > 0:
                fine = int(diff.days) * 0.25
            else:
                fine = 0
            cursor = cnx.cursor()
            cursor.execute("UPDATE FINES SET FINES.fine_amt = '" + str(fine) +
                           "' WHERE FINES.Loan_Id = '" + str(record[0]) + "'")
            cnx.commit()
        messagebox.showinfo("Info", "Generated Fines")

    def pay_fines(self):
        self.newPayFinesWindow = Toplevel(self.parent)
        self.newPayFinesWindow.title("Fine!!")
        self.app1 = PayFines(self.newPayFinesWindow)

    def add_borrower(self):
        self.newBorrowerWindow = Toplevel(self.parent)
        self.newBorrowerWindow.title("Borrowing Person New")
        self.newapp = BorrowingPerson(self.newBorrowerWindow)
class Program(Frame):
    """Class to represent a main window"""
    def __init__(self, parent):
        # Some top-level settings.
        Frame.__init__(self, parent)
        self.content = Frame(self, padding=(5, 5, 5, 20))
        self.parent = parent
        self.parent.title('Restaurant manager')
        self.parent.minsize(DEFAULT_MINSIZE_WIDTH, DEFAULT_MINSIZE_HEIGHT)
        self.parent.protocol('WM_DELETE_WINDOW', self.onQuit)

        # Some variables.
        self.track_weight = IntVar()
        self.custom_entries = []
        self.jsonReader = JsonReader(json_path)
        self.frames = []
        self.entries = {}
        self.dishes = self.jsonReader.getDishesDict()
        self.dishes_names = self.jsonReader.getDishesNames()
        self.parent.iconphoto(
            True, PhotoImage(file=os.path.join(sys.path[0], logo_path)))

        # Initialize all widgets.
        self.initWidgets()

    def initWidgets(self):
        """
        Initialize all widgets in window here.
        Entries are saved in [self.entries] list.
        ----------------------------------------------------------
        5 frames are initialized and saved into [self.frames] list here:
        1) [About frame] - Frame to contain all non-food entries.
        2) [Separator frame] - Frame to contain a simple separator.
        3) [New order frame] - Frame to contain entries for adding orders to the main table.
        4) [Orders table frame] - Frame to contain table with list of added orders.
        5) [Save report frame] - Frame to contain buttons, which save a report.
        ----------------------------------------------------------
        """
        # Create 5 frames here.
        for i in range(5):
            self.frames.append(Frame(self.content))
        # Set the weights of cols and rows in the grid.
        self.configureGrid()
        # Center a window.
        self.centerWindow()

        # Place 4 frames to the window.
        self.frames[0].grid(column=0, row=0, sticky=N + E + W, padx=5, pady=3)
        self.frames[1].grid(column=0,
                            row=1,
                            sticky=N + S + E + W,
                            padx=5,
                            pady=3)
        self.frames[2].grid(column=0,
                            row=2,
                            sticky=N + S + E + W,
                            padx=5,
                            pady=3)
        self.frames[3].grid(column=0,
                            row=3,
                            sticky=N + S + E + W,
                            padx=5,
                            pady=10)
        self.frames[4].grid(column=0, row=4, sticky=S + E + W, padx=5, pady=3)

        # About frame widgets.
        Label(self.frames[0], text='Заказчик').grid(row=0,
                                                    column=0,
                                                    sticky=E,
                                                    pady=5)
        Label(self.frames[0], text='Менеджер').grid(row=0,
                                                    column=2,
                                                    sticky=E,
                                                    pady=5)
        Label(self.frames[0],
              text='Вид мероприятия',
              justify=RIGHT,
              wraplength=90).grid(row=0, column=4, sticky=E, pady=5)
        Label(self.frames[0], text='Дата').grid(row=1,
                                                column=0,
                                                sticky=E,
                                                pady=5)
        Label(self.frames[0], text='Время').grid(row=1,
                                                 column=2,
                                                 sticky=E,
                                                 pady=5)
        Label(self.frames[0],
              text='Место проведения',
              justify=RIGHT,
              wraplength=90).grid(row=1, column=4, sticky=E, pady=5)
        Label(self.frames[0],
              text='Количество персон',
              justify=RIGHT,
              wraplength=90).grid(row=1, column=6, sticky=E, pady=5)

        self.entries['client'] = Entry(self.frames[0])
        self.entries['manager'] = Entry(self.frames[0])
        self.entries['type'] = Entry(self.frames[0], width=10)
        self.entries['date'] = Entry(self.frames[0])
        self.entries['time'] = Entry(self.frames[0])
        self.entries['location'] = Entry(self.frames[0], width=10)
        self.entries['persons'] = Entry(self.frames[0], width=10)

        self.entries['client'].focus_set()
        today = date.today().isoformat().split('-')[::-1]
        self.entries['date'].insert(0, '.'.join(today))

        self.entries['client'].grid(row=0,
                                    column=1,
                                    sticky=E + W,
                                    padx=(3, 13),
                                    pady=5)
        self.entries['manager'].grid(row=0,
                                     column=3,
                                     sticky=E + W,
                                     padx=(3, 13),
                                     pady=5)
        self.entries['type'].grid(row=0,
                                  column=5,
                                  columnspan=3,
                                  sticky=E + W,
                                  padx=(3, 13),
                                  pady=5)
        self.entries['date'].grid(row=1,
                                  column=1,
                                  sticky=E + W,
                                  padx=(3, 13),
                                  pady=5)
        self.entries['time'].grid(row=1,
                                  column=3,
                                  sticky=E + W,
                                  padx=(3, 13),
                                  pady=5)
        self.entries['location'].grid(row=1,
                                      column=5,
                                      sticky=E + W,
                                      padx=(3, 13),
                                      pady=5)
        self.entries['persons'].grid(row=1,
                                     column=7,
                                     sticky=E + W,
                                     padx=(3, 13),
                                     pady=5)

        # Add a separator between [about] and [new order] frames
        sep1 = Frame(self.frames[1], height=2, borderwidth=1, relief='sunken')
        sep1.pack(fill=X, padx=1, pady=10)

        # New Order frame widgets.
        Label(self.frames[2], text='Название', anchor=E).grid(row=0,
                                                              column=0,
                                                              sticky=E)
        Label(self.frames[2], text='Комментарий', anchor=E).grid(row=1,
                                                                 column=0,
                                                                 sticky=E)
        Label(self.frames[2], text='Количество', anchor=E).grid(row=2,
                                                                column=0,
                                                                sticky=E)
        self.sum_lbl = Label(self.frames[2],
                             text='Текущая сумма заказа:\n 0 грн',
                             anchor=E,
                             justify=RIGHT)

        self.entries['name'] = AutocompleteEntry(self.frames[2])
        self.entries['comment'] = Entry(self.frames[2])
        self.entries['amount'] = Entry(self.frames[2])
        addOrder_btn = Button(self.frames[2], text='Добавить блюдо в отчет')

        self.entries['name'].set_completion_list(self.dishes_names)
        self.entries['amount'].insert(0, '1')
        addOrder_btn['command'] = lambda: self.addDish()

        self.entries['name'].grid(row=0,
                                  column=1,
                                  columnspan=5,
                                  sticky=W + E,
                                  pady=3,
                                  padx=(3, 15))
        self.entries['comment'].grid(row=1,
                                     column=1,
                                     columnspan=5,
                                     sticky=W + E,
                                     pady=3,
                                     padx=(3, 15))
        self.entries['amount'].grid(row=2,
                                    column=1,
                                    columnspan=2,
                                    sticky=W + E,
                                    pady=3,
                                    padx=(3, 15))
        addOrder_btn.grid(row=3, column=1, sticky=W, pady=3, padx=3)
        self.sum_lbl.grid(row=4, column=5, pady=0, padx=(190, 0))

        customEntry_btn = Button(self.frames[2],
                                 text='Добавить собственную строку в отчет')
        customEntry_btn['command'] = lambda: self.addCustomEntry()
        customEntry_btn.grid(row=4, column=1, sticky=W, pady=3, padx=3)

        # Orders Table frame widgets.
        self.orders_view = Treeview(self.frames[3])
        self.orders_view['columns'] = ('Weight', 'Amount', 'Comment', 'Price',
                                       'Sum')
        self.orders_view.bind('<Delete>',
                              lambda e: self.deleteEntry(e, self.orders_view))

        self.orders_view.heading('#0', text='Название')
        self.orders_view.column('#0', anchor='w', minwidth=307, width=307)
        self.orders_view.heading('Weight', text='Выход')
        self.orders_view.column('Weight',
                                anchor=CENTER,
                                minwidth=100,
                                width=100,
                                stretch=NO)
        self.orders_view.heading('Amount', text='Количество')
        self.orders_view.column('Amount',
                                anchor=CENTER,
                                minwidth=100,
                                width=100,
                                stretch=NO)
        self.orders_view.heading('Comment', text='Комментарий')
        self.orders_view.column('Comment', anchor='w', minwidth=130, width=130)
        self.orders_view.heading('Price', text='Цена, грн')
        self.orders_view.column('Price',
                                anchor=CENTER,
                                minwidth=110,
                                width=110,
                                stretch=NO)
        self.orders_view.heading('Sum', text='Сумма, грн')
        self.orders_view.column('Sum',
                                anchor=CENTER,
                                minwidth=108,
                                width=108,
                                stretch=NO)

        self.orders_view.grid(row=0,
                              column=0,
                              sticky=N + S + E + W,
                              padx=3,
                              pady=3)

        # NOTE: next [for] block is for testing purposes only.
        """
        for dish in self.dishes:
            self.orders_view.insert('', 'end',
                text=dish,
                values=[
                    self.dishes[dish]['weight'],
                    5,  # [amount] column
                    'wats up?',  # [comment] column
                    self.dishes[dish]['price'],
                    5 * float(self.dishes[dish]['price'])
                ]
            )
        """

        orders_scrlbar = Scrollbar(self.frames[3],
                                   orient=VERTICAL,
                                   command=self.orders_view.yview)
        self.orders_view['yscrollcommand'] = orders_scrlbar.set
        orders_scrlbar.grid(row=0, column=1, sticky=N + S)

        # Save Report frame widgets.
        saveWeb_btn = Button(self.frames[4], text='Сохранить отчет', width=20)
        trackweight_chkbox = Checkbutton(self.frames[4],
                                         text='Учитывать средний вес',
                                         variable=self.track_weight)

        saveWeb_btn['command'] = lambda: self.saveWeb()

        saveWeb_btn.pack(side='left', anchor=CENTER, padx=5, pady=3)
        trackweight_chkbox.pack(side='left', anchor=CENTER, pady=3, padx=3)

    def configureGrid(self):
        """Configure weights of grids columns and rows"""
        # Top-level configuration.
        self.grid(sticky=N + S + E + W)
        top = self.winfo_toplevel()
        top.rowconfigure(0, weight=1)
        top.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        # Configuration of main content frame.
        self.configureFrame(self.content, [1], [0, 0, 0, 3, 0])
        # Configuration of about frame.
        self.configureFrame(self.frames[0], [0, 1, 0, 1, 0, 0, 0, 0],
                            [0, 0, 0])
        # Configuration of new order frame.
        self.configureFrame(self.frames[2], [0, 1, 1, 1, 1, 1], [0, 0, 0, 0])
        # Configuration of orders table frame.
        self.configureFrame(self.frames[3], [1, 0], [1])

    def centerWindow(self):
        """Place the main window in the center of screen"""
        window_w = DEFAULT_MINSIZE_WIDTH
        window_h = DEFAULT_MINSIZE_HEIGHT
        screen_w = self.winfo_screenwidth()
        screen_h = self.winfo_screenheight()
        x = (screen_w - window_w) / 2
        y = (screen_h - window_h) / 2
        self.parent.geometry('%dx%d+%d+%d' % (window_w, window_h, x, y))

    def onQuit(self):
        """Before the program exits, ask user, if he really wants it"""
        if messagebox.askyesno('Выход из программы',
                               'Вы действительно хотите выйти из программы?'):
            self.quit()

    @staticmethod
    def deleteEntry(e, tree):
        """Event to handle deletion in TreeView woth [Delete] button"""
        selected_item = tree.selection()[0]  # get selected item
        tree.delete(selected_item)

    @staticmethod
    def configureFrame(frame, columns_wght, rows_wght):
        """Function to organize frame configuration routine"""
        frame.grid(column=0, row=0, sticky=N + S + E + W)
        for i, weight in enumerate(columns_wght):
            frame.columnconfigure(i, weight=weight)
        for i, weight in enumerate(rows_wght):
            frame.rowconfigure(i, weight=weight)

    def saveWeb(self):
        """Save data from the TreeView to the html report"""
        # Validation: if there is no items in tree_view
        if not self.orders_view.get_children():
            messagebox.showerror('Ошибка', 'Ошибка создания отчета: нет блюд.')
            return

        # Open file dialog to choose saving path.
        file = filedialog.asksaveasfile(mode='w',
                                        defaultextension='.html',
                                        filetypes=[('Веб страница', '.html'),
                                                   ('Все файлы', '.*')])
        # If user pressed [Cancel] or closed a file dialog.
        if file is None:
            return

        # Pack files to send to HTML saver module.
        # Dictionary looks like: { name:{weight,amount,comment,price,total}, name:... }
        packed_dishes = {
            'global': {
                'trackw': self.track_weight.get(),  # flag - is weight tracked
                'totalsum':
                self.sum_lbl['text'][21:-4],  # str - total sum of dishes
                'centries': self.custom_entries  # [5*str] - custom entries
            },
            'about': {
                'client': self.entries['client'].get(),
                'manager': self.entries['manager'].get(),
                'type': self.entries['type'].get(),
                'date': self.entries['date'].get(),
                'time': self.entries['time'].get(),
                'location': self.entries['location'].get(),
                'persons': self.entries['persons'].get()
            },
            'dishes': {}
        }
        for child in self.orders_view.get_children():
            child_content = self.orders_view.item(child)
            child_values = child_content['values']
            child_name = child_content['text']
            child_type = self.dishes[child_name]['type']
            # Pack data about a certain dish.
            packed_child = {
                child_name: {
                    'weight': child_values[0],
                    'amount': child_values[1],
                    'comment': child_values[2],
                    'price': child_values[3],
                    'total': child_values[4],
                    'type': child_type
                }
            }
            packed_dishes['dishes'].update(packed_child)
        # Save the HTML report
        html_writer = DishesHTMLReport(file, data=packed_dishes)
        html_writer.create_html()
        messagebox.showinfo('Успешное сохранение',
                            'Данные были успешно сохранены.')

    def addCustomEntry(self):
        """This functions opens a window, which gives access for creating custom entries to report"""
        newentry_dialog = NewEntryDialog(
            self, title='Добавить собственную строку в отчет')
        if newentry_dialog.result:
            self.custom_entries.append(newentry_dialog.result)

    def addDish(self):
        """This function adds an entry to the order_view TreeView widget."""
        # Get packed_info as a dictionary.
        packed_info = self.packInfo()
        # If info packed successfully, add a new entry to orders TreeView.
        if not packed_info:
            return
        # Add a dish to the TreeView.
        self.orders_view.insert('',
                                'end',
                                text=packed_info['dish'],
                                values=packed_info['values'])
        # Clear all entries.
        entries_toclear = ['name', 'comment', 'amount']
        for entry_key in entries_toclear:
            self.entries[entry_key].delete(0, END)
            self.entries[entry_key].insert(0, '')
        self.entries['amount'].insert(0, '1')
        # Change [sum] label.
        total_sum = float(self.sum_lbl['text'][21:-4]) + float(
            packed_info['values'][4])
        self.sum_lbl['text'] = 'Текущая сумма заказа:\n %.2f грн' % total_sum
        # Set focus to ['name'] entry.
        self.entries['name'].focus_set()

    def packInfo(self):
        """Pack values, that were inserted into Entries and Text, into dictionary"""
        msg = self.validateForm()
        if msg == 'OK':
            name = self.entries['name'].get()
            amount = self.entries['amount'].get()
            total_price = float(amount) * float(self.dishes[name]['price'])
            pack = {
                'dish':
                name,
                'values': [
                    self.dishes[name]['weight'],
                    str(amount), self.entries['comment'].get(),
                    self.dishes[name]['price'],
                    '%.2f' % total_price
                ]
            }
            return pack
        elif msg == 'NEWDISH_CANCELED':
            return False
        else:
            messagebox.showerror('Ошибка ввода',
                                 'При вводе случились ошибки: \n%s' % msg)
            return False

    def validateForm(self):
        """Validate all Entry and Text Widgets"""
        msg = ''
        index = 1
        translations = {
            'client': 'Клиент',
            'manager': 'Менеджер',
            'type': 'Вид мероприятия',
            'date': 'Дата',
            'time': 'Время',
            'location': 'Место проведения',
            'persons': 'Количество персон',
            'name': 'Название',
            'comment': 'Комментарий',
            'amount': 'Количество',
        }

        for k in self.entries:
            # Check if some entry is empty.
            if self.entries[k].get() == '':
                if k == 'comment':
                    continue
                msg += '%i) Поле [%s] пустое.\n' % (index, translations[k])
                index += 1

        # Persons entry should contain only digits.
        if not all(letter.isdigit()
                   for letter in self.entries['persons'].get()):
            msg += '%i) Поле [Количество персон] должно содержать только цифры.\n' % index
            index += 1
        # Check date entry.
        match = re.search(r'(\d{2})[.](\d{2})[.](\d{4})$',
                          self.entries['date'].get())
        if not match:
            msg += '%i) Неправильный формат даты.\nПравильный формат: дд.мм.гггг\n' % index
            index += 1
        # Check amount entry.
        check = all(letter.isdigit() or letter == '.'
                    for letter in self.entries['amount'].get())
        if not check:
            msg += '%i) Поле [Количество] должно содержать только цифры, или точки.\n' % index
            index += 1

        # Ask about [name] entry only if there are no more errors left.
        if msg != '':
            return msg

        # Check name entry.
        if (self.entries['name'].get() not in self.dishes_names
                and self.entries['name'].get() != ''):
            if messagebox.askyesno(
                    'Добавление нового блюда',
                    'Блюда %s нет в списке. Добавить?' %
                    self.entries['name'].get()):
                # Create a new window, which will contain a [result] dictionary {name,type,weight,price}
                newdish_dialog = NewDishDialog(self,
                                               self.entries['name'].get(),
                                               'Добавить новое блюдо')
                if newdish_dialog.result:
                    dishToJSON = {
                        newdish_dialog.result['name']: {
                            'weight': newdish_dialog.result['weight'],
                            'price': newdish_dialog.result['price'],
                            'type': newdish_dialog.result['type']
                        }
                    }
                    self.jsonReader.writeDish(dishToJSON)
                    self.jsonReader.prepInformation()
                    self.dishes = self.jsonReader.getDishesDict()
                    self.dishes_names = self.jsonReader.getDishesNames()
                    self.entries['name'].set_completion_list(self.dishes_names)
                else:
                    # if [exit] was pressed
                    return 'NEWDISH_CANCELED'
            else:
                return 'NEWDISH_CANCELED'
        # Check if the same dish is in the orderslist.
        for child in self.orders_view.get_children():
            child_content = self.orders_view.item(child)
            if self.entries['name'].get() == child_content['text']:
                msg += '%i) Ошибка в поле [Название] - такое блюдо уже есть в списке.' % index
                index += 1

        # If all tests passed correctly, msg is 'OK'
        if msg == '':
            msg = 'OK'
        return msg
Exemple #28
0
class RightTree(Frame):
    def get_size_in_pixels(self, text):
        """
        Returns the length of the String 'text' in pixels.
        """
        font = ft.Font()
        w = font.measure(text)
        return w

    def __init__(self, parent, dispatch_event):
        """
        Builds the lower right tree, which informs the user about the metadata information.
        Initialisation creates a frame, a treeview and two scrollbars for the treeview element. 
        
        On Inform, if there is a dataset selected it will build a Treeview with the metadata.
        """
        super().__init__(parent)
        self.dispatch_event = dispatch_event
        self.tree = Treeview(self, columns=["value"], show="tree")
        #self.configure(height=1000)
        self.scrollbar_y = Scrollbar(self.tree, orient="vertical")
        self.scrollbar = Scrollbar(self.tree, orient="horizontal")
        self.scrollbar.config(command=self.tree.xview)
        self.scrollbar_y.config(command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.scrollbar_y.set,
                            xscrollcommand=self.scrollbar.set)
        self.tree.pack(fill="both", expand=True)
        self.scrollbar.pack(side="bottom", fill="x")
        self.scrollbar_y.pack(side="right", fill="y")
        self.pack(expand=1, fill='both')
        self.bind("<Configure>", self.on_resize)

    def on_resize(self, event):
        """
        Sets the width of column 0 to an arbitrary, long enough value, to fix issue nr.005.
        """
        self.scrollbar.config(command=self.tree.xview)
        self.scrollbar.pack(side="bottom", fill="x")
        self.tree.column(0, width=600)
        self.update()
        pass

    def inform(self, data):
        """
        Inform function of the RightTree class. 
        Loads available data. If there is a project, it clears the Treeview.
        If there is exactly 1 selection, it will build a tree with the metadata shown in it.
        If there is no selection or more than 1, it will show an appropriate message.
        """
        project = data["project"]
        if project:
            # First delete everything - Selection might have changed
            self.tree.delete(*self.tree.get_children())
            # 3 ifs : no selection, 1 selected, multiple selections
            sel = project.selection
            if len(sel) == 0:
                self.tree.column("#0", width=1100)
                self.tree.insert("",
                                 tkinter.END,
                                 "Project information",
                                 text="Please add and select a dataset")
            elif len(sel) == 1:
                index = sel[0]  # For legacy reasons variable named name
                self.tree.insert("",
                                 tkinter.END,
                                 "Project information",
                                 text="Project information")
                self.tree.insert("Project information",
                                 tkinter.END,
                                 "Project Path",
                                 text="Path",
                                 values=[project.path])
                self.tree.insert("",
                                 tkinter.END,
                                 "Dataset information",
                                 text="Dataset information")
                self.tree.insert("Dataset information",
                                 tkinter.END,
                                 "Dataset Path",
                                 text="Path",
                                 values=[project.datasets[index].path])
                self.tree.insert(
                    "Dataset information",
                    tkinter.END,
                    "Rows",
                    text="Rows",
                    values=[
                        len(project.datasets[index].data)
                    ])  # example: 120000 rows with time from 0 to 59.9995 s.
                # HERE I AM
                textlines = textwrap.wrap(
                    (project.datasets[index].metadata["Description"]),
                    width=70)
                if textlines == []:
                    textlines.append("No description given.")
                self.tree.insert("Dataset information",
                                 tkinter.END,
                                 "Dataset Description",
                                 text="Description",
                                 values=[textlines[0]])
                if len(textlines) > 1:
                    for i in range(1, len(textlines)):
                        self.tree.insert("Dataset information",
                                         tkinter.END,
                                         "Dataset Description %d" % (i),
                                         text="",
                                         values=[textlines[i]])
                self.tree.insert("", tkinter.END, "Method", text="Method")
                if project.datasets[index].metadata[
                        "Method"] == "HILDE-Homogeneous":
                    self.tree.insert(
                        "Method",
                        tkinter.END,
                        value=textwrap.wrap("HILDE (homogeneous noise)"))
                elif project.datasets[index].metadata[
                        "Method"] == "HILDE-Heterogeneous":
                    self.tree.insert(
                        "Method",
                        tkinter.END,
                        value=textwrap.wrap("HILDE (heterogeneous noise)"))
                elif project.datasets[index].metadata[
                        "Method"] == "JULES-Homogeneous":
                    self.tree.insert(
                        "Method",
                        tkinter.END,
                        value=textwrap.wrap("JULES (homogeneous noise)"))
                elif project.datasets[index].metadata[
                        "Method"] == "JSMURF-Homogeneous":
                    self.tree.insert(
                        "Method",
                        tkinter.END,
                        value=textwrap.wrap("JSMURF (homogeneous noise)"))
                else:
                    self.tree.insert(
                        "Method",
                        tkinter.END,
                        value=textwrap.wrap("JSMURF (heterogeneous noise)"))
                # Here i will go

                self.tree.insert("",
                                 tkinter.END,
                                 "Dataset parameters",
                                 text="Dataset parameters")
                self.tree.insert("Dataset parameters",
                                 tkinter.END,
                                 "Sampling rate in Hz",
                                 text="Sampling rate in Hz",
                                 values=project.datasets[index].
                                 metadata["Sampling rate in Hz"])
                self.tree.insert("Dataset parameters",
                                 tkinter.END,
                                 "Cut-off frequency in Hz",
                                 text="Cut-off frequency in Hz",
                                 values=[
                                     project.datasets[index].
                                     metadata["Cut-off frequency in Hz"]
                                 ])
                self.tree.insert(
                    "Dataset parameters",
                    tkinter.END,
                    "Filter type",
                    text="Filter type",
                    values=[project.datasets[index].metadata["Filter type"]])

                if project.datasets[index].metadata[
                        "Method"] == "HILDE-Homogeneous":
                    self.tree.insert(
                        "Dataset parameters",
                        tkinter.END,
                        "Quantile 1",
                        text="Quantile 1",
                        values=["will be computed by MC simulation"])
                    self.tree.insert("Quantile 1",
                                     tkinter.END,
                                     "Significance level 1",
                                     text="Alpha1",
                                     values=[
                                         project.datasets[index].
                                         metadata["Significance level 1"]
                                     ])
                    # self.tree.insert("Quantile 1", tkinter.END, "Repetitions 1", text="Repetitions", values=[
                    #     project.datasets[index].metadata["Repetitions"]])
                    self.tree.insert("Quantile 1",
                                     tkinter.END,
                                     "Repetitions ",
                                     text="Repetitions",
                                     values=[
                                         project.datasets[index].
                                         metadata["Repetitions_Hilde"]
                                     ])

                    self.tree.insert(
                        "Dataset parameters",
                        tkinter.END,
                        "Quantile 2",
                        text="Quantile 2",
                        values=["will be computed by MC simulation"])
                    self.tree.insert("Quantile 2",
                                     tkinter.END,
                                     "Significance level 2",
                                     text="Alpha2",
                                     values=[
                                         project.datasets[index].
                                         metadata["Significance level 2"]
                                     ])
                    self.tree.insert("Quantile 2",
                                     tkinter.END,
                                     "Repetitions",
                                     text="Repetitions",
                                     values=[
                                         project.datasets[index].
                                         metadata["Repetitions_Hilde"]
                                     ])

                elif project.datasets[index].metadata[
                        "Method"] == "HILDE-Heterogeneous":
                    self.tree.insert(
                        "Dataset parameters",
                        tkinter.END,
                        "Quantile 1",
                        text="Quantile 1",
                        values=["will be computed by MC simulation"])
                    self.tree.insert("Quantile 1",
                                     tkinter.END,
                                     "Significance level 1",
                                     text="Alpha1",
                                     values=[
                                         project.datasets[index].
                                         metadata["Significance level 1"]
                                     ])
                    self.tree.insert("Quantile 1",
                                     tkinter.END,
                                     "Repetitions ",
                                     text="Repetitions",
                                     values=[
                                         project.datasets[index].
                                         metadata["Repetitions_Hilde"]
                                     ])

                    self.tree.insert(
                        "Dataset parameters",
                        tkinter.END,
                        "Quantile 2",
                        text="Quantile 2",
                        values=["will be computed by MC simulation"])
                    self.tree.insert("Quantile 2",
                                     tkinter.END,
                                     "Significance level 2",
                                     text="Alpha2",
                                     values=[
                                         project.datasets[index].
                                         metadata["Significance level 2"]
                                     ])
                    self.tree.insert("Quantile 2",
                                     tkinter.END,
                                     "Repetitions",
                                     text="Repetitions",
                                     values=[
                                         project.datasets[index].
                                         metadata["Repetitions_Hilde"]
                                     ])

                elif project.datasets[index].metadata[
                        "Method"] == "JULES-Homogeneous":
                    if project.datasets[index].metadata[
                            "Quantile_JULES_HOMOGENEOUS provided"]:
                        self.tree.insert(
                            "Dataset parameters",
                            tkinter.END,
                            "Quantile",
                            text="Quantile",
                            values=[
                                project.datasets[index].
                                metadata["Quantile_JULES_HOMOGENEOUS"]
                            ])
                    else:
                        self.tree.insert(
                            "Dataset parameters",
                            tkinter.END,
                            "Quantile",
                            text="Quantile",
                            values=["will be computed by MC simulation"])
                        self.tree.insert("Quantile",
                                         tkinter.END,
                                         "Significance level",
                                         text="Alpha",
                                         values=[
                                             project.datasets[index].
                                             metadata["Significance level"]
                                         ])
                        self.tree.insert(
                            "Quantile",
                            tkinter.END,
                            "Repetitions",
                            text="Repetitions",
                            values=[
                                project.datasets[index].metadata["Repetitions"]
                            ])

                elif project.datasets[index].metadata[
                        "Method"] == "JSMURF-Homogeneous":
                    if project.datasets[index].metadata[
                            "Quantile_JSMURF_HOMOGENEOUS provided"]:
                        self.tree.insert(
                            "Dataset parameters",
                            tkinter.END,
                            "Quantile",
                            text="Quantile",
                            values=[
                                project.datasets[index].
                                metadata["Quantile_JSMURF_HOMOGENEOUS"]
                            ])
                    else:

                        self.tree.insert(
                            "Dataset parameters",
                            tkinter.END,
                            "Quantile",
                            text="Quantile",
                            values=["will be computed by MC simulation"])
                        self.tree.insert("Quantile",
                                         tkinter.END,
                                         "Significance level",
                                         text="Alpha",
                                         values=[
                                             project.datasets[index].
                                             metadata["Significance level"]
                                         ])
                        self.tree.insert(
                            "Quantile",
                            tkinter.END,
                            "Repetitions",
                            text="Repetitions",
                            values=[
                                project.datasets[index].metadata["Repetitions"]
                            ])

                else:
                    self.tree.insert(
                        "Dataset parameters",
                        tkinter.END,
                        "Quantile",
                        text="Quantile",
                        values=["will be computed by MC simulation"])
                    self.tree.insert("Quantile",
                                     tkinter.END,
                                     "Significance level",
                                     text="Alpha",
                                     values=[
                                         project.datasets[index].
                                         metadata["Significance level"]
                                     ])
                    self.tree.insert(
                        "Quantile",
                        tkinter.END,
                        "Repetitions",
                        text="Repetitions",
                        values=[
                            project.datasets[index].metadata["Repetitions"]
                        ])

                maxw = 600
                #600
                for child in self.tree.get_children():
                    self.tree.see(child)
                    w = self.get_size_in_pixels(
                        str(self.tree.item(child)['values']))
                    if (w > maxw):
                        maxw = w
                    for grandchild in self.tree.get_children(child):
                        self.tree.see(grandchild)
                        w = self.get_size_in_pixels(
                            str(self.tree.item(grandchild)['values']))
                        if (w > maxw):
                            maxw = w
                        for ggrandchild in self.tree.get_children(grandchild):
                            self.tree.see(ggrandchild)
                            w = self.get_size_in_pixels(
                                str(self.tree.item(ggrandchild)['values']))

                            if (w > maxw):
                                maxw = w

                self.tree.column(0, width=maxw)
                self.tree.column("#0", width=200, stretch=False)
                #200

            else:
                self.tree.column("#0", width=1000)
                #1000
                self.tree.insert(
                    "",
                    tkinter.END,
                    "Project information",
                    text=
                    "Multiple Datasets have been selected, select single dataset to show project information."
                )
Exemple #29
0
class Library:
    """ Main class. Combines GUI, functionality and Database.

    Args:
        root (instance): tkinter's root instance.

    """
    appName = "Knihovna"
    appVersion = "0.2"

    tabList = [["Knihy", ["ID", "Název knihy", "Autor", "Ilustrátor", "Rok"]]]

    def __init__(self, root):
        """Initialises Library class.

        Args:
            root (instance): tkinter's root instance.

        """
        self.root = root
        self.root.geometry('1000x500')
        self.root.configure(background='#bdc3c7')
        self.root.minsize(1000, 500)
        self.root.title(Library.appName + " v" + Library.appVersion)

        self.toplevel = None

        self.notebook = Autoresized_Notebook(self.root)

        self.tables = []
        self.tabs = []
        i = 0
        for tab in Library.tabList:
            tabframe = Frame(self.notebook)
            self.notebook.add(tabframe, text=f"{tab[0]}")

            # zjistí, který tab je právě otevřený a zavolá funkci windowCreate, které předá název tabu
            Button(tabframe,
                   text='+',
                   command=lambda: self.windowCreate(),
                   height=1).pack(fill=X)

            if len(tab) >= 2:
                columnList = ""
                e = 0
                for columnName in tab[1]:
                    if e != 0:
                        columnList += ", "
                    columnList += f"{e}"
                    e = e + 1

                # + editovací tlačítko
                columnList += ", " + str((int(e) + 1))

                self.treeview = Treeview(tabframe,
                                         columns=(columnList),
                                         show="headings",
                                         height=10)
                self.treeview.bind("<ButtonRelease-1>", self.bookEditBind)
                f = 0
                for columnName in tab[1]:
                    self.treeview.column(f,
                                         minwidth=0,
                                         width=150,
                                         anchor=N,
                                         stretch=TRUE)
                    self.treeview.heading(f, text=f"{columnName}", anchor=W)
                    f = f + 1
                i = i + 1

                self.treeview.column(f + 1,
                                     minwidth=0,
                                     width=150,
                                     anchor=N,
                                     stretch=TRUE)
                self.treeview.heading(f + 1, text="jiné", anchor=W)

                self.updateTable()

                self.tables.append(
                    self.treeview.pack(fill=X, side=TOP, expand=1))

            Button(tabframe, text='Exit', command=root.destroy).pack(padx=100,
                                                                     pady=100)

        self.notebook.pack(fill=BOTH, expand=1)

    def windowCreate(self, id=None, deleteCallback=None):
        """Creates another window.

        Args:
            id (int): id of selected book (default None).
            deleteCallback (function): callback of inserted function.

        """
        if (self.toplevel is not None) and self.toplevel.exists == True:
            return

        self.toplevel = Window(self.root,
                               id,
                               saveNewBook=self.save,
                               deleteBook=deleteCallback)

    def bookEditBind(self, event):
        """Binds event when clicking to 'edit' book info.

        Args:
            event (instance): event.

        """
        button = self.treeview.identify_column(event.x)
        region = self.treeview.identify_region(event.x, event.y)

        if button != '#6' or region != 'cell':
            return
        item = self.treeview.focus()
        id = self.treeview.item(item)['values'][0]
        self.windowCreate(id, self.delete)

    def getBooks(self):
        """Clears self.books, reselects book info and its metadata and reinserts itself to self.books."""
        self.books = []
        booksInfo = Database.select("SELECT * FROM books")
        for book in booksInfo:
            info = {
                "ID": book[0],
                "authors": [],
                "illustrators": [],
                "title": book[1],
                "year": book[2]
            }
            meta = Database.select(
                f"SELECT meta.role, meta.name  FROM bookWorkers LEFT JOIN (SELECT workers.ID, (people.forename || ' ' || people.surname) as name, roles.name as role FROM workers LEFT JOIN people ON people.ID = workers.peopleID LEFT JOIN roles ON workers.roleID = roles.ID) meta ON bookWorkers.workersID = meta.ID WHERE bookID = {book[0]}"
            )
            for person in meta:
                info[person[0] + "s"].append(person[1])

            self.books.append(info)

    def updateTable(self):
        """Deletes data from table and calls getBooks to reinsert data."""
        self.getBooks()
        self.treeview.delete(*self.treeview.get_children())

        for book in self.books:
            if (len(book["authors"]) >= 2):
                authors = ", ".join(book["authors"])
            else:
                authors = book["authors"][0]

            if (len(book["illustrators"]) >= 2):
                illustrators = ", ".join(book["illustrators"])
            elif not book["illustrators"]:
                illustrators = ""
            else:
                illustrators = book["illustrators"][0]
            self.treeview.insert("",
                                 END,
                                 values=(book["ID"], book["title"], authors,
                                         illustrators, book["year"],
                                         "upravit"))

    def delete(self, id):
        """Deletes selected book and updates table immediately after.

        Args:
            id (int): id of selected (edited) book.

        """
        Database.execute(f"DELETE FROM books WHERE ID = {id}")
        Database.execute(f"DELETE FROM bookWorkers WHERE bookID = {id}")
        self.updateTable()

    def save(self, data, id):
        """Saves data to Database using class of the same name.

        Args:
            data (array): example: [{'forename': 'dd', 'surname': 'dd'}], 'illustrators': [{'forename': 'dd', 'surname': 'dd'}], 'title': None, 'year': None}
            id (integer): id of selected book.

        """

        bookID = Database.execute(
            f"INSERT INTO books (title, year) VALUES ('{data['title']}', '{data['year']}')"
        )

        for role in data["roles"]:
            for person in data["roles"][role]:
                personID = Database.select(
                    f"SELECT ID FROM people WHERE forename = '{person['forename']}' AND surname = '{person['surname']}'"
                )
                if not personID:
                    personID = Database.execute(
                        f"INSERT INTO people (forename, surname) VALUES ('{person['forename']}', '{person['surname']}')"
                    )
                else:
                    personID = personID[0][0]

                workerID = Database.select(
                    f"SELECT ID FROM workers WHERE peopleID = '{personID}' AND roleID = (SELECT ID FROM roles WHERE name = '{role}')"
                )
                if not workerID:
                    workerID = Database.execute(
                        f"INSERT INTO workers (peopleID, roleID) VALUES ({personID}, (SELECT ID FROM roles WHERE name = '{role}'))"
                    )
                else:
                    workerID = workerID[0][0]

                bookWorkerID = Database.select(
                    f"SELECT ID FROM bookWorkers WHERE workersID = '{workerID}' AND roleID = (SELECT ID FROM roles WHERE name = '{role}')"
                )
                if not bookWorkerID:
                    bookWorkerID = Database.execute(
                        f"INSERT INTO bookWorkers (bookID, workersID) VALUES ('{bookID}', '{workerID}')"
                    )
                else:
                    bookWorkerID = bookWorkerID[0][0]
        self.updateTable()
class Expenses(Frame):

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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


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

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

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

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

        numDays = self.nums(1,lastDay)

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

        itemType = self.chooseItemType.get()

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

        else:
            self.obtainData(itemType)

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

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

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

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

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

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

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

        self.createDisplayTable()

        self.obtainDetailedData(name, type)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        InventoryDB.close()

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

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

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

        self.year = IntVar(self)

        numYears = self.nums(2015, 2030)

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

        self.year.set(numYears[0])

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


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

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

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

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

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

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

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

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

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

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

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

                self.backFunction = self.viewTotalCostYear

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

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

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

                self.backFunction = self.viewTotalCostMonth

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

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

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

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

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.place();
        self.inventoryDB = InventoryDatabase()
        # self.inventoryDB.createTable()
        self.createOptionButtons()
Exemple #31
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 #32
0
class FormChildAED:
    def __init__(self, frm_parent, title, connection):
        self.connection = connection
        self.directive = Message()
        self.title = title
        self.decide = True
        self.id_selected = 0
        self.frm_child_list = LabelFrame(frm_parent)
        self.frm_child_crud = LabelFrame(frm_parent)
        self.frm_child_crud.config(fg=TEXT_COLOR, font=SUBTITLE_FONT)
        self.initialize_components()

    def initialize_components(self):
        """
        Method that initialize the visual components for each form associated with the local administration
        """
        # Resources for the Forms
        self.new_icon = PhotoImage(file=r"./Resources/create.png")
        self.modify_icon = PhotoImage(file=r"./Resources/modify.png")
        self.remove_icon = PhotoImage(file=r"./Resources/delete.png")
        self.save_icon = PhotoImage(file=r"./Resources/save.png")
        self.cancel_icon = PhotoImage(file=r"./Resources/cancel.png")

        # Components for List Form
        lbl_sep1 = Label(self.frm_child_list)
        lbl_sep1.grid(row=0, column=0, padx=10, pady=25)
        self.trv_available = Treeview(self.frm_child_list,
                                      height=15,
                                      columns=('N', 'Name', 'Surname',
                                               'E-mail'))
        self.trv_available.heading('#0', text='ID', anchor=CENTER)
        self.trv_available.heading('#1', text='N', anchor=CENTER)
        self.trv_available.heading('#2', text='Name', anchor=CENTER)
        self.trv_available.heading('#3', text='Surname', anchor=CENTER)
        self.trv_available.heading('#4', text='E-mail', anchor=CENTER)
        self.trv_available.column('#0', width=0, minwidth=50, stretch=NO)
        self.trv_available.column('#1', width=20, minwidth=20, stretch=NO)
        self.trv_available.column('#2', width=200, minwidth=200, stretch=NO)
        self.trv_available.column('#3', width=200, minwidth=200, stretch=NO)
        self.trv_available.column('#4', width=400, minwidth=400, stretch=NO)
        self.trv_available.grid(row=0, column=1, sticky=W, pady=25)
        vsb_trv_av = Scrollbar(self.frm_child_list,
                               orient="vertical",
                               command=self.trv_available.yview)
        vsb_trv_av.grid(row=0, column=2, pady=25, sticky=NS)
        self.trv_available.configure(yscrollcommand=vsb_trv_av.set)
        frm_aux4 = Frame(self.frm_child_list)
        btn_new = Button(frm_aux4, image=self.new_icon, command=self.click_new)
        btn_new.grid(row=0, column=0, pady=5, padx=5, sticky=E)
        btn_new_ttp = CreateToolTip(btn_new, 'New ' + self.title.lower())
        btn_edit = Button(frm_aux4,
                          image=self.modify_icon,
                          command=self.click_update)
        btn_edit.grid(row=1, column=0, pady=5, padx=5, sticky=E)
        btn_edit_ttp = CreateToolTip(btn_edit, 'Edit ' + self.title.lower())
        btn_delete = Button(frm_aux4,
                            image=self.remove_icon,
                            command=self.click_delete)
        btn_delete.grid(row=2, column=0, pady=5, padx=5, sticky=E)
        btn_delete_ttp = CreateToolTip(btn_delete,
                                       'Delete ' + self.title.lower())
        frm_aux4.grid(row=0, column=3, pady=25, padx=25, sticky=NW)

        # Components for CRUD FRM
        lbl_name = Label(self.frm_child_crud, text='Name*')
        lbl_name.config(fg=TEXT_COLOR, font=LABEL_FONT)
        lbl_name.grid(row=0, column=0, pady=10, padx=20, sticky=W)
        lbl_surname = Label(self.frm_child_crud, text='Surname*')
        lbl_surname.config(fg=TEXT_COLOR, font=LABEL_FONT)
        lbl_surname.grid(row=1, column=0, pady=10, padx=20, sticky=W)
        lbl_email = Label(self.frm_child_crud, text='E-mail*')
        lbl_email.config(fg=TEXT_COLOR, font=LABEL_FONT)
        lbl_email.grid(row=2, column=0, pady=10, padx=20, sticky=W)
        self.lbl_old_passwd = Label(self.frm_child_crud, text='Old password*')
        self.lbl_old_passwd.config(fg=TEXT_COLOR, font=LABEL_FONT)
        self.lbl_passwd = Label(self.frm_child_crud, text='New password*')
        self.lbl_passwd.config(fg=TEXT_COLOR, font=LABEL_FONT)
        self.lbl_passwd_conf = Label(self.frm_child_crud,
                                     text='Confirm new password*')
        self.lbl_passwd_conf.config(fg=TEXT_COLOR, font=LABEL_FONT)
        self.txt_name = Entry(self.frm_child_crud)
        self.txt_name.grid(row=0, column=1, pady=10, padx=20, sticky=W)
        self.txt_surname = Entry(self.frm_child_crud)
        self.txt_surname.grid(row=1, column=1, pady=10, padx=20, sticky=W)
        self.txt_email = Entry(self.frm_child_crud)
        self.txt_email.grid(row=2, column=1, pady=10, padx=20, sticky=W)
        self.txt_old_passwd = Entry(self.frm_child_crud, show="*")
        self.txt_passwd = Entry(self.frm_child_crud, show="*")
        self.txt_passwd_conf = Entry(self.frm_child_crud, show="*")
        sep_aux2 = Separator(self.frm_child_crud, orient=VERTICAL)
        sep_aux2.grid(row=0, column=2, sticky=NS, rowspan=6)
        frm_aux = Frame(self.frm_child_crud)
        btn_save = Button(frm_aux,
                          image=self.save_icon,
                          command=self.click_save)
        btn_save.grid(row=0, column=0, padx=5, pady=5, sticky=E)
        btn_save_ttp = CreateToolTip(btn_save, 'Save ' + self.title.lower())
        btn_cancel = Button(frm_aux,
                            image=self.cancel_icon,
                            command=self.click_cancel)
        btn_cancel.grid(row=1, column=0, padx=5, pady=5, sticky=E)
        btn_cancel_ttp = CreateToolTip(btn_cancel, 'Cancel')
        frm_aux.grid(row=0, column=3, pady=10, padx=25, sticky=N, rowspan=6)

    def retrieve_list(self):
        """
        Method that retrieve users information from the server and displays them in the TreeView from
        the List Form
        """
        # Remove existing elements in the list
        for item in self.trv_available.get_children():
            self.trv_available.delete(item)
        # Retrieve information from the server
        if self.title == 'Experimenter':
            self.directive = Message(action=17)
        elif self.title == 'Designer':
            self.directive = Message(action=22)
        elif self.title == 'Administrator':
            self.directive = Message(action=12)
        else:
            raise Exception('Error en recuperacion: tipo de usuario')
        self.connection = self.directive.send_directive(self.connection)
        # Adding elements in the list
        for index, item in enumerate(self.connection.message.information):
            elements = item.split('¥')
            self.trv_available.insert('',
                                      'end',
                                      text=elements[0],
                                      values=(index + 1, elements[1],
                                              elements[2], elements[3]))
        # Mark first element of the treeview if exist
        if len(self.trv_available.get_children()) != 0:
            self.trv_available.selection_set(
                self.trv_available.get_children()[0])

    def show_frm(self):
        """
        Show the List form when the User administration is called
        """
        self.retrieve_list()
        self.frm_child_list.grid(row=1,
                                 column=0,
                                 columnspan=9,
                                 rowspan=8,
                                 pady=10,
                                 padx=10)

    def hide_frm(self):
        """
        Hide the User administration Forms
        """
        self.clear_fields()
        self.frm_child_list.grid_forget()
        self.frm_child_crud.grid_forget()

    def click_new(self):
        """
        Initialize CRUD Form for creating a new user.
        """
        self.user = Designer()
        self.frm_child_list.grid_forget()
        self.txt_name.focus_set()
        self.frm_child_crud['text'] = 'New ' + self.title.lower()
        self.lbl_passwd.grid(row=3, column=0, pady=10, padx=20, sticky=W)
        self.lbl_passwd_conf.grid(row=4, column=0, pady=10, padx=20, sticky=W)
        self.txt_passwd.grid(row=3, column=1, pady=10, padx=20, sticky=W)
        self.txt_passwd_conf.grid(row=4, column=1, pady=10, padx=20, sticky=W)
        self.frm_child_crud.grid(row=1,
                                 column=0,
                                 columnspan=9,
                                 rowspan=8,
                                 pady=10,
                                 padx=10)

    def click_update(self):
        """
        Initialize CRUD Form for updating a user. It loads information of selected User into visual components
        """
        if len(self.trv_available.selection()) == 1:
            id_selected = int(
                self.trv_available.item(
                    self.trv_available.selection())['text'])
            if self.title == 'Experimenter':
                self.directive = Message(action=20, information=[id_selected])
            elif self.title == 'Designer':
                self.directive = Message(action=25, information=[id_selected])
            else:
                self.directive = Message(action=15, information=[id_selected])
            self.connection = self.directive.send_directive(self.connection)
            if self.connection.message.action == 5:  # An error ocurred while trying to update the item
                messagebox.showerror(
                    parent=self.frm_child_list,
                    title='Can not update the item',
                    message=self.connection.message.information[0])
            else:
                self.user = Designer(
                    id=id_selected,
                    name=self.connection.message.information[0],
                    surname=self.connection.message.information[1],
                    user=self.connection.message.information[2],
                    password=self.connection.message.information[3])
                self.txt_name.insert(0, self.user.name)
                self.txt_surname.insert(0, self.user.surname)
                self.txt_email.insert(0, self.user.user)
                self.frm_child_list.grid_forget()
                self.txt_name.focus_set()
                self.frm_child_crud['text'] = 'Update ' + self.title.lower()
                self.lbl_old_passwd.grid(row=3,
                                         column=0,
                                         pady=10,
                                         padx=20,
                                         sticky=W)
                self.lbl_passwd.grid(row=4,
                                     column=0,
                                     pady=10,
                                     padx=20,
                                     sticky=W)
                self.lbl_passwd_conf.grid(row=5,
                                          column=0,
                                          pady=10,
                                          padx=20,
                                          sticky=W)
                self.txt_old_passwd.grid(row=3,
                                         column=1,
                                         pady=10,
                                         padx=20,
                                         sticky=W)
                self.txt_passwd.grid(row=4,
                                     column=1,
                                     pady=10,
                                     padx=20,
                                     sticky=W)
                self.txt_passwd_conf.grid(row=5,
                                          column=1,
                                          pady=10,
                                          padx=20,
                                          sticky=W)
                self.frm_child_crud.grid(row=1,
                                         column=0,
                                         columnspan=9,
                                         rowspan=8,
                                         pady=10,
                                         padx=10)
        else:
            messagebox.showwarning(parent=self.frm_child_list,
                                   title='No selection',
                                   message='You must select one item')

    def click_delete(self):
        """
        Method that removes a selected user from the initial list (changes are updated in DB)
        """
        if len(self.trv_available.selection()) == 1:
            decision = messagebox.askyesno(
                parent=self.frm_child_list,
                title='Confirmation',
                message='Are you sure you want to delete the item?')
            if decision:
                id_selected = int(
                    self.trv_available.item(
                        self.trv_available.selection())['text'])
                if self.title == 'Experimenter':
                    self.directive = Message(action=19,
                                             information=[id_selected])
                elif self.title == 'Designer':
                    self.directive = Message(action=24,
                                             information=[id_selected])
                else:
                    self.directive = Message(action=14,
                                             information=[id_selected])
                self.connection = self.directive.send_directive(
                    self.connection)
                if self.connection.message.action == 5:  # An error ocurred while deleting the item
                    messagebox.showerror(
                        parent=self.frm_child_list,
                        title='Can not delete the item',
                        message=self.connection.message.information[0])
                else:
                    self.retrieve_list()
        else:
            messagebox.showwarning(parent=self.frm_child_list,
                                   title='No selection',
                                   message='You must select one item')

    def click_save(self):
        """
        Saves information of the user inserted into the visual components and sends to the server
        """
        if self.validate_fields():
            self.user.name = self.txt_name.get()
            self.user.surname = self.txt_surname.get()
            self.user.user = self.txt_email.get()
            self.user.password = self.txt_passwd.get()
            if self.user.id == 0:  # Creating an user
                if self.title == 'Experimenter':
                    self.directive = Message(
                        action=16,
                        information=[
                            self.user.name, self.user.surname, self.user.user,
                            hashlib.sha1(
                                self.user.password.encode()).hexdigest()
                        ])
                elif self.title == 'Designer':
                    self.directive = Message(
                        action=21,
                        information=[
                            self.user.name, self.user.surname, self.user.user,
                            hashlib.sha1(
                                self.user.password.encode()).hexdigest()
                        ])
                else:
                    self.directive = Message(
                        action=11,
                        information=[
                            self.user.name, self.user.surname, self.user.user,
                            hashlib.sha1(
                                self.user.password.encode()).hexdigest()
                        ])
            else:  # Updating an user
                if self.title == 'Experimenter':
                    self.directive = Message(
                        action=18,
                        information=[
                            self.user.id, self.user.name, self.user.surname,
                            self.user.user,
                            hashlib.sha1(
                                self.user.password.encode()).hexdigest()
                        ])
                elif self.title == 'Designer':
                    self.directive = Message(
                        action=23,
                        information=[
                            self.user.id, self.user.name, self.user.surname,
                            self.user.user,
                            hashlib.sha1(
                                self.user.password.encode()).hexdigest()
                        ])
                else:
                    self.directive = Message(action=13,
                                             information=[
                                                 self.user.id, self.user.name,
                                                 self.user.surname,
                                                 self.user.user,
                                                 self.user.password
                                             ])
            self.connection = self.directive.send_directive(self.connection)
            if self.connection.message.action == 5:
                messagebox.showwarning(parent=self.frm_child_crud,
                                       title='Repeated e-mail',
                                       message=self.connection.message.comment)
            else:
                self.clear_fields()
                self.frm_child_crud.grid_forget()
                self.show_frm()

    def click_cancel(self):
        """
        Function activated when 'Cancel' button is pressed in frm_child_crud
        """
        decision = True
        if self.txt_name.get() != self.user.name or \
                self.txt_surname.get() != self.user.surname or \
                self.txt_email.get() != self.user.user or len(self.txt_passwd.get()) != 0 or \
                len(self.txt_passwd_conf.get()) != 0:
            if self.user.id != 0 and len(
                    self.txt_passwd_conf.get()) != 0 or self.user.id == 0:
                decision = messagebox.askyesno(
                    parent=self.frm_child_crud,
                    title='Cancel',
                    message='Are you sure you want to cancel?')
        if decision:
            self.clear_fields()
            self.frm_child_crud.grid_forget()
            self.show_frm()

    def validate_fields(self):
        if len(self.txt_name.get()) == 0:
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Missing information',
                message='You must insert a name for the {}'.format(
                    self.title.lower()))
            return False
        if len(self.txt_surname.get()) == 0:
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Missing information',
                message='You must insert a surname for the {}'.format(
                    self.title.lower()))
            return False
        if len(self.txt_email.get()) == 0:
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Missing information',
                message='You must insert an e-mail for the {}'.format(
                    self.title.lower()))
            return False
        # If updating an user
        if self.user.id != 0 and len(self.txt_old_passwd.get()) == 0:
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Missing information',
                message='You must insert the old password for the {}'.format(
                    self.title.lower()))
            return False
        if len(self.txt_passwd.get()) == 0:
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Missing information',
                message='You must insert a new password for the {}'.format(
                    self.title.lower()))
            return False
        if len(self.txt_passwd_conf.get()) == 0:
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Missing information',
                message='You must confirm the new password for the {}'.format(
                    self.title.lower()))
            return False
        if self.txt_passwd.get() != self.txt_passwd_conf.get():
            messagebox.showwarning(
                parent=self.frm_child_crud,
                title='Password field',
                message=
                'The new password you provided does not match the confirmation'
            )
            return False
        # If updating an user
        if self.user.id != 0 and self.user.password != hashlib.sha1(
                self.txt_old_passwd.get().encode()).hexdigest():
            messagebox.showwarning(parent=self.frm_child_crud,
                                   title='Old password field',
                                   message='The old password is incorrect')
            return False
        return True

    def clear_fields(self):
        self.txt_name.delete(0, END)
        self.txt_surname.delete(0, END)
        self.txt_email.delete(0, END)
        self.txt_old_passwd.delete(0, END)
        self.txt_passwd.delete(0, END)
        self.txt_passwd_conf.delete(0, END)
        self.lbl_old_passwd.grid_forget()
        self.lbl_passwd.grid_forget()
        self.lbl_passwd_conf.grid_forget()
        self.txt_old_passwd.grid_forget()
        self.txt_passwd.grid_forget()
        self.txt_passwd_conf.grid_forget()
Exemple #33
0
class GUIExample(master.Subscriber):
    def __init__(self):
        #jumbonet stuff
        self.net = master.Master()
        self.net.mainloop()
        self.output = {}  # uuid -> list of lines of output
        self.processes = {}  # uuid/iid -> remote object

        #the fugly tkinter stuff
        self.tk = Tk()
        self.input = StringVar()
        self.selection = (None, False, False
                          )  #process/remote, is_process, is_remote
        self.tv = None  # treeview
        self.dsp_global = None
        self.dsp_process = None

    def _setup(self):
        tk = self.tk
        tk.wm_title("Jumbonet GUI Example")
        tk.protocol("WM_DELETE_WINDOW", self.shutdown)

        height = 250

        # center: treeview
        self.tv = Treeview(tk)
        tv = self.tv
        tv.config(height=height)

        # treeview configuration
        tv["columns"] = ("process", "status")
        tv.column("process", width=130)
        tv.column("status", width=70)
        tv.heading("process", text="Process UUID")
        tv.heading("status", text="Status")
        tv.bind("<ButtonRelease-1>", self.row_selected)

        # right: log windows
        r_frame = Frame(tk, height=height)
        scroll = Scrollbar(r_frame)

        #the global log (top)
        self.dsp_global = TextDisplay(r_frame, width=70, height=20)
        self.dsp_global.append("Global information")

        #the process log (bottom)
        self.dsp_process = TextDisplay(r_frame, width=70, height=25)
        self.dsp_process.append("This shows output of the selected process")

        #left: entry and buttons
        self.input.set("")
        l_frame = Frame(tk, width=200, height=height)
        l = Label(l_frame, text="Start process here")
        e = Entry(l_frame, textvariable=self.input)
        buttons = Frame(l_frame)

        # buttons
        button_add = Button(buttons, text="Start", command=self.start_process)
        button_kill = Button(buttons, text="Kill", command=self.kill_process)

        # packing all of it
        # frame on left
        l.pack(side=TOP, fill=X)
        e.pack(side=TOP, fill=X)

        button_add.pack(side=LEFT)
        button_kill.pack(side=LEFT)
        buttons.pack(side=TOP, fill=X)

        # applog frame on right
        scroll.pack(side=RIGHT, fill=Y)
        self.dsp_global.pack(side=TOP, fill=X)
        self.dsp_process.pack(side=TOP, fill=X)

        # top-level pack
        l_frame.pack(side=LEFT, fill=Y, expand=False)
        tv.pack(side=LEFT, fill=Y, expand=False)
        r_frame.pack(side=LEFT, fill=Y, expand=False)

    def shutdown(self):
        self.net.shutdown()
        sys.exit(0)

    def row_selected(self, a):
        iid = self.tv.focus()
        log.debug("Selected: {}".format(iid))

        assert (iid is not None)

        # is it a remote?
        r = self.net.remotes.get(iid)
        if r is not None:
            self.selection = (r, False, True)
            return

        # is it a process?
        #the process we're already showing output from?
        if self.selection[1] and iid == self.selection[0].uuid:
            #nothing to do then
            return

        # is it another process?
        p = self.processes[iid]
        if p is not None:
            # clear the log and display whats happening on the selected process
            self.dsp_process.clear()
            lines = self.output.get(iid)
            self.dsp_process.append(lines)
            self.selection = (p, True, False)
        else:
            self.selection = (None, False, False)

    def start_process(self):
        log.debug("Selected: {}".format(self.selection))

        if not self.selection[2]:
            return

        cmd = self.input.get()

        if cmd == "type shell command here ":
            self.dsp_global.append("\nPlease type a valid shell command")
            return

        cmdargs = cmd.split(" ")
        r = self.selection[0]

        p = r.popen(cmdargs,
                    self,
                    listen_output=True,
                    listen_error=True,
                    listen_status=True)

        self.output[p.uuid] = list()
        self.processes[p.uuid] = p

        self.tv.insert(parent=self.selection[0].name,
                       index="end",
                       iid=p.uuid,
                       text=cmd,
                       values=(p.uuid, "Running"))
        self.dsp_global.append("\nStart {} as {} to {}".format(
            cmd, p.uuid, self.selection))

    def kill_process(self):
        if not self.selection[1]:
            return

        p = self.selection[0]

        if not p.alive:
            self.dsp_global.append("\nCannot kill {} has alread exited".format(
                p.uuid))
        else:
            self.dsp_global.append("\nKilling {}".format(self.selection))
            p.kill()

    def _update_process_display(self, remotename, uuid, args, lines):
        old_output = self.output.get(uuid)
        old_output.extend(lines)

        if not self.selection[1]:
            return

        # are we showing the same process already? then add them to the log
        if uuid == self.selection[0].uuid:
            self.dsp_process.append(lines)
            self.dsp_process.see(END)

    def receive_out(self, remotename, uuid, args, lines):
        self._update_process_display(remotename, uuid, args, lines)

    def receive_err(self, remotename, uuid, args, lines):
        self._update_process_display(remotename, uuid, args, lines)

    def receive_status(self, remotename, uuid, args, exitcode):
        self.dsp_global.append("\nExit {} aka {} with code".format(
            args, uuid, exitcode))
        self.tv.item(uuid, values=(uuid, "Exited ".format(exitcode)))

    #### these could also be used to get a nicer output for debugging complex testcases
    def add_host(self, remote):
        self.tv.insert("",
                       END,
                       text=remote.name,
                       iid=remote.name,
                       values=[],
                       open=True)

    def add_process(self, remote, process):
        self.processes[process.uuid] = remote
        self.tv.insert(remote.name,
                       END,
                       iid=process.uuid,
                       text=" ".join(process.args),
                       values=(process.uuid, "Running"))
Exemple #34
0
class App(ttk.Frame):
    def __init__(self, parent=None, *args, **kwargs):
        self._running = threading.Event()
        self._stop = threading.Event()
        self._stop.clear()

        self.init_UI(parent)
        self.init()

    def init_UI(self, parent=None):
        ttk.Frame.__init__(self, parent)
        self.parent = parent

        '''
        ### Frame setting
        '''
        self.frame_l = Frame(self.parent)
        self.frame_l.grid(row=0, column=0, padx=1, pady=1, sticky='NSWE')

        self.frame_r = Frame(self.parent)
        self.frame_r.grid(row=0, column=1, padx=1, pady=1, sticky='NSWE')
        Grid.rowconfigure(self.frame_r, 0, weight=1)
        Grid.columnconfigure(self.frame_r, 0, weight=1)

        '''
        ### setting_panel
        '''
        self.setting_panel = ttk.LabelFrame(self.frame_l, text=u"设置")
        self.setting_panel.grid(column=0, row=0, padx=5, pady=0)

        self.add_btn = Button(
            self.setting_panel, text=u"添加",
            command=self.add_btn_click, bg='#2E8B57')
        self.add_btn.grid(row=0, column=2, padx=1, pady=5, sticky='NWSE')

        self.new_url = StringVar()
        self.entry_new_url = Entry(
            self.setting_panel, textvariable=self.new_url)
        self.entry_new_url.grid(row=0, column=0, pady=5, columnspan=2, sticky='NWSE')

        Label(self.setting_panel, text=u'刷新频率(秒):').grid(
            row=1, column=0, padx=0, pady=5, sticky='NWSE')

        self.set_btn = Button(
            self.setting_panel, text=u"设置",
            command=self.set_btn_click, bg='#2E8B57')
        self.set_btn.grid(row=1, column=2, pady=5, sticky='NWSE')

        self.refresh_delay = StringVar()
        self.entry_refresh_delay = Entry(
            self.setting_panel, textvariable=self.refresh_delay)
        self.entry_refresh_delay.grid(row=1, column=1, pady=5, sticky='NWSE')
        self.refresh_delay.set('60')

        '''
        ### control_panel
        '''
        self.control_panel = ttk.LabelFrame(self.frame_l, text=u"操作")
        self.control_panel.grid(column=0, row=1, padx=5, pady=0, sticky='NWSE')
        Grid.columnconfigure(self.control_panel, 0, weight=1)

        self.displayed_msg = StringVar()
        self.displayed_msg.set(u'正在初始化...')
        self.label = Label(self.control_panel, textvariable=self.displayed_msg, bg='#AAAAAA')
        self.label.grid(row=0, column=0, padx=1, pady=5, rowspan=2, sticky='NWSE')

        self.start_btn = Button(
            self.control_panel, text=u"开始",
            command=self.start_btn_click, bg='#2E8B57')
        self.start_btn.grid(row=0, column=1, padx=1, pady=5, sticky='NWSE')

        self.stop_btn = Button(
            self.control_panel, text=u"停止",
            command=self.stop_btn_click, bg='#2E8B57')
        self.stop_btn.grid(row=1, column=1, padx=1, pady=5, sticky='NWSE')

        '''
        ### Treeview
        '''
        self.tree = Treeview(
            self.frame_r,
            columns=['c1', 'c2', 'c3'],
            displaycolumns=['c1', 'c2'],
            selectmode='browse',
        )

        #  设置每列宽度和对齐方式
        self.tree.column('#0', anchor='center', width=60)
        self.tree.column('c1', anchor='w')
        self.tree.column('c2', anchor='center', width=80)
        self.tree.column('c3', anchor='center')

        #  设置每列表头标题文本
        self.tree.heading('c1', text=u'视频名称')
        self.tree.heading('c2', text=u'发布时间')
        self.tree.heading('c3', text=u'url')

        self.tree.grid(row=0, column=0, sticky='NSWE')

        # ----vertical scrollbar------------
        self.vbar = ttk.Scrollbar(
            self.frame_r, orient=VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.vbar.set)
        self.vbar.grid(row=0, column=1, sticky='NS')

        '''
        #  定义并绑定Treeview组件的鼠标单击事件
        '''
        menu = Menu(self.frame_r, tearoff=0)
        menu.add_command(label=u"删除选中行", command=self.delete)
        def treeviewDoubleClick(event):
            '''
            如果是根结点,打开个人主页
            如果是子节点,打开视频页面
            '''
            webbrowser.open(
                self.tree.item(self.tree.selection()[0], "values")[2])

            if self.tree.tag_has('unread', self.tree.selection()[0]):
                self.tree.item(
                    self.tree.selection()[0],
                    image=image_old,
                    tag=['root', 'read'])

        def treeviewOpen(event):
            '''
            如果是根结点,打开个人主页
            如果是子节点,打开视频页面
            '''
            if self.tree.tag_has('unread', self.tree.selection()[0]):
                self.tree.item(
                    self.tree.selection()[0],
                    image=image_old,
                    tag=['root', 'read']
                )

        def treeviewPopupmenu(event):
            menu.post(event.x_root, event.y_root)

        self.tree.bind('<Double-1>', treeviewDoubleClick)
        self.tree.bind('<<TreeviewOpen>>', treeviewOpen)
        self.tree.bind('<Button-3>', treeviewPopupmenu)


    def init(self):
        if not os.path.exists(DATA_PATH):
            os.makedirs(DATA_PATH)

        if not os.path.exists(CONF_PATH):
            os.makedirs(CONF_PATH)

        self.data_list = []
        files = os.listdir(DATA_PATH)
        for file in files:
            with open('%s%s' %(DATA_PATH, file), 'r') as f:
                data = json.load(f)
                self.new_watcher(json.dumps(data))

        if os.path.exists(CONF_FILE):
            with open(CONF_FILE, 'r') as f:
                try:
                    self.refresh_delay.set(json.load(f)['wait_time'])
                except:
                    pass

        self.p = threading.Thread(target=self.run)
        self.delay = int(self.refresh_delay.get())

        self.status_audit()

    def new_watcher(self, data):
        logging.info('new_watcher')
        logging.info(data)
        info = json.loads(data)
        try:
            self.tree.insert('', 'end',
                             info['u_id'],
                             text=info['u_name'],
                             image=image_old,
                             values=['', '', info['url']],
                             tag=['root', 'read'])
            self.data_list.append(info)
        except Exception, ex:
            logging.error(ex)