gui.py 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874
  1. import time
  2. import tkinter
  3. import os
  4. import logging
  5. from sys import exit
  6. import threading
  7. import tkinter.messagebox
  8. from tkinter import ttk
  9. from newtkinter import asksaveasfilename, askdirectory, askopenfilenames
  10. from tkinter.scrolledtext import ScrolledText
  11. import gitrepo.template
  12. from gitrepo import controller
  13. from system import exception_catch, basicConfig, QueueController
  14. queue_controller = QueueController()
  15. logging.basicConfig(**basicConfig)
  16. class UIAPI:
  17. @staticmethod
  18. @exception_catch()
  19. def cli_gui(
  20. func,
  21. args,
  22. name="CoTan Git",
  23. break_time=0,
  24. show_screen=True,
  25. tip_text="",
  26. is_threaded_refresh=False,
  27. is_asynchronous_display=False,
  28. ):
  29. command_thread = func(*args)
  30. format_flat = True
  31. stop_key = gitrepo.template.stop_key
  32. def save_to_txt():
  33. nonlocal data
  34. dic = asksaveasfilename(title="选择文件保存位置", filetypes=[("TXT", ".txt")])
  35. if not dic.endswith(".txt"):
  36. dic += ".txt"
  37. with open(dic, "w", encoding="utf-8") as f:
  38. f.write(data)
  39. keep_button = True
  40. stop_button = True
  41. def update_button():
  42. if not keep_button:
  43. button_list[1].config(state=tkinter.DISABLED)
  44. if not stop_button:
  45. button_list[0].config(state=tkinter.DISABLED)
  46. def stop():
  47. nonlocal start, keep_button, stop_button
  48. start = 0
  49. stop_button = False
  50. keep_button = False
  51. update_button()
  52. def keep():
  53. nonlocal start, keep_button
  54. start = float("inf")
  55. keep_button = False
  56. update_button()
  57. def pipe():
  58. pass
  59. def format_information():
  60. nonlocal text, out_data, data, format_flat
  61. text.clear()
  62. if format_flat:
  63. text.insert(tkinter.END, data)
  64. else:
  65. text.insert(tkinter.END, out_data)
  66. format_flat = not format_flat
  67. start = time.time()
  68. data = ""
  69. out_data = "" # 包含out的data
  70. if show_screen:
  71. text, cli_screen, button_list = API.show_cli_gui(
  72. save_to_txt, stop, keep, format_information, pipe, name=name
  73. ) # [close,keep]
  74. update_button()
  75. if tip_text != "":
  76. text.insert("0.0", f"载入前提示>>> {tip_text}\n")
  77. out_data += f"载入前提示>>> {tip_text}\n"
  78. data += f"{tip_text}\n"
  79. cli_screen.update()
  80. else:
  81. class TkNone:
  82. def title(self, *args, **kwargs):
  83. return
  84. def insert(self, *args, **kwargs):
  85. return
  86. def update(self, *args, **kwargs):
  87. return
  88. def config(self, *args, **kwargs):
  89. return
  90. text = TkNone()
  91. cli_screen = TkNone()
  92. button_list = [TkNone(), TkNone()]
  93. u = threading.Thread(target=API.progress_bar_gui)
  94. u.start()
  95. SCREEN.update()
  96. def update_screen():
  97. nonlocal start
  98. while True:
  99. try:
  100. SCREEN.update()
  101. if show_screen:
  102. try:
  103. cli_screen.update()
  104. except BaseException as e:
  105. logging.warning(str(e))
  106. assert not time.time() - start >= break_time or break_time == 0
  107. assert not (break_time == 0 and start == 0)
  108. except AssertionError:
  109. start = 0
  110. break
  111. if is_threaded_refresh or not is_asynchronous_display:
  112. # 如果没有启动到多进程的效果,请检查Update是不是加了(),这里需要回调
  113. threaded_update = threading.Thread(target=update_screen)
  114. threaded_update.start()
  115. if is_asynchronous_display: # 等待后显示
  116. if break_time == 0:
  117. break_ti = None # 此处break_ti是为了别面覆盖break_time,因为Update进程需要用
  118. else:
  119. break_ti = break_time
  120. def wait_command_thread():
  121. nonlocal start
  122. command_thread.wait(break_ti)
  123. start = 0
  124. threaded_update = threading.Thread(
  125. target=wait_command_thread
  126. ) # 这么做不是多此一举,如果没有wait,进程并不会退出
  127. threaded_update.start()
  128. update_screen() # 遇到sleep等主线程阻塞,top.update等会阻塞子线程,因此,必须保证主线程不会被wait所阻塞
  129. out = command_thread.stdout.read().split("\n")
  130. for i in out:
  131. if not show_screen:
  132. break
  133. try: # 如果界面被关掉了,会报错
  134. cli_screen.title(f"{name} : 运行中")
  135. except tkinter.TclError:
  136. text, cli_screen, button_list = API.show_cli_gui(
  137. save_to_txt, stop, keep, format_information, pipe, name=f"{name} : 运行中"
  138. )
  139. update_button()
  140. text.insert(tkinter.END, out_data)
  141. if stop and i.replace(" ", "").replace("\n", "") != stop_key:
  142. text.insert(tkinter.END, f"[out]> {i}\n")
  143. data += i + "\n"
  144. out_data += f"[out]> {i}\n"
  145. else:
  146. text.insert(tkinter.END, "[END]")
  147. out_data += f"[END]"
  148. data += f"[END]"
  149. start = 0
  150. else: # 即时显示
  151. while True:
  152. # 界面设置
  153. try: # 如果界面被关掉了,会报错
  154. cli_screen.title(f"{name} : 运行中")
  155. except tkinter.TclError:
  156. text, cli_screen, button_list = API.show_cli_gui(
  157. save_to_txt, stop, keep, format_information, pipe, name=f"{name} : 运行中"
  158. )
  159. update_button()
  160. text.insert(tkinter.END, out_data)
  161. # 界面刷新
  162. try:
  163. if not is_threaded_refresh:
  164. SCREEN.update()
  165. cli_screen.update()
  166. except tkinter.TclError:
  167. break
  168. # 输出字符
  169. try:
  170. # .decode(str_code)#不需要decode,因为Popen已经设置了universal_newlines=True
  171. i = command_thread.stdout.readline()
  172. bool_text = i.replace(" ", "").replace("\n", "")
  173. if bool_text != "":
  174. print(stop_key)
  175. print(bool_text)
  176. if stop and bool_text == stop_key:
  177. start = 0
  178. else:
  179. text.insert(tkinter.END, f"[out]> {i}")
  180. data += i
  181. out_data += f"[out]> {i}"
  182. if (
  183. command_thread.returncode == 0
  184. or (time.time() - start >= break_time != 0)
  185. or (break_time == 0 and start == 0)
  186. ):
  187. text.insert(tkinter.END, "[END]")
  188. out_data += f"[END]"
  189. data += f"[END]"
  190. break
  191. elif command_thread.returncode is not None:
  192. assert False
  193. except (tkinter.TclError, AssertionError):
  194. if show_screen:
  195. text.insert(tkinter.END, "[ERROR]")
  196. out_data += f"[ERROR]"
  197. data += f"[ERROR]"
  198. break
  199. try: # 如果界面被关掉了,会报错
  200. if show_screen:
  201. cli_screen.title(f"{name} : 运行完毕")
  202. except tkinter.TclError:
  203. pass
  204. command_thread.kill()
  205. try:
  206. button_list[0].config(state=tkinter.DISABLED)
  207. button_list[1].config(state=tkinter.DISABLED)
  208. except (AttributeError, NameError):
  209. pass
  210. return data
  211. @staticmethod
  212. @exception_catch()
  213. def progress_bar_gui(*args, name="CoTan_Git >>> 运行中...", **kwargs):
  214. progress_screen = tkinter.Toplevel(bg=bg_color)
  215. progress_screen.title(name)
  216. progress_screen.geometry("+10+10") # 设置所在位置
  217. mpb = ttk.Progressbar(
  218. progress_screen, orient="horizontal", length=300, mode="determinate"
  219. )
  220. mpb.pack()
  221. progress_screen.resizable(width=False, height=False)
  222. mpb["maximum"] = 50
  223. mpb["value"] = 0
  224. for i in range(50):
  225. mpb["value"] = i + 1
  226. progress_screen.update()
  227. SCREEN.update()
  228. time.sleep(0.001)
  229. progress_screen.destroy()
  230. @staticmethod
  231. @exception_catch()
  232. def get_commit_id_gui():
  233. global commit
  234. the_commit = commit.get()
  235. return the_commit
  236. @staticmethod
  237. @exception_catch()
  238. def show_cli_gui(
  239. out_func, close_func, keep_func, not_out, pipe_func, name="CoTan_Git >>> 命令行"
  240. ):
  241. global bg_color
  242. cli_screen = tkinter.Toplevel(bg=bg_color)
  243. cli_screen.title(name)
  244. cli_screen.geometry("+10+10") # 设置所在位置
  245. cli_screen.resizable(width=False, height=False)
  246. class ScrolledCli(ScrolledText):
  247. def __init__(self, *args, **kwargs):
  248. super(ScrolledCli, self).__init__(*args, **kwargs)
  249. def insert(self, index, chars, *args):
  250. text.config(state=tkinter.NORMAL)
  251. super(ScrolledCli, self).insert(index, chars, *args)
  252. text.config(state=tkinter.DISABLED)
  253. def clear(self):
  254. text.config(state=tkinter.NORMAL)
  255. self.delete("0.0", tkinter.END)
  256. text.config(state=tkinter.DISABLED)
  257. text = ScrolledCli(cli_screen, font=("黑体", 11), height=30, width=100)
  258. text.grid(column=0, row=0, columnspan=5, sticky=tkinter.E + tkinter.W)
  259. text.config(state=tkinter.DISABLED)
  260. tkinter.Button(
  261. cli_screen,
  262. bg=bg_color,
  263. fg=word_color,
  264. text="输出文档",
  265. font=("黑体", 11),
  266. width=20,
  267. height=2,
  268. command=out_func,
  269. ).grid(column=4, row=1, sticky=tkinter.E + tkinter.W)
  270. close = tkinter.Button(
  271. cli_screen,
  272. bg=bg_color,
  273. fg=word_color,
  274. text="关闭子线程连接",
  275. font=("黑体", 11),
  276. width=20,
  277. height=2,
  278. command=close_func,
  279. )
  280. close.grid(column=0, row=1, sticky=tkinter.E + tkinter.W)
  281. keep = tkinter.Button(
  282. cli_screen,
  283. bg=bg_color,
  284. fg=word_color,
  285. text="保持线程连接",
  286. font=("黑体", 11),
  287. width=20,
  288. height=2,
  289. command=keep_func,
  290. )
  291. keep.grid(column=1, row=1, sticky=tkinter.E + tkinter.W)
  292. tkinter.Button(
  293. cli_screen,
  294. bg=bg_color,
  295. fg=word_color,
  296. text="格式化输出",
  297. font=("黑体", 11),
  298. width=20,
  299. height=2,
  300. command=not_out,
  301. ).grid(column=2, row=1, sticky=tkinter.E + tkinter.W)
  302. tkinter.Button(
  303. cli_screen,
  304. bg=bg_color,
  305. fg=word_color,
  306. text="启动CoTan命令行",
  307. font=("黑体", 11),
  308. width=20,
  309. height=2,
  310. command=pipe_func,
  311. state=tkinter.DISABLED,
  312. ).grid(column=3, row=1, sticky=tkinter.E + tkinter.W)
  313. cli_screen.update()
  314. return text, cli_screen, [close, keep]
  315. @staticmethod
  316. @exception_catch()
  317. def repo_init_gui():
  318. new_dir = askdirectory(title="选择仓库地址")
  319. if new_dir == "":
  320. raise Exception
  321. return new_dir
  322. @staticmethod
  323. @exception_catch()
  324. def get_repo_name_gui(): # 获得名字统一接口
  325. global git, repo_list, repo_box
  326. try:
  327. return repo_list[repo_box.curselection()[0]]
  328. except IndexError:
  329. try:
  330. return repo_list[0]
  331. except IndexError:
  332. return None
  333. @staticmethod
  334. @exception_catch()
  335. def update_repo_box_gui():
  336. global git, repo_list, repo_box
  337. repo_list = list(git.get_git_dict().keys())
  338. repo_box.delete(0, tkinter.END)
  339. repo_box.insert(tkinter.END, *repo_list)
  340. @staticmethod
  341. @exception_catch()
  342. def update_file_box_gui():
  343. global file_list, file_box
  344. file_box.delete(0, tkinter.END)
  345. file_box.insert(tkinter.END, *file_list)
  346. @staticmethod
  347. @exception_catch()
  348. def update_git_file_last_gui():
  349. global last_name
  350. if last_name is None:
  351. return False
  352. API.update_git_file_gui(last_name)
  353. @staticmethod
  354. @exception_catch()
  355. def update_git_file_select_gui():
  356. name = API.get_repo_name_gui()
  357. API.update_git_file_gui(name)
  358. @staticmethod
  359. @exception_catch()
  360. def update_git_file_gui(name):
  361. global git, repo_dir, last_name
  362. dir_list = git.get_dir(name)
  363. try: # 窗口可能已经关闭
  364. repo_dir.delete(0, tkinter.END)
  365. repo_dir.insert(tkinter.END, *dir_list)
  366. except BaseException as e:
  367. logging.warning(str(e))
  368. last_name = name
  369. @staticmethod
  370. @exception_catch()
  371. def add_file_list_gui():
  372. global file_list, file_box
  373. new_file = set(askopenfilenames(title=f"选择文件"))
  374. have_file = set(file_list)
  375. file_list += list(new_file - (new_file & have_file)) # 筛选出重复
  376. API.update_file_box_gui()
  377. @staticmethod
  378. @exception_catch()
  379. def add_file_input_dir_gui():
  380. global file_dir
  381. new_dir = file_dir.get()
  382. if new_dir.replace(" ", "") != "" and new_dir not in file_list:
  383. file_list.append(new_dir)
  384. API.update_file_box_gui()
  385. @staticmethod
  386. @exception_catch()
  387. def add_file_by_git_gui():
  388. global file_dir
  389. new_dir = file_dir.get()
  390. if new_dir.replace(" ", "") != "":
  391. name = API.get_repo_name_gui()
  392. new_dir = git.make_dir(name, new_dir)
  393. if new_dir not in file_list:
  394. file_list.append(new_dir)
  395. API.update_file_box_gui()
  396. @staticmethod
  397. @exception_catch()
  398. def diff_gui():
  399. branch = master.get()
  400. if branch == "":
  401. branch = "HEAD"
  402. return branch
  403. @staticmethod
  404. @exception_catch()
  405. def commit_file_gui():
  406. m = commit_message.get()
  407. if m.replace(" ", "") == "":
  408. tkinter.messagebox.showinfo("警告!", "非常遗憾,我不同意你commit而不添加任何描述!\n描述是很重要的!")
  409. raise Exception
  410. return m
  411. @staticmethod
  412. @exception_catch()
  413. def log_gui(log_type_):
  414. graph = bool(log_type_[0].get())
  415. abbrev = bool(log_type_[1].get())
  416. pretty = bool(log_type_[2].get())
  417. return abbrev, graph, pretty
  418. @staticmethod
  419. @exception_catch()
  420. def reset_head_gui():
  421. repo_head = head.get()
  422. if repo_head == "":
  423. repo_head = "HEAD~1"
  424. the_reset_type = reset_type.get()
  425. return repo_head, the_reset_type
  426. @staticmethod
  427. @exception_catch()
  428. def reset_file_gui():
  429. repo_head = head.get()
  430. if repo_head == "":
  431. repo_head = "HEAD~1"
  432. return repo_head
  433. @staticmethod
  434. @exception_catch()
  435. def add_new_branch_gui():
  436. name = API.get_branch_name_gui()
  437. origin = origin_branch.get()
  438. return name, origin
  439. @staticmethod
  440. @exception_catch()
  441. def branch_merge_gui():
  442. message = commit_message.get()
  443. parameters_no_ff = not bool(no_fast_forward.get()) # 对于no_ff来说,True - 使用快速合并,所以要翻转
  444. if message.replace(" ", "") == "" and parameters_no_ff:
  445. tkinter.messagebox.showinfo(
  446. "警告!", "非常遗憾,我不同意你commit而不添加任何描述!\n描述是很重要的!" "(如果你不想添加描述,请使用快速合并,但我并不建议!)"
  447. )
  448. raise Exception
  449. name = API.get_branch_name_gui()
  450. return message, name, parameters_no_ff
  451. @staticmethod
  452. @exception_catch()
  453. def get_branch_name_gui():
  454. return branch_name.get()
  455. @staticmethod
  456. @exception_catch()
  457. def get_stash_gui():
  458. stash_num = stash_name.get()
  459. return stash_num
  460. @staticmethod
  461. @exception_catch()
  462. def add_remote_gui():
  463. ssh = remote_ssh.get()
  464. name = remote_name.get()
  465. return name, ssh
  466. @staticmethod
  467. @exception_catch()
  468. def del_remote_gui():
  469. name = remote_name.get()
  470. return name
  471. @staticmethod
  472. @exception_catch()
  473. def bind_remote_branch_gui():
  474. remote = remote_branch.get()
  475. local = local_branch.get()
  476. return local, remote
  477. @staticmethod
  478. @exception_catch()
  479. def pull_push_gui():
  480. branch = remote_branch.get()
  481. remote = remote_name.get()
  482. local = local_branch.get()
  483. allow = bool(allow_history.get())
  484. parameters_u = bool(push_bind.get())
  485. parameters_f = tkinter.messagebox.askokcancel("提示", f"是否需要强制推送?(强制推送不被建议)")
  486. return allow, branch, local, parameters_f, parameters_u, remote
  487. @staticmethod
  488. @exception_catch()
  489. def get_search_key_gui():
  490. return show_search_key.get()
  491. @staticmethod
  492. @exception_catch()
  493. def add_tag_gui():
  494. global tag_name, commit, tag_message
  495. the_tag_name = tag_name.get()
  496. the_commit = tag_commit.get()
  497. the_tag_message = tag_message.get()
  498. return the_tag_name, the_commit, the_tag_message
  499. @staticmethod
  500. @exception_catch()
  501. def push_tag_gui():
  502. global tag_name
  503. the_tag_name = tag_name.get()
  504. remoto = remote_name.get()
  505. return remoto, the_tag_name
  506. @staticmethod
  507. @exception_catch()
  508. def get_remote_name_gui():
  509. remoto = remote_name.get()
  510. return remoto
  511. @staticmethod
  512. @exception_catch()
  513. def del_remote_tag_gui():
  514. remoto = remote_name.get()
  515. tag = tag_name.get()
  516. return remoto, tag
  517. @staticmethod
  518. @exception_catch()
  519. def del_remote_branch_gui():
  520. remote = remote_name.get()
  521. branch = remote_branch.get()
  522. return branch, remote
  523. @staticmethod
  524. @exception_catch()
  525. def del_tag_gui():
  526. tag = tag_name.get()
  527. return tag
  528. @staticmethod
  529. @exception_catch()
  530. def featch_remote_gui():
  531. branch = remote_branch.get()
  532. remote = remote_name.get()
  533. local = local_branch.get()
  534. return branch, local, remote
  535. @staticmethod
  536. @exception_catch()
  537. def get_customize_gui():
  538. command = customize_input.get()
  539. is_threaded_refresh = bool(threaded_refresh.get())
  540. is_asynchronous_display = bool(asynchronous_display.get())
  541. return command, is_asynchronous_display, is_threaded_refresh
  542. @staticmethod
  543. @exception_catch()
  544. def clone_git_gui():
  545. new_dir = askdirectory(title="选择仓库地址")
  546. name = git.clone_repo(new_dir)
  547. return name
  548. @staticmethod
  549. @exception_catch()
  550. def branch_new_gui():
  551. new_name = branch_new_name.get()
  552. old_name = API.get_branch_name_gui()
  553. return new_name, old_name
  554. @staticmethod
  555. @exception_catch()
  556. def get_file_box_index_gui():
  557. return file_box.curselection()[0]
  558. class API(UIAPI):
  559. @staticmethod
  560. @exception_catch()
  561. def branch_new(): # 克隆仓库
  562. new_name, old_name = API.branch_new_gui()
  563. API.cli_gui(git.rename_branch, (API.get_repo_name_gui(), old_name, new_name), show_screen=False)
  564. API.update_repo_box_gui()
  565. @staticmethod
  566. @exception_catch()
  567. def clone_git(): # 克隆仓库
  568. name = API.clone_git_gui()
  569. API.clone_core(name, clone_repo.get())
  570. API.update_repo_box_gui()
  571. @staticmethod
  572. @exception_catch()
  573. def clone_core(name, url):
  574. try:
  575. API.cli_gui(
  576. git.clone,
  577. (name, url),
  578. break_time=0,
  579. tip_text=f"{url}:正在执行克隆操作",
  580. is_threaded_refresh=True,
  581. is_asynchronous_display=True,
  582. )
  583. git.after_clone(name)
  584. except BaseException:
  585. raise
  586. finally:
  587. API.update_git_file_last_gui()
  588. @staticmethod
  589. @exception_catch()
  590. def customize():
  591. command, is_asynchronous_display, is_threaded_refresh = API.get_customize_gui()
  592. API.cli_gui(
  593. git.customize_command,
  594. (API.get_repo_name_gui(), command),
  595. break_time=0,
  596. tip_text=f"{command}:操作进行中",
  597. is_threaded_refresh=is_threaded_refresh,
  598. is_asynchronous_display=is_asynchronous_display,
  599. )
  600. API.update_git_file_last_gui()
  601. @staticmethod
  602. @exception_catch()
  603. def fetch_remote():
  604. branch, local, remote = API.featch_remote_gui()
  605. API.cli_gui(
  606. git.fetch,
  607. (API.get_repo_name_gui(), local, remote, branch),
  608. break_time=0,
  609. tip_text=f"此操作需要连接远程仓库,请稍等...",
  610. is_threaded_refresh=True,
  611. is_asynchronous_display=True,
  612. )
  613. API.update_git_file_last_gui()
  614. @staticmethod
  615. @exception_catch()
  616. def del_tag():
  617. tag = API.del_tag_gui()
  618. API.cli_gui(git.del_tag, (API.get_repo_name_gui(), tag))
  619. API.update_git_file_last_gui()
  620. @staticmethod
  621. @exception_catch()
  622. def del_remote_branch():
  623. branch, remote = API.del_remote_branch_gui()
  624. API.cli_gui(
  625. git.del_branch_remote,
  626. (API.get_repo_name_gui(), remote, branch),
  627. break_time=0,
  628. tip_text=f"此操作需要连接远程仓库,请稍等...",
  629. is_threaded_refresh=True,
  630. is_asynchronous_display=True,
  631. )
  632. API.update_git_file_last_gui()
  633. @staticmethod
  634. @exception_catch()
  635. def del_remote_tag():
  636. remoto, tag = API.del_remote_tag_gui()
  637. API.cli_gui(
  638. git.del_tag_remote,
  639. (API.get_repo_name_gui(), remoto, tag),
  640. break_time=0,
  641. tip_text=f"此操作需要连接远程仓库,请稍等...",
  642. is_threaded_refresh=True,
  643. is_asynchronous_display=True,
  644. )
  645. API.update_git_file_last_gui()
  646. @staticmethod
  647. @exception_catch()
  648. def push_all_tag():
  649. remoto = API.get_remote_name_gui()
  650. API.cli_gui(
  651. git.push_all_tag,
  652. (API.get_repo_name_gui(), remoto),
  653. break_time=0,
  654. tip_text=f"此操作需要连接远程仓库,请稍等...",
  655. is_threaded_refresh=True,
  656. is_asynchronous_display=True,
  657. )
  658. API.update_git_file_last_gui()
  659. @staticmethod
  660. @exception_catch()
  661. def push_tag():
  662. remoto, the_tag_name = API.push_tag_gui()
  663. API.cli_gui(
  664. git.push_tag,
  665. (API.get_repo_name_gui(), the_tag_name, remoto),
  666. break_time=0,
  667. tip_text=f"此操作需要连接远程仓库,请稍等...",
  668. is_threaded_refresh=True,
  669. is_asynchronous_display=True,
  670. )
  671. API.update_git_file_last_gui()
  672. @staticmethod
  673. @exception_catch()
  674. def add_tag():
  675. the_tag_name, the_commit, the_tag_message = API.add_tag_gui()
  676. API.cli_gui(
  677. git.add_tag, (API.get_repo_name_gui(), the_tag_name, the_commit, the_tag_message), show_screen=False
  678. )
  679. API.update_git_file_last_gui()
  680. @staticmethod
  681. @exception_catch()
  682. def show_tag(type_):
  683. global git
  684. key = API.get_search_key_gui()
  685. API.cli_gui(
  686. {1: git.get_tag_list, 0: git.search_commit}.get(type_, git.search_commit),
  687. (API.get_repo_name_gui(), key),
  688. )
  689. API.update_git_file_last_gui()
  690. @staticmethod
  691. @exception_catch()
  692. def pull_push_remote(type_):
  693. allow, branch, local, parameters_f, parameters_u, remote = API.pull_push_gui()
  694. API.cli_gui(
  695. {0: git.pull_from_remote, 1: git.push_to_remote}.get(
  696. type_, git.pull_from_remote
  697. ),
  698. (API.get_repo_name_gui(), local, remote, branch, allow, parameters_u, parameters_f),
  699. break_time=0,
  700. tip_text=f"此操作需要连接远程仓库,请稍等...",
  701. is_threaded_refresh=True,
  702. is_asynchronous_display=True,
  703. )
  704. API.update_git_file_last_gui()
  705. @staticmethod
  706. @exception_catch()
  707. def bind_remote_branch():
  708. local, remote = API.bind_remote_branch_gui()
  709. API.cli_gui(git.bind_branch, (API.get_repo_name_gui(), local, remote))
  710. API.update_git_file_last_gui()
  711. @staticmethod
  712. @exception_catch()
  713. def del_remote():
  714. name = API.del_remote_gui()
  715. API.cli_gui(git.del_remote, (API.get_repo_name_gui(), name))
  716. API.update_git_file_last_gui()
  717. @staticmethod
  718. @exception_catch()
  719. def add_remote():
  720. name, ssh = API.add_remote_gui()
  721. API.cli_gui(git.remote_add, (API.get_repo_name_gui(), ssh, name))
  722. API.update_git_file_last_gui()
  723. @staticmethod
  724. @exception_catch()
  725. def cherry_pick():
  726. the_commit = API.get_commit_id_gui()
  727. API.cli_gui(git.cherry_pick, (API.get_repo_name_gui(), the_commit))
  728. API.update_git_file_last_gui()
  729. @staticmethod
  730. @exception_catch()
  731. def open_stash(type_):
  732. stash_num = API.get_stash_gui()
  733. if stash_num == "":
  734. stash_num = "0"
  735. API.cli_gui([git.drop_stash, git.apply_stash][type_], (API.get_repo_name_gui(), stash_num))
  736. API.update_git_file_last_gui()
  737. @staticmethod
  738. @exception_catch()
  739. def branch_merge():
  740. message, name, parameters_no_ff = API.branch_merge_gui()
  741. API.cli_gui(git.merge_branch, (API.get_repo_name_gui(), name, parameters_no_ff, message))
  742. API.update_git_file_last_gui()
  743. @staticmethod
  744. @exception_catch()
  745. def del_branch(type_):
  746. name = API.get_branch_name_gui()
  747. API.cli_gui(git.del_branch, (API.get_repo_name_gui(), name, type_))
  748. API.update_git_file_last_gui()
  749. @staticmethod
  750. @exception_catch()
  751. def switch_branch():
  752. name = API.get_branch_name_gui()
  753. API.cli_gui(git.switch_branch, (API.get_repo_name_gui(), name), break_time=1, show_screen=False)
  754. API.update_git_file_last_gui()
  755. @staticmethod
  756. @exception_catch()
  757. def add_new_branch():
  758. name, origin = API.add_new_branch_gui()
  759. API.cli_gui(
  760. git.new_branch, (API.get_repo_name_gui(), name, origin), break_time=1, show_screen=False
  761. )
  762. API.update_git_file_last_gui()
  763. @staticmethod
  764. @exception_catch()
  765. def remove_file():
  766. if not file_list:
  767. return False
  768. API.cli_gui(git.rm, (API.get_repo_name_gui(), file_list))
  769. API.update_git_file_last_gui()
  770. @staticmethod
  771. @exception_catch()
  772. def checkout_file(): # 从暂存区、仓库返回文件
  773. if not file_list:
  774. return False
  775. API.cli_gui(git.checkout_version, (API.get_repo_name_gui(), file_list))
  776. API.update_git_file_last_gui()
  777. @staticmethod
  778. @exception_catch()
  779. def reset_file(): # 使用reset回退文件
  780. repo_head = API.reset_file_gui()
  781. API.cli_gui(git.back_version_file, (API.get_repo_name_gui(), repo_head, file_list))
  782. API.update_git_file_last_gui()
  783. @staticmethod
  784. @exception_catch()
  785. def reset_head():
  786. repo_head, the_reset_type = API.reset_head_gui()
  787. API.cli_gui(git.back_version, (API.get_repo_name_gui(), repo_head, the_reset_type))
  788. API.update_git_file_last_gui()
  789. @staticmethod
  790. @exception_catch()
  791. def log():
  792. global git, log_type
  793. name = API.get_repo_name_gui()
  794. abbrev, graph, pretty = API.log_gui(log_type)
  795. API.cli_gui(git.log, (name, graph, pretty, abbrev))
  796. API.update_git_file_last_gui()
  797. @staticmethod
  798. @exception_catch()
  799. def not_parameters_call(func):
  800. global git
  801. name = API.get_repo_name_gui()
  802. API.cli_gui(func, (name,))
  803. API.update_git_file_last_gui()
  804. @staticmethod
  805. @exception_catch()
  806. def commit_file():
  807. name = API.get_repo_name_gui()
  808. API.cli_gui(git.commit_file, (name, API.commit_file_gui()))
  809. API.update_git_file_last_gui()
  810. @staticmethod
  811. @exception_catch()
  812. def diff():
  813. branch = API.diff_gui()
  814. API.cli_gui(git.diff_file, (API.get_repo_name_gui(), branch))
  815. API.update_git_file_last_gui()
  816. @staticmethod
  817. @exception_catch()
  818. def remove_the_staging():
  819. global git
  820. dic = file_list
  821. if not dic:
  822. dic = "."
  823. API.cli_gui(git.reset_file, (API.get_repo_name_gui(), dic))
  824. API.update_git_file_last_gui()
  825. @staticmethod
  826. @exception_catch()
  827. def add():
  828. dic = file_list
  829. if not dic:
  830. dic = "." # 查一下取消的dic
  831. API.cli_gui(git.add_file, (API.get_repo_name_gui(), dic))
  832. API.update_git_file_last_gui()
  833. @staticmethod
  834. @exception_catch()
  835. def del_file():
  836. del file_list[API.get_file_box_index_gui()]
  837. API.update_file_box_gui()
  838. @staticmethod
  839. @exception_catch()
  840. def clean_file():
  841. global file_list
  842. file_list = []
  843. API.update_file_box_gui()
  844. @staticmethod
  845. @exception_catch()
  846. def repo_init(): # 创建仓库
  847. global git
  848. new_dir = API.repo_init_gui()
  849. git.open_repo(new_dir)
  850. API.update_repo_box_gui()
  851. def git_main(in_queue, out_queue):
  852. global SCREEN, queue_controller
  853. queue_controller.set_queue(in_queue, out_queue)
  854. class Stop:
  855. def __call__(self, *args, **kwargs):
  856. exit(0)
  857. stop = Stop()
  858. queue_controller.set_before_stop(stop)
  859. queue_controller()
  860. SCREEN.mainloop()
  861. queue_controller.stop_process()
  862. file_list = []
  863. PATH = os.getcwd()
  864. git = controller.GitCtrol()
  865. repo_list = []
  866. SCREEN = tkinter.Tk()
  867. last_name = None
  868. bg_color = "#FFFAFA" # 主颜色
  869. buttom_color = "#FFFAFA" # 按钮颜色
  870. word_color = "#000000" # 文字颜色
  871. SCREEN["bg"] = bg_color
  872. FONT = ("黑体", 11) # 设置字体
  873. SCREEN.title("CoTan仓库管理器")
  874. SCREEN.resizable(width=False, height=False)
  875. SCREEN.geometry("+10+10") # 设置所在位置
  876. SCREEN.iconbitmap(bitmap=f'Pic{os.sep}favicon.ico', default=f'Pic{os.sep}favicon.ico')
  877. gui_width = 13 # 标准宽度
  878. gui_height = 2
  879. row = 0
  880. column = 0
  881. tkinter.Button(
  882. SCREEN,
  883. bg=buttom_color,
  884. fg=word_color,
  885. text="克隆仓库",
  886. command=API.clone_git,
  887. font=FONT,
  888. width=gui_width,
  889. height=gui_height,
  890. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  891. tkinter.Button(
  892. SCREEN,
  893. bg=buttom_color,
  894. fg=word_color,
  895. text="打开仓库",
  896. command=API.repo_init,
  897. font=FONT,
  898. width=gui_width,
  899. height=gui_height,
  900. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  901. tkinter.Button(
  902. SCREEN,
  903. bg=buttom_color,
  904. fg=word_color,
  905. text="查看文件",
  906. command=API.update_git_file_select_gui,
  907. font=FONT,
  908. width=gui_width,
  909. height=gui_height,
  910. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  911. row += 1
  912. tkinter.Label(
  913. SCREEN,
  914. text="克隆URL:",
  915. bg=bg_color,
  916. fg=word_color,
  917. font=FONT,
  918. width=gui_width,
  919. height=gui_height,
  920. ).grid(column=column, row=row)
  921. clone_repo = tkinter.Entry(SCREEN, width=gui_width * 2)
  922. clone_repo.grid(column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W)
  923. row += 1
  924. repo_box = tkinter.Listbox(SCREEN, width=gui_width * 3, height=gui_height * 4)
  925. repo_box.grid(
  926. column=column,
  927. row=row,
  928. columnspan=3,
  929. rowspan=4,
  930. sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N,
  931. )
  932. row += 4
  933. tkinter.Label(
  934. SCREEN,
  935. text="【仓库文件列表】",
  936. bg=bg_color,
  937. fg=word_color,
  938. font=FONT,
  939. width=gui_width * 3,
  940. height=gui_height,
  941. ).grid(
  942. column=column,
  943. columnspan=3,
  944. row=row,
  945. sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N,
  946. ) # 设置说明
  947. row += 1
  948. repo_dir = tkinter.Listbox(SCREEN, width=gui_width * 3, height=gui_height * 4)
  949. repo_dir.grid(
  950. column=column,
  951. row=row,
  952. columnspan=3,
  953. rowspan=4,
  954. sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N,
  955. )
  956. row += 4
  957. tkinter.Label(
  958. SCREEN,
  959. text="【添加文件列表】",
  960. bg=bg_color,
  961. fg=word_color,
  962. font=FONT,
  963. width=gui_width * 3,
  964. height=gui_height,
  965. ).grid(
  966. column=column,
  967. columnspan=3,
  968. row=row,
  969. sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N,
  970. ) # 设置说明
  971. row += 1
  972. file_dir = tkinter.Entry(SCREEN, width=gui_width * 2)
  973. file_dir.grid(
  974. column=column,
  975. row=row,
  976. columnspan=3,
  977. sticky=tkinter.E + tkinter.W + tkinter.N + tkinter.S,
  978. )
  979. row += 1
  980. tkinter.Button(
  981. SCREEN,
  982. bg=buttom_color,
  983. fg=word_color,
  984. text="填充路径并添加",
  985. command=API.add_file_by_git_gui,
  986. font=FONT,
  987. width=gui_width,
  988. height=gui_height,
  989. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  990. tkinter.Button(
  991. SCREEN,
  992. bg=buttom_color,
  993. fg=word_color,
  994. text="直接添加",
  995. command=API.add_file_input_dir_gui,
  996. font=FONT,
  997. width=gui_width,
  998. height=gui_height,
  999. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1000. tkinter.Button(
  1001. SCREEN,
  1002. bg=buttom_color,
  1003. fg=word_color,
  1004. text="选择文件",
  1005. command=API.add_file_list_gui,
  1006. font=FONT,
  1007. width=gui_width,
  1008. height=gui_height,
  1009. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1010. row += 1
  1011. tkinter.Button(
  1012. SCREEN,
  1013. bg=buttom_color,
  1014. fg=word_color,
  1015. text="把文件移除出列表",
  1016. command=API.del_file,
  1017. font=FONT,
  1018. width=gui_width,
  1019. height=gui_height,
  1020. ).grid(column=column, row=row, columnspan=2, sticky=tkinter.E + tkinter.W)
  1021. tkinter.Button(
  1022. SCREEN,
  1023. bg=buttom_color,
  1024. fg=word_color,
  1025. text="清空列表",
  1026. command=API.clean_file,
  1027. font=FONT,
  1028. width=gui_width,
  1029. height=gui_height,
  1030. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1031. row += 1
  1032. file_box = tkinter.Listbox(SCREEN, width=gui_width * 3, height=gui_height * 4)
  1033. file_box.grid(
  1034. column=column,
  1035. row=row,
  1036. columnspan=3,
  1037. rowspan=4,
  1038. sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N,
  1039. )
  1040. row += 4
  1041. tkinter.Button(
  1042. SCREEN,
  1043. bg=buttom_color,
  1044. fg=word_color,
  1045. text="添加暂存区文件",
  1046. command=API.add,
  1047. font=FONT,
  1048. width=gui_width,
  1049. height=gui_height,
  1050. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1051. tkinter.Button(
  1052. SCREEN,
  1053. bg=buttom_color,
  1054. fg=word_color,
  1055. text="移除暂存区文件",
  1056. command=API.remove_the_staging,
  1057. font=FONT,
  1058. width=gui_width,
  1059. height=gui_height,
  1060. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1061. tkinter.Button(
  1062. SCREEN,
  1063. bg=buttom_color,
  1064. fg=word_color,
  1065. text="提交到git",
  1066. command=API.commit_file,
  1067. font=FONT,
  1068. width=gui_width,
  1069. height=gui_height,
  1070. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1071. row += 1
  1072. tkinter.Button(
  1073. SCREEN,
  1074. bg=buttom_color,
  1075. fg=word_color,
  1076. text="查看执行日志",
  1077. command=lambda: API.not_parameters_call(git.do_log),
  1078. font=FONT,
  1079. width=gui_width,
  1080. height=gui_height,
  1081. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1082. tkinter.Button(
  1083. SCREEN,
  1084. bg=buttom_color,
  1085. fg=word_color,
  1086. text="查看文件日志",
  1087. command=API.log,
  1088. font=FONT,
  1089. width=gui_width,
  1090. height=gui_height,
  1091. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1092. tkinter.Button(
  1093. SCREEN,
  1094. bg=buttom_color,
  1095. fg=word_color,
  1096. text="查看状态",
  1097. command=lambda: API.not_parameters_call(git.status),
  1098. font=FONT,
  1099. width=gui_width,
  1100. height=gui_height,
  1101. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1102. row += 1
  1103. log_type = []
  1104. lable = ["显示轴", "commit完全显示", "简化显示"] # 复选框
  1105. for i in range(3):
  1106. log_type.append(tkinter.IntVar())
  1107. tkinter.Checkbutton(
  1108. SCREEN,
  1109. bg=bg_color,
  1110. fg=word_color,
  1111. activebackground=bg_color,
  1112. activeforeground=word_color,
  1113. selectcolor=bg_color,
  1114. text=lable[i],
  1115. variable=log_type[-1],
  1116. ).grid(column=column + i, row=row, sticky=tkinter.W)
  1117. log_type[-1].set(1)
  1118. row += 1
  1119. tkinter.Button(
  1120. SCREEN,
  1121. bg=buttom_color,
  1122. fg=word_color,
  1123. text="版本回退",
  1124. command=API.reset_head,
  1125. font=FONT,
  1126. width=gui_width,
  1127. height=gui_height,
  1128. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1129. tkinter.Button(
  1130. SCREEN,
  1131. bg=buttom_color,
  1132. fg=word_color,
  1133. text="放弃修改",
  1134. command=API.checkout_file,
  1135. font=FONT,
  1136. width=gui_width,
  1137. height=gui_height,
  1138. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1139. tkinter.Button(
  1140. SCREEN,
  1141. bg=buttom_color,
  1142. fg=word_color,
  1143. text="删除文件",
  1144. command=API.remove_file,
  1145. font=FONT,
  1146. width=gui_width,
  1147. height=gui_height,
  1148. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1149. row += 1
  1150. reset_type = tkinter.IntVar() # 正,负,0
  1151. lable = ["回退到工作区", "回退到暂存区", "无痕回退"] # 复选框
  1152. for i in range(3):
  1153. tkinter.Radiobutton(
  1154. SCREEN,
  1155. bg=bg_color,
  1156. fg=word_color,
  1157. activebackground=bg_color,
  1158. activeforeground=word_color,
  1159. selectcolor=bg_color,
  1160. text=lable[i],
  1161. variable=reset_type,
  1162. value=i,
  1163. ).grid(column=column + i, row=row, sticky=tkinter.W)
  1164. column += 3
  1165. tkinter.Label(SCREEN, text="", bg=bg_color, fg=word_color, font=FONT, width=1).grid(
  1166. column=column, row=row
  1167. ) # 设置说明
  1168. column += 1
  1169. row = 0
  1170. tkinter.Label(
  1171. SCREEN,
  1172. text="【参数操作】",
  1173. bg=bg_color,
  1174. fg=word_color,
  1175. font=FONT,
  1176. width=gui_width * 3,
  1177. height=gui_height,
  1178. ).grid(
  1179. column=column,
  1180. columnspan=3,
  1181. row=row,
  1182. sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N,
  1183. ) # 设置说明
  1184. row += 1
  1185. tkinter.Label(
  1186. SCREEN,
  1187. text="提交描述:",
  1188. bg=bg_color,
  1189. fg=word_color,
  1190. font=FONT,
  1191. width=gui_width,
  1192. height=gui_height,
  1193. ).grid(column=column, row=row)
  1194. commit_message = tkinter.Entry(SCREEN, width=gui_width * 2)
  1195. commit_message.grid(
  1196. column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W
  1197. )
  1198. row += 1
  1199. tkinter.Label(
  1200. SCREEN,
  1201. text="diff分支:",
  1202. bg=bg_color,
  1203. fg=word_color,
  1204. font=FONT,
  1205. width=gui_width,
  1206. height=gui_height,
  1207. ).grid(column=column, row=row)
  1208. master = tkinter.Entry(SCREEN, width=gui_width * 2)
  1209. master.grid(column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W)
  1210. row += 1
  1211. tkinter.Label(
  1212. SCREEN,
  1213. text="回退版本号:",
  1214. bg=bg_color,
  1215. fg=word_color,
  1216. font=FONT,
  1217. width=gui_width,
  1218. height=gui_height,
  1219. ).grid(column=column, row=row)
  1220. head = tkinter.Entry(SCREEN, width=gui_width * 2)
  1221. head.grid(column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W)
  1222. row += 1
  1223. tkinter.Label(
  1224. SCREEN,
  1225. text="本地分支:",
  1226. bg=bg_color,
  1227. fg=word_color,
  1228. font=FONT,
  1229. width=gui_width,
  1230. height=gui_height,
  1231. ).grid(column=column, row=row)
  1232. branch_name = tkinter.Entry(SCREEN, width=gui_width * 2)
  1233. branch_name.grid(
  1234. column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W
  1235. )
  1236. row += 1
  1237. tkinter.Label(
  1238. SCREEN,
  1239. text="远程分支:",
  1240. bg=bg_color,
  1241. fg=word_color,
  1242. font=FONT,
  1243. width=gui_width,
  1244. height=gui_height,
  1245. ).grid(column=column, row=row)
  1246. origin_branch = tkinter.Entry(SCREEN, width=gui_width * 2)
  1247. origin_branch.grid(
  1248. column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W
  1249. )
  1250. row += 1
  1251. tkinter.Label(
  1252. SCREEN,
  1253. text="远程仓库链接:",
  1254. bg=bg_color,
  1255. fg=word_color,
  1256. font=FONT,
  1257. width=gui_width,
  1258. height=gui_height,
  1259. ).grid(column=column, row=row)
  1260. remote_ssh = tkinter.Entry(SCREEN, width=gui_width)
  1261. remote_ssh.grid(column=column + 1, columnspan=2, row=row, sticky=tkinter.E + tkinter.W)
  1262. row += 1
  1263. tkinter.Label(
  1264. SCREEN,
  1265. text="远程仓库名:",
  1266. bg=bg_color,
  1267. fg=word_color,
  1268. font=FONT,
  1269. width=gui_width,
  1270. height=gui_height,
  1271. ).grid(column=column, row=row)
  1272. remote_name = tkinter.Entry(SCREEN, width=gui_width)
  1273. remote_name.grid(
  1274. column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W
  1275. )
  1276. row += 1
  1277. tkinter.Label(
  1278. SCREEN,
  1279. text="commit:",
  1280. bg=bg_color,
  1281. fg=word_color,
  1282. font=FONT,
  1283. width=gui_width,
  1284. height=gui_height,
  1285. ).grid(column=column, row=row)
  1286. commit = tkinter.Entry(SCREEN, width=gui_width)
  1287. commit.grid(column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W)
  1288. row += 1
  1289. tkinter.Label(
  1290. SCREEN,
  1291. text="标签名字:",
  1292. bg=bg_color,
  1293. fg=word_color,
  1294. font=FONT,
  1295. width=gui_width,
  1296. height=gui_height,
  1297. ).grid(column=column, row=row)
  1298. tag_name = tkinter.Entry(SCREEN, width=gui_width)
  1299. tag_name.grid(column=column + 1, columnspan=2, row=row, sticky=tkinter.E + tkinter.W)
  1300. row += 1
  1301. tkinter.Label(
  1302. SCREEN,
  1303. text="查询关键字:",
  1304. bg=bg_color,
  1305. fg=word_color,
  1306. font=FONT,
  1307. width=gui_width,
  1308. height=gui_height,
  1309. ).grid(column=column, row=row)
  1310. show_search_key = tkinter.Entry(SCREEN, width=gui_width)
  1311. show_search_key.grid(
  1312. column=column + 1, columnspan=2, row=row, sticky=tkinter.E + tkinter.W
  1313. )
  1314. row += 1
  1315. tkinter.Label(
  1316. SCREEN,
  1317. text="工作区序号:",
  1318. bg=bg_color,
  1319. fg=word_color,
  1320. font=FONT,
  1321. width=gui_width,
  1322. height=gui_height,
  1323. ).grid(column=column, row=row)
  1324. stash_name = tkinter.Entry(SCREEN, width=gui_width)
  1325. stash_name.grid(column=column + 1, row=row, columnspan=2, sticky=tkinter.E + tkinter.W)
  1326. row += 1
  1327. tkinter.Label(
  1328. SCREEN,
  1329. text="【高级操作】",
  1330. bg=bg_color,
  1331. fg=word_color,
  1332. font=FONT,
  1333. width=gui_width * 3,
  1334. height=gui_height,
  1335. ).grid(
  1336. column=column,
  1337. columnspan=3,
  1338. row=row,
  1339. sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N,
  1340. ) # 设置说明
  1341. row += 1
  1342. tkinter.Button(
  1343. SCREEN,
  1344. bg=buttom_color,
  1345. fg=word_color,
  1346. text="查看分支",
  1347. command=lambda: API.not_parameters_call(git.branch_view),
  1348. font=FONT,
  1349. width=gui_width,
  1350. height=gui_height,
  1351. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1352. tkinter.Button(
  1353. SCREEN,
  1354. bg=buttom_color,
  1355. fg=word_color,
  1356. text="新建分支",
  1357. command=API.add_new_branch,
  1358. font=FONT,
  1359. width=gui_width,
  1360. height=gui_height,
  1361. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1362. tkinter.Button(
  1363. SCREEN,
  1364. bg=buttom_color,
  1365. fg=word_color,
  1366. text="切换分支",
  1367. command=API.switch_branch,
  1368. font=FONT,
  1369. width=gui_width,
  1370. height=gui_height,
  1371. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1372. row += 1
  1373. tkinter.Button(
  1374. SCREEN,
  1375. bg=buttom_color,
  1376. fg=word_color,
  1377. text="删除分支",
  1378. command=lambda: API.del_branch(1),
  1379. font=FONT,
  1380. width=gui_width,
  1381. height=gui_height,
  1382. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1383. tkinter.Button(
  1384. SCREEN,
  1385. bg=buttom_color,
  1386. fg=word_color,
  1387. text="丢弃分支",
  1388. command=lambda: API.del_branch(0),
  1389. font=FONT,
  1390. width=gui_width,
  1391. height=gui_height,
  1392. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1393. tkinter.Button(
  1394. SCREEN,
  1395. bg=buttom_color,
  1396. fg=word_color,
  1397. text="合并分支",
  1398. command=API.switch_branch,
  1399. font=FONT,
  1400. width=gui_width,
  1401. height=gui_height,
  1402. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1403. no_fast_forward = tkinter.IntVar()
  1404. row += 1
  1405. tkinter.Button(
  1406. SCREEN,
  1407. bg=buttom_color,
  1408. fg=word_color,
  1409. text="合并分支",
  1410. command=API.branch_merge,
  1411. font=FONT,
  1412. width=gui_width,
  1413. height=gui_height,
  1414. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1415. tkinter.Button(
  1416. SCREEN,
  1417. bg=buttom_color,
  1418. fg=word_color,
  1419. text="退出冲突处理",
  1420. command=lambda: API.not_parameters_call(git.merge_abort),
  1421. font=FONT,
  1422. width=gui_width,
  1423. height=gui_height,
  1424. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1425. tkinter.Checkbutton(
  1426. SCREEN,
  1427. bg=bg_color,
  1428. fg=word_color,
  1429. activebackground=bg_color,
  1430. activeforeground=word_color,
  1431. selectcolor=bg_color,
  1432. text="使用快速合并",
  1433. variable=no_fast_forward,
  1434. ).grid(column=column + 1, row=row, sticky=tkinter.W)
  1435. no_fast_forward.set(0)
  1436. row += 1
  1437. tkinter.Button(
  1438. SCREEN,
  1439. bg=buttom_color,
  1440. fg=word_color,
  1441. text="连接远程仓库",
  1442. command=API.add_remote,
  1443. font=FONT,
  1444. width=gui_width,
  1445. height=gui_height,
  1446. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1447. tkinter.Button(
  1448. SCREEN,
  1449. bg=buttom_color,
  1450. fg=word_color,
  1451. text="推送到远程仓库",
  1452. command=lambda: API.pull_push_remote(1),
  1453. font=FONT,
  1454. width=gui_width,
  1455. height=gui_height,
  1456. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1457. tkinter.Button(
  1458. SCREEN,
  1459. bg=buttom_color,
  1460. fg=word_color,
  1461. text="从远程仓库抓取",
  1462. command=lambda: API.pull_push_remote(0),
  1463. font=FONT,
  1464. width=gui_width,
  1465. height=gui_height,
  1466. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1467. push_bind = tkinter.IntVar()
  1468. allow_history = tkinter.IntVar()
  1469. row += 1
  1470. tkinter.Button(
  1471. SCREEN,
  1472. bg=buttom_color,
  1473. fg=word_color,
  1474. text="分支绑定",
  1475. command=API.bind_remote_branch,
  1476. font=FONT,
  1477. width=gui_width,
  1478. height=gui_height,
  1479. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1480. tkinter.Checkbutton(
  1481. SCREEN,
  1482. bg=bg_color,
  1483. fg=word_color,
  1484. activebackground=bg_color,
  1485. activeforeground=word_color,
  1486. selectcolor=bg_color,
  1487. text="无视历史记录",
  1488. variable=allow_history,
  1489. ).grid(column=column + 1, row=row, sticky=tkinter.W)
  1490. tkinter.Checkbutton(
  1491. SCREEN,
  1492. bg=bg_color,
  1493. fg=word_color,
  1494. activebackground=bg_color,
  1495. activeforeground=word_color,
  1496. selectcolor=bg_color,
  1497. text="推送时绑定",
  1498. variable=push_bind,
  1499. ).grid(column=column + 2, row=row, sticky=tkinter.W)
  1500. allow_history.set(0)
  1501. push_bind.set(0)
  1502. row += 1
  1503. tkinter.Button(
  1504. SCREEN,
  1505. bg=buttom_color,
  1506. fg=word_color,
  1507. text="应用标签",
  1508. command=API.add_tag,
  1509. font=FONT,
  1510. width=gui_width,
  1511. height=gui_height,
  1512. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1513. tkinter.Button(
  1514. SCREEN,
  1515. bg=buttom_color,
  1516. fg=word_color,
  1517. text="查看已有标签",
  1518. command=lambda: API.show_tag(1),
  1519. font=FONT,
  1520. width=gui_width,
  1521. height=gui_height,
  1522. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1523. tkinter.Button(
  1524. SCREEN,
  1525. bg=buttom_color,
  1526. fg=word_color,
  1527. text="查询commit记录",
  1528. command=lambda: API.show_tag(0),
  1529. font=FONT,
  1530. width=gui_width,
  1531. height=gui_height,
  1532. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1533. row += 1
  1534. tkinter.Button(
  1535. SCREEN,
  1536. bg=buttom_color,
  1537. fg=word_color,
  1538. text="推送标签",
  1539. command=API.push_tag,
  1540. font=FONT,
  1541. width=gui_width,
  1542. height=gui_height,
  1543. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1544. tkinter.Button(
  1545. SCREEN,
  1546. bg=buttom_color,
  1547. fg=word_color,
  1548. text="推送所有标签",
  1549. command=API.push_all_tag,
  1550. font=FONT,
  1551. width=gui_width,
  1552. height=gui_height,
  1553. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1554. tkinter.Button(
  1555. SCREEN,
  1556. bg=buttom_color,
  1557. fg=word_color,
  1558. text="删除本地标签",
  1559. command=API.del_tag,
  1560. font=FONT,
  1561. width=gui_width,
  1562. height=gui_height,
  1563. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1564. row += 1
  1565. tkinter.Button(
  1566. SCREEN,
  1567. bg=buttom_color,
  1568. fg=word_color,
  1569. text="删除远程标签",
  1570. command=API.del_remote_tag,
  1571. font=FONT,
  1572. width=gui_width,
  1573. height=gui_height,
  1574. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1575. tkinter.Button(
  1576. SCREEN,
  1577. bg=buttom_color,
  1578. fg=word_color,
  1579. text="删除远程分支",
  1580. command=API.del_remote_branch,
  1581. font=FONT,
  1582. width=gui_width,
  1583. height=gui_height,
  1584. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1585. tkinter.Button(
  1586. SCREEN,
  1587. bg=buttom_color,
  1588. fg=word_color,
  1589. text="刷新远程分支",
  1590. command=API.fetch_remote,
  1591. font=FONT,
  1592. width=gui_width,
  1593. height=gui_height,
  1594. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1595. row += 1
  1596. tkinter.Button(
  1597. SCREEN,
  1598. bg=buttom_color,
  1599. fg=word_color,
  1600. text="commit补丁",
  1601. command=API.cherry_pick,
  1602. font=FONT,
  1603. width=gui_width,
  1604. height=gui_height,
  1605. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1606. tkinter.Button(
  1607. SCREEN,
  1608. bg=buttom_color,
  1609. fg=word_color,
  1610. text="删除远程仓库",
  1611. command=API.del_remote,
  1612. font=FONT,
  1613. width=gui_width,
  1614. height=gui_height,
  1615. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1616. tkinter.Button(
  1617. SCREEN,
  1618. bg=buttom_color,
  1619. fg=word_color,
  1620. text="工作区列表",
  1621. command=lambda: API.not_parameters_call(git.stash_list),
  1622. font=FONT,
  1623. width=gui_width,
  1624. height=gui_height,
  1625. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1626. row += 1
  1627. tkinter.Button(
  1628. SCREEN,
  1629. bg=buttom_color,
  1630. fg=word_color,
  1631. text="文件回退",
  1632. command=API.reset_file,
  1633. font=FONT,
  1634. width=gui_width,
  1635. height=gui_height,
  1636. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1637. tkinter.Button(
  1638. SCREEN,
  1639. bg=buttom_color,
  1640. fg=word_color,
  1641. text="分支重命名",
  1642. command=API.branch_new,
  1643. font=FONT,
  1644. width=gui_width,
  1645. height=gui_height,
  1646. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1647. branch_new_name = tkinter.Entry(SCREEN, width=gui_width)
  1648. branch_new_name.grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1649. row += 1
  1650. tkinter.Button(
  1651. SCREEN,
  1652. bg=buttom_color,
  1653. fg=word_color,
  1654. text="保存工作区",
  1655. command=lambda: API.not_parameters_call(git.save_stash),
  1656. font=FONT,
  1657. width=gui_width,
  1658. height=gui_height,
  1659. ).grid(column=column, row=row, sticky=tkinter.E + tkinter.W)
  1660. tkinter.Button(
  1661. SCREEN,
  1662. bg=buttom_color,
  1663. fg=word_color,
  1664. text="恢复工作区",
  1665. command=lambda: API.open_stash(1),
  1666. font=FONT,
  1667. width=gui_width,
  1668. height=gui_height,
  1669. ).grid(column=column + 1, row=row, sticky=tkinter.E + tkinter.W)
  1670. tkinter.Button(
  1671. SCREEN,
  1672. bg=buttom_color,
  1673. fg=word_color,
  1674. text="删除工作区",
  1675. command=lambda: API.open_stash(0),
  1676. font=FONT,
  1677. width=gui_width,
  1678. height=gui_height,
  1679. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1680. row += 1
  1681. threaded_refresh = tkinter.IntVar()
  1682. asynchronous_display = tkinter.IntVar()
  1683. tkinter.Checkbutton(
  1684. SCREEN,
  1685. bg=bg_color,
  1686. fg=word_color,
  1687. activebackground=bg_color,
  1688. activeforeground=word_color,
  1689. selectcolor=bg_color,
  1690. text="多进程刷新",
  1691. variable=threaded_refresh,
  1692. ).grid(column=0, row=row, sticky=tkinter.W)
  1693. tkinter.Checkbutton(
  1694. SCREEN,
  1695. bg=bg_color,
  1696. fg=word_color,
  1697. activebackground=bg_color,
  1698. activeforeground=word_color,
  1699. selectcolor=bg_color,
  1700. text="异步显示",
  1701. variable=asynchronous_display,
  1702. ).grid(column=1, row=row, sticky=tkinter.W)
  1703. customize_input = tkinter.Entry(SCREEN, width=gui_width * 3)
  1704. customize_input.grid(
  1705. column=2,
  1706. row=row,
  1707. columnspan=4,
  1708. sticky=tkinter.E + tkinter.W + tkinter.N + tkinter.S,
  1709. )
  1710. tkinter.Button(
  1711. SCREEN,
  1712. bg=buttom_color,
  1713. fg=word_color,
  1714. text="执行操作",
  1715. command=API.customize,
  1716. font=FONT,
  1717. width=gui_width,
  1718. height=gui_height,
  1719. ).grid(column=column + 2, row=row, sticky=tkinter.E + tkinter.W)
  1720. threaded_refresh.set(0)
  1721. asynchronous_display.set(1)
  1722. tag_message = commit_message
  1723. tag_commit = commit
  1724. remote_branch = origin_branch
  1725. local_branch = branch_name