class PopupFrameView(Toplevel): # СОРТИРОВКА ФИЛЬМОВ;
    def __init__(self, x, y, *data):
        super().__init__()
        self.x = x
        self.y = y
        self.vr = data
        self.init_frame()
        self.db = db
        self.view = appl
        self.view_record()

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

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

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

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

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

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

    def view_record(self): # ПРОСМОТР ОТСОРТИРОВАННЫХ ДАННЫХ;
        num = 0
        if (self.vr[0][0] != '' and self.vr[0][1] == '' and self.vr[0][2] == ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE mors=? ''', (self.vr[0][0], ))
        if (self.vr[0][0] == '' and self.vr[0][1] != '' and self.vr[0][2] == ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE janr=? ''', (self.vr[0][1], ))
        if (self.vr[0][0] == '' and self.vr[0][1] == '' and self.vr[0][2] != ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE flag=? ''', (self.vr[0][2], ))
        if (self.vr[0][0] != '' and self.vr[0][1] != '' and self.vr[0][2] != ''):
            self.db.c.execute(''' SELECT id, name FROM films WHERE mors=? AND janr=? AND flag=? ''', (self.vr[0][0], self.vr[0][1], self.vr[0][2]))
        [ self.tree.delete(i) for i in self.tree.get_children() ]
        for row in self.db.c.fetchall():
            [ self.tree.insert('', 'end', values=row) ]
            num += 1
        self.count['text'] = 'Количество записей: %d' % num
Esempio n. 2
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()
Esempio n. 3
0
class PreviewDataTable:
    """
    PreviewDataTable
    show the user the head of the data that they have imported
    @methods:
    ----------
    update_table: remove column names and rows, get column names from ImportDataManager, append data to each row
    Problem: treeview is resizing to the width of the screen size, when it's told explcitly not to (stretch=False)
    """
    def __init__(self, mainframe):
        self.mainframe = mainframe
        self.treeview = Treeview(mainframe.root)
        self.treeview['columns'] = ("column 1", "column 2", "column 3",
                                    "column 4", "column 5")
        self.treeview['show'] = 'headings'  # removes empty identifier column
        for column in self.treeview['columns']:
            self.treeview.heading(column, text=str(column), anchor="w")
            self.treeview.column(column,
                                 anchor="center",
                                 width=80,
                                 stretch=False)
        for i in range(5):
            self.treeview.insert('', 'end')
            self.treeview.bind('<Button-1>', self.handle_click)

    def update_table(self, dataframe=None):
        if isinstance(dataframe, pd.DataFrame) or isinstance(
                self.mainframe.importExportDataManager.get_data(),
                pd.DataFrame):
            # delete everything from treeview
            for child in self.treeview.get_children():
                self.treeview.delete(child)
            # create columns
            self.treeview[
                'columns'] = self.mainframe.importExportDataManager.get_column_names(
                )
            for column in self.treeview['columns']:
                self.treeview.heading(column,
                                      text=str(column),
                                      anchor="center")
                self.treeview.column(column,
                                     anchor="center",
                                     width=80,
                                     stretch=False)

            # insert data from head of pandas dataframe
            if dataframe is None and self.mainframe.importExportDataManager.get_data(
            ) is not None:
                df = self.mainframe.importExportDataManager.get_data().copy()
            else:
                df = dataframe.copy()
            self.format_data(df)
            for i, j in df.head().iterrows():
                append_data = []
                for k in j:
                    append_data.append(k)
                self.treeview.insert('', 'end', value=append_data)

    def format_data(self, df):
        if isinstance(df, pd.DataFrame):
            for column in df.columns:
                if df[column].dtype == "float64":
                    df[column] = df[column].round(decimals=int(
                        self.mainframe.optionsWindow.settings.get(
                            "decimal places")))

    # makes columns unresizeable
    def handle_click(self, event):
        if self.treeview.identify_region(event.x, event.y) == "separator":
            return "break"
Esempio n. 4
0
class SearchApplication(GenericFrame):
    FAVICON = "../assets/favicon.ico"

    def __init__(self, parent=None, app_window=None):
        self.lastValue = None
        self.category_option = StringVar("")
        self.column_id = [
            'ProductDescription', 'ManufacturerName', 'ManufacturerPartNumber',
            'DigiKeyPartNumber', 'Category'
        ]
        Frame.__init__(self, parent)
        self.pack()
        self.parent = parent
        self.app_window = app_window
        self.selectedField = None

        self.parent.title("Partlocater - Advanced Database Search")
        self.parent.iconbitmap(self.FAVICON)
        self.menubar = Frame(self, background='white')

        self.menubar.pack(side=TOP, fill=X, expand=YES)
        self.win_frame = Frame(self)
        self.win_frame.pack(side=TOP, fill=BOTH, expand=YES)
        self.editbutton = Menubutton(self.menubar,
                                     text='Edit',
                                     background='grey98')
        self.editbutton.pack(side=LEFT, fill=X)
        self.editmenu = Menu(self.editbutton, tearoff=0)
        self.editbutton.config(menu=self.editmenu)
        self.copySourcesMenu = Menu(self.editbutton, tearoff=0)
        self.editmenu.add_cascade(label='Copy', menu=self.copySourcesMenu)
        self.copySourcesMenu.add_command(label='Part Number',
                                         state=DISABLED,
                                         command=self.on_copy_partnumber)
        self.partnumber_index = 0
        self.copySourcesMenu.add_command(label='Selected Parameter',
                                         state=DISABLED,
                                         command=self.on_copy_parameters)
        self.selectedParameter_index = 1
        self.copySourcesMenu.add_command(label='Selected Part All Parameters',
                                         state=DISABLED,
                                         command=self.on_copy_all_parameters)
        self.allParameters_index = 2
        self.editmenu.add_command(label='Delete Part',
                                  state=DISABLED,
                                  command=self.on_delete)

        self.searchLF = LabelFrame(self.win_frame, text="Search")
        self.searchLF.pack(side=LEFT, fill=X, expand=YES, pady=4, padx=6)
        self.searchLeftF = Frame(self.searchLF)
        self.searchLeftF.pack(side=LEFT, anchor=W)
        self.searchRightF = Frame(self.searchLF)
        self.searchRightF.pack(side=LEFT, anchor=N)
        self.searchLabelWidth = 20
        self.catF = Frame(self.searchLeftF)
        self.catF.pack(side=TOP, anchor=W)
        self.catL = Label(self.catF,
                          text='Category',
                          width=self.searchLabelWidth,
                          anchor=W,
                          justify=LEFT)
        self.catL.pack(side=LEFT, fill=X, expand=YES)
        self.cat = StringVar()
        self.catE = Entry(self.catF,
                          textvariable=self.cat,
                          width=50,
                          state=DISABLED)
        self.catE.config(disabledbackground=self.catE.cget("bg"))
        self.catE.config(disabledforeground=self.catE.cget("fg"))
        self.catE.pack(side=LEFT, fill=X, expand=YES, pady=4)
        self.category_option = StringVar()
        self.cat.set("All")
        option_list = ['All', 'All'] + Config().tables
        self.catM = OptionMenu(self.searchRightF,
                               self.category_option,
                               *option_list,
                               command=self.on_category)
        self.catM.pack(side=TOP, anchor=N, fill=X, expand=YES)

        self.manF = Frame(self.searchLeftF)
        self.manF.pack(side=TOP, anchor=W)
        self.manL = Label(self.manF,
                          text='ManufacturerName',
                          width=self.searchLabelWidth,
                          anchor=W,
                          justify=LEFT)
        self.manL.pack(side=LEFT, fill=X, expand=YES, pady=4)
        self.man = StringVar()
        self.manE = Entry(self.manF, width=50, textvariable=self.man)
        self.manE.pack(side=LEFT, fill=X, expand=YES, pady=4)

        self.mpnF = Frame(self.searchLeftF)
        self.mpnF.pack(side=TOP, anchor=W)
        self.mpnL = Label(self.mpnF,
                          text='ManufacturerPartNumber',
                          width=self.searchLabelWidth,
                          anchor=W,
                          justify=LEFT)
        self.mpnL.pack(side=LEFT, fill=X, expand=YES, pady=4)
        self.mpn = StringVar()
        self.mpnE = Entry(self.mpnF, width=50, textvariable=self.mpn)
        self.mpnE.pack(side=LEFT, fill=X, expand=YES, pady=4)

        self.spnF = Frame(self.searchLeftF)
        self.spnF.pack(side=TOP, anchor=W)
        self.spnL = Label(self.spnF,
                          text='DigiKeyPartNumber',
                          width=self.searchLabelWidth,
                          anchor=W,
                          justify=LEFT)
        self.spnL.pack(side=LEFT, fill=X, expand=YES, pady=4)
        self.spn = StringVar()
        self.spnE = Entry(self.spnF, width=50, textvariable=self.spn)
        self.spnE.pack(side=LEFT, fill=X, expand=YES, pady=4)

        self.descF = Frame(self.searchLeftF)
        self.descF.pack(side=TOP, anchor=W)
        self.descL = Label(self.descF,
                           text='ProductDescription',
                           width=self.searchLabelWidth,
                           anchor=W,
                           justify=LEFT)
        self.descL.pack(side=LEFT, fill=X, expand=YES, pady=4)
        self.desc = StringVar()
        self.descE = Entry(self.descF, width=50, textvariable=self.desc)
        self.descE.pack(side=LEFT, fill=X, expand=YES, pady=4)
        self.descE.focus_force()

        self.findF = Frame(self.searchLeftF)
        self.findF.pack(side=TOP, anchor=E)
        self.findB = ttk.Button(self.findF,
                                text="Find",
                                width=12,
                                command=lambda event=None: self.do_find(event))
        self.findB.pack(side=LEFT, pady=4)
        self.clearB = ttk.Button(self.findF,
                                 text="Clear",
                                 width=6,
                                 command=self.on_clear_search)
        self.clearB.pack(side=LEFT, pady=4)

        self.partsLF = LabelFrame(self, text="Found Components")
        self.partsLF.pack(side=TOP, fill=X, expand=YES, pady=4, padx=4)
        self.partsF = Frame(self.partsLF)
        self.partsF.pack(side=TOP, pady=4, padx=4)
        # change treeview for search here
        self.partsTV = Treeview(self.partsF,
                                selectmode=BROWSE,
                                show='tree headings',
                                columns=self.column_id)

        self.partsTV.bind('<Double-Button-1>', self.on_edit_item)
        self.partsTV.bind('<<TreeviewSelect>>', self.fieldChanged)
        self.partsTV.bind('<Escape>', self.clearSelection)
        self.partsTV.bind('<MouseWheel>', self.mousewheel)
        self.partsTV.bind('<Button-4>', self.mousewheel)
        self.partsTV.bind('<Button-5>', self.mousewheel)
        vcmd = (self.register(self.validateEntry), '%P')
        self.editfield = ttk.Entry(self.partsTV,
                                   validate='key',
                                   validatecommand=vcmd)
        self.editfield.bind('<Return>', self.updateField)
        self.editfield.bind('<Escape>', self.clearSelection)

        self.partsTV.bind('<Control-c>', self.on_copy_element)
        self.partsTV.column("#0", minwidth=0, width=18, stretch=NO)
        for t in self.column_id:
            self.partsTV.heading(t, text=Config().parameter[t])
        self.partsTV.column('Category', width=60)
        self.scrollbar = Scrollbar(self.partsF,
                                   orient='vertical',
                                   command=self.partsTV.yview)
        self.scrollbar.pack(side=RIGHT, fill=Y, expand=YES, anchor=E)
        self.partsTV.configure(yscroll=self.scrollbar.set)
        self.scrollbar.config(command=self.yview)

        self.partsTV.pack(side=TOP, anchor=W, fill=X, expand=YES)
        self.partsTV.delete(*self.partsTV.get_children())
        # end change of treeview
        # change the following to menu item
        #self.part_buttonF = Frame(self.partsLF)
        #self.delete_partB = ttk.Button(self.partsLF, text="Delete Part from Database", command=self.on_delete,
        #state=DISABLED)
        #self.delete_partB.pack(side=RIGHT, anchor=W, expand=NO, pady=4, padx=6)
        #self.partsB = ttk.Button(self.partsLF, text="Copy Selected To Part Find", command=self.on_copy, state=DISABLED)
        #self.partsB.pack(side=RIGHT, anchor=W, expand=NO, pady=4, padx=6)
        #self.part_buttonF.pack(side=BOTTOM)
        # start remove vvv
        #self.element_labelframe = LabelFrame(self, text="Modify Name/Value")
        #self.element_labelframe.pack(side=TOP, fill=X, expand=YES, pady=4, padx=6)
        #self.element_frame = Frame(self.element_labelframe)
        #self.element_frame.pack(side=TOP)

        #self.element_name = StringVar()
        #self.element_label = Label(self.element_frame, textvariable=self.element_name, width=30, anchor=W, justify=LEFT)
        #self.element_label.pack(side=LEFT, anchor=W, fill=X, expand=YES, pady=4)
        #self.element_value = StringVar()
        #self.element_entry = Entry(self.element_frame, width=50, textvariable=self.element_value)
        #self.element_entry.pack(side=LEFT, fill=X, expand=YES, pady=4)
        #self.default_color = self.element_entry.cget('background')

        #self.element_update = ttk.Button(self.element_frame, text="Update", command=self.on_update_element,
        #state=DISABLED)
        #self.element_update.pack(side=LEFT, fill=X, expand=YES, pady=4)
        #self.element_cancel = ttk.Button(self.element_frame, text="Cancel", command=self.on_clear_element,
        #state=DISABLED)
        #self.element_cancel.pack(side=LEFT, fill=X, expand=YES, pady=4)
        # end remove ^^^

        self.statusLF = LabelFrame(self, text="Status")
        self.statusLF.pack(side=BOTTOM, fill=X, expand=YES, pady=4, padx=6)
        self.statusF = Frame(self.statusLF)
        self.statusF.pack(side=TOP, fill=X, expand=YES, padx=6)
        self.status = self.StatusBar(self.statusF, self)

    def validateEntry(self, P):
        if (len(P) <= 120):
            return True
        else:
            self.bell()
            return False

    # scroll bar event
    def yview(self, *args):
        if self.selectedField is not None:
            self.editfield.place_forget()
            self.selectedField = None
        self.partsTV.yview(*args)

    # mousewheel and button4/5 event
    def mousewheel(self, event):
        if self.selectedField is not None:
            self.editfield.place_forget()
            self.selectedField = None

    # escape event in treeview or editfield
    def clearSelection(self, event):
        self.editfield.place_forget()
        self.selectedField = None
        self.partsTV.selection_remove(self.partsTV.selection())
        self.status.set("")

    # double button event
    def on_edit_item(self, event):
        if self.partsTV.parent(self.partsTV.selection()
                               ) == '':  # testing should not edit a parent
            self.selectedField = None
            return
        if (self.partsTV.identify_region(event.x, event.y) == 'cell'):
            self.selectedField = self.partsTV.identify_row(event.y)
            x, y, width, height = self.partsTV.bbox(self.selectedField, '#2')
            v = self.partsTV.set(self.selectedField, 1)
            self.editfield.pack()
            self.editfield.delete(0, len(self.editfield.get()))
            self.editfield.insert(0, v)
            self.editfield.selection_range(0, 'end')
            self.editfield.focus_force()
            self.editfield.place(x=x, y=y, width=width, height=height)

    # find button event
    def on_find(self):
        category = self.cat.get()
        search_list = []
        col_list = []
        search_str = self.man.get()
        if not (validate(search_str)):
            raise Exception("Invalid Manufacture Name")
        search_list.append(search_str)
        col_list.append(Config().parameter['ManufacturerName'])
        search_str = self.mpn.get()
        if not (validate(search_str)):
            raise Exception("Invalid Manufacture Part Number")
        search_list.append(search_str)
        col_list.append(Config().parameter['ManufacturerPartNumber'])
        search_str = self.spn.get()
        if not (validate(search_str)):
            raise Exception("Invalid Supplier Part Number")
        search_list.append(search_str)
        col_list.append(Config().parameter['DigiKeyPartNumber'])
        search_str = self.desc.get().split()
        if not (validate(search_str)):
            raise Exception("Invalid Description")
        search_list += search_str
        col_list.append(Config().parameter['ProductDescription'])
        select = "SELECT * FROM `" + Config().loaded_db.name + "`."
        where = "WHERE"
        like = ""
        i = 0
        for item in search_list:
            if len(item) > 0:
                item = item.replace('%', '\\%')
                item = item.replace('"', '')
                item = item.replace("'", "")
                if i < 3:
                    like += where + " `" + col_list[
                        i] + "` LIKE '" + item + "%'"
                else:
                    like += where + " (`" + col_list[i] + "` LIKE '" + item + "%' OR `" + \
                            col_list[i] + "` LIKE '% " + item + "%')"
                where = " AND"
            i = i + 1 if (i < 3) else i
        self.partsTV.delete(*self.partsTV.get_children())
        count = 0
        if category == "All":
            for table in Config().tables:
                qry = select + "`" + table + "` " + like
                result = Config().loaded_db.query(qry)
                for record in result:
                    v = []
                    spn = record[Config().parameter['DigiKeyPartNumber']]
                    count += 1
                    for id in self.column_id:
                        if id == 'Category':
                            v.append(table)
                        else:
                            v.append(record[Config().parameter[id]])
                    id = self.partsTV.insert('',
                                             'end',
                                             iid=spn,
                                             text=spn,
                                             values=v)
                    for params in record:
                        if record[params] is not None:
                            self.partsTV.insert(id,
                                                'end',
                                                text=spn,
                                                values=(params,
                                                        record[params]))
        else:
            qry = select + "`" + category + "` " + like
            result = Config().loaded_db.query(qry)
            for record in result:
                v = []
                count += 1
                spn = record[Config().parameter['DigiKeyPartNumber']]
                for id in self.column_id:
                    if id == 'Category':
                        v.append(category)
                    else:
                        v.append(record[Config().parameter[id]])
                id = self.partsTV.insert('',
                                         'end',
                                         iid=spn,
                                         text=spn,
                                         values=v)
                for params in record:
                    if record[params] is not None:
                        self.partsTV.insert(id,
                                            'end',
                                            text=spn,
                                            values=(params, record[params]))
        self.status.set(("No" if count == 0 else str(count)) + " items found")

    # return event
    def updateField(self, event):
        value = self.editfield.get()
        self.editfield.place_forget()
        name = self.partsTV.item(self.selectedField, "text")
        if not validate(value):
            self.status.seterror("Invalid value, must not have quotes")
            return
        self.partsTV.set(self.selectedField, "#2", value)
        key = self.partsTV.set(self.selectedField, "#1")
        self.editfield.place_forget()
        element_parent = self.partsTV.parent(self.selectedField)
        table_name = self.partsTV.item(
            element_parent, "values")[self.column_id.index('Category')]
        part_number = self.partsTV.item(
            element_parent,
            "values")[self.column_id.index('DigiKeyPartNumber')]
        set_param = "SET `" + key + "` = '" + value + "' "
        where = "WHERE `" + Config(
        ).parameter['DigiKeyPartNumber'] + "` = '" + part_number + "'"
        qry = "UPDATE `" + Config(
        ).loaded_db.name + "`.`" + table_name + "` " + set_param + where
        print(qry)
        try:
            Config().loaded_db.query(qry)
        except Exception as e:
            self.status.seterror("Database query failed: %s", e)
            return
        self.status.set("Changed " + key + " to " + value + " for part " +
                        part_number + ".")
        self.partsTV.see(self.selectedField)

    # clear button in search frame
    def on_clear_search(self):
        self.man.set("")
        self.mpn.set("")
        self.spn.set("")
        self.desc.set("")
        self.cat.set("All")
        self.category_option.set("All")
        self.partsTV.delete(*self.partsTV.get_children())

    def do_flash(self):
        current_color = self.element_entry.cget("background")
        if current_color == self.default_color:
            self.element_entry.config(background="red")
        else:
            self.element_entry.config(background=self.default_color)
            return
        self.after(250, self.do_flash)

    # category option menu
    def on_category(self, value):
        self.catE.config(state=NORMAL)
        self.cat.set(value)
        self.catE.config(state=DISABLED)

    #def on_copy(self):
    #selected = self.partsTV.selection()[0]
    #key = self.partsTV.item(selected, "values")[self.column_id.index('DigiKeyPartNumber')]
    #self.app_window.part_num_string.set(key)
    #self.status.set("Part Number '" + key + "' copied to Part Find")
    # Edit -> Delete menu
    def on_delete(self):
        selected = self.partsTV.selection()[0]
        key = self.partsTV.item(
            selected, "values")[self.column_id.index('DigiKeyPartNumber')]
        table = self.partsTV.item(selected,
                                  "values")[self.column_id.index('Category')]
        if messagebox.askokcancel(
                "Delete", "Click OK if you really want to delete '" + key +
                "' from database?"):
            Config().loaded_db.query("DELETE FROM `" + table + "` WHERE `" +
                                     Config().parameter['DigiKeyPartNumber'] +
                                     "` = '" + key + "'")
            self.status.set("Part Number '" + key + "' deleted from database")

    # treeview select event
    def fieldChanged(self, event):
        selected = self.partsTV.selection()
        if len(selected) > 0:
            self.copySourcesMenu.entryconfig(self.partnumber_index,
                                             state=NORMAL)
            self.copySourcesMenu.entryconfig(self.allParameters_index,
                                             state=NORMAL)
        else:
            self.copySourcesMenu.entryconfig(self.partnumber_index,
                                             state=DISABLED)
            self.copySourcesMenu.entryconfig(self.allParameters_index,
                                             state=DISABLED)
            return
        if self.partsTV.parent(selected) == '':
            self.copySourcesMenu.entryconfig(self.selectedParameter_index,
                                             state=DISABLED)
        else:
            self.copySourcesMenu.entryconfig(self.selectedParameter_index,
                                             state=NORMAL)
        if selected != self.selectedField:
            self.editfield.place_forget()
            self.selectedField = None

    def on_copy_parameters(self):
        selected = self.partsTV.selection()
        if len(selected) == 0 or self.partsTV.parent(selected) == '':
            return
        try:
            property = self.partsTV.item(selected, "values")
            self.parent.clipboard_clear()
            self.parent.clipboard_append(property[0] + '\t' + property[1])
            self.parent.update()
            self.status.set(property[0] + ' ' + property[1] +
                            " copied to clipboard")
        except Exception as e:
            pass

    def on_copy_partnumber(self):
        selected = self.partsTV.selection()
        if len(selected) == 0 or self.partsTV.parent(selected) == '':
            return
        try:
            if self.partsTV.parent(selected) != '':
                selected = self.partsTV.parent(selected)
            partnumber = self.partsTV.item(
                selected, "values")[self.column_id.index('DigiKeyPartNumber')]
            self.parent.clipboard_clear()
            self.parent.clipboard_append(partnumber)
            self.parent.update()
            self.status.set(" '" + partnumber + "' copied to clipboard")
        except Exception as e:
            pass

    def on_copy_all_parameters(self):
        selected = self.partsTV.selection()
        if len(selected) == 0:
            return
        try:
            if self.partsTV.parent(selected) != '':
                selected = self.partsTV.parent(selected)
            partnumber = self.partsTV.item(
                selected, "values")[self.column_id.index('DigiKeyPartNumber')]
            elements = self.partsTV.get_children(selected)
            self.parent.clipboard_clear()
            self.parent.clipboard_clear()
            for i in elements:
                element = self.partsTV.item(i, "values")
                self.parent.clipboard_append(element[0] + "\t" + element[1] +
                                             "\n")
            self.parent.update()
            self.status.set("All properties of " + partnumber +
                            " copied to clipboard")
        except Exception as e:
            pass

        # deprecate
    def on_copy_element(self, event):
        try:
            selected = self.partsTV.selection()[0]
            if self.partsTV.parent(selected) == '':
                partnumber = self.partsTV.item
                elements = self.partsTV.get_children(selected)
                self.parent.clipboard_clear()
                for i in elements:
                    element = self.partsTV.item(i, "values")
                    self.parent.clipboard_append(element[0] + "\t" +
                                                 element[1] + "\n")
                self.parent.update()
                self.status.set("All properties of " +
                                self.partsTV.item(selected, "values")[3] +
                                " copied to clipboard")
            else:
                key = self.partsTV.item(selected, "values")[0]
                val = self.partsTV.item(selected, "values")[1]
                self.parent.clipboard_clear()
                self.parent.clipboard_append(val)
                self.parent.update()
                self.status.set(key + " '" + val + "' copied to clipboard")
        except Exception as e:
            pass

    def do_find(self, event):
        try:
            self.on_find()
        except Exception as e:
            self.status.seterror(e)
class CollectionOfFilms(Frame): # ГЛАВНЫЙ КЛАСС;
    def __init__(self, root, x, y):
        super().__init__(root)
        self.x = x
        self.y = y
        self.init_main()
        self.db = db
        self.update_records()

    def init_main(self):
        # СТИЛЬ ШРИФТА;
        font_style = ('Consolas', '12')
        
        # СТИЛЬ ТАБЛИЦ и КНОПОК в ВСПЛЫВАЮЩИХ ОКНАХ;
        Style().configure("Treeview.Heading", font=font_style, foreground='#425370')
        Style().configure('Treeview', font=font_style, foreground='#425370')
        Style().configure('TButton', font=('Consolas', '10'))
        Style().configure('TLabel', font=font_style, background='#EDF0F5', foreground='#425370')
        
        # ВЕРХНЯЯ и НИЖНЯЯ ПАНЕЛЬ для КНОПОК и ПОДСКАЗОК;
        TB_TOP = Frame(self, bg='#EDF0F5', bd=1)
        TB_BOT = Frame(self, bg='#EDF0F5', bd=1)
        TB_TOP.pack(side=TOP, fill=X)
        TB_BOT.pack(side=BOTTOM, fill=X)

        # КНОПКИ на ВЕРХНЕЙ ПАНЕЛИ;
        btn_add_ = Button(TB_TOP, text='Добавить', compound=TOP, command=self.open_dlg_add,
                          bg='#EDF0F5', activebackground='#425370', activeforeground='white',
                          width=15, height=1, font=font_style, relief=GROOVE, overrelief=GROOVE)
        btn_edit = Button(TB_TOP, text='Редактировать', compound=TOP, command=self.open_dlg_edit,
                          bg='#EDF0F5', activebackground='#425370', activeforeground='white',
                          width=15, height=1, font=font_style, relief=GROOVE, overrelief=GROOVE)
        btn_del_ = Button(TB_TOP, text='Удалить', compound=TOP, command=self.open_dlg_del,
                          bg='#EDF0F5', activebackground='#425370', activeforeground='white',
                          width=15, height=1, font=font_style, relief=GROOVE, overrelief=GROOVE)
        btn_view = Button(TB_BOT, text='Просмотр', compound=TOP, command=self.open_dlg_view,
                          bg='#EDF0F5', activebackground='#425370', activeforeground='white',
                          width=10, height=1, font=font_style, relief=FLAT, overrelief=FLAT)

        btn_add_.pack(side=LEFT)
        btn_edit.pack(side=LEFT)
        btn_del_.pack(side=RIGHT)
        btn_view.pack(side=RIGHT)

        btn_add_.bind('<Enter>', lambda event: btn_add_.configure(bg='#8E9FBD', fg='white'))
        btn_add_.bind('<Leave>', lambda event: btn_add_.configure(bg='#EDF0F5', fg='black'))
        btn_edit.bind('<Enter>', lambda event: btn_edit.configure(bg='#8E9FBD', fg='white'))
        btn_edit.bind('<Leave>', lambda event: btn_edit.configure(bg='#EDF0F5', fg='black'))
        btn_del_.bind('<Enter>', lambda event: btn_del_.configure(bg='#8E9FBD', fg='white'))
        btn_del_.bind('<Leave>', lambda event: btn_del_.configure(bg='#EDF0F5', fg='black'))
        btn_view.bind('<Enter>', lambda event: btn_view.configure(bg='#8E9FBD', fg='white'))
        btn_view.bind('<Leave>', lambda event: btn_view.configure(bg='#EDF0F5', fg='black'))

        # ВЫВОД ОШИБОК и КОЛ-ВА ЗАПИСЕЙ на НИЖНЮЮ ПАНЕЛЬ;
        self.error = Label(TB_BOT, foreground='red')
        self.count = Label(TB_BOT)
        self.error.pack(side=RIGHT)
        self.count.pack(side=LEFT)

        # ПОЛОСА ПРОКРУТКИ и ТАБЛИЦА;
        _yscroll_ = Scrollbar(self)
        self.tree = Treeview(self, columns=('id', 'name', 'mors', 'janr', 'flag'), height=20, show='headings', yscrollcommand=_yscroll_.set)
        _yscroll_.config(command=self.tree.yview)

        self.tree.column('id',   width=50,  minwidth=50, anchor=CENTER)
        self.tree.column('name', width=370, minwidth=370)
        self.tree.column('mors', width=110, minwidth=110)
        self.tree.column('janr', width=110, minwidth=110)
        self.tree.column('flag', width=140, minwidth=140)

        self.tree.heading('id',   text='№')
        self.tree.heading('name', text='Название')
        self.tree.heading('mors', text='Кино/Сериал')
        self.tree.heading('janr', text='Жанр')
        self.tree.heading('flag', text='Просмотр')

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

    def update_records(self): # ОБНОВЛЕНИЕ ДАННЫХ;
        num = 0
        self.db.c.execute(''' SELECT * FROM films ''')
        [ self.tree.delete(i) for i in self.tree.get_children() ]
        for row in self.db.c.fetchall():
            [ self.tree.insert('', 'end', values=row) ]
            num += 1
        self.count['text'] = ' Количество записей: %d' % (num)

    def add_record(self, name, mors, janr, flag): # ДОБАВЛЕНИЕ;
        if (name != ''):
            self.error['text'] = ''
            flag_record = False
            self.db.c.execute(''' SELECT name FROM films ''')
            for row in self.db.c.fetchall(): # Проверка на схожую запись;
                if (name == row[0]): flag_record = True
            if (not flag_record): self.db.add_data(name, mors, janr, flag)
            else: self.error['text'] = 'Такая запись уже существует! '
        else: self.error['text'] = 'Данные не введены в поле! '
        self.update_records()
    
    def edit_record(self, name, mors, janr, flag): # РЕДАКТИРОВАНИЕ;
        if (name != ''):
            self.error['text'] = ''
            self.db.c.execute(''' UPDATE films SET name=?, mors=?, janr=?, flag=? WHERE id=? ''',
                              (name, mors, janr, flag, self.tree.set(self.tree.selection()[0], '#1')))
        else: self.error['text'] = 'Данные не введены в поле! '
        self.db.conn.commit()
        self.update_records()

    def delete_record(self): # УДАЛЕНИЕ;
        for item in self.tree.selection():
            self.db.c.execute(''' DELETE FROM films WHERE id=? ''', (self.tree.set(item)['id'],))
        self.db.conn.commit()
        self.update_records()

    def open_dlg_add(self): # ОТКРЫВАЕМ ОКНО ДОБАВЛЕНИЯ;
        self.error['text'] = ''
        AddData(self.x, self.y)

    def open_dlg_edit(self): # ОТКРЫВАЕМ ОКНО РЕДАКТИРОВАНИЯ;
        if self.tree.selection():
            self.error['text'] = ''
            EditData(self.x, self.y, self.tree.item(self.tree.selection()[0])['values'][1])
        else: self.error['text'] = 'Не выбрана запись для редактирования! '

    def open_dlg_del(self): # ОТКРЫВАЕМ ОКНО УДАЛЕНИЯ;
        if (self.tree.selection()):
            self.error['text'] = ''
            DeleteData(self.x, self.y)
        else: self.error['text'] = 'Нет записей для удаления! '

    def open_dlg_view(self): # ОТКРЫВАЕМ ОКНО ПРОСМОТРА;
        self.error['text'] = ''
        SelectForViewRecords(self.x, self.y)