Source code for GUI.Widgets
"""
.. module:: Widgets
This module implements two custom widgets to add more functionalities to the :py:mod:`GUI.HomeFrame`. the two widgets
are: a ``tkinter.LabelFrame`` to set up a custom table and a ``tkinter.PanedWindows`` to set up the three main buttons.
"""
from tkinter import *
from tkinter.ttk import Treeview
from .AddPassFrame import AddPassFrame
from .ModifyPassFrame import ModifyPassFrame
from CORE.DAODatabase import DAO
import tkinter.messagebox as message
dao = DAO()
USER_ID = 0
[docs]class EntriesTable(LabelFrame):
"""
.. class:: EntriesTable
This class is used to display a custom table with all the data from the user logged. The label frame contains a
`Treeview widget <https://tkdocs.com/tutorial/tree.html>`_ which is used to create a table since tkinter does not
have a table widget implemented. The data is requested to the database and then is entered into the ``Treeview``
with loops. It also has bound an event to detect when the user selects a row of the table.
"""
def __init__(self, root, user):
LabelFrame.__init__(self, root)
self.idList = []
global USER_ID
USER_ID = user
self.scroll = Scrollbar(self, orient=VERTICAL)
self.table = Treeview(self, height=10, selectmode="extended")
self.table.config(yscrollcommand=self.scroll.set)
self.scroll.config(command=self.table.yview())
self.table["columns"] = ("ID", "User", "Site name", "Username")
self.table.column("#0", width=0, stretch=NO)
for i in self.table["columns"]:
self.table.column(i, anchor=W, width=200)
self.table.heading("#0", text="", anchor=CENTER)
for j in self.table["columns"]:
self.table.heading(j, text=j, anchor=W)
id = 0
for k in dao.get_user_data(USER_ID):
self.table.insert(parent="", index=id, iid=str(id), text="", values=k)
id += 1
self.table.bind("<<TreeviewSelect>>", lambda event: self.add_id_to_list())
self.scroll.pack(side=RIGHT, fill=Y)
self.table.pack()
self.config(text="Database passwords")
self.pack(padx=40, pady=40)
[docs] def add_id_to_list(self):
"""
This method is called when the user clicks into a table row and adds the id of the password to the list. This
list is called by :py:meth:`.HomeFrame.copy_to_clipboard`
"""
selected = self.table.item(self.table.selection()[0], "values")[0]
self.idList.insert(0, selected)
[docs]class ButtonPanel(PanedWindow):
"""
.. class:: ButtonPanel
This class is used to display a custom panel with three buttons. These buttons are the ones to `add`, `modify` and
`delete` passwords. When these buttons are pressed they raise their respective frames to perform the actions
except to delete a password.
"""
def __init__(self, root, master, user):
PanedWindow.__init__(self, root)
self.master = master
self.root = root
self.user = user
self.add_password = Button(
root,
text="Add",
bg="green3",
fg="black",
activebackground="green1",
command=lambda: self.add_new_password(),
)
self.modify_password = Button(
root,
text="Modify",
bg="orange3",
activebackground="orange1",
fg="black",
command=self.modify_password,
)
self.delete_password = Button(
root,
text="Delete",
bg="red3",
activebackground="red1",
fg="black",
command=self.delete_password,
)
self.add_password.grid(column=3, row=0, pady=10, padx=20, ipadx=40)
self.modify_password.grid(column=3, row=1, pady=10, padx=20, ipadx=30)
self.delete_password.grid(column=3, row=2, pady=10, padx=20, ipadx=30)
[docs] def add_new_password(self):
"""
This function is called when the user clicks the ``Add password`` button. When called, this function raises
the :py:mod:`GUI.AddPassFrame`.
"""
add_password_frame = AddPassFrame(
root=self.root, master=self.master, user_id=USER_ID
)
add_password_frame.tkraise()
[docs] def delete_password(self):
"""
This function is called when the user clicks the ``Delete password`` button. To delete a password the user
just needs to select the row wanted and press the button. This function will check the id of the password
selected and delete it after the user confirms the questions.
:except: This function excepts an ``IndexError`` if the user did not select any row from the table
"""
try:
if len(self.root.label_frame.table.selection()) == 1:
selected = self.root.label_frame.table.item(
self.root.label_frame.table.selection()[0], "values"
)[0]
ask = message.askyesno(
"Deleting password",
"Are you sure you want to delete this password?",
)
if ask:
dao.delete_one_password(id=selected)
self.root.refresh_table(self.master, USER_ID)
else:
ask = message.askyesno(
"Deleting password",
"Are you sure you want to delete this passwords?",
)
if ask:
dao.delete_many_passwords(self.root.label_frame.idList)
self.root.refresh_table(self.master, USER_ID)
except IndexError:
message.showerror(
"Error", "You have to select an entry of the table to delete it"
)
# try:
# selected = self.root.labelFrame.table.item(self.root.labelFrame.table.selection()[0], 'values')[0]
# ask = message.askyesno("Deleting password", "Are you sure you want to delete this password?")
# if ask:
# dao.deleteOnePassword(ID=selected)
# self.root.refreshTable(self.master)
# except IndexError:
# message.showerror("Error", "You have to select an entry of the table to delete it")
[docs] def modify_password(self):
"""
This function is called when the user clicks the ``Modify password`` button. To modify a password the user
has to select the password wanted in the database and then click the button.
The function checks the id of the password selected and then raises the :py:mod:`GUI.ModifyPassFrame`. If the
user did not select a password and clicks the button it will show an error message.
:except: This functions excepts an ``IndexError`` if the user did not select any row from the table and displays
an error message
"""
try:
selected = self.root.label_frame.table.item(
self.root.label_frame.table.selection()[0], "values"
)[0]
modify_password_frame = ModifyPassFrame(
root=self.root, master=self.master, password_id=selected, user=USER_ID
)
modify_password_frame.tkraise()
except IndexError:
message.showerror("Error", "You need to select first an entry to modify it")