From 4dcfeac86d0b69a56a2001f7bdd44d79e4cf1a9e Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 20 Feb 2025 22:52:03 +0800 Subject: [PATCH] =?UTF-8?q?[feature]=20=E6=96=B0=E5=A2=9E=E9=80=9A?= =?UTF-8?q?=E4=BF=A1server=20=E6=96=B0=E5=A2=9E=E9=80=9A=E4=BF=A1=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 70 ++++- app_origin.py | 58 ++++ .../application_controller.cpython-313.pyc | Bin 0 -> 4352 bytes application/app.py | 92 ++++++- application/application_controller.py | 75 +++++ .../__pycache__/__init__.cpython-313.pyc | Bin 261 -> 283 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 286 -> 308 bytes .../ui_widget_card.cpython-313.pyc | Bin 5703 -> 5725 bytes .../__pycache__/widget_card.cpython-313.pyc | Bin 11854 -> 11876 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 148 -> 170 bytes .../ui_widget_channel.cpython-313.pyc | Bin 109510 -> 109532 bytes .../widget_channel.cpython-313.pyc | Bin 4134 -> 4156 bytes .../__pycache__/Ui_widget.cpython-313.pyc | Bin 76756 -> 76778 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 147 -> 169 bytes .../audio_filter_componet.cpython-313.pyc | Bin 45523 -> 45809 bytes .../audio_filter_controller.cpython-313.pyc | Bin 0 -> 7718 bytes .../audio_filter_model.cpython-313.pyc | Bin 12543 -> 12565 bytes .../checkbox_header.cpython-313.pyc | Bin 3345 -> 3367 bytes .../__pycache__/resources.cpython-313.pyc | Bin 2074 -> 2096 bytes .../widget_filter/audio_filter_componet.py | 30 +- .../widget_filter/audio_filter_controller.py | 257 ++++++++++++++++++ .../__pycache__/__init__.cpython-313.pyc | Bin 145 -> 167 bytes .../ui_widget_main.cpython-313.pyc | Bin 63588 -> 63610 bytes .../__pycache__/widget_main.cpython-313.pyc | Bin 1189 -> 1211 bytes param_struct_test | 2 +- 25 files changed, 548 insertions(+), 36 deletions(-) create mode 100644 app_origin.py create mode 100644 application/__pycache__/application_controller.cpython-313.pyc create mode 100644 application/application_controller.py create mode 100644 component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc create mode 100644 component/widget_filter/audio_filter_controller.py diff --git a/app.py b/app.py index e140316..5cf30e8 100644 --- a/app.py +++ b/app.py @@ -3,33 +3,62 @@ from component.widget_channel.widget_channel import Widget_Channel from component.widget_card.widget_card import Widget_Card from component.widget_card.widget_card import CardData from component.widget_filter.audio_filter_componet import AudioFilterWidget +from component.widget_filter.audio_filter_model import AudioFilterModel +from component.widget_filter.audio_filter_controller import AudioFilterController +from param_struct_test.service_manager import ServiceManager +from application.application_controller import ApplicationController from datetime import date -from PySide6.QtWidgets import QMainWindow +from PySide6.QtWidgets import QMainWindow, QPushButton, QVBoxLayout from PySide6.QtWidgets import QWidget from PySide6.QtCore import QObject class MainWindow(QWidget): def __init__(self): super().__init__() + # 初始化服务 + ServiceManager.instance().init_services("127.0.0.1", 1234) + # 初始化应用控制器 + self.app_controller = ApplicationController.instance() + self.widget_main = Widget_Main() self.widget_channel = Widget_Channel() self.widget_card = Widget_Card() - self.widget_main.ui.ListWidget_vLayout.addWidget(self.widget_card) + # self.widget_main.ui.ListWidget_vLayout.addWidget(self.widget_card) self.widget_main.ui.Channel_hLayout.addWidget(self.widget_channel) self.widget_filter_list = [] + self.filter_controllers = [] # 存储控制器实例 + + # 添加测试按钮 + self.test_button = QPushButton("Test Communication") + self.test_button.clicked.connect(self.test_communication) + self.widget_main.ui.ListWidget_vLayout.addWidget(self.test_button) self.create_filter_widget() self.setup_connections() def create_filter_widget(self): for i in range(24): + # 创建widget filter_widget = AudioFilterWidget() filter_widget.set_channel_id(i) filter_widget.set_channel_name(f"Channel {i+1}") + + # 创建model和controller + model = AudioFilterModel(channel_id=i, channel_name=f"Channel {i+1}") + controller = AudioFilterController(model) + controller.set_widget(filter_widget) + + # 连接控制器信号 + controller.error_occurred.connect(lambda msg: print(f"Error: {msg}")) + controller.state_changed.connect(lambda state: print(f"State changed: {state}")) + controller.params_synced.connect(lambda: print("Params synced")) + + # 存储实例 self.widget_filter_list.append(filter_widget) + self.filter_controllers.append(controller) def setup_connections(self): print("setup_connections") @@ -39,20 +68,37 @@ class MainWindow(QWidget): print(f"channel_id: {channel_id}") self.widget_filter_list[channel_id].show() + def test_communication(self): + """测试通信功能""" + print("Testing communication...") + + # 测试第一个控制器的通信 + if self.filter_controllers: + controller = self.filter_controllers[0] + + # 测试从服务器加载数据 + print("Testing load from server...") + controller.load_from_server() + + # 测试同步数据到服务器 + print("Testing sync to server...") + # controller.sync_to_server() + if __name__ == '__main__': import sys from PySide6.QtWidgets import QApplication app = QApplication(sys.argv) main_window = MainWindow() - for i in range(1, 11): - data = CardData( - name=f"项目 {i}", - date=date.today().strftime("%Y-%m-%d"), - description=f"这是项目 {i} 的详细描述信息,可以包含多行文本内容。这是一个较长的描述,用于测试换行效果。" - ) - main_window.widget_card.add_card_item(data) + + # # 添加测试卡片 + # for i in range(1, 11): + # data = CardData( + # name=f"项目 {i}", + # date=date.today().strftime("%Y-%m-%d"), + # description=f"这是项目 {i} 的详细描述信息,可以包含多行文本内容。这是一个较长的描述,用于测试换行效果。" + # ) + # main_window.widget_card.add_card_item(data) + main_window.widget_main.show() - sys.exit(app.exec()) - - + sys.exit(app.exec()) \ No newline at end of file diff --git a/app_origin.py b/app_origin.py new file mode 100644 index 0000000..e140316 --- /dev/null +++ b/app_origin.py @@ -0,0 +1,58 @@ +from component.widget_main.widget_main import Widget_Main +from component.widget_channel.widget_channel import Widget_Channel +from component.widget_card.widget_card import Widget_Card +from component.widget_card.widget_card import CardData +from component.widget_filter.audio_filter_componet import AudioFilterWidget + +from datetime import date +from PySide6.QtWidgets import QMainWindow +from PySide6.QtWidgets import QWidget +from PySide6.QtCore import QObject + +class MainWindow(QWidget): + def __init__(self): + super().__init__() + self.widget_main = Widget_Main() + self.widget_channel = Widget_Channel() + self.widget_card = Widget_Card() + + self.widget_main.ui.ListWidget_vLayout.addWidget(self.widget_card) + self.widget_main.ui.Channel_hLayout.addWidget(self.widget_channel) + + self.widget_filter_list = [] + + self.create_filter_widget() + self.setup_connections() + + def create_filter_widget(self): + for i in range(24): + filter_widget = AudioFilterWidget() + filter_widget.set_channel_id(i) + filter_widget.set_channel_name(f"Channel {i+1}") + self.widget_filter_list.append(filter_widget) + + def setup_connections(self): + print("setup_connections") + self.widget_channel.channel_btn_clicked.connect(self.on_channel_btn_clicked) + + def on_channel_btn_clicked(self, channel_id: int): + print(f"channel_id: {channel_id}") + self.widget_filter_list[channel_id].show() + +if __name__ == '__main__': + import sys + from PySide6.QtWidgets import QApplication + + app = QApplication(sys.argv) + main_window = MainWindow() + for i in range(1, 11): + data = CardData( + name=f"项目 {i}", + date=date.today().strftime("%Y-%m-%d"), + description=f"这是项目 {i} 的详细描述信息,可以包含多行文本内容。这是一个较长的描述,用于测试换行效果。" + ) + main_window.widget_card.add_card_item(data) + main_window.widget_main.show() + sys.exit(app.exec()) + + diff --git a/application/__pycache__/application_controller.cpython-313.pyc b/application/__pycache__/application_controller.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e1b7f2264db57a657d5005cafc18932c7eecfb7 GIT binary patch literal 4352 zcmahMTW}NC_3mmVt)-PE%Wubk%)`#w*fHS|A`AnVgw_rQywwadsNE6rVnk(0xhthH zGnw(Uoy0V}KH?6245c5LkRRfYV8!X{F8pz%y&1^OjonB=qP+|^pb2zp04 z_uPB#o_p_k-(`=-MW8JNZ;W4Z6Y?J%Sj}ESmM;M^LlmNL!(@n~+z?OsAse*?aE>1q zhV0Zn%HYlpnl8zAAD7P6iw&NiZm z+j(=(?WL`$kI`y?<_dG$ZRRws8+XgnLmbF9!+G@ZiPKs%Z8((Jcp?%v1SOtK13@?t zgIU|Y#H1k}PNic>Aj+IkGZsllqVb5X!@zSSLL(EpqS1F^Q4J<)OX#6UA~LQ~m~oqI zkI>}1lhM+-SXVj?S>6M~84@OxQwZf1j@mYnun@K@d>2r{4!~>-bHc2+jYq-4oPcwR zoz{#yWT(+Em`tQ;G9K5cx#0mg=0g#d7@p_~NsWyej-SQG#>>EE7juQq{LJk$8#XRn?O*s;A?zgqBDG*`}wd0ke@rBAJe$d~{W%cq{5a z;KaQfRaHk~RE?z5GB4Lq0v*ZH0UEkwcZqs zMB!U497(0(u_)W55?9MN>q|}2T42ZkUR!?&zz1ZpzG+@)%1iaXIGlIYPV1Kjr{6u> z_odK6krIi({{WFk%vPv%sPeCv1K_}ZeAVZ_hu&DSHp^cmtR;;cjM7D8?9p*&p zQXFlBx)o%$Tr z5;)beZyOXZZ48m!9BtZ2pC7aK-&QtqD3>-R%O>`(Hmj4-T`2W6dgqJUfg|lch(*FSNpo(y)iv_ z?oi(AzxdwS_vXZQW(H4*14Y5aaRrb)+zdGmz1c=f@x>Zre*)s(am#8T##uVlxZ~&s zto?`!kssHQ72yRylx42*6=n3pe0+r$h}C0pDEF2E0%V-X{K%P2RV5LK>48WS1GmWZX9-Qx^E@ck6I=MLoD-C6wYxaVIx zx9-h(|G_!w;62fE)|nMs7R0uEci)1zWpqg1NBoze6(C}Sc83f2r~Ni9aZnoL;B zpIIjJbThJbmXv8~%XBWRY^ZuTkKbZ9gr=5$U z*HlkVd?hQsGArczk7oOi-W5m9`0K+>U1fWVqUTu+ar`d_0L+kMfog#%#9R7 z_{+7W_sSNb8q>|C5SP4`q49wF^82<$X+;b%mD(GyLD}j#9D)2CXj;;hslZLRm zi&~DC;1xc>hxnIEA4FbfBF0m!YNP0atJ?9EU>xGB?^FHEitTlqbpmjGVO)^y84SiH zxBu)$;ZHwbx_+)OeF@TG;gg$7AKWa=%${i-WGz@Jy*{kjf`$~yjKz{rkHx`c!L*rG zLw+F?gUSe$gZ31SK|P2=V~q;sUWH*p5vZO_Qq`;jDSl@(TDzF>CX<4Vv@t`_CSqw; zBv}rGW@}nir32Be$mG@PM)abHgx~2u1u#V(i=?J@u2#M_kn0)9_6#hDyYnsWxt3tI zCHVP3Zr4b5*T{U!;b{+K^wzFv&%fO*i;^!Vb!Mf`oYa$*dKNbC&9CjrH*d%_cW0Zs z^Nk(3#?EYG=Od@kTl<6v9&gc3q*gQX;I*TbCWhw3jPWuc&ntsQamA`;W#oGD1Bk8} z;F;P`t_VUls0m8@ScW$S<3lZAe70&CCBy}f5yI9$Uq1bBLWRm0>dk! zqX2Ud9ZRWUKa7m6&(ZFSjOze=sJ{sS>M)UX_vPeZRu1Omy;*thm-7Csv}yX#J#W*c zGgo)!yqo8}n`hf{TlQzS?7w~T?v}Um%^UCdHa@bG?m-Te?rShLSBh@|V9SacxtTT~ zjzu4BLePw0Jp#Ok`7Rg)%y6?ZWkO4zN{+D%%W4#s`Y7mwn9mmo3xp0JK%1Zv0yI>L zk%FQyXd3{-Q!0C+T0E|*GDmx1mes3!%>sy(TnMoE)-M3~{(Z9OYnb}sBL`WtVQ#}~ z^X)t5gw{p7Zh9f 'ApplicationController': + """获取ApplicationController的单例实例""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + if ApplicationController._instance is not None: + raise RuntimeError("ApplicationController is a singleton!") + super().__init__() + ApplicationController._instance = self + self._controllers: Dict[str, QObject] = {} + self._setup_service_connections() + + def _setup_service_connections(self): + """设置服务连接""" + service = ServiceManager.instance().params_service + # 连接服务信号到应用控制器的槽 + service.signal_request_complete.connect(self._on_service_request_complete) + + def register_controller(self, controller_id: str, controller: QObject): + """注册控制器""" + self._controllers[controller_id] = controller + + def unregister_controller(self, controller_id: str): + """注销控制器""" + if controller_id in self._controllers: + del self._controllers[controller_id] + + @Slot(SignalProxy) + def _on_service_request_complete(self, signal_proxy: SignalProxy): + """服务请求完成的槽函数""" + # 找到对应的controller_id + print("CCCCCC:signal_proxy.data:", signal_proxy.data) + controller_id = self._get_controller_id_for_widget(signal_proxy.widget) + + # 测试用 返回值类似这种格式 用来标机控件 + controller_id = "audio_filter" + if controller_id: + # 转发信号 + self.signal_params_updated.emit(ControllerSignalData( + controller_id=controller_id, + widget=signal_proxy.widget, + data=signal_proxy.data + )) + + def _get_controller_id_for_widget(self, widget: QObject) -> Optional[str]: + """根据widget查找对应的controller_id""" + # 这里需要根据您的具体实现来确定如何找到对应的controller_id + # 示例实现 + for controller_id, controller in self._controllers.items(): + if hasattr(controller, 'widget') and controller.widget == widget: + return controller_id + return None \ No newline at end of file diff --git a/component/__pycache__/__init__.cpython-313.pyc b/component/__pycache__/__init__.cpython-313.pyc index 4bcf2c0969e421acfaa4c518d3eede318c4b54df..e4bbba2edac60acef5947a8947e641af6c30e304 100644 GIT binary patch delta 60 zcmZo=n$5)hnU|M~0SF!*-a3(cuBw%bRg7aw)(s~E?!#Nzni%HopL+?d3o)VHQyU delta 38 scmdnOG>?hW~aAk2xYHmzoQF2CRNosOQX;G?f RK~Z9INoI2D<`SmM!T`Z%7cc+- delta 41 vcmcbsb6kh}GcPX}0}yn5+`N%HiizLM#VW?JEU`E~xU#q;HFt9t(`8`*85a&1 diff --git a/component/widget_card/__pycache__/widget_card.cpython-313.pyc b/component/widget_card/__pycache__/widget_card.cpython-313.pyc index 1c8d5c77669560443e80567b6bb8b4dcd6105439..a6552c6d49d7ee8a75a24e3de7781fe80d3ef3ee 100644 GIT binary patch delta 63 zcmX>X^CX7*GcPX}0}wnsymcdYA&aV~i&czcSz>W~aAk2xYHmzoQF2CRNosOQX;G?f RK~Z9INoI2D=5Ch5ngHME7t;U$ delta 41 vcmaD7b1sJaGcPX}0}y=qvw0(TAq&5;i&czcSz>W~aAk2xYVPKREQd7#IROta diff --git a/component/widget_channel/__pycache__/__init__.cpython-313.pyc b/component/widget_channel/__pycache__/__init__.cpython-313.pyc index 5874d50ca9a4304b67a40e3eeac510895c46ec67..01974309d5b7bfb2cd41f9a4e25aa7ebaff16fac 100644 GIT binary patch delta 60 zcmbQjxQdbcGcPX}0}wnsymcbCv8tzwRg7aGcPX}0}yCD-8_-onBUmND#o!au{b`svbZEQcVeW~aAk2xYHmzoQF2CRNosOQX;G?f RK~Z9INoI2DW@FaRTmYbi7IXjr delta 41 vcmdm^uuOsbGcPX}0}ymcZP~~z$;xl(Vin_9mRKAgTv=R_n!DMP^)nX$?qCdt diff --git a/component/widget_filter/__pycache__/Ui_widget.cpython-313.pyc b/component/widget_filter/__pycache__/Ui_widget.cpython-313.pyc index f41c12b7728e37c626e58a318279aa08d8973dbb..55a44f6b0c4813cabf2aa5336281b21da9fe6ca1 100644 GIT binary patch delta 69 zcmca|o#oYa7Vgiyyj%=G@bK`~M((ZLjFQ}{o-S4~j%A6(@xhhFC8@bFiABj7nI);o YC8b5Fx&=jv$t9V|soRaY85b%50A6SqrT_o{ delta 47 zcmaELo#o1P7Vgiyyj%=G@WF0NBllKrMoDgdV-Kqs$FjuY_~6RolGNPop4^NJ6##rw B4@Lk0 diff --git a/component/widget_filter/__pycache__/__init__.cpython-313.pyc b/component/widget_filter/__pycache__/__init__.cpython-313.pyc index a3637de9ae95e832af9b3feecaf7b91bd2d1b862..e4f88846ad71628aeba09af8ed9e8ad0cddaba74 100644 GIT binary patch delta 60 zcmbQtxRR0kGcPX}0}wnsymcbCv8soQRg7aio`STL0@m`V2s9uPCW^0Ho!TpIkvmGgTuTL7JiQDdIOk&v zO!tR7>dXjxxw-iQ_{->A|Y8cxixARgs>x4ox!T+gzCIlHHB4Y zis1I#2Rp?QA+_#lgjRq*4XHwmo>E-O-m^T2FT-WA#%Z2%RRr(CE`C0q&sX3I8xqUx zNG$bkCXJ@tR$M6-F)isrhLE|C!&PFHHyGEGIEpTY$r7^JGh4`6sC7epmXTF?I}?%d zSe(yVRCv3{FW|I14iO?Q&RONOBlk23t`%#&kw-9ACG@QI_A>G51mY zwXwH77+xOiQe?a)+%9*K2`vvf#H3qW+}u@_%O*1+G>S)C5 z0BE2iDQk?dg#Ma6mIQ09LZO_!7KMtLLTyoF~g1qi}&v zIWhr0qJPcnGQg*F%Yy0@NTVZ9T+zUC8d=J7@HhQ<*##4HlD>7r5F)UC7`Bmp>-#`q zaR$luz5xAX)Vm)BNr^BFJIOgV?j{Wz#$brv+^`EkqT!9NX&|4NHci4lI4(o#UW@ ze%61UgEBfWSd#>`^z5E{T4>T@G>I;2A@E{xa|pGl ztK&FrGjenB*oFegse3XI&sHs-4w^o}W6Y-mDSffi=P>xlUW=d0+FMD%*qYQAY&zv`>$#MiAl3)>#61Iv+cFP7v;)c7AM85*~e%JEF{ y-Z&4G{4u`RbdhZkyHR96sXtSlb2kk^`DIjg1JztbD`I!e6qMq-A*R-9Z9jDz# z7g5lO3=BF?Hk}SdQKJhCx+6qMrXgxH!I+SdXsSOjibN$L3&W3SqUYX@Nzbbr8;I;?~jlraQ?5Nmv~jq zb=7v{`Nsq|NlpIvEgan*$g(VKlYcik*KDp79VH02u>Q(fe>~<{iD$tpZc4FN^7;qK zVq<|LbqmXun>x16o3%8vO&IyFly%eK-$TBwx6=q`0vlv>+oN4OqCMeI(g~Towt=2# z{H|zUGK4qBdqREWsJh6k&ZzH+CXyL-do-BL+$d zfMz;jr~+6|=Z%|nuz}_l&1zwUp0%C?D5bq+ud3jA#lcbD4NyWxD=uiJS%-$ z&{r@<`Hm_Ulh*Cjaxg_b-JbxwLH`I$0K7xTgV#7n(|ut#2cJ{g8`HogYTtcT4Mu7j zECWze_t3j4u+kq=r&UlxryspT3r+OmlYgq=L3-gpJrB{j!{Hn_P9u{ZfT!szFRWL? zJpKCRQ8j!_yN~_?aFOhI{R(_TT919m?EgA83Gh9geAB_fHG1~#PSC7jdxmXf%}kK} zktb$0vbdkk@G3U>;fRCK zkaB9e`U5zyE8%r=SVUxawk>~-oo^ev_X!Jg*o&5oODM diff --git a/component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc b/component/widget_filter/__pycache__/audio_filter_controller.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de6796138596b8361e8bd528ee10b1d781e84675 GIT binary patch literal 7718 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 delta 41 vcmbQ5^gogNGcPX}0}vQ?Z`;Vt#>8*qVHM+8mRKAgTv=R_n!DMI>AoHS3Q!F| diff --git a/component/widget_filter/__pycache__/checkbox_header.cpython-313.pyc b/component/widget_filter/__pycache__/checkbox_header.cpython-313.pyc index b09ea10c92072287e34d456861abfde8cd596fef..d176b662f53ace1215544f7525f3771252c1f22d 100644 GIT binary patch delta 63 zcmbOzwOoq(GcPX}0}wnsymceD4zsGii&czcSz>W~aAk2xYHmzoQF2CRNosOQX;G?f RK~Z9INoI2DW;f>3oB)<^7B>I@ delta 41 vcmZ23HBpNDGcPX}0}z~O*s_sZhne5f!z#wHEU`E~xU#q;HFt9i^Jz{1`A`h; diff --git a/component/widget_filter/__pycache__/resources.cpython-313.pyc b/component/widget_filter/__pycache__/resources.cpython-313.pyc index 835b1ae4fa7c5338080521d335e27c07911cd62c..760073ee4b6aa3b01393283af466f50acdc622fd 100644 GIT binary patch delta 63 zcmbOwut9+PGcPX}0}wnsymceDI-9Dei&czcSz>W~aAk2xYHmzoQF2CRNosOQX;G?f RK~Z9INoI2DW=FQ0i~y9l7BK(- delta 41 vcmdlWFiU{@GcPX}0}$*m+p>{cosHkv!z#wHEU`E~xU#q;HFtA3+f7CQ?&b`U diff --git a/component/widget_filter/audio_filter_componet.py b/component/widget_filter/audio_filter_componet.py index f0056c3..e145b53 100644 --- a/component/widget_filter/audio_filter_componet.py +++ b/component/widget_filter/audio_filter_componet.py @@ -6,20 +6,20 @@ from PySide6.QtGui import QPainter, QColor, QPen, QBrush, QPainterPath, QIcon, Q from PySide6.QtCore import QFile -from Ui_widget import Ui_Widget -from audio_filter_model import AudioFilterModel -from checkbox_header import SCheckBoxHeaderView -import resources +# from Ui_widget import Ui_Widget +# from audio_filter_model import AudioFilterModel +# from checkbox_header import SCheckBoxHeaderView +# import resources from typing import List, Dict, Optional, Any -# from component.widget_filter.Ui_widget import Ui_Widget -# from component.widget_filter.checkbox_header import SCheckBoxHeaderView -# from component.widget_filter.checkbox_header import SCheckBoxHeaderView -# from component.widget_filter.Ui_widget import Ui_Widget +from component.widget_filter.Ui_widget import Ui_Widget +from component.widget_filter.checkbox_header import SCheckBoxHeaderView +from component.widget_filter.audio_filter_model import AudioFilterModel +from component.widget_filter.Ui_widget import Ui_Widget -# import component.widget_filter.resources +import component.widget_filter.resources class ReadOnlyDelegate(QStyledItemDelegate): @@ -800,12 +800,12 @@ if __name__ == "__main__": # 测试模型更新 def test_update(): - # model.set_channel_params(ChannelParams( - # delay=50.0, - # volume=-40.0, - # mix_right=50.0, - # mix_left=50.0 - # )) + 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) diff --git a/component/widget_filter/audio_filter_controller.py b/component/widget_filter/audio_filter_controller.py new file mode 100644 index 0000000..981a5e5 --- /dev/null +++ b/component/widget_filter/audio_filter_controller.py @@ -0,0 +1,257 @@ +from PySide6.QtCore import QObject, Signal, Slot +from typing import Dict, Any, Optional +from dataclasses import dataclass +from enum import Enum, auto +from application.application_controller import ApplicationController, ControllerSignalData +from param_struct_test.service_manager import ServiceManager +from param_struct_test.params_service import ParamsService +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 + +class AudioControllerState(Enum): + """音频控制器状态""" + IDLE = auto() + UPDATING = auto() + ERROR = auto() + +class AudioFilterController(QObject): + CONTROLLER_ID = "audio_filter" + + # 定义信号 + state_changed = Signal(AudioControllerState) # 状态变化信号 + error_occurred = Signal(str) # 错误信号 + params_synced = Signal() # 参数同步完成信号 + filter_changed = Signal(int, str, float) # 滤波器参数变化信号 + channel_changed = Signal(str, float) # 通道参数变化信号 + + def __init__(self, model: AudioFilterModel): + super().__init__() + self.model = model + self.widget = None + self._state = AudioControllerState.IDLE + self._setup_application_controller() + self._setup_model_connections() + + @property + def state(self) -> AudioControllerState: + """获取当前状态""" + return self._state + + @state.setter + def state(self, value: AudioControllerState): + """设置状态并发送信号""" + if self._state != value: + self._state = value + self.state_changed.emit(value) + + def _setup_application_controller(self): + """设置应用控制器连接""" + app_controller = ApplicationController.instance() + app_controller.register_controller(self.CONTROLLER_ID, self) + app_controller.signal_params_updated.connect(self._on_params_updated) + + def _setup_model_connections(self): + pass + """设置模型信号连接""" + # self.model.dataChanged.connect(self._on_model_data_changed) + + # to do:后续看情况调整是否需要单独下发调整的滤波器数据 + # self.model.filterAdded.connect(self._on_filter_added) + # self.model.filterRemoved.connect(self._on_filter_removed) + # self.model.filterUpdated.connect(self._on_filter_updated) + # self.model.channelParamsChanged.connect(self._on_channel_params_changed) + + def set_widget(self, widget: AudioFilterWidget): + """设置关联的widget""" + self.widget = widget + self.widget.setModel(self.model) + self._setup_widget_connections() + + def _setup_widget_connections(self): + """设置widget信号连接""" + if self.widget: + pass + # to do:后续看情况调整是否需要单独下发调整的滤波器数据 + # self.widget.filter_changed.connect(self._on_widget_filter_changed) + # self.widget.param_changed.connect(self._on_widget_param_changed) + # self.widget.filter_added.connect(self._on_widget_filter_added) + # self.widget.filter_deleted.connect(self._on_widget_filter_deleted) + # self.widget.filter_enabled_changed.connect(self._on_widget_filter_enabled_changed) + + @Slot(ControllerSignalData) + def _on_params_updated(self, signal_data: ControllerSignalData): + """处理来自ApplicationController的参数更新信号""" + if signal_data.controller_id != self.CONTROLLER_ID: + return + + try: + self.state = AudioControllerState.UPDATING + data = signal_data.data + + # 使用ChannelParams类创建实例 + channel_params = ChannelParams( + delay=data.get('delay_data1', 0.0), + volume=data.get('vol_data1', 0.0), + mix_right=data.get('mix_right_data1', 0.0), + mix_left=data.get('mix_left_data1', 0.0) + ) + + # 更新通道参数 + self.model.set_channel_params(channel_params) + + # 清除现有滤波器 + self.model.filters.clear() # 使用filters列表的clear方法替代clear_filters + + # 解析并添加滤波器参数 + # filter_index = 1 + # while True: + # filter_type_value = data.get(f'filterType1_{filter_index}') + # if filter_type_value is None: + # break + + # # 使用FilterParams类创建实例 + # filter_params = FilterParams( + # filter_type=FilterType(filter_type_value), + # frequency=data.get(f'fc1_{filter_index}', 0.0), + # q_value=data.get(f'q1_{filter_index}', 0.0), + # gain=data.get(f'gain1_{filter_index}', 0.0), + # slope=data.get(f'slope1_{filter_index}', 0.0) + # ) + # self.model.add_filter(filter_params) + # filter_index += 1 + + self.params_synced.emit() + self.state = AudioControllerState.IDLE + + except Exception as e: + self.state = AudioControllerState.ERROR + self.error_occurred.emit(f"Error updating params: {str(e)}") + + def sync_to_server(self): + """同步数据到服务器""" + try: + self.state = AudioControllerState.UPDATING + params = self.model.get_all_data() + ServiceManager.instance().params_service.set_params(params) + except Exception as e: + self.state = AudioControllerState.ERROR + self.error_occurred.emit(f"Error syncing to server: {str(e)}") + + def load_from_server(self): + """从服务器加载数据""" + try: + print("BBBBBB:load_from_server") + self.state = AudioControllerState.UPDATING + ServiceManager.instance().params_service.get_params(self.widget) + except Exception as e: + self.state = AudioControllerState.ERROR + self.error_occurred.emit(f"Error loading from server: {str(e)}") + + # 模型信号处理器 + def _on_model_data_changed(self): + """处理模型数据变化""" + if self.widget and self.state != AudioControllerState.UPDATING: + self.widget.set_all_params(self.model.to_widget_params()) + + # def _on_filter_added(self, index: int): + # """处理滤波器添加""" + # if self.widget: + # filter_params = self.model.get_filter(index) + # if filter_params: + # self.widget.add_filter(filter_params) + + # def _on_filter_removed(self, index: int): + # """处理滤波器移除""" + # if self.widget: + # self.widget.remove_filter(index) + + # def _on_filter_updated(self, index: int): + # """处理滤波器更新""" + # if self.widget: + # filter_params = self.model.get_filter(index) + # if filter_params: + # self.widget.update_filter(index, filter_params) + + # def _on_channel_params_changed(self): + # """处理通道参数变化""" + # if self.widget: + # channel_params = self.model.get_channel_params() + # self.widget.update_channel_params(channel_params) + + +######################################################################################### + # Widget信号处理器 + # def _on_widget_filter_changed(self, index: int, param_name: str, value: float): + # """处理widget滤波器参数变化""" + # try: + # filter_params = self.model.get_filter(index) + # if filter_params: + # setattr(filter_params, param_name, value) + + # # to do:按照目前架构,这块的调整是个死循环,后续看具体情况进行解耦 + # self.model.update_filter(index, filter_params) + # # self.filter_changed.emit(index, param_name, value) + # except Exception as e: + # self.error_occurred.emit(f"Error updating filter: {str(e)}") + + # def _on_widget_param_changed(self, param_name: str, value: float): + # """处理widget通道参数变化""" + # try: + # channel_params = self.model.get_channel_params() + # setattr(channel_params, param_name, value) + # self.model.set_channel_params(channel_params) + # self.channel_changed.emit(param_name, value) + # except Exception as e: + # self.error_occurred.emit(f"Error updating channel params: {str(e)}") + + # def _on_widget_filter_added(self, filter_type: str): + # """处理widget添加滤波器""" + # try: + # filter_params = FilterParams( + # filter_type=FilterType[filter_type], + # frequency=0.0, + # q_value=0.0, + # gain=0.0, + # slope=0.0 + # ) + # self.model.add_filter(filter_params) + # except Exception as e: + # self.error_occurred.emit(f"Error adding filter: {str(e)}") + + # def _on_widget_filter_deleted(self, index: int): + # """处理widget删除滤波器""" + # try: + # self.model.remove_filter(index) + # except Exception as e: + # self.error_occurred.emit(f"Error removing filter: {str(e)}") + + # def _on_widget_filter_enabled_changed(self, index: int, enabled: bool): + # """处理widget滤波器启用状态变化""" + # try: + # filter_params = self.model.get_filter(index) + # if filter_params: + # filter_params.enabled = enabled + # self.model.update_filter(index, filter_params) + # except Exception as e: + # self.error_occurred.emit(f"Error updating filter state: {str(e)}") +########################################################################################## + + + # def save_preset(self, filepath: str): + # """保存预设""" + # try: + # self.model.save_to_file(filepath) + # except Exception as e: + # self.error_occurred.emit(f"Error saving preset: {str(e)}") + + # def load_preset(self, filepath: str): + # """加载预设""" + # try: + # new_model = AudioFilterModel.load_from_file(filepath) + # self.model = new_model + # self._setup_model_connections() + # if self.widget: + # self.widget.set_all_params(self.model.to_widget_params()) + # except Exception as e: + # self.error_occurred.emit(f"Error loading preset: {str(e)}") \ No newline at end of file diff --git a/component/widget_main/__pycache__/__init__.cpython-313.pyc b/component/widget_main/__pycache__/__init__.cpython-313.pyc index 4278c737074d53c11b28f7accb0d884ad950f908..806555aa0cc5830cb9a22c9b438e73661568b433 100644 GIT binary patch delta 60 zcmbQpxSWyuGcPX}0}wnsymcbCv8tPkRg7ai&czcSz>W~aAk2xYHmzoQF2CRNosOQX;G?f RK~Z9INoI2D<{TzVCIFoF73cr} delta 41 vcmdnZxs;RpGcPX}0}x34-Mo=Ih>73W#VW?JEU`E~xU#q;HFt9plO+=X_Gt`k diff --git a/param_struct_test b/param_struct_test index b130b72..1dd0e56 160000 --- a/param_struct_test +++ b/param_struct_test @@ -1 +1 @@ -Subproject commit b130b72db80780cb7ca7636a08fc5052f3a6976f +Subproject commit 1dd0e56a13ecd81d921d2ac4c6e7132c3f9cc587