From 3df2988915b419137c6b776e54f28288d5056025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Fri, 1 May 2026 23:54:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(merge):=20=E6=B7=BB=E5=8A=A0=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E9=A2=84=E8=A7=88=20Tab=20=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增第三个 Tab「合并预览」,只读展示系统+用户 PATH 完整列表 - 选项卡切换时自动刷新合并列表 - 支持无效/重复路径高亮 - 新增中英文翻译 Co-Authored-By: Claude Opus 4.7 --- include/controller/callbacks_internal.h | 3 +++ include/utils/ui_constants.h | 1 + locale/en_US/LC_MESSAGES/en_US.mo | Bin 6358 -> 6404 bytes locale/zh_CN/LC_MESSAGES/zh_CN.mo | Bin 6156 -> 6200 bytes lua/config.lua | 1 + po/en_US.po | 4 ++++ po/messages.pot | 4 ++++ po/zh_CN.po | 4 ++++ src/controller/callbacks.c | 22 ++++++++++++++++++++++ src/controller/callbacks_sys.c | 1 + src/ui/main_window.c | 24 ++++++++++++++++++++++++ 11 files changed, 64 insertions(+) diff --git a/include/controller/callbacks_internal.h b/include/controller/callbacks_internal.h index 1438c6e..b14af9d 100644 --- a/include/controller/callbacks_internal.h +++ b/include/controller/callbacks_internal.h @@ -23,4 +23,7 @@ Ihandle *get_current_list(Ihandle *dlg); // 刷新撤销/重做按钮的启用状态 void refresh_undo_redo_buttons(Ihandle *dlg); +// 同步合并预览列表 +void sync_merged_list(Ihandle *dlg); + #endif // CALLBACKS_INTERNAL_H diff --git a/include/utils/ui_constants.h b/include/utils/ui_constants.h index ecf89e8..b052aa8 100644 --- a/include/utils/ui_constants.h +++ b/include/utils/ui_constants.h @@ -10,6 +10,7 @@ // 列表控件 #define CTRL_LIST_SYS "LIST_SYS" #define CTRL_LIST_USER "LIST_USER" +#define CTRL_LIST_MERGED "LIST_MERGED" // 选项卡 #define CTRL_TABS_MAIN "TABS_MAIN" diff --git a/locale/en_US/LC_MESSAGES/en_US.mo b/locale/en_US/LC_MESSAGES/en_US.mo index c60b2830ed81a8a4640dd8f4b2adafa6defc70ec..439c72f81efb56c158d9bae3bee55b2689b8fb24 100644 GIT binary patch delta 1660 zcmZY8OGwmF6vy#Xjyd^Er_?5`u}CV*7iplI5y>Lb(Dl_P@s8N$J41*vE z7g|IMF(R6%sEE*oK@o#RP=dCU$c0H!DAf0-|6MZvKllD0=bn4+y`PFYio@e+uA9c+ zG5)jo-yEaf!e25}EHNv^-M9@~aUDLzT>OHGXmMuCAQ5+B7V@*hT#7N|^l#w``u#}! zusxf}v+*M;p=neizfdKOY9I?vDGa{BG4fqGEy zjiVBqMs3PJ$<$w^%poh3QZq%umMV*R$Yy?%Z50y|9 z756*pRQMU4rd>rPFcfxf%%Uoh!3NO4WvElpj>NVh{Y6#=r2VSKwwLjfM4mf!G5o{*YBF!n;uB2c~W3a(j+Y&t66g(H{@&pz|x)c7!{dd1Q_8&1i Bms|h< delta 1616 zcmXZbPe@cz6vy#nGdiVHj@p=-rkP1t_-D#LSu{{t6E4&UNdha%Mc_h<{!#cKEF>f) zaA6^cOcY3q9HNCm617RFaA79ZCTgRL2*I$#zCY*5IG=m(ynFAt=f2Y&nyzrZrF#dA zzq9=3@?YdpFaEayb|slrVJ%i;2X4d1Sd8z`kH0X0|L_p{eP(>Dfv*rYyZs&v((gmo zcPvVymVq&3uFd0G{Eb?0$u*h5H2OKnknO}R7{aaCh>6&VId}zAupf1>hnS5okdJ*_ z9e2!TXlUaF)WS=ciV5rD1~7wuJ}RIPmf}I=QR_g>yN24(LCwGGI*9w|KS3SfyF0#s zRqSt`dP{#|POx{BUG=W<8 z3#uB**qx?bM+GqE_U9ZLN`;S$*TyBNYPg83ZDYtIHi24j#`O;>ux#!_3s<1-z8O^w z1E|c6qpolkxkXz+-F-0~y+h6^8rt9{>W5*}#;;Kee?SgzKU_T=PbuAw3Mhi5cn7u4 zOVqqcWQu)7&0lm4a;2(<)5rlF8>OKKCQ+#kkOoCwj~vokkf5y{wLurMmfc6);Rxy^ zx?@$t5~>=SSX3E_qN*W>XjKiDQS-Yo$o}?-#(oB-QFmBFSgM8_s6d8L0Y1akRHCXO zi7y3Kh+445wGqqd_o4!Rg9SK`Otn1Hr)oHi5%#wc8hQs-P;d8cUSVaT2gA6Gs)h$V zq=1%D0j05uo)05atrHbUKkD~UR5iTE2$t}M>$%&gz=p9pL}QkQQW?mK-)RvtWc5fk gtpimJgQyd{&9YcuYMwVXo^d20_B3V1N9$PPf8e-`qyPW_ diff --git a/locale/zh_CN/LC_MESSAGES/zh_CN.mo b/locale/zh_CN/LC_MESSAGES/zh_CN.mo index 870d568565334a6601727123921a9b89e7ff669f..375f38beab177330a248561aa0dde134e72efd9e 100644 GIT binary patch delta 1653 zcmXZcO-NKx7{>8Kjhf?VscANuX_@30&KOysf@NeSAz_h0*oQbHZNiK`MCw{f4H~3T z5iU$4kT61+vMH*CE`lfuX(b{pQfw2L7zHi*KYE7i{oQl#Iq!MTm$w4ZfHRfix@Y*+ z^Owor*5xWK{gR+8)|eewg*&kgH{nan!wK}Di8E#ucyJG9B9}SIZ5xJc`2nU;eu%_( z%yS+}crl8^GXHP|F5{+vZmSoQDf^HrrWCWV0(0;b#^5#d;tfo|e$>E*a4o(^F7s{i zy<^NQ59-(zzZBSwD=8;ivoV#jAC*uA7Ge!5P#Y?tFsj4bsP?_qCs;~3iWBxloa zeTzku6X~5tvlk2Ts$*Y7Pys%p8qT9OO$i%94O*?8sP6;Tcc_FW?RRZ1?S%~1N5}Ly zs(m|Z1|Fm8kD}^1KY7py^I2p1GzU?8q6yVddqei4Ivzm<7`HB1)0lrh@3r=-*NJM^ zXUoIZkJee-uJa$Dwnl!z+KUP_g9_kf9i$I=Wp>$etu=&dDgQ(wl? zZNVQoG)8h%HOq=GFSz^7P)B~)4rh)QS>^YII+ zV-M3RH(Ph3`l(0t^BOCuYvS1Q3Y3dFR&}UT(S{0e*OsHU`~fv1zfd!jnGx~DX1NlB n&5gl^>_g4Li)VtDB9-o#c+Yfqc>2}Ik4GJ|gW*V3>Zt2Kr&pBB delta 1610 zcmXZcPe_zO7{~FaT>ovGZkmc_YJU)OLsxNE+M*zdgb+(4iol9mDvYp%3_Yw!hmu7N z>JU*BE!8Cnmq;RzIs`?B@K9Eyh198ogpgT5-=90nyZd=(-kE1+o|$*YgYjT&I?r>> z_#EY1%6DU$N~uo{Y|bzXV+0$q3pe0>ti;#o!#VWhUu;5OrWu#D@>7rdUHK9gP##9& z$1K53go-hwul>L*{D}&<==4&#igF23WdSV1dR&KlF&)oh37*FlID%T(4J^hd$YpPr z>SJb8+-Tr=RNzI-#bwzk{g_X=95tbOtihc~Q|m(YyMP)nhU!1)ypCHbKR_*D*458r znDH&mo0|C+q|UY@m+j_91MEYk_#k>PidxAjT#o}7!UQTKAMgPFLhWWNvr_*yRO&lW z8R^DYB{##|ti{Ku6i%X6@E(=Q@0f>*LQKm;1uS(|VUThIYQo2{0#Bn>9LGYuiOrZq zP2`V{{V(UnzcO{mYHL+>;Rv^!;5!c`@)C!KE+UYH*#(oUoSJcXCIRM&{PGrtD;(Um8 zl>Z@@g_uPRo{2~@{f)M2USAgDp7vlsRJigOe-p*QZi4wcSA7W<>ua}TP2 zH!1^HQSHZ2?WR!+j1{xDjA`3YhvEpT // 辅助函数:获取主对话框 @@ -62,3 +63,24 @@ void refresh_undo_redo_buttons(Ihandle *dlg) if (btn_redo) IupSetAttribute(btn_redo, "ACTIVE", can_redo(ctx->undo_redo_mgr) ? "YES" : "NO"); } + +// 同步合并预览列表(sys + user) +void sync_merged_list(Ihandle *dlg) +{ + AppContext *ctx = get_app_context_from_dlg(dlg); + Ihandle *list_merged = IupGetDialogChild(dlg, CTRL_LIST_MERGED); + if (!ctx || !list_merged) + return; + + IupSetAttribute(list_merged, "REMOVEITEM", "ALL"); + + int pos = 1; + for (int i = 0; i < ctx->sys_paths.count; i++) + IupSetAttributeId(list_merged, "", pos++, string_list_get(&ctx->sys_paths, i)); + for (int i = 0; i < ctx->user_paths.count; i++) + IupSetAttributeId(list_merged, "", pos++, string_list_get(&ctx->user_paths, i)); + + int total = ctx->sys_paths.count + ctx->user_paths.count; + IupSetInt(list_merged, "COUNT", total); + refresh_single_list_style(list_merged); +} diff --git a/src/controller/callbacks_sys.c b/src/controller/callbacks_sys.c index f1c8de8..e13ba7f 100644 --- a/src/controller/callbacks_sys.c +++ b/src/controller/callbacks_sys.c @@ -164,6 +164,7 @@ void load_all_paths(void) sync_string_list_to_ui(list_sys, &ctx->sys_paths); sync_string_list_to_ui(list_user, &ctx->user_paths); + sync_merged_list(dlg); Ihandle *lbl_status = IupGetDialogChild(dlg, CTRL_LBL_STATUS); if (lbl_status) diff --git a/src/ui/main_window.c b/src/ui/main_window.c index 10a5e39..f710758 100644 --- a/src/ui/main_window.c +++ b/src/ui/main_window.c @@ -1,5 +1,6 @@ #include "ui/main_window.h" #include "controller/callbacks.h" +#include "controller/callbacks_internal.h" #include "core/lua_config.h" #include "utils/i18n.h" #include "utils/ui_constants.h" @@ -24,6 +25,16 @@ static Ihandle *create_path_list(const char *name) return list; } +// 选项卡切换回调:切换到合并预览时刷新列表 +static int tab_change_cb(Ihandle *self, Ihandle *new_tab, Ihandle *old_tab) +{ + (void)old_tab; + (void)new_tab; + Ihandle *dlg = IupGetDialog(self); + sync_merged_list(dlg); + return IUP_DEFAULT; +} + // 创建主窗口 Ihandle *create_main_window(void) { @@ -31,6 +42,15 @@ Ihandle *create_main_window(void) Ihandle *list_sys = create_path_list(CTRL_LIST_SYS); // 创建用户路径列表 Ihandle *list_user = create_path_list(CTRL_LIST_USER); + // 创建合并预览列表(只读) + Ihandle *list_merged = IupFlatList(); + IupSetAttribute(list_merged, "NAME", CTRL_LIST_MERGED); + IupSetAttribute(list_merged, "EXPAND", "YES"); + IupSetAttribute(list_merged, "ITEMPADDING", lua_config_get_string("list", "item_padding")); + IupSetAttribute(list_merged, "BACKCOLOR", lua_config_get_string("list", "backcolor")); + IupSetAttribute(list_merged, "BORDER", "YES"); + IupSetAttribute(list_merged, "HLINE", "NO"); + IupSetAttribute(list_merged, "ACTIVE", "NO"); // 只读 // 创建搜索框 Ihandle *txt_search = IupText(NULL); @@ -43,11 +63,14 @@ Ihandle *create_main_window(void) Ihandle *tabs_main = IupTabs( IupVbox(list_sys, NULL), IupVbox(list_user, NULL), + IupVbox(list_merged, NULL), NULL); IupSetAttribute(tabs_main, "NAME", CTRL_TABS_MAIN); IupSetAttribute(tabs_main, "TABTITLE0", _(lua_config_get_string("label", "tab_sys"))); IupSetAttribute(tabs_main, "TABTITLE1", _(lua_config_get_string("label", "tab_user"))); + IupSetAttribute(tabs_main, "TABTITLE2", _(lua_config_get_string("label", "tab_merged"))); IupSetAttribute(tabs_main, "TABTYPE", "TOP"); + IupSetCallback(tabs_main, "TABCHANGE_CB", (Icallback)tab_change_cb); // 创建操作按钮 Ihandle *btn_new = IupButton(_(lua_config_get_string("button", "new")), NULL); @@ -201,6 +224,7 @@ void refresh_main_window_ui(Ihandle *main_dlg) { IupSetAttribute(tabs, "TABTITLE0", _(lua_config_get_string("label", "tab_sys"))); IupSetAttribute(tabs, "TABTITLE1", _(lua_config_get_string("label", "tab_user"))); + IupSetAttribute(tabs, "TABTITLE2", _(lua_config_get_string("label", "tab_merged"))); } // 辅助函数:设置子控件标题