je-editor 0.0.222__py3-none-any.whl → 0.0.224__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of je-editor might be problematic. Click here for more details.
- je_editor/__init__.py +2 -2
- je_editor/git_client/commit_graph.py +7 -7
- je_editor/git_client/git_action.py +0 -7
- je_editor/pyside_ui/browser/browser_view.py +16 -4
- je_editor/pyside_ui/browser/browser_widget.py +43 -29
- je_editor/pyside_ui/browser/main_browser_widget.py +85 -0
- je_editor/pyside_ui/code/auto_save/auto_save_manager.py +34 -2
- je_editor/pyside_ui/code/auto_save/auto_save_thread.py +19 -6
- je_editor/pyside_ui/code/code_format/pep8_format.py +53 -9
- je_editor/pyside_ui/code/code_process/code_exec.py +88 -52
- je_editor/pyside_ui/code/plaintext_code_edit/code_edit_plaintext.py +116 -55
- je_editor/pyside_ui/code/running_process_manager.py +19 -1
- je_editor/pyside_ui/code/shell_process/shell_exec.py +71 -48
- je_editor/pyside_ui/code/syntax/python_syntax.py +45 -10
- je_editor/pyside_ui/code/syntax/syntax_setting.py +40 -12
- je_editor/pyside_ui/code/textedit_code_result/code_record.py +34 -12
- je_editor/pyside_ui/code/variable_inspector/inspector_gui.py +53 -6
- je_editor/pyside_ui/dialog/ai_dialog/set_ai_dialog.py +30 -3
- je_editor/pyside_ui/dialog/file_dialog/create_file_dialog.py +35 -2
- je_editor/pyside_ui/dialog/file_dialog/open_file_dialog.py +33 -5
- je_editor/pyside_ui/dialog/file_dialog/save_file_dialog.py +25 -3
- je_editor/pyside_ui/dialog/search_ui/search_error_box.py +26 -1
- je_editor/pyside_ui/dialog/search_ui/search_text_box.py +26 -1
- je_editor/pyside_ui/git_ui/code_diff_compare/code_diff_viewer_widget.py +11 -11
- je_editor/pyside_ui/git_ui/git_client/commit_table.py +46 -8
- je_editor/pyside_ui/git_ui/git_client/git_branch_tree_widget.py +49 -15
- je_editor/pyside_ui/git_ui/git_client/git_client_gui.py +81 -16
- je_editor/pyside_ui/git_ui/git_client/graph_view.py +64 -20
- je_editor/pyside_ui/main_ui/ai_widget/ai_config.py +20 -5
- je_editor/pyside_ui/main_ui/ai_widget/ask_thread.py +20 -1
- je_editor/pyside_ui/main_ui/ai_widget/chat_ui.py +56 -41
- je_editor/pyside_ui/main_ui/ai_widget/langchain_interface.py +45 -6
- je_editor/pyside_ui/main_ui/console_widget/console_gui.py +44 -12
- je_editor/pyside_ui/main_ui/console_widget/qprocess_adapter.py +34 -13
- je_editor/pyside_ui/main_ui/dock/destroy_dock.py +33 -2
- je_editor/pyside_ui/main_ui/editor/editor_widget.py +104 -20
- je_editor/pyside_ui/main_ui/editor/editor_widget_dock.py +34 -7
- je_editor/pyside_ui/main_ui/editor/process_input.py +38 -11
- je_editor/pyside_ui/main_ui/ipython_widget/rich_jupyter.py +46 -11
- je_editor/pyside_ui/main_ui/main_editor.py +180 -42
- je_editor/pyside_ui/main_ui/menu/check_style_menu/build_check_style_menu.py +51 -28
- je_editor/pyside_ui/main_ui/menu/dock_menu/build_dock_menu.py +83 -36
- je_editor/pyside_ui/main_ui/menu/file_menu/build_file_menu.py +70 -17
- je_editor/pyside_ui/main_ui/menu/help_menu/build_help_menu.py +35 -4
- je_editor/pyside_ui/main_ui/menu/language_menu/build_language_server.py +41 -1
- je_editor/pyside_ui/main_ui/menu/python_env_menu/build_venv_menu.py +100 -42
- je_editor/pyside_ui/main_ui/menu/run_menu/build_run_menu.py +57 -7
- je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_debug_menu.py +50 -4
- je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_program_menu.py +52 -6
- je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_shell_menu.py +44 -4
- je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/utils.py +23 -1
- je_editor/pyside_ui/main_ui/menu/set_menu_bar.py +37 -12
- je_editor/pyside_ui/main_ui/menu/style_menu/build_style_menu.py +44 -7
- je_editor/pyside_ui/main_ui/menu/tab_menu/build_tab_menu.py +127 -44
- je_editor/pyside_ui/main_ui/menu/text_menu/build_text_menu.py +65 -1
- je_editor/pyside_ui/main_ui/save_settings/setting_utils.py +18 -1
- je_editor/pyside_ui/main_ui/save_settings/user_color_setting_file.py +33 -3
- je_editor/pyside_ui/main_ui/save_settings/user_setting_file.py +38 -11
- je_editor/pyside_ui/main_ui/system_tray/extend_system_tray.py +39 -2
- je_editor/start_editor.py +26 -1
- je_editor/utils/encodings/python_encodings.py +101 -98
- je_editor/utils/file/open/open_file.py +36 -19
- je_editor/utils/file/save/save_file.py +35 -14
- je_editor/utils/json/json_file.py +29 -14
- je_editor/utils/json_format/json_process.py +33 -2
- je_editor/utils/logging/loggin_instance.py +38 -8
- je_editor/utils/multi_language/multi_language_wrapper.py +29 -4
- je_editor/utils/redirect_manager/redirect_manager_class.py +49 -11
- je_editor/utils/venv_check/check_venv.py +45 -15
- {je_editor-0.0.222.dist-info → je_editor-0.0.224.dist-info}/METADATA +1 -1
- {je_editor-0.0.222.dist-info → je_editor-0.0.224.dist-info}/RECORD +74 -74
- je_editor/git_client/github.py +0 -81
- {je_editor-0.0.222.dist-info → je_editor-0.0.224.dist-info}/WHEEL +0 -0
- {je_editor-0.0.222.dist-info → je_editor-0.0.224.dist-info}/licenses/LICENSE +0 -0
- {je_editor-0.0.222.dist-info → je_editor-0.0.224.dist-info}/top_level.txt +0 -0
|
@@ -4,38 +4,66 @@ import sys
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Dict, Type
|
|
6
6
|
|
|
7
|
+
# 匯入 Jedi 設定,用於 Python 自動補全與分析
|
|
8
|
+
# Import Jedi settings for Python auto-completion and analysis
|
|
7
9
|
import jedi.settings
|
|
10
|
+
|
|
11
|
+
# 匯入 PySide6 (Qt for Python) 的核心模組
|
|
12
|
+
# Import PySide6 core modules
|
|
8
13
|
from PySide6.QtCore import QTimer, QEvent
|
|
9
14
|
from PySide6.QtGui import QFontDatabase, QIcon, Qt, QTextCharFormat
|
|
10
15
|
from PySide6.QtWidgets import QMainWindow, QWidget, QTabWidget
|
|
11
|
-
|
|
16
|
+
|
|
17
|
+
# 匯入 Qt Material 主題工具
|
|
18
|
+
# Import Qt Material style tools
|
|
12
19
|
from qt_material import QtStyleTools
|
|
13
20
|
|
|
21
|
+
# 匯入專案內部模組 (自訂 UI 與功能)
|
|
22
|
+
# Import project-specific modules (custom UI and features)
|
|
14
23
|
from je_editor.pyside_ui.browser.browser_widget import BrowserWidget
|
|
24
|
+
from je_editor.pyside_ui.browser.main_browser_widget import MainBrowserWidget
|
|
15
25
|
from je_editor.pyside_ui.code.auto_save.auto_save_manager import init_new_auto_save_thread, file_is_open_manager_dict
|
|
16
26
|
from je_editor.pyside_ui.main_ui.editor.editor_widget import EditorWidget
|
|
17
27
|
from je_editor.pyside_ui.main_ui.menu.set_menu_bar import set_menu_bar
|
|
18
|
-
from je_editor.pyside_ui.main_ui.save_settings.user_color_setting_file import
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
from je_editor.pyside_ui.main_ui.save_settings.user_color_setting_file import (
|
|
29
|
+
write_user_color_setting,
|
|
30
|
+
read_user_color_setting,
|
|
31
|
+
update_actually_color_dict,
|
|
32
|
+
actually_color_dict
|
|
33
|
+
)
|
|
34
|
+
from je_editor.pyside_ui.main_ui.save_settings.user_setting_file import (
|
|
35
|
+
user_setting_dict,
|
|
36
|
+
read_user_setting,
|
|
21
37
|
write_user_setting
|
|
38
|
+
)
|
|
22
39
|
from je_editor.pyside_ui.main_ui.system_tray.extend_system_tray import ExtendSystemTray
|
|
23
40
|
from je_editor.utils.file.open.open_file import read_file
|
|
24
41
|
from je_editor.utils.logging.loggin_instance import jeditor_logger
|
|
25
42
|
from je_editor.utils.multi_language.multi_language_wrapper import language_wrapper
|
|
26
43
|
from je_editor.utils.redirect_manager.redirect_manager_class import redirect_manager_instance
|
|
27
44
|
|
|
45
|
+
# 定義一個字典,用來存放可擴充的 Tab (標籤頁)
|
|
46
|
+
# Define a dictionary to store extendable tabs
|
|
28
47
|
EDITOR_EXTEND_TAB: Dict[str, Type[QWidget]] = {}
|
|
29
48
|
|
|
30
49
|
|
|
31
50
|
class EditorMain(QMainWindow, QtStyleTools):
|
|
51
|
+
"""
|
|
52
|
+
主編輯器視窗類別
|
|
53
|
+
Main editor window class
|
|
54
|
+
繼承 QMainWindow 與 QtStyleTools
|
|
55
|
+
"""
|
|
32
56
|
|
|
33
57
|
def __init__(self, debug_mode: bool = False, show_system_tray_ray: bool = False):
|
|
58
|
+
# 初始化時記錄 log
|
|
59
|
+
# Log initialization
|
|
34
60
|
jeditor_logger.info(f"Init EditorMain "
|
|
35
61
|
f"debug_mode: {debug_mode} "
|
|
36
62
|
f"show_system_tray_ray: {show_system_tray_ray}")
|
|
37
63
|
super(EditorMain, self).__init__()
|
|
38
|
-
|
|
64
|
+
|
|
65
|
+
# 初始化變數
|
|
66
|
+
# Initialize variables
|
|
39
67
|
self.file_menu = None
|
|
40
68
|
self.code_result = None
|
|
41
69
|
self.code_edit = None
|
|
@@ -45,77 +73,130 @@ class EditorMain(QMainWindow, QtStyleTools):
|
|
|
45
73
|
self.font_menu = None
|
|
46
74
|
self.working_dir = None
|
|
47
75
|
self.show_system_tray_ray = show_system_tray_ray
|
|
48
|
-
|
|
49
|
-
#
|
|
76
|
+
|
|
77
|
+
# 讀取使用者設定
|
|
78
|
+
# Read user settings
|
|
50
79
|
read_user_setting()
|
|
51
|
-
|
|
80
|
+
|
|
81
|
+
# 設定語言 (多語系支援)
|
|
82
|
+
# Set language (multi-language support)
|
|
52
83
|
language_wrapper.reset_language(user_setting_dict.get("language", "English"))
|
|
53
|
-
|
|
84
|
+
|
|
85
|
+
# Jedi 設定:關閉快取解析器,避免執行緒問題
|
|
86
|
+
# Jedi settings: disable fast parser for thread safety
|
|
54
87
|
jedi.settings.fast_parser = False
|
|
55
|
-
#
|
|
56
|
-
|
|
57
|
-
#
|
|
88
|
+
jedi.settings.case_insensitive_completion = False # 關閉大小寫不敏感補全 / Disable case-insensitive completion
|
|
89
|
+
|
|
90
|
+
# Python 編譯器 (可由使用者指定)
|
|
91
|
+
# Python compiler (can be set by user)
|
|
58
92
|
self.python_compiler = None
|
|
93
|
+
|
|
94
|
+
# 除錯模式
|
|
59
95
|
# Debug mode
|
|
60
96
|
self.debug_mode: bool = debug_mode
|
|
61
|
-
|
|
97
|
+
|
|
98
|
+
# Windows 系統專用:設定應用程式 ID
|
|
99
|
+
# Windows only: set application ID
|
|
62
100
|
self.id = language_wrapper.language_word_dict.get("application_name")
|
|
63
101
|
if sys.platform in ["win32", "cygwin", "msys"]:
|
|
64
102
|
from ctypes import windll
|
|
65
103
|
windll.shell32.SetCurrentProcessExplicitAppUserModelID(self.id)
|
|
66
|
-
|
|
104
|
+
|
|
105
|
+
# 設定 Python 輸出不緩衝
|
|
106
|
+
# Set Python output unbuffered
|
|
67
107
|
os.environ["PYTHONUNBUFFERED"] = "1"
|
|
68
|
-
|
|
108
|
+
|
|
109
|
+
# 自動儲存執行緒
|
|
110
|
+
# Auto-save thread
|
|
69
111
|
self.auto_save_thread = None
|
|
70
|
-
|
|
112
|
+
|
|
113
|
+
# 預設編碼
|
|
114
|
+
# Default encoding
|
|
71
115
|
self.encoding = "utf-8"
|
|
116
|
+
|
|
117
|
+
# 讀取使用者顏色設定
|
|
118
|
+
# Read user color settings
|
|
72
119
|
read_user_color_setting()
|
|
73
|
-
|
|
120
|
+
|
|
121
|
+
# 字型資料庫
|
|
122
|
+
# Font database
|
|
74
123
|
self.font_database = QFontDatabase()
|
|
75
|
-
|
|
124
|
+
|
|
125
|
+
# 建立 TabWidget (多分頁編輯器)
|
|
126
|
+
# Create TabWidget (multi-tab editor)
|
|
76
127
|
self.tab_widget = QTabWidget()
|
|
77
|
-
self.tab_widget.setTabsClosable(True)
|
|
128
|
+
self.tab_widget.setTabsClosable(True) # 可關閉分頁 / Tabs closable
|
|
78
129
|
self.tab_widget.setAttribute(Qt.WidgetAttribute.WA_AlwaysShowToolTips, on=False)
|
|
79
130
|
self.tab_widget.tabCloseRequested.connect(self.close_tab)
|
|
80
|
-
|
|
131
|
+
|
|
132
|
+
# 建立計時器,用來處理訊息重導 (stdout/stderr)
|
|
133
|
+
# Timer for redirecting messages (stdout/stderr)
|
|
81
134
|
self.redirect_timer = QTimer(self)
|
|
82
135
|
self.redirect_timer.setInterval(10)
|
|
83
136
|
self.redirect_timer.start()
|
|
137
|
+
|
|
138
|
+
# 設定視窗標題與提示
|
|
139
|
+
# Set window title and tooltip
|
|
84
140
|
self.setWindowTitle(language_wrapper.language_word_dict.get("application_name"))
|
|
85
141
|
self.setToolTip(language_wrapper.language_word_dict.get("application_name"))
|
|
142
|
+
|
|
143
|
+
# 設定選單列
|
|
144
|
+
# Set menu bar
|
|
86
145
|
set_menu_bar(self)
|
|
87
|
-
|
|
146
|
+
|
|
147
|
+
# 設定應用程式圖示
|
|
148
|
+
# Set application icon
|
|
88
149
|
self.icon_path = Path(os.getcwd() + "/je_driver_icon.ico")
|
|
89
150
|
self.icon = QIcon(str(self.icon_path))
|
|
90
151
|
if self.icon.isNull() is False:
|
|
91
152
|
self.setWindowIcon(self.icon)
|
|
153
|
+
# 如果系統支援系統匣,則顯示圖示
|
|
154
|
+
# Show system tray icon if available
|
|
92
155
|
if ExtendSystemTray.isSystemTrayAvailable() and self.show_system_tray_ray:
|
|
93
156
|
self.system_tray = ExtendSystemTray(main_window=self)
|
|
94
157
|
self.system_tray.setIcon(self.icon)
|
|
95
158
|
self.system_tray.setVisible(True)
|
|
96
159
|
self.system_tray.show()
|
|
97
160
|
self.system_tray.setToolTip(language_wrapper.language_word_dict.get("application_name"))
|
|
98
|
-
|
|
161
|
+
|
|
162
|
+
# 設定輸出重導 (stdout/stderr)
|
|
163
|
+
# Setup output redirection (stdout/stderr)
|
|
99
164
|
redirect_manager_instance.restore_std()
|
|
100
165
|
redirect_manager_instance.set_redirect()
|
|
101
|
-
|
|
166
|
+
|
|
167
|
+
# 再次設定計時器,定期檢查輸出
|
|
168
|
+
# Setup timer again to check redirected output
|
|
102
169
|
self.redirect_timer = QTimer(self)
|
|
103
170
|
self.redirect_timer.setInterval(10)
|
|
104
171
|
self.redirect_timer.timeout.connect(self.redirect)
|
|
105
172
|
self.redirect_timer.start()
|
|
106
|
-
|
|
173
|
+
|
|
174
|
+
# 建立主要分頁:編輯器與瀏覽器
|
|
175
|
+
# Create main tabs: editor and browser
|
|
176
|
+
main_browser_widget = MainBrowserWidget()
|
|
107
177
|
self.tab_widget.addTab(EditorWidget(self), language_wrapper.language_word_dict.get("tab_name_editor"))
|
|
108
|
-
self.tab_widget.addTab(
|
|
109
|
-
self.tab_widget.addTab(
|
|
110
|
-
BrowserWidget(start_url="https://stackoverflow.com/", search_prefix="https://stackoverflow.com/search?q="),
|
|
111
|
-
language_wrapper.language_word_dict.get("tab_menu_stackoverflow_tab_name"))
|
|
178
|
+
self.tab_widget.addTab(main_browser_widget, language_wrapper.language_word_dict.get("tab_name_web_browser"))
|
|
112
179
|
|
|
180
|
+
# 預設新增一個 StackOverflow 瀏覽分頁
|
|
181
|
+
# Add a default StackOverflow browser tab
|
|
182
|
+
main_browser_widget.add_browser_tab(
|
|
183
|
+
BrowserWidget(start_url="https://stackoverflow.com/", search_prefix="https://stackoverflow.com/search?q="))
|
|
184
|
+
|
|
185
|
+
# 加入擴充的自訂分頁
|
|
186
|
+
# Add extended custom tabs
|
|
113
187
|
for widget_name, widget in EDITOR_EXTEND_TAB.items():
|
|
114
188
|
self.tab_widget.addTab(widget(), widget_name)
|
|
189
|
+
|
|
190
|
+
# 設定中央元件為 TabWidget
|
|
191
|
+
# Set central widget as TabWidget
|
|
115
192
|
self.setCentralWidget(self.tab_widget)
|
|
116
|
-
|
|
193
|
+
|
|
194
|
+
# 啟動時讀取設定
|
|
195
|
+
# Load startup settings
|
|
117
196
|
self.startup_setting()
|
|
118
|
-
|
|
197
|
+
|
|
198
|
+
# 如果是 debug 模式,10 秒後自動關閉
|
|
199
|
+
# If debug mode, auto-close after 10 seconds
|
|
119
200
|
if self.debug_mode:
|
|
120
201
|
close_timer = QTimer(self)
|
|
121
202
|
close_timer.setInterval(10000)
|
|
@@ -123,61 +204,91 @@ class EditorMain(QMainWindow, QtStyleTools):
|
|
|
123
204
|
close_timer.start()
|
|
124
205
|
|
|
125
206
|
def clear_code_result(self):
|
|
207
|
+
"""
|
|
208
|
+
清除目前編輯器的輸出結果
|
|
209
|
+
Clear the current editor's output result
|
|
210
|
+
"""
|
|
126
211
|
jeditor_logger.info(f"EditorMain clear_code_result")
|
|
127
212
|
widget = self.tab_widget.currentWidget()
|
|
128
213
|
if isinstance(widget, EditorWidget):
|
|
129
214
|
widget.code_result.clear()
|
|
130
215
|
|
|
131
216
|
def redirect(self) -> None:
|
|
217
|
+
"""
|
|
218
|
+
將 stdout/stderr 的訊息導入到編輯器的輸出區域
|
|
219
|
+
Redirect stdout/stderr messages into the editor's output area
|
|
220
|
+
"""
|
|
132
221
|
jeditor_logger.info(f"EditorMain redirect")
|
|
222
|
+
# 遍歷所有分頁 (Tab),尋找 EditorWidget
|
|
223
|
+
# Iterate through all tabs to find EditorWidget
|
|
133
224
|
for code_editor in range(self.tab_widget.count()):
|
|
134
225
|
widget = self.tab_widget.widget(code_editor)
|
|
135
226
|
if isinstance(widget, EditorWidget):
|
|
136
|
-
#
|
|
227
|
+
# stdout 輸出處理
|
|
228
|
+
# Handle stdout messages
|
|
137
229
|
if not redirect_manager_instance.std_out_queue.empty():
|
|
138
230
|
output_message = redirect_manager_instance.std_out_queue.get_nowait()
|
|
139
231
|
output_message = str(output_message).strip()
|
|
140
232
|
if output_message:
|
|
141
233
|
text_cursor = self.code_result.textCursor()
|
|
142
234
|
text_format = QTextCharFormat()
|
|
235
|
+
# 設定正常輸出顏色
|
|
236
|
+
# Set normal output color
|
|
143
237
|
text_format.setForeground(actually_color_dict.get("normal_output_color"))
|
|
144
238
|
text_cursor.insertText(output_message, text_format)
|
|
145
239
|
text_cursor.insertBlock()
|
|
240
|
+
|
|
241
|
+
# stderr 錯誤輸出處理
|
|
242
|
+
# Handle stderr messages
|
|
146
243
|
if not redirect_manager_instance.std_err_queue.empty():
|
|
147
244
|
error_message = redirect_manager_instance.std_err_queue.get_nowait()
|
|
148
245
|
error_message = str(error_message).strip()
|
|
149
246
|
if error_message:
|
|
150
247
|
text_cursor = self.code_result.textCursor()
|
|
151
248
|
text_format = QTextCharFormat()
|
|
249
|
+
# 設定錯誤輸出顏色
|
|
250
|
+
# Set error output color
|
|
152
251
|
text_format.setForeground(actually_color_dict.get("error_output_color"))
|
|
153
252
|
text_cursor.insertText(error_message, text_format)
|
|
154
253
|
text_cursor.insertBlock()
|
|
155
|
-
break
|
|
254
|
+
break # 找到第一個 EditorWidget 就結束迴圈 / Stop after first EditorWidget found
|
|
156
255
|
|
|
157
256
|
def startup_setting(self) -> None:
|
|
257
|
+
"""
|
|
258
|
+
啟動時套用使用者設定 (字型、樣式、上次開啟的檔案)
|
|
259
|
+
Apply user settings on startup (fonts, styles, last opened file)
|
|
260
|
+
"""
|
|
158
261
|
jeditor_logger.info(f"EditorMain startup_setting")
|
|
159
|
-
#
|
|
262
|
+
# 設定 UI 字型與大小
|
|
263
|
+
# Set UI font and size
|
|
160
264
|
self.setStyleSheet(
|
|
161
265
|
f"font-size: {user_setting_dict.get('ui_font_size', 12)}pt;"
|
|
162
266
|
f"font-family: {user_setting_dict.get('ui_font', 'Lato')};"
|
|
163
267
|
)
|
|
164
|
-
|
|
268
|
+
|
|
269
|
+
# 套用到每個編輯器分頁
|
|
270
|
+
# Apply settings to each editor tab
|
|
165
271
|
for code_editor_count in range(self.tab_widget.count()):
|
|
166
272
|
widget = self.tab_widget.widget(code_editor_count)
|
|
167
273
|
if isinstance(widget, EditorWidget):
|
|
168
|
-
#
|
|
274
|
+
# 編輯區字型
|
|
275
|
+
# Font for code editor
|
|
169
276
|
widget.code_edit.setStyleSheet(
|
|
170
277
|
f"font-size: {user_setting_dict.get('font_size', 12)}pt;"
|
|
171
278
|
f"font-family: {user_setting_dict.get('font', 'Lato')};"
|
|
172
279
|
)
|
|
173
|
-
#
|
|
280
|
+
# 輸出區字型
|
|
281
|
+
# Font for output area
|
|
174
282
|
widget.code_result.setStyleSheet(
|
|
175
283
|
f"font-size: {user_setting_dict.get('font_size', 12)}pt;"
|
|
176
284
|
f"font-family: {user_setting_dict.get('font', 'Lato')};"
|
|
177
285
|
)
|
|
178
|
-
#
|
|
286
|
+
# 預設 Python 編譯器
|
|
287
|
+
# Default Python compiler
|
|
179
288
|
self.python_compiler = user_setting_dict.get("python_compiler", None)
|
|
180
|
-
|
|
289
|
+
|
|
290
|
+
# 嘗試開啟上次編輯的檔案
|
|
291
|
+
# Try to open last edited file
|
|
181
292
|
last_file = user_setting_dict.get("last_file", None)
|
|
182
293
|
if last_file is not None:
|
|
183
294
|
last_file_path = pathlib.Path(last_file)
|
|
@@ -189,32 +300,51 @@ class EditorMain(QMainWindow, QtStyleTools):
|
|
|
189
300
|
file_is_open_manager_dict.update({str(last_file_path): str(last_file_path.name)})
|
|
190
301
|
widget.rename_self_tab()
|
|
191
302
|
|
|
192
|
-
#
|
|
303
|
+
# 套用 UI 樣式 (主題)
|
|
304
|
+
# Apply UI stylesheet (theme)
|
|
193
305
|
self.apply_stylesheet(self, user_setting_dict.get("ui_style", "dark_amber.xml"))
|
|
194
|
-
#
|
|
306
|
+
# 更新顏色設定
|
|
307
|
+
# Update color settings
|
|
195
308
|
update_actually_color_dict()
|
|
196
309
|
|
|
197
310
|
def go_to_new_tab(self, file_path: Path):
|
|
311
|
+
"""
|
|
312
|
+
開啟新分頁並載入檔案
|
|
313
|
+
Open a new tab and load a file
|
|
314
|
+
"""
|
|
198
315
|
jeditor_logger.info(f"EditorMain go_to_new_tab file_path: {file_path}")
|
|
199
316
|
if file_is_open_manager_dict.get(str(file_path), None) is None:
|
|
317
|
+
# 建立新的編輯器分頁
|
|
318
|
+
# Create a new editor tab
|
|
200
319
|
editor_widget = EditorWidget(self)
|
|
201
320
|
self.tab_widget.addTab(
|
|
202
321
|
editor_widget,
|
|
203
322
|
f"{language_wrapper.language_word_dict.get('tab_menu_editor_tab_name')} "
|
|
204
|
-
f"{self.tab_widget.count()}"
|
|
323
|
+
f"{self.tab_widget.count()}"
|
|
324
|
+
)
|
|
205
325
|
self.tab_widget.setCurrentWidget(editor_widget)
|
|
206
326
|
editor_widget.open_an_file(file_path)
|
|
207
327
|
else:
|
|
328
|
+
# 如果檔案已開啟,直接切換到該分頁
|
|
329
|
+
# If file already opened, switch to that tab
|
|
208
330
|
widget: QWidget = self.tab_widget.findChild(EditorWidget, str(file_path))
|
|
209
331
|
self.tab_widget.setCurrentWidget(widget)
|
|
210
332
|
|
|
211
333
|
def closeEvent(self, event) -> None:
|
|
334
|
+
"""
|
|
335
|
+
視窗關閉事件:儲存使用者設定
|
|
336
|
+
Window close event: save user settings
|
|
337
|
+
"""
|
|
212
338
|
jeditor_logger.info("EditorMain closeEvent")
|
|
213
339
|
write_user_setting()
|
|
214
340
|
write_user_color_setting()
|
|
215
341
|
super().closeEvent(event)
|
|
216
342
|
|
|
217
343
|
def event(self, event: QEvent) -> bool:
|
|
344
|
+
"""
|
|
345
|
+
事件處理:忽略 ToolTip 類型事件
|
|
346
|
+
Event handler: ignore ToolTip events
|
|
347
|
+
"""
|
|
218
348
|
jeditor_logger.info(f"EditorMain event: {event}")
|
|
219
349
|
if event.type() == QEvent.Type.ToolTip:
|
|
220
350
|
event.ignore()
|
|
@@ -223,6 +353,10 @@ class EditorMain(QMainWindow, QtStyleTools):
|
|
|
223
353
|
return super().event(event)
|
|
224
354
|
|
|
225
355
|
def close_tab(self, index: int):
|
|
356
|
+
"""
|
|
357
|
+
關閉指定索引的分頁
|
|
358
|
+
Close tab at given index
|
|
359
|
+
"""
|
|
226
360
|
widget = self.tab_widget.widget(index)
|
|
227
361
|
if widget:
|
|
228
362
|
widget.close()
|
|
@@ -230,4 +364,8 @@ class EditorMain(QMainWindow, QtStyleTools):
|
|
|
230
364
|
|
|
231
365
|
@classmethod
|
|
232
366
|
def debug_close(cls):
|
|
233
|
-
|
|
367
|
+
"""
|
|
368
|
+
除錯模式下自動關閉程式
|
|
369
|
+
Auto-close the program in debug mode
|
|
370
|
+
"""
|
|
371
|
+
sys.exit(0)
|
|
@@ -1,81 +1,104 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
1
|
+
from __future__ import annotations # 啟用未來版本的型別註解功能 / Enable postponed evaluation of type annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING # 僅在型別檢查時使用,避免循環匯入 / Used only for type checking to avoid circular imports
|
|
4
4
|
|
|
5
|
-
from je_editor.pyside_ui.main_ui.editor.editor_widget import EditorWidget
|
|
6
|
-
from je_editor.utils.logging.loggin_instance import jeditor_logger
|
|
7
|
-
from je_editor.utils.multi_language.multi_language_wrapper import language_wrapper
|
|
5
|
+
from je_editor.pyside_ui.main_ui.editor.editor_widget import EditorWidget # 編輯器分頁元件 / Editor tab widget
|
|
6
|
+
from je_editor.utils.logging.loggin_instance import jeditor_logger # 專案內的日誌紀錄器 / Project logger
|
|
7
|
+
from je_editor.utils.multi_language.multi_language_wrapper import language_wrapper # 多語系支援 / Multi-language wrapper
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
from je_editor.pyside_ui.main_ui.main_editor import EditorMain
|
|
11
|
-
from PySide6.QtGui import QAction, QKeySequence
|
|
12
|
-
from yapf.yapflib.yapf_api import FormatCode
|
|
10
|
+
from je_editor.pyside_ui.main_ui.main_editor import EditorMain # 僅在型別檢查時匯入 / Import only for type checking
|
|
13
11
|
|
|
14
|
-
from
|
|
12
|
+
from PySide6.QtGui import QAction, QKeySequence # Qt 動作與快捷鍵 / Qt actions and shortcuts
|
|
13
|
+
from yapf.yapflib.yapf_api import FormatCode # YAPF 程式碼格式化工具 / YAPF code formatter
|
|
14
|
+
|
|
15
|
+
from je_editor.utils.json_format.json_process import reformat_json # JSON 格式化工具 / JSON reformatter
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
def set_check_menu(ui_we_want_to_set: EditorMain) -> None:
|
|
19
|
+
"""
|
|
20
|
+
建立「程式碼檢查/格式化」選單,並加入三個功能:
|
|
21
|
+
- 使用 YAPF 重新格式化 Python 程式碼
|
|
22
|
+
- 重新格式化 JSON
|
|
23
|
+
- 檢查 Python 檔案格式
|
|
24
|
+
|
|
25
|
+
Create "Check/Format Code" menu with three actions:
|
|
26
|
+
- Reformat Python code with YAPF
|
|
27
|
+
- Reformat JSON
|
|
28
|
+
- Check Python file format
|
|
29
|
+
"""
|
|
18
30
|
jeditor_logger.info(f"build_check_style_menu.py set_check_menu ui_we_want_to_set: {ui_we_want_to_set}")
|
|
31
|
+
|
|
32
|
+
# 在主選單中新增一個子選單 / Add submenu to main menu
|
|
19
33
|
ui_we_want_to_set.check_menu = ui_we_want_to_set.menu.addMenu(
|
|
20
34
|
language_wrapper.language_word_dict.get("check_code_style_menu_label"))
|
|
21
|
-
|
|
35
|
+
|
|
36
|
+
# === 1. Yapf Python 程式碼格式化 / Yapf Python code reformat ===
|
|
22
37
|
ui_we_want_to_set.check_menu.yapf_check_python_action = QAction(
|
|
23
38
|
language_wrapper.language_word_dict.get("yapf_reformat_label"))
|
|
24
39
|
ui_we_want_to_set.check_menu.yapf_check_python_action.setShortcut(
|
|
25
|
-
QKeySequence("Ctrl+Shift+Y"))
|
|
40
|
+
QKeySequence("Ctrl+Shift+Y")) # 設定快捷鍵 / Set shortcut
|
|
26
41
|
ui_we_want_to_set.check_menu.yapf_check_python_action.triggered.connect(
|
|
27
|
-
lambda: yapf_check_python_code(
|
|
28
|
-
ui_we_want_to_set
|
|
29
|
-
)
|
|
42
|
+
lambda: yapf_check_python_code(ui_we_want_to_set)
|
|
30
43
|
)
|
|
31
44
|
ui_we_want_to_set.check_menu.addAction(ui_we_want_to_set.check_menu.yapf_check_python_action)
|
|
32
|
-
|
|
45
|
+
|
|
46
|
+
# === 2. JSON 重新格式化 / Reformat JSON ===
|
|
33
47
|
ui_we_want_to_set.check_menu.reformat_json_action = QAction(
|
|
34
48
|
language_wrapper.language_word_dict.get("reformat_json_label"))
|
|
35
49
|
ui_we_want_to_set.check_menu.reformat_json_action.setShortcut("Ctrl+j")
|
|
36
50
|
ui_we_want_to_set.check_menu.reformat_json_action.triggered.connect(
|
|
37
|
-
lambda: reformat_json_text(
|
|
38
|
-
ui_we_want_to_set
|
|
39
|
-
)
|
|
51
|
+
lambda: reformat_json_text(ui_we_want_to_set)
|
|
40
52
|
)
|
|
41
53
|
ui_we_want_to_set.check_menu.addAction(ui_we_want_to_set.check_menu.reformat_json_action)
|
|
42
|
-
|
|
54
|
+
|
|
55
|
+
# === 3. Python 格式檢查 / Python format check ===
|
|
43
56
|
ui_we_want_to_set.check_menu.check_python_format = QAction(
|
|
44
57
|
language_wrapper.language_word_dict.get("python_format_checker"))
|
|
45
58
|
ui_we_want_to_set.check_menu.check_python_format.setShortcut("Ctrl+Alt+p")
|
|
46
59
|
ui_we_want_to_set.check_menu.check_python_format.triggered.connect(
|
|
47
|
-
lambda: check_python_format(
|
|
48
|
-
ui_we_want_to_set
|
|
49
|
-
)
|
|
60
|
+
lambda: check_python_format(ui_we_want_to_set)
|
|
50
61
|
)
|
|
51
62
|
ui_we_want_to_set.check_menu.addAction(ui_we_want_to_set.check_menu.check_python_format)
|
|
52
63
|
|
|
53
64
|
|
|
54
65
|
def yapf_check_python_code(ui_we_want_to_set: EditorMain) -> None:
|
|
66
|
+
"""
|
|
67
|
+
使用 YAPF 重新格式化目前分頁中的 Python 程式碼
|
|
68
|
+
Reformat current tab's Python code using YAPF
|
|
69
|
+
"""
|
|
55
70
|
jeditor_logger.info(f"build_check_style_menu.py yapf_check_python_code ui_we_want_to_set: {ui_we_want_to_set}")
|
|
56
71
|
widget = ui_we_want_to_set.tab_widget.currentWidget()
|
|
57
72
|
if isinstance(widget, EditorWidget):
|
|
58
|
-
code_text = widget.code_edit.toPlainText()
|
|
59
|
-
widget.code_result.setPlainText("")
|
|
73
|
+
code_text = widget.code_edit.toPlainText() # 取得編輯器文字 / Get code text
|
|
74
|
+
widget.code_result.setPlainText("") # 清空結果區域 / Clear result area
|
|
60
75
|
format_code = FormatCode(
|
|
61
76
|
unformatted_source=code_text,
|
|
62
|
-
style_config="google"
|
|
77
|
+
style_config="google" # 使用 Google 風格 / Use Google style
|
|
63
78
|
)
|
|
64
79
|
if isinstance(format_code, tuple):
|
|
65
|
-
widget.code_edit.setPlainText(format_code[0])
|
|
80
|
+
widget.code_edit.setPlainText(format_code[0]) # 將格式化後的程式碼寫回編輯器 / Write formatted code back
|
|
66
81
|
|
|
67
82
|
|
|
68
83
|
def reformat_json_text(ui_we_want_to_set: EditorMain) -> None:
|
|
84
|
+
"""
|
|
85
|
+
重新格式化目前分頁中的 JSON 文字
|
|
86
|
+
Reformat JSON text in the current editor tab
|
|
87
|
+
"""
|
|
69
88
|
jeditor_logger.info(f"build_check_style_menu.py reformat_json_text ui_we_want_to_set: {ui_we_want_to_set}")
|
|
70
89
|
widget = ui_we_want_to_set.tab_widget.currentWidget()
|
|
71
90
|
if isinstance(widget, EditorWidget):
|
|
72
91
|
code_text = widget.code_edit.toPlainText()
|
|
73
92
|
widget.code_result.setPlainText("")
|
|
74
|
-
widget.code_edit.setPlainText(reformat_json(code_text))
|
|
93
|
+
widget.code_edit.setPlainText(reformat_json(code_text)) # 呼叫 JSON 格式化工具 / Call JSON reformatter
|
|
75
94
|
|
|
76
95
|
|
|
77
96
|
def check_python_format(ui_we_want_to_set: EditorMain) -> None:
|
|
97
|
+
"""
|
|
98
|
+
呼叫 EditorWidget 的檔案格式檢查功能
|
|
99
|
+
Call EditorWidget's file format checker
|
|
100
|
+
"""
|
|
78
101
|
jeditor_logger.info(f"build_check_style_menu.py check_python_format ui_we_want_to_set: {ui_we_want_to_set}")
|
|
79
102
|
widget = ui_we_want_to_set.tab_widget.currentWidget()
|
|
80
103
|
if isinstance(widget, EditorWidget):
|
|
81
|
-
widget.check_file_format()
|
|
104
|
+
widget.check_file_format()
|