@@ -1,11 +1,14 @@
import sys
import tkinter as tk
from tkinter import ttk , messagebox
from pathlib import Path
import logging
import os
from PIL import Image , ImageTk
import time
from PIL import Image
from PyQt5 . QtWidgets import ( QMainWindow , QWidget , QVBoxLayout , QHBoxLayout ,
QLabel , QLineEdit , QPushButton , QFrame , QTextEdit ,
QMessageBox , QApplication )
from PyQt5 . QtCore import Qt , QTimer
from PyQt5 . QtGui import QIcon , QPixmap
sys . path . append ( str ( Path ( __file__ ) . parent . parent ) )
from utils . config import Config
@@ -20,149 +23,120 @@ def get_version():
logging . error ( f " 读取版本号失败: { str ( e ) } " )
return " 未知版本 "
class MainWindow :
class MainWindow ( QMainWindow ) :
def __init__ ( self ) :
super ( ) . __init__ ( )
self . config = Config ( )
self . switcher = AccountSwitcher ( )
self . root = tk . Tk ( )
version = get_version ( )
cursor_version = self . switcher . get_cursor_version ( )
self . root . t itle( f " 听泉Cursor助手 v { version } (本机Cursor版本: { cursor_version } ) " )
self . root . geometry ( " 600x500 " ) # 调整窗口大小
self . root . resizable ( True , True ) # 允许调整窗口大小
# 设置窗口最小尺寸
self . root . minsize ( 600 , 500 )
self . setWindowT itle( f " 听泉Cursor助手 v { version } (本机Cursor版本: { cursor_version } ) " )
self . setMinimumSize ( 600 , 500 )
# 设置图标
try :
# 设置图标 - 使用PIL
current_dir = os . path . dirname ( os . path . abspath ( __file__ ) )
icon_path = os . path . join ( os . path . dirname ( current_dir ) , " icon " , " th.jpg " )
if os . path . exists ( icon_path ) :
# 打开并调整图片大小
img = Image . open ( icon_path )
img = img . resize ( ( 32 , 32 ) , Image . Resampling . LANCZOS )
# 转换为PhotoImage
self . icon = ImageTk . PhotoImage ( img )
self . root . iconphoto ( True , self . icon )
self . setWindowIcon ( QIcon ( icon_path ) )
logging . info ( f " 成功加载图标: { icon_path } " )
else :
logging . error ( f " 图标文件不存在: { icon_path } " )
except Exception as e :
logging . error ( f " 设置图标失败: { str ( e ) } " )
# 设置关闭窗口处理
self . root . protocol ( " WM_DELETE_WINDOW " , self . on_closing )
# 创建主窗口部件
central_widget = QWidget ( )
self . setCentralWidget ( central_widget )
# 初始化状态变量
self . status_var = tk . StringVar ( value = " " )
# 设置样式
self . style = ttk . Style ( )
self . style . configure ( " TButton " , padding = 5 , font = ( " Microsoft YaHei UI " , 9 ) )
self . style . configure ( " TLabelframe " , padding = 10 , font = ( " Microsoft YaHei UI " , 9 ) )
self . style . configure ( " TLabel " , padding = 2 , font = ( " Microsoft YaHei UI " , 9 ) )
self . style . configure ( " Custom.TButton " , padding = 10 , font = ( " Microsoft YaHei UI " , 9 ) )
self . style . configure ( " Action.TButton " , padding = 8 , font = ( " Microsoft YaHei UI " , 9 ) )
self . setup_ui ( )
# 启动时检查一次状态
self . check_status ( )
def setup_ui ( self ) :
""" 设置UI界面 """
# 主框架
main_frame = ttk . Frame ( self . root , padding = 10 )
main_frame . pack ( fill = " both " , expand = True )
# 功能菜单
menu_frame = ttk . Frame ( main_frame )
menu_frame . pack ( fill = " x " , pady = ( 0 , 10 ) )
ttk . Label ( menu_frame , text = " 功能(F) " ) . pack ( side = " left " )
# 创建主布局
main_layout = QVBoxLayout ( central_widget )
# 设备ID区域
device_frame = ttk . Frame ( main_frame )
device_frame . pack ( fill = " x " , pady = ( 0 , 10 ) )
ttk . Label ( device_frame , text = " 设备识别码(勿动): " ) . pack ( side = " left " )
self . hardware_id_var = tk . StringVar ( value = self . switcher . hardware_id )
device_id_entry = ttk . Entry ( device_frame , textvariable = self . hardware_id_var , width = 35 , state = " readonly " )
device_id_entry . pack ( side = " left " , padx = 5 )
copy_btn = ttk . Button ( device_frame , text = " 复制ID " , command = self . copy_device_id , width = 8 )
copy_btn . pack ( side = " left " )
device_frame = QFrame ( )
device_layout = QHBoxLayout ( device_frame )
device_layout . addWidget ( QLabel ( " 设备识别码(勿动): " ) )
self . hardware_id_edit = QLineEdit ( self . switcher . hardware_id )
self . hardware_id_edit . setReadOnly ( True )
device_layout . addWidget ( self . hardware_id_edit )
copy_btn = QPushButton ( " 复制ID " )
copy_btn . clicked . connect ( self . copy_device_id )
device_layout . addWidget ( copy_btn )
main_layout . addWidget ( device_frame )
# 会员状态区域
status_frame = ttk . LabelFrame ( main_frame , text = " 会员状态 " )
status_frame . pack ( fill = " x " , pady = ( 0 , 10 ) )
self . status_text = tk . Text ( status_frame , height = 5 , width = 40 , font = ( " Microsoft YaHei UI " , 9 ) )
self . status_text . pack ( fill = " both " , padx = 5 , pady = 5 )
self . status_text . config ( state = " disabled " )
status_frame = QFrame ( )
status_layout = QVBoxLayout ( status_frame )
status_layout . addWidget ( QLabel ( " 会员状态 " ) )
self . status_text = QTextEdit ( )
self . status_text . setReadOnly ( True )
self . status_text . setMinimumHeight ( 100 )
status_layout . addWidget ( self . status_text )
main_layout . addWidget ( status_frame )
# 激活区域
activation_frame = ttk . LabelFrame ( main_frame , text = " 激活(叠加)会员,多个激活码可叠加整体时长 " )
activation_frame . pack ( fill = " x " , pady = ( 0 , 10 ) )
input_frame = ttk . Frame ( activation_frame )
input_frame . pack ( fill = " x " , padx = 5 , pady = 5 )
ttk . Label ( input_frame , tex t= " 激活码: " ) . pack ( side = " left " )
self . activation_var = tk . StringVar ( )
activation_entry = ttk . Entry ( input_frame , textvariable = self . activation_var , width = 35 )
activation_entry . pack ( side = " left " , padx = 5 )
activate_btn = ttk . Button ( input_frame , text = " 激活 " , command = self . activate_account , width = 8 )
activate_btn . pack ( side = " left " )
activation_frame = QFrame ( )
activation_layout = QVBoxLayout ( activation_frame )
activation_layout . addWidget ( QLabel ( " 激活(叠加)会员,多个激活码可叠加整体时长 " ) )
input_frame = QFrame ( )
input_layout = QHBoxLayout ( input_frame )
input_layout . addWidget ( QLabel ( " 激活码: " ) )
self . activation_edi t = QLineEdit ( )
input_layout . addWidget ( self . activation_edit )
activate_btn = QPushButton ( " 激活 " )
activate_btn . clicked . connect ( self . activate_account )
input_layout . addWidget ( activate_btn )
activation_layout . addWidget ( input_frame )
main_layout . addWidget ( activation_frame )
# 操作按钮区域
btn_frame = ttk . Frame ( main_frame )
btn_frame . pack ( fill = " x " , pady = 5 )
btn_frame = QFrame ( )
btn_layout = QVBoxLayout ( btn_frame )
refresh_btn = QPushButton ( " 刷新Cursor编辑器授权 " )
refresh_btn . clicked . connect ( self . refresh_cursor_auth )
btn_layout . addWidget ( refresh_btn )
bypass_btn = QPushButton ( " 突破Cursor0.45.x限制 " )
bypass_btn . clicked . connect ( self . dummy_function )
btn_layout . addWidget ( bypass_btn )
disable_update_btn = QPushButton ( " 禁用Cursor版本更新 " )
disable_update_btn . clicked . connect ( self . disable_cursor_update )
btn_layout . addWidget ( disable_update_btn )
main_layout . addWidget ( btn_frame )
self . style . configure ( " Action.TButton " , padding = 8 )
ttk . Button ( btn_frame , text = " 刷新Cursor编辑器授权 " , command = self . refresh_cursor_auth , style = " Action.TButton " ) . pack ( fill = " x " , pady = 2 )
ttk . Button ( btn_frame , text = " 突破Cursor0.45.x限制 " , command = self . dummy_function , style = " Action.TButton " ) . pack ( fill = " x " , pady = 2 )
ttk . Button ( btn_frame , text = " 禁用Cursor版本更新 " , command = self . disable_cursor_update , style = " Action.TButton " ) . pack ( fill = " x " , pady = 2 )
# 启动时检查一次状态
QTimer . singleShot ( 0 , self . check_status )
def copy_device_id ( self ) :
""" 复制设备ID到剪贴板 """
# 先检查状态
if not self . check_status ( ) :
return
self . root . clipboard_clear ( )
self . root . clipboard_append ( self . hardware_id_var . get ( ) )
QApplication . clipboard ( ) . setText ( self . hardware_id_edit . text ( ) )
QMessageBox . information ( self , " 提示 " , " 设备ID已复制到剪贴板 " )
def activate_account ( self ) :
""" 激活账号 """
code = self . activation_var . ge t( ) . strip ( )
code = self . activation_edit . tex t( ) . strip ( )
if not code :
m essageb ox. show warning( " 提示 " , " 请输入激活码 " )
QM essageB ox. warning ( self , " 提示 " , " 请输入激活码 " )
return
self . status_var . set ( " 正在激活... " )
self . root . update ( )
try :
success , message , account_info = self . switcher . check_activation_code ( code )
if success :
# 更新会员信息显示
self . update_status_display ( account_info )
m essageb ox. showinfo ( " 激活成功 " , " 激活成功! \n " + message )
self . status_var . set ( " 激活成功 " )
QM essageB ox. information ( self , " 激活成功 " , " 激活成功! \n " + message )
# 清空激活码输入框
self . activation_var . set ( " " )
self . activation_edit . clear ( )
else :
m essageb ox. showerror ( " 激活失败 " , message )
self . status_var . set ( " 激活失败 " )
QM essageB ox. critical ( self , " 激活失败 " , message )
# 激活后检查一次状态
self . check_status ( )
except Exception as e :
m essageb ox. showerror ( " 错误 " , f " 激活失败: { str ( e ) } " )
self . status_var . set ( " 发生错误 " )
QM essageB ox. critical ( self , " 错误 " , f " 激活失败: { str ( e ) } " )
# 出错后也检查状态
self . check_status ( )
@@ -175,11 +149,6 @@ class MainWindow:
logging . info ( " 激活记录: " )
for record in status_info [ ' activation_records ' ] :
logging . info ( f " - 记录: { record } " )
# 启用文本框编辑
self . status_text . config ( state = " normal " )
# 清空当前内容
self . status_text . delete ( 1.0 , tk . END )
# 更新状态文本
status_map = {
@@ -217,25 +186,16 @@ class MainWindow:
f " 地区: { device_info . get ( ' location ' , ' -- ' ) } "
] )
# 写入状态信息
self . status_text . insert ( tk . END , " \n " . join ( status_lines ) )
# 禁用文本框编辑
self . status_text . config ( state = " disabled " )
# 更新状态文本
self . status_text . setPlainText ( " \n " . join ( status_lines ) )
def check_status ( self ) :
""" 检查会员状态 """
try :
self . status_var . set ( " 正在检查状态... " )
self . root . update ( )
status = self . switcher . get_member_status ( )
if status :
self . update_status_display ( status )
if status . get ( ' status ' ) = = ' inactive ' :
self . status_var . set ( " 未激活 " )
return False
self . status_var . set ( " 状态检查完成 " )
return True
return status . get ( ' status ' ) ! = ' inactive '
else :
# 更新为未激活状态
inactive_status = {
@@ -247,148 +207,34 @@ class MainWindow:
" activation_records " : [ ]
}
self . update_status_display ( inactive_status )
self . status_var . set ( " 未激活 " )
return False
except Exception as e :
logging . error ( f " 检查状态失败: { str ( e ) } " )
self . status_var . set ( " 状态检查失败 " )
messagebox . showerror ( " 错误 " , f " 检查状态失败: { str ( e ) } " )
QMessageBox . critical ( self , " 错误 " , f " 检查状态失败: { str ( e ) } " )
return False
def show_purchase_info ( self ) :
""" 显示购买信息 """
# 创建自定义对话框
dialog = tk . Toplevel ( self . root )
dialog . title ( " 提示 " )
dialog . geometry ( " 400x280 " ) # 增加高度
dialog . resizable ( False , False )
# 设置模态
dialog . transient ( self . root )
dialog . grab_set ( )
# 创建提示图标
icon_frame = ttk . Frame ( dialog )
icon_frame . pack ( pady = 10 )
ttk . Label ( icon_frame , text = " ℹ ️ " , font = ( " Segoe UI " , 24 ) ) . pack ( )
# 创建消息文本
message_frame = ttk . Frame ( dialog )
message_frame . pack ( pady = 5 , padx = 20 )
ttk . Label ( message_frame , text = " 您还不是会员,请先购买激活会员用讯。 " , font = ( " Microsoft YaHei UI " , 10 ) ) . pack ( )
# 创建可复制的文本框
buy_info = " 闲鱼: xxxx \n 微信: behikcigar \n 网站自助购买: nezhacursor.nosqli.com "
text = tk . Text ( dialog , height = 4 , width = 40 , font = ( " Microsoft YaHei UI " , 9 ) )
text . pack ( pady = 5 , padx = 20 )
text . insert ( " 1.0 " , buy_info )
text . config ( state = " normal " ) # 允许选择和复制
# 创建按钮框架
btn_frame = ttk . Frame ( dialog )
btn_frame . pack ( pady = 10 )
# 复制按钮
def copy_info ( ) :
dialog . clipboard_clear ( )
dialog . clipboard_append ( buy_info )
messagebox . showinfo ( " 提示 " , " 购买信息已复制到剪贴板 " , parent = dialog )
ttk . Button ( btn_frame , text = " 复制信息 " , command = copy_info ) . pack ( side = " left " , padx = 5 )
ttk . Button ( btn_frame , text = " 确定 " , command = dialog . destroy ) . pack ( side = " left " , padx = 5 )
# 设置对话框位置为居中
dialog . update_idletasks ( )
width = dialog . winfo_width ( )
height = dialog . winfo_height ( )
x = ( dialog . winfo_screenwidth ( ) / / 2 ) - ( width / / 2 )
y = ( dialog . winfo_screenheight ( ) / / 2 ) - ( height / / 2 )
dialog . geometry ( f " { width } x { height } + { x } + { y } " )
# 等待对话框关闭
self . root . wait_window ( dialog )
def minimize_window ( self ) :
""" 最小化窗口 """
self . root . iconify ( )
def maximize_window ( self ) :
""" 最大化/还原窗口 """
if self . root . state ( ) == ' zoomed ' :
self . root . state ( ' normal ' )
else :
self . root . state ( ' zoomed ' )
def on_closing ( self ) :
""" 窗口关闭处理 """
try :
logging . info ( " 正在关闭程序... " )
# 先退出主循环
self . root . quit ( )
# 等待一小段时间确保资源释放
time . sleep ( 0.5 )
except Exception as e :
logging . error ( f " 关闭程序时出错: { str ( e ) } " )
finally :
try :
# 销毁窗口
self . root . destroy ( )
# 再等待一小段时间
time . sleep ( 0.5 )
# 强制结束进程
if sys . platform == " win32 " :
import os
os . _exit ( 0 )
except :
# 如果还是无法正常关闭,直接强制退出
os . _exit ( 0 )
def run ( self ) :
""" 运行程序 """
self . root . mainloop ( )
def refresh_cursor_auth ( self ) :
""" 刷新Cursor编辑器 授权 """
if not self . check_status ( ) :
self . show_purchase_info ( )
return
""" 刷新Cursor授权 """
try :
success , message = self . switcher . refresh_cursor_auth ( )
if success :
m essageb ox. showinfo ( " 成功 " , " Cursor编辑器授权刷新成功! \n " + message )
QM essageB ox. information ( self , " 成功 " , message )
else :
m essageb ox. showerror ( " 错误 " , message )
QM essageB ox. critical ( self , " 失败 " , message )
except Exception as e :
m essageb ox. showerror ( " 错误 " , f " 刷新失败: { str ( e ) } " )
def disable_cursor_update ( self ) :
""" 禁用Cursor版本更新 """
if not self . check_status ( ) :
self . show_purchase_info ( )
return
QM essageB ox. critical ( self , " 错误 " , f " 刷新授权 失败: { str ( e ) } " )
def disable_cursor_update ( self ) :
""" 禁用Cursor更新 """
try :
success , message = self . switcher . disable_cursor_update ( )
if success :
m essageb ox. showinfo ( " 成功 " , message )
QM essageB ox. information ( self , " 成功 " , message )
else :
m essageb ox. showerror ( " 错误 " , message )
QM essageB ox. critical ( self , " 失败 " , message )
except Exception as e :
m essageb ox. showerror ( " 错误 " , f " 操作 失败: { str ( e ) } " )
def dummy_function ( self ) :
""" 突破版本限制 """
if not self . check_status ( ) :
self . show_purchase_info ( )
return
QM essageB ox. critical ( self , " 错误 " , f " 禁用更新 失败: { str ( e ) } " )
try :
success , message = self . switcher . bypass_version_limit ( )
if success :
messagebox . showinfo ( " 成功 " , message )
else :
messagebox . showerror ( " 错误 " , message )
except Exception as e :
messagebox . showerror ( " 错误 " , f " 操作失败: { str ( e ) } " )
def dummy_function ( self ) :
""" 占位函数 """
QMessageBox . information ( self , " 提示 " , " 此功能暂未实现 " )