[feature] 新增filter model中get/set接口

This commit is contained in:
Sam 2025-02-20 09:58:01 +08:00
parent aede544740
commit 6aed85c3c9
3 changed files with 204 additions and 72 deletions

View File

@ -10,6 +10,7 @@ from Ui_widget import Ui_Widget
# from component.widget_filter.checkbox_header import SCheckBoxHeaderView # from component.widget_filter.checkbox_header import SCheckBoxHeaderView
from audio_filter_model import AudioFilterModel
from checkbox_header import SCheckBoxHeaderView from checkbox_header import SCheckBoxHeaderView
# from component.widget_filter.checkbox_header import SCheckBoxHeaderView # from component.widget_filter.checkbox_header import SCheckBoxHeaderView
@ -371,16 +372,16 @@ class AudioFilterWidget(QWidget):
# 参数输入框变化 # 参数输入框变化
self.ui.lineEdit_11.textChanged.connect( self.ui.lineEdit_11.textChanged.connect(
lambda v: self._on_param_changed('delay_data1', v) lambda v: self._on_param_changed('delay', v)
) )
self.ui.lineEdit_10.textChanged.connect( self.ui.lineEdit_10.textChanged.connect(
lambda v: self._on_param_changed('ENC_volume_data1', v) lambda v: self._on_param_changed('volume', v)
) )
self.ui.lineEdit_13.textChanged.connect( self.ui.lineEdit_13.textChanged.connect(
lambda v: self._on_param_changed('ENT_mx_right_data', v) lambda v: self._on_param_changed('mix_right', v)
) )
self.ui.lineEdit_12.textChanged.connect( self.ui.lineEdit_12.textChanged.connect(
lambda v: self._on_param_changed('ENT_mix_left_data', v) lambda v: self._on_param_changed('mix_left', v)
) )
# 按钮点击 # 按钮点击
@ -409,8 +410,8 @@ class AudioFilterWidget(QWidget):
"""设置参数数据""" """设置参数数据"""
if 'delay_data1' in params: if 'delay_data1' in params:
self.ui.lineEdit_11.setText(str(params['delay_data1'])) self.ui.lineEdit_11.setText(str(params['delay_data1']))
if 'ENT_volume_data1' in params: if 'ENC_volume_data1' in params:
self.ui.lineEdit_10.setText(str(params['ENT_volume_data1'])) self.ui.lineEdit_10.setText(str(params['ENC_volume_data1']))
if 'ENT_mx_right_data' in params: if 'ENT_mx_right_data' in params:
self.ui.lineEdit_13.setText(str(params['ENT_mx_right_data'])) self.ui.lineEdit_13.setText(str(params['ENT_mx_right_data']))
if 'ENT_mix_left_data' in params: if 'ENT_mix_left_data' in params:
@ -431,7 +432,7 @@ class AudioFilterWidget(QWidget):
# 私有方法 # 私有方法
def _on_slider_changed(self, param: str, value: float): def _on_slider_changed(self, param: str, value: float):
"""处理滑块值变化""" """处理滑块值变化"""
if self.current_filter_index >= 0: if self.current_filter_index >= 0 and hasattr(self, 'model'):
# 更新表格中的值 # 更新表格中的值
column = {'freq': 3, 'q': 4, 'gain': 5, 'slope': 6}.get(param) column = {'freq': 3, 'q': 4, 'gain': 5, 'slope': 6}.get(param)
if column is not None: if column is not None:
@ -442,14 +443,37 @@ class AudioFilterWidget(QWidget):
column, column,
item item
) )
# 发送信号
self.filter_changed.emit(self.current_filter_index, param, value) # 更新model中的滤波器参数
filter_params = self.model.filters[self.current_filter_index]
if param == 'freq':
filter_params.frequency = value
elif param == 'q':
filter_params.q_value = value
elif param == 'gain':
filter_params.gain = value
elif param == 'slope':
filter_params.slope = value
self.model.update_filter(self.current_filter_index, filter_params)
def _on_param_changed(self, param: str, value: str): def _on_param_changed(self, param: str, value: str):
"""处理参数值变化""" """处理参数值变化"""
if hasattr(self, 'model'):
try: try:
float_value = float(value) float_value = float(value)
self.param_changed.emit(param, float_value) # 更新model中的通道参数
channel_params = self.model.channel_params
if param == 'delay':
channel_params.delay = float_value
elif param == 'volume':
channel_params.volume = float_value
elif param == 'mix_right':
channel_params.mix_right = float_value
elif param == 'mix_left':
channel_params.mix_left = float_value
self.model.set_channel_params(channel_params)
except ValueError: except ValueError:
pass pass
@ -518,10 +542,11 @@ class AudioFilterWidget(QWidget):
def _on_filter_type_changed(self, row: int, filter_type: str): def _on_filter_type_changed(self, row: int, filter_type: str):
"""处理滤波器类型变化""" """处理滤波器类型变化"""
# 更新表格中的滤波器名称 if hasattr(self, 'model'):
# name_item = QTableWidgetItem(filter_type) # 更新model中的滤波器类型
# name_item.setTextAlignment(Qt.AlignCenter) filter_params = self.model.filters[row]
# self.ui.tableWidget.setItem(row, 1, name_item) filter_params.filter_type = FilterType[filter_type]
self.model.update_filter(row, filter_params)
# 发送信号通知类型变化 # 发送信号通知类型变化
self.filter_added.emit(filter_type) self.filter_added.emit(filter_type)
@ -591,6 +616,12 @@ class AudioFilterWidget(QWidget):
def _on_checkbox_clicked(self, row: int, checked: bool): def _on_checkbox_clicked(self, row: int, checked: bool):
"""处理单个复选框点击事件""" """处理单个复选框点击事件"""
if hasattr(self, 'model'):
# 更新model中的滤波器启用状态
filter_params = self.model.filters[row]
filter_params.enabled = checked
self.model.update_filter(row, filter_params)
self.filter_enabled_changed.emit(row, checked) self.filter_enabled_changed.emit(row, checked)
# 更新表头复选框状态 # 更新表头复选框状态
@ -674,6 +705,57 @@ class AudioFilterWidget(QWidget):
self.ui.verticalSlider_3.setValue(int(data.get('gain', 0))) self.ui.verticalSlider_3.setValue(int(data.get('gain', 0)))
self.ui.verticalSlider_4.setValue(int(data.get('slope', 0))) self.ui.verticalSlider_4.setValue(int(data.get('slope', 0)))
def setModel(self, model: AudioFilterModel):
"""设置数据模型并建立连接"""
self.model = model
# 连接模型信号到视图更新方法
self.model.dataChanged.connect(self._updateFromModel)
self.model.filterAdded.connect(self._handleFilterAdded)
self.model.filterRemoved.connect(self._handleFilterRemoved)
self.model.filterUpdated.connect(self._handleFilterUpdated)
self.model.channelParamsChanged.connect(self._handleChannelParamsChanged)
# 设置初始数据
self.set_channel_id(model.channel_id)
self.set_channel_name(model.channel_name)
self._updateFromModel()
def _updateFromModel(self):
"""从模型更新整个UI"""
if not hasattr(self, 'model'):
return
# 更新UI参数
self.set_all_params(self.model.to_widget_params())
def _handleFilterAdded(self, index: int):
"""处理滤波器添加事件"""
self._updateFromModel()
def _handleFilterRemoved(self, index: int):
"""处理滤波器删除事件"""
self._updateFromModel()
def _handleFilterUpdated(self, index: int):
"""处理滤波器更新事件"""
if index == self.current_filter_index:
filter_params = self.model.filters[index]
self._update_sliders({
'freq': filter_params.frequency,
'q': filter_params.q_value,
'gain': filter_params.gain,
'slope': filter_params.slope
})
def _handleChannelParamsChanged(self):
"""处理通道参数更新事件"""
params = self.model.channel_params
self.ui.lineEdit_11.setText(str(params.delay))
self.ui.lineEdit_10.setText(str(params.volume))
self.ui.lineEdit_13.setText(str(params.mix_right))
self.ui.lineEdit_12.setText(str(params.mix_left))
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
from PySide6.QtWidgets import QApplication from PySide6.QtWidgets import QApplication
@ -681,49 +763,16 @@ if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
# Create and show widget # 创建模型
# widget = AudioFilterWidget()
# widget.setWindowTitle("Audio Filter Widget")
# widget.resize(800, 600)
# widget.set_channel_id(2)
# widget.set_channel("channel_2")
# test_case_3 = {
# 'delay_data2': 100.0, # 最大延迟
# 'vol_data2': -80.0, # 最小音量
# 'mix_right_data2': 100.0, # 最大混音
# 'mix_left_data2': 0.0, # 最小混音
# 'filterType2_1': 2, # 低架滤波器
# 'fc2_1': 20000.0, # 最大频率
# 'q2_1': 10.0, # 最大Q值
# 'gain2_1': 12.0, # 最大增益
# 'slope2_1': 4.0, # 最大斜率
# 'filterType2_2': 3, # 高架滤波器
# 'fc2_2': 20.0, # 最小频率
# 'q2_2': 0.1, # 最小Q值
# 'gain2_2': -12.0, # 最小增益
# 'slope2_2': 1.0 # 最小斜率
# }
# widget.set_all_params(test_case_3)
# # 获取所有参数
# params = widget.get_all_params()
# print("params:", params)
# widget.show()
# 创建模型实例
model = AudioFilterModel(channel_id=2, channel_name="channel_2") model = AudioFilterModel(channel_id=2, channel_name="channel_2")
# 设置通道参数 # 设置通道参数
model.channel_params = ChannelParams( model.set_channel_params(ChannelParams(
delay=100.0, delay=100.0,
volume=-80.0, volume=-80.0,
mix_right=100.0, mix_right=100.0,
mix_left=0.0 mix_left=0.0
) ))
# 添加滤波器 # 添加滤波器
model.add_filter(FilterParams( model.add_filter(FilterParams(
@ -742,16 +791,26 @@ if __name__ == "__main__":
slope=1.0 slope=1.0
)) ))
widget_params = model.to_widget_params() # 创建视图并设置模型
print("widget_params:", widget_params)
widget = AudioFilterWidget() widget = AudioFilterWidget()
widget.set_channel_id(model.channel_id) widget.setModel(model)
widget.set_channel_name(model.channel_name)
widget.set_all_params(widget_params)
params = widget.get_all_params()
print("params:", params)
widget.show() widget.show()
# 测试模型更新
def test_update():
# model.set_channel_params(ChannelParams(
# delay=50.0,
# volume=-40.0,
# mix_right=50.0,
# mix_left=50.0
# ))
widget_params = model.get_all_data()
print("widget_params:", widget_params)
# 可以添加一个按钮来触发测试更新
from PySide6.QtWidgets import QPushButton
test_button = QPushButton("Test Update")
test_button.clicked.connect(test_update)
test_button.show()
sys.exit(app.exec()) sys.exit(app.exec())

View File

@ -1,6 +1,7 @@
from dataclasses import dataclass, asdict from dataclasses import dataclass, asdict
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
from enum import Enum from enum import Enum
from PySide6.QtCore import QObject, Signal
class FilterType(Enum): class FilterType(Enum):
PEAK = 0 PEAK = 0
@ -65,26 +66,50 @@ class ChannelParams:
mix_left=data.get(f'mix_left_data{channel_id}', 0.0) mix_left=data.get(f'mix_left_data{channel_id}', 0.0)
) )
class AudioFilterModel: class AudioFilterModel(QObject):
# 定义信号
dataChanged = Signal() # 数据更新信号
filterAdded = Signal(int) # 新增滤波器信号,参数为索引
filterRemoved = Signal(int) # 删除滤波器信号,参数为索引
filterUpdated = Signal(int) # 滤波器更新信号,参数为索引
channelParamsChanged = Signal() # 通道参数更新信号
def __init__(self, channel_id: int, channel_name: str): def __init__(self, channel_id: int, channel_name: str):
super().__init__()
self.channel_id = channel_id self.channel_id = channel_id
self.channel_name = channel_name self.channel_name = channel_name
self.channel_params = ChannelParams(0.0, 0.0, 0.0, 0.0) self.channel_params = ChannelParams(0.0, 0.0, 0.0, 0.0)
self.filters: List[FilterParams] = [] self.filters: List[FilterParams] = []
def updateData(self):
"""触发数据更新信号"""
self.dataChanged.emit()
def add_filter(self, filter_params: FilterParams): def add_filter(self, filter_params: FilterParams):
"""添加新的滤波器""" """添加新的滤波器"""
self.filters.append(filter_params) self.filters.append(filter_params)
self.filterAdded.emit(len(self.filters) - 1)
self.updateData()
def remove_filter(self, index: int): def remove_filter(self, index: int):
"""移除指定索引的滤波器""" """移除指定索引的滤波器"""
if 0 <= index < len(self.filters): if 0 <= index < len(self.filters):
self.filters.pop(index) self.filters.pop(index)
self.filterRemoved.emit(index)
self.updateData()
def update_filter(self, index: int, filter_params: FilterParams): def update_filter(self, index: int, filter_params: FilterParams):
"""更新指定索引的滤波器参数""" """更新指定索引的滤波器参数"""
if 0 <= index < len(self.filters): if 0 <= index < len(self.filters):
self.filters[index] = filter_params self.filters[index] = filter_params
self.filterUpdated.emit(index)
self.updateData()
def set_channel_params(self, params: ChannelParams):
"""设置通道参数"""
self.channel_params = params
self.channelParamsChanged.emit()
self.updateData()
def to_widget_params(self) -> Dict[str, Any]: def to_widget_params(self) -> Dict[str, Any]:
"""转换为AudioFilterWidget兼容的参数格式""" """转换为AudioFilterWidget兼容的参数格式"""
@ -132,3 +157,51 @@ class AudioFilterModel:
model.channel_params = ChannelParams(**data['channel_params']) model.channel_params = ChannelParams(**data['channel_params'])
model.filters = [FilterParams(**f) for f in data['filters']] model.filters = [FilterParams(**f) for f in data['filters']]
return model return model
def get_channel_params(self) -> ChannelParams:
"""获取通道参数"""
return self.channel_params
def get_filter(self, index: int) -> Optional[FilterParams]:
"""获取指定索引的滤波器参数"""
if 0 <= index < len(self.filters):
return self.filters[index]
return None
def get_all_filters(self) -> List[FilterParams]:
"""获取所有滤波器参数"""
return self.filters.copy()
def get_filter_count(self) -> int:
"""获取滤波器数量"""
return len(self.filters)
def get_channel_info(self) -> Dict[str, Any]:
"""获取通道基本信息"""
return {
'channel_id': self.channel_id,
'channel_name': self.channel_name
}
def get_all_data(self) -> Dict[str, Any]:
"""获取所有数据的完整快照"""
return {
'channel_id': self.channel_id,
'channel_name': self.channel_name,
'channel_params': asdict(self.channel_params),
'filters': [asdict(f) for f in self.filters]
}
def is_filter_enabled(self, index: int) -> bool:
"""检查指定滤波器是否启用"""
if 0 <= index < len(self.filters):
return self.filters[index].enabled
return False
def get_enabled_filters(self) -> List[FilterParams]:
"""获取所有启用的滤波器"""
return [f for f in self.filters if f.enabled]
def get_widget_params(self) -> Dict[str, Any]:
"""获取用于widget的参数格式与to_widget_params相同"""
return self.to_widget_params()