Advertisement
MizunoBrasil

Gerenciador de Senhas v. 5.2

Aug 18th, 2024 (edited)
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.72 KB | Source Code | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, messagebox
  3. import sqlite3
  4. import pyperclip
  5. import webbrowser
  6.  
  7. class Application(tk.Tk):
  8.     def __init__(self):
  9.         super().__init__()
  10.         self.title("Gerenciador de Senhas de Sites - Versão 5.2")
  11.         self.geometry("1000x600")
  12.         self.sort_order_site = "asc"
  13.         self.sort_order_login = "asc"
  14.         self.init_db()  # Inicializa o banco de dados primeiro
  15.         self.create_widgets()
  16.         self.create_menu()
  17.         self.date_label = ttk.Label(self, text="Mizuno - 18/08/2024")
  18.         self.date_label.place(x=10, y=self.winfo_height() - 30)
  19.         self.center_window()
  20.  
  21.     def create_widgets(self):
  22.         self.search_var = tk.StringVar()
  23.         self.search_entry = ttk.Entry(self, textvariable=self.search_var)
  24.         self.search_entry.pack(pady=(0, 10))
  25.         self.search_button = ttk.Button(self, text="Pesquisar", command=self.search_records)
  26.         self.search_button.pack(pady=(0, 10))
  27.         self.tree = ttk.Treeview(self, columns=("Site", "URL", "Login", "Senha"), show="headings")
  28.         self.tree.heading("Site", text="Site", command=self.sort_sites)
  29.         self.tree.heading("URL", text="URL")
  30.         self.tree.heading("Login", text="Login", command=self.sort_login)
  31.         self.tree.heading("Senha", text="Senha")
  32.         self.tree.pack(pady=10, side="left", fill="both", expand=True)
  33.         scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.tree.yview)
  34.         scrollbar.pack(side="right", fill="y")
  35.         self.tree.configure(yscrollcommand=scrollbar.set)
  36.         self.refresh_button = ttk.Button(self, text="Atualizar", command=self.refresh_tree)
  37.         self.refresh_button.pack()
  38.         self.add_button = ttk.Button(self, text="Adicionar", command=self.add_entry)
  39.         self.add_button.pack()
  40.         self.edit_button = ttk.Button(self, text="Editar", command=self.edit_entry)
  41.         self.edit_button.pack()
  42.         self.delete_button = ttk.Button(self, text="Excluir", command=self.confirm_delete)
  43.         self.delete_button.pack()
  44.         self.load_data()
  45.         self.tree.bind("<Button-3>", self.popup_menu)
  46.         self.tree.bind("<Double-1>", self.open_url)
  47.  
  48.     def create_menu(self):
  49.         self.menu_bar = tk.Menu(self)
  50.         self.file_menu = tk.Menu(self.menu_bar, tearoff=0)
  51.         self.file_menu.add_command(label="Sobre", command=self.show_about_dialog)
  52.         self.file_menu.add_separator()
  53.         self.file_menu.add_command(label="Sair", command=self.quit_app)
  54.         self.menu_bar.add_cascade(label="Arquivo", menu=self.file_menu)
  55.         self.config(menu=self.menu_bar)
  56.  
  57.     def open_url(self, event):
  58.         if self.tree.selection():
  59.             item = self.tree.selection()[0]
  60.             url = self.tree.item(item, "values")[1]
  61.             webbrowser.open(url)
  62.  
  63.     def center_window(self):
  64.         self.update_idletasks()
  65.         width = self.winfo_width()
  66.         height = self.winfo_height()
  67.         x = (self.winfo_screenwidth() - width) // 2
  68.         y = (self.winfo_screenheight() - height) // 2
  69.         self.geometry('{}x{}+{}+{}'.format(width, height, x, y))
  70.  
  71.     def init_db(self):
  72.         self.conn = sqlite3.connect("dados.db")
  73.         self.cursor = self.conn.cursor()
  74.         self.cursor.execute("""
  75.            CREATE TABLE IF NOT EXISTS senhas (
  76.                id INTEGER PRIMARY KEY AUTOINCREMENT,
  77.                site TEXT,
  78.                url TEXT,
  79.                login TEXT,
  80.                senha TEXT
  81.            )
  82.        """)
  83.         self.conn.commit()
  84.  
  85.     def load_data(self):
  86.         self.cursor.execute("SELECT site, url, login, senha FROM senhas")
  87.         for row in self.cursor.fetchall():
  88.             self.tree.insert("", "end", values=row)
  89.  
  90.     def save_data(self):
  91.         self.cursor.execute("DELETE FROM senhas")
  92.         for item in self.tree.get_children():
  93.             values = self.tree.item(item, "values")
  94.             self.cursor.execute("INSERT INTO senhas (site, url, login, senha) VALUES (?, ?, ?, ?)", values)
  95.         self.conn.commit()
  96.  
  97.     def refresh_tree(self):
  98.         for item in self.tree.get_children():
  99.             self.tree.delete(item)
  100.         self.load_data()
  101.  
  102.     def add_entry(self):
  103.         AddEntryWindow(self)
  104.  
  105.     def edit_entry(self):
  106.         try:
  107.             item = self.tree.selection()[0]
  108.             values = self.tree.item(item, "values")
  109.             EditEntryWindow(self, values)
  110.         except IndexError:
  111.             messagebox.showerror("Erro", "Selecione um registro para editar.")
  112.  
  113.     def delete_entry(self):
  114.         selected_item = self.tree.selection()[0]
  115.         site = self.tree.item(selected_item, "values")[0]
  116.         self.cursor.execute("DELETE FROM senhas WHERE site=?", (site,))
  117.         self.conn.commit()
  118.         self.tree.delete(selected_item)
  119.  
  120.     def confirm_delete(self):
  121.         try:
  122.             if messagebox.askyesno("Confirmar", "Tem certeza que deseja excluir este registro?"):
  123.                 self.delete_entry()
  124.         except IndexError:
  125.             messagebox.showerror("Erro", "Selecione um registro para excluir.")
  126.  
  127.     def popup_menu(self, event):
  128.         popup_menu = tk.Menu(self, tearoff=0)
  129.         popup_menu.add_command(label="Copiar URL", command=lambda: self.copy_to_clipboard(1))
  130.         popup_menu.add_command(label="Copiar Login", command=lambda: self.copy_to_clipboard(2))
  131.         popup_menu.add_command(label="Copiar Senha", command=lambda: self.copy_to_clipboard(3))
  132.         popup_menu.post(event.x_root, event.y_root)
  133.  
  134.     def copy_to_clipboard(self, column_index):
  135.         item = self.tree.selection()[0]
  136.         value = self.tree.item(item, "values")[column_index]
  137.         pyperclip.copy(value)
  138.  
  139.     def sort_sites(self):
  140.         items = self.tree.get_children("")
  141.         if self.sort_order_site == "asc":
  142.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[0])
  143.             self.sort_order_site = "desc"
  144.         else:
  145.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[0], reverse=True)
  146.             self.sort_order_site = "asc"
  147.         for item in sorted_items:
  148.             self.tree.move(item, "", "end")
  149.  
  150.     def sort_login(self):
  151.         items = self.tree.get_children("")
  152.         if self.sort_order_login == "asc":
  153.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[2])
  154.             self.sort_order_login = "desc"
  155.         else:
  156.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[2], reverse=True)
  157.             self.sort_order_login = "asc"
  158.         for item in sorted_items:
  159.             self.tree.move(item, "", "end")
  160.  
  161.     def show_about_dialog(self):
  162.         messagebox.showinfo("Sobre", "Filtre os dados por Site ou por Login ou pesquise na caixa de texto.\n\nVersão 5.2 - Última atualização: 18/08/2024, by Mizuno.")
  163.  
  164.     def quit_app(self):
  165.         self.conn.close()
  166.         self.destroy()
  167.  
  168.     def search_records(self):
  169.         search_term = self.search_var.get().strip().lower()
  170.         if not search_term:
  171.             messagebox.showinfo("Pesquisa", "Digite um termo de pesquisa.")
  172.             return
  173.  
  174.         # Limpa a TreeView antes de preencher com os resultados da pesquisa
  175.         for item in self.tree.get_children():
  176.             self.tree.delete(item)
  177.  
  178.         self.cursor.execute("""
  179.            SELECT site, url, login, senha FROM senhas
  180.            WHERE lower(site) LIKE ? OR lower(url) LIKE ? OR lower(login) LIKE ?
  181.        """, ('%' + search_term + '%', '%' + search_term + '%', '%' + search_term + '%'))
  182.  
  183.         found = False
  184.         for row in self.cursor.fetchall():
  185.             self.tree.insert("", "end", values=row)
  186.             found = True
  187.  
  188.         if not found:
  189.             messagebox.showinfo("Pesquisa", "Nenhum registro correspondente encontrado.")
  190.             self.refresh_tree()  # Chama a função de atualização da árvore diretamente após fechar o alerta
  191.  
  192. class AddEntryWindow(tk.Toplevel):
  193.     def __init__(self, parent):
  194.         super().__init__(parent)
  195.         self.title("Adicionar Entrada")
  196.         self.geometry("400x300")
  197.         self.create_widgets()
  198.  
  199.     def create_widgets(self):
  200.         self.site_label = ttk.Label(self, text="Site:")
  201.         self.site_label.pack(pady=5)
  202.         self.site_entry = ttk.Entry(self)
  203.         self.site_entry.pack(pady=5)
  204.  
  205.         self.url_label = ttk.Label(self, text="URL:")
  206.         self.url_label.pack(pady=5)
  207.         self.url_entry = ttk.Entry(self)
  208.         self.url_entry.pack(pady=5)
  209.  
  210.         self.login_label = ttk.Label(self, text="Login:")
  211.         self.login_label.pack(pady=5)
  212.         self.login_entry = ttk.Entry(self)
  213.         self.login_entry.pack(pady=5)
  214.  
  215.         self.senha_label = ttk.Label(self, text="Senha:")
  216.         self.senha_label.pack(pady=5)
  217.         self.senha_entry = ttk.Entry(self)
  218.         self.senha_entry.pack(pady=5)
  219.  
  220.         self.save_button = ttk.Button(self, text="Salvar", command=self.save_entry)
  221.         self.save_button.pack(pady=20)
  222.  
  223.     def save_entry(self):
  224.         site = self.site_entry.get().strip()
  225.         url = self.url_entry.get().strip()
  226.         login = self.login_entry.get().strip()
  227.         senha = self.senha_entry.get().strip()
  228.         if site and url and login and senha:
  229.             self.master.cursor.execute("INSERT INTO senhas (site, url, login, senha) VALUES (?, ?, ?, ?)",
  230.                                        (site, url, login, senha))
  231.             self.master.conn.commit()
  232.             self.master.refresh_tree()
  233.             self.destroy()
  234.         else:
  235.             messagebox.showerror("Erro", "Todos os campos devem ser preenchidos.")
  236.  
  237. class EditEntryWindow(tk.Toplevel):
  238.     def __init__(self, parent, values):
  239.         super().__init__(parent)
  240.         self.title("Editar Entrada")
  241.         self.geometry("400x300")
  242.         self.values = values
  243.         self.create_widgets()
  244.  
  245.     def create_widgets(self):
  246.         self.site_label = ttk.Label(self, text="Site:")
  247.         self.site_label.pack(pady=5)
  248.         self.site_entry = ttk.Entry(self)
  249.         self.site_entry.insert(0, self.values[0])
  250.         self.site_entry.pack(pady=5)
  251.  
  252.         self.url_label = ttk.Label(self, text="URL:")
  253.         self.url_label.pack(pady=5)
  254.         self.url_entry = ttk.Entry(self)
  255.         self.url_entry.insert(0, self.values[1])
  256.         self.url_entry.pack(pady=5)
  257.  
  258.         self.login_label = ttk.Label(self, text="Login:")
  259.         self.login_label.pack(pady=5)
  260.         self.login_entry = ttk.Entry(self)
  261.         self.login_entry.insert(0, self.values[2])
  262.         self.login_entry.pack(pady=5)
  263.  
  264.         self.senha_label = ttk.Label(self, text="Senha:")
  265.         self.senha_label.pack(pady=5)
  266.         self.senha_entry = ttk.Entry(self)
  267.         self.senha_entry.insert(0, self.values[3])
  268.         self.senha_entry.pack(pady=5)
  269.  
  270.         self.save_button = ttk.Button(self, text="Salvar", command=self.save_entry)
  271.         self.save_button.pack(pady=20)
  272.  
  273.     def save_entry(self):
  274.         site = self.site_entry.get().strip()
  275.         url = self.url_entry.get().strip()
  276.         login = self.login_entry.get().strip()
  277.         senha = self.senha_entry.get().strip()
  278.         if site and url and login and senha:
  279.             selected_item = self.master.tree.selection()[0]
  280.             self.master.cursor.execute("""
  281.                UPDATE senhas
  282.                SET site = ?, url = ?, login = ?, senha = ?
  283.                WHERE site = ?
  284.            """, (site, url, login, senha, self.values[0]))
  285.             self.master.conn.commit()
  286.             self.master.refresh_tree()
  287.             self.destroy()
  288.         else:
  289.             messagebox.showerror("Erro", "Todos os campos devem ser preenchidos.")
  290.  
  291. def main():
  292.     app = Application()
  293.     app.mainloop()
  294.  
  295. if __name__ == "__main__":
  296.     main()
  297.  
Tags: python CRUD
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement