Добавлена бета версия
This commit is contained in:
297
main.py
Normal file
297
main.py
Normal file
@@ -0,0 +1,297 @@
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
|
||||
from api import get_repo_data, get_commits, get_code_lines
|
||||
from parser import parse_repo_info, parse_authors
|
||||
from storage import (
|
||||
register_user,
|
||||
check_user,
|
||||
get_repositories,
|
||||
add_repository,
|
||||
delete_repository,
|
||||
)
|
||||
|
||||
|
||||
class GiteaAnalyzerApp:
|
||||
def __init__(self):
|
||||
self.root = tk.Tk()
|
||||
self.root.title("Gitea Analyzer")
|
||||
self.root.geometry("1200x750")
|
||||
self.root.minsize(1000, 650)
|
||||
self.root.resizable(True, True)
|
||||
self.current_user = None
|
||||
|
||||
self.bg = "#eef4ff"
|
||||
self.panel = "#ffffff"
|
||||
self.button = "#6aa6ff"
|
||||
self.root.configure(bg=self.bg)
|
||||
|
||||
self.show_splash()
|
||||
self.root.mainloop()
|
||||
|
||||
def clear(self):
|
||||
for widget in self.root.winfo_children():
|
||||
widget.destroy()
|
||||
|
||||
def make_button(self, parent, text, command, width=24):
|
||||
return tk.Button(
|
||||
parent,
|
||||
text=text,
|
||||
command=command,
|
||||
width=width,
|
||||
bg=self.button,
|
||||
fg="white",
|
||||
activebackground="#4d8ee8",
|
||||
activeforeground="white",
|
||||
font=("Arial", 11, "bold"),
|
||||
relief="flat",
|
||||
cursor="hand2",
|
||||
pady=6,
|
||||
)
|
||||
|
||||
def show_splash(self):
|
||||
self.clear()
|
||||
|
||||
frame = tk.Frame(self.root, bg=self.bg)
|
||||
frame.pack(expand=True)
|
||||
|
||||
tk.Label(
|
||||
frame,
|
||||
text="Gitea Repository Analyzer",
|
||||
font=("Arial", 28, "bold"),
|
||||
bg=self.bg,
|
||||
fg="#1d3557",
|
||||
).pack(pady=20)
|
||||
|
||||
tk.Label(
|
||||
frame,
|
||||
text="Анализ репозиториев: автор, соавторы, даты и строки Python-кода",
|
||||
font=("Arial", 14),
|
||||
bg=self.bg,
|
||||
fg="#333333",
|
||||
).pack(pady=10)
|
||||
|
||||
tk.Label(
|
||||
frame,
|
||||
text="Загрузка...",
|
||||
font=("Arial", 12),
|
||||
bg=self.bg,
|
||||
fg="#555555",
|
||||
).pack(pady=30)
|
||||
|
||||
self.root.after(1200, self.show_login)
|
||||
|
||||
def show_login(self):
|
||||
self.clear()
|
||||
|
||||
frame = tk.Frame(self.root, bg=self.panel, padx=35, pady=35)
|
||||
frame.place(relx=0.5, rely=0.5, anchor="center")
|
||||
|
||||
tk.Label(frame, text="Вход в аккаунт", font=("Arial", 22, "bold"), bg=self.panel).pack(pady=10)
|
||||
|
||||
tk.Label(frame, text="Логин", bg=self.panel, font=("Arial", 11)).pack(anchor="w")
|
||||
login_entry = tk.Entry(frame, width=35, font=("Arial", 12))
|
||||
login_entry.pack(pady=5)
|
||||
|
||||
tk.Label(frame, text="Пароль", bg=self.panel, font=("Arial", 11)).pack(anchor="w")
|
||||
password_entry = tk.Entry(frame, width=35, font=("Arial", 12), show="*")
|
||||
password_entry.pack(pady=5)
|
||||
|
||||
def login():
|
||||
login_value = login_entry.get().strip()
|
||||
password_value = password_entry.get().strip()
|
||||
|
||||
if not login_value or not password_value:
|
||||
messagebox.showerror("Ошибка", "Введите логин и пароль")
|
||||
return
|
||||
|
||||
if check_user(login_value, password_value):
|
||||
self.current_user = login_value
|
||||
self.show_main_screen()
|
||||
else:
|
||||
messagebox.showerror("Ошибка", "Неверный логин или пароль")
|
||||
|
||||
self.make_button(frame, "Войти", login).pack(pady=12)
|
||||
self.make_button(frame, "Создать профиль", self.show_register).pack(pady=5)
|
||||
|
||||
def show_register(self):
|
||||
self.clear()
|
||||
|
||||
frame = tk.Frame(self.root, bg=self.panel, padx=35, pady=35)
|
||||
frame.place(relx=0.5, rely=0.5, anchor="center")
|
||||
|
||||
tk.Label(frame, text="Создание профиля", font=("Arial", 22, "bold"), bg=self.panel).pack(pady=10)
|
||||
|
||||
tk.Label(frame, text="Логин", bg=self.panel, font=("Arial", 11)).pack(anchor="w")
|
||||
login_entry = tk.Entry(frame, width=35, font=("Arial", 12))
|
||||
login_entry.pack(pady=5)
|
||||
|
||||
tk.Label(frame, text="Пароль", bg=self.panel, font=("Arial", 11)).pack(anchor="w")
|
||||
password_entry = tk.Entry(frame, width=35, font=("Arial", 12), show="*")
|
||||
password_entry.pack(pady=5)
|
||||
|
||||
def register():
|
||||
login_value = login_entry.get().strip()
|
||||
password_value = password_entry.get().strip()
|
||||
|
||||
if not login_value or not password_value:
|
||||
messagebox.showerror("Ошибка", "Введите логин и пароль")
|
||||
return
|
||||
|
||||
if len(password_value) < 4:
|
||||
messagebox.showerror("Ошибка", "Пароль должен быть минимум 4 символа")
|
||||
return
|
||||
|
||||
ok, text = register_user(login_value, password_value)
|
||||
|
||||
if ok:
|
||||
messagebox.showinfo("Готово", text)
|
||||
self.show_login()
|
||||
else:
|
||||
messagebox.showerror("Ошибка", text)
|
||||
|
||||
self.make_button(frame, "Зарегистрироваться", register).pack(pady=12)
|
||||
self.make_button(frame, "Назад", self.show_login).pack(pady=5)
|
||||
|
||||
def show_main_screen(self):
|
||||
self.clear()
|
||||
|
||||
top = tk.Frame(self.root, bg="#1d3557", height=60)
|
||||
top.pack(fill="x")
|
||||
|
||||
tk.Label(
|
||||
top,
|
||||
text=f"Gitea Analyzer | Пользователь: {self.current_user}",
|
||||
bg="#1d3557",
|
||||
fg="white",
|
||||
font=("Arial", 18, "bold"),
|
||||
).pack(side="left", padx=20, pady=15)
|
||||
|
||||
tk.Button(
|
||||
top,
|
||||
text="Выйти",
|
||||
command=self.show_login,
|
||||
bg="#e63946",
|
||||
fg="white",
|
||||
activebackground="#c1121f",
|
||||
activeforeground="white",
|
||||
relief="flat",
|
||||
font=("Arial", 12),
|
||||
cursor="hand2",
|
||||
).pack(side="right", padx=20, pady=12)
|
||||
|
||||
content = tk.Frame(self.root, bg=self.bg)
|
||||
content.pack(fill="both", expand=True, padx=15, pady=15)
|
||||
|
||||
left = tk.Frame(content, bg=self.panel, padx=15, pady=15)
|
||||
left.pack(side="left", fill="y")
|
||||
|
||||
right = tk.Frame(content, bg=self.panel, padx=15, pady=15)
|
||||
right.pack(side="right", fill="both", expand=True, padx=(15, 0))
|
||||
|
||||
tk.Label(left, text="Мои репозитории", bg=self.panel, font=("Arial", 18, "bold")).pack(anchor="w")
|
||||
|
||||
repo_listbox = tk.Listbox(left, width=44, height=18, font=("Arial", 11))
|
||||
repo_listbox.pack(pady=10, fill="y")
|
||||
|
||||
tk.Label(left, text="Новая ссылка", bg=self.panel, font=("Arial", 12)).pack(anchor="w")
|
||||
|
||||
repo_entry = tk.Entry(left, width=44, font=("Arial", 11))
|
||||
repo_entry.pack(pady=5, fill="x")
|
||||
|
||||
result_text = tk.Text(right, width=70, height=28, font=("Consolas", 12), wrap="word")
|
||||
result_text.pack(fill="both", expand=True)
|
||||
|
||||
def refresh_list():
|
||||
repo_listbox.delete(0, tk.END)
|
||||
for repo in get_repositories(self.current_user):
|
||||
repo_listbox.insert(tk.END, repo)
|
||||
|
||||
def get_selected_repo():
|
||||
selection = repo_listbox.curselection()
|
||||
if not selection:
|
||||
return None
|
||||
return repo_listbox.get(selection[0])
|
||||
|
||||
def save_repo():
|
||||
link = repo_entry.get().strip()
|
||||
|
||||
if not link:
|
||||
messagebox.showerror("Ошибка", "Введите ссылку")
|
||||
return
|
||||
|
||||
added = add_repository(self.current_user, link)
|
||||
|
||||
if added:
|
||||
repo_entry.delete(0, tk.END)
|
||||
refresh_list()
|
||||
messagebox.showinfo("Готово", "Ссылка сохранена")
|
||||
else:
|
||||
messagebox.showinfo("Информация", "Эта ссылка уже сохранена")
|
||||
|
||||
def remove_repo():
|
||||
link = get_selected_repo()
|
||||
|
||||
if not link:
|
||||
messagebox.showerror("Ошибка", "Выберите репозиторий")
|
||||
return
|
||||
|
||||
delete_repository(self.current_user, link)
|
||||
refresh_list()
|
||||
result_text.delete("1.0", tk.END)
|
||||
|
||||
def analyze_repo(repo_link=None):
|
||||
link = repo_link or get_selected_repo()
|
||||
|
||||
if not link:
|
||||
messagebox.showerror("Ошибка", "Выберите репозиторий")
|
||||
return
|
||||
|
||||
try:
|
||||
result_text.delete("1.0", tk.END)
|
||||
result_text.insert(tk.END, "Загрузка данных...\n")
|
||||
self.root.update()
|
||||
|
||||
repo_data = get_repo_data(link)
|
||||
commits = get_commits(link)
|
||||
lines = get_code_lines(link)
|
||||
|
||||
info = parse_repo_info(repo_data)
|
||||
authors = parse_authors(commits)
|
||||
|
||||
owner = repo_data.get("owner", {}).get("login", "—")
|
||||
|
||||
coauthors = []
|
||||
for author in authors:
|
||||
if author != owner:
|
||||
coauthors.append(author)
|
||||
|
||||
result_text.delete("1.0", tk.END)
|
||||
result_text.insert(tk.END, f"Ссылка:\n{link}\n\n")
|
||||
result_text.insert(tk.END, info)
|
||||
|
||||
result_text.insert(tk.END, "\nАвтор репозитория:\n")
|
||||
result_text.insert(tk.END, f"- {owner}\n")
|
||||
|
||||
result_text.insert(tk.END, "\nСоавторы по коммитам:\n")
|
||||
if coauthors:
|
||||
for author in coauthors:
|
||||
result_text.insert(tk.END, f"- {author}\n")
|
||||
else:
|
||||
result_text.insert(tk.END, "- нет соавторов\n")
|
||||
|
||||
result_text.insert(tk.END, f"\nСтрок Python-кода: {lines}\n")
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("Ошибка", str(e))
|
||||
result_text.delete("1.0", tk.END)
|
||||
|
||||
self.make_button(left, "Сохранить ссылку", save_repo).pack(pady=5)
|
||||
self.make_button(left, "Обновить информацию", analyze_repo).pack(pady=5)
|
||||
self.make_button(left, "Удалить ссылку", remove_repo).pack(pady=5)
|
||||
|
||||
refresh_list()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
GiteaAnalyzerApp()
|
||||
Reference in New Issue
Block a user