settings.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. import logging
  2. import tkinter as tk
  3. from tkinter import ttk
  4. from typing import List
  5. from plat.base.base_control import BaseControl, AbsControl
  6. from utils.config import version
  7. class _SettingsConnect(tk.Frame):
  8. """
  9. 连接云手机
  10. """
  11. def __init__(self, master=None, control: AbsControl = None, cnf=None, **kw):
  12. super().__init__(master, cnf if cnf is not None else {}, **kw)
  13. self.control = control
  14. self.init_ui()
  15. self.pack(padx=10, pady=10)
  16. def init_ui(self):
  17. """
  18. 初始化连接
  19. 云手机开启 ABD后无法自动识别,需要通过shell 连接一下。
  20. :return:
  21. """
  22. logging.info(f"连接云手机--->")
  23. content = ttk.Frame(self)
  24. content.pack(fill=tk.BOTH, expand=True)
  25. fieldset = ttk.LabelFrame(content, text="连接信息")
  26. fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
  27. content.grid_columnconfigure(0, weight=1)
  28. content.grid_rowconfigure(0, weight=1)
  29. fieldset.grid_columnconfigure(0, weight=1)
  30. fieldset.grid_rowconfigure(1, weight=1)
  31. cmd_label = ttk.Label(fieldset, text="ADB连接(一行一个):")
  32. cmd_label.grid(row=0, column=0, padx=5, pady=5, sticky="nw")
  33. cmd_text = tk.Text(fieldset, height=10)
  34. cmd_text.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
  35. test_btn = ttk.Button(fieldset, text="连接云手机", command=lambda: self.control.init_adb(cmd_text.get('1.0', tk.END).split('\n'), log_text, **{'ui': self}))
  36. test_btn.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
  37. # 日志区域
  38. log_label = ttk.Label(content, text="连接信息:")
  39. log_label.grid(row=1, column=0, padx=5, pady=5, sticky="nw")
  40. log_text = tk.Text(content, height=10)
  41. log_text.grid(row=2, column=0, padx=10, pady=(0, 10), sticky="nsew")
  42. content.grid_rowconfigure(2, weight=1)
  43. # def _connect_adb(self, cmd_text, log_text):
  44. # # 创建加载指示器
  45. #
  46. # def func():
  47. # self.control.init_adb(cmd_text.get('1.0', tk.END).split('\n'), log_text)
  48. #
  49. # self.control.loadding(self, func)
  50. # loading_window = tk.Toplevel(self)
  51. # loading_window.title("连接中")
  52. # loading_window.geometry("200x100")
  53. # loading_window.transient(self) # 设置为模态
  54. # loading_window.grab_set() # 设置为模态
  55. # loading_window.overrideredirect(True) # 移除窗口边框和按钮
  56. # # 相对于父窗口居中显示
  57. # window_width = loading_window.winfo_reqwidth()
  58. # window_height = loading_window.winfo_reqheight()
  59. # parent_x = self.winfo_rootx()
  60. # parent_y = self.winfo_rooty()
  61. # parent_width = self.winfo_width()
  62. # parent_height = self.winfo_height()
  63. # position_right = parent_x + (parent_width - window_width) // 2
  64. # position_down = parent_y + (parent_height - window_height) // 2
  65. # loading_window.geometry(f"+{position_right}+{position_down}")
  66. # loading_label = ttk.Label(loading_window, text="连接中...", padding=20)
  67. # loading_label.pack(expand=True)
  68. #
  69. # def thread_task():
  70. # try:
  71. # self.control.init_adb(cmd_text.get('1.0', tk.END).split('\n'), log_text)
  72. # finally:
  73. # # 在主线程中销毁加载指示器
  74. # self.after(0, lambda: [loading_window.grab_release(), loading_window.destroy()])
  75. #
  76. # import threading
  77. # thread = threading.Thread(target=thread_task)
  78. # # thread.daemon = True # 设置为守护线程,这样主程序退出时线程会自动结束
  79. # thread.start()
  80. class _SettingsKey(tk.Frame):
  81. """
  82. 设置快捷键
  83. """
  84. keys_mappings = {
  85. '买入/开多': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
  86. '买入/平多': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
  87. '卖出/开空': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
  88. '卖出/平空': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
  89. "一键撤单": {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
  90. '撤销委托': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
  91. }
  92. def __init__(self, master=None, cnf=None, **kw):
  93. super().__init__(master, cnf if cnf is not None else {}, **kw)
  94. self.control = None
  95. self.init_ui()
  96. self.pack(padx=10, pady=10)
  97. def init_ui(self):
  98. # 快捷键设置
  99. fieldset = ttk.LabelFrame(self, text="快捷键设置")
  100. fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
  101. fieldset.grid_columnconfigure(0, weight=1)
  102. fieldset.grid_rowconfigure(1, weight=1)
  103. # 配置Checkbutton样式
  104. style = ttk.Style()
  105. style.configure("TCheckbutton", )
  106. # 循环 keys_mappings
  107. for i, (key, value) in enumerate(self.keys_mappings.items()):
  108. # 创建一个 frame 来保存当前行的所有控件
  109. row_frame = ttk.Frame(fieldset)
  110. row_frame.grid(row=i, column=0, sticky="ew", padx=5, pady=5)
  111. # 创建说明标签
  112. label = ttk.Label(row_frame, text=f"{key:<7}:")
  113. label.pack(side=tk.LEFT, padx=(0, 10))
  114. # 为每个按键组合创建变量并保存在字典中
  115. key_state = {
  116. 'name': key,
  117. 'ctrl_var': tk.BooleanVar(value=value['ctrl']),
  118. 'alt_var': tk.BooleanVar(value=value['alt']),
  119. 'shift_var': tk.BooleanVar(value=value['shift']),
  120. 'key_var': tk.StringVar(value=value['key'])
  121. }
  122. # 创建复选框
  123. ttk.Checkbutton(row_frame, text="Ctrl", variable=key_state['ctrl_var'],
  124. command=lambda state=key_state: self._on_checkbox_click(state)).pack(side=tk.LEFT, padx=5)
  125. ttk.Checkbutton(row_frame, text="Alt", variable=key_state['alt_var'],
  126. command=lambda state=key_state: self._on_checkbox_click(state)).pack(side=tk.LEFT, padx=5)
  127. ttk.Checkbutton(row_frame, text="Shift", variable=key_state['shift_var'],
  128. command=lambda state=key_state: self._on_checkbox_click(state)).pack(side=tk.LEFT, padx=5)
  129. # 创建下拉框
  130. options = [chr(i) for i in range(65, 91)] + [f"F{i}" for i in range(1, 13)]
  131. combo = ttk.Combobox(row_frame, textvariable=key_state['key_var'], values=options,
  132. width=8, state='readonly', )
  133. combo.bind('<<ComboboxSelected>>', lambda event, state=key_state: self._on_checkbox_click(state))
  134. # 如果key_state中已有值就使用已有值,否则设置为第一个选项
  135. if key_state['key_var'].get():
  136. combo.set(key_state['key_var'].get())
  137. else:
  138. combo.current(i) # 设置第一个选项为默认值
  139. combo.pack(side=tk.LEFT, padx=5)
  140. # idx = len(self.keys_mappings)
  141. # save_btn = ttk.Button(self, text="保存",
  142. # command=lambda: print('保存快捷键设置'))
  143. # save_btn.grid(row=idx + 1, column=0, padx=5, pady=5, sticky="nwe")
  144. # test_btn = ttk.Button(self, text="恢复默认",
  145. # command=lambda: print('恢复默认'))
  146. # test_btn.grid(row=idx + 2, column=0, padx=5, pady=5, sticky="nwe")
  147. def _on_checkbox_click(self, key_state: dict):
  148. """
  149. 复选框点击事件处理
  150. """
  151. # 获取当前状态
  152. name = key_state['name']
  153. ctrl_state = key_state['ctrl_var'].get()
  154. alt_state = key_state['alt_var'].get()
  155. shift_state = key_state['shift_var'].get()
  156. key = key_state['key_var'].get()
  157. # 更新映射
  158. self.keys_mappings[name].update({
  159. 'ctrl': ctrl_state,
  160. 'alt': alt_state,
  161. 'shift': shift_state,
  162. 'key': key
  163. })
  164. logging.info(f"快捷键 '{name}' 更新: Ctrl={ctrl_state}, Alt={alt_state}, Shift={shift_state}, Key={key}")
  165. self._key_binds(name)
  166. def _key_binds(self, name: str):
  167. """
  168. 绑定快捷键
  169. :param name:
  170. :return:
  171. """
  172. key = self.keys_mappings[name]
  173. logging.info(f"<UNK> '{key}' <UNK>")
  174. key_combo = []
  175. if key['ctrl']:
  176. key_combo.append('Control')
  177. if key['shift']:
  178. key_combo.append('Shift')
  179. if key['alt']:
  180. key_combo.append('Alt')
  181. # 组合所有激活的修饰键
  182. if key_combo:
  183. key_bind = f"<{'-'.join(key_combo)}-{key['key'].lower()}>"
  184. self.winfo_toplevel().unbind_all(key_bind)
  185. self.winfo_toplevel().bind_all(key_bind, lambda event: self._demo_click(f'-->{name}'))
  186. logging.info(f'绑定快捷键: {key_bind} --> {name}')
  187. else:
  188. # 如果没有修饰键,直接绑定键值
  189. self.winfo_toplevel().unbind_all(f"<{key['key'].lower()}>")
  190. self.winfo_toplevel().bind_all(f"<{key['key'].lower()}>", lambda event: self._demo_click(f'-->{name}'))
  191. logging.info(f"<{key['key']}=> {name} ")
  192. pass
  193. def _demo_click(self, event):
  194. logging.info(f"<DEMO> {event} <DEMO>")
  195. def _keys_binds(self, keys: List[dict]):
  196. """
  197. 返回快捷键映射
  198. :param keys: [{'ctrl':True,'shift':True,'alt':True,'key':'a'},...]
  199. :return:
  200. """
  201. # 循环 keys 绑定快捷键, self.control
  202. for i, key in enumerate(keys):
  203. # 绑定快捷键
  204. self.init_ui(keys)
  205. class _SettingsOther(tk.Frame):
  206. """
  207. 其他设置
  208. """
  209. def __init__(self, master=None, cnf=None, **kw):
  210. super().__init__(master, cnf if cnf is not None else {}, **kw)
  211. self.tel_connect = None
  212. self.control = None
  213. self.init_ui()
  214. def init_ui(self):
  215. # 创建并配置notebook
  216. notebook = ttk.Notebook(self)
  217. # 设置notebook的填充
  218. notebook.pack(anchor="w", fill=tk.BOTH, expand=True)
  219. class _SettingsAbout(tk.Frame):
  220. """
  221. 关于
  222. """
  223. def __init__(self, master=None, cnf=None, **kw):
  224. super().__init__(master, cnf if cnf is not None else {}, **kw)
  225. self.init_ui()
  226. self.pack(padx=10, pady=10)
  227. def init_ui(self):
  228. # 创建一个 Frame 来模拟 <fieldset>
  229. fieldset = ttk.LabelFrame(self, text="群控助手")
  230. fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nw")
  231. self.grid_columnconfigure(0, weight=1)
  232. self.grid_rowconfigure(0, weight=0)
  233. fieldset.grid_columnconfigure(0, weight=1)
  234. fieldset.grid_rowconfigure(1, weight=1)
  235. cmd_label = ttk.Label(fieldset, text=f"版本:{version}")
  236. cmd_label.grid(row=0, column=0, padx=5, pady=5, sticky="nw")
  237. cmd_label = ttk.Label(fieldset, text=f"作者:强哥")
  238. cmd_label.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
  239. cmd_label = ttk.Label(fieldset, text=f"邮箱:fzxs88@yeah.net")
  240. cmd_label.grid(row=3, column=0, padx=5, pady=5, sticky="nw")
  241. class SettingUI(tk.Frame):
  242. """
  243. 设置页面
  244. """
  245. def __init__(self, master=None, control: BaseControl = None, cnf=None, **kw):
  246. super().__init__(master, cnf if cnf is not None else {}, **kw)
  247. self.about = None
  248. self.options = None
  249. self.key_mapping = None
  250. self.tel_connect = None
  251. self.control = control
  252. self.init_ui()
  253. def init_ui(self):
  254. # 创建并配置notebook
  255. notebook = ttk.Notebook(self)
  256. #
  257. # 设置notebook的填充
  258. notebook.pack(anchor="w", fill=tk.BOTH, expand=True)
  259. #
  260. # 第一个选项卡的内容
  261. self.tel_connect = ttk.Frame(notebook)
  262. notebook.add(self.tel_connect, text="连接云手机")
  263. _SettingsConnect(master=self.tel_connect, control=self.control)
  264. # 第二个选项卡的内容
  265. self.key_mapping = ttk.Frame(notebook)
  266. notebook.add(self.key_mapping, text="设置快捷键")
  267. _SettingsKey(self.key_mapping)
  268. # 第三个选项卡的内容
  269. self.options = ttk.Frame(notebook)
  270. notebook.add(self.options, text="其他设置")
  271. label3 = ttk.Label(self.options, text="其他设置")
  272. label3.pack(padx=10, pady=10)
  273. # 第四个选项卡的内容
  274. self.about = ttk.Frame(notebook)
  275. notebook.add(self.about, text="关于")
  276. _SettingsAbout(self.about)