Advertisement
MizunoBrasil

Gerenciador de Senhas v. 5.4

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