From 1c282000c8dab1f3d0e4a6523353ae481438b269 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Sun, 14 Oct 2018 23:09:54 -0700 Subject: [PATCH] Fix flicker issues on the balances and transactions tables --- application.qrc | 7 ++- Ubuntu-R.ttf => res/Ubuntu-R.ttf | Bin res/connected.png | Bin 0 -> 9498 bytes res/loading.gif | Bin 0 -> 802 bytes qt5.natvis => res/qt5.natvis | 0 src/about.ui | 38 ++++++++---- src/balancestablemodel.cpp | 27 ++++++-- src/balancestablemodel.h | 8 ++- src/main.cpp | 2 +- src/mainwindow.cpp | 19 +++++- src/mainwindow.h | 4 ++ src/precompiled.h | 1 + src/rpc.cpp | 102 ++++++++++++------------------- src/txtablemodel.cpp | 14 ++++- src/txtablemodel.h | 6 +- src/ui_about.h | 48 ++++++++++----- zcash-qt-wallet.pro | 8 ++- 17 files changed, 179 insertions(+), 105 deletions(-) rename Ubuntu-R.ttf => res/Ubuntu-R.ttf (100%) create mode 100644 res/connected.png create mode 100644 res/loading.gif rename qt5.natvis => res/qt5.natvis (100%) diff --git a/application.qrc b/application.qrc index 23e792d..3979228 100644 --- a/application.qrc +++ b/application.qrc @@ -1,5 +1,10 @@ - Ubuntu-R.ttf + res/Ubuntu-R.ttf + + res/connected.png + res/loading.gif + + diff --git a/Ubuntu-R.ttf b/res/Ubuntu-R.ttf similarity index 100% rename from Ubuntu-R.ttf rename to res/Ubuntu-R.ttf diff --git a/res/connected.png b/res/connected.png new file mode 100644 index 0000000000000000000000000000000000000000..4feefae8cd9dc5fa9276ea9136cec0a917e83603 GIT binary patch literal 9498 zcmV+#CFR zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3=Cl^i*ih5y5fH33?f19{GPu;%Y~kx`PW*|X$K zXH{lo1n|Ta0BH9A{^ywg;ZKPro0v+?EoaN0*kbdYAF6%*dA&Lt?|<)~{k-z~m-o&4 z2cEYAui^D;-p}=&_tVE0N_^fQU*9)nKKH55jXrLC{{%f*KR?&i=SIQ5-gnRMraj;5 z@zZpk|NHse_PP1@-(w*dD{;Tzjo-lq%YU<;5*R_Kq3gZ-->8dt?a%um#Gl8`y#M$u zc<(=bi=FMy`{8RSjLpvl`CE*h_g(t-et3V3|1u)?@#HTbxaFq({O42b&RO-G{hD2m znMh^xOzLea_a`nKgfiT(W&RfapZK}lzm30@DNZuB$mZbhG_E;MWRHuCp}XVueVuMH z#OSv#ym~*0xZbOw_~z$LO4MI>doJm z!(a2WH~-Dw_Zyv~*g9wHd#o6jS4}evWlsO)DiY$(6Vr6#d;gkGbz?szHju$|!(5qQ zx8rq-k=#dZg`4NVb;(9!U#;QFdTv07cy?kiE|3A6T}UoFTf8sM5ywh?IwSX#{U8G_ zCBK|Gojq>w`)H7#_K6=R})O03jSPa#E=xnyBfF9FC(C6`iaX{FatV@);JQfqCsH{SvfmRfGbwAxzhoriXA-T8Lsir$AG zVZ@O}9%a9e3J!mtA+;{ZMNsoOsg7 zr<{7)>F-&4vidb^?px-5pEdVnO&N>#y7G}V-Y(_s7EW-Ilru8sqa))*8K9uOa%QWG z(JOPxnQfk?NS>^@q~t88jFG{(olnQT=k6nOzs;LT@vrjcf0a3-)ct>C&M0+H=6=lE zPqMc9Wt4Ceq%KrUZ8!iM7wp=7?c$_AzxJIOTHFksk%criQ!dM_ba=C-)x#i8J!Lx@ z%n^xjan0LY)`SRC=zcIie`=!W@~FP&)0iS)OT0|%eU-y+eUg#sTa0V&zUGO<%+Y`w z_)M$h)(+(~0nyx;&B`N%ML$Apc^?zT8N`@kIctYecuI4*?7g{P8O$T_y*dxjn%kMl z$9i02cuA#5AxnTvVW;kKd?=$hgQ>aqPy6R4oI zQ*DfL6tWpQNYx1WZgF_$!#^=B_Sh>av_X4v(SxHQUjtlLY03#`uSV z)Y~4#uH$&bo*H%T#CS5fZ1-AcWIq+h5b7>28S0a(N||xBN;n6xO%!!(ZB3PZC#}T6 z)ir&ha7&mugk|~m%(Ma5asOywL()212vc-zNXJX(F1aK_aJQRq35B}Vgfz?QL}&FlX0Hu!nqwp$X9v)gqoqP<>@|TLPnX9` zM^w{KD$AGY%XSngHwnNVLDlGb9eJnb55+`NxV(JK@E1UWl7S+*Aw^r-bOx0$fUZ(p zQM$vLb24f|ni@TFH1-%;Pn4mcG{nv%*6L-0G1C&2bZR_iQoC-|?GMb!yF!C9M_QYq zO*9l!Eo#KIMw`u|Nt|nE%mNa10?^Vtt2vYBww`*)Dx8)_22Oo##m5GyrfGMNZ8z@Q z2~!*NaH)W%Bc!9y!|T$=Has8>Wlk8MZZZL%w^t8doJ6xHkj?s|$R*n1*sunn$)rg2 zo{z~V)I&{`gf>o*&X7E)y*Dt#sWqS~U_NA^oHybMdL(Hmr6=H~pjua(W`n=bS7|sA zMr8r;OsV<~H4w61QQ%`apo7|KjmFpr#hPeFh=m3RDLj>DLR!m{j&(xX2?%h7B08-O zdrO9r2c{!|R(BCIxWW}^g*?Mzb}&Z(#sRfFuh|`LqQgmXxuL2Gj>gSaT}MKB z5lbJbNALuGo6(VN9t34KD7TSYN{`@_KvY{VqwSU5P|*O)w*cN6d&D0g-BQ$GqstcG}Xf*i}cyXJ9&HzAB8G){7kQjJ>#m1JW z9l5UBCQaEVW56J+6`-Q)MTrz+b{Ejx%Fp~!2A>K!2N+HI*s~R{@{~bKBRj94fvU+2#RSJZHV-- zx624Ky+c2u89NM2QEh50SQ-xVa}KODV%073-X6onmtCMmj<*2HUKN^+m~^BiqOG=! za+rzAK_P~LpvtI+O%c*EQ(@cmn%gzfyrWKo2Qa)nPM4Kz>8^u9P^R z`1Mx~$lBWv_mxQ6v(X#<5E5ZC8Yzp#6P-&JBOqEiM5ZaR9hMX}FbVt`PL=wwZb1E2 z7N7_R9V^tIkujZI(NB6k@@39wb4((;>j;P#!!4A6jKp|t6Poi)M{1dC7R83#m$-i7S|`3djR^k?oJ*P{P~pp#(}>$w1Is!W<}psPTHW4c1K z7We`0ZI~d9aVTw7J0pPKQOI@5F{#c4A&as-u2X-5XkX22k0G)`VJJ9k=LVt+71;dF z6AApFFlwy=EgfY6J|eDy1&J*h(6xwVst}t2li+Czcm5E-u{Pk2yy;R2s13;@qDM($ zT<9Q(9mx%zvY7|S&g7}MGxqHfu^g-`Igav&5>ZU*_q7X9l2M}*{)SUMk_oS7 z5+zb6h@#I1y%QQ1ztB|yoiZDlLns`O0QD0Fnz*Gp0=#$c<3dr`W;eiu3wv%b8l4NK z&Wfwkb``~IsbQ7-` zwTOq#SlD4P6QxOqi2a+UOfn}n79C=UpxTsb#Tao-lLLag%0$FaU)?V`JeUGtrWm~H z!A2sBX2(Jna6~%8bXgrOoWMSls>cK*RRjD+kOt&W06|1hhx=khF z>*h6Hp1Dh>44$ObGEfVt4lG(k#LmdjjDU?3lSFfne&hwDMdLxO5H4CJ;$-1!6aZa< ztRe7p?eR1Uh73IcAZZw{X`)%~Pv$RD|K$}mpRgK5nZN=M14kg;5#LPljn)pFARj#14HfRDgTF_y>dg_T2fp$8rI9qB(3LY-J4)eg!8fs0zK zbTzVK_v~&KN$PTss=jKmFTYj+K@MC~S&TDcnGU`{)#oFD@_r7OLzS(xgfT`h{e57Pba{c0}`4 z`Tie1t!JI0PuKlKY(zmx8=@IhWYh)Xbh|?NB{;D!YX}flA#C^unL^nk3{RmF(MI?f zND-k(V_=-?%>tBQYH+SlC&&YGp|+u?jZ;fnB?*mRX9h77!=g3! zAzvu}e60rF@xZFDa2n!SW5zYfkb+w{4$6OMQOClwskeY~M45N=?HV*ADry!yus`i4 z6Dz(_HYLo$SYc?~cSmwig1~2PlnmlRK8+x%-?XMxU(0G&1|MuQRVuO^Z5d5cYd1_? zl(;M?=C~gUTZkRdj3sJ0YDpSsK{6h=M79Bi-aLdnVUlS`Z*gIuJBCU=tU&A|rMKHg zEgjh7ly%@4oN`UrVMoB%pll90dTN0c89fc^6e4y#odr?NR}?FX`!`jbu06nrA!NDB z5)_%ASw5cVnHDq8IFAeIMUekin-@e!!y^H?cNB=x57d2uE-DlPi+CUX+6ilgqya+fXaoJV9V?!3|vfc>{ zsu@sX+($+Rbz=M2I8t8bGe)Ufs!yxOXqn>d>>ZGA0M8s=*>HD|DS&`j(6uXsfR6V( z>Q%e$-1^K2sjfhnuhmF**39#;_sAEwb3|2x_f>1avw$Nw)JjIx;0b!01b*${48Hv^H@Y(s0tfb!N_UB5!B4vRD!wKnPq-+DT5 zkkSEXC(5Vb`q0HrI~JHr8xa&oi_<&F{L(R3T8&|HO`^oW=LpLIl%umm^bO=1C}<3@WbU?IY!&{(pLerKlLdn!goR4BE~WG3m?HGHfg;j{i26c)oQR`8N)tWrS54^ zTBQ)|EmbTeprEipFP6ceJF1xrnK3PYF*;bBK;})tB%vqh4)5&T4I2=qjd1Mbh8Bkx2w^@A{S@V0Nf# zDd9#!LBTB_hfewi)vJ~Om?7*nJzAXGL}JX2MY-jk&i(gMG-;J;uspcY@G zWT{l?7fxp8@*v`zSSBjFFxRJRe_XCLpWbK|>+3TuNv(Sr0u>e0(URGw8VL?Pk7gVP zH--i#$F!^+G^G~C>ESCMo4U4C%yozKvgh|BQR3)&8FFnlpbJr<337qu)Q3R3dJ8f( zV2o@HosILf+V&gWdFq9p7uRH(jTFpguRBC8Uq|V+&c>ZV4dgHpH*#oNz)lnx(iL6B zYq5n9<^ZE6iado2+L#3)5`~*`KFo+TP?fY$uHHoWUdtDG(E|+vMAuu`Enx-P@=fmn|6gC2)UZZQ!7}_DYPB(b`FIq=ImeF;dN0-S5xk8oz9;LIMH8h?>I z`T^znt8T~Q(nWM&7yy!*=5~Jg)cK_97)(nUzs3(5HTH^Ct^G(ifa}@^(gqCUM7$|e zXt`#nW;OfJR8J3D@Ubd$och4pA3Pb6eKk*eYaXHl6*BV=scNoP)n-t5>z>JghkIQG zq4m#-w!c$a{ziu8P0==}FsN+K7*G5BRri?Rw9gL>73csA??} z0vy^MPufjSSlw{fpO{e~{jMZ24UIxs&qzi#YS#d|;gA9h$u8RGrB(7#dP~rHepa(s z?VM|KL8kd_Jt~ZQb^#3@Y&{0G(WjQP7vZ$ywMOW8YzdS|h@sl89Ve&xcj(2>xC?WK z${UzVuPwTe7NKPOzN?XU2d2rUZ*ZO=3~l^t;%Ev73)26CuY1SzPKWVL|trXL% zMX0xD5wuM#L=4&hMV|!B96`YW2MZ2)x!k&s6GioJ>$yK)tkWhvRR|{6)W9<60y(^~ z1t`;Z=C&`f28tk1z$5>x98kd87QXlTM{?`StJc_12lqG1Xi zg)y^pLPj`6yK6Ghye`5XtMOt`*R;Ip$Y|3(P11>xoFa`4%;9aR$wk;PMhGpJ@geA> zIUOuo5@m zeUh)1+TS2chRJ9oDxHGN8zt)$R7i>L-jQm{Jy(~wT2V<)6LAxT_~H-Z?XDD$(Y z!d+@Ex&>x{jU$Sm|uMWb5DO45paVwgT_J)O1AZ*W-YXlt_la`D+_UV znu9hU0y+WWj)V}~2@w!eOb{i{H&J<3`&y*|Y%x4hT=_kUhFZ|+9q&;M2qJCKKqtrx zP_)Gzs5nU}hg{sw9&PDh>4Jl@w3P)A-lZsSbWTEtXXyrUj~2jnc&-&HNoPrPFsr$W z3PdnEWPHSBcbo_|IDs*VVUzY{nsx#xvR~|Iee7&ug`K8_Lc(3xj#QEL*^EMmhK<}8 zaw*oRT3zS|e}OqAsR_4fZdArdgki<% zsq@A}rt08_cIm^qH^X8}gxo!Ql*5Eiwe%j)*JEqn9L0F| z&6EFflED1CZCULaiL|BRzzNzL<0mdZrH$9Vh}SGE@0|dEk5eQ{ z?Ab>r+jTy&N&1151$F1ORR9}-HH6?E^cgyB=2WZ&oCG}u%aHD-Fl*5n7VtEqDsd8~ zq2ZI&$vmwu5S5^oj%XlAj5c%{x&fPFi}o>* z=_<~&IDAkf|{9>+BcPKa`B)T7NrFN58Jv)?Swmoq5?7{~S7t zwG|zZzh};jNBPz8Iu6siR^8<^QS>l>EV6A?n~aTOC|H5z5wx@ae9NasvGdkHJ;}8X zo{SYfYesuu=-6u3i7%eJB-ZArT9csOFfI3-Q0_f#ptc5WnL6oJlzy#ZHGl(*S;(Js z1_B8N0j8&0RnCbj)VYsSbmWdSY`E2E3iN=}spWjN0x3Q;5b43^Y0+v3EO3P3Xdk(^ zTbGBsl1|j=%-Zij`jH_4A*pFveS}CG)3r2;R($Irop_glG*FFssSkvb^b#`M*(td1 z(J*%z%y^geGh(l_8Va?4g4Kanz#DIt1dQ5&C1H3jg5*3}IS(sID}iIcWWWg5QM5IR z(!^S58Dr3o(hZZ6gh*d2vRXiNcas3G1CiLA6D?Lsa|SGV2_L z-+%Y@k8hj*?&}|)n6F>gQZxO&vD6+-kC95fFKPo7Qg!NCM{bVG=b9Z@PcO`UMYBqN z9q9b>01E#;f!n_x|GUriFBXcKnW_rfFF^o=p0uo}t&XwQ!m%qi6Kp`DXGs;B=b#d% zcKQa4gcx`o#x{q#EIM`cb{ZSObJ?~jH7TWQS6>$(|F#$2) z?i*_&;?CEPzkZ6to&*OW7-Y&TN(33osOVKQ=R!Q|3^wzi_1m(@KW*Mn&CMe1itydv zQ`lhHK?iluZ3J^!3)4_j!9kWm#gjfj4%_$)=zTcESOfYz*q?niXc2nr(0?JE5fGgV zfOe=p#~Zxx-C6W666R}PbkM&Dc09&LRu&yU0|pX+X8?)>*j4n84xH#fO%KIel}BhE zd~Fg3<4+}G{&WEka(HX=UkcAb36f^R+^=0NNj9&{>k{%&CR~m>k3T1$_ zm1(D|+dbEUQF*G)=}3*L?rtJ#@zanRuT?Isgca@Xo;ZstPQZP1P6)StwVaN9NJF1# zZyoI&`p2i{XCG%7@QB%7_uo-q31DwD7gkkU_X9^m>&=pCM|>#|^8&!(>5 z#E;Xjn%1>0@F?{F0004WQchCRCwC$o!erYIuJ#rNF5|!hyi0T zaO~Li|9|5lj+>^f1qgH*5%yDFnzFJbjV_}RA&V9*TC`}@QHy5l;Q)SYDPdY|xH!YNM>PsSVFyLg2dK72Yr#OvQz*elW3z$mkTQao?7z^rOBDS|rAvnb# zE-Z~VM?tYj9IdRBfZ`DpGY7PRSTKr9teCZf=3QLl18fo3Cc^~9D1$+RbCiUf8k@=B z1Z)uv&2Cabu}T=3qc)P_mHZj{dayq%PF^praRau9Q)33juW5iKM-Rv+ZBJbx01u~Z zGVT}+L2Ufo=D>p>*2s1;sSyt9C#j;^I!>iKC^}I$ffX45ip_nIpW|<)zde_j>0wh#G0s0=9_Ka5Du|4!-M67;UC_8fo+Ze0kB# zBj{!31R)ZX@J*v2d%l{Kz;w{bw#-1{cx0!YQ}`Q;cs7eLAzL_3LK0Z_H0=w(V1*#J~c zYJ6-%S#eOg8Fk_)95j*l$xlc!*DX0nRf#pz5`{*D8fFd91|h4o3-ee6v_QzRm!0N) zXq$lM38Sq2K0QRMfQqE=@goh(?q8^b2sQy#W9jI47-f%d9A3c2R+#9Hhhyh7tp5DU zp)NjiFfkac6my!9^HP?5`OaZ3Mpm1sdR{tiZSlpyp)T5XP`S1kwLXOUuW#*l@yRH< zU74LvDb|N$*7&0O=WF|1WY!&2uJK3h)9|$>BD38G@B1{F!M!%nLv#YD+G`uRU#f-p zWRTe==GQc;`|BeUyq_T|hMUNVgUUVc(fQA8sEgoWkhv={efBiaMOO~0&z{Dg9}en^ z&Ky*qA5Pfx9^j&bK>ryIuNKbnd;20QTshcvIcUn^Q%^&E2Dq}d^#yir|8^oe1?;#H zJS`{c3F3bbL@1mD`dE2v!D+JF6{_x@pKCT-|>(Ae5{ za6oMgLn)YW^x~j;6Uuzfi8y-bgM;pJ*QRnX|8~&{;E?7pCJK}C4X)y4Sg z;tw|k;0D#jFj(8nBVrRp*nJKV0{{+`Q9Hcx^i&vn-?apu)VwZ!&wo= zm5*|5t&6T4)F{|y_KVz=(d5I+CWcu^NvCjPpw+%~DtU{UTNq|JEUo&b-=GHV{Obq@ zSPNSF39r!VdF#L9u??&y`-ta|tB~rnj(h(hpuuM3<6Y~3-nSU}BvLSSKE>#ly8>ya z6CRkG|64&}yi)>uGC{L{v+EnYyY>y<&YS=Hhiz1x`x}Y(osI#)ZggVq6&9H!$k~l}(YAEL$XU51zEs5a0|&$f z@u`g3?T(UW#J4JLFLDT85e%xh9UrB@!FSIpPQdh-!y&m6OsY>trvN-U)dZV%4L4+D z`+J%lL8&@rVsaU0!P1%_);^yC+2ZAUf?ioFU<4&^|5ciiKvbMhOoy_iW2bXL!ctL{ z6k1H)a|S2?Xjz3u_c=E&u9uug08+H5{6TyFNeBrL@%(Zvwj_A%imW%yPQ!vFvP07*qoM6N<$g83WxhyVZp literal 0 HcmV?d00001 diff --git a/res/loading.gif b/res/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..891c0f88c8c57e5e82db85a119e66cee9f1f1c09 GIT binary patch literal 802 zcmZ?wbhEHb6ky^kv0}xZJ$ufbJ9qEiy(v?sym;{;Ww7u3PTCdvDb3Dx66`_rhfsuiQfgPxgYr_&pm93@ERu{6MO0$8b`9I8< z#5VEDqbl|Lv&7R}z-lJ6ZNk6CgWTq!5F zYRYVWA#J~7b=KxNsUDr+&_#E<3Pf{qYhUD%rKvzyKMt;2I3Z8AyYKbOeWkxwZOr`( zu@ya9Dialog + + + + zcash-qt-wallet + + + + + + Version + + + + + + @@ -23,17 +39,17 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright (c) 2018 Aditya Kulkarni. (MIT License)</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Special thanks to:</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">JSON for Modern C++ : <a href="https://nlohmann.github.io/json/"><span style=" text-decoration: underline; color:#007af4;">https://nlohmann.github.io/json/</span></a></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">QR Code generator library Nayuki : <a href="https://www.nayuki.io/page/qr-code-generator-library"><span style=" text-decoration: underline; color:#007af4;">https://www.nayuki.io/page/qr-code-ge…</span></a></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Made with QT : <a href="https://www.qt.io/"><span style=" text-decoration: underline; color:#007af4;">https://www.qt.io/</span></a></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">LICENSE:</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</li> -<li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Software is provided &quot;as is&quot;, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.</li></ul></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.1pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Copyright (c) 2018 Aditya Kulkarni. (MIT License)</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Special thanks to:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">JSON for Modern C++ : </span><a href="https://nlohmann.github.io/json/"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#007af4;">https://nlohmann.github.io/json/</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">QR Code generator library Nayuki : </span><a href="https://www.nayuki.io/page/qr-code-generator-library"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#007af4;">https://www.nayuki.io/page/qr-code-ge…</span></a></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Made with QT : </span><a href="https://www.qt.io/"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#007af4;">https://www.qt.io/</span></a></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">LICENSE:</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:11pt;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</li> +<li style=" font-family:'Ubuntu'; font-size:11pt;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Software is provided &quot;as is&quot;, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.</li></ul></body></html> diff --git a/src/balancestablemodel.cpp b/src/balancestablemodel.cpp index f6f5e08..11de043 100644 --- a/src/balancestablemodel.cpp +++ b/src/balancestablemodel.cpp @@ -1,21 +1,29 @@ #include "balancestablemodel.h" -BalancesTableModel::BalancesTableModel( - QObject *parent, - const QMap* balances, - const QList* outputs) +BalancesTableModel::BalancesTableModel(QObject *parent) : QAbstractTableModel(parent) +{ +} + +void BalancesTableModel::setNewData(const QMap* balances, + const QList* outputs) { // Copy over the utxos for our use + delete utxos; utxos = new QList(); // This is a QList deep copy. *utxos = *outputs; // Process the address balances into a list + delete modeldata; modeldata = new QList>(); std::for_each(balances->constKeyValueBegin(), balances->constKeyValueEnd(), [=] (auto it) { modeldata->push_back(std::make_tuple(it.first, QString::number(it.second, 'f'))); }); + + // And then update the data + dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1)); + layoutChanged(); } BalancesTableModel::~BalancesTableModel() { @@ -25,6 +33,7 @@ BalancesTableModel::~BalancesTableModel() { int BalancesTableModel::rowCount(const QModelIndex&) const { + if (modeldata == nullptr) return 0; return modeldata->size(); } @@ -36,6 +45,14 @@ int BalancesTableModel::columnCount(const QModelIndex&) const QVariant BalancesTableModel::data(const QModelIndex &index, int role) const { + auto fnSplitAddressForWrap = [=] (const QString& a) -> QString { + if (!a.startsWith("z")) return a; + + auto half = a.length() / 2; + auto splitted = a.left(half) + "\n" + a.right(a.length() - half); + return splitted; + }; + if (role == Qt::TextAlignmentRole && index.column() == 1) return QVariant(Qt::AlignRight | Qt::AlignVCenter); if (role == Qt::ForegroundRole) { @@ -57,7 +74,7 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { switch (index.column()) { - case 0: return std::get<0>(modeldata->at(index.row())); + case 0: return fnSplitAddressForWrap(std::get<0>(modeldata->at(index.row()))); case 1: return QVariant(std::get<1>(modeldata->at(index.row())) % " ZEC"); } } diff --git a/src/balancestablemodel.h b/src/balancestablemodel.h index 588294c..c0824ec 100644 --- a/src/balancestablemodel.h +++ b/src/balancestablemodel.h @@ -8,17 +8,19 @@ class BalancesTableModel : public QAbstractTableModel { public: - BalancesTableModel(QObject* parent, const QMap* balances, const QList* outputs); + BalancesTableModel(QObject* parent); ~BalancesTableModel(); + void setNewData(const QMap* balances, const QList* outputs); + int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; private: - QList>* modeldata; - QList* utxos; + QList>* modeldata = nullptr; + QList* utxos = nullptr; }; #endif // BALANCESTABLEMODEL_H \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bc1cbb5..61f1ff5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); #ifdef Q_OS_LINUX - QFontDatabase::addApplicationFont(":/fonts/Ubuntu-R.ttf"); + QFontDatabase::addApplicationFont(":/fonts/res/Ubuntu-R.ttf"); qApp->setFont(QFont("Ubuntu", 11, QFont::Normal, false)); #endif diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5095d79..8a8211a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -21,8 +21,19 @@ MainWindow::MainWindow(QWidget *parent) : settings = new Settings(); // Status Bar + loadingLabel = new QLabel(); + loadingMovie = new QMovie(":/icons/res/loading.gif"); + loadingMovie->setScaledSize(QSize(32, 16)); + loadingMovie->start(); + loadingLabel->setAttribute(Qt::WA_NoSystemBackground); + loadingLabel->setMovie(loadingMovie); + + ui->statusBar->addPermanentWidget(loadingLabel); + loadingLabel->setVisible(false); + statusLabel = new QLabel(); ui->statusBar->addPermanentWidget(statusLabel); + statusIcon = new QLabel(); ui->statusBar->addPermanentWidget(statusIcon); @@ -65,7 +76,11 @@ MainWindow::MainWindow(QWidget *parent) : QObject::connect(ui->actionAbout, &QAction::triggered, [=] () { QDialog aboutDialog(this); Ui_about about; - about.setupUi(&aboutDialog); + about.setupUi(&aboutDialog); + + QString version = QString("Version ") % QString(APP_VERSION) % " (" % QString(__DATE__) % ")"; + about.versionLabel->setText(version); + aboutDialog.exec(); }); @@ -272,4 +287,6 @@ MainWindow::~MainWindow() delete ui; delete rpc; delete settings; + + delete loadingMovie; } diff --git a/src/mainwindow.h b/src/mainwindow.h index 8e4b610..d94fe5d 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -25,6 +25,8 @@ public: QLabel* statusLabel; QLabel* statusIcon; + QLabel* loadingLabel; + private: void setupSendTab(); void setupTransactionsTab(); @@ -42,6 +44,8 @@ private: RPC* rpc; Settings* settings; + + QMovie* loadingMovie; }; #endif // MAINWINDOW_H diff --git a/src/precompiled.h b/src/precompiled.h index 1eb8519..2d18169 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc.cpp b/src/rpc.cpp index 238e3cf..4c6c572 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -9,6 +9,19 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) { this->main = main; this->ui = main->ui; + // Setup balances table model + balancesTableModel = new BalancesTableModel(main->ui->balancesTable); + main->ui->balancesTable->setModel(balancesTableModel); + main->ui->balancesTable->setColumnWidth(0, 300); + + // Setup transactions table model + transactionsTableModel = new TxTableModel(ui->transactionsTable); + main->ui->transactionsTable->setModel(transactionsTableModel); + main->ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); + main->ui->transactionsTable->setColumnWidth(1, 350); + main->ui->transactionsTable->setColumnWidth(2, 200); + main->ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); + reloadConnectionInfo(); // Set up a timer to refresh the UI every few seconds @@ -16,15 +29,15 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) { QObject::connect(timer, &QTimer::timeout, [=]() { refresh(); }); - timer->start(1 * 60 * 1000); // Query every minute + timer->start(10 * 1000); // Set up the timer to watch for tx status txTimer = new QTimer(main); QObject::connect(txTimer, &QTimer::timeout, [=]() { refreshTxStatus(); }); - // Start at every minute. When an operation is pending, this will change to every second - txTimer->start(1 * 60 * 1000); + // Start at every 10s. When an operation is pending, this will change to every second + txTimer->start(10 * 1000); } RPC::~RPC() { @@ -276,7 +289,8 @@ void RPC::getInfoThenRefresh() { .append(QString::number(reply["blocks"].get())) .append(")"); main->statusLabel->setText(statusText); - main->statusIcon->clear(); // TODO: Add checked icon + QIcon i(":/icons/res/connected.png"); + main->statusIcon->setPixmap(i.pixmap(16, 16)); // Refresh everything. refreshBalances(); @@ -337,17 +351,9 @@ void RPC::refreshBalances() { }; // Function to create the data model and update the views, used below. - auto updateUI = [=] () { - // Create the balances table model. - - // Delete the old Model, because the setModel() doesn't take ownership of the Model object - delete balancesTableModel; - - balancesTableModel = new BalancesTableModel(ui->balancesTable, allBalances, utxos); - ui->balancesTable->setModel(balancesTableModel); - - // Configure Balances Table - ui->balancesTable->setColumnWidth(0, 300); + auto updateUI = [=] () { + // Update balances model data, which will update the table too + balancesTableModel->setNewData(allBalances, utxos); // Add all the addresses into the inputs combo box auto lastFromAddr = ui->inputsCombo->currentText().split("(")[0].trimmed(); @@ -355,7 +361,7 @@ void RPC::refreshBalances() { ui->inputsCombo->clear(); auto i = allBalances->constBegin(); while (i != allBalances->constEnd()) { - QString item = i.key() % "(" % QString::number(i.value(), 'f', 8) % " ZEC)"; + QString item = i.key() % "(" % QString::number(i.value(), 'f') % " ZEC)"; ui->inputsCombo->addItem(item); if (item.startsWith(lastFromAddr)) ui->inputsCombo->setCurrentText(item); @@ -376,9 +382,6 @@ void RPC::refreshBalances() { } void RPC::refreshTransactions() { - // First, delete the previous headers - delete transactionsTableModel; - auto txdata = new QList(); getTransactions([=] (json reply) { @@ -395,12 +398,8 @@ void RPC::refreshTransactions() { txdata->push_front(tx); } - transactionsTableModel = new TxTableModel(ui->transactionsTable, txdata); - ui->transactionsTable->setModel(transactionsTableModel); - - ui->transactionsTable->setColumnWidth(1, 300); - ui->transactionsTable->setColumnWidth(2, 200); - ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); + // Update model data, which updates the table view + transactionsTableModel->setNewData(txdata); }); } @@ -418,6 +417,14 @@ void RPC::refreshTxStatus(const QString& newOpid) { }; doRPC(payload, [=] (const json& reply) { + // If there is some op that we are watching, then show the loading bar, otherwise hide it + if (watchingOps.isEmpty()) { + main->loadingLabel->setVisible(false); + } else { + main->loadingLabel->setVisible(true); + main->loadingLabel->setToolTip(QString::number(watchingOps.size()) + " tx computing"); + } + // There's an array for each item in the status for (auto& it : reply.get()) { // If we were watching this Tx and it's status became "success", then we'll show a status bar alert @@ -425,20 +432,18 @@ void RPC::refreshTxStatus(const QString& newOpid) { if (watchingOps.contains(id)) { // And if it ended up successful QString status = QString::fromStdString(it["status"]); - qDebug() << QString::fromStdString("Watching opid, current status= ") % status; if (status == "success") { - qDebug() << QString::fromStdString("Success, showing status message"); main->ui->statusBar->showMessage(" Tx " % id % " computed successfully and submitted"); - + main->loadingLabel->setVisible(false); + watchingOps.remove(id); - txTimer->start(1 * 60 * 1000); + txTimer->start(10 * 1000); - // Refresh balances to show unconfirmed balances + // Refresh balances to show unconfirmed balances refresh(); } else if (status == "failed") { // If it failed, then we'll actually show a warning. auto errorMsg = QString::fromStdString(it["error"]["message"]); - qDebug() << QString::fromStdString("Failed with message") % errorMsg; QMessageBox msg( QMessageBox::Critical, "Transaction Error", @@ -447,47 +452,18 @@ void RPC::refreshTxStatus(const QString& newOpid) { main ); - txTimer->start(1 * 60 * 1000); watchingOps.remove(id); + txTimer->start(10 * 1000); + main->ui->statusBar->showMessage(" Tx " % id % " failed", 15 * 1000); + main->loadingLabel->setVisible(false); msg.exec(); } else if (status == "executing") { // If the operation is executing, then watch every second. - qDebug() << QString::fromStdString("executing, doing again in 1 sec"); txTimer->start(1 * 1000); } } } }); } - - - /* - [ - { - "id": "opid-ad54b34c-1d89-48af-9cb5-4825905fc62e", - "status": "executing", - "creation_time": 1539490482, - "method": "z_sendmany", - "params": { - "fromaddress": "t1aWhRh9JNKWzpzjn2gmULDJzfKLC724EPS", - "amounts": [ - { - "address": "zcVHg9euUSQF8ef7ZXztrv4LcdC1mytEUYLuoj4W5iSygLFYjm1yQCggAYnnydUaHLy2GBaxF4PX5vjaJjnj2Lq3ecQtGF4", - "amount": 0.0001 - } - ], - "minconf": 1, - "fee": 0.0001 - } - },{ - "id": "opid-7807e672-7f8c-428a-8587-3354d0ae1b88", - "status": "failed", - "creation_time": 1539490847, - "error": { - "code": -6, - "message": "Insufficient protected funds, have 0.0006001, need 111.0001" - }, - ] - */ \ No newline at end of file diff --git a/src/txtablemodel.cpp b/src/txtablemodel.cpp index 3bcc90c..8f9796a 100644 --- a/src/txtablemodel.cpp +++ b/src/txtablemodel.cpp @@ -1,9 +1,8 @@ #include "txtablemodel.h" - TxTableModel::TxTableModel(QObject *parent, QList* data) + TxTableModel::TxTableModel(QObject *parent) : QAbstractTableModel(parent) { - modeldata = data; headers << "Category" << "Address" << "Date/Time" << "Amount"; } @@ -11,8 +10,17 @@ TxTableModel::~TxTableModel() { delete modeldata; } +void TxTableModel::setNewData(QList* data) { + delete modeldata; + modeldata = data; + + dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1)); + layoutChanged(); + } + int TxTableModel::rowCount(const QModelIndex&) const { + if (modeldata == nullptr) return 0; return modeldata->size(); } @@ -45,7 +53,7 @@ TxTableModel::~TxTableModel() { case 0: return modeldata->at(index.row()).type; case 1: return modeldata->at(index.row()).address; case 2: return modeldata->at(index.row()).datetime; - case 3: return QVariant(QString::number(modeldata->at(index.row()).amount, 'f', 8) % " ZEC"); + case 3: return QVariant(QString::number(modeldata->at(index.row()).amount, 'f') % " ZEC"); } } diff --git a/src/txtablemodel.h b/src/txtablemodel.h index 2d1e014..c461c7d 100644 --- a/src/txtablemodel.h +++ b/src/txtablemodel.h @@ -7,9 +7,11 @@ class TxTableModel: public QAbstractTableModel { public: - TxTableModel(QObject* parent, QList* addresses); + TxTableModel(QObject* parent); ~TxTableModel(); + void setNewData(QList* addresses); + QString getTxId(int row); int rowCount(const QModelIndex &parent) const; @@ -18,7 +20,7 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role) const; private: - QList* modeldata; + QList* modeldata = nullptr; QList headers; }; diff --git a/src/ui_about.h b/src/ui_about.h index e450de0..9e9dbd6 100644 --- a/src/ui_about.h +++ b/src/ui_about.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -22,6 +24,9 @@ class Ui_about { public: QVBoxLayout *verticalLayout; + QGroupBox *groupBox; + QVBoxLayout *verticalLayout_2; + QLabel *versionLabel; QTextEdit *textEdit; QDialogButtonBox *buttonBox; @@ -32,6 +37,18 @@ public: about->resize(497, 448); verticalLayout = new QVBoxLayout(about); verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + groupBox = new QGroupBox(about); + groupBox->setObjectName(QStringLiteral("groupBox")); + verticalLayout_2 = new QVBoxLayout(groupBox); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + versionLabel = new QLabel(groupBox); + versionLabel->setObjectName(QStringLiteral("versionLabel")); + + verticalLayout_2->addWidget(versionLabel); + + + verticalLayout->addWidget(groupBox); + textEdit = new QTextEdit(about); textEdit->setObjectName(QStringLiteral("textEdit")); textEdit->setReadOnly(true); @@ -56,23 +73,26 @@ public: void retranslateUi(QDialog *about) { about->setWindowTitle(QApplication::translate("about", "Dialog", nullptr)); + groupBox->setTitle(QApplication::translate("about", "zcash-qt-wallet", nullptr)); + versionLabel->setText(QApplication::translate("about", "Version", nullptr)); textEdit->setHtml(QApplication::translate("about", "\n" "\n" -"

Copyright (c) 2018 Aditya Kulkarni. (MIT License)

\n" -"


\n" -"

Special thanks to:

\n" -"

JSON for Modern C++ : https://nlohmann.github.io/json/

\n" -"

QR Code generator library Nayuki : https://www.nayuki.io/page/qr-code-ge\342\200\246

\n" -"

Made with QT : https://www.qt.io/

\n" -"

LICENSE:

\n" -"

Permission is hereby granted, free of charge, " - "to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

\n" -"
  • The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  • \n" -"
  • The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the w" - "arranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
", nullptr)); +"\n" +"

Copyright (c) 2018 Aditya Kulkarni. (MIT License)

\n" +"


\n" +"

Special thanks to:

\n" +"

JSON for Modern C++ : https://nlohmann.github.io/json/

\n" +"

QR Code generator library Nayuki : https://www.nayuki.io/page/qr-code-ge\342\200\246

\n" +"

Made with QT : https://www.qt.io/

\n" +"

LICENSE:

\n" +"

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

\n" +"
  • The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  • \n" +"
  • The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the" + " Software.
", nullptr)); } // retranslateUi }; diff --git a/zcash-qt-wallet.pro b/zcash-qt-wallet.pro index d02412e..a00e9bb 100644 --- a/zcash-qt-wallet.pro +++ b/zcash-qt-wallet.pro @@ -13,13 +13,19 @@ PRECOMPILED_HEADER = src/precompiled.h greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = zcash-qt-wallet +APP_VERSION=\\\"0.1.5\\\" + + TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS +DEFINES += \ + QT_DEPRECATED_WARNINGS \ + APP_VERSION=$$APP_VERSION + INCLUDEPATH += src/3rdparty/