Beispiel #1
0
 def processPackets(self):
     newPacket = self.parser.getPacket()
     while newPacket:
         Logger.debug("[REALM] >> " + newPacket)
         DatabaseManager().addPacket(1, newPacket)
         data = bytearray(newPacket.encode("utf-8"))
         data += b'\x00'
         if self.remoteServer.send(data) == False:
             self.fd.close()
             Logger.info("[REALM] Client " + self.ip + ":" + self.port + " disconnected")
             return (False)
         newPacket = self.parser.getPacket()
     return (True)
Beispiel #2
0
 def processPackets(self):
     newPacket = self.parser.getPacket()
     while newPacket:
         Logger.debug("[GAME] << " + newPacket)
         DatabaseManager().addPacket(0, newPacket)
         data = bytearray(newPacket.encode("utf-8"))
         data += b'\x00'
         if self.localClient.send(data) == False:
             self.socket.close()
             Logger.info("[GAME] Server disconnected")
             return (False)
         newPacket = self.parser.getPacket()
     return (True)
Beispiel #3
0
class FunctionController:
    def __init__(self, rootWindow, database, backEvent, year):
        self.rootWindow = rootWindow
        self.backEvent = backEvent
        self.database = database
        self.year = year
        # Start logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("FunctionController logger has started.")

        self.functionWindow = Toplevel(self.rootWindow)
        self.functionWindow.title("Check a book.")
        self.functionWindow.protocol('WM_DELETE_WINDOW', self.goBack)
        self.functionWindow.bind("<<back>>", lambda _: self.backEvent())

        self.data = self.database.findBestBook(self.year)
        values = self.database.executeStatement(
            f"SELECT * FROM `ksiazki` WHERE `tytul` = '{self.data[0][0][0]}'")
        self.finalData = dict()
        self.finalData["Title"] = values[0][1]
        self.finalData["Date"] = str(values[0][2])
        self.finalData["Genre"] = values[0][3]
        self.finalData["Amount"] = self.data[1][0][0]

        self.mainFrame = Frame(self.functionWindow,
                               bd=4,
                               relief=RAISED,
                               width=self.functionWindow.winfo_width(),
                               height=self.functionWindow.winfo_height())
        self.mainFrame.pack(fill='both', side=TOP)

        titleLabel = Label(self.mainFrame,
                           text=f"Most hired book in year {year} is..",
                           font=("Arial Bold", 18))
        titleLabel.grid(row=0, column=0, columnspan=3, padx=40, pady=20)

        rowNo = 1
        for no, val in self.finalData.items():
            l1 = Label(self.mainFrame,
                       text=f"{no}: {val}",
                       font=("Arial Bold", 14))
            l1.grid(row=rowNo, column=0, columnspan=3, padx=10, pady=10)
            rowNo += 1

    def goBack(self):
        self.functionWindow.event_generate("<<back>>")
Beispiel #4
0
 def parsePacket(self, packet):
     if len(packet) > 3 and packet[0] == 'A' and packet[
             1] == 'X' and packet[2] == 'K':
         Logger.debug("[REALM] onSelectServer packet detected!")
         encryptedIp = packet[3:11]
         encryptedPort = packet[11:14]
         ticket = packet[14:]
         decryptedIp = CipherManager.decryptIp(encryptedIp)
         decryptedPort = CipherManager.decryptPort(encryptedPort)
         newGameClient = GameLocalClient(decryptedIp, decryptedPort)
         newGameClient.listen()
         newEncryptedIp = CipherManager.encryptIp(
             newGameClient.getListeningIp())
         newEncryptedPort = CipherManager.encryptPort(
             newGameClient.getListeningPort())
         newPacket = "AXK" + newEncryptedIp + newEncryptedPort + ticket
         Logger.debug("[REALM] Replacing packet '" + packet +
                      "' with packet '" + newPacket + "'")
         newGameClient.start()
         return (newPacket)
     return (packet)
Beispiel #5
0
class TableController:
    """ Class that contains all methods to handle with choosen table menu with
    following functionality: add, modify, delete record, sort by columns, find record"""
    def __init__(self, tableName, database, themeWindow, returnEvent):
        self.tableName = tableName
        self.database = database
        self.themeWindow = themeWindow
        # Start logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("TableController logger has started.")

        self.addWindow = None
        self.modifyWindow = None

        self.columnNames = self.database.getColumns(tableName)
        self.tableData = self.database.getRawData(tableName)
        self.data = self.database.getData(tableName)
        self.model = TableModel()

        if len(self.data) == 0:
            messagebox.showwarning("Empty table", "This table has no records!")
            self.data["_"] = dict()
            self.data["_"]["_"] = "Empty table"
        else:
            for key, records in self.data.items():
                for col, value in records.items():
                    if isinstance(value, datetime.date):
                        self.data[key][col] = str(value)
        self.model.importDict(self.data)

        # Widgets
        self.content = Frame(self.themeWindow,
                             bg="#B7B9B8",
                             bd=4,
                             relief=RAISED,
                             width=self.themeWindow.winfo_width() - 80,
                             height=self.themeWindow.winfo_height() - 80)
        self.content.place(x=40, y=40)
        self.content.grid(row=0, column=0)
        self.content.bind("<<goback>>", lambda _: returnEvent(None))
        self.content.update()

        # Canvas with options menu
        self.topCanvas = Canvas(self.content,
                                bg="white",
                                bd=1,
                                relief=RAISED,
                                width=int(self.content.winfo_width()),
                                height=int(self.content.winfo_height() / 12))
        self.topCanvas.pack(fill='both', side=TOP)

        self.backButton = Button(self.topCanvas,
                                 text=" < ",
                                 command=self.back,
                                 width=9)
        self.backButton.pack(fill='both', side=LEFT)
        self.showButton = Button(self.topCanvas,
                                 text="Refresh table",
                                 command=self.refreshTable,
                                 width=22)
        self.showButton.pack(fill='both', side=LEFT)

        # Canvas with data
        self.middleFrame = Frame(self.content)
        self.middleFrame.pack(fill='both', side=TOP)
        self.table = CustomTable(self.middleFrame, model=self.model)
        self.table.show()

        # Canvas with DML buttons
        self.bottomCanvas = Canvas(self.content,
                                   bg="white",
                                   bd=1,
                                   relief=FLAT,
                                   width=int(self.content.winfo_width()),
                                   height=int(self.content.winfo_height() / 5))
        self.bottomCanvas.pack(fill='both', side=TOP)
        self.buttonAdd = Button(self.bottomCanvas,
                                text=" ADD ",
                                command=self.add,
                                width=24,
                                height=3,
                                bd=5)
        self.buttonAdd.pack(side=LEFT)
        self.buttonModify = Button(self.bottomCanvas,
                                   text=" MODIFY ",
                                   command=self.modify,
                                   width=25,
                                   height=3,
                                   bd=5)
        self.buttonModify.pack(side=LEFT)
        self.buttonDelete = Button(self.bottomCanvas,
                                   text=" DELETE ",
                                   command=lambda: self.delete(self.tableName),
                                   width=25,
                                   height=3,
                                   bd=5)
        self.buttonDelete.pack(side=LEFT)

    def back(self):
        """ Go back to main window """
        self.content.event_generate("<<goback>>")

    def backEvent(self, event):
        if self.addWindow is not None:
            self.addWindow.addWindow.destroy()
            self.addWindow = None
        if self.modifyWindow is not None:
            self.modifyWindow.modifyWindow.destroy()
            self.modifyWindow = None
        self.refreshTable()

    def add(self):
        """ Go to add window """
        if self.addWindow is None:
            self.logger.debug("Starting add window.")
            self.addWindow = AddController(self.themeWindow, self.tableName,
                                           self.database, self.backEvent)

    def modify(self):
        """ Go to modify window """
        if self.table.startrow != self.table.endrow:
            messagebox.showwarning('Modify error',
                                   'Please select only one record!')
        else:
            selectedRow = self.table.currentrow
            if self.modifyWindow is None:
                self.logger.debug("Starting modify window.")
                self.modifyWindow = ModifyController(
                    self.themeWindow, self.tableName, self.database,
                    self.model.getRecName(selectedRow), self.data,
                    self.backEvent)

    def delete(self, tableName):
        """ Delete selected records """
        for no, i in enumerate(self.table.multiplerowlist):
            recName = self.model.getRecName(i)
            deletedRecord = list()
            for column, value in self.data[recName].items():
                deletedRecord.append(value)
            try:
                self.database.deleteRecord(tableName, deletedRecord)
            except Exception as e:
                self.logger.error(
                    f"Can not delete selected records! Error = {e}")
                errorNo = int(e.__str__().split()[0][1:-1])
                if errorNo == 1451:
                    messagebox.showerror(
                        "Can not delete selected records!",
                        f"There are bounds including selected record.")
                else:
                    messagebox.showerror("Can not delete selected records!",
                                         f"Error {e}")

                return
        confirm = messagebox.askyesno(
            "Deleting record confirmation",
            f"Are You sure that You want to delete {len(self.table.multiplerowlist)} records?"
        )
        if confirm:
            self.database.connection.commit()
        else:
            self.database.connection.rollback()
        self.model.createEmptyModel()
        self.refreshTable()
        return

    def refreshTable(self):
        self.data = self.database.getData(self.tableName)
        if len(self.data) == 0:
            messagebox.showwarning("Empty table", "This table has no records!")
            self.data["_"] = dict()
            self.data["_"]["_"] = "Empty table"
        else:
            for key, records in self.data.items():
                for col, value in records.items():
                    if isinstance(value, datetime.date):
                        self.data[key][col] = str(value)
        self.model.importDict(self.data)
        self.table.redraw()
Beispiel #6
0
class ModifyController:
    def __init__(self, themeWindow, tableName, database, selectedRecord, data,
                 backEvent):
        self.themeWindow = themeWindow
        self.tableName = tableName
        self.database = database
        self.selectedRecord = selectedRecord
        self.data = data
        self.backEvent = backEvent
        # Start logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("ModifyController logger has started.")

        self.modifyWindow = Toplevel(self.themeWindow)
        self.modifyWindow.title("Modify an existing record.")
        self.modifyWindow.protocol('WM_DELETE_WINDOW', self.goBack)
        self.modifyWindow.bind("<<back>>", lambda _: self.backEvent(None))

        self.helpWindow = None

        self.newRecord = list()
        self.emptyCols = 0
        self.emptyButton = IntVar()

        self.colNames = self.database.getColumns(self.tableName)
        self.colTypes = self.database.getColumnTypes(self.tableName)
        self.colKeys = self.database.getColumnKeys(self.tableName)
        self.colNulls = self.database.getColumnNullable(self.tableName)
        self.colConstraints = self.database.getTableCheckConstraint(
            self.tableName)
        print(f"DEBUG = {self.colConstraints}")
        self.colFrame = Frame(self.modifyWindow,
                              bd=4,
                              relief=RAISED,
                              width=self.themeWindow.winfo_width(),
                              height=self.themeWindow.winfo_height() - 40)
        self.colFrame.pack(fill='both', side=TOP)

        self.entries = list()

        if self.tableName in ["wlasciciel_biblioteka"]:
            for no, col in enumerate(self.colNames):
                Label(self.colFrame, text=col,
                      font=("Arial Bold", 12)).grid(row=no, column=0)
                combo = ttk.Combobox(self.colFrame,
                                     values=self.initComboValues(
                                         self.tableName, col[0]))
                combo.grid(row=no, column=1, columnspan=2, padx=20, pady=10)
                if data[self.selectedRecord][col[0]] is not None:
                    combo.set(data[self.selectedRecord][col[0]])
                self.entries.append(combo)

        elif self.tableName in ["autor_ksiazka"]:
            for no, col in enumerate(self.colNames):
                Label(self.colFrame, text=col,
                      font=("Arial Bold", 12)).grid(row=no, column=0)
                vals = self.initComboValues(self.tableName, col[0])
                combo = ttk.Combobox(self.colFrame, values=vals)
                combo.grid(row=no, column=1, columnspan=2, padx=20, pady=10)
                valueHelper = Button(
                    self.colFrame,
                    text="?",
                    command=lambda b=col[0], c=combo: self.showHelp(b, c))
                valueHelper.grid(row=no, column=3)
                if data[self.selectedRecord][col[0]] is not None:
                    combo.set(data[self.selectedRecord][col[0]])
                self.entries.append(combo)

        else:
            for no, col in enumerate(self.colNames):
                if col[0][-2:] == "id" and self.colKeys[col[0]][0] == 'PRI':
                    self.emptyCols += 1
                    continue
                if self.colKeys[col[0]][0] == 'PRI':
                    _text = self.colNames[no][0] + "*"
                else:
                    _text = self.colNames[no][0]
                Label(self.colFrame, text=_text,
                      font=("Arial Bold", 12)).grid(row=no, column=0)
                if self.colTypes[col[0]] == 'date':
                    entry = DateEntry(self.colFrame, date_pattern='y/mm/dd')
                    entry.grid(row=no,
                               column=1,
                               columnspan=2,
                               padx=20,
                               pady=10)
                    if self.colNulls[col[0]] == 'YES':
                        emptyButton = Checkbutton(self.colFrame,
                                                  text="Empty",
                                                  variable=self.emptyButton,
                                                  command=self.clicked)
                        emptyButton.grid(row=no, column=3)
                        self.emptyDate = entry
                else:
                    if self.colKeys[col[0]][0] == 'MUL':
                        vals = self.database.executeStatement(
                            f"SELECT {self.colKeys[col[0]][2]} FROM {self.colKeys[col[0]][1]}"
                        )
                        entry = ttk.Combobox(self.colFrame, values=vals)
                        entry.grid(row=no,
                                   column=1,
                                   columnspan=2,
                                   padx=20,
                                   pady=10)
                    else:
                        if col[0] in self.colConstraints.keys():
                            entry = ttk.Combobox(
                                self.colFrame,
                                values=self.colConstraints[col[0]])
                        else:
                            entry = Entry(self.colFrame, width=20)
                        entry.grid(row=no,
                                   column=1,
                                   columnspan=2,
                                   padx=20,
                                   pady=10)

                if data[self.selectedRecord][col[0]] is not None:
                    if self.colTypes[col[0]] == 'date':
                        entry.set_date(data[self.selectedRecord][col[0]])
                    else:
                        entry.insert(END, data[self.selectedRecord][col[0]])
                self.entries.append(entry)

        self.oldRecord = list()
        for entry in self.entries:
            self.oldRecord.append(entry.get())

        if self.emptyCols > 0:
            if self.tableName == "pracownicy":
                self.oldRecord.insert(
                    0,
                    self.database.executeStatement(
                        f"SELECT `{self.colNames[0][0]}` FROM `{self.tableName}`"
                        +
                        f"WHERE `{self.colNames[2][0]}` = \"{self.oldRecord[1]}\" AND"
                        + f"`{self.colNames[3][0]}` = \"{self.oldRecord[2]}\"")
                    [0][0])

            else:
                self.oldRecord.insert(
                    0,
                    self.database.executeStatement(
                        f"SELECT `{self.colNames[0][0]}` FROM `{self.tableName}`"
                        +
                        f"WHERE `{self.colNames[1][0]}` = \"{self.oldRecord[0]}\" AND"
                        + f"`{self.colNames[2][0]}` = \"{self.oldRecord[1]}\"")
                    [0][0])

        self.buttonFrame = Frame(self.modifyWindow,
                                 bd=4,
                                 relief=RAISED,
                                 width=self.themeWindow.winfo_width(),
                                 height=40)
        self.buttonFrame.pack(fill='both', side=TOP)
        self.addButton = Button(self.buttonFrame,
                                text="Modify",
                                command=self.checkEntry)
        self.addButton.pack(side=LEFT)
        self.cancelButton = Button(self.buttonFrame,
                                   text="Cancel",
                                   command=self.goBack)
        self.cancelButton.pack(side=LEFT)

    def clicked(self):
        if self.emptyButton.get() == 0:
            self.emptyDate.configure(state='enabled')
        else:
            self.emptyDate.configure(state='disabled')

    def checkEntry(self):
        self.newRecord.clear()
        for i in range(self.emptyCols):
            self.newRecord.append("")
        for entry in self.entries:
            value = entry.get()
            if len(value) == 10 and value[4] == "/" and value[7] == "/":
                value = value.replace("/", "-", 2)
            self.newRecord.append(value)
        for no, col in enumerate(self.colNulls.values()):
            if col == 'YES':
                if self.emptyButton.get() == 1:
                    self.newRecord[no] = ""

        if self.emptyCols == 1:
            self.newRecord[0] = self.oldRecord[0]

        if self.tableName == "autorzy" and self.database.executeStatement(
                f"SELECT `data_smierci`" +
                f"FROM `autorzy` WHERE `autor_id` = \"{self.newRecord[0]}\""
        )[0][0] == None:
            self.oldRecord[-1] = ""
        try:
            self.database.modifyRecord(self.tableName, self.oldRecord,
                                       self.newRecord)
        except Exception as e:
            self.logger.error(f"Exception! e = {e}")
            try:
                errorNo = int(e.__str__().split()[0][1:-1])
            except:
                errorNo = 0
            if errorNo == 1048:
                messagebox.showerror("Can not add a record to database!",
                                     f"{e.__str__().split(',')[1][:-2]}")
            elif errorNo == 1062:
                messagebox.showerror(
                    "Can not add a record to database!",
                    f"Primary column value (with '*') is duplicate!")
            elif errorNo == 0:
                messagebox.showerror("Can not add a record to database!",
                                     f"{e}")
            else:
                messagebox.showerror("Can not add a record to database!",
                                     f"{e.__str__().split(',')[1][:-2]}")
            self.newRecord = list()
            return
        confirm = messagebox.askyesno(
            "Modify record confirmation",
            "Are You sure that You want to modify this record in database?")

        if confirm:
            self.database.connection.commit()
            self.goBack()
        else:
            self.database.connection.rollback()
            self.themeWindow.focus_set()

    def goBack(self):
        self.modifyWindow.event_generate("<<back>>")

    def initComboValues(self, tableName, col):
        return self.database.executeStatement(
            f"SELECT DISTINCT `{col}` FROM `{tableName}`")

    def showHelp(self, column, combo):
        if self.helpWindow is not None:
            return

        def select():
            atr = self.listbox.get(self.listbox.curselection())
            if self.column == "autorzy_autor_id":
                atr = atr.split(" ")
                id = self.database.executeStatement(
                    f"SELECT `autor_id` " +
                    f"FROM `autorzy` WHERE `imie` = \"{atr[0]}\" " +
                    f"AND `nazwisko` = \"{atr[1]}\" ")
            else:
                id = self.database.executeStatement(
                    f"SELECT `ksiazka_id` " +
                    f"FROM `ksiazki` WHERE `tytul` = \"{atr}\" ")
            self.combo.set(id)
            exit()
            return

        def exit():
            self.helpWindow.destroy()
            self.helpWindow = None

        self.column = column
        self.combo = combo

        self.helpWindow = Toplevel(self.modifyWindow)
        self.helpWindow.protocol('WM_DELETE_WINDOW', exit)

        vals = list()
        if self.column == "autorzy_autor_id":
            temp_vals = self.database.executeStatement(
                f"SELECT `imie`, `nazwisko` FROM `autorzy`")
            for val1, val2 in temp_vals:
                vals.append(val1 + " " + val2)
        else:
            temp_vals = self.database.executeStatement(
                f"SELECT `tytul` FROM `ksiazki`")
            for val1 in temp_vals:
                vals.append(val1[0])

        self.listbox = Listbox(self.helpWindow)
        self.listbox.pack(side=TOP)

        for val in vals:
            self.listbox.insert("end", val)

        self.button = Button(self.helpWindow, text="Select", command=select)
        self.button.pack(side=TOP)
Beispiel #7
0
class LogonController:
    def __init__(self, mainWindow, eventF, width=300, height=200):
        # Initialize logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("LogonController logger has started.")

        # Create sub window with signing info
        self.tlLogon = Toplevel(mainWindow)
        self.tlLogon.title("Sign In")
        mainWindow.update()
        # Calculate offset of sub window
        xOffset = (mainWindow.winfo_width() / 2) - (width / 2)
        yOffset = (mainWindow.winfo_height() / 2) - (height / 2)

        self.tlLogon.geometry(
            f"{width}x{height}+{int(xOffset)}+{int(yOffset)}")
        self.tlLogon.lift()
        self.tlLogon.resizable(0, 0)
        self.tlLogon.attributes("-topmost", True)
        self.tlLogon.bind("<FocusIn>", self.eventHandleFocus)
        self.tlLogon.protocol('WM_DELETE_WINDOW', self.doNothing)
        self.tlLogon.bind('<<signed>>', lambda database: eventF(self.dataBase))

        # Other widgets
        self.content = Frame(self.tlLogon)
        self.content.place(x=self.tlLogon.winfo_width() / 12,
                           y=self.tlLogon.winfo_height() / 6)

        self.labelAddress = Label(self.content,
                                  text="Adress:",
                                  font=("Arial Bold", 12))
        self.labelAddress.grid(row=0, column=0)

        self.textAddress = Entry(self.content, width=20)
        self.textAddress.grid(row=0, column=1)
        self.textAddress.insert(END, "localhost")  # TODO: REMOVE IT LATER

        self.labelUser = Label(self.content,
                               text="Username:"******"Arial Bold", 12))
        self.labelUser.grid(row=1, column=0)

        self.textUser = Entry(self.content, width=20)
        self.textUser.grid(row=1, column=1)
        self.textUser.insert(END, "root")  # TODO: REMOVE IT LATER

        self.labelPassword = Label(self.content,
                                   text="Password:"******"Arial Bold", 12))
        self.labelPassword.grid(row=2, column=0)

        self.textPassword = Entry(self.content, show='*', width=20)
        self.textPassword.grid(row=2, column=1)

        self.labelDatabase = Label(self.content,
                                   text="Database Name:",
                                   font=("Arial Bold", 12))
        self.labelDatabase.grid(row=3, column=0)

        self.textDatabase = Entry(self.content, width=20)
        self.textDatabase.grid(row=3, column=1)
        self.textDatabase.insert(END, "ZBD_project")

        self.buttonLogin = Button(self.content,
                                  text="Sign in",
                                  command=self.clickLogin)
        self.buttonLogin.grid(row=4, column=1)

        self.labelDatabase = Label(self.content,
                                   text="Incorrect login input!",
                                   font=("Arial Bold", 8),
                                   fg="red")
        self.labelDatabase.grid(row=5, column=1)
        self.labelDatabase.grid_remove()

    def clickLogin(self):
        self.logger.debug("Attempt to sign in.")
        address = self.textAddress.get()
        user = self.textUser.get()
        password = self.textPassword.get()
        databaseName = self.textDatabase.get()
        if self.signInToDatabase(address, user, password, databaseName):
            self.labelDatabase.grid_remove()
            self.logger.info("Signed in!")
            self.tlLogon.event_generate("<<signed>>")
        else:
            self.labelDatabase.grid()

    def signInToDatabase(self, address, user, password, databaseName):
        try:
            dataBase = Database(host=address,
                                user=user,
                                password=password,
                                database=databaseName)
        except ConnectionRefusedError:
            self.logger.error("Could not connect to data base system!")
            return False
        self.dataBase = dataBase
        return True

    def eventHandleFocus(self, event):
        if event.widget == self.tlLogon:
            self.tlLogon.focus_set()

    def doNothing(self):
        pass
Beispiel #8
0
class Database:
    def __init__(self, host, user, password="", database="zbd_project"):
        """Initialize database object"""
        # Initialize logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("Database logger has started.")
        self.connection = None
        # Initialize database connection
        try:
            self.logger.debug("Trying to attempt connection with database.")
            self.connection = pymysql.connect(host=host, user=user, passwd=password, database=database)
        except Exception as e:
            self.logger.critical(f"Could not connect to database! Error = {e}")
            raise ConnectionRefusedError(f"Could not connect to database! Error = {e}")
        self.logger.info("Database connection is stable.")

        self.config = dict()
        try:
            with open("config.json") as f:
                self.config = {**self.config, **json.load(f)}
        except IOError as e:
            self.logger.error(f"Error occured while reading config from .json file!. Error = {e}")
            exit(-1)
        self.logger.debug("Config has been read.")

        # Initialize global cursor
        self.logger.debug("Creating global cursor.")
        self.cursor = self.connection.cursor()
        self.logger.debug("Global cursor created.")

    def __del__(self):
        """ Close connection with database """
        # Close database connection
        if self.connection:
            self.logger.info("Closing database connection.")
            try:
                self.connection.close()
            except:
                pass

    def executeStatement(self, statement):
        """ Execute an statement using database cursor"""
        try:
            self.logger.debug(f"Executing statement = {statement}")
            self.cursor.execute(statement)
        except Exception as e:
            self.logger.error(f"Could not realize an execute statement. Statement = {statement}. Error = {e}")
            raise Exception(e)
        result = self.cursor.fetchall()
        self.logger.debug(f"Result = {result}")
        return result

    def getTableNames(self):
        """ Get all table names read from config file """
        return self.config["table_names"]

    def getRawData(self, tableName):
        """ Gets data and return its in list form """
        statement = "SELECT * FROM " + tableName + ";"
        return self.executeStatement(statement)

    def getColumns(self, tableName):
        """Create and execute statement"""
        tableName = "'" + tableName + "'"
        statement = "SELECT column_name FROM information_schema.columns WHERE table_name = " + tableName + ";"
        return self.executeStatement(statement)

    def getColumnTypes(self, tableName):
        """Create and execute statement"""
        tableName = "'" + tableName + "'"
        statement = "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = " + tableName + ";"
        columns = self.executeStatement(statement)
        res = {}
        for column in columns:
            res[column[0]] = column[1]
        return res

    """Create dictionary res[columnName] = [keyType, refTable, refColumn]"""
    def getColumnKeys(self, tableName):
        tableName = "'" + tableName + "'"
        statement = "SELECT column_name, column_key FROM information_schema.columns WHERE table_name = " + tableName + ";"
        columns = self.executeStatement(statement)
        res = {}
        for column in columns:
            name = column[0]
            key = column[1]
            if key == 'MUL':
                statement = "SELECT referenced_table_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_name = " + tableName + " AND column_name = " + "'" + name + "'" + ";"
                tmp = self.executeStatement(statement)[0]
                refTable = tmp[0]
                refColumn = tmp[1]
            else:
                refTable = 'NULL'
                refColumn = 'NULL'

            res[name] = [key, refTable, refColumn]

        return res

    def getColumnNullable(self, tableName):
        """Create and execute statement"""
        tableName = "'" + tableName + "'"
        statement = "SELECT column_name, IS_NULLABLE FROM information_schema.columns WHERE table_name = " + tableName + ";"
        columns = self.executeStatement(statement)
        res = {}
        for column in columns:
            res[column[0]] = column[1]
        return res

    def getTableCheckConstraint(self, tableName):
        """Create and execute statement"""
        tableName = "'" + tableName + "'"
        statement = "SELECT constraint_name, check_clause FROM information_schema.check_constraints WHERE table_name = " + tableName + ";"
        columns = self.executeStatement(statement)
        res = {}
        for column in columns:
            values = column[1]
            values = values[22:-1]
            values = list(values.split(","))
            newValues = []
            for val in values:
                newValues.append(val[1:-1])
            res[column[0]] = newValues
        return res

    def getData(self, tableName):
        """ Gets data and return it in dict form """
        rowData = self.getRawData(tableName)
        columns = self.getColumns(tableName)
        result = dict()
        for noR, row in enumerate(rowData):
            result[f"rec{noR + 1}"] = dict()
            for noC, column in enumerate(columns):
                result[f"rec{noR + 1}"][f"{column[0]}"] = row[noC]
        return result

    def addRecord(self, tableName, values):
        self.logger.debug(f"Adding new record to table {tableName}. Values = {values}")

        try:
            """Check if values are in correct format"""
            self.logger.debug("Checking if values are in correct format.")
            columnTypes = self.getColumnTypes(tableName)
            tmp = self.getColumns(tableName)
            columnNames = []
            for column in tmp:
                newColumn = str(column)
                newColumn = newColumn[2:-3]
                columnNames.append(newColumn)
            for i in range(len(columnTypes)):
                name = columnNames[i]
                type = columnTypes[name]
                value = values[i]
                value = str(value)
                if value in ('NULL', None, ''):
                    continue
                elif type == 'int':
                    if not re.match('^[0-9]+$', value):
                        raise Exception(f"Wrong {name}. Make sure {name} contains only digits.")
                elif type == 'date':
                    condition = self.executeStatement(f"SELECT (SELECT CURDATE()) < '{value}'")
                    if not re.match('^[0-9]{4}-[0-9]{2}-[0-9]{2}$', value):
                        raise Exception(f"Wrong {name}. Make sure {name} is in 'YYYY-MM-DD' format.")
                    elif condition == ((1,),):
                        raise Exception(f"Wrong {name}. Date can't be from the future.")

            self.logger.debug("Creating addRecord statement.")

            """Create columns_str string to hold columns names ready to put into mysql question"""
            columns_str = "("
            for column in columnNames:
                newColumn = "`" + column + "`"
                columns_str += newColumn + ", "
            columns_str = columns_str[:-2] + ")"

            """Create values_str string to hold columns values ready to put into mysql question"""
            values_str = "("
            for v in values:
                newValue = v
                if newValue in ('NULL', None, ''):
                    newValue = 'NULL'
                else:
                    newValue = "'" + str(v) + "'"
                values_str += newValue + ", "
            values_str = values_str[:-2] + ")"

            """Create statement"""
            tableName = "`" + tableName + "`"
            statement = "INSERT INTO " + tableName + columns_str + " VALUES " + values_str + ";"
            self.logger.debug(f"AddRecord statement created succesfully. Statement = {statement}")

            """Executing statement"""
            self.executeStatement(statement)
            self.logger.debug(f"Record {values[0]} added succesfully.")
            return True

        except Exception as e:
            self.logger.error(f"Could not realize an addRecord function. Error = {e}")
            raise Exception(e)

    def modifyRecord(self, tableName, oldValues, values):
        self.logger.debug(f"Modifying record {oldValues} from {tableName}. New values = {values}")

        try:
            """Check if values are in correct format"""
            self.logger.debug("Checking if values are in correct format.")
            columnTypes = self.getColumnTypes(tableName)
            tmp = self.getColumns(tableName)
            columnNames = []
            for column in tmp:
                newColumn = str(column)
                newColumn = newColumn[2:-3]
                columnNames.append(newColumn)
            for i in range(len(columnTypes)):
                name = columnNames[i]
                type = columnTypes[name]
                value = values[i]
                value = str(value)
                if value in ('NULL', None, ''):
                    continue
                elif type == 'int':
                    if not re.match('^[0-9]+$', value):
                        raise Exception(f"Wrong {name}. Make sure {name} contains only digits.")
                elif type == 'date':
                    condition = self.executeStatement(f"SELECT (SELECT CURDATE()) < '{value}'")
                    if not re.match('^[0-9]{4}-[0-9]{2}-[0-9]{2}$', value):
                        raise Exception(f"Wrong {name}. Make sure {name} is in 'YYYY-MM-DD' format.")
                    elif condition == ((1,),):
                        raise Exception(f"Wrong {name}. Date can't be from the future.")
            self.logger.debug("Creating modifyRecord statement.")

            """Create columns names ready to put into mysql question"""
            columns = []
            tmp = self.getColumns(tableName)
            for column in tmp:
                newColumn = str(column)
                newColumn = "`" + newColumn[2:-3] + "`"
                columns.append(newColumn)

            """Create set_str ready to put into mysql question"""
            set_str = ""
            for i in range(len(columns)):
                if str(values[i]) in ('NULL', None, ''):
                    set_str += columns[i] + " = "
                    set_str += 'NULL' + ", "
                else:
                    set_str += columns[i] + " = "
                    set_str += "'" + str(values[i]) + "', "
            set_str = set_str[:-2]

            """Create where_str ready to put into mysql question"""
            where_str = ""
            for i in range(len(columns)):
                oldValue = oldValues[i]
                if oldValue in ('NULL', None, ''):
                    where_str += columns[i] + " IS NULL AND "
                else:
                    where_str += columns[i] + " = "
                    oldValue = str(oldValues[i])
                    where_str += "'" + oldValue + "' AND "
            where_str = where_str[:-5]

            """Create statement"""
            tableName = "`" + tableName + "`"
            statement = "UPDATE " + tableName + " SET " + set_str + " WHERE " + where_str + ";"
            self.logger.debug(f"ModifyRecord statement created succesfully. Statement = {statement}")

            """Executing statement"""
            self.executeStatement(statement)
            self.logger.debug(f"Record {oldValues[0]} modified succesfully.")
            return True

        except Exception as e:
            self.logger.error(f"Could not realize an modifyRecord function. Error = {e}")
            raise Exception(e)

    def deleteRecord(self, tableName, values):
        self.logger.debug(f"Deleting record {values[0]} from {tableName}.")

        try:
            self.logger.debug("Creating deleteRecord statement.")

            """Create columns names ready to put into mysql question"""
            columns = []
            tmp = self.getColumns(tableName)
            for column in tmp:
                newColumn = str(column)
                newColumn = "`" + newColumn[2:-3] + "`"
                columns.append(newColumn)

            """Create where_str ready to put into mysql question"""
            where_str = ""
            for i in range(len(columns)):
                value = values[i]
                if value in ('NULL', None, ''):
                    where_str += columns[i] + " IS NULL AND "
                else:
                    where_str += columns[i] + " = "
                    value = str(values[i])
                    where_str += "'" + value + "' AND "
            where_str = where_str[:-5]

            """Create statement"""
            tableName = "`" + tableName + "`"
            statement = "DELETE FROM " + tableName + " WHERE " + where_str + ";"
            self.logger.debug(f"DeleteRecord statement created succesfully. Statement = {statement}")

            """Executing statement"""
            self.executeStatement(statement)
            self.logger.debug(f"Record {values[0]} deleted succesfully.")
            return True

        except Exception as e:
            self.logger.error(f"Could not realize an deleteRecord function. Error = {e}")
            raise Exception(e)

    def borrowBook(self, libraryName, workerName, workerSurname,
                    readerName, readerSurname, bookTitle,
                    bookDate, bookGenre, comments):
        self.logger.debug("Borrowing book.")

        try:
            self.executeStatement(f"CALL borrowBook('{libraryName}', '{workerName}', '{workerSurname}',"
                                  f"'{readerName}', '{readerSurname}', '{bookTitle}',"
                                  f"'{bookDate}', '{bookGenre}', '{comments}');")
            self.logger.debug("Book borrowed succesfully.")
            return True

        except Exception as e:
            self.logger.error(f"Could not realize an borrowBook function. Error = {e}")
            raise Exception(e)

    def findBestBook(self, bookDateYear):
        self.logger.debug("Finding best book.")

        try:
            bestBookBorrowCount = self.executeStatement(f"SELECT findBestBookBorrowCount({bookDateYear});")
            bestBookTitle = self.executeStatement(f"SELECT findBestBookTitle({bookDateYear});")
            self.logger.debug(f"Book found succesfully. BookID = {bestBookTitle}. Count = {bestBookBorrowCount}")
            return [bestBookTitle, bestBookBorrowCount]

        except Exception as e:
            self.logger.error(f"Could not realize an findBestBook function. Error = {e}")
            raise Exception(e)

    def generateDataBase(self):
        self.logger.debug(f"Generating new data base started.")

        names = ['Piotr', 'Maciej', 'Jan', 'Jakub', 'Karol', 'Joanna', 'Marta', 'Magda', 'Natalia', 'Olga']
        surnames = ['Krol', 'Nowak', 'Zima', 'Leszczyk', 'Karol', 'Nowaczyk', 'Kowalczyk', 'Wozniak', 'Mazur', 'Krawczyk']
        dates = ['1970-05-05', '1971-12-25', '1972-08-01', '1973-07-17', '1974-10-11', '1975-01-22', '1976-03-30', '1977-11-28', '1978-09-03', '1979-04-14']
        libraryNames = ['Czytam_ksiazki', 'Czytanie_jest_fajne', 'Ksiazki_sa_super', 'Biblioteka_dziecieca', 'Biblioteka_szkolna', 'Biblioteka_miejska', 'Warto_czytac', 'Super_Biblioteka', 'Biblioteka_na_rynku', 'Biblioteka_na_Kwiatowej']
        adresses = ['Kwiatowa_10', 'Rzeczypospolitej_5', 'Dluga_4', 'Krutka_1', 'Poznanska_12', 'Wroclawska_43', 'Zawila_3', 'Czysta_21', 'Powstancow_2', 'Brudna_31']
        genres = ['fantasy', 'horror', 'klasyka', 'kryminal', 'sensacja', 'thriller', 'literatura_mlodziezowa', 'literatura_obyczajowa', 'romans', 'powiesc_historyczna']
        operationTypes = ['wypozyczenie', 'zwrot', 'przedluzenie']
        comments = ['pierwszy raz od dawna', 'sprawna operacja', 'bez uwag']
        booksTitles = ['Szeptucha', 'Polska_odwraca_oczy', 'On', 'Zycie_na_pelnej_petardzie', 'Okularnik', 'Najgorszy_czlowiek_na_swiecie', 'Inna_dusza', 'Ksiegi_Jakubowe', 'Gniew', 'Trociny']
        firmNames = ['Januszpol', 'Toyota', 'Adidas', 'Walkman', 'Red_Bull', 'Junkers', 'Ikea', 'Tesco', 'CCC', 'Bakoma']
        workersFunctions = ['szef', 'sprzatanie', 'obsluga_bazy', 'kucharz']

        self.logger.debug("Random collumn values created succesfully.")

        """Generate authors"""
        self.logger.debug("Generating authors. Putting records to `autorzy` table.")
        for i in range(10):
            author_id = 'NULL'
            name = random.choice(names)
            surname = surnames[i]
            birthday = random.choice(dates)
            tmp = random.choice([True, False])
            if tmp:
                deathday = 'NULL'
            else:
                deathYear = birthday[:4]
                deathYear = int(deathYear)
                tmp = random.randint(1,40)
                deathYear = deathYear + tmp
                deathYear = str(deathYear)
                tmp = random.choice(dates)
                deathday = deathYear + tmp[4:]
            values = [author_id, name, surname, birthday, deathday]
            self.addRecord('autorzy', values)
        self.logger.debug("Authors records put into 'autorzy' table succesfully.")

        """Generate libraries"""
        self.logger.debug("Generating libraries. Putting records to `biblioteki` table.")
        for i in range(10):
            name = libraryNames[i]
            adres = adresses[i]
            values = [name, adres]
            self.addRecord('biblioteki', values)
        self.logger.debug("Libraries records put into 'biblioteki' table succesfully.")

        """Generate readers"""
        self.logger.debug("Generating readers. Putting records to `czytelnicy` table.")
        for i in range(10):
            reader_id = 'NULL'
            name = random.choice(names)
            surname = surnames[i]
            values = [reader_id, name, surname]
            self.addRecord('czytelnicy', values)
        self.logger.debug("Readers records put into 'czytelnicy' table succesfully.")

        """Generate sections"""
        self.logger.debug("Generating sections. Putting records to `dzialy` table.")
        for i in range(10):
            name = 'dzial' + str(i)
            location = 'lokalizacja' + str(i)
            values = [name, location]
            self.addRecord('dzialy', values)
        self.logger.debug("Sections records put into 'dzialy' table succesfully.")
            
        """Generate genres"""
        self.logger.debug("Generating genres. Putting records to `gatunki` table.")
        for i in range(10):
            name = genres[i]
            values = [name]
            self.addRecord('gatunki', values)
        self.logger.debug("Genres records put into 'gatunki' table succesfully.")
        
        """Generate books"""
        self.logger.debug("Generating books. Putting records to `ksiazki` table.")
        for i in range(10):
            book_id = 'NULL'
            title = booksTitles[i]
            date = random.choice(dates)
            genre = random.choice(genres)
            values = [book_id, title, date, genre]
            self.addRecord('ksiazki', values)
        self.logger.debug("Books records put into 'ksiazki' table succesfully.")

        """Generate bookstands"""
        self.logger.debug("Generating bookstands. Putting records to `regaly` table.")
        for i in range(10):
            number = i
            capacity = random.randint(5,9)
            booksCount = 0
            section = random.randint(0,9)
            section = 'dzial' + str(section)
            values = [number, capacity, booksCount, section]
            self.addRecord('regaly', values)
        self.logger.debug("Bookstands records put into 'regaly' table succesfully.")
        
        """Generate ovners"""
        self.logger.debug("Generating ovners. Putting records to `wlasciciele` table.")
        tmp = random.randint(1000000000,2000000000)
        for i in range(10):
            nip = tmp + i
            if random.randint(0,1) == 1:
                firmName = firmNames[i]
                name = 'NULL'
                surname = 'NULL'
            else:
                firmName = 'NULL'
                name = random.choice(names)
                surname = surnames[i]
            values = [nip, firmName, name, surname]
            self.addRecord('wlasciciele', values)
        self.logger.debug("Ovners records put into 'wlasciciele' table succesfully.")
        
        """Generate ovner-library"""
        self.logger.debug("Generating ovner-library. Putting records to `wlasciciel_biblioteka` table.")
        tmp = self.getRawData('wlasciciele')
        nips = [record[0] for record in tmp]
        tmp = self.getRawData('biblioteki')
        libraries = [record[0] for record in tmp]
        for i in range(len(libraries)):
            nip = random.choice(nips)
            library = libraries[i]
            values = [nip, library]
            self.addRecord('wlasciciel_biblioteka', values)
        self.logger.debug("Ovner-library records put into 'wlasciciel_biblioteka' table succesfully.")
        
        """Generate author-book"""
        self.logger.debug("Generating author-book. Putting records to `autor_ksiazka` table.")
        tmp = self.getRawData('autorzy')
        authors_ids = [record[0] for record in tmp]
        tmp = self.getRawData('ksiazki')
        books_ids = [record[0] for record in tmp]
        for i in range(len(books_ids)):
            author_id = random.choice(authors_ids)
            book_id = books_ids[i]
            values = [author_id, book_id]
            self.addRecord('autor_ksiazka', values)
        self.logger.debug("Author-book records put into 'autor_ksiazka' table succesfully.")
        
        """Generate specimens"""
        self.logger.debug("Generating specimens. Putting records to `egzemplarze` table.")
        tmp = self.getRawData('ksiazki')
        books_ids = [record[0] for record in tmp]
        tmp = self.getRawData('regaly')
        bookstandsNumbers = [record[0] for record in tmp]
        for _ in range(10):
            specimen_id = 'NULL'
            book_id = random.choice(books_ids)
            bookstandNumber = random.choice(bookstandsNumbers)
            """Increment bookstand books count"""
            statement = "SELECT `liczba_ksiazek` FROM `regaly` WHERE `numer` = " + str(bookstandNumber) + ";"
            booksCount = self.executeStatement(statement)
            statement = "SELECT `pojemnosc` FROM `regaly` WHERE `numer` = " + str(bookstandNumber) + ";"
            capacity = self.executeStatement(statement)
            if booksCount < capacity:
                statement = "UPDATE `regaly` SET `liczba_ksiazek` = `liczba_ksiazek` + 1 WHERE `numer` = " + str(bookstandNumber) + ";"
                self.executeStatement(statement)
                """Add specimen"""
                values = [specimen_id, book_id, bookstandNumber]
                self.addRecord('egzemplarze', values)
            else:
                self.logger.error(f"Could not add specimen to bookstand {bookstandNumber}. Not enough space on the bookstand")
                return False
        self.logger.debug("Specimens records put into 'egzemplarze' table succesfully.")

        
        """Generate workers. Disable FK checking"""
        self.logger.debug("Generating workers. Putting records to `pracownicy` table.")
        self.executeStatement("SET FOREIGN_KEY_CHECKS = 0;")
        self.logger.debug("FOREIGN_KEY_CHECKS disabled")
        for i in range(10):
            worker_id = 'NULL'
            if i != 0:
                boss_id = random.choice(['NULL', random.randint(0, i - 1)])
            else:
                boss_id = 'NULL'
            name = random.choice(names)
            surname = surnames[i]
            function = random.choice(workersFunctions)
            values = [worker_id, boss_id, name, surname, function]
            self.addRecord('pracownicy', values)
        self.executeStatement("SET FOREIGN_KEY_CHECKS = 1;")
        self.logger.debug("FOREIGN_KEY_CHECKS enabled")
        self.logger.debug("Workers records put into 'pracownicy' table succesfully.")

        """Generate operations"""
        self.logger.debug("Generating operations. Putting records to `historia_operacji` table.")
        tmp = self.getRawData('biblioteki')
        libraries = [record[0] for record in tmp]
        tmp = self.getRawData('pracownicy')
        workers_ids = [record[0] for record in tmp]
        tmp = self.getRawData('czytelnicy')
        readers_ids = [record[0] for record in tmp]
        tmp = self.getRawData('egzemplarze')
        specimens_ids = [record[0] for record in tmp]
        for _ in range(10):
            operation_id = 'NULL'
            date = random.choice(dates)
            library = random.choice(libraries)
            worker_id = random.choice(workers_ids)
            reader_id = random.choice(readers_ids)
            specimen_id = random.choice(specimens_ids)
            operationType = random.choice(operationTypes)
            delay = random.choice(['NULL', random.randint(1,20)])
            comment = random.choice(['NULL', random.choice(comments)])
            values = [operation_id, date, library, worker_id, reader_id, specimen_id, operationType, delay, comment]
            self.addRecord('historia_operacji', values)
        self.logger.debug("Operations records put into 'historia_operacji' table succesfully.")

        """Commit"""
        self.connection.commit()
Beispiel #9
0
class MainController:
    """ A class that contains all methods to handle main window with table names """
    def __init__(self, themeWindow, database, logoutEvent):
        self.database = database
        self.themeWindow = themeWindow
        # Start logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("MainController logger has started.")
        # Read table names from database object
        self.tableNames = self.database.getTableNames()
        if len(self.tableNames) != 0:
            self.logger.debug("Table names are loaded")
        else:
            self.logger.warning("No table names has been loaded!")

        self.procedureController = None
        self.functionController = None
        self.choiceWindow = None

        # Widgets
        # Main frame of this window
        self.content = Frame(self.themeWindow,
                             bg="#B7B9B8",
                             bd=4,
                             relief=RAISED,
                             width=self.themeWindow.winfo_width() - 80,
                             height=self.themeWindow.winfo_height() - 80)
        self.content.place(x=40, y=40)
        self.content.grid(row=0, column=0)
        self.content.bind("<<signout>>", lambda _: logoutEvent(None))
        self.content.update()

        self.listFrame = Frame(self.content,
                               bg="white",
                               bd=1,
                               relief=FLAT,
                               width=int(self.content.winfo_width() / 2 + 20),
                               height=int(self.content.winfo_height() - 60))
        self.listFrame.place(x=20, y=20)

        # Canvas which contains whole list of table names with their buttons
        self.tablesCanvas = Canvas(self.listFrame,
                                   bg="white",
                                   bd=1,
                                   relief=FLAT,
                                   width=int(self.content.winfo_width() / 2),
                                   height=int(self.content.winfo_height() -
                                              60))
        self.tablesCanvas.update()
        self.tablesScrollY = Scrollbar(self.listFrame,
                                       orient="vertical",
                                       command=self.tablesCanvas.yview)

        self.tablesFrame = Frame(self.tablesCanvas,
                                 bg="white",
                                 bd=0,
                                 relief=FLAT,
                                 width=self.tablesCanvas.winfo_width(),
                                 height=self.tablesCanvas.winfo_height())

        self.selectionVar = IntVar(
        )  # Int variable which contains current selection
        for no, table in enumerate(self.tableNames):
            Radiobutton(self.tablesFrame,
                        bg="white",
                        text=f"{table}",
                        variable=self.selectionVar,
                        value=no,
                        command=lambda: self.selection(self.tableNames[
                            self.selectionVar.get()])).pack(anchor=W)

        self.tablesCanvas.place(x=40, y=30)
        self.tablesCanvas.create_window(0,
                                        0,
                                        anchor='nw',
                                        window=self.tablesFrame)
        self.tablesCanvas.configure(scrollregion=self.tablesCanvas.bbox('all'),
                                    yscrollcommand=self.tablesScrollY.set)
        self.tablesCanvas.pack(fill='both', expand=True, side='left')
        self.tablesScrollY.pack(fill='y', side='left')

        # Frame which contain buttons
        self.buttonsFrame = Frame(self.content,
                                  bg="#B7B9B8",
                                  relief=RAISED,
                                  width=int(self.content.winfo_width() / 4),
                                  height=int(self.content.winfo_height() - 60))

        self.buttonsFrame.place(x=380, y=20)

        # Button to view selected table
        self.buttonViewTable = Button(self.buttonsFrame,
                                      text="View Table",
                                      command=self.viewTable,
                                      width=20,
                                      height=5)
        self.buttonViewTable.grid(row=0, column=0)
        # Button with SQL defined procedure
        self.buttonViewTable = Button(self.buttonsFrame,
                                      text="Hire a book",
                                      command=self.customProcedure,
                                      width=20,
                                      height=5)
        self.buttonViewTable.grid(row=1, column=0)
        # Button with SQL defined function
        self.buttonViewTable = Button(self.buttonsFrame,
                                      text="Top book",
                                      command=self.functionEntry,
                                      width=20,
                                      height=5)
        self.buttonViewTable.grid(row=2, column=0)
        # Button to log out
        self.buttonViewTable = Button(self.buttonsFrame,
                                      text="Log out",
                                      command=self.logout,
                                      width=20,
                                      height=5)
        self.buttonViewTable.grid(row=3, column=0)

    def selection(self, tabName):
        self.logger.debug(f"Choosed `{tabName}` table.")

    def customProcedure(self):
        if self.procedureController is None:
            self.procedureController = ProcedureController(
                self.themeWindow, self.database, self.backEvent)

    def customFunction(self, year):
        self.year = year
        if self.functionController is None:
            self.functionController = FunctionController(
                self.themeWindow, self.database, self.backEvent, self.year)
            self.choiceWindow.destroy()
            self.choiceWindow = None

    def functionEntry(self):
        if self.choiceWindow is not None:
            return
        years = self.database.executeStatement(
            "SELECT DISTINCT `data` FROM `historia_operacji` " +
            "WHERE `rodzaj_operacji` = \"wypozyczenie\"")
        new_years = list()
        if len(years) == 0:
            messagebox.showwarning("No hired books",
                                   "There are no hired books yet!")
            return
        for no, y in enumerate(years):
            new_years.append(y[0].year)

        self.choiceWindow = Toplevel(self.themeWindow)
        self.choiceWindow.protocol('WM_DELETE_WINDOW', self.backEvent)

        titleLabel = Label(self.choiceWindow,
                           text="What is best hired book in selected year?")
        titleLabel.grid(row=0, column=0, columnspan=2)
        label = Label(self.choiceWindow, text="Choose year: ")
        label.grid(row=1, column=0)
        combo = ttk.Combobox(self.choiceWindow, values=new_years)
        combo.grid(row=1, column=1, columnspan=2)
        combo.configure(state="readonly")
        button = Button(self.choiceWindow,
                        text="Select",
                        command=lambda: self.customFunction(combo.get()))
        button.grid(row=2, column=0)

    def backEvent(self):
        if self.procedureController is not None:
            self.procedureController.procedureWindow.destroy()
            self.procedureController = None
        if self.functionController is not None:
            self.functionController.functionWindow.destroy()
            self.functionController = None
        if self.choiceWindow is not None:
            self.choiceWindow.destroy()
            self.choiceWindow = None

    def logout(self):
        """ Generate an event to sign out """
        self.content.event_generate("<<signout>>")

    def viewTable(self):
        """ Go to selected table screen """
        self.content.grid_forget()
        self.tableController = TableController(
            self.tableNames[self.selectionVar.get()], self.database,
            self.themeWindow, self.chooseTableEvent)

    def chooseTableEvent(self, _):
        self.tableController.content.destroy()
        self.content.grid(row=0, column=0)
Beispiel #10
0
class ProcedureController:
    def __init__(self, rootWindow, database, backEvent):
        self.rootWindow = rootWindow
        self.backEvent = backEvent
        self.database = database
        # Start logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug("ProcedureController logger has started.")

        self.mainLabels = ["Library", "Book title", "Genre", "Publishing date"]
        self.personalLabels = [
            "Reader's surname", "Reader's name", "Employee's surname",
            "Employee's name", "Comment(optional)"
        ]

        self.procedureWindow = Toplevel(self.rootWindow)
        self.procedureWindow.title("Check a book.")
        self.procedureWindow.protocol('WM_DELETE_WINDOW', self.goBack)
        self.procedureWindow.bind("<<back>>", lambda _: self.backEvent())

        self.mainFrame = Frame(self.procedureWindow,
                               bd=4,
                               relief=RAISED,
                               width=self.procedureWindow.winfo_width() - 40,
                               height=self.procedureWindow.winfo_height() - 40)
        self.mainFrame.pack(fill='both', side=TOP)

        self.comboBoxes = list()
        self.frames = list()
        for lab in self.mainLabels:
            self.frames.append(Frame(self.mainFrame))
            if len(self.comboBoxes) == 0:
                self.comboBoxes.append(
                    extendedComboBox(self.database, self.frames[-1], lab))
                self.comboBoxes[-1].combo.configure(state='readonly')
            else:
                self.comboBoxes.append(
                    extendedComboBox(self.database, self.frames[-1], lab))
                self.comboBoxes[-2].setChild(self.comboBoxes[-1])
                self.comboBoxes[-1].disable()
            self.frames[-1].pack(fill='both', side=TOP)
            # self.frames.append(Frame(self.mainFrame,
            #                          width=self.procedureWindow.winfo_width() - 40,
            #                          height=20 * 4
            #                          ))
            # Label(self.frames[no], text=lab, font=("Arial Bold", 12)).grid(row=0, column=0, columnspan=3)
            # entry = Entry(self.frames[no], width=20)
            # entry.grid(row=0, column=3, columnspan=2)
            # self.entries.append(entry)
            # self.frames[no].pack(fill='both', side=TOP)

        self.restFrame = Frame(self.mainFrame,
                               width=self.procedureWindow.winfo_width() - 40,
                               height=20 * 6)
        self.entries = dict()
        for no, lab in enumerate(self.personalLabels):
            #print(no, lab)
            l = Label(self.restFrame, text=lab, font=("Arial Bold", 12))
            l.grid(row=no, column=0, columnspan=3)
            if lab == "Comment(optional)":
                # self.commentEntry = Entry(self.restFrame, width=20)
                # self.commentEntry.grid(row=no, column=3, columnspan=2)
                self.commentEntry = scrolledtext.ScrolledText(self.restFrame,
                                                              width=40,
                                                              height=10)
                self.commentEntry.grid(row=no, column=3, columnspan=2)
                continue
            if lab == "Reader's surname":
                val = database.executeStatement(
                    "SELECT `nazwisko` FROM `pracownicy`")
            elif lab == "Reader's name":
                val = database.executeStatement(
                    "SELECT `imie` FROM `pracownicy`")
            elif lab == "Employee's surname":
                val = database.executeStatement(
                    "SELECT `nazwisko` FROM `pracownicy`")
            elif lab == "Employee's name":
                val = database.executeStatement(
                    "SELECT `imie` FROM `pracownicy`")
            entry = ttk.Combobox(self.restFrame, values=([""] + list(val)))
            entry.configure(state='readonly')
            entry.grid(row=no, column=3, columnspan=2, padx=5, pady=10)
            entry.bind("<<ComboboxSelected>>", lambda _: self.refreshValues())
            self.entries[l.cget("text")] = entry

        self.restFrame.pack(fill='both', side=BOTTOM)

        self.buttonFrame = Frame(self.procedureWindow,
                                 bd=4,
                                 relief=RAISED,
                                 width=self.procedureWindow.winfo_width() - 40,
                                 height=40)
        self.buttonFrame.pack(fill='both', side=TOP)

        self.hireButton = Button(self.buttonFrame,
                                 text="Hire",
                                 command=self.applyProcedure)
        self.hireButton.pack(side=LEFT)
        self.cancelButton = Button(self.buttonFrame,
                                   text="Cancel",
                                   command=self.goBack)
        self.cancelButton.pack(side=LEFT)

    def goBack(self):
        self.procedureWindow.event_generate("<<back>>")

    def applyProcedure(self):
        args = dict()
        for label, entry in self.entries.items():
            if entry.get() == "":
                self.logger.error("Not all entries are filled")
                messagebox.showerror("Not all mandatory entries are filled!",
                                     "Not all mandatory entries are filled!")
                return
            else:
                args[label] = entry.get()

        for combo in self.comboBoxes:
            if combo.combo.get() == "":
                self.logger.error("Not all entries are filled")
                messagebox.showerror("Not all mandatory entries are filled!",
                                     "Not all mandatory entries are filled!")
                return
            else:
                args[combo.label.cget("text")] = combo.combo.get()
        args["Comment(optional)"] = self.commentEntry.get('1.0', END)

        try:
            self.database.borrowBook(args["Library"], args["Employee's name"],
                                     args["Employee's surname"],
                                     args["Reader's name"],
                                     args["Reader's surname"],
                                     args["Book title"],
                                     args["Publishing date"], args["Genre"],
                                     args["Comment(optional)"])
        except Exception as e:
            errorNo = int(e.__str__().split()[0][1:-1])
            if errorNo == 1644:
                self.logger.error(f"{e.__str__().split(',')[1][:-2]}")
                messagebox.showerror("Error while hiring a book.",
                                     f"{e.__str__().split(',')[1][:-2]}")
                return
            else:
                self.logger.error(f"{e}")
                messagebox.showerror("Error while hiring a book.", f"{e}")
                return
        self.database.connection.commit()
        self.goBack()

    def refreshValues(self):
        for lab, en in self.entries.items():
            if lab == "Reader's surname":
                if en.get() is not "":
                    val = self.database.executeStatement(
                        f"SELECT `imie` FROM `czytelnicy` " +
                        f"WHERE `nazwisko` = \"{en.get()}\"")
                else:
                    val = self.database.executeStatement(
                        f"SELECT `imie` FROM `czytelnicy`")
                self.entries["Reader's name"].configure(values=([""] +
                                                                list(val)))
                #self.entries[lab].set("")
            elif lab == "Reader's name":
                if en.get() is not "":
                    val = self.database.executeStatement(
                        f"SELECT `nazwisko` FROM `czytelnicy` " +
                        f"WHERE `imie` = \"{en.get()}\"")
                else:
                    val = self.database.executeStatement(
                        f"SELECT `nazwisko` FROM `czytelnicy`")
                self.entries["Reader's surname"].configure(values=([""] +
                                                                   list(val)))
                # self.entries[lab].set("")
            elif lab == "Employee's surname":
                if en.get() is not "":
                    val = self.database.executeStatement(
                        f"SELECT `imie` FROM `pracownicy` " +
                        f"WHERE `nazwisko` = \"{en.get()}\"")
                else:
                    val = self.database.executeStatement(
                        f"SELECT `imie` FROM `pracownicy`")
                self.entries["Employee's name"].configure(values=([""] +
                                                                  list(val)))
                # self.entries[lab].set("")
            elif lab == "Employee's name":
                if en.get() is not "":
                    val = self.database.executeStatement(
                        f"SELECT `nazwisko` FROM `pracownicy` " +
                        f"WHERE `imie` = \"{en.get()}\"")
                else:
                    val = self.database.executeStatement(
                        f"SELECT `nazwisko` FROM `pracownicy`")
                self.entries["Employee's surname"].configure(
                    values=([""] + list(val)))
Beispiel #11
0
class App:
    def __init__(self, configPath, width=640, height=480):
        # Initialize logger
        self.logger = Logger(__name__, loggingLevel="debug")
        self.logger.debug(
            "==================================================================="
        )
        self.logger.debug("Application logger has started.")

        self.config = dict()
        try:
            with open(configPath) as f:
                self.config = {**self.config, **json.load(f)}
        except IOError as e:
            self.logger.error(
                f"Error occured while reading config from .json file!. Error = {e}"
            )
            exit(-1)
        self.logger.debug("Config has been read.")

        # Initialize app window
        self.logger.debug("Initializing application window.")
        self.window = Tk()
        self.window.title("Database Application.")
        self.logger.debug("Application window has been initialized.")

        self.window.geometry(f"{int(width)}x{int(height)}+0+0")
        self.window.resizable(0, 0)
        self.window.attributes("-topmost", True)

        # Setting a theme picture
        self.theme = Canvas(width=width, height=height, bg='black')
        self.theme.grid(column=0, row=0)
        self.imagesDict = dict()
        self.imagesDict["themeC"] = PhotoImage(file="theme.gif")
        self.imagesDict["themeG"] = PhotoImage(file="grayscale_theme.gif")
        self.logger.debug("Images has been loaded.")
        self.imageOnCanvas = self.theme.create_image(
            0, 0, image=self.imagesDict["themeG"], anchor=NW)
        self.logger.debug("Setting grayscale theme.")

    def __del__(self):
        # Delete dataBase object to close connection with database
        if self.database:
            self.logger.debug("Deleting database object.")
            try:
                del self.database
            except:
                pass
        self.logger.info("Closing application.")
        self.logger.debug(
            "==================================================================="
        )

    def main(self):
        self.logonWindow = LogonController(self.window, self.logonEvent)
        self.window.mainloop()

    def logonEvent(self, database):
        try:
            self.logonWindow.tlLogon.destroy()
        except Exception as e:
            self.logger.error(
                f"An error occurred while destroying logon window! Exception = {e}"
            )
        self.window.attributes("-topmost", True)
        self.window.attributes("-topmost", False)
        self.theme.itemconfig(self.imageOnCanvas,
                              image=self.imagesDict["themeC"])
        self.logger.debug("Setting coloured theme.")

        self.database = database

        self.mainWindow = MainController(self.window, self.database,
                                         self.logoutEvent)

    def logoutEvent(self, _):
        try:
            self.mainWindow.content.destroy()
        except Exception as e:
            self.logger.error(
                f"An error occurred while destroying logon window! Exception = {e}"
            )
        self.logger.info("Signed out")
        self.theme.itemconfig(self.imageOnCanvas,
                              image=self.imagesDict["themeG"])

        self.database = None

        self.logonWindow = LogonController(self.window, self.logonEvent)