TV/tkinter_ui/tkinter_ui.py
2025-01-08 17:13:26 +08:00

251 lines
9.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import sys
sys.path.append(os.path.dirname(sys.path[0]))
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
from utils.config import config
from utils.tools import resource_path, get_version_info
from main import UpdateSource
import asyncio
import threading
import webbrowser
from about import AboutUI
from default import DefaultUI
from speed import SpeedUI
from prefer import PreferUI
from multicast import MulticastUI
from hotel import HotelUI
from subscribe import SubscribeUI
from online_search import OnlineSearchUI
from utils.speed import check_ffmpeg_installed_status
class TkinterUI:
def __init__(self, root):
info = get_version_info()
self.root = root
self.root.title(info.get("name", ""))
self.version = info.get("version", "")
self.about_ui = AboutUI()
self.default_ui = DefaultUI()
self.speed_ui = SpeedUI()
self.prefer_ui = PreferUI()
self.multicast_ui = MulticastUI()
self.hotel_ui = HotelUI()
self.subscribe_ui = SubscribeUI()
self.online_search_ui = OnlineSearchUI()
self.update_source = UpdateSource()
self.update_running = False
self.result_url = None
def view_result_link_callback(self, event):
webbrowser.open_new_tab(self.result_url)
def save_config(self):
config.save()
messagebox.showinfo("提示", "保存成功")
def change_state(self, state):
self.default_ui.change_entry_state(state=state)
self.speed_ui.change_entry_state(state=state)
self.prefer_ui.change_entry_state(state=state)
self.multicast_ui.change_entry_state(state=state)
self.hotel_ui.change_entry_state(state=state)
self.subscribe_ui.change_entry_state(state=state)
self.online_search_ui.change_entry_state(state=state)
async def run_update(self):
self.update_running = not self.update_running
if self.update_running:
self.run_button.config(text="取消更新", state="normal")
self.change_state("disabled")
self.progress_bar["value"] = 0
self.progress_label.pack()
self.view_result_link.pack()
self.progress_bar.pack()
await self.update_source.start(self.update_progress)
else:
self.stop()
self.update_source.stop()
self.run_button.config(text="开始更新", state="normal")
self.change_state("normal")
self.progress_bar.pack_forget()
self.view_result_link.pack_forget()
self.progress_label.pack_forget()
def on_run_update(self):
if not self.update_running and config.open_filter_resolution and not check_ffmpeg_installed_status():
if messagebox.askyesno("提示",
"使用分辨率相关功能需要安装FFmpeg为了实现更佳的观看体验\n是否前往官网下载?"):
return webbrowser.open("https://ffmpeg.org")
loop = asyncio.new_event_loop()
def run_loop():
asyncio.set_event_loop(loop)
loop.run_until_complete(self.run_update())
self.thread = threading.Thread(target=run_loop, daemon=True)
self.thread.start()
def stop(self):
asyncio.get_event_loop().stop()
def update_progress(self, title, progress, finished=False, url=None):
self.progress_bar["value"] = progress
progress_text = f"{title}, 进度: {progress}%" if not finished else f"{title}"
self.progress_label["text"] = progress_text
self.root.update()
if finished:
self.run_button.config(text="开始更新", state="normal")
self.update_running = False
self.change_state("normal")
if url:
self.view_result_link.config(text=url)
self.result_url = url
def init_UI(self):
menu_bar = tk.Menu(self.root)
help_menu = tk.Menu(menu_bar, tearoff=0)
help_menu.add_command(
label="关于",
command=lambda: self.about_ui.init_ui(root=self.root, version=self.version),
)
menu_bar.add_cascade(label="帮助", menu=help_menu)
self.root.config(menu=menu_bar)
notebook = tk.ttk.Notebook(self.root)
notebook.pack(fill="both", padx=10, pady=5)
frame_default = tk.ttk.Frame(notebook)
frame_speed = tk.ttk.Frame(notebook)
frame_prefer = tk.ttk.Frame(notebook)
frame_hotel = tk.ttk.Frame(notebook)
frame_multicast = tk.ttk.Frame(notebook)
frame_subscribe = tk.ttk.Frame(notebook)
frame_online_search = tk.ttk.Frame(notebook)
settings_icon_source = Image.open(
resource_path("static/images/settings_icon.png")
).resize((16, 16))
settings_icon = ImageTk.PhotoImage(settings_icon_source)
speed_icon_source = Image.open(
resource_path("static/images/speed_icon.png")
).resize((16, 16))
speed_icon = ImageTk.PhotoImage(speed_icon_source)
prefer_icon_source = Image.open(
resource_path("static/images/prefer_icon.png")
).resize((16, 16))
prefer_icon = ImageTk.PhotoImage(prefer_icon_source)
hotel_icon_source = Image.open(
resource_path("static/images/hotel_icon.png")
).resize((16, 16))
hotel_icon = ImageTk.PhotoImage(hotel_icon_source)
multicast_icon_source = Image.open(
resource_path("static/images/multicast_icon.png")
).resize((16, 16))
multicast_icon = ImageTk.PhotoImage(multicast_icon_source)
subscribe_icon_source = Image.open(
resource_path("static/images/subscribe_icon.png")
).resize((16, 16))
subscribe_icon = ImageTk.PhotoImage(subscribe_icon_source)
online_search_icon_source = Image.open(
resource_path("static/images/online_search_icon.png")
).resize((16, 16))
online_search_icon = ImageTk.PhotoImage(online_search_icon_source)
notebook.add(
frame_default, text="通用设置", image=settings_icon, compound=tk.LEFT
)
notebook.add(frame_speed, text="测速设置", image=speed_icon, compound=tk.LEFT)
notebook.add(frame_prefer, text="偏好设置", image=prefer_icon, compound=tk.LEFT)
notebook.add(frame_hotel, text="酒店源", image=hotel_icon, compound=tk.LEFT)
notebook.add(
frame_multicast, text="组播源", image=multicast_icon, compound=tk.LEFT
)
notebook.add(
frame_subscribe, text="订阅源", image=subscribe_icon, compound=tk.LEFT
)
notebook.add(
frame_online_search,
text="关键字搜索",
image=online_search_icon,
compound=tk.LEFT,
)
notebook.settings_icon = settings_icon
notebook.speed_icon = speed_icon
notebook.prefer_icon = prefer_icon
notebook.hotel_icon = hotel_icon
notebook.multicast_icon = multicast_icon
notebook.subscribe_icon = subscribe_icon
notebook.online_search_icon = online_search_icon
self.default_ui.init_ui(frame_default)
self.speed_ui.init_ui(frame_speed)
self.prefer_ui.init_ui(frame_prefer)
self.multicast_ui.init_ui(frame_multicast)
self.hotel_ui.init_ui(frame_hotel)
self.subscribe_ui.init_ui(frame_subscribe)
self.online_search_ui.init_ui(frame_online_search)
root_operate = tk.Frame(self.root)
root_operate.pack(fill=tk.X, pady=8, padx=120)
root_operate_column1 = tk.Frame(root_operate)
root_operate_column1.pack(side=tk.LEFT, fill=tk.Y)
root_operate_column2 = tk.Frame(root_operate)
root_operate_column2.pack(side=tk.RIGHT, fill=tk.Y)
self.save_button = tk.ttk.Button(
root_operate_column1, text="保存设置", command=self.save_config
)
self.save_button.pack(side=tk.LEFT, padx=4, pady=8)
self.run_button = tk.ttk.Button(
root_operate_column2, text="开始更新", command=self.on_run_update
)
self.run_button.pack(side=tk.LEFT, padx=4, pady=8)
root_progress = tk.Frame(self.root)
root_progress.pack(fill=tk.X)
self.progress_bar = tk.ttk.Progressbar(
root_progress, length=300, mode="determinate"
)
self.progress_bar.pack_forget()
self.progress_label = tk.Label(root_progress, text="进度: 0%")
self.progress_label.pack_forget()
self.view_result_link = tk.Label(
root_progress, text="", fg="blue", cursor="hand2"
)
self.view_result_link.bind(
"<Button-1>",
self.view_result_link_callback,
)
self.view_result_link.pack_forget()
def get_root_location(root):
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
width = 500
height = 650
x = (screen_width / 2) - (width / 2)
y = (screen_height / 2) - (height / 2)
return (width, height, x, y)
if __name__ == "__main__":
root = tk.Tk()
tkinter_ui = TkinterUI(root)
tkinter_ui.init_UI()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry("%dx%d+%d+%d" % get_root_location(root))
root.iconbitmap(resource_path("static/images/favicon.ico"))
root.after(0, config.copy)
root.mainloop()