liuyuqi-cnb 3 months ago
parent
commit
3de653895b
4 changed files with 269 additions and 150 deletions
  1. 266 128
      gui_main.py
  2. 2 6
      main.py
  3. 0 15
      repo_sync/__init__.py
  4. 1 1
      repo_sync/options.py

+ 266 - 128
gui_main.py

@@ -2,13 +2,19 @@ import sys
 import os
 import threading
 import subprocess
-from PyQt5.QtWidgets import (
-    QApplication, QTabWidget, QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
-    QRadioButton, QPushButton, QButtonGroup, QGroupBox, QMessageBox, 
-    QLineEdit, QScrollArea, QFileDialog, QFormLayout, QCheckBox, QTextEdit,
-    QComboBox, QDialog, QDialogButtonBox, QGridLayout, QToolButton
-)
-from PyQt5.QtCore import Qt, pyqtSignal, QObject
+try:
+    from PyQt5.QtWidgets import (
+        QApplication, QTabWidget, QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
+        QRadioButton, QPushButton, QButtonGroup, QGroupBox, QMessageBox, 
+        QLineEdit, QScrollArea, QFileDialog, QFormLayout, QCheckBox, QTextEdit,
+        QComboBox, QDialog, QDialogButtonBox, QGridLayout, QToolButton, QListWidget, QListWidgetItem
+    )
+    from PyQt5.QtCore import Qt, pyqtSignal, QObject
+    HAS_QT = True
+except ImportError:
+    HAS_QT = False
+    print("PyQt5 not installed, GUI mode not available")
+
 from repo_sync import RepoSync, __version__
 from dotenv import load_dotenv, set_key, find_dotenv, dotenv_values
 import json
@@ -129,8 +135,25 @@ class MainTab(QWidget):
         
         # 读取所有账户
         accounts = self.get_platform_accounts(platform)
-        for account_name in accounts:
-            self.account_combo.addItem(account_name)
+        
+        # 找出启用的账户
+        enabled_account = "default"
+        env_values = dotenv_values(find_dotenv())
+        for account in accounts:
+            if account != "default" and env_values.get(f"{platform}_{account}_enabled", "").lower() == "true":
+                enabled_account = account
+                break
+        
+        # 添加账户到下拉框,启用的账户放在最前面
+        if enabled_account in accounts:
+            accounts.remove(enabled_account)
+            self.account_combo.addItem(f"{enabled_account} (启用中)")
+            
+        for account in accounts:
+            self.account_combo.addItem(account)
+        
+        # 默认选择启用的账户
+        self.account_combo.setCurrentIndex(0)
 
     def get_platform_accounts(self, platform):
         # 读取.env文件中的所有配置
@@ -145,7 +168,7 @@ class MainTab(QWidget):
         for key in env_values.keys():
             if key.startswith(prefix) and "_" in key[len(prefix):]:
                 account_name = key[len(prefix):].split("_")[0]
-                if account_name != "default":
+                if account_name != "default" and account_name != "":
                     accounts.add(account_name)
         
         return sorted(list(accounts))
@@ -160,7 +183,10 @@ class MainTab(QWidget):
         pf_id = self.pf_buttons.checkedId()
         op = ["create", "push", "pull", "clone", "delete"][op_id]
         pf = self.platforms[pf_id]
-        account = self.account_combo.currentText()
+        
+        # 获取选择的账户名(去掉可能的"(启用中)"后缀)
+        account_text = self.account_combo.currentText()
+        account = account_text.split(" (")[0] if " (" in account_text else account_text
         
         # 清空结果区域
         self.result_text.clear()
@@ -178,6 +204,16 @@ class MainTab(QWidget):
         cmd.extend(["-p", pf])
         cmd.extend(["-repo_path", repo_path])
         
+        # 如果不是默认账户,需要设置环境变量
+        env = os.environ.copy()
+        if account != "default":
+            # 读取账户配置
+            env_values = dotenv_values(find_dotenv())
+            for key, value in env_values.items():
+                if key.startswith(f"{pf}_{account}_"):
+                    field = key[len(f"{pf}_{account}_"):]
+                    env[f"{pf}_{field}"] = value
+        
         # 执行命令
         self.run_btn.setEnabled(False)
         self.cancel_btn.setEnabled(True)
@@ -186,12 +222,12 @@ class MainTab(QWidget):
         # 在新线程中执行命令
         self.process_thread = threading.Thread(
             target=self.run_process,
-            args=(cmd,)
+            args=(cmd, env)
         )
         self.process_thread.daemon = True
         self.process_thread.start()
 
-    def run_process(self, cmd):
+    def run_process(self, cmd, env=None):
         try:
             self.process = subprocess.Popen(
                 cmd,
@@ -199,7 +235,8 @@ class MainTab(QWidget):
                 stderr=subprocess.STDOUT,
                 text=True,
                 bufsize=1,
-                universal_newlines=True
+                universal_newlines=True,
+                env=env
             )
             
             # 读取输出
@@ -298,16 +335,12 @@ class SettingsTab(QWidget):
     def __init__(self, parent=None):
         super().__init__(parent)
         self.init_ui()
-        self.load_settings()
 
     def init_ui(self):
         layout = QVBoxLayout()
         
-        # 创建滚动区域
-        scroll = QScrollArea()
-        scroll.setWidgetResizable(True)
-        content = QWidget()
-        content_layout = QVBoxLayout()
+        # 创建平台选择标签页
+        self.platform_tabs = QTabWidget()
         
         # 平台配置
         self.platform_configs = {
@@ -321,90 +354,148 @@ class SettingsTab(QWidget):
             "cnb": ["username", "token", "private"]
         }
         
-        # 为每个平台创建分组
-        self.platform_groups = {}
+        # 为每个平台创建标签页
+        self.platform_pages = {}
         for platform in self.platform_configs.keys():
-            group = QGroupBox(platform.capitalize())
-            group_layout = QVBoxLayout()
-            
-            # 账户选择和管理
-            account_header = QHBoxLayout()
-            account_header.addWidget(QLabel("Accounts:"))
-            account_combo = QComboBox()
-            account_combo.setMinimumWidth(200)
-            account_header.addWidget(account_combo)
-            
-            # 添加账户按钮
-            add_btn = QToolButton()
-            add_btn.setText("+")
-            add_btn.clicked.connect(lambda checked, p=platform: self.add_account(p))
-            account_header.addWidget(add_btn)
-            
-            # 删除账户按钮
-            del_btn = QToolButton()
-            del_btn.setText("-")
-            del_btn.clicked.connect(lambda checked, p=platform, c=account_combo: self.delete_account(p, c))
-            account_header.addWidget(del_btn)
-            
-            # 启用账户按钮
-            enable_btn = QPushButton("Enable")
-            enable_btn.clicked.connect(lambda checked, p=platform, c=account_combo: self.enable_account(p, c))
-            account_header.addWidget(enable_btn)
-            
-            group_layout.addLayout(account_header)
-            
-            # 账户详情区域
+            page = QWidget()
+            page_layout = QVBoxLayout()
+            
+            # 账户管理区域
+            account_group = QGroupBox("账户管理")
+            account_layout = QVBoxLayout()
+            
+            # 账户列表
+            accounts_list_layout = QHBoxLayout()
+            
+            # 左侧:账户列表
+            self.account_lists = {}
+            account_list = QListWidget()
+            account_list.setMinimumWidth(200)
+            account_list.itemClicked.connect(lambda item, p=platform: self.select_account(p, item))
+            account_list.setStyleSheet("""
+                QListWidget::item:selected { background-color: #a6d8ff; }
+                QListWidget::item[enabled="true"] { font-weight: bold; color: #0066cc; }
+            """)
+            accounts_list_layout.addWidget(account_list)
+            self.account_lists[platform] = account_list
+            
+            # 右侧:账户详情
             account_details = QWidget()
             account_form = QFormLayout()
             account_details.setLayout(account_form)
-            group_layout.addWidget(account_details)
+            accounts_list_layout.addWidget(account_details, 1)
             
-            group.setLayout(group_layout)
-            content_layout.addWidget(group)
+            account_layout.addLayout(accounts_list_layout)
             
-            # 保存引用
-            self.platform_groups[platform] = {
-                "group": group,
-                "combo": account_combo,
-                "details": account_details,
-                "form": account_form
+            # 账户操作按钮
+            buttons_layout = QHBoxLayout()
+            add_btn = QPushButton("添加账户")
+            add_btn.clicked.connect(lambda checked=False, p=platform: self.add_account(p))
+            delete_btn = QPushButton("删除账户")
+            delete_btn.clicked.connect(lambda checked=False, p=platform: self.delete_account(p))
+            enable_btn = QPushButton("设为启用")
+            enable_btn.clicked.connect(lambda checked=False, p=platform: self.enable_account(p))
+            
+            buttons_layout.addWidget(add_btn)
+            buttons_layout.addWidget(delete_btn)
+            buttons_layout.addWidget(enable_btn)
+            buttons_layout.addStretch()
+            
+            account_layout.addLayout(buttons_layout)
+            account_group.setLayout(account_layout)
+            page_layout.addWidget(account_group)
+            
+            # 保存页面引用
+            self.platform_pages[platform] = {
+                "page": page,
+                "form": account_form,
+                "details": account_details
             }
+            
+            page.setLayout(page_layout)
+            self.platform_tabs.addTab(page, platform.capitalize())
         
-        content.setLayout(content_layout)
-        scroll.setWidget(content)
-        layout.addWidget(scroll)
+        layout.addWidget(self.platform_tabs)
         
         # 保存按钮
-        self.save_btn = QPushButton("Save Settings")
+        self.save_btn = QPushButton("保存设置")
         self.save_btn.clicked.connect(self.save_settings)
         layout.addWidget(self.save_btn, alignment=Qt.AlignCenter)
         
         self.setLayout(layout)
+        
+        # 加载设置
+        self.load_settings()
+        
+        # 连接标签页变更事件
+        self.platform_tabs.currentChanged.connect(self.tab_changed)
+
+    def tab_changed(self, index):
+        try:
+            # 使用有序字典确保顺序一致性
+            platforms = list(self.platform_configs.keys())
+            if index < 0 or index >= len(platforms):
+                return
+            platform = platforms[index]
+            self.update_account_details(platform)
+        except Exception as e:
+            print(f"Error in tab_changed: {e}")
 
     def load_settings(self):
         # 读取.env文件
         env_values = dotenv_values(find_dotenv())
         
         # 为每个平台加载账户
-        for platform, group_data in self.platform_groups.items():
-            combo = group_data["combo"]
-            combo.clear()
+        for platform in self.platform_configs.keys():
+            account_list = self.account_lists[platform]
+            account_list.clear()
             
             # 查找该平台的所有账户
             accounts = self.get_platform_accounts(platform, env_values)
             
-            # 添加到下拉框
+            # 添加到列表
             for account in accounts:
-                combo.addItem(account)
-            
-            # 连接选择变更事件
-            combo.currentIndexChanged.connect(
-                lambda idx, p=platform: self.update_account_details(p)
-            )
+                item = QListWidgetItem(account)
+                # 标记默认账户
+                if account == "default":
+                    item.setData(Qt.UserRole, "default")
+                    # 检查是否有其他账户被设为启用
+                    is_enabled = True
+                    for other_account in accounts:
+                        if other_account != "default" and self.is_account_enabled(platform, other_account, env_values):
+                            is_enabled = False
+                            break
+                    item.setData(Qt.UserRole + 1, is_enabled)
+                else:
+                    item.setData(Qt.UserRole, account)
+                    item.setData(Qt.UserRole + 1, self.is_account_enabled(platform, account, env_values))
+                
+                # 设置启用状态的显示
+                if item.data(Qt.UserRole + 1):
+                    item.setData(Qt.UserRole + 2, "true")
+                    item.setText(f"{account} (启用中)")
+                
+                account_list.addItem(item)
             
-            # 更新当前选择的账户详情
-            if combo.count() > 0:
-                self.update_account_details(platform)
+            # 选择第一个账户
+            if account_list.count() > 0:
+                account_list.setCurrentRow(0)
+                self.select_account(platform, account_list.item(0))
+
+    def is_account_enabled(self, platform, account, env_values=None):
+        """检查账户是否被设为启用"""
+        if env_values is None:
+            env_values = dotenv_values(find_dotenv())
+        
+        if account == "default":
+            # 默认账户,检查是否有其他账户被设为启用
+            for key in env_values.keys():
+                if key.startswith(f"{platform}_") and "_enabled" in key and env_values[key].lower() == "true":
+                    return False
+            return True
+        else:
+            # 其他账户,检查是否有enabled标记
+            return env_values.get(f"{platform}_{account}_enabled", "").lower() == "true"
 
     def get_platform_accounts(self, platform, env_values=None):
         if env_values is None:
@@ -419,25 +510,22 @@ class SettingsTab(QWidget):
         for key in env_values.keys():
             if key.startswith(prefix) and "_" in key[len(prefix):]:
                 account_name = key[len(prefix):].split("_")[0]
-                if account_name != "default":
+                if account_name != "default" and account_name != "":
                     accounts.add(account_name)
         
         return sorted(list(accounts))
 
-    def update_account_details(self, platform):
-        group_data = self.platform_groups[platform]
-        combo = group_data["combo"]
-        form = group_data["form"]
+    def select_account(self, platform, item):
+        if not item:
+            return
+        
+        account = item.data(Qt.UserRole)
+        form = self.platform_pages[platform]["form"]
         
         # 清空表单
         while form.rowCount() > 0:
             form.removeRow(0)
         
-        # 获取当前选择的账户
-        account = combo.currentText()
-        if not account:
-            return
-        
         # 读取账户配置
         env_values = dotenv_values(find_dotenv())
         
@@ -488,13 +576,22 @@ class SettingsTab(QWidget):
             self.load_settings()
             
             # 选择新账户
-            combo = self.platform_groups[platform]["combo"]
-            idx = combo.findText(account_name)
-            if idx >= 0:
-                combo.setCurrentIndex(idx)
+            account_list = self.account_lists[platform]
+            for i in range(account_list.count()):
+                if account_list.item(i).data(Qt.UserRole) == account_name:
+                    account_list.setCurrentRow(i)
+                    self.select_account(platform, account_list.item(i))
+                    break
 
-    def delete_account(self, platform, combo):
-        account = combo.currentText()
+    def delete_account(self, platform):
+        account_list = self.account_lists[platform]
+        current_item = account_list.currentItem()
+        
+        if not current_item:
+            return
+            
+        account = current_item.data(Qt.UserRole)
+        
         if account == "default":
             QMessageBox.warning(self, "Warning", "Cannot delete the default account.")
             return
@@ -524,34 +621,57 @@ class SettingsTab(QWidget):
             # 重新加载设置
             self.load_settings()
 
-    def enable_account(self, platform, combo):
-        account = combo.currentText()
-        if account == "default":
-            QMessageBox.information(self, "Information", "Default account is already enabled.")
+    def enable_account(self, platform):
+        account_list = self.account_lists[platform]
+        current_item = account_list.currentItem()
+        
+        if not current_item:
             return
+            
+        account = current_item.data(Qt.UserRole)
         
         # 读取账户配置
         env_file = find_dotenv()
         env_values = dotenv_values(env_file)
         
-        # 获取账户配置
-        account_config = {}
-        prefix = f"{platform}_{account}_"
-        for key, value in env_values.items():
-            if key.startswith(prefix):
-                field = key[len(prefix):]
-                account_config[field] = value
+        # 先清除所有账户的启用状态
+        for key in list(env_values.keys()):
+            if key.startswith(f"{platform}_") and key.endswith("_enabled"):
+                del env_values[key]
         
-        # 更新默认配置
-        for field, value in account_config.items():
-            default_key = f"{platform}_{field}"
-            set_key(env_file, default_key, value)
+        # 设置当前账户为启用
+        if account != "default":
+            set_key(env_file, f"{platform}_{account}_enabled", "true")
+            
+            # 将账户配置复制到默认配置
+            account_config = {}
+            prefix = f"{platform}_{account}_"
+            for key, value in env_values.items():
+                if key.startswith(prefix):
+                    field = key[len(prefix):]
+                    if field != "enabled":  # 不复制enabled标记
+                        account_config[field] = value
+            
+            # 更新默认配置
+            for field, value in account_config.items():
+                default_key = f"{platform}_{field}"
+                set_key(env_file, default_key, value)
         
         QMessageBox.information(
             self, 
             "Success", 
-            f"Account '{account}' has been enabled as the default for {platform}."
+            f"Account '{account}' has been enabled for {platform}."
         )
+        
+        # 重新加载设置
+        self.load_settings()
+
+    def update_account_details(self, platform):
+        account_list = self.account_lists[platform]
+        current_item = account_list.currentItem()
+        
+        if current_item:
+            self.select_account(platform, current_item)
 
     def save_settings(self):
         env_file = find_dotenv()
@@ -559,22 +679,28 @@ class SettingsTab(QWidget):
             env_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), '.env')
         
         # 保存当前显示的账户配置
-        for platform, group_data in self.platform_groups.items():
-            combo = group_data["combo"]
-            account = combo.currentText()
-            
-            if account and hasattr(self, 'field_widgets'):
-                for key, widget in self.field_widgets.items():
-                    if key.startswith(f"{platform}_{account}"):
-                        if isinstance(widget, QCheckBox):
-                            value = str(widget.isChecked()).lower()
-                        else:
-                            value = widget.text().strip()
-                        
-                        if value:
-                            set_key(env_file, key, value)
+        platform = list(self.platform_configs.keys())[self.platform_tabs.currentIndex()]
+        account_list = self.account_lists[platform]
+        current_item = account_list.currentItem()
+        
+        if current_item and hasattr(self, 'field_widgets'):
+            account = current_item.data(Qt.UserRole)
+            
+            for key, widget in self.field_widgets.items():
+                if key.startswith(f"{platform}_{account}"):
+                    if isinstance(widget, QCheckBox):
+                        value = str(widget.isChecked()).lower()
+                    else:
+                        value = widget.text().strip()
+                    
+                    if value:
+                        set_key(env_file, key, value)
         
         QMessageBox.information(self, "Success", "Settings saved successfully!")
+        
+        # 如果修改的是启用的账户,更新默认配置
+        if current_item and current_item.data(Qt.UserRole + 1):
+            self.enable_account(platform)
 
 class AboutTab(QWidget):
     def __init__(self, parent=None):
@@ -605,10 +731,22 @@ class RepoSyncMainWindow(QTabWidget):
         self.addTab(self.about_tab, '关于')
 
 def main():
-    app = QApplication(sys.argv)
-    window = RepoSyncMainWindow()
-    window.show()
-    sys.exit(app.exec_())
+    """GUI主入口函数"""
+    if not HAS_QT:
+        print("PyQt5 not installed. Please install it with: pip install PyQt5")
+        print("Running in fallback mode...")
+        # 这里可以添加一个简单的命令行界面作为后备
+        return
+        
+    try:
+        app = QApplication(sys.argv)
+        window = RepoSyncMainWindow()
+        window.show()
+        sys.exit(app.exec_())
+    except Exception as e:
+        print(f"Error starting GUI: {str(e)}")
+        import traceback
+        traceback.print_exc()
 
 if __name__ == '__main__':
     main() 

+ 2 - 6
main.py

@@ -6,11 +6,7 @@
 @License :   Copyright © 2017-2022 liuyuqi. All Rights Reserved.
 @Desc    :   
 '''
-from repo_sync import main, gui_main
-import sys
+from repo_sync import main
 
 if __name__=='__main__':
-    if len(sys.argv) > 1 and sys.argv[1] == 'gui':
-        gui_main()
-    else:
-        main()
+    main()

+ 0 - 15
repo_sync/__init__.py

@@ -21,18 +21,3 @@ def main(argv=None):
         logger.error('ERROR: Interrupted by user')
         sys.exit(1)
 
-# GUI入口
-def gui_main():
-    """GUI entry point of the program"""
-    try:
-        from .gui_main import main as gui_main_func
-        gui_main_func()
-    except ImportError as e:
-        print(f"GUI dependencies not installed: {e}")
-        print("Please install PyQt5 and pywin32 with: pip install PyQt5 pywin32")
-        sys.exit(1)
-    except Exception as e:
-        print(f"Error starting GUI: {str(e)}")
-        import traceback
-        traceback.print_exc()
-        sys.exit(1)

+ 1 - 1
repo_sync/options.py

@@ -23,7 +23,7 @@ def parser_args(overrideArguments=None):
     argparser.add_argument(
         'command',
         help='command: ',
-        choices=['create', 'clone', 'push', 'delete', 'pull', 'gui'],
+        choices=['create', 'clone', 'push', 'delete', 'pull'],
         nargs='?',
         default=''
     )