Advertisement
MizunoBrasil

Gerenciador de Senhas v. 5.5

Nov 4th, 2024
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.90 KB | None | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, messagebox
  3. import sqlite3
  4. import pyperclip
  5. import webbrowser
  6. from reportlab.lib.pagesizes import letter, landscape
  7. from reportlab.pdfgen import canvas
  8.  
  9. class Application(tk.Tk):
  10.     def __init__(self):
  11.         super().__init__()
  12.         self.title("Gerenciador de Senhas de Sites - Versão 5.5")
  13.         self.geometry("1000x600")
  14.         self.sort_order_site = "asc"
  15.         self.sort_order_login = "asc"
  16.         self.init_db()
  17.         self.create_widgets()
  18.         self.create_menu()
  19.         self.date_label = ttk.Label(self, text="Mizuno - 02/11/2024")
  20.         self.date_label.place(x=10, y=self.winfo_height() - 30)
  21.         self.center_window()
  22.  
  23.     def create_widgets(self):
  24.         self.search_var = tk.StringVar()
  25.         self.search_entry = ttk.Entry(self, textvariable=self.search_var, width=50)
  26.         self.search_entry.pack(pady=(0, 10))
  27.  
  28.         # Vincula o evento KeyRelease para busca em tempo real
  29.         self.search_entry.bind("<KeyRelease>", lambda event: self.search_records())
  30.  
  31.         self.search_button = ttk.Button(self, text="Pesquisar", command=self.search_records)
  32.         self.search_button.pack(pady=(0, 10))
  33.  
  34.         # Botão Atualizar com o mesmo comportamento do código 1
  35.         self.refresh_button = ttk.Button(self, text="Atualizar", command=self.refresh_tree)
  36.         self.refresh_button.pack(pady=(0, 10))
  37.  
  38.         self.tree = ttk.Treeview(self, columns=("Site", "URL", "Login", "Senha"), show="headings")
  39.         self.tree.heading("Site", text="Site", command=self.sort_sites)
  40.         self.tree.heading("URL", text="URL")
  41.         self.tree.heading("Login", text="Login", command=self.sort_login)
  42.         self.tree.heading("Senha", text="Senha")
  43.         self.tree.pack(pady=10, side="left", fill="both", expand=True)
  44.  
  45.         scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.tree.yview)
  46.         scrollbar.pack(side="right", fill="y")
  47.         self.tree.configure(yscrollcommand=scrollbar.set)
  48.  
  49.         self.add_button = ttk.Button(self, text="Adicionar", command=self.add_entry)
  50.         self.add_button.pack()
  51.         self.edit_button = ttk.Button(self, text="Editar", command=self.edit_entry)
  52.         self.edit_button.pack()
  53.         self.delete_button = ttk.Button(self, text="Excluir", command=self.confirm_delete)
  54.         self.delete_button.pack()
  55.         self.pdf_button = ttk.Button(self, text="Exportar PDF", command=self.export_to_pdf)
  56.         self.pdf_button.pack()
  57.  
  58.         self.load_data()
  59.         self.tree.bind("<Button-3>", self.popup_menu)
  60.         self.tree.bind("<Double-1>", self.open_url)
  61.  
  62.     def create_menu(self):
  63.         self.menu_bar = tk.Menu(self)
  64.         self.file_menu = tk.Menu(self.menu_bar, tearoff=0)
  65.         self.file_menu.add_command(label="Sobre", command=self.show_about_dialog)
  66.         self.file_menu.add_separator()
  67.         self.file_menu.add_command(label="Sair", command=self.quit_app)
  68.         self.menu_bar.add_cascade(label="Arquivo", menu=self.file_menu)
  69.         self.config(menu=self.menu_bar)
  70.  
  71.     def open_url(self, event):
  72.         if self.tree.selection():
  73.             item = self.tree.selection()[0]
  74.             url = self.tree.item(item, "values")[1]
  75.             webbrowser.open(url)
  76.  
  77.     def center_window(self):
  78.         self.update_idletasks()
  79.         width = self.winfo_width()
  80.         height = self.winfo_height()
  81.         x = (self.winfo_screenwidth() - width) // 2
  82.         y = (self.winfo_screenheight() - height) // 2
  83.         self.geometry(f'{width}x{height}+{x}+{y}')
  84.  
  85.     def init_db(self):
  86.         self.conn = sqlite3.connect("dados.db")
  87.         self.cursor = self.conn.cursor()
  88.         self.cursor.execute("""
  89.            CREATE TABLE IF NOT EXISTS senhas (
  90.                id INTEGER PRIMARY KEY AUTOINCREMENT,
  91.                site TEXT,
  92.                url TEXT,
  93.                login TEXT,
  94.                senha TEXT
  95.            )
  96.        """)
  97.         self.conn.commit()
  98.  
  99.     def load_data(self):
  100.         self.cursor.execute("SELECT site, url, login, senha FROM senhas")
  101.         for row in self.cursor.fetchall():
  102.             self.tree.insert("", "end", values=row)
  103.  
  104.     def save_data(self):
  105.         self.cursor.execute("DELETE FROM senhas")
  106.         for item in self.tree.get_children():
  107.             values = self.tree.item(item, "values")
  108.             self.cursor.execute("INSERT INTO senhas (site, url, login, senha) VALUES (?, ?, ?, ?)", values)
  109.         self.conn.commit()
  110.  
  111.     def refresh_tree(self):
  112.         for item in self.tree.get_children():
  113.             self.tree.delete(item)
  114.         self.load_data()
  115.  
  116.     def add_entry(self):
  117.         AddEntryWindow(self)
  118.  
  119.     def edit_entry(self):
  120.         try:
  121.             item = self.tree.selection()[0]
  122.             values = self.tree.item(item, "values")
  123.             EditEntryWindow(self, values)
  124.         except IndexError:
  125.             messagebox.showerror("Erro", "Selecione um registro para editar.")
  126.  
  127.     def delete_entry(self):
  128.         selected_item = self.tree.selection()[0]
  129.         site = self.tree.item(selected_item, "values")[0]
  130.         self.cursor.execute("DELETE FROM senhas WHERE site=?", (site,))
  131.         self.conn.commit()
  132.         self.tree.delete(selected_item)
  133.  
  134.     def confirm_delete(self):
  135.         try:
  136.             if messagebox.askyesno("Confirmar", "Tem certeza que deseja excluir este registro?"):
  137.                 self.delete_entry()
  138.         except IndexError:
  139.             messagebox.showerror("Erro", "Selecione um registro para excluir.")
  140.  
  141.     def popup_menu(self, event):
  142.         popup_menu = tk.Menu(self, tearoff=0)
  143.         popup_menu.add_command(label="Copiar URL", command=lambda: self.copy_to_clipboard(1))
  144.         popup_menu.add_command(label="Copiar Login", command=lambda: self.copy_to_clipboard(2))
  145.         popup_menu.add_command(label="Copiar Senha", command=lambda: self.copy_to_clipboard(3))
  146.         popup_menu.post(event.x_root, event.y_root)
  147.  
  148.     def copy_to_clipboard(self, column_index):
  149.         item = self.tree.selection()[0]
  150.         value = self.tree.item(item, "values")[column_index]
  151.         pyperclip.copy(value)
  152.  
  153.     def sort_sites(self):
  154.         items = self.tree.get_children("")
  155.         if self.sort_order_site == "asc":
  156.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[0])
  157.             self.sort_order_site = "desc"
  158.         else:
  159.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[0], reverse=True)
  160.             self.sort_order_site = "asc"
  161.         for item in sorted_items:
  162.             self.tree.move(item, "", "end")
  163.  
  164.     def sort_login(self):
  165.         items = self.tree.get_children("")
  166.         if self.sort_order_login == "asc":
  167.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[2])
  168.             self.sort_order_login = "desc"
  169.         else:
  170.             sorted_items = sorted(items, key=lambda x: self.tree.item(x, "values")[2], reverse=True)
  171.             self.sort_order_login = "asc"
  172.         for item in sorted_items:
  173.             self.tree.move(item, "", "end")
  174.  
  175.     def show_about_dialog(self):
  176.         messagebox.showinfo("Sobre", "Filtre os dados por Site ou por Login ou pesquise na caixa de texto.\n\nVersão 5.5 - Última atualização: 02/11/2024, Mizuno.")
  177.  
  178.     def quit_app(self):
  179.         self.conn.close()
  180.         self.destroy()
  181.  
  182.     def search_records(self):
  183.         search_term = self.search_var.get().strip().lower()
  184.  
  185.         # Limpa a TreeView antes de preencher com os resultados da pesquisa
  186.         for item in self.tree.get_children():
  187.             self.tree.delete(item)
  188.  
  189.         # Se não houver termo de pesquisa, exibe todos os registros
  190.         if not search_term:
  191.             self.load_data()
  192.             return
  193.  
  194.         # Realiza a consulta de acordo com o termo de pesquisa
  195.         self.cursor.execute("""
  196.            SELECT site, url, login, senha FROM senhas
  197.            WHERE lower(site) LIKE ? OR lower(url) LIKE ? OR lower(login) LIKE ?
  198.        """, ('%' + search_term + '%', '%' + search_term + '%', '%' + search_term + '%'))
  199.  
  200.         for row in self.cursor.fetchall():
  201.             self.tree.insert("", "end", values=row)
  202.  
  203.     def export_to_pdf(self):
  204.         file_name = "informacoes_exportadas.pdf"
  205.         c = canvas.Canvas(file_name, pagesize=landscape(letter))
  206.         c.setFont("Helvetica", 10)
  207.  
  208.         x_position = 40
  209.         y_position = 550
  210.  
  211.         headers = ["Site", "URL", "Login", "Senha"]
  212.         for header in headers:
  213.             c.drawString(x_position, y_position, header)
  214.             x_position += 200
  215.  
  216.         y_position -= 20
  217.         x_position = 40
  218.  
  219.         for item in self.tree.get_children():
  220.             if y_position < 40:
  221.                 c.showPage()
  222.                 c.setFont("Helvetica", 10)
  223.                 y_position = 550
  224.                 x_position = 40
  225.                 for header in headers:
  226.                     c.drawString(x_position, y_position, header)
  227.                     x_position += 200
  228.                 y_position -= 20
  229.                 x_position = 40
  230.  
  231.             values = self.tree.item(item, "values")
  232.             for value in values:
  233.                 c.drawString(x_position, y_position, str(value))
  234.                 x_position += 200
  235.             y_position -= 20
  236.             x_position = 40
  237.  
  238.         c.save()
  239.         messagebox.showinfo("Exportação de dados", f"Arquivo {file_name} foi gerado com sucesso.")
  240.  
  241. class AddEntryWindow(tk.Toplevel):
  242.     def __init__(self, parent):
  243.         super().__init__(parent)
  244.         self.title("Adicionar Entrada")
  245.         self.geometry("400x300")
  246.         self.create_widgets()
  247.         self.center_window()
  248.  
  249.     def create_widgets(self):
  250.         self.site_label = ttk.Label(self, text="Site:")
  251.         self.site_label.pack(pady=5)
  252.         self.site_entry = ttk.Entry(self, width=50)
  253.         self.site_entry.pack(pady=5)
  254.  
  255.         self.url_label = ttk.Label(self, text="URL:")
  256.         self.url_label.pack(pady=5)
  257.         self.url_entry = ttk.Entry(self, width=50)
  258.         self.url_entry.pack(pady=5)
  259.  
  260.         self.login_label = ttk.Label(self, text="Login:")
  261.         self.login_label.pack(pady=5)
  262.         self.login_entry = ttk.Entry(self, width=50)
  263.         self.login_entry.pack(pady=5)
  264.  
  265.         self.senha_label = ttk.Label(self, text="Senha:")
  266.         self.senha_label.pack(pady=5)
  267.         self.senha_entry = ttk.Entry(self, width=50)
  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 center_window(self):
  274.         self.update_idletasks()
  275.         width = self.winfo_width()
  276.         height = self.winfo_height()
  277.         x = (self.winfo_screenwidth() - width) // 2
  278.         y = (self.winfo_screenheight() - height) // 2
  279.         self.geometry(f'{width}x{height}+{x}+{y}')
  280.  
  281.     def save_entry(self):
  282.         site = self.site_entry.get().strip()
  283.         url = self.url_entry.get().strip()
  284.         login = self.login_entry.get().strip()
  285.         senha = self.senha_entry.get().strip()
  286.         if site and url and login and senha:
  287.             self.master.cursor.execute("INSERT INTO senhas (site, url, login, senha) VALUES (?, ?, ?, ?)",
  288.                                        (site, url, login, senha))
  289.             self.master.conn.commit()
  290.             self.master.refresh_tree()
  291.             self.destroy()
  292.         else:
  293.             messagebox.showerror("Erro", "Todos os campos devem ser preenchidos.")
  294.  
  295. class EditEntryWindow(tk.Toplevel):
  296.     def __init__(self, parent, values):
  297.         super().__init__(parent)
  298.         self.title("Editar Entrada")
  299.         self.geometry("400x300")
  300.         self.values = values
  301.         self.create_widgets()
  302.         self.center_window()
  303.  
  304.     def create_widgets(self):
  305.         self.site_label = ttk.Label(self, text="Site:")
  306.         self.site_label.pack(pady=5)
  307.         self.site_entry = ttk.Entry(self, width=50)
  308.         self.site_entry.pack(pady=5)
  309.         self.site_entry.insert(0, self.values[0])
  310.  
  311.         self.url_label = ttk.Label(self, text="URL:")
  312.         self.url_label.pack(pady=5)
  313.         self.url_entry = ttk.Entry(self, width=50)
  314.         self.url_entry.pack(pady=5)
  315.         self.url_entry.insert(0, self.values[1])
  316.  
  317.         self.login_label = ttk.Label(self, text="Login:")
  318.         self.login_label.pack(pady=5)
  319.         self.login_entry = ttk.Entry(self, width=50)
  320.         self.login_entry.pack(pady=5)
  321.         self.login_entry.insert(0, self.values[2])
  322.  
  323.         self.senha_label = ttk.Label(self, text="Senha:")
  324.         self.senha_label.pack(pady=5)
  325.         self.senha_entry = ttk.Entry(self, width=50)
  326.         self.senha_entry.pack(pady=5)
  327.         self.senha_entry.insert(0, self.values[3])
  328.  
  329.         self.save_button = ttk.Button(self, text="Salvar", command=self.save_entry)
  330.         self.save_button.pack(pady=20)
  331.  
  332.     def center_window(self):
  333.         self.update_idletasks()
  334.         width = self.winfo_width()
  335.         height = self.winfo_height()
  336.         x = (self.winfo_screenwidth() - width) // 2
  337.         y = (self.winfo_screenheight() - height) // 2
  338.         self.geometry(f'{width}x{height}+{x}+{y}')
  339.  
  340.     def save_entry(self):
  341.         site = self.site_entry.get().strip()
  342.         url = self.url_entry.get().strip()
  343.         login = self.login_entry.get().strip()
  344.         senha = self.senha_entry.get().strip()
  345.         if site and url and login and senha:
  346.             selected_item = self.master.tree.selection()[0]
  347.             self.master.cursor.execute("""
  348.                UPDATE senhas
  349.                SET site = ?, url = ?, login = ?, senha = ?
  350.                WHERE site = ?
  351.            """, (site, url, login, senha, self.values[0]))
  352.             self.master.conn.commit()
  353.             self.master.refresh_tree()
  354.             self.destroy()
  355.         else:
  356.             messagebox.showerror("Erro", "Todos os campos devem ser preenchidos.")
  357.  
  358. def main():
  359.     app = Application()
  360.     app.mainloop()
  361.  
  362. if __name__ == "__main__":
  363.     main()
  364.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement