diff --git a/app.py b/app.py index b8122f3..84e52d4 100644 --- a/app.py +++ b/app.py @@ -11,7 +11,7 @@ from component.widget_filter.audio_filter_model import AudioFilterModel from component.widget_filter.audio_filter_controller import AudioFilterController from component.widget_card.widget_card import ParamData from component.widget_log.widget_log import Widget_Log -from persistence.data_store_manager_origin import DataStoreManager +from persistence.data_store_manager import DataStoreManager from persistence.data_store_origin import DataStore from param_struct_test.service_manager import ServiceManager from application.application_controller import ApplicationController @@ -97,7 +97,7 @@ class MainWindow(QWidget): if param_info.get('name') == selected_name: return True return False - # app.py + def update_channel_from_card(self): """根据选中的卡片更新通道数据""" try: @@ -105,80 +105,98 @@ class MainWindow(QWidget): selected_param_name, selected_project_name = self.widget_card.get_selected_param_name() logger.info(f"selected_param_name: {selected_param_name}, selected_project_name: {selected_project_name}") - # 2. 获取项目数据 - projects = self.data_manager.get_projects() - project_name = projects[0] - project_data = self.data_manager.get_project(project_name) - - if not project_data or 'params' not in project_data: - logger.error("Project data not found or invalid") + if not selected_param_name or not selected_project_name: + logger.warning("未选择参数或项目") return - - # 3. 查找匹配的参数数据 - param_data = None - for key, param_info in project_data['params'].items(): - if param_info.get('name') == selected_param_name: - param_data = param_info - break - - if not param_data or 'channels' not in param_data: - logger.error(f"Parameter data not found for name: {selected_param_name}") + + # 2. 获取参数数据 + param_data = self.data_manager.get_param_data(selected_project_name, selected_param_name) + + # 新增: 根据参数名称查找对应的参数键并更新current_param + # project_names = self.data_manager.get_projects() + # project_data = self.data_manager.get_project(project_names[0]) + # if project_data and 'params' in project_data: + # for param_key, param_info in project_data['params'].items(): + # if param_info.get('name') == selected_param_name: + # # 找到匹配的参数键,更新current_param + # self.data_manager.current_param = param_key + # logger.info(f"已更新当前参数键: {param_key}") + # break + + self.data_manager.current_param = param_data + if not param_data: + logger.error(f"未找到参数数据: {selected_param_name}") return - - # 4. 处理每个通道的数据 - for channel_id, channel_data in param_data['channels'].items(): + + # 3. 处理每个通道的数据 + for channel_id, channel_data in param_data.items(): try: - channel_id = int(channel_id) - 1 # JSON中通道从1开始,程序中从0开始 + channel_id = int(channel_id) if 0 <= channel_id < len(self.filter_controllers): controller = self.filter_controllers[channel_id] controller.update_from_card_data(channel_data) - # controller.update_ui() except Exception as e: - logger.error(f"Error processing channel {channel_id}: {str(e)}") + logger.error(f"处理通道 {channel_id} 时出错: {str(e)}") continue - logger.info("Successfully updated all channels from card data") + logger.info("成功从卡片数据更新所有通道") except Exception as e: - logger.error(f"Error updating channel from card: {str(e)}") + logger.error(f"从卡片更新通道时出错: {str(e)}") def load_default_project(self): """Load the first available project or create a default one if none exists""" try: + # 获取项目列表 projects = self.data_manager.get_projects() if not projects: - # Create default project if none exists - logger.info("Creating default project...") - self.data_manager.create_project("default", "Default project configuration") + # 如果没有项目,创建默认项目 + logger.info("创建默认项目...") + self.data_manager.create_project("default", "默认项目配置") projects = ["default"] - # Load the first project - project_name = projects[0] - project_data = self.data_manager.get_project(project_name) - - logger.info(f"Loading project: {project_name}") - - if project_data and 'params' in project_data: - self.widget_card.list_widget.clear() - - # 将字符串转换为 ParamData 对象 - param_objects = [ - ParamData(name=param_data['name']) - for param_data in project_data['params'].values() - ] - - card_data = CardData( - name=project_data['name'], - date=project_data['created_at'].split('T')[0], - description=project_data['description'], - params=param_objects # 使用 ParamData 对象列表 - ) + # 清空当前卡片列表 + self.widget_card.list_widget.clear() - self.widget_card.add_card_item(card_data) + # 遍历所有项目并加载 + for project_name in projects: + # 从数据管理器获取项目数据 + project_data = self.data_manager.get_project(project_name) + #to do:目前支持一个项目 + self.data_manager._store.current_project = project_name + if not project_data: + logger.warning(f"无法加载项目: {project_name}") + continue + + logger.info(f"加载项目: {project_name}") + + # 检查项目数据是否包含参数 + if 'params' in project_data: + # 创建参数对象列表 + param_objects = [] + for param_id, param_data in project_data['params'].items(): + if isinstance(param_data, dict) and 'name' in param_data: + param_objects.append(ParamData(name=param_data['name'])) + + # 创建卡片数据 + card_data = CardData( + name=project_data.get('name', project_name), + date=project_data.get('created_at', '').split('T')[0] if 'created_at' in project_data else '', + description=project_data.get('description', ''), + params=param_objects + ) + + # 添加卡片到界面 + self.widget_card.add_card_item(card_data) + logger.info(f"已添加项目卡片 '{project_data.get('name', project_name)}' 包含 {len(param_objects)} 个参数") + else: + logger.warning(f"项目 '{project_name}' 没有参数数据") except Exception as e: - logger.error(f"Error loading default project: {e}") + logger.error(f"加载默认项目时出错: {str(e)}") + import traceback + logger.error(traceback.format_exc()) def load_config(self): """加载通道配置文件""" @@ -219,9 +237,83 @@ class MainWindow(QWidget): print("setup_connections") self.widget_channel.channel_btn_clicked.connect(self.on_channel_btn_clicked) self.widget_card.parameterSelected.connect(self.on_widget_card_parameter_selected) - + # 连接编辑信号 + self.widget_card.itemEdited.connect(self.on_widget_card_item_edited) + # 连接参数添加信号 + self.widget_card.parameterAdded.connect(self.on_widget_card_parameter_added) + + # data_store_manager.current_param def on_widget_card_parameter_selected(self, param_name: str, project_name: str): logger.info(f"on_widget_card_parameter_selected: {param_name}, {project_name}") + + try: + # 获取参数数据 + param_data = self.data_manager.get_param_data(project_name, param_name) + + if not param_data: + logger.warning(f"未找到参数数据: {param_name}") + return + + # 更新所有通道的滤波器数据 + for channel_id, channel_data in param_data.items(): + try: + channel_id = int(channel_id) + if 0 <= channel_id < len(self.filter_controllers): + controller = self.filter_controllers[channel_id] + controller.update_from_card_data(channel_data) + except Exception as e: + logger.error(f"处理通道 {channel_id} 时出错: {str(e)}") + continue + + logger.info(f"成功从参数 {param_name} 更新所有通道") + except Exception as e: + logger.error(f"参数选择更新出错: {str(e)}") + import traceback + logger.error(traceback.format_exc()) + + def on_widget_card_item_edited(self, edit_type, old_value, new_value, project_name): + """处理卡片项目编辑事件""" + if edit_type == "parameter_name": + try: + # 查找项目文件名 + projects = self.data_manager.get_projects() + project_filename = None + + for proj_filename in projects: + project_data = self.data_manager.get_project(proj_filename) + if project_data and project_data.get('name') == project_name: + project_filename = proj_filename + + # 1. 更新JSON中的参数名 + if 'params' in project_data: + for param_id, param_info in project_data['params'].items(): + if param_info.get('name') == old_value: + # 更新参数名 + param_info['name'] = new_value + # 保存更新后的项目数据 + self.data_manager.update_project(proj_filename, project_data) + logger.info(f"已更新参数名: {old_value} -> {new_value}") + + # 2. 重命名参数文件 + params_dir = os.path.join("data", "projects", "params") + for file in os.listdir(params_dir): + # 查找与旧参数名匹配的文件 + if file.startswith(f"{project_name}_") and file.endswith('.csv'): + param_part = file[len(project_name)+1:-4] # 提取参数名部分 + if param_part == old_value: + old_path = os.path.join(params_dir, file) + new_path = os.path.join(params_dir, f"{project_name}_{new_value}.csv") + try: + os.rename(old_path, new_path) + logger.info(f"已重命名参数文件: {old_path} -> {new_path}") + except Exception as e: + logger.error(f"重命名参数文件失败: {str(e)}") + break + break + except Exception as e: + logger.error(f"处理参数编辑时出错: {str(e)}") + import traceback + logger.error(traceback.format_exc()) def set_default_filter_widget(self, channel_id: int): while self.widget_main.ui.verticalLayout_Filter.count(): @@ -242,6 +334,7 @@ class MainWindow(QWidget): # Add the selected channel's filter widget to the layout filter_widget = self.widget_filter_list[channel_id] self.widget_main.ui.verticalLayout_Filter.addWidget(filter_widget) + filter_widget.ui.groupBox_4.setTitle(f"Channel {channel_id+1}") filter_widget.show() def test_communication(self): @@ -352,6 +445,59 @@ class MainWindow(QWidget): return channel_data + def on_widget_card_parameter_added(self, param_name: str, project_name: str): + """处理添加新参数的事件""" + logger.info(f"添加新参数: {param_name}, 项目: {project_name}") + + try: + # 获取项目列表 + projects = self.data_manager.get_projects() + project_found = False + project_filename = None + + # 查找对应的项目文件名 + for proj_filename in projects: + project_data = self.data_manager.get_project(proj_filename) + if project_data and project_data.get('name') == project_name: + project_found = True + project_filename = proj_filename + + # 创建空的通道数据结构 + empty_channel_data = {} + for i in range(len(self.filter_controllers)): + empty_channel_data[i] = { + 'delay_data': 0.0, + 'vol_data': 0.0, + 'mix_left_data': 0.0, + 'mix_right_data': 0.0, + 'filters': [] + } + + # 保存新参数 - 使用项目文件名 + self.data_manager.save_param(project_filename, param_name, empty_channel_data, "") + + # 重命名参数文件,使用项目的name字段而不是文件名 + old_param_path = os.path.join("data", "projects", "params", f"{project_filename}_{param_name}.csv") + new_param_path = os.path.join("data", "projects", "params", f"{project_name}_{param_name}.csv") + + if os.path.exists(old_param_path): + try: + os.rename(old_param_path, new_param_path) + logger.info(f"已重命名参数文件: {old_param_path} -> {new_param_path}") + except Exception as e: + logger.error(f"重命名参数文件失败: {str(e)}") + + logger.info(f"已创建新参数: {param_name}, 文件名: {project_name}_{param_name}.csv") + break + + if not project_found: + logger.warning(f"未找到项目: {project_name}") + + except Exception as e: + logger.error(f"创建参数时出错: {str(e)}") + import traceback + logger.error(traceback.format_exc()) + if __name__ == '__main__': import sys from PySide6.QtWidgets import QApplication diff --git a/application/__pycache__/__init__.cpython-313.pyc b/application/__pycache__/__init__.cpython-313.pyc index 7d14cf3..cce8e1e 100644 Binary files a/application/__pycache__/__init__.cpython-313.pyc and b/application/__pycache__/__init__.cpython-313.pyc differ diff --git a/application/__pycache__/application_controller.cpython-313.pyc b/application/__pycache__/application_controller.cpython-313.pyc index 5a18b96..6b86a53 100644 Binary files a/application/__pycache__/application_controller.cpython-313.pyc and b/application/__pycache__/application_controller.cpython-313.pyc differ diff --git a/component/__pycache__/__init__.cpython-313.pyc b/component/__pycache__/__init__.cpython-313.pyc index 9df0975..e4bbba2 100644 Binary files a/component/__pycache__/__init__.cpython-313.pyc and b/component/__pycache__/__init__.cpython-313.pyc differ diff --git a/component/widget_card/__pycache__/__init__.cpython-313.pyc b/component/widget_card/__pycache__/__init__.cpython-313.pyc index 2fdf8bb..e25210c 100644 Binary files a/component/widget_card/__pycache__/__init__.cpython-313.pyc and b/component/widget_card/__pycache__/__init__.cpython-313.pyc differ diff --git a/component/widget_card/__pycache__/ui_widget_card.cpython-313.pyc b/component/widget_card/__pycache__/ui_widget_card.cpython-313.pyc index d702ce5..b7a290c 100644 Binary files a/component/widget_card/__pycache__/ui_widget_card.cpython-313.pyc and b/component/widget_card/__pycache__/ui_widget_card.cpython-313.pyc differ diff --git a/component/widget_card/__pycache__/widget_card.cpython-313.pyc b/component/widget_card/__pycache__/widget_card.cpython-313.pyc index e34ccf4..37edbc6 100644 Binary files a/component/widget_card/__pycache__/widget_card.cpython-313.pyc and b/component/widget_card/__pycache__/widget_card.cpython-313.pyc differ diff --git a/component/widget_card/widget_card.py b/component/widget_card/widget_card.py index 549c11d..58db273 100644 --- a/component/widget_card/widget_card.py +++ b/component/widget_card/widget_card.py @@ -34,6 +34,8 @@ class CardData: class Widget_Card(QWidget): parameterSelected = Signal(str, str) # Signal that emits (parameter_name, project_name) + itemEdited = Signal(str, str, str, str) # Signal that emits (edit_type, old_value, new_value, project_name) + parameterAdded = Signal(str, str) # Signal that emits (parameter_name, project_name) def __init__(self): super().__init__() @@ -44,6 +46,11 @@ class Widget_Card(QWidget): self.list_widget.itemDelegate().parameterSelected.connect( lambda param_name, project_name: self.parameterSelected.emit(param_name, project_name) ) + + # Connect the itemDelegate's itemEdited signal + self.list_widget.itemDelegate().itemEdited.connect( + lambda edit_type, old_value, new_value, project_name: self.itemEdited.emit(edit_type, old_value, new_value, project_name) + ) def setup_ui(self): self.setWindowTitle("卡片列表示例") @@ -280,6 +287,9 @@ class Widget_Card(QWidget): item_height = self.calculate_item_height(data) item.setSizeHint(QSize(380, item_height)) + # 发射参数添加信号 + self.parameterAdded.emit(new_param.name, data.name) + # 刷新显示 self.list_widget.viewport().update() @@ -320,8 +330,24 @@ class Widget_Card(QWidget): return None, None + def add_parameter(self, param_name: str): + """添加新参数到当前选中的项目""" + current_item = self.list_widget.currentItem() + if current_item: + card_data = current_item.data(Qt.ItemDataRole.UserRole) + card_data.params.append(ParamData(name=param_name)) + + # 更新UI + self.list_widget.viewport().update() + + # 发射参数添加信号 + self.parameterAdded.emit(param_name, card_data.name) + return True + return False + class CardItemDelegate(QStyledItemDelegate): parameterSelected = Signal(str, str) # Signal that emits (parameter_name, project_name) + itemEdited = Signal(str, str, str, str) # Signal that emits (edit_type, old_value, new_value, project_name) def __init__(self, parent=None): super().__init__(parent) @@ -343,12 +369,13 @@ class CardItemDelegate(QStyledItemDelegate): desc_rect = self.getDescriptionRect(option.rect) if event.type() == QEvent.MouseButtonDblClick: - if title_rect.contains(pos): - self.editing_field = 'name' - self.edit_rect = title_rect - self.parent().edit(index) - return True - elif desc_rect.contains(pos): + # 移除对标题区域双击事件的处理 + # if title_rect.contains(pos): + # self.editing_field = 'name' + # self.edit_rect = title_rect + # self.parent().edit(index) + # return True + if desc_rect.contains(pos): self.editing_field = 'description' self.edit_rect = desc_rect self.parent().edit(index) @@ -444,14 +471,29 @@ class CardItemDelegate(QStyledItemDelegate): return data = index.data(Qt.ItemDataRole.UserRole) + old_value = "" + edit_type = "" + if self.editing_field == 'name': + old_value = data.name data.name = editor.text() + edit_type = "project_name" elif self.editing_field == 'description': + old_value = data.description data.description = editor.text() + edit_type = "project_description" elif self.editing_param_index >= 0: + old_value = data.params[self.editing_param_index].name data.params[self.editing_param_index].name = editor.text() + edit_type = "parameter_name" model.setData(index, data, Qt.ItemDataRole.UserRole) + + # 发射编辑完成信号 + if old_value != editor.text(): + print(f"发射编辑完成信号: {edit_type}, {old_value}, {editor.text()}, {data.name}") + self.itemEdited.emit(edit_type, old_value, editor.text(), data.name) + self.editing_field = None self.editing_param_index = -1 diff --git a/component/widget_channel/__pycache__/__init__.cpython-313.pyc b/component/widget_channel/__pycache__/__init__.cpython-313.pyc index 5afb715..0197430 100644 Binary files a/component/widget_channel/__pycache__/__init__.cpython-313.pyc and b/component/widget_channel/__pycache__/__init__.cpython-313.pyc differ diff --git a/component/widget_channel/__pycache__/ui_widget_channel.cpython-313.pyc b/component/widget_channel/__pycache__/ui_widget_channel.cpython-313.pyc index 6e08042..6b6b219 100644 Binary files a/component/widget_channel/__pycache__/ui_widget_channel.cpython-313.pyc and b/component/widget_channel/__pycache__/ui_widget_channel.cpython-313.pyc differ diff --git a/component/widget_channel/__pycache__/widget_channel.cpython-313.pyc b/component/widget_channel/__pycache__/widget_channel.cpython-313.pyc index 54418c6..2378d36 100644 Binary files a/component/widget_channel/__pycache__/widget_channel.cpython-313.pyc and b/component/widget_channel/__pycache__/widget_channel.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/Ui_widget.cpython-313.pyc b/component/widget_filter/__pycache__/Ui_widget.cpython-313.pyc index 176f55b..f1cfb25 100644 Binary files a/component/widget_filter/__pycache__/Ui_widget.cpython-313.pyc and b/component/widget_filter/__pycache__/Ui_widget.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/Ui_widget_origin.cpython-313.pyc b/component/widget_filter/__pycache__/Ui_widget_origin.cpython-313.pyc index 9d5cf9a..9e7e582 100644 Binary files a/component/widget_filter/__pycache__/Ui_widget_origin.cpython-313.pyc and b/component/widget_filter/__pycache__/Ui_widget_origin.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/__init__.cpython-313.pyc b/component/widget_filter/__pycache__/__init__.cpython-313.pyc index a3637de..e4f8884 100644 Binary files a/component/widget_filter/__pycache__/__init__.cpython-313.pyc and b/component/widget_filter/__pycache__/__init__.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/audio_filter_componet.cpython-313.pyc b/component/widget_filter/__pycache__/audio_filter_componet.cpython-313.pyc index ac282f6..afdb721 100644 Binary files a/component/widget_filter/__pycache__/audio_filter_componet.cpython-313.pyc and b/component/widget_filter/__pycache__/audio_filter_componet.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc b/component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc index eb7ebd1..2a4cc32 100644 Binary files a/component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc and b/component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/audio_filter_model.cpython-313.pyc b/component/widget_filter/__pycache__/audio_filter_model.cpython-313.pyc index eec0d06..5414af2 100644 Binary files a/component/widget_filter/__pycache__/audio_filter_model.cpython-313.pyc and b/component/widget_filter/__pycache__/audio_filter_model.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/checkbox_header.cpython-313.pyc b/component/widget_filter/__pycache__/checkbox_header.cpython-313.pyc index b09ea10..d176b66 100644 Binary files a/component/widget_filter/__pycache__/checkbox_header.cpython-313.pyc and b/component/widget_filter/__pycache__/checkbox_header.cpython-313.pyc differ diff --git a/component/widget_filter/__pycache__/resources.cpython-313.pyc b/component/widget_filter/__pycache__/resources.cpython-313.pyc index 835b1ae..760073e 100644 Binary files a/component/widget_filter/__pycache__/resources.cpython-313.pyc and b/component/widget_filter/__pycache__/resources.cpython-313.pyc differ diff --git a/component/widget_filter/audio_filter_componet.py b/component/widget_filter/audio_filter_componet.py index a1e208e..6789665 100644 --- a/component/widget_filter/audio_filter_componet.py +++ b/component/widget_filter/audio_filter_componet.py @@ -706,7 +706,7 @@ class AudioFilterWidget(QWidget): self.current_filter_index = row filter_name_item = self.ui.tableWidget.item(row, 1) if filter_name_item: - self.ui.groupBox_4.setTitle(filter_name_item.text()) + # self.ui.groupBox_4.setTitle(filter_name_item.text()) # 获取当前滤波器类型和slope值 filter_type_combo = self.ui.tableWidget.cellWidget(row, 2) diff --git a/component/widget_filter/audio_filter_controller.py b/component/widget_filter/audio_filter_controller.py index 472d3e7..7994708 100644 --- a/component/widget_filter/audio_filter_controller.py +++ b/component/widget_filter/audio_filter_controller.py @@ -17,6 +17,7 @@ from component.widget_filter.audio_filter_model import AudioFilterModel from component.widget_filter.audio_filter_componet import AudioFilterWidget from component.widget_filter.audio_filter_model import FilterParams, FilterType, ChannelParams from param_struct_test.params_service import Response, CMD +from persistence.data_store_manager import DataStoreManager # from audio_filter_model import AudioFilterModel # from audio_filter_componet import AudioFilterWidget @@ -90,7 +91,6 @@ class AudioFilterController(QObject): try: self.state = AudioControllerState.UPDATING - # 1. Update channel parameters channel_params = ChannelParams( delay=card_data.get('delay_data', 0.0), volume=card_data.get('vol_data', 0.0), @@ -99,22 +99,47 @@ class AudioFilterController(QObject): ) self.model.set_channel_params(channel_params) - # 2. Clear existing filters and add new ones self.model.filters.clear() - # Convert and add new filters for filter_data in card_data.get('filters', []): - filter_type = FilterType[filter_data['type']] + # 检查滤波器参数是否都为0 + all_zeros = all([ + filter_data.get('frequency', 0.0) == 0.0 and filter_data.get('fc', 0.0) == 0.0, + filter_data.get('q', 0.0) == 0.0, + filter_data.get('gain', 0.0) == 0.0, + filter_data.get('slope', 0.0) == 0.0 + ]) + + # 如果所有参数都为0,跳过这个滤波器 + if all_zeros: + continue + + # 正确处理整数类型的 filterType + filter_type = None + if 'type' in filter_data and filter_data['type'] is not None: + # 如果是字符串名称 + if isinstance(filter_data['type'], str): + filter_type = FilterType[filter_data['type']] + # 如果是整数值 + elif isinstance(filter_data['type'], int): + filter_type = FilterType(filter_data['type']) + elif 'filterType' in filter_data and filter_data['filterType'] is not None: + # 如果是字符串名称 + if isinstance(filter_data['filterType'], str): + filter_type = FilterType[filter_data['filterType']] + # 如果是整数值 + elif isinstance(filter_data['filterType'], int): + filter_type = FilterType(filter_data['filterType']) + filter_params = FilterParams( filter_type=filter_type, - frequency=filter_data['frequency'], - q_value=filter_data['q'], - gain=filter_data['gain'], - slope=filter_data['slope'] + frequency=filter_data.get('frequency', 0.0) or filter_data.get('fc', 0.0), + q_value=filter_data.get('q', 0.0), + gain=filter_data.get('gain', 0.0), + slope=filter_data.get('slope', 0.0) ) self.model.filters.append(filter_params) - # 3. Update UI if self.widget: self.widget.updateUI() @@ -442,9 +467,56 @@ class AudioFilterController(QObject): self.model.update_filter(index, filter_params) print(f"_on_widget_filter_changed model:{self.model.filters}") # self.filter_changed.emit(index, param_name, value) + + # 同步更新CSV文件中的数据 + self._sync_to_csv() except Exception as e: self.error_occurred.emit(f"Error updating filter: {str(e)}") + def _sync_to_csv(self): + """同步当前滤波器数据到CSV文件""" + try: + # 获取当前项目和参数名称 + data_store_manager = DataStoreManager.get_instance() + current_project = data_store_manager.current_project + current_param = data_store_manager.current_param + + + # 如果仍然没有当前项目或参数,则不进行同步 + if not current_project or not current_param: + return + + # 准备通道数据 + channel_data = {} + model_data = self.model.get_all_data() + channel_id = model_data['channel_id'] + + # 构建通道数据结构 + channel_data[channel_id] = { + 'mix_left_data': model_data['channel_params']['mix_left'], + 'mix_right_data': model_data['channel_params']['mix_right'], + 'delay_data': model_data['channel_params']['delay'], + 'vol_data': model_data['channel_params']['volume'], + 'filters': [] + } + + # 添加滤波器数据 + for filter_param in model_data['filters']: + filter_data = { + 'fc': filter_param['frequency'], + 'q': filter_param['q_value'], + 'gain': filter_param['gain'], + 'slope': filter_param['slope'], + 'filterType': filter_param['filter_type'].value + } + channel_data[channel_id]['filters'].append(filter_data) + + # 保存到CSV文件 + data_store_manager.save_param(current_project, current_param, channel_data) + + except Exception as e: + self.error_occurred.emit(f"同步到CSV文件时发生错误: {str(e)}") + # def _on_widget_param_changed(self, param_name: str, value: float): # """处理widget通道参数变化""" # try: diff --git a/component/widget_log/__pycache__/log_handler.cpython-313.pyc b/component/widget_log/__pycache__/log_handler.cpython-313.pyc index 4242896..f87d8e4 100644 Binary files a/component/widget_log/__pycache__/log_handler.cpython-313.pyc and b/component/widget_log/__pycache__/log_handler.cpython-313.pyc differ diff --git a/component/widget_log/__pycache__/ui_widget_log.cpython-313.pyc b/component/widget_log/__pycache__/ui_widget_log.cpython-313.pyc index 2bde4ef..259fa81 100644 Binary files a/component/widget_log/__pycache__/ui_widget_log.cpython-313.pyc and b/component/widget_log/__pycache__/ui_widget_log.cpython-313.pyc differ diff --git a/component/widget_log/__pycache__/widget_log.cpython-313.pyc b/component/widget_log/__pycache__/widget_log.cpython-313.pyc index 7a43192..9bff257 100644 Binary files a/component/widget_log/__pycache__/widget_log.cpython-313.pyc and b/component/widget_log/__pycache__/widget_log.cpython-313.pyc differ diff --git a/component/widget_main/__pycache__/Ui_widget.cpython-313.pyc b/component/widget_main/__pycache__/Ui_widget.cpython-313.pyc index 61e8ef3..7fe80db 100644 Binary files a/component/widget_main/__pycache__/Ui_widget.cpython-313.pyc and b/component/widget_main/__pycache__/Ui_widget.cpython-313.pyc differ diff --git a/component/widget_main/__pycache__/__init__.cpython-313.pyc b/component/widget_main/__pycache__/__init__.cpython-313.pyc index 65cf329..806555a 100644 Binary files a/component/widget_main/__pycache__/__init__.cpython-313.pyc and b/component/widget_main/__pycache__/__init__.cpython-313.pyc differ diff --git a/component/widget_main/__pycache__/widget_main.cpython-313.pyc b/component/widget_main/__pycache__/widget_main.cpython-313.pyc index 067eb7c..75f30b1 100644 Binary files a/component/widget_main/__pycache__/widget_main.cpython-313.pyc and b/component/widget_main/__pycache__/widget_main.cpython-313.pyc differ diff --git a/data/projects/default.json b/data/projects/default.json deleted file mode 100644 index 06601bc..0000000 --- a/data/projects/default.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "name": "test_default", - "created_at": "2025-02-25T10:30:00", - "last_modified": "2025-02-25T11:45:00", - "description": "test_xxxxx", - "params": { - "test_1": { - "name": "test_1-name", - "created_at": "2024-03-21T10:30:00", - "description": "test-description", - "channels": { - "1": { - "delay_data": 0.02, - "vol_data": -2.5, - "mix_left_data": 0.7, - "mix_right_data": 0.3, - "filters": [ - { - "name": "Filters_1", - "type": "HIGHPASS", - "frequency": 20.0, - "q": 0.707, - "gain": 0.0, - "slope": 24, - "enabled": true - }, - { - "name": "Filters_2", - "type": "PEAK", - "frequency": 250.0, - "q": 2.5, - "gain": -3.0, - "slope": 0, - "enabled": true - }, - { - "name": "Filters_3", - "type": "LOWSHELF", - "frequency": 100.0, - "q": 1.0, - "gain": 3.0, - "slope": 12, - "enabled": true - } - ] - }, - "2": { - "delay_data": 0.02, - "vol_data": -2.5, - "mix_left_data": 0.3, - "mix_right_data": 0.7, - "filters": [ - { - "name": "Filters_1", - "type": "HIGHPASS", - "frequency": 20.0, - "q": 0.707, - "gain": 0.0, - "slope": 24, - "enabled": true - }, - { - "name": "Filters_2", - "type": "PEAK", - "frequency": 2000.0, - "q": 1.4, - "gain": -2.0, - "slope": 0, - "enabled": true - }, - { - "name": "Filters_3", - "type": "HIGHSHELF", - "frequency": 8000.0, - "q": 1.0, - "gain": 1.5, - "slope": 12, - "enabled": true - } - ] - } - } - }, - "test_2": { - "name": "test_2-name", - "created_at": "2024-03-21T10:30:00", - "description": "test_2-description", - "channels": { - "1": { - "delay_data": 0.0, - "vol_data": 0.0, - "mix_left_data": 1.0, - "mix_right_data": 0.0, - "filters": [ - { - "name": "Filters_1", - "type": "HIGHPASS", - "frequency": 45.0, - "q": 0.707, - "gain": 0.0, - "slope": 18, - "enabled": true - }, - { - "name": "Filters_2", - "type": "PEAK", - "frequency": 400.0, - "q": 2.0, - "gain": -2.0, - "slope": 0, - "enabled": true - } - ] - } - } - } - } -} \ No newline at end of file diff --git a/data/projects/params/test_project_param2.csv b/data/projects/params/aaa_abc.csv similarity index 95% rename from data/projects/params/test_project_param2.csv rename to data/projects/params/aaa_abc.csv index 4ae6084..8ea9c7f 100644 --- a/data/projects/params/test_project_param2.csv +++ b/data/projects/params/aaa_abc.csv @@ -2,11 +2,11 @@ parameter,value dataset.audio_mode,0 dataset.send_action,0 dataset.tuning_parameters.mix_parameters[0].ch_n,0 -dataset.tuning_parameters.mix_parameters[0].mix_left_data,0.7 -dataset.tuning_parameters.mix_parameters[0].mix_right_data,0.3 +dataset.tuning_parameters.mix_parameters[0].mix_left_data,1.0 +dataset.tuning_parameters.mix_parameters[0].mix_right_data,1.0 dataset.tuning_parameters.mix_parameters[1].ch_n,1 -dataset.tuning_parameters.mix_parameters[1].mix_left_data,0.5 -dataset.tuning_parameters.mix_parameters[1].mix_right_data,0.5 +dataset.tuning_parameters.mix_parameters[1].mix_left_data,0.0 +dataset.tuning_parameters.mix_parameters[1].mix_right_data,0.0 dataset.tuning_parameters.mix_parameters[2].ch_n,2 dataset.tuning_parameters.mix_parameters[2].mix_left_data,0.0 dataset.tuning_parameters.mix_parameters[2].mix_right_data,0.0 @@ -19,16 +19,16 @@ dataset.tuning_parameters.mix_parameters[4].mix_right_data,0.0 dataset.tuning_parameters.mix_parameters[5].ch_n,5 dataset.tuning_parameters.mix_parameters[5].mix_left_data,0.0 dataset.tuning_parameters.mix_parameters[5].mix_right_data,0.0 -dataset.tuning_parameters.eq_parameters[0].fc,100.0 -dataset.tuning_parameters.eq_parameters[0].q,0.7 -dataset.tuning_parameters.eq_parameters[0].gain,2.0 -dataset.tuning_parameters.eq_parameters[0].slope,12 -dataset.tuning_parameters.eq_parameters[0].filterType,1 -dataset.tuning_parameters.eq_parameters[1].fc,200.0 -dataset.tuning_parameters.eq_parameters[1].q,1.0 -dataset.tuning_parameters.eq_parameters[1].gain,-3.0 -dataset.tuning_parameters.eq_parameters[1].slope,6 -dataset.tuning_parameters.eq_parameters[1].filterType,2 +dataset.tuning_parameters.eq_parameters[0].fc,10.0 +dataset.tuning_parameters.eq_parameters[0].q,10.0 +dataset.tuning_parameters.eq_parameters[0].gain,10.0 +dataset.tuning_parameters.eq_parameters[0].slope,10.0 +dataset.tuning_parameters.eq_parameters[0].filterType,0 +dataset.tuning_parameters.eq_parameters[1].fc,0.0 +dataset.tuning_parameters.eq_parameters[1].q,0.0 +dataset.tuning_parameters.eq_parameters[1].gain,0.0 +dataset.tuning_parameters.eq_parameters[1].slope,0 +dataset.tuning_parameters.eq_parameters[1].filterType,0 dataset.tuning_parameters.eq_parameters[2].fc,0.0 dataset.tuning_parameters.eq_parameters[2].q,0.0 dataset.tuning_parameters.eq_parameters[2].gain,0.0 @@ -119,11 +119,11 @@ dataset.tuning_parameters.eq_parameters[19].q,0.0 dataset.tuning_parameters.eq_parameters[19].gain,0.0 dataset.tuning_parameters.eq_parameters[19].slope,0 dataset.tuning_parameters.eq_parameters[19].filterType,0 -dataset.tuning_parameters.eq_parameters[20].fc,1000.0 -dataset.tuning_parameters.eq_parameters[20].q,1.4 -dataset.tuning_parameters.eq_parameters[20].gain,-3.0 -dataset.tuning_parameters.eq_parameters[20].slope,6 -dataset.tuning_parameters.eq_parameters[20].filterType,2 +dataset.tuning_parameters.eq_parameters[20].fc,0.0 +dataset.tuning_parameters.eq_parameters[20].q,0.0 +dataset.tuning_parameters.eq_parameters[20].gain,0.0 +dataset.tuning_parameters.eq_parameters[20].slope,0 +dataset.tuning_parameters.eq_parameters[20].filterType,0 dataset.tuning_parameters.eq_parameters[21].fc,0.0 dataset.tuning_parameters.eq_parameters[21].q,0.0 dataset.tuning_parameters.eq_parameters[21].gain,0.0 @@ -430,7 +430,6 @@ dataset.tuning_parameters.eq_parameters[81].gain,0.0 dataset.tuning_parameters.eq_parameters[81].slope,0 dataset.tuning_parameters.eq_parameters[81].filterType,0 dataset.tuning_parameters.eq_parameters[82].fc,0.0 -dataset.tuning_parameters.eq_parameters[82].fc,0.0 dataset.tuning_parameters.eq_parameters[82].q,0.0 dataset.tuning_parameters.eq_parameters[82].gain,0.0 dataset.tuning_parameters.eq_parameters[82].slope,0 @@ -621,9 +620,9 @@ dataset.tuning_parameters.eq_parameters[119].gain,0.0 dataset.tuning_parameters.eq_parameters[119].slope,0 dataset.tuning_parameters.eq_parameters[119].filterType,0 dataset.tuning_parameters.delay_parameters[0].ch_n,0 -dataset.tuning_parameters.delay_parameters[0].delay_data,0.05 +dataset.tuning_parameters.delay_parameters[0].delay_data,10.0 dataset.tuning_parameters.delay_parameters[1].ch_n,1 -dataset.tuning_parameters.delay_parameters[1].delay_data,0.1 +dataset.tuning_parameters.delay_parameters[1].delay_data,0.0 dataset.tuning_parameters.delay_parameters[2].ch_n,2 dataset.tuning_parameters.delay_parameters[2].delay_data,0.0 dataset.tuning_parameters.delay_parameters[3].ch_n,3 @@ -633,9 +632,9 @@ dataset.tuning_parameters.delay_parameters[4].delay_data,0.0 dataset.tuning_parameters.delay_parameters[5].ch_n,5 dataset.tuning_parameters.delay_parameters[5].delay_data,0.0 dataset.tuning_parameters.volume_parameters[0].ch_n,0 -dataset.tuning_parameters.volume_parameters[0].vol_data,-3.0 +dataset.tuning_parameters.volume_parameters[0].vol_data,10.0 dataset.tuning_parameters.volume_parameters[1].ch_n,1 -dataset.tuning_parameters.volume_parameters[1].vol_data,-6.0 +dataset.tuning_parameters.volume_parameters[1].vol_data,0.0 dataset.tuning_parameters.volume_parameters[2].ch_n,2 dataset.tuning_parameters.volume_parameters[2].vol_data,0.0 dataset.tuning_parameters.volume_parameters[3].ch_n,3 @@ -643,4 +642,4 @@ dataset.tuning_parameters.volume_parameters[3].vol_data,0.0 dataset.tuning_parameters.volume_parameters[4].ch_n,4 dataset.tuning_parameters.volume_parameters[4].vol_data,0.0 dataset.tuning_parameters.volume_parameters[5].ch_n,5 -dataset.tuning_parameters.volume_parameters[5].vol_data,0.0 \ No newline at end of file +dataset.tuning_parameters.volume_parameters[5].vol_data,0.0 diff --git a/data/projects/params/test_project_param1.csv b/data/projects/params/aaa_abcd.csv similarity index 100% rename from data/projects/params/test_project_param1.csv rename to data/projects/params/aaa_abcd.csv diff --git a/data/projects/test_project.json b/data/projects/test_project.json index 39ebfb8..59a8357 100644 --- a/data/projects/test_project.json +++ b/data/projects/test_project.json @@ -1,20 +1,20 @@ { - "name": "test_project", - "created_at": "2025-02-25T10:30:00", - "last_modified": "2025-02-25T14:45:00", - "description": "这是一个测试项目", - "params": { - "param1": { - "name": "param1", - "created_at": "2025-02-25T11:00:00", - "description": "这是第一个参数配置", - "channels": {} - }, - "param2": { - "name": "param2", - "created_at": "2025-02-25T13:30:00", - "description": "这是第二个参数配置", - "channels": {} - } + "name": "aaa", + "created_at": "2025-02-25T10:30:00", + "last_modified": "2025-02-25T23:49:56.152782", + "description": "123", + "params": { + "param1": { + "name": "abc", + "created_at": "2025-02-25T11:00:00", + "description": "这是第一个参数配置", + "channels": {} + }, + "param2": { + "name": "abcd", + "created_at": "2025-02-25T13:30:00", + "description": "这是第二个参数配置", + "channels": {} } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/persistence/__pycache__/data_store.cpython-313.pyc b/persistence/__pycache__/data_store.cpython-313.pyc index dc8fcd1..3962612 100644 Binary files a/persistence/__pycache__/data_store.cpython-313.pyc and b/persistence/__pycache__/data_store.cpython-313.pyc differ diff --git a/persistence/__pycache__/data_store_manager.cpython-313.pyc b/persistence/__pycache__/data_store_manager.cpython-313.pyc index c33f3fd..e9eeb01 100644 Binary files a/persistence/__pycache__/data_store_manager.cpython-313.pyc and b/persistence/__pycache__/data_store_manager.cpython-313.pyc differ diff --git a/persistence/data_store.py b/persistence/data_store.py index a489dae..bcfb0cf 100644 --- a/persistence/data_store.py +++ b/persistence/data_store.py @@ -223,7 +223,10 @@ class DataStore: with open(file_path, 'r', encoding='utf-8') as f: data = json.load(f) - return ProjectData(**data) + project_data = ProjectData(**data) + + + return project_data except Exception as e: logger.error(f"加载项目失败: {e}") return None @@ -253,10 +256,12 @@ class DataStore: channel_data = {} # 处理混音参数 + # to do:后续处理这个6 for i in range(6): # 假设最多6个通道 ch_key = f'dataset.tuning_parameters.mix_parameters[{i}].ch_n' if ch_key in param_data: - channel_id = int(param_data[ch_key]) + # 将字符串先转为浮点数,再转为整数,避免小数点导致的转换错误 + channel_id = int(float(param_data[ch_key])) if channel_id not in channel_data: channel_data[channel_id] = {'filters': []} @@ -274,7 +279,8 @@ class DataStore: for i in range(6): ch_key = f'dataset.tuning_parameters.delay_parameters[{i}].ch_n' if ch_key in param_data: - channel_id = int(param_data[ch_key]) + # 同样先转为浮点数再转为整数 + channel_id = int(float(param_data[ch_key])) if channel_id not in channel_data: channel_data[channel_id] = {'filters': []} @@ -286,7 +292,8 @@ class DataStore: for i in range(6): ch_key = f'dataset.tuning_parameters.volume_parameters[{i}].ch_n' if ch_key in param_data: - channel_id = int(param_data[ch_key]) + # 同样先转为浮点数再转为整数 + channel_id = int(float(param_data[ch_key])) if channel_id not in channel_data: channel_data[channel_id] = {'filters': []} @@ -323,11 +330,13 @@ class DataStore: slope_key = f'dataset.tuning_parameters.eq_parameters[{i}].slope' if slope_key in param_data: - filter_data['slope'] = int(param_data[slope_key]) + # 先转为浮点数再转为整数 + filter_data['slope'] = int(float(param_data[slope_key])) filter_type_key = f'dataset.tuning_parameters.eq_parameters[{i}].filterType' if filter_type_key in param_data: - filter_data['filterType'] = int(param_data[filter_type_key]) + # 先转为浮点数再转为整数 + filter_data['filterType'] = int(float(param_data[filter_type_key])) return channel_data diff --git a/persistence/data_store_manager.py b/persistence/data_store_manager.py index d863d12..5084f22 100644 --- a/persistence/data_store_manager.py +++ b/persistence/data_store_manager.py @@ -109,6 +109,39 @@ class DataStoreManager: except Exception as e: return False + def update_project(self, project_name: str, project_data: Dict) -> bool: + """更新项目数据""" + try: + # 将字典转换为ProjectData对象 + from persistence.models import ProjectData + from dataclasses import asdict + + # 如果传入的是字典,需要转换为ProjectData对象 + if isinstance(project_data, dict): + # 确保params是字典而不是列表 + if 'params' in project_data and not isinstance(project_data['params'], dict): + project_data['params'] = {} + + # 创建ProjectData对象 + from persistence.models import ProjectData + project_data_obj = ProjectData(**project_data) + else: + project_data_obj = project_data + + # 更新最后修改时间 + from datetime import datetime + project_data_obj.last_modified = datetime.now().isoformat() + + # 保存项目元数据 + self._store._save_project_metadata(project_name, project_data_obj) + return True + except Exception as e: + from component.widget_log.log_handler import logger + logger.error(f"更新项目失败: {e}") + import traceback + logger.error(traceback.format_exc()) + return False + @classmethod def get_instance(cls) -> 'DataStoreManager': """获取 DataStoreManager 实例"""