From ba8a50e0b957ffde1fa32ef28bc5d6d9053038c8 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Fri, 19 Sep 2025 16:03:23 +0200 Subject: [PATCH 1/9] debug frictions --- src/View/Frictions/UndoCommand.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/View/Frictions/UndoCommand.py b/src/View/Frictions/UndoCommand.py index 14d6395b..dc060f00 100644 --- a/src/View/Frictions/UndoCommand.py +++ b/src/View/Frictions/UndoCommand.py @@ -151,6 +151,7 @@ class ReplaceDataCommand(QUndoCommand): self._new_data = new_data self._old_rows = list(range(len(frictions))) self._new_rows = list(range(len(new_data))) + self._new = [] self._old_friction = [] for row in self._old_rows: @@ -162,15 +163,20 @@ class ReplaceDataCommand(QUndoCommand): self._frictions.insert(row, el) def redo(self): - self._frictions.delete_i(self._old_rows) - for row in self._new_rows: - new = self._frictions.new(row) - d = self._new_data[row] - new.edge = d[0] - new.begin_rk = d[1] - new.end_rk = d[2] - new.begin_strickler = d[3] - new.end_strickler = d[4] + if len(self._new) == 0: + self._frictions.delete_i(self._old_rows) + for row in self._new_rows: + new = self._frictions.new(row) + d = self._new_data[row] + new.edge = d[0] + new.begin_rk = d[1] + new.end_rk = d[2] + new.begin_strickler = d[3] + new.end_strickler = d[4] + self._new.append((row, new)) + else: + for row, el in self._new: + self._frictions.insert(row, el) class DelCommand(QUndoCommand): From 9270dd0ff18969e94203bd291a5c628977acd155 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Fri, 19 Sep 2025 16:04:10 +0200 Subject: [PATCH 2/9] add HHLab test case --- tests_cases/HHLab/HHLab.pamhyr | Bin 0 -> 176128 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests_cases/HHLab/HHLab.pamhyr diff --git a/tests_cases/HHLab/HHLab.pamhyr b/tests_cases/HHLab/HHLab.pamhyr new file mode 100644 index 0000000000000000000000000000000000000000..f2b713ab41dcb91db99fa16c6890d4134c065717 GIT binary patch literal 176128 zcmeI54{#&bec!PFh<^mIB=~3VMDlKV|6v|+y8w0p_-s?u33sN&BPAZMmd<~mC9ovd z0s#sDPe-TeSuo0+8l)Vg-e$f6f2EdfOoviHHCZ zAOb{y2oM1xKm>>Y5g-CYfCvzQyCyJp6h-t6<9~cG#Q%ZA7k<#ef0w@$evtnX{~7-0 z`4WHat}CGehyW2F0z`la5CI}U1c(3;AOb|-4MpIV+vPrf`CarLZ4@>GfyGs$D&l8tQ!MGvh*g#6q6Q zJy+DKwOm!ZuICC`O_x(jI-brbvJy)rrFc>u_qa}<%U5)b!K|w!)ua-aqt>}Kz^~12M$06Y3 zTDeqnt-C(U_Wv9n$fsxWU!UDeRucgtKm>>Y5g-CYfCvx)B0vO)01?=eK*;HF2!4(; zA5?I;+5X?lzneY(|A+kN`Iq>g<=63%UPOQh5CI}U1c(3;AOb{y2oM1xKm>@uJ_$td zbUio3aXz1q^Q`0XeP?9rkc6~xE3L;U)%41GxhN}6e(TV=ZHc=ni93T^LJX3lRvuSF zl5zUCgvo7zvmsEOo~_}t0f)byqmiC)y0-cz0uJ90GswrmAlbRa_W$X?4;=g-WB>mO z|8f4q{0&~?-@zyOBYaQzyWu|!|I6@8;TOW!!%v1Ug{APJ(Ekhl_t5W#J{S76&<8@5 z(6!Kmp);Yr;9mv575r-O)4^X3-U_}ixDb3x@Ki9=`-9&9();D!Pxijp`&{pO?>l?n z-ka_{((6Hm^dbU8fCvx)B0vO)01+SpKQaR0wBNynI1b-~c_S`)YdB?n_Hvvj;+lFz znflv*^5Io^>yV1{ekgHVPo)rXPJRA=e>VH8zw;$|E38;Kd>rSFIOVNS(){elXIDht z5)x)cKQcNiE0OJdgK@vZAL4uvM7HY*%6^9rsjvr`hb60Q=y-Y8)Srg#T;|^V5ov4q zTr=H+^e;5h55>&N>Q?g3saL-G*F&GF{xNb)HgmX<{*>>RoEs-EN?Su`&2(m-i{DNb zCd`8BR`c8C48EypHNRc&VAQf2rSL6Qo@v(U4Z`{nv(j^0!>60+9;AQa+y8oO@V|Zj z+}5E}W~FuOgU+chyfg*b5OSPs=5QnZr!4EwZ4I3;(@pDx+sVRlv!J^5!R>Mek2S4F zYNOu4@uu~`7AwVOonAkzKl8$OT>toUv8~~w&2$gaznJs<;Khrz*w&#VW~FuO{m!W` zzU`rF-_482G1koCM*5wL)tmqBKmA2)YiQI=H?8+?CkrEHL3Qi>+vN;C(6k<@jd}+U zH?8-#Sb3;fr`H4P)&8XWe?Bs~H7qpKJxKrJSEKL!*oc2}>(H=SY2A7ctp7yexBfEq z8RQsh=5QnZgBJVAt)W3P-L&4boh%HP1=X$hY?m__X`57-TcQK{2$@3{(Ty6=tTsG01+Sp zM1Tko0U|&IhyW2F0z`la{D=t*x?Pi8wOqs>>&vZc75wc!+%OOycDZEEC>b?FE9Ua$ zQUUMErK)$t={nCXl{ZQSt+Kf-U}p$uj$5f8mXKR7zaG34jN)nk@AdwE@27kJe(#OmYrSvl6?>h5Zw0;*cscOFz*^wZ zKs+!M@c94S|4skb{IB?b!~cu^5BT5bf5bn5Cl$Wu`#s-3@qO4=@h$ok->~=pc>lfk zH@&~?{b_H`JMBH;^?3e==XX4x^!%LXY0njp;t_iOs^`_7S9*S>=T?v2bEzlV)9d~d z_t)J2)cvCSy8ChWdH0xW%k>S{Z@d1H>le{HdJ%#9nE+q*IQ&CHTtdZPamv4omTsp(7_MoS4)t6S1HL7Gg);!+yrrV}ta6GwvzmNW_}jDodl zDxs>VSw?e5@{q!)Gms`?88k>rOR!r_#ns5@l9lze6iY#xN~Yxu@+SaUMZuaSJq4+n zh$)$rs;1LQN>0fckb2URo`f`+h$WM0HG_<)q>@n}%~{eDkj4`+2okb_Zjj>WlE}z= zA%#)LAx*?&MNu+xJgy{?FgY^%9xLlH2@Df4NtTsVT2?_(Rv~@2B^`%Uje}Mukw{4y zIUyxc@aVfNsR(H@j;hm{L>xXLqfuz?HA{LF(s&#Vl9CBDH$72bZWx{V-f_0J6cUsa>NRd}gr=(OyO`*Z60;B$xB^`kj zMo9`Xs&O@ul9NeDuUgUvAcZ?;;u&;~tiU2QlZlKhLJFe}Ln_D8QbL6Xz;P5MosNuN zv9cbLV(2;0l2Y)iB&2d0U9ezD1xQsHhDphIN|iDy{)10FW=V%3P0IL7aUaBS z_%nPtp(fIbilLAKt9L*Qvv`Q%Sb(7>6DS~+Ng(fxl{YNK(3qGCCr-xWaf~($hGk+F-GxEEp=mPo}@DMdlM zRQL&4XCWRq#|0o}w#f;gMx!K*vQ%X3VJov=g5y9Vp`iN!8!oEKsQQ8>_CXBGWVj@2 zvMHAmk+Fv?u@@p(hGCRW;|*E`7gQogrkPmgJWM3Tq*N*?#WB68DIkxdw;qHXru9J1 ze%Q2-PGQ!OF!my&Q!Mu+=SEJL#@tJllM3dYGr1mLhd4KyQBO%(DK5A!OG)(gsaA>;lVm+bVU`GH zuz`x4>CrGmNEUR@f7+d15f8ik6T&IV1vM$hI3;k z%pkg=^By?Hq*2ZcHc5=XG-eY_4Jd#g9k+6tp$3svQQ+Sg*@-kFH$N&`QZv-B$cp(I zaR|W=ZRSUgLJE^us6k*w3o&U+Xez=5KYGN zbjA^}F&0&R^srT`8D|juFn%#gvDT6lImwS4vPw1MOdR0=;T#^E!O92*3077!%pmq9 z*`$d;p(HS4^P|I-v>s;C7&plj7-4dhReod$QcxN+!wj3RffpcH@9?98R@Qo$Q7|JW zGZ}aro7?yYutQ`W7r}IkFoXF}MZdBs7ygZ%A{(z}kU{tYIRtt*1;PZ{+HXnwkQ2il zu^84O5V4gL490GfO_x@Pfs?5T1ab`JjFO4-W7t%(39lYw(AV$^EXFW0(g~R#3tQrP zjDdS&-GgN(^ssE=$3m949%EEQ&NPBS3Tr&b`LUoSuE!YULF`oEa+r@Zm=1a&2CRCF z!351_Y9+&P@nZoiZ#~3dt%OCIiX|_`hmzpO{Fb;LVz3B{XX2PtF-+tHYW7*;Mu@pedWeBvpmt10Sk__e%KVWYD|<7> zNQghOg7||qA%^}Dw2h;|$Nf|9AA=&s!t1jR+6{B0vO)01+SpM1Tko0U|&IhyW3|TLQHI zzgvQop9l~EB0vO)01+SpM1Tko0U|&Ih`{|%fbIXiyzJn=#s4e*W&VTw8b6PZ^dbU8 zfCvx)B0vO)01+SpM1Tko0V42|O<>eK&ktvZdc7WJWa@=a`s7o8v^n+bRoAy?pZ@G9 zJJv5`N_(9AE~$C8pDA@agS({W5r3xC<@E28vZMa2lATV^PU(nw;Gdb->DnoLz&!Ym z9XjfD?v#c2zjOq-IR}4(|Gn@hLJ#*&`R9B;^n9o1Wp~#3FSt2~>9ubHw~U}yn4045 z;KYTcqF&T+T!VE+L#<*gZLnh+%+na!3PKkaveS!MadG;g*{s-B?My&yc^L(9W^OTi zDZ3!f%`b{`S7&F%M;B%;PcJ+nK9YSxoW8m^KQo7tFK6c#&)Tz=cIUNgu)`xHaWVTi z3a%HvTS4xmP|P>XvuC_GzmT1|G{;OlQ_M%jh3v)bLU!&#_R5|OKVuZ4Ew)E*`+B{C zqHxb9+Opn@U$86T1HrX7se}_cI-#g-u6LGeOP#Xog%y2omP`7IQOZ@G0>tUrHXWsx z3SBf>dxX_x>ywJXP9dr2T7GqBSKQJ9Ug7+C?#>ftSF|~Tq)l?KtwY)<9jH%!+z!9A z4~Ji}JN)iu?_zx3?-gX3yEEQ~@$Mo5UC15?>W|dXOXWfvM{jjernQHQvgDog?nHcE zVQh?h{uz_ra>dBA$++>a-$tsDdKY|*uJh`>8L{SYY)lDl#=TWj6%i=^R8g;V(Pp#6 zesxcw(Gd1T?t-Wxx2&%^1!>B_L`x~ z&iF#KL8>Q|!*fM9sdii&{sXS%PicSj}q$;?6na9dfqL);Aw< zd4=(D?v}N;+OA^zoqG?)rV%aWh+>!RlHJ;Fh;MXSac|m%EmlOYa$W&{xaFqhGDc|` z2l6eKowf$BlrvB1oAxb%cy(^(v8&m$;&rXKv12z8J?-=e=Z824rUCs%JxpmEH587| zIaXj!X8(6#OY39XTK4^a!1*CZ_+se2!EEoQ|D(Q7dEe7>-96y^5O>q@eBk3utKBQG z!adhccEEJ}*#dg~gcG>!8ukj8FLQS`&53k%vry4CibkF-NH_Aejf!5)EooIGn7-dl ze%Lmex@jM19`3Z(>NaI`y9ltyxVFzpORLpJfV2x*CuJzvCf4@N-?^r__2iIOn4aeD zJkq5X+823fpX3k3+}_r^rEJBba-dBHjzG&=u=z2y}nI z4EA?tyIf`}Z`8Ug)eB;moA!40Mk(zzT8BeRakgR6x)AHQ!ECLrQwgm>{?=myULhLg z?!3oZ80uBMa=mO+%xl1y%vwGT+q%{+J5Z-~nwh$94)mgaU1L{9>?;@h(5r4#mbJXz zNu}96hQqKssqbgMdC*Pc&6z&)Qqiqx(~o!c)2@Vp&i#59 zJ=(3m^5r#l5yZX?Y4z7z!@O6RoaAojthVepuzcqM<`H{Kc4!}{A$K?1b!&Lnm6+AC z_F!)6VRO%Vd&mOQxCUF@zO31AhtbqH5QaAMl|8w&8|{)cqg1YR8USmUfpB%l_T^Hm z1Kdu9%r7UNJ8ZUd_u2HjQ^K}(@0K5^{jaSXw1R7M5yf`(%nrBnMYDoY&97<|e6MGN zYcHbvglG?_STpSrX_{B!TYHY}|DF8T+28;F`cL@olbTNihyW2F0z`la5CI}U1c(3; zAOb|-^-7=*rwNSVv4G2E+}2jB>2J9f!ubILQZ5y>YW3PRw*Qa&4m zO<`3PNuSA|Waqvq{bRnmdJXqYS8Muu zZcSU!x7ALt6W|j4W8R%=`Rer+Ep`$dv^+btmW$s`RsF_X3t!owBzK;j>a15fQ@Jv3+PK=uljk&a95#JH7t!a2FqG*)# z9KNdAU|)t-8>%8ZKJKJ2=47gkRwvj&dJT;;I6}@JJvqh{mW>h^GBupC^=AA?5`G$* zr*WK|@3f`Kc$pc_!%=qR zoy-d(W(LzsaQA{ zu$4o*Vb8Io6&Yw~OIFv#*!g(#yl}|W$MC@2T&!LA+ObhfJ?FOn_6tL%976?< zCNAkX2_5eGj8V(4W-^u@J5vvOgDrY%Xy7{h)u_VBWUCuu?07viX~5KLO3|nSZaihq z$Oc&%&p*}?umks?AL*w5SY4kT!Uz5SZu-|O{Rws~-wZGGnfi@sWtTZ|CQh5D^hNsx z-c)AIGlA3*i0qWU2|);3Quu>Ke7iqK*g<_K2ZWHRkzX!i(!Mb%$IQabWBMj}A!rJ# zYvpon6$4&hw!n$(n7#xr^qOMU57yXa_xM;E6YQiuG$mjaP%E$J*zGrZg;8y0s4keb zonR;TVSe$O%1>9{mt$X$SM-|kezV+%OsxrafFFwVnOeAqr)HEkFaUQbUon-BvE%&Y zA;D`Z+va|DYObjxvNQcK^gX6d6F0&QW^zk|o$3dT9=itOU{iw~><10EslmowqnyS} ze2N|IHysi>L>05HF?Ph?NkP~hQcUqlcEVruq|iQ|m})23L4T($wLOE0sm1pH9RI2V zKlCC3M1Tko0U|&IhyW2F0z`la5CI}U1YU;(j&W|s$oYc4jEAUe4_p6;jjNXU8*BJ` zCRJ>Y5g-CYpiW?v3pjlJA-@;@%}P^G zE?xfpKYRIyQy=eRZ$82H|BgO_MFfZd5g-CYfCvx)B0vO)01+SpM1TmqkqOZL|Bc+c z)HWhO1c(3;AOb{y2oM1xKm>>Y5g-B<0ownQClCQ5Km>>Y5g-CYfCvx)B0vO)01|2aP9zz@BM01+SpM1Tko0U|&IhyW2F0z`la5CN0G&3Vr2@XN<<6K%JoaGy-7#@I5ST6&k*`z`*R+CeRv@mG3&ygM*J?~VU*0I97+pkxIMa_6 zSXpYy|4*(>1c(3; zAOb{y2oM1xKm>>Y5g-CY;Ehj!_Wy7EKBg8D0U|&IhyW2F0z`la5CI}U1c(3;2n7y1 z{M?g{(EEcwo|#H5S9wZA>t@@QrI!j_b$~Iimuk4BhTRg=xww@s^0hAVLT5R_T?#LiWmDuAmi+YOQ+4C`5O5 zN^5y$2ic0M7`Rm^XQs2vHt&eu85{EoQ&ZgYGwraigY{y1TQb-`%M#y#u(Kl|k>~aCNONZdcdp;(T?jeL9$>-Rc%iXg1e)w1Lue zt3A3XdM7^W6{e@T=gX#lY-h;jSG9_kujv(drID|;mxwkGX|HFW<__cY2y@k;RL(Kxp;MM=CP~U7Qc=rMm)l$an50s3i^%e z(?z4E=d_Jl+5DW_wl61dzdw5O%3-e%jdHg%vpw@0we^kK!Xwk>glzvbYHOEWhS_%) zbX(xY9i@9lS8-P)6>CPVxHD9Xt$o%t4n!Re=gJ#k{Y6c5m=9x>j4Yx7CiT#_mhE?Hz0^o;hl+Gw=Mg$zrLzQ7UMa z&FyVc&RQq76&$zGX{&Y@nD!eP&BcbTp>`0ZGH&OuZ_w>Y5g-CYfCvx)B0vQ01%Uu7r0-soL}d^GB0vO) z01+SpM1Tko0U|&IhyW2F0{1Hc`u_iZ?HRI*2oM1xKm>>Y5g-CYfCvx)B0vO)z`Y|t z`~Q2#l1d^1M1Tko0U|&IhyW2F0z`la5CI}^zY?JR|NYuCWET-20z`la5CI}U1c(3; zAOb{y2oQmLM}YSK_l_l%LPpuwP(mKB0vO) z01+SpM1Tko0U|&IhyW2F0{4yp?f>r`ODc&75CI}U1c(3;AOb{y2oM1xKm>@u{YrrL z|MzRpkX=N82oM1xKm>>Y5g-CYfCvx)B0vQ09Rb?^-#eC65)mK*M1Tko0U|&IhyW2F z0z`la5P|!Z0PX+p*PbD}hyW2F0z`la5CI}U1c(3;AOb{y2;4gYZ2#|df5Q>}wcz)A zKN9$P-yQEbKGKT_5CJ0a`X_Mbt*5-g*ckVBFW0oCqFykTbJcY{-}rap!a{a>F)J=k zKQx;a8>wdk;*OV55NGBVvzM|9;@teAICph+R(y0}=JNEy6XGM;C(iE5z=|s9%i2b< zwkzju?KQo&S}ur-*~d|Kz5Lx;6&$m8V3sZMH*sda1AvEwrRtK})8> zZiDk}()E(r7ve+n^RwCMxeg{?oL|V!T$*Ey&$J+oqTq|!h3wpg>=m=uw1QEsRnHiO z=x!@o%P7F?Rt0*B+)y)C(I%GykQ~ENY)Uo|9i%c zw~@N5qyvL3ps4*1(fxG6k7X+Lx!clW&`f#-#Km$xZ9VS-cTQK z&00_I@`xYXfCGwd><>B|ZoT`MSGatcyE9<|C~7smq7`%ba;a7^mNsfexs)qtHLczS z-Q=fiu)1m6BVU&xB~D*moS&IP1(&mPi*{dP7D}C_ET$lLQYhvdq0U}%>vUes+Z=PR z*6oXxTCjvx(2oM1xKm>>Y5g-CYfCvx)BJlbr@c#kXx{kI0 literal 0 HcmV?d00001 From 41cffd13e0ab19751f019c48a00eefc817c44c84 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Fri, 19 Sep 2025 16:33:06 +0200 Subject: [PATCH 3/9] debug --- src/View/LateralContribution/Table.py | 2 +- src/View/LateralContribution/UndoCommand.py | 22 ++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/View/LateralContribution/Table.py b/src/View/LateralContribution/Table.py index 56eb70e2..e7596d14 100644 --- a/src/View/LateralContribution/Table.py +++ b/src/View/LateralContribution/Table.py @@ -116,7 +116,7 @@ class ComboBoxDelegate(QItemDelegate): def setModelData(self, editor, model, index): text = str(editor.currentText()) - if self._mode == "rk": + if self._mode == "rk" and self._data.reach is not None: profiles = list( filter( lambda p: p.display_name() == text, diff --git a/src/View/LateralContribution/UndoCommand.py b/src/View/LateralContribution/UndoCommand.py index e101f513..2ecbe67b 100644 --- a/src/View/LateralContribution/UndoCommand.py +++ b/src/View/LateralContribution/UndoCommand.py @@ -143,13 +143,13 @@ class DelCommand(QUndoCommand): self._tab = tab self._rows = rows - self._bc = [] + self._lc = [] for row in rows: - self._bc.append((row, self._lcs.get(self._tab, row))) - self._bc.sort() + self._lc.append((row, self._lcs.get(self._tab, row))) + self._lc.sort() def undo(self): - for row, el in self._bc: + for row, el in self._lc: self._lcs.insert(self._tab, row, el) def redo(self): @@ -219,14 +219,14 @@ class PasteCommand(QUndoCommand): self._lcs = lcs self._tab = tab self._row = row - self._bc = deepcopy(bc) - self._bc.reverse() + self._lc = deepcopy(bc) + self._lc.reverse() def undo(self): - self._lcs.delete(self._tab, self._bc) + self._lcs.delete(self._tab, self._lc) def redo(self): - for bc in self._bc: + for bc in self._lc: self._lcs.insert(self._tab, self._row, bc) @@ -237,11 +237,11 @@ class DuplicateCommand(QUndoCommand): self._lcs = lcs self._tab = tab self._rows = rows - self._bc = deepcopy(bc) - self._bc.reverse() + self._lc = deepcopy(bc) + self._lc.reverse() def undo(self): - self._lcs.delete(self._tab, self._bc) + self._lcs.delete(self._tab, self._lc) def redo(self): for bc in self._lcs: From 80ae4c36adaa96f9c0819b7c8d5d601a062a6e8a Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 23 Sep 2025 14:17:59 +0200 Subject: [PATCH 4/9] import lateral contributions from file --- src/View/LateralContribution/Table.py | 56 +++++++++++++++++---- src/View/LateralContribution/UndoCommand.py | 56 ++++++++++++++++++--- src/View/LateralContribution/Window.py | 28 ++++++++++- src/View/LateralContribution/translate.py | 4 ++ src/View/ui/EditLateralContribution.ui | 12 +++++ src/View/ui/LateralContributions.ui | 13 +++++ 6 files changed, 149 insertions(+), 20 deletions(-) diff --git a/src/View/LateralContribution/Table.py b/src/View/LateralContribution/Table.py index e7596d14..5bee4de8 100644 --- a/src/View/LateralContribution/Table.py +++ b/src/View/LateralContribution/Table.py @@ -38,7 +38,7 @@ from View.LateralContribution.UndoCommand import ( SetNameCommand, SetEdgeCommand, SetTypeCommand, SetBeginCommand, SetEndCommand, AddCommand, DelCommand, SortCommand, - MoveCommand, PasteCommand, DuplicateCommand, + MoveCommand, PasteCommand, DuplicateCommand, ImportCommand, ) from Model.LateralContribution.LateralContributionTypes import ( @@ -116,17 +116,20 @@ class ComboBoxDelegate(QItemDelegate): def setModelData(self, editor, model, index): text = str(editor.currentText()) - if self._mode == "rk" and self._data.reach is not None: - profiles = list( - filter( - lambda p: p.display_name() == text, - self._data.reach.profiles - ) - ) - - value = profiles[0].rk if len(profiles) > 0 else None - else: + if self._data is None: value = text + else: + if self._mode == "rk" and self._data.reach is not None: + profiles = list( + filter( + lambda p: p.display_name() == text, + self._data.reach.profiles + ) + ) + + value = profiles[0].rk if len(profiles) > 0 else None + else: + value = text model.setData(index, value) editor.close() @@ -293,3 +296,34 @@ class TableModel(PamhyrTableModel): self.endMoveRows() self.layoutChanged.emit() + + def read_from_lat(self, file_name): + logger.debug(f"Import lateral contributions from {file_name}") + data = [] + current_reach = -1 + with open(file_name, encoding="utf-8") as lat_file: + for line in lat_file: + if not (line.startswith("#") or + line.startswith("*") or + len(line) < 1): + line = line.split() + if line[0] == "$": + current_reach = int(line[1]) - 1 + if (current_reach <= len(self._data.enable_edges()) and + current_reach > 0) : + data.append([self._data.enable_edges()[current_reach], float(line[2]), float(line[3])]) + else: + if (current_reach <= len(self._data.enable_edges()) and + current_reach > 0) : + data[-1].append([float(line[0]), float(line[1])]) + + self.layoutAboutToBeChanged.emit() + + self._undo.push( + ImportCommand( + self._lst, self._tab, data + ) + ) + + self.layoutAboutToBeChanged.emit() + self.layoutChanged.emit() diff --git a/src/View/LateralContribution/UndoCommand.py b/src/View/LateralContribution/UndoCommand.py index 2ecbe67b..a320073f 100644 --- a/src/View/LateralContribution/UndoCommand.py +++ b/src/View/LateralContribution/UndoCommand.py @@ -28,6 +28,10 @@ from Model.LateralContribution.LateralContributionList import ( LateralContributionList ) +from Model.LateralContribution.LateralContributionTypes import ( + NotDefined, LateralContrib, +) + class SetNameCommand(QUndoCommand): def __init__(self, lcs, tab, index, new_value): @@ -213,36 +217,72 @@ class MoveCommand(QUndoCommand): class PasteCommand(QUndoCommand): - def __init__(self, lcs, tab, row, bc): + def __init__(self, lcs, tab, row, lc): QUndoCommand.__init__(self) self._lcs = lcs self._tab = tab self._row = row - self._lc = deepcopy(bc) + self._lc = deepcopy(lc) self._lc.reverse() def undo(self): self._lcs.delete(self._tab, self._lc) def redo(self): - for bc in self._lc: - self._lcs.insert(self._tab, self._row, bc) + for lc in self._lc: + self._lcs.insert(self._tab, self._row, lc) +class ImportCommand(QUndoCommand): + def __init__(self, lcs, tab, data): + QUndoCommand.__init__(self) + + self._tab = tab + self._lcs = lcs + self._data = data + self._old_rows = list(range(len(self._lcs.get_tab(self._tab)))) + self._new_rows = list(range(len(self._data))) + + self._new_lc = None + self._old_lc = [] + for row in self._old_rows: + self._old_lc.append((row, self._lcs.get(self._tab, row))) + + def undo(self): + self._lcs.delete_i(self._tab, self._new_rows) + for row, el in self._old_lc: + self._lcs.insert(self._tab, row, el) + + def redo(self): + self._lcs.delete_i(self._tab, self._old_rows) + if self._new_lc == None: + self._new_lc = [] + for row, data in enumerate(self._data): + new = LateralContrib(status=self._lcs._status) + new.edge = data[0] + new.begin_rk = data[1] + new.end_rk = data[2] + for i, val in enumerate(data[3:]): + new.insert(i, val) + self._new_lc.append(new) + + for row, el in enumerate(self._new_lc): + self._lcs.insert(self._tab, row, el) + class DuplicateCommand(QUndoCommand): - def __init__(self, lcs, tab, rows, bc): + def __init__(self, lcs, tab, rows, lc): QUndoCommand.__init__(self) self._lcs = lcs self._tab = tab self._rows = rows - self._lc = deepcopy(bc) + self._lc = deepcopy(lc) self._lc.reverse() def undo(self): self._lcs.delete(self._tab, self._lc) def redo(self): - for bc in self._lcs: - self._lcs.insert(self._tab, self._rows[0], bc) + for lc in self._lcs: + self._lcs.insert(self._tab, self._rows[0], lc) diff --git a/src/View/LateralContribution/Window.py b/src/View/LateralContribution/Window.py index db8b2791..1b74f5cf 100644 --- a/src/View/LateralContribution/Window.py +++ b/src/View/LateralContribution/Window.py @@ -22,6 +22,7 @@ from tools import trace, timer from View.Tools.PamhyrWindow import PamhyrWindow +from PyQt5 import QtWidgets from PyQt5.QtGui import ( QKeySequence, ) @@ -29,7 +30,7 @@ from PyQt5.QtGui import ( from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, QCoreApplication, QModelIndex, pyqtSlot, - QRect, + QRect, QSettings, ) from PyQt5.QtWidgets import ( @@ -153,6 +154,8 @@ class LateralContributionWindow(PamhyrWindow): ) def setup_connections(self): + self.find(QAction, "action_import").triggered.connect( + self.import_from_file) self.find(QAction, "action_add").triggered.connect(self.add) self.find(QAction, "action_del").triggered.connect(self.delete) self.find(QAction, "action_edit").triggered.connect(self.edit) @@ -297,3 +300,26 @@ class LateralContributionWindow(PamhyrWindow): parent=self ) win.show() + + def import_from_file(self): + options = QFileDialog.Options() + settings = QSettings(QSettings.IniFormat, + QSettings.UserScope, 'MyOrg', ) + options |= QFileDialog.DontUseNativeDialog + + file_types = [ + self._trad["file_lat"], + self._trad["file_all"], + ] + + filename, _ = QtWidgets.QFileDialog.getOpenFileName( + self, + self._trad["open_file"], + "", + ";; ".join(file_types), + options=options + ) + + if filename != "": + tab = self.current_tab() + self._table[tab].read_from_lat(filename) diff --git a/src/View/LateralContribution/translate.py b/src/View/LateralContribution/translate.py index e3de3d87..787e0cfb 100644 --- a/src/View/LateralContribution/translate.py +++ b/src/View/LateralContribution/translate.py @@ -52,6 +52,10 @@ class LCTranslate(MainTranslate): self._dict["x"] = _translate("Geometry", "X (m)") self._dict["y"] = _translate("Geometry", "Y (m)") self._dict["z"] = _translate("Geometry", "Z (m)") + self._dict["file_lat"] = _translate( + "LateralContribution", "Shapefile (*.LAT *.lat)") + self._dict["file_all"] = _translate( + "LateralContribution", "All files (*)") self._sub_dict["table_headers"] = { "name": self._dict["name"], diff --git a/src/View/ui/EditLateralContribution.ui b/src/View/ui/EditLateralContribution.ui index 21736a6b..2e739f88 100644 --- a/src/View/ui/EditLateralContribution.ui +++ b/src/View/ui/EditLateralContribution.ui @@ -112,6 +112,18 @@ Sort points + + + + ressources/import.pngressources/import.png + + + Import + + + Import from file + + diff --git a/src/View/ui/LateralContributions.ui b/src/View/ui/LateralContributions.ui index 32f4f60a..5d44cba2 100644 --- a/src/View/ui/LateralContributions.ui +++ b/src/View/ui/LateralContributions.ui @@ -97,6 +97,7 @@ false + @@ -162,6 +163,18 @@ Sort by names + + + + ressources/import.pngressources/import.png + + + Import + + + Import from file + + From e7b63fe2705520d97a02093c9ee425a45b02f1d6 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 23 Sep 2025 14:55:31 +0200 Subject: [PATCH 5/9] debug --- src/View/BoundaryCondition/Edit/Table.py | 5 ++++- src/View/LateralContribution/Table.py | 13 +++++++++---- src/tools.py | 5 ++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index e50308fc..313abb89 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -227,7 +227,10 @@ class TableModel(PamhyrTableModel): line.startswith("*") or line.startswith("$")): line = line.split() - data0.append(float(line[0]) * mult) + if bctype == "ZD": + data0.append(float(line[0])) + else: + data0.append(old_pamhyr_date_to_timestamp(line[0])) data1.append(line[1]) self.replace_data(data0, data1) diff --git a/src/View/LateralContribution/Table.py b/src/View/LateralContribution/Table.py index 5bee4de8..9e69dddd 100644 --- a/src/View/LateralContribution/Table.py +++ b/src/View/LateralContribution/Table.py @@ -19,7 +19,7 @@ import logging import traceback -from tools import trace, timer +from tools import trace, timer, old_pamhyr_date_to_timestamp from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, @@ -310,12 +310,17 @@ class TableModel(PamhyrTableModel): if line[0] == "$": current_reach = int(line[1]) - 1 if (current_reach <= len(self._data.enable_edges()) and - current_reach > 0) : + current_reach >= 0) : data.append([self._data.enable_edges()[current_reach], float(line[2]), float(line[3])]) else: if (current_reach <= len(self._data.enable_edges()) and - current_reach > 0) : - data[-1].append([float(line[0]), float(line[1])]) + current_reach >= 0) : + data[-1].append( + [ + old_pamhyr_date_to_timestamp(line[0]), + float(line[1]) + ] + ) self.layoutAboutToBeChanged.emit() diff --git a/src/tools.py b/src/tools.py index 8c14e267..553cc1fb 100644 --- a/src/tools.py +++ b/src/tools.py @@ -260,7 +260,10 @@ def date_dmy_to_timestamp(date: str): def old_pamhyr_date_to_timestamp(date: str): v = date.split(":") if len(v) != 4: - return 0 + if len(v) == 1: # minutes + return int(float(v[0]) * 60) # Minute to sec + else: + return 0 m = [ (24 * 60 * 60), # Day to sec From 1b2f98494b612f436c84b7ad6c8f8bbbfdc97121 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Tue, 23 Sep 2025 15:53:49 +0200 Subject: [PATCH 6/9] pep8 --- src/View/LateralContribution/Table.py | 11 ++++++++--- src/View/LateralContribution/UndoCommand.py | 3 ++- src/tools.py | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/View/LateralContribution/Table.py b/src/View/LateralContribution/Table.py index 9e69dddd..8b33f76b 100644 --- a/src/View/LateralContribution/Table.py +++ b/src/View/LateralContribution/Table.py @@ -310,11 +310,16 @@ class TableModel(PamhyrTableModel): if line[0] == "$": current_reach = int(line[1]) - 1 if (current_reach <= len(self._data.enable_edges()) and - current_reach >= 0) : - data.append([self._data.enable_edges()[current_reach], float(line[2]), float(line[3])]) + current_reach >= 0): + data.append( + [self._data.enable_edges()[current_reach], + float(line[2]), + float(line[3]) + ] + ) else: if (current_reach <= len(self._data.enable_edges()) and - current_reach >= 0) : + current_reach >= 0): data[-1].append( [ old_pamhyr_date_to_timestamp(line[0]), diff --git a/src/View/LateralContribution/UndoCommand.py b/src/View/LateralContribution/UndoCommand.py index a320073f..d3afd803 100644 --- a/src/View/LateralContribution/UndoCommand.py +++ b/src/View/LateralContribution/UndoCommand.py @@ -256,7 +256,7 @@ class ImportCommand(QUndoCommand): def redo(self): self._lcs.delete_i(self._tab, self._old_rows) - if self._new_lc == None: + if self._new_lc is None: self._new_lc = [] for row, data in enumerate(self._data): new = LateralContrib(status=self._lcs._status) @@ -270,6 +270,7 @@ class ImportCommand(QUndoCommand): for row, el in enumerate(self._new_lc): self._lcs.insert(self._tab, row, el) + class DuplicateCommand(QUndoCommand): def __init__(self, lcs, tab, rows, lc): QUndoCommand.__init__(self) diff --git a/src/tools.py b/src/tools.py index 553cc1fb..6f0919d4 100644 --- a/src/tools.py +++ b/src/tools.py @@ -260,8 +260,8 @@ def date_dmy_to_timestamp(date: str): def old_pamhyr_date_to_timestamp(date: str): v = date.split(":") if len(v) != 4: - if len(v) == 1: # minutes - return int(float(v[0]) * 60) # Minute to sec + if len(v) == 1: # minutes + return int(float(v[0]) * 60) # Minute to sec else: return 0 From 7d42c164fc76021c9e6fc7c125c3e52771ed9811 Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Thu, 25 Sep 2025 17:01:01 +0200 Subject: [PATCH 7/9] debug --- src/Model/SedimentLayer/SedimentLayer.py | 21 +++++++++++---------- src/View/Results/Window.py | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Model/SedimentLayer/SedimentLayer.py b/src/Model/SedimentLayer/SedimentLayer.py index b31238cd..b8fc19dc 100644 --- a/src/Model/SedimentLayer/SedimentLayer.py +++ b/src/Model/SedimentLayer/SedimentLayer.py @@ -277,18 +277,19 @@ class SedimentLayer(SQLSubModel): "FROM sedimentary_layer " ) - for row in table: - sl = cls( - id=row[0], - name=row[1], - comment=row[2], - status=data['status'] - ) + if table is not None: + for row in table: + sl = cls( + id=row[0], + name=row[1], + comment=row[2], + status=data['status'] + ) - data["sl"] = sl.id - sl._layers = Layer._db_load(execute, data) + data["sl"] = sl.id + sl._layers = Layer._db_load(execute, data) - new.append(sl) + new.append(sl) return new diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index b5270fdd..d37f37f9 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -494,7 +494,7 @@ class ResultsWindow(PamhyrWindow): table = self.find(QTableView, f"tableView_profile") indexes = table.selectedIndexes() if len(indexes) == 0: - return 0 + return [] return [i.row() for i in indexes] From da03f39425ea83b650402ac64705999f5f4f68eb Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Mon, 29 Sep 2025 11:23:46 +0200 Subject: [PATCH 8/9] debug --- src/View/BoundaryCondition/Edit/translate.py | 2 +- src/View/InitialConditions/Window.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/View/BoundaryCondition/Edit/translate.py b/src/View/BoundaryCondition/Edit/translate.py index efc180d1..3312c7d0 100644 --- a/src/View/BoundaryCondition/Edit/translate.py +++ b/src/View/BoundaryCondition/Edit/translate.py @@ -41,7 +41,7 @@ class BCETranslate(BCTranslate): "BoundaryCondition", "Mage hydrograph file (*.HYD)") self._dict["file_lim"] = _translate( "BoundaryCondition", "Mage limnigraph file (*.LIM)") - self._dict["file_lim"] = _translate( + self._dict["file_ava"] = _translate( "BoundaryCondition", "Mage rating curve file (*.AVA)") self._dict["file_all"] = _translate( "BoundaryCondition", "All files (*)") diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py index 1946706f..90ced991 100644 --- a/src/View/InitialConditions/Window.py +++ b/src/View/InitialConditions/Window.py @@ -314,9 +314,10 @@ class InitialConditionsWindow(PamhyrWindow): def _import_from_results(self, results): logger.debug(f"import from results: {results}") - self._table.import_from_results(row, results) + self._table.import_from_results(results) def _import_from_ini_file(self, file_name): + logger.debug(f"import from INI file: {file_name}") self._table.read_from_ini(file_name) def move_up(self): From 706a900c8ece1d2fba90df0046443201c601948d Mon Sep 17 00:00:00 2001 From: Theophile Terraz Date: Mon, 29 Sep 2025 15:25:35 +0200 Subject: [PATCH 9/9] work on rubar3 --- src/Solver/RubarBE.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Solver/RubarBE.py b/src/Solver/RubarBE.py index bf946f42..448ace6a 100644 --- a/src/Solver/RubarBE.py +++ b/src/Solver/RubarBE.py @@ -74,10 +74,10 @@ class Rubar3(CommandLineSolver): ("rubarbe_tf_5", "y"), ("rubarbe_tf_6", "n"), ("rubarbe_trased", "y"), - ("rubarbe_optfpc", "0"), - ("rubarbe_ros", "2650.0"), - ("rubarbe_dm", "0.1"), - ("rubarbe_segma", "1.0"), + #("rubarbe_optfpc", "0"), + #("rubarbe_ros", "2650.0"), + #("rubarbe_dm", "0.1"), + #("rubarbe_segma", "1.0"), # Sediment parameters ("rubarbe_sediment_ros", "2650.0"), ("rubarbe_sediment_por", "0.4"), @@ -167,7 +167,7 @@ class Rubar3(CommandLineSolver): it = iter(params) line = 0 - while line < 29: + while line < 25: param = next(it) name = param.name value = param.value @@ -277,19 +277,20 @@ class Rubar3(CommandLineSolver): f.write(f"{ind:>4} {rk:>11.3f} {n_points:>4}\n") - for point in profile.points: + station = profile.get_station() + for i, point in enumerate(profile.points): label = point.name.lower() if label != "": if label[0] == "r": label = label[1].upper() else: - label = label[1].upper() + label = " " else: label = " " - y = point.y + y = station[i] z = point.z - dcs = 0.001 + dcs = 1.0 scs = 1.0 tmcs = 0.0 @@ -444,10 +445,10 @@ class Rubar3(CommandLineSolver): z = data[profile.rk][0] q = data[profile.rk][1] - # height = z - profile.z_min() + height = z - profile.z_min() speed = profile.speed(q, z) - return z, speed + return height, speed def _export_hydro(self, study, repertory, qlog, name="0"): if qlog is not None: @@ -470,7 +471,7 @@ class Rubar3(CommandLineSolver): for bc in bcs: f.write(f"{len(bc)}\n") for d0, d1 in bc.data: - f.write(f"{d0} {d1}\n") + f.write(f"{d1} {d0}\n") def _export_condav(self, study, repertory, qlog, name="0"): if qlog is not None: @@ -493,7 +494,7 @@ class Rubar3(CommandLineSolver): for bc in bcs: f.write(f"{len(bc)}\n") for d0, d1 in bc.data: - f.write(f"{d0} {d1}\n") + f.write(f"{d1} {d0}\n") class RubarBE(Rubar3):