qnapi-0.1.5/0000755000175000017500000000000011015004533012223 5ustar patrykpatrykqnapi-0.1.5/macx/0000755000175000017500000000000011015004533013153 5ustar patrykpatrykqnapi-0.1.5/macx/qnapi.icns0000644000175000017500000006547010762222423015165 0ustar patrykpatrykicnsk8is3243IG*@ݙ$ I\,3v$-֪u-W-Ą8eA2 1r }?I / @K trI yߢںD*_V%$pd#!WkqoeE kV(1_U  [;K9(Q L 3: 9+1 - 6,''&' )   s8mkdS =.ܽ 4r+-I^LҿC 97 }UpRy>L=N@"Eq>NU9< =|^ eG t%`y il32G  Qٵ}*MɆŗ8,m2}M1D~.h:N`cnX g^  Gլ“M ! h^H*),C@GS pfh"43 Ёr (^/A+> %B TzxGl'  (MetwuiW; %az~{|zm@ CwxwrZD?@Nfqpr_GvrnC -\ii\4nka  GbbO`e`F[[-9c`-NSJO[O0NLUU1FH*NP?A.HJ7:-BC35' <:/&+//-(.0 3446621133/')+"1.'  $** %# **" $ $#      l8mk9TWVJ#Bu"@ k x_#6 %^{4*a_f# \$"==<%G4וOI/`dw)1il?= QeKoT!v <ދw'\ǰEga r2byVgqk 6~q*NtUߞe]uqdZLth>~y~dZk$  ldI=b'L}cn}2w{5ih32eãw2 fΈk ɐB<ݜn\p؃Z7<6SFA-ʁ ^ց{ڀ0- LxeË5]Y8X%hp}pmV EIjmF r-u,Q$rՀÀ،FU]HAց=$r؀L2Ձ 5j!+`, zE16mmÕu(tۈH( =٤_%(  ! :Ynyyxm[B9s}J;~ Hlr! zqP9/9Nk~~}|z+|YSyxxv's~~}}s"huttsn\zyc Ypo]+wvvug [kj3csrrncggf^!oonn8/cb&HkkjdZ^^]GaggfA8ZZYWcb$VVUU!__^^ RRQQ!([[ZZNNMM&&WWVVCJII*$SSRREFEE#OONN())(BBAAKKJJIIHGGFFEC2 >>==CGFFEED CCBBAA@@=( :998,CBBAA@>53 9==<<;;9")665-?>>==(766. 22111::99 !2 11'..-+6655+ '.--,+**)!2110'))(''&&)--,,& %$##" &('& ! !$$##"!                 h8mk FtR iԅ)#Z{ OҁL##(Kyo GAtqLaIC!0 ;8P8ARRRRD"`8^T(;F-(|`D{$nU+8*7b!ayVSؗxV-'cǮH !| 22222(12221222))nRe;y E}vR[,@ǦxUP`(@JJm (@{ʧF*(B)(;Q)sP=`9_%\\ET4%\\Z;\\\#:\\\\\\Lit32U&6vՕF&fv61֛'Gg WwgשW( ۳2YIyyՖfF&Vyf6z5 Uˏz# UԎT{e=DT".;͋ T~~ :.'"!^V J׉!^?1Љ!G(@Ϩ@`X@׈(Xx(h׼g'GH8WH@آƈ)@7F@&FfF&6'vv69W@ƇGygÈVfw & Jեկhx  وuƆ/ZŋfV6VvOĈ`@0Ս%eej z %e0P 5z Dي&&_  L,<o  .y&s9؋'CN]Y='@=~ [M~'AO~SL?  ?#@דoDߏpP00$_ΐ> Nڎ+ʥ>~**}]M=ٕm-=]̌=  |̄ ~~Q /qwvutp"~}||y)Sutscy}|{icponjuyxw=anmllWMxwvNjmmlkj'(vuttXhkkji_buutse5ihg&tsrnUhhgfXKrqp8 ZfedmpoZedcP7onmnnmZccba jnmlQ%a`/%lkjQ``_^U?kkjiO/^]\_ihg#Z]\[*hhgf A[ZY@*feU$YXUIedcc4XWVV`cbNVUTba``]2UUTS1`_GSRQ=_^]CRQP</^]\.POB.\[Z-ONM-ZY,MLK,YXW,;KJ ,WV+7JIHH+VVUTT*6IHG*TSTS)AGFE*SSRQ)FEDEDQP(DCBBPON2  CCBA:NML( #15DGKKJIEA3!A@A@??/JMMLKJIHGF?.@@?>(9KJIHGFEDDB5$>=<<0JIHGFEDCBB/.==<;HGHGFGFEFEDCBA@@:;:99 GFEDCDCBA@?>=%:98/:EDCBA@?>=8"876(CBA@?>=<;1/7765BA@?51%$%$(35<;<;:9. 5412@?>; *8:98776(432#??>= /8764'210;=<; 26541,10//*<;:2432/. ::98 0210.-,* 872 10/." ,-,+57765' (//.-$'+*)(543&-,+'  &*)(%321%*+*)('02210$*)('&% 0/.(('('&%$%$"(.-,( %&%$#"" )--,+& %$#$#"!! )+*) #"!  (*)('& "! !  (('('&%%#  %&%$#    %$#"!   ##"!  !                     t8mk@ TӴdT$ dߔT%eu0Ee eeff VF1g B2XHxxxXyyySy=C-Ԥddd%%4dtD ;d^>$ S:~^!S :~?b!_!h w(hwxXHgH?G(ghw@'@@G@@@@@@%%%%%%%%%%%@ԤE@u5 @U@Fv#- vYw vg@$*&<8jN^eei @%5UEoUUUUUUuz E% $d* /y\#N&.>}"yݝMbyͭ}nnn.>nnn.#....  {8<<;+^:*M-]\<<<< \{{k؋K K;K{ʫ[[5 KKK[zKK;  +zʚ8X6R%o2 !Vst4K}m +f9É9xs k EPP6@GǥKy/@dENxX@T @l|@;%Nd[WzyyycCݳl,![FK } Y+.OD/vN<_k)Gt=Ev< S2V Vs4SV Vt4'CCCCCCCCCC"2CCCCCCCCCCCCCCCCCC.CCCCCCCCCCCCCCCCCCCCqnapi-0.1.5/macx/Info.plist0000644000175000017500000000221710771423066015143 0ustar patrykpatryk CFBundleDocumentTypes CFBundleTypeExtensions rm mpg mpeg mov avi rmvb mkv m4v mp4 asf divx ogm dat wmv CFBundleTypeIconFile @ICON@ CFBundleTypeRole Editor LSUIElement CFBundleExecutable @EXECUTABLE@ CFBundleGetInfoString Created by Qt/QMake CFBundleIconFile @ICON@ CFBundlePackageType APPL CFBundleSignature ttxt LSUIElement qnapi-0.1.5/res/0000755000175000017500000000000011015004533013014 5ustar patrykpatrykqnapi-0.1.5/res/qnapi-48-icon.png0000644000175000017500000000370010775662604016036 0ustar patrykpatrykPNG  IHDR00WsRGB pHYs  eIDATh{l酖J[E. Z("L7 t8-ũL]41qfqi0ajQ+/$"VT=z =<9)>}ϓb,o4bJ2_Gp;֡ B n_8 :YɈ!ؾuͼkJiop7?+rɜ[ǸʌU!85>B?MQz `/=W,f''1,/V&DV]}73*1714J3F6.<B IF|>Co\d)$хN|:|=NSy؀&4%7}F8”yCquʘlTnEl%xa}N]M֩J,Ch5K6| n{~`bz| d=[" T %kZY1G|*P-~CzC\>O~}^e- (\|ttgH.ݒ}.f.‘0&]]`Ab}_h+>pW3G?# Em-IZ۳U٣dF]|rLİvF,sؕOeKdgľz JR5'UQ3>ڍh4"~,>HuY >ٓս ǰnwwͦi /]ot;KR\wVT}kT 8$r7k4{[ Ű}xssy4/۸g-+pYTXzH͖{Jz'X7Z;r>\U,~*'zّ\aoY?fJչ?/Ƽ6q¤]i'KVJ\}{:h䦍ےjpbWd?o|X?HنtԾiXL[ )=#*ї[Mm$QeBEAniL[*2ZPquRH<7:qXVrkU;/u)D ^̐X&w;N6%Y 3ZQa/81s(ڣ[Y a^zF~=}϶3&E{gkC탢Ao 0DxBh&BqUC#V w ffE8aG2xJ'Zǂ(s+Q[@]5Ҹ[d}2_GQw@7V 86FM_&ԃE!g>/퉚_E>s՟Q{>|{{ڨ>zm/;h&Z( e2Xh@IENDB`qnapi-0.1.5/res/icon_accept.png0000644000175000017500000000057410775662604016024 0ustar patrykpatrykPNG  IHDR(-SsRGB`PLTE!vGKp.ݖi湋XSqD6Y~mR,WLw]zF~GOPL`RgBZtRNS@fbKGDH pHYs  tIME "[IDAT] AA@T`26˕~q P!88zO!Aw(uR#Py29f@tBԎigz/l(e}m Di֔ C,HOmekI = IENDB`qnapi-0.1.5/res/icon_cancel.png0000644000175000017500000000111311011701211015744 0ustar patrykpatrykPNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˥kkAkH !)4^cƘ4eJKi(̇\ ĕή;OgV7U/ þϙ3`  Fe` ݇[:WnF{2 28dA2I>w&B;6Y$ ZŽ=DUemӁfZ/Rm Cz/ tB ̛NJ a;rd N,XX'>Kry88 x__Y7ͫʹZȋ ==tajD_RA#(Uxf84ݹ9n2$b'C{M9Hj9,=ݫ R,2Z˾u0(fԘycRݵt#]畸ݿIENDB`qnapi-0.1.5/res/qnapi-128.png0000644000175000017500000001513110775662604015170 0ustar patrykpatrykPNG  IHDR>asRGB pHYs  IDATxy|ǿIHH.&H]*( hQKoźַԪV-j@+bp\w!@ dOn=sg޹7!g>IL99f30 9 @&#K͍ۿ\$[WXdol¡E$`i .%?y"5zOfo,LqPOwZ w ɰr??LjVfsU7Ê{O(.M`")-m 0XoOqݛYKvmg;( φ'ώf3j" lm` 7Stoú- 0'Kdoڂ3CȡcxJhnPkކOՆ_|xX^50m7klL'^10W=05N@9v?3nHN^: w > ˀɎs|2="xý0%, unv':, y ŗ=6p?J`K 1tK:+!<7D3Bn੼Oˤ*YMhKa):0|i 6GEt<4Jtc\*q_8|Py Xx>|Ǜ4ElT aRL'b*9?Ǐ<3aB/J|q~ 8~e0`B׼XpK?hk1.0s%TKj94?|l,poh&doA4 "W -gCQo<bͧ{ >{ s*YԜQ-Fxcl/ ^5!B!|??ہR%Z~gb }"6Oȵთ6+^m  Y<6' Ln*f"B~g@TVl2G~f3ṴX.qO3QYYwH@lԌKhr]@QG[tRYdj\Njz`E{M?_^SH}*um&쿥@Q8-9%ϔ GdO@a_UfJ R{! &]>cD'lWmrG"gT?#љd[;¹ h` s۷VF;X1(|w[wѕ_ /‘h6;G+|9&4Ol^e+Ŋ=(z&T.rapxXv;[+xrwFVeJZpP /ș,=Ypp8ܛe)>Gxh_ &dZp(ýEj!垓S"` ް}#"Ds҈ٔ^iB6 %Q BVU/^+gжs{&94ث *E3kjX~TCz?:T"TFk:{d:#Sy IOvYÒa`y,.1]2 lǍp_'gSiQYe"A';nnd`B]#)p&xl Gõ`a,)/tNl6=7fiN(9)NIR>~[9~sGO1pbCGA f\gnpS{18W!2[9RCwB?]H1")TIq gC]w +|^ > Yn;ߧcŠ.+3 pE /N)뇸`F_IYw}a0JM Dx $ CSLk9^9Xc&r_~0`6cx"EѨӟ˅YΔ:Yp^~Q"ҩf=Wp[&Ab&S.'ge\u>ϜPaOvu:V_%fM[p2U {*|[iG$Tw~IW 惰Sk/Vg;"enD`bSQ~#vsZPcwJ "י!%+GpaWqfw3/r^$?ѡ*ad[蝈 0**U΀\IGO'8jPoW=T츰B (t/ Nx~6vS)vN(WnvsQ&p /% &q`Z:Mr\:_IҨtMpJ}a4 Ƥ&gLˀ%eP\o*z!­kxO0}?ʠnJ-I߫D+}ˑr T1GƤt9#U"\K T|^*aR9&Dp1o[#)EAxX: c0AY≻?)i,slC >|b plW 09/QNpQQk[t۶zp6 iLGo$*O١y#>+~s᲌iRo#X}Z%PƷ‚.qY)cٖs6B~y!"،"~f-N~X]BX@R[*TA\'׬cpY ++aRT4'2MtB[0XS>&Ѐ,_BqmlwhCyWCA5x(wH1pa"LH$ 5:eNݫe =%W QG g*N0 =J_V|ӣ*z/mpQ BWD>usP-pŸޏ,Ჰ5 _|Orr v7?H10;椇TYka pFvG61BUXS00:`IGV~+1pȠTߦ&G֩n^ r&5Pɂx_׉VĔoq 9Fbz*"XQ-=FF"7=WY'Rq/]^G> m"TۖҀ<#`] Cޫӊka)xJtXo5wobYVAb}'kpc97pI,Z|3FFl!Mya)v(5 }pG%< caMV*{,h (Cabo~/O 0.:de:'+~uC!|l]qE=dۢIG2jgr}$Rb}|;p~Ep%V$(ɖ0=?'"6M8е8_n `J5P/6˂[r{4+"=b`HXscjN x l0b2wY-'dGХQ0\1f#p[Ϧp lAB"}BL "Db/#r`#L=J;#1vQYw.{ue01=J #ܯj#D ({9 X/]΍3ZъVD~pUtjwrỆ+zoކW:|wA$O6}4N.|׫zB5jA{A ՈG8 -ʞp,0_pj1]Y&!I/J|Qi!sMDD!\Rr{{Zr_ ȉ֦+ cL; q/[έr^i +,I]DŽv4}[]iD_X`l8DB(74%mLGaE=4ȼ0{unjIxfIƧW8*@IӾ]|,Fl1sbM*+VQipbXn&QÔo[CstXIh tY,s3@AhNr?{\)gC/?.HF"@Fᗡ- 3d%È}# 6p;'p}DT #&K!U4o:iZ~iǍ:Xkn'!.!$T h󒎉{P.4|ff.[5qP9#\;V gIENDB`qnapi-0.1.5/res/qnapi-16.png0000644000175000017500000000117310777125146015102 0ustar patrykpatrykPNG  IHDRasRGB pHYs   IDAT8˥_huαbVm1ucNHNBSMN0Rv2o0% $r^#] E`c폳<^tntA_9.W8ߡ͒3;cSl_AU.<5seڗWQZ-I;u|B|,hS';[<#b-ޭQe >)v%nl[_r3WR%![hC`h•)V>'A,+i'hI8ˏft XM03S>h 6m &SP-TĴ協Dz{w=q+,doΜ3ߙ3gLN1M%QlZā% ٌ ׌ьFj E~=ξ:<®۪2E-#~yWʌk14V\?;s?dBgWNV쭊]?E}ڠւA=ȷ 2 gf6֕+_l%؋x[P_@"AO8VX~ԒΩ[u5 _763HО4j躲Nuͱ'lzP2y;F[m,_m`$]&;u&|͞1k8AbT+ir1N&6LqJQTe񫚌>A6kHW&=>AĴMͥLWk}M "&$V4YE\*}LTe}pN%,v-ؘXsAN<(bqEX-}V'r_b{ o($'fΏ(##/\ zSq5>fMU(ؚgI6sXrR1?ecEcqOo*x!^gk{W ڂE.ΔuE1laX)'1`c3蘾NPh/Vve'xy'_O0!*g)`wM6ȗ)3>18,ϰȪw BLؒMm@[&qX'!Sx%B.,e.RtE@/q #t${* ncj pb']yB8=EcJz~6ִiLer(}L@OVN഼ո 񉴚{p=ڛ*`Xz-Du7MO?5O ޜO|p!d IENDB`qnapi-0.1.5/res/qnapi-22-mono.png0000644000175000017500000000113510775662604016046 0ustar patrykpatrykPNG  IHDRnsRGB pHYs  IDAT(͓;hSq7\hhLZ(b-QSj 8ŊB,")JQqP+EAtj@Ƞڴ57΁:!TXf)>n;pP;1"Z*cT`K z f&P w8f<^2村N6Z]}^kw}ELq àDzW]b_ !a^LL4lٶ/.Hr?XPd5vbGȗ*K5C糾U0X!P6_to^T..DQsI sɮ<',V:DU`"[yLe!G~(s7k~Kn޾]8$cTԌڙ a(n"yϝ2?!BA 9UgH}pYiDAņD9>7*Kx\M\j-B)2YBNؐcG:%={={.>]2 Xg@>`3na${ Q8J>HV)yi00UR.6:[G6{ρ!V(F0. ,/p\(f`0{Jl/ľi.zhj }fPl Np=~,/ˁ!lWཱི*jKlXuiPu{aNV܏y~|ؑ VX+uV5?,ЧiZ.l9I恲MP/@pl"9<B/~@iq&IabfWUM0~3u\"(Zr4Wӏ/݄657QzrÔ-g1ɇ kt+u:lĺqy3OCaj utu^ҙS&nG!C&hP.Eyt~tFX=ah=(xW+; ({4hy4 F%Jh w/']wԚe R .Ɏ@@`7ANhjj[{̰d20>^wU#j4{c PY=/> \ǘz`&@]/i~S p7p cvT(mP7B=tҢ"{fvtunTꀮnC7 A#lZccZ) n=izh\>[*NdY\(0Z d3S݁X>lS.8zS m^Xa08! OmX0nj=',UXM柆G!m)f6gA|v1AiIp=؁7k5j& N{0/oԷZ[-#`Ja7 W` O)qph /K@p. GR<'G#&՚lw{`GN!21ʥHٝhDF) 2Mwこl)@d"!EH%d?01&lFe!Rl">>XMQwo\<{R\L@lOke.6#r{ȩtjA^#d3&#Uvd9 Ќ lHG" HiOINĘ@|d}K 1\燀$@ݑ3(տӀtMZW"K r`& F Q?nER ؁caFynG ~D\ݱfM_ ]^|Q'C䰇6\ 붘{USJ䶪̣ZU!r{e9냁'BCx\al %D+㬶_2|P;h-O3Z[$Wuv#=N!-g-ŧ }QϭpN0Nߥ3韘μE͍"hL|ۜ0Fu\Hwyza WVQ[_b>N=*7e;e5-un۴ P7pY2IENDB`qnapi-0.1.5/res/qnapi.png0000644000175000017500000000164210775662604014662 0ustar patrykpatrykPNG  IHDRĴl;sRGB pHYs  GIDAT8˵mhVu߳ǽgV&|ckN*Lň/هӘ ҈@DH"%E!H~hfS3J ͹g݇ >9_ZAX(Cp$ j=Dҹc)+K%gNwY]nxU  n^e>i.V{ b.3f(w|v 2@>6g3xEu`#B:)Tkf܋1v#4VKFQю~il8K qtHxöy"X3bJ:}yebV@mOpOOa m]q*fnL닸6nkI F`H?G*#{twSۊVIekp=NgAd"eKinACo[>hgJkkwOĽV,ʈ+˵bQ;Çt^u%:QqEM+L1C,sDdZ|>J;g2"7Id'r$ؒIcDq0ZTu`2J4VxL';sSYbJAR믲Y;jӜb/+EFET]bGX]".(-DAx&֎K[ܐV8:q9gvpYG ܚbSxF droƵxD?'ՅXI,6 edo u 5LV[4^\Nln".Mjp @c~B$<{IENDB`qnapi-0.1.5/res/film.png0000644000175000017500000000121511014771767014473 0ustar patrykpatrykPNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˥OhAn RK%JzQAP4 KOyd^*DQT4"RKmNZIcgotד ?v7aZ`|j8q\yR И}>9[TbۢY3CG:1AN0]efB8pA'/h|GWMa:h(⋐R.{!2I{ =p?q4Ot\"M'gS m9?hubָnlÁ1ҫ Rb=`g\9niܦ5ZFͦ7~ynHt*s)^d+Gt?`_A`Sw37Sk#`ƿ#Sk؅逅%Q~9Nf X Y5ͳASdhhJ ܻPjbKq[myzkd@lhZpwIΚbX(d>_M2hYVhrЂIENDB`qnapi-0.1.5/res/resources.qrc0000644000175000017500000000051411014771767015560 0ustar patrykpatryk qnapi-22-mono.png qnapi-48-icon.png qnapi-48.png qnapi.png film.png icon_accept.png icon_cancel.png qnapi-0.1.5/res/qnapi-512.png0000644000175000017500000006317510775662604015200 0ustar patrykpatrykPNG  IHDRxsRGB pHYs   IDATxinKU:pCJ@iAFE&7kl0I@ tJJB$yn՘ĀMF :i-ߺ?oo޽vU1YZygyWSUs1g͚AAAAAAAAAAAAAAAAAAAAAAAAAAAAA@A?A HAAB(2M HAF_J Ko A}1A$8 /&EA!2t HAF_ ҇/2t h (Z /HW  ҝE,2 h =*Z H  MM_7 m3 " ұ /q$y |L|.8wY)Woy0%C@x%hhR[A Rߔ-#!)Ɏ!EbB"*# ҹ 㿊zq۳޼=R$`g+4X_Adz% mf+< ie ƶO)1bed1|t h 2g_1 m;6X I>.Y_Q[F eɒώx 3b@XЂd{x\)B1΁mf|Z9P, +,ZhB o홢9y&/iFJuj(Vjxt h Ga^s$.w*l" ?Q ѣEP(ed@:Zd)Ov\^xx>aExԌͼKɰ+:qѣ6))Dey|J~֩p. \[-b)r .2=ƃ%Dk{Y[NnjfiPKpZSM-a?(0Υ{Y x ձJ\DAg;k{ G=EВ.Th;{O^D>529oһٯ\m׶ V]&WJ2xlqV!XN_]d0 i`{9WV;;6ބgiz۬h?  2NHxGlz=zxfgaƫ!A̱5ziDI Hw*oyܵkkm@XCpj@D;ZIZ/o!"hF,:[uގ|DH`⺌rn= fGG=#(x=4=I^Aƿ(UKɲjucd}ds0ERz[،ReE& ? [ h҅<ˎg{%=duwϢP,!/+TA-,:,^ӼG Zk|ZgwRdhIMmGJeh'ha-ƿ6l}=]j Qs<DIr?`u]׎K)^d44A,?kt-^i!cHKR}ޅXVwٱ  md wOգK5Ὁz^22},ɌUQ3-dfIu1:IB1itA,?mUtk-՜d; iYm-!xOģ&0d'Dc1xJz Wm z>0~S ׊<7=S%Jf -F= B^O$@Ф+;h:-' z(n^֪\C//z~ƽ rgZDye/M!VMk^ X^{!)bTO;SdaICF@̱T0 Ln^vjP0Fc jk{6yKKoO![#M9Ͽ[$W71^CEyZB،lӫ޽A)#C&Qƿx^o9jkݳOGC\;u$@Y8gvDf*(9VtyNjlgyܮ&:=^:" 4y2g31[˿g4^~l%|T|!0Qm]* ϖ491?1^!`=eZ[ڿza&i ݣ%?VCm bo8ƈ':ߥ641= 72o\SВ>ΘLފ" F7skAn^_^e{wqFsekDu1g mr=e2eԮ=&<֨},?ֈw5^GYw?(2-)OV~(N#iy =K2lheeԒy{צex`aƿe)kmeQcaz-/Ԑ%7lZl$`ܵdwD4ZOm 0|IIy{sZ"YB^=ZgaedN< _>A-ւ?܈™@x.pǝj5uQݻXPZA>YBPQ#~DGE8]Ϧ(( kxNd`& {2jK0l16l&1J/ YC?}rd0?[ ƨ~TU\!XzjF0#G`z=bA +fȇe">RX8MoDy< v,T {E {%0~ ӄOl5٩ik? ɒgрȀ73 wɐ0:~ W[ }=˟)-A׹{$'a:k{<o+iH:n%3GJ!l)-ې+-(`iJfO/&Jp'ߟۿO ;$Jj]GC^K22P޻h9 9{&ѷ8[]lY'^HxdDXQ_6~c~V'3P2' E{s<J:[[|,Ʌ>0>YqSh(Gnu<L\.,aԧOY[ֱ>d,jnΞgo#) Kѩ+r3tKJu|Oqm]s{GiÒa!>Ga&X-G '|‹$H86B J .rb% Yã:D1oDcYI}W$H"" ?`)MoXmu/l32p6C>~59rpxdU@Jg OumOhQ9kK^?Ƽ$=$DÉ Nh P??+&4kI]3&Gi Nf yk[-8d[:6'-T$ﭼCS94ƁjsD`$)e)] QOHƉ\#&!3wfZ~g%EA89{\.RP=2YxY). [tLiRm\y" GxG6%a2ǂ@PRN*N '%+Tgy.72тesa&{^9k& nݳFK"a-ƿ]OIA֑$F!%)<8<9A$.Hc_-C]sҴ!+>\HF2-ysUjE <_kW7{(_c6߇rH.$ dk$ff/_XA /X$|Fwb` "GG+#9ӿW3{%f !eս/1NIrg}׍[& ['+f+ }0®-J<AZ;D;y:"gjegED ptD@z &W_6 `8 n-9JD'&P=5P[q^``Dk%-8sJIB IE)UΈZ2Jy!7;eܙʃ%w(^& p<6q N־31J[ ’H5^ɟ>D)S6J6p9" ;YmX6tOn0o++/d$_q=߾nǎpLtHE`mv_ VP v* uf+bp_޿ 0ʞ;CG:sԙu\K@v;/ 1S&`* *I@x%; bJa^5S Kxs LA ln9#A^;- Z$"k9]f{`,)/s PX* pzd(xVTFgt #68r.da(8͜BZKӿ.?2Fw8fR U$=d?(f`XES [1̶Ary 𪄜Ih$i`^h cQXye9]*eaIgvpJVMy{TXD{lbyKif=-BAY?btKiqH (PF8py̦)˄JDC8a$ ی1fRetG@9Bi4dAX `CX #Sa?!Fz]lc2`D ~l.(0+N}oJ~^ƽ@/,Ǖ zNYJ]&IP`5,:\s5wȇ~B(wyC_P0$ 6!<"0ߒxdž'o+/K`? I5 V6B?\,M< =v-[{l NO/ 2r.<(Ί-X.)Pp(`wA9 PVsJ:q\ W#f&=Z ¶YO[^urXDO)ĕ]f d%h-/saxY]ۥt?[5-KEOT(,l1)(`GAXÎss[%Ft" a]K8(NAcW2ga$ GR{0@0h,VȋUe BeHxQ_(~v~幧irs?9W @9Ԣ"  btK@~{[[4"K BJu&¿< W/%3qށK DсE! ۾=!]za g3`G:-刦}dFw#6hbeEr4<Ϡe.BSyV+ƒa(t '+o$0rauN{w$YGSې1aKoi($]`,Vt| OA>eS-݇^c>r!ae"!AN裩)ۜ얤 (d;G# atL(_0ZxKS8 H\\X+fԸ|!QcD@0Mt˕d\RȈb"=}7k 0 L3<QL9tn?[gIzHf-=1'OiTbB!Dȧd{ S-K3FN STyyKi[aN;FN#1 Sƚ"xg  (eθE}踣/,SKD򍉀_EVr笈ĺNhXØ<6B`];Aֆ0=o:E( t `K"l!f3PFbt-uW2BHA嬭 BATct-+o.0 PZAkVa\$/Sf?قj@ Ka,͟7pL+Mɐ3F=V< 0\ "F=Ɯ9;j]K{d 8:)S,Y@{)0PJf2ߡ|&W_{PmA֎MRf ܖh 0xKog( F 1;c}"C" <~IxsJSUf<xygq*$4 4:o7>&seU@zN`VR UdIBZG GpmЙl])tr}څ جLֿ $/9tXLaD'rdҕXr8*V1 [SXutrO)s0QY"~ϵS`sZ Ԯ$Aah8> =s@]զ qMIK` #VJcR]Nغ̪R[KI/96brZupRX-w"/ L5%4&-QsW"Vh\OFa-=]RxA6PX25͠U:'.de Zd Uf"gcfjŊDB^dT^a(="aMɨ[+PS`V>Ofv)*!-3–g(k3UN?ju̦R qgxޣ095\GQ`a:n;Jo1l}H@V@Z 0DCi+/qVg'f@w9jjc%b2"" bX!6 ?&(k6D49V`ʓ3-Ḏ 0$X^;/G0v瓃@  HexN>ZbXRksJ5Nr'wN?weneE O`N~ ax#CgH7Ῥ3B<_3H\m@sBAO22C ꒮7^z0odZm"\ȎQiScǟ<ɁRW6bN $8 ^{ ׬a a 8ŗ zmbP'QҪG Q6bj DQK[$@y;h9L 0TXruZ$Qq|~35 FDz';(Iut!s&g _9:I XLLui[yq&Yh u\2kZgZaBǙ4M [Zo1eeHGFDGzu;!e?֢"?O2g+j1(IRtSqTVg )Pc&z~e%3&%?Vo ,]O}K-b^%5Rg}k 2g} E_t%"AHVv'䵛0CrѲRHG}ʜ,OrF*he2 iԊ*H )8HZ]LhUxΖgj 5\t;yl`gʮp8>"acii 1GO ""&U[26` XTo` m|Jr(X$Glxݪ^9K晢d5DatcŮ4a:x6ώX͒i'4lsLv_ gY(1*%F2^,{o+yH\#KRSј̻LI@>D22D2[ӧWg XXCDƘ`x)NEAA[#B"+~ijT(y@R5l5>'cT^)\!~[P"a]~az ݍ쥿zt~Wn4X+l>.sw{m/YciP29LgDoq&ikY'CN#sĬߪA15kU_r$ ޒ g&L`l(nX$t;JIA{{I4"/ldY{7l^G55SdX[z2g-T-=)|ialQ ƻ` ]a@v Ɵ`=k |z;pI$Nz3р{U$`FrCD!㍿ ЉJj SM 1K%KmOP0D*L:aN X$-͎om8H˴bKdu/ OXrLkPlPy+\ / mJD~Hg**Zd V^9<>Ke=yO߁(J)ux[V6w$WqFøyA޿"#> FMIJ%J]|Q[k\yC#=]k}Z#`732;[8F12%juK%vv'HEN Goa/1essHb`P5lJ~f4 %*bw+pQ/- MZ18[s>QzFón)$PU+"l$:Ȋd{q[@xt"GB ƞc&6CK"<[HOT\*ڞɟ@4pg;etd)1gN"3L"+=}Sl>KUs7!pwuD@|eOX  q-`Au)9|SUT޿o,(m,{攡E$KoUWF22L畏#ez-X{",bN D S$e||̅_sK_JsÉz=(y[KzK S.=scy;r5a5YgheX錤d]/Wq2- l[D<%A~WΓj 2o?&pgOG') Oю}Q"9xc&m"5/[)/>^1ۋ '|[ a)NEnl*_N T?@_zn++jx[bLâUՏe])sIUU91HHp&tk !@YLmZp/@n1¥ sݒ%C[RK!ʐTd+\ (vKk5٫f'vĂo\W>v <מ<ML\C_yZ ߕ3=^O =ksEDFtsZϭhL{Mw)]V`R_.BbJ4G$z[|ֲHi$ȻzՕ"-$!?:VCK_rx|-! 3"VvpM`u @ Vc vJd֞zrJ 5 r `Z"s㹛 bS|i x5Z{"ZKܶ‹.yL,F. IDATdRn<{HA.? /S$i y8ʯMN9Rg*b2k;w͝5Mj@R<ђRT"/5Q8yStR> [>8$i5:/{><޿dv+F]T %]lmA ü+Nѱ®p]3KrYz'dA$'1GTq<'_B6 {xkӻxю^YBBkz)Q_@J7 (y M( o>1z%"8egm\a/aOvh `I 2U|{{̇=lqM[ߋPgK2}Yef=:J ܿ.j~@l a&sTJIt_:vz/ ,PWOj ֦ECA{!܁ 5P +X](>cBaxWrdp).8N?-ν1G*m\6 +%s"<$籡;rh).96 8KصbVrVCt"I *e/YX"vJZ!]⺩s޿u< 2\(:b]6:fɡ)5nݗ Y ?+b+s2"L5>hV'AbeKT  &ǞpxCvCY"Mrgzp̞1{wC/1бyn>G,oSW?Qzj譌ՐceOﭨ6WǿAoX oGy+TIg:Lvȷiq0ǰ]p;1[jpȅgیO+/e%\H1jc@h`&;L;%oY^i=YzwE%%/I,cOAw($:BV(#ʘ2DPNIJ'[EyAe[z(D jz{$G}N ZKzGW/5ZW@X܂%L=%v?^:LlR lØv;!kZ<h&*Pxt2+/%!h@΃y@S*|[f(0u4k˓л?$|m~RL0<ykϹh1E (2pM5l+Wj;]:tAD6U (q-!e,v[(V"GMoJYag䂉y׼W&jM$@@X xÓfio;(yTAke 488\fDn\5ɭ 3k5)} Yi4<m3 Bܤp}!TxxKߩk7$H^Q’WayTjC7OS[PĞfbWXۥsܘ\EL+2D4,':p%%l 걠^XFjP:(AmX5YZ}DV*L_HIT5T֚9w:>ul6Q[[]TPߝ'O9tU*w)nr<+I4Ca}zCᩤXl".PԈ)Tٝ5-17e>e~ڥhD~(x_@WakZoAhU-vX?_ZgdE60seٕ[ 1,Zhr kQ+h5-ϟK#D> ,J W+R>^*iG4e}+$I8ǂen"{?AةXoG}$HFsZ1چw$g`'mѳ! 웳GzGDћ혩Ug(E/z?#'"†H-Ha5z12V#rͮ4=@{^#F+IQP2-U^y5왡̽E2~MbSkK>QAPz?"zAa$ ޼Q1-=YEZkh"C{j{NUd\{&Ygw&|Dd@@0 `vF1x5QnE4bY%Ɖ1cn-N&蓴7bqoO"P7ND7=e 1ކ(.x1Z AK‡Vz1dƿϬ `m}撜>)#'zAa$敆*+vhD0$+iܫo 3DY;Ru@D$Wm{rSg.񧲏zAaU$l4VRϨƛx]2icU{MOqΡFB ZKOojURH5xьlyYZ1=ǥ.~XfKO":%HZ}3.&Mb 1e8(oǶġ6I[=<: k2U'[׸[sOIJ""‘{ 7EO yĔ9 [.~Y:{TD+aMN>e/4so Ȳ G&y(9wf~hb|gCS͐7P2N'"񒀳DN>Fz1V|kZ]%2`yݍe18-Duۆ~4{"^-%Ur]Sz) {ӛv= [mnZFf٢1elQڬR"u"'-^w|j 5V=-o^P$`"0R1zD6Yhc˹H{";hxS 9A2agtyBߥYbj' 4*"g k57EVJLY/4[t Sۡ^IO%&#zAyI@K)GtX{܇aHG9׵넍1$",l-yacD q㛠O4Jg~mRd8z"}2e/lchztL N) zɓi|Wemu޼WdT+)-1"sƘ9yB8&L#( 76k*lwεH%Q:0mKbm')m6[ 2C^L>EK2/$ymek{5MBgZאfDXPY -idEMJ{,o[`TzVOe<Xa#"ʵX0Z\^U D1>EEի9/ѯN;Zv*I,r^9L8]`w|mTOOK^PXr4d ?q6˹aNX 7V!`z%G?ֳE-;\h瓁"2?: @@/(l~t%J dQa|X#ZRx摆<гCjƙ8w} V˞fgg\t'j%LATG '$$xEH% A>Qf%>b u "6iRH1@ˣnRh5ިC$4LBӹN@ 15ɣᓲzAA$z# UٿUKi4Գz5wUK2d"zAAD la,0Fq{#ޕ=6(?J6ߚ "zAA$E8 -G/g˽vvDHdk8[SzAAD'ȅ-[Lv˞>ЧqOH.AclџMȡ^P bת0^^SYM ,E\$FTl0^P!0bhn[Rн]J7/ar/6ަG/#"zAAD`/{M *"=T#uݺaYG dB5V@u,LtdVϮE5X~ "kF,X3A&c}ʷ$"zAA$`{uu3DZZϪWCs%i}}[G B |nPF*GU"zAAD@K%g"zAA$@SJFd \>A8b})} "pQr!DA@/( ‘DɁւ^P@ɂֆ  HK (HKA"$ H c+ H ]ZZczAA2 E)H7ik%ARC }5uA@FZkT/+ftu}tkW*R±\nAaANAAAAAAAAAAAAAAAAAPTZ+~ork;?p.V x77x5LW+@](r|xbsxxk=hHW+~]U\̟x=>aF AO5wWp| |oNih>.l uհ5 U!DXð \! yxNnD֏/( &\wu?? +NrD6'axk_pi4Ж j\ 34 k-4ߍA`x0;j D c |6x'g~Ώ_Ht}<|/I1jٝG2 }>}˴N Sö TT.W=|'N*]Y.IxAcu5-$> qp'}V4W9[>=x}/$#1!xh?uUi|^G#7oq}VC5L>Iѧ \Oɣ'Z4N/N?Yˀƽ>H^ē$ΓtwCə׮|1x|.r"No]>g>a/HڈQs gXoĺKB16 _ <{Q8л4.h <_3<.x pZ  7V>E!X-:r+M?+Mk4Ejи_}>ƞN*G4' I7u9) lT y"UҊ~NuZYf5ou1왯T3FFdx}_8I*I +$I~ۈp-AXf^N?a* vCA2گ CV_+pXia{KIDATWF弾tM8ظ?0S +|NrEf|k o+i= ?7~IHg'|]/N pR}DRONX\8Oq#$Mnأ$Ò͟ ,\8v?< ɇO'̎+.xuOɰC'gp+̇q\ay`\IX14^W1F.7)|hay,e|jFAsݒaɇOInDs3> 8%?͟:+0WA]3o/aɇOIDc8950'^>h_)|ha^`.@]Y=h?aɇOI"ucsK%Ò͟ ,'@EW+-u7h(|ha/ w't|v$"?8hT ^[9.791*.SK psQ"ͨMwyk?xw^uBeP`puԝc,'0p_O~T?p**8ï=+xO%;rIMvUޱ's}}eg8N R\GNX n D-z}?Ng:FsJT/ #K>O˄SBupsp|*-YaǓ0!qM,KNZ% q{Yω~}X&D׍K  p\('kAÿI  > QAAAA8><4 qCaADa                               B3 56 IENDB`qnapi-0.1.5/win32/0000755000175000017500000000000011015004531013163 5ustar patrykpatrykqnapi-0.1.5/win32/qnapi.rc0000644000175000017500000000007710771166713014650 0ustar patrykpatrykIDI_ICON1 ICON DISCARDABLE "qnapi.ico" qnapi-0.1.5/win32/qnapi.ico0000644000175000017500000055324610771166713015031 0ustar patrykpatryk (`` PP gVHH T>@@ (BY00 %   h>( 'CCCCCCCCCC"2CCCCCCCCCCCCCCCCCC.CCCCCCCCCCCCCCCCCCCCSV Vt4S2V Vs4OD/vN<_k)Gt=Ev< Y+. } [FK!,Cl[Wzyyycl|@;%Nd @X@T/@dENx6@GKyEPP9xs k K}m +f9 !Vst4X6R%o2 KKK[zKK;  +z8;K{[[5kK K \{{<<< \ <L| \L <L\M]  = -] |*=  m-=  }]M : **  ^+ >~ >  N + ; _ <<!!!  pP00$8 @##""""""!!!!!!  o o o oD L%$$$$$$######""""""! ?  ? # A%&&&&&%%%%%%$$$$$#  O~ S{ M(('('''''&&&&&&%%#~'   =(*)))))(((((('''&~ ["!!!!! ! n.#.... y =)+++++******))))'}nnn.>nn @###""""""!!!!!! )--,,,,,,,+++++&]Mb Y%$$$$$#$#####""""""!!(.......------,('}" C%&&&&%%%%%%$$$$######"" NyNy00000//////...(&&.s('('''''&&&&&&&%%%%$%$$$"9>02211111000000$ #.*)))))(((((((''''''&&&&&&% y%3333332222221% \*+++++******)))))((((((''''''*_5555444444333& / ---,,,,,,++++' L, <&***)))))))(((o5776666655555' $d D(//......-----$&&'+++++******)( 8888887777772 E 10000000/////." 5,-,,,,,,,++++z% %::99999998888eoUUUUUUu 0022222111111000P.....------,*zz<;;;;;;:::::: 2444433333332222///////.....U;===<<<<<<;;;; 26665555544444441j ,111000000//*E`??>>>>>=======@ 0/88887777777666664'%5e222222111110e%2@@@@@????>>>>>;fV 6Vv*8:::999999888888776O(44433333222#eBBBAAAAA@@@@@@@????51%%%$%$$$$(35<<<<;<;;;;;;::::99999. /i Z555554444441@(CCCCCCBBBBBBAAAAAA@@@@@@??????>>>>>======<<<<<<;;;;;1x N^ /77666665555ue:EEEDDDDDDCCCCCCBBBBBBAAAAA@@@@@@@????>>>>>>>======8h"88877777776< &GFFFFFEEEEEEEDDDDDCDCCCCBBBBBBBAAAAAA@@@@@??????>=% 8jJ:9999999888/fHHHGHGGGGFGFFFFEFEEEEDDDDDDDCCCCCBBBBBBAAAAAA@@:w$* ;;;;::::::99&0JIIIIIIIHHHHHGGGGGGGFFFFFEEEEEDDDDDDDCCCCCCBB/gg.==<<<<<;;;;V@9KKKKJJJJJJIIIIIIHHHHHHGGGGGGFFFFFFEEEEEDDB5$Gw y>>>======<<vJMMLLLLLKKKKKKKJJJJJIIIIIIHHHHHHGGGGGGF?.WvY@@@????>>>>>(6NNNNNMMMMMML( ' ' '#v15DGKKJJJJJIIIIIIEA3!v6- 9AAA@A@@@@??/@PPPOOOOONNN2 &FfffffffffF &v#CCBBBBBAAAA:@FQQQQQPPPPPP(FDDDDDCCCCCBB@*SSRRRRRRQQQ)UFEEEEEDEDDDD@*TTTTTSTSSSS)u5 AGGGFFFFFFFE@+VVUUUUUUUTT*E6IHHHHHGGGGG7@,WWWWWWVVVVV+@%%%%%%%%%%%7JJJIIIIIIHH@@,YYYXXXXXWWW,@;KKKKKKKJJJJ )@-ZZZZZZYYYYY,@MMMMMLLLLKKK@.\\\[[[[[[[Z-GONNNNNNNMMMM@/^]]]]]\\\\\.PPPPOOOOOOOB@H___^^^^^^^]C'@RQQQQQQPPPP<8``````_____GwWSSSSSRRRRRQ=bbbbaaaaa``]2UUTTTTTTSSS1`cccccccbbbbGgNVVVVVUUUUUTHhIeeeddddddcc4G'XXXWWWWWWWVV(*hffffffeeeeeU$gYYYYYYXXXXXUH(hhgggggggfff ?A[[[ZZZZZZZY@_iiiiihhhhhg#XgZ]\\\\\\[[[[*x?kkjjjjjjiiiOX/^^^^]]]]]]]\(Hw%Xllllkkkkkkkj@xQ``_____^^^^U(jnmmmmmmllllQh%`aaaaa```````/7oooonnnnmnnm@ Zccbbbbbbbaaa w(mppppppoooooZh@edddddccccccPKrrrqqqqqqppp8! !ZfffffeeeedddG?tssssssrrrrrn1UhhgggggfffffX_?buuttttttsssse!b!5iiiiiihhhhhhg&^(VvvvvvvuuuuuttX :Jhkkjjjjjjjiii_~^MxwwwwwwwvvvvvN!S!jmmllllllkkkkj'^'uyyyyxxxxxwwww=:"annnnnmmmmmmllW~><~{zzzzzzyyyyyxx> $ S:cpppoooooonnnnj.d||{{{{{{zzzzzzY d%Torrqqqqqppppppo7~^.y}}}}||||||{{{{i;D ;<tsssssrrrrrrqqqPd"D~~~~~}}}}}}||y)Td%%4dt"Suuuuutttttsssssc>{~~~~~~~Q /eqwwwvvvvvvuuuuutp=dSpJ# (Ueyyxxxxxxwwwwwwvvv'T-\yK5 )Ub{zzzzzyyyyyyxxxxxx9zC]\3f6Ys|||||{{{{{{{zzzzzzy:zy]mL4f$F &+VKRr~~~~~~}}}}}}|||||{{{{:y=y@y|vuuuuuutt~~~~~~~~}}}};ySy/Y~z$Iyxvi2Xx RxExX(jVHB9gwv.W2 1W}t?w(Gfs7g g11LyzZ'V&:fmAv6Ff 6CvqzxTT'F f e  1U1U1U1U1U1U1U1U1U&  eEe%eu0 dTTdT$ ????????ǀ?ǀ????? ?? ??00p??????????????(` !!!!!!!!!!! !!!!!!!!!!!!!! !!!!!!![f4#;4jF} Ye?":3iD{ 85!? bi&^-3,3?v>dcT? .*__?__`?<g_k_?bZ&_m _A?\6 __tX_:\!?tM__ ?pe _y_G!@b`` 5Uu=sF0 B(&5cnvB?+U ======5=====%==4 ========<5(=======$ "" !#"+22) !+McyaA"$] }W+ \  P&G""Wl/ k*8 y "8FF^bNF,>0(I 6Zfq1" wNu K *l_(('z+ | yGJ _*- M `  v'9 _)7 f\mw  _)-+   \^3W_)9E_)! H_(0; ! eH*! %*"##"""""!!! } g W UC77G W g 8" %%%%$$$$####" G' :v71 )('''''&&&&%" K DN-)**)))(((((fz"!!!!!  O ]'& > ,,+++++***(%G6/2"/./26;!~$###"#""""!!!! vJ +-....-----(i v2/! \%&&&%%%%$$$#####" S-"u 7*0000////.*] o,- a%%(('''''&&&&%%%%%$#g/0"222211111,^A$H J"(***))))((((''''&&&& 5"c555444433+Mo !R*-,,,,,++),) )*)))))(($ (>%-776666654S*F A"-/.....--*1!+++++***)m) 888888777#P?? @ E c 4+11100000/+j  C'---,,,,,&2  &0;;;;;::::E :34443333322,M[.////.... 7 ]b===<<<<<<;W -`!066665554442$J$1110000/$ / 0????>>>===3I ( 4R"/6988888777766f @|G/3322221,P @< +BBAAAA@@@@@???92++*+**,38<<<;;;;;;:::995*A n!45544443vj$DCCCCBBBBBAAAA@@@@??????>>>====<=<<<;:-_ Q 3 __37666655' 4EEEEDDDDDCCCCCBBBBAAAAA@@@@????>>>>>8z$ 4 2(" /088888770 0 " :>HGHGGGFFFFEFEEEDDDDDCCCCBBBBAAAAA:0nR 8#*;;:::::9\! &)YEJIIIIIHHHHGGGGGFFFEEEEDEDDDCCC@7,Q +&\v==<<<<;;!D *<"sJLKKKKJJJJJIIIIHHHHGGGGGFFFFD9'K )2 1 4:??>>>===+^ #D0NNNMMMMK1 /:"s*49=>?>>>><:3+d 8$ AA@A@@@?5`3PPOOOONFH '222222 *"0 0CCBBBBBA>o ;RQQQQQPF? K 5# /EDDDDDCCCo ?TTTSTSSH? f +@GGFFFFFE o AVVUUUUUJ? %P *X #m *o (] %E " 3};IHHHHHGG ,o BXXWWWWVL?D ( ) / 4 6 7 6 5 4 1>JJJJJIII #o CZZZZYYYN?6MMMMLLLKKo E\\[[[[[O?2ONNNNNNMIo?^^]]]]]UT5$ $ (QPPPPOOOB N 8````___Z&g,< CMSSSSRRRQ?_-;0}bbbabaa`7 n #m0UUTTTTTS0V*1'c_ddccccbH  ! BWWVVVVVUQ) %,Uffffeee_<@ /=NYYYYXXXT9 !  Lhggggggf*if,l'mX[[Z[ZZZG %d5jjiiiihhM ! @]]]\\\\\8 13kllkkkkkjH t9& jNZ`____^^Y%f@% XnmmmmlllJ 7 0Haaaa`a``O %6& r/lnoooonnne&X &$bccccbbbb?1  #Xrrqqqqpp[0 4%{'Mffffeeeda) %J<qssssrrrqJ x3 !X=fhggggfgfH 4"?;euuuuttttq5t  & m(`bjiiiiihhdLo,.dwwwwwwvvvn3o /1%'>kmlllllkkiAI F`yyyxxxxwwh-a ]!   Q#O\onnnmmmmm]@ m1 'Rr{zzzzzyyyn3l G. 8+adpppppoooon4w6 9vw}}|||||{{xP*f 70* 0(,0,x <tsssrrrrrqoH%J ]K~~~~}}}}}|]? ~%X$R#R#R#R$b&r!HRquuuutttsssX% 3. f~~lF/#@jwwwwwvvvvvuf E<&&_|O%J<Hqzzzzyyyyxxxxl D9+)/`x_B.Z9 ;(Q=|[u}|||{{{{{{zzzi,\M<'=%^yph\XWWWWW_got}~~~~~}}}}}||p,\`>*-B}{|g)y*,0ZtvL- s@ '63Ri"D_?) ;`m=u F& u ,OT~nE- $8:; A :Jvk,S'c9 ^(F{lv|mW*L ,1 b ",N;hKXa``a``VMDz.R$@  F'-0R        A1' i J+% =$e {y%A!:016$ :0.@NNNNNNNN>">4!;.72!=8?@8?@?8?@?0?@????????@????? ?>?????(P gIIII*$I< GIIIIIIIIIF1IIIII7IIIIII] _UgW H`m~(kwcdq09^[p2E?a/@</Z#"4Y/YQt\/j1#J/@!Gu(/?-"t 2Bg6j{%![0kXWVa CY![[[[[%Y[[[1#[[@=[[[[[[ZO2[[[[[["%33-! 0 6 H K @ ("Is  `& *qP4 {Q V  ]!#-0%.*% J08)( [&Y p.'*" X>  gj " _ 'K (7 q & , h \ / i  - t2!!  R4-^3#####""""!u@/+%'-J q'K @!&&&&%%%%$# P;Jb"? 9#)))(((('% @ 5!! $E 1 :<1!$,++++***&p_,A(+&)'*.*_'!###""""!!!!wU+o#....----$ 61:-#L,&&&%%%$$$#### P8)i/110000/&*9$) W!((((''''&&&&%%%##/4333322&)k&,+++++**)()(((('' c'G "7666555*' \/ e I%....---)l g(++****(k'C58888774P 755<[ 2.110000/*Y~---,,,,% W(;;;;:::3 > 344333332+ 5 ////...r 4 "b *9>===<<<7 )  %l(2776666552! 0  =-211100##5w@@@@????>4(vZKKKKKTo$*5::::9998881]| H,443333/ 7u $.5CCCBBBBAAA@?=<<<;;;======<<<;;:4 /` 6 >3666555V ,CEEEDDDDCCCBBBBAAAA@@@@???>>>>=) ;+* 2"8,888877&nHHHGGGGFFEFEEDDDDCCCCBBBAAAA6% .e 3" ";;::::3,JJJJIIIIHHHGGGGFFFEEEEEDA<0 z &- =R>==<<<8=B ;MMLLLLG0*4>FIIIIHHHHFB7&U"( 7 > %@@???><Y`APOOONN*   2R_____M 02 7 7CBBBAA@sv 'FQQQQPP#ob *% 1;EDDDDCC!!z/JTTSTSS$o}5#8@GGFFFF% !/LVVVVUU%o wE&54FVV V V VVU "C:25# / 87>IIIHHH, "/NYYXXXW&o g8FKKKKJJ( ! 0P\[[ZZZ'ot;NNNNNML%z !{ "O^]]]]\0 / QPPPOOMd t  K```___=7yESSSRRRNX OFcbbbbaN $- -VUUUUTM *?0yeedddd\A)c )@XXXWWWK3 g6fgggffe.t. n0R[ZZZZY< 5 ZjiiihhNA *r]]\\\\\&k#AllkkkkjE 5 `P`___^^U0Y(JhnnmmmmJ j -(h`bbaaaaA ,./ Vppppook+d 6" Oeedddcc!V 4.,cqsrrrrqb/%3  CggggfffV P _!`uuutttsU  +# +idiiiiihf-o<)"IwwwwwvvvNb/%(FlmllllkkQ &\YVyyyyxxxtI )+&  d'Xaooonnnmh"O=0 1k|{{{{zzzV.=  + h5ulrrqqqqpn> T"0%Kv~~}}}}|{j&NV);3(1(1(2(35L}.JquutttssrQ 6 r=y}~vG00ffwwwwvvvvub272 zB}}S(O ;;ykzzzzyyyxxxi//65  ByhQ6j ? 4.[A\q|}}|||||{{{g"GX<66fy}||{{|~~~}f:r@65kyS# oA6Jq+Uh@ 5  g)VuC J2#U8O|tI.02:& ~ 4\YqQ3_ X25 67@q\mvxxxxwojN;j/  ;*(3  %&5) F  88./"/6]    zZ8/167 " # # # "     p??????>?????(H `T&uuup.u[luuufnuuuui3uuuuu-UuuuuuG#)%`T46#^,) EKw"' F H}cc!G-R|EG 98+qGC8xQ]G{(N&4G  #gO'\%A}7[M 0E+fj 7= XsoR5 = bAS'*} _!% w  I# '   g 0\ @ AV>g F  vz g@ n ; [ g+ c v -:  g)G g+ w og*"""""!!!  r h N N mF g/&%%%$$$$#{?  P X T+_)((('''&!p'  adiX (+++++**)#&V%8#0# &$*4 ##""""!!!! NH ) v....---+i *p&&&%%%$$####3 |( `$-111000,Y &  N G)))(((('''&&&%L#444333._ Y(  Mr*,,,++* _())((('#  mH7776664l U 3 0(&  0 5!.///..-+++++*(+Q+:99998*  +"02221110"..---- :>A<=<<<;;*Q#36555444.s 6,1000/-*$)(@???>>>;"X 3 & % % % % ,@j"1899988876& 0 >333222vp % %:BBBAAA@@@?<777668;=<<<<;;;::1yh 7= .365554&2VDEEDDDDCCCBBBAAAA@@@???>>>=: &- 2 *888871!i+HHHGGGFFFFEEDDDDCCCBBBAAA4uw 2f;;:::9K:KKJJJIIIHHHHGGGFFFEEE@5(W) :"4?>====<{@ "ENMMLLD mU&1:?AAA@@>90p5: 3$ A@@???&#_ IPPOOO1 % & & & & 3 4CCCBBB/ %k8NSRRRQ0~ #; . DEEEED3 ' 8PUUUUT2 !ouH (> 5 ?HHHGG9 ' 8SXXXWW3C $ +3543 07 DKKJJJ9 ' 8U[ZZZZ5J NMMMML8 'u *W^]]]\=n +PPPPOO2 %i  V```__K 4 #7@SSSRRR. #GQcccbbY $3i-VVUUUTR 0m9feeeeb$[2=& AYXXXXU-?0!Qfhhggg<*( #W[[[ZZJ *%]kjjjib*4&0^^^]]]:$ Fmmmmll6.7 #Saa````E &I CDlpooooc,p2 .tdddccbT , )UrrrrqqJM1 G^gfffed/yo,`uuutttq; M)#Viiiihh_03)Twwwwvvr2m, +Ommlllki1v@i6rzzzyyyq3l N& %y#MooooonnR5-)<|y|||{{{vD  ^"&) (& ): :Yrrrrqqqc={;%; P~~~~~}|Y0 q l l l 4pjvuuutttp+`20 _ [wR5 -^byyxxxwwwv9|8"6 ]|`:r @ /$JJoz||{{{zzzwAM9  S{rgbbbbdltz~~~}}}v@ m>8  ?u~p2e r? 9  "?gR)lA9 X1Yof'KK)= ,Oa\*P1+:/ o ,9dk{w]7d1S4 1#x $?3ZExQQQQL=n2X7 t(1 YT%3% _  E/9.5!;) : ; ; ; : ;1"='81 7???@? ?|???(@ B/j*ykT$,imR"gQgmcv__{zd_<@q_P%=t</8j u+$zzzzozzz zz,zzzzzxg*zzzzz %)EE1! A Q e Y 0E Y9-2eE?B:f V}#"R?-N  ?2b z ;f  ?&  v g ?( ?( K !!!  ? ?&`%%$$$###!s/3w s> 1_((('''&&%  ~ \N++++***! 9v"J7'"+'>##""""!!!(*9&-/...--  f-' m&&&%%%%$$##%#221110 #q"**)))(('''&&&7V655444 5" q I*---,,)U**)))(Z+ 388877-["**2V -"11000/) 1 %--,,,%[<;;;:: *"4443333*"*.0///.c . o2??>>==1 / 3v088877766 l32221&d ,BBBAAA@@@=521115;<<<;;;:::/Al/455543 !"~EEDDDDCCBBBAAAA@@@??>>>=7W"/S)88877VA7HHHGGGFFFEEEDDCCCCBBBA2W 2 # s<;;::# qFKKKJJJIIIHHHGGGFFFC3w 3! .?>>==0 %= ONNNMF +Gg(24433,"zK "4BAA@@: )]1RQQQP<z  %bDDDCCC ,a@UTTTS> 'N! $]AGGFFF -@XWWWVA/ ( " $ $ # ! $UAJJJII -@[ZZZZC #! %iMMMMLL ,m2^]]]]J #EPPPOOG +]aa``_X{;TSSSRD (? e\dcccb3-WVVVU1 #$ 4Bffffe1{7 eFZYYYX%k "'_jiiihP  !\]\\\[( llllkk@0 S6``___Pq YIooonnT(#accbbb.y !%9rrrqqq/j"Ifffeea]uutttp:x&"/pjiiihh;%U)3wxwwwvl * -Ilmlllkf DvG{zzzyyj3q'%+amppooon-h%P* e}}}|||w/a F &NAttssrrrI6u~~R.#Jdwwwvvvu`6Y0yZ#F 4j`{zzzzyyyh%<|/t|aK:s:s:s:s@Pg|~~~}}}||ka | b^ t s1 ^XXYt&2999983h|,&.433#8DDCCBBBAA@@??>>==;# L- 7771 $EHHHGGFFEEDDCCBA9! 0;L<;;: ;# ! GMLLK5+7@CCCB>5!{6&- 1 @??>b *:3aQPPK ""/ 1 DCCB } 0H7%oUTTN   d '! CGGG' 3_7'oYXXR < # # - . , + HKKJ'2[7&g]\\W %/ % POON"p0F "Gaa`^@(* ,7TTSRV *- #_edd2 "kk*{XWWV "2 UhhhQ) G\[[M s6mllkA bXB_``_7  #jppoU "* $ Iddcb4 $8Kttss=!$  3}hhhgL6 = rxxwu3n U'  K'Ymmmlg<*P* 6oz{{zw?  O$ % N7ynqqqo; 8+O~~}Z0   *UuvuuuT .'#2 V[-X$#*UVy{zzyy^"Q#M L}snmmry~~}Z  v9#L0Zz|;u t<#)D{zS! T.  0U_e?t -!!  -+L6_6_6_+M3 !<0* E  _+)2&#' ''!#7. g0|G0|0|x~???? ?????????( @  PB2KP=PJPP( PP, m_~a+./_o@!o`_msoaoSc"ss+| [3 d ^3 | V|(PfhL^5:h7 b!  uZ o ! o  ""! t b c] #))&u  ! veI +"0/*1Q$('&&%#* P763+"" O 6&.."+*"4"0=<1 S'655  +00Jt *CCBA@;9:>==</Edq66! kIIHGGFEED>,G +$o (=<2!.OO#t<WYS 1 #59CB@ ,/6VU_ v !m "8 ',EHG 0?8\[#c <ONK .2 0~ba3v/UTG %@hgS$&+y[Z9 @dmlA VVa`T :ssa  18hgZ&E a lyxW   m.hnnm'] #>|~}i4 {hp HuttH+3)*Sa8n!A9<-[Mv|{zV d.4t~D x* 8euW+ UJ(9dOTRCy)J , #o  !J) `C`C`app9 <???(  @lM2V{2Aec/7^xFXlM  W13 J >* =',  O C$ g<? k /0%1n F&$u % |?-s}-6vX3 = ]:A)/+f4?tgH=rD=J% PET|/W _ (\p"L  ]>` # `s#Hs9C;q7 ? "djRUr~F w  ~,PZojO7 T  Ea ^ 5  !qnapi-0.1.5/ui/0000755000175000017500000000000011015004534012641 5ustar patrykpatrykqnapi-0.1.5/ui/frmoptions.ui0000644000175000017500000004243011014610763015411 0ustar patrykpatryk frmOptions 0 0 550 401 QNapi - opcje programu :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png 0 0 0 530 317 Główne Ścieżka do programu 7z: /usr/bin/7z 0 false ... Ścieżka do katalogu tymczasowego: /tmp ... Nazwa użytkownika: Załóż konto Hasło: QLineEdit::Password Preferowany jezyk napisów: Polski Angielski Nie twórz kopii istniejących napisów. Nadpisuj je bez pytania. Używaj stylu BrushedMetal (Mac OS X) true 0 0 530 317 Przetwarzanie napisów Włącz przetwarzanie pobranych napisów true true Zmień kodowanie znaków w pobranych napisach false Próbuj automatycznie wykrywać kodowanie źródłowe false Qt::Horizontal QSizePolicy::Fixed 30 20 false 0 0 Z: Qt::AlignCenter false 0 0 Windows-1250 Qt::Horizontal QSizePolicy::Fixed 25 20 false 0 0 Na: Qt::AlignCenter false 0 0 UTF-8 Qt::Horizontal QSizePolicy::Fixed 25 20 0 Qt::Horizontal QSizePolicy::Fixed 30 20 false Pokaż wszystkie dostępne kodowania znaków Usuń z pliku z napisami linie, które zawierają następujące słowa: false <!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:'DejaVu Sans'; font-size:10pt; 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;">movie info</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;">synchro</p></body></html> false 0 Zmień uprawnienia do pliku z napisami na: false 0 0 999; 644 Qt::Horizontal 130 20 Qt::Horizontal 40 20 Anuluj Zapisz tabPostProcessing le7zPath pb7zPathSelect leTmpPath pbTmpPathSelect leNick lePass pbRegister cbLang cbNoBackup cbUseBrushedMetal gbPpEnable cbChangeEncoding cbAutoDetectEncoding cbEncFrom cbEncTo cbRemoveLines teRemoveWords cbChangePermissions lePermissions pbCancel pbSave pbSave clicked() frmOptions accept() 544 394 327 211 pbCancel clicked() frmOptions reject() 455 394 327 211 cbRemoveLines toggled(bool) teRemoveWords setEnabled(bool) 128 209 129 251 cbChangePermissions toggled(bool) lePermissions setEnabled(bool) 284 330 358 327 qnapi-0.1.5/ui/frmreport.ui0000644000175000017500000001177711015000561015231 0ustar patrykpatryk frmReport 0 0 560 280 450 230 Zgłoś niepasujące napisy :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png &Wybierz plik z filmem: pbMovieSelect 0 0 ... &Język napisów: cbLanguage Polski Angielski &Problem: cbProblem Napisy wyświetlają się w nieodpowiednim momencie Napisy są do innego filmu Napisy przetłumaczone przez komputerowy translator Tylko część napisów Inny powód (wpisz poniżej) false 0 0 Wskaż plik z filmem oraz opisz problem. 0 0 &Anuluj false 0 0 Wyślij raport pushButton clicked() frmReport close() 305 195 423 69 qnapi-0.1.5/ui/frmcorrect.ui0000644000175000017500000001076611014352445015366 0ustar patrykpatryk frmCorrect 0 0 570 380 460 270 Wyślij poprawione napisy :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png Wskaż plik z filmem: ... Wskaż poprawione napisy do powyższego pliku: ... &Język napisów: cbLanguage Qt::Horizontal 31 20 0 0 Polski Angielski &Opis poprawki: teComment 0 0 Wypełnij wszystkie pola, aby wysłać poprawkę &Anuluj false &Wyślij pushButton clicked() frmCorrect close() 378 299 477 247 qnapi-0.1.5/ui/frmprogress.ui0000644000175000017500000000603510776154702015575 0ustar patrykpatryk frmProgress 0 0 600 120 580 100 800 140 true QNapi - pobieranie napisów... :/icon/qnapi-48-icon.png 0 0 75 true QFrame::NoFrame QFrame::Plain 0 0 50 false Pobieranie napisów do filmu... Qt::AutoText false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 24 Anuluj pbCancel clicked() frmProgress close() 554 99 299 59 qnapi-0.1.5/ui/frmscan.ui0000644000175000017500000002226710776154512014661 0ustar patrykpatryk frmScan 0 0 800 450 480 400 QNapi - skanowanie katalogów i dopasowywanie napisów :/icon/qnapi-48-icon.png 0 0 ... false Skanuj Wskaż katalog do przeszukania: false Znalezione filmy: false true QAbstractItemView::DragDrop QAbstractItemView::ExtendedSelection false Qt::Horizontal QSizePolicy::Minimum 4 20 0 0 Qt::Vertical QSizePolicy::Fixed 20 20 false >> false > false < false << Qt::Horizontal QSizePolicy::Minimum 4 20 false Wybrane filmy: false true QAbstractItemView::DragDrop QAbstractItemView::ExtendedSelection 0 0 false 0 Anuluj false Pobierz napisy 0 0 0 Filtr rozszerzeń plików: true *.avi *.asf *.divx *.dat *.mkv *.mov *.mp4 *.mpeg *.mpg *.ogm *.rm *.rmvb *.wmv *.* 0 Pomiń pliki zawierające w nazwie: PL dubbing Podczas wyszukiwania pomijaj pliki, do których istnieją juz napisy QDragListWidget QListWidget
../src/qdraglistwidget.h
qnapi-0.1.5/ui/frmcreateuser.ui0000644000175000017500000000646511014601020016052 0ustar patrykpatryk frmCreateUser 0 0 500 190 350 150 QNapi - zakładanie konta na serwerze NAPI-PROJEKT :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png Login: false Załóż konto Hasło: QLineEdit::Password Anuluj Powtórz hasło: QLineEdit::Password Adres e-mail: Wpisz dane potrzebne do założenia konta Qt::AlignCenter leLogin lePass leRepeatPass leMail pbCreate pbCancel pbCancel clicked() frmCreateUser close() 434 53 248 91 qnapi-0.1.5/ui/frmsummary.ui0000644000175000017500000000662311011700631015406 0ustar patrykpatryk frmSummary Qt::WindowModal 0 0 610 290 QNapi - rezultat dopasowania napisów :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png QTabWidget::North 0 0 0 590 206 Pobrano napisy dla 0 0 590 206 Nie udało się pobrać napisów 0 Qt::Horizontal 40 20 0 0 OK Qt::Horizontal 40 20 pbOK clicked() frmSummary accept() 348 308 348 164 qnapi-0.1.5/ui/frmupload.ui0000644000175000017500000001027311014567000015175 0ustar patrykpatryk frmUpload 0 0 650 200 540 185 QNapi - dodawanie nowych napisów :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png Wskaż katalog, z którego dodać napisy: 0 0 ... false 0 0 &Skanuj false 0 Folderów: <b>0</b> Filmów: <b>0</b> Napisów: <b>0</b> 0 0 Anuluj false 0 0 Wyślij napisy do serwera pbCancel clicked() frmUpload close() 321 152 267 86 qnapi-0.1.5/ui/frmabout.ui0000644000175000017500000012044111011547124015024 0ustar patrykpatryk frmAbout 0 0 666 400 400 300 QNapi - informacje o programie :/icon/qnapi-48-icon.png:/icon/qnapi-48-icon.png 0 0 :/icon/qnapi-48.png Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 15 16 75 true QNapi version Qt::AlignCenter true 0 0 0 562 282 O programie true 0 0 530 276 Podziękowania true 0 0 530 276 Wsparcie true 0 0 530 276 Licencja <!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:'DejaVu Sans'; font-size:10pt; 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;">GNU GENERAL PUBLIC 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version 2, June 1991</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Preamble</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The licenses for most software are designed to take away your freedom to share and change it.By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it.(Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.)You can apply it to your programs, too.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">When we speak of free software, we are referring to freedom, not price.Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have.You must make sure that they, too, receive or can get the source code.And you must show them these terms so they know their rights.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software.If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally, any free program is threatened constantly by software patents.We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary.To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The precise terms and conditions for copying, distribution and modification follow.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">GNU GENERAL PUBLIC 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License.The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language.(Hereinafter, translation is included without limitation in the term "modification".)Each licensee is addressed as "you".</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Activities other than copying, distribution and modification are not covered by this License; they are outside its scope.The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License.(Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These requirements apply to the modified work as a whole.If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works.But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">c) Accompany it with the information you received as to the offer to distribute corresponding source code.(This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The source code for a work means the preferred form of the work for making modifications to it.For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable.However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License.Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">5. You are not required to accept this License, since you have not signed it.However, nothing else grants you permission to modify or distribute the Program or its derivative works.These actions are prohibited by law if you do not accept this License.Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions.You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License.If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all.For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices.Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded.In such case, this License incorporates the limitation as if written in the body of this 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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time.Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Each version is given a distinguishing version number.If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation.If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission.For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this.Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NO WARRANTY</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">END OF TERMS AND CONDITIONS</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How to Apply These Terms to Your New Programs</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To do so, attach the following notices to the program.It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;one line to give the program's name and a brief idea of what it does.&gt; Copyright (C) &lt;year&gt;&lt;name of author&gt;</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Also add information on how to contact you by electronic and paper mail.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If the program is interactive, make it output a short notice like this when it starts in an interactive mode:</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License.Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary.Here is a sample; alter the names:</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;signature of Ty Coon&gt;, 1 April 1989 Ty Coon, President of Vice</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;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This General Public License does not permit incorporating your program into proprietary programs.If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library.If this is what you want to do, use the GNU Lesser General Public License instead of this 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;"></p></body></html> 0 Qt::Horizontal 40 20 Zamknij Qt::Horizontal 40 20 pbClose clicked() frmAbout close() 300 318 259 169 qnapi-0.1.5/src/0000755000175000017500000000000011015004533013012 5ustar patrykpatrykqnapi-0.1.5/src/movieinfo.cpp0000644000175000017500000000244211000145225015511 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "movieinfo.h" MovieInfo::MovieInfo(const QString & filename) { fps = width = height = time = 0; isErr = false; QFile file(filename); if(!file.open(QIODevice::ReadOnly)) { isErr = true; return; } char buff[4]; file.read(buff, 4); if(strncmp(buff, RIFF_HEADER, 4) != 0) { isErr = true; return; } MainAVIHeader hdr; if(!file.seek(0x20)) { isErr = true; file.close(); return; } if(!file.read((char*)&hdr, sizeof(MainAVIHeader))) { isErr = true; file.close(); return; } file.close(); width = hdr.dwWidth; height = hdr.dwHeight; fps = 1000000.0f/(float)hdr.dwMicroSecPerFrame; time = (int)ceil((float)hdr.dwTotalFrames / fps); } qnapi-0.1.5/src/main.cpp0000644000175000017500000000503311015002433014440 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include #include #include #include #include #include "version.h" #include "qnapiconfig.h" #include "qnapiapp.h" #include "qnapicli.h" int main(int argc, char **argv) { QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QStringList args; for(int i = 1; i < argc; i++) { QString p = argv[i]; if(p.startsWith("file://")) p = p.remove(0, 7); if(QFileInfo(p).isFile()) args << p; } #ifndef Q_WS_WIN QNapiCli *cliApp = new QNapiCli(argc, argv); bool useGui = !cliApp->analyze(); #else bool useGui = true; #endif QNapiApp app(argc, argv, useGui); QNapiApp::setApplicationName("QNapi"); #ifndef Q_WS_WIN if(!useGui) { int r = cliApp->exec(); delete cliApp; return r; } else { delete cliApp; } #endif app.setQuitOnLastWindowClosed(false); if(!app.isInstanceAllowed()) { for(int i = 0; i < args.size(); i++) app.sendRequest(args[i]); return 0; } if(GlobalConfig().firstRun()) { if(QMessageBox::question(0, QObject::tr("Pierwsze uruchomienie"), QObject::tr("To jest pierwsze uruchomienie programu QNapi. Czy chcesz go " "teraz skonfigurować?"), QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes ) { app.showOptions(); } } // Jesli podano parametry, ustawiamy tzw. batch mode if(args.size() > 0) { app.progress()->enqueueFiles(args); app.progress()->setBatchMode(true); if(!app.progress()->download()) return 1; } // Jesli nie dzialamy w trybie pobierania, mozemy ew. utworzyc ikone w tray-u // badz pokazac okno wyboru plikow z filmami if(!app.progress()->isBatchMode()) { // Jesli nie ma traya, od razu wyswietlamy okienko z wyborem pliku if(!QSystemTrayIcon::isSystemTrayAvailable()) { app.progress()->setBatchMode(true); app.showOpenDialog(); } else // Jesli ikona w tray-u jest obsligiwana, tworzymy ja { app.createTrayIcon(); } } return app.exec(); } qnapi-0.1.5/src/frmcorrect.cpp0000644000175000017500000001252311014655601015676 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmcorrect.h" frmCorrect::frmCorrect(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); connect(ui.pbMovieSelect, SIGNAL(clicked()), this, SLOT(selectMovie())); connect(ui.pbSubtitlesSelect, SIGNAL(clicked()), this, SLOT(selectSubtitles())); connect(ui.leMovieSelect, SIGNAL(textChanged(QString)), this, SLOT(checkPostEnable())); connect(ui.leSubtitlesSelect, SIGNAL(textChanged(QString)), this, SLOT(checkPostEnable())); connect(ui.teComment, SIGNAL(textChanged()), this, SLOT(checkPostEnable())); connect(ui.pbPost, SIGNAL(clicked()), this, SLOT(pbPostClicked())); connect(&postThread, SIGNAL(postFinished(bool)), this, SLOT(postFinished(bool))); connect(&postThread, SIGNAL(invalidUserPass()), this, SLOT(invalidUserPass())); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmCorrect::closeEvent(QCloseEvent *event) { if(postThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać wysyłanie poprawki?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { pbPostClicked(); } event->ignore(); } else event->accept(); } void frmCorrect::selectMovie() { QString fileName; QNapiOpenDialog openDialog(this, tr("Wskaż plik z filmem"), GlobalConfig().previousDialogPath(), QNapiOpenDialog::Movies); if(openDialog.selectFile()) { fileName = openDialog.selectedFiles().first(); GlobalConfig().setPreviousDialogPath(openDialog.directory().path()); } if(!fileName.isEmpty() && QFile::exists(fileName)) ui.leMovieSelect->setText(fileName); QFileInfo fi(fileName); QString propSubtitleFile = fi.path() + "/" + fi.completeBaseName() + ".txt"; if(QFile::exists(propSubtitleFile)) ui.leSubtitlesSelect->setText(propSubtitleFile); } void frmCorrect::selectSubtitles() { QString fileName; QNapiOpenDialog openDialog(this, tr("Wskaż plik z napisami"), GlobalConfig().previousDialogPath(), QNapiOpenDialog::Subtitles); if(openDialog.selectFile()) { fileName = openDialog.selectedFiles().first(); GlobalConfig().setPreviousDialogPath(openDialog.directory().path()); } if(!fileName.isEmpty() && QFile::exists(fileName)) ui.leSubtitlesSelect->setText(fileName); } void frmCorrect::checkPostEnable() { ui.pbPost->setEnabled( QFile::exists(ui.leMovieSelect->text()) && QFile::exists(ui.leSubtitlesSelect->text()) && !ui.teComment->toPlainText().isEmpty() ); ui.lbAction->setText(ui.pbPost->isEnabled() ? tr("Teraz możesz wysłać poprawione napisy.") : tr("Wypełnij wszystkie pola, aby wysłać poprawkę")); } void frmCorrect::pbPostClicked() { if(!postThread.isRunning()) { ui.leMovieSelect->setEnabled(false); ui.pbMovieSelect->setEnabled(false); ui.leSubtitlesSelect->setEnabled(false); ui.pbSubtitlesSelect->setEnabled(false); ui.teComment->setEnabled(false); ui.pbPost->setText(tr("Zatrzymaj")); ui.lbAction->setText(tr("Wysyłanie poprawki do serwera...")); postThread.setPostParams(ui.leMovieSelect->text(), ui.leSubtitlesSelect->text(), ui.teComment->toPlainText(), (ui.cbLanguage->currentIndex() == 0) ? "PL" : "ENG"); postThread.start(); } else { postThread.requestAbort(); ui.lbAction->setText(tr("Przerywanie wysyłania...")); ui.pbPost->setEnabled(false); qApp->processEvents(); } } void frmCorrect::postFinished(bool interrupted) { ui.leMovieSelect->setEnabled(true); ui.pbMovieSelect->setEnabled(true); ui.leSubtitlesSelect->setEnabled(true); ui.pbSubtitlesSelect->setEnabled(true); ui.teComment->setEnabled(true); ui.pbPost->setEnabled(true); ui.pbPost->setText(tr("Wyślij")); if(interrupted) { ui.lbAction->setText(tr("Przerwano wysyłanie poprawki.")); } else { switch(postThread.taskResult) { case QNapiProjektEngine::NAPI_FAIL: ui.lbAction->setText(tr("Błąd podczas wysyłania poprawki.")); break; default: ui.lbAction->setText(tr("Poprawka wysłana.")); } } } void frmCorrect::invalidUserPass() { QMessageBox::information(this, tr("Błąd!"), QString(tr("Nazwa użytkownika lub hasło jest niepoprawne."))); } void PostThread::run() { abort = false; if(!QNapiProjektEngine::checkUser(GlobalConfig().nick(), GlobalConfig().pass())) { emit invalidUserPass(); emit postFinished(true); return; } if(abort) { postFinished(true); return; } QNapiProjektEngine *napi; if((napi = new QNapiProjektEngine(movie, subtitles))) { taskResult = napi->uploadSubtitles(language, GlobalConfig().nick(), GlobalConfig().pass(), true, comment); delete napi; } postFinished(); } qnapi-0.1.5/src/frmupload.cpp0000644000175000017500000002221311014655601015516 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmupload.h" frmUpload::frmUpload(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); connect(ui.pbSelectDirectory, SIGNAL(clicked()), this, SLOT(selectDirectory())); connect(ui.leSelectDirectory, SIGNAL(textChanged(QString)), this, SLOT(leSelectDirectoryChanged())); connect(ui.pbScan, SIGNAL(clicked()), this, SLOT(pbScanClicked())); connect(&scanThread, SIGNAL(scanFinished(bool)), this, SLOT(scanFinished(bool))); connect(&scanThread, SIGNAL(folderChange(QString)), this, SLOT(folderChange(QString))); connect(ui.pbUpload, SIGNAL(clicked()), this, SLOT(pbUploadClicked())); connect(&uploadThread, SIGNAL(finished()), this, SLOT(uploadFinished())); connect(&uploadThread, SIGNAL(progressChange(int)), ui.pbProgress, SLOT(setValue(int))); connect(&uploadThread, SIGNAL(fileNameChange(QString)), this, SLOT(fileNameChange(QString))); connect(&uploadThread, SIGNAL(checkingUserPass()), this, SLOT(checkingUserPass())); connect(&uploadThread, SIGNAL(invalidUserPass()), this, SLOT(invalidUserPass())); if(QFileInfo(GlobalConfig().previousDialogPath()).isDir()) ui.leSelectDirectory->setText(GlobalConfig().previousDialogPath()); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmUpload::closeEvent(QCloseEvent *event) { if(scanThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać skanowanie katalogów?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { scanThread.requestAbort(); ui.lbAction->setText(tr("Kończenie zadań...")); qApp->processEvents(); scanThread.wait(); event->accept(); } else { event->ignore(); } return; } else if(uploadThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać wysyłanie napisów?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { pbUploadClicked(); } event->ignore(); } else event->accept(); } void frmUpload::selectDirectory() { QString dir = QFileInfo(ui.leSelectDirectory->text()).path(); dir = QDir().exists(dir) ? dir : GlobalConfig().previousDialogPath(); QNapiOpenDialog openDialog(this, tr("Wskaż katalog do skanowania"), dir, QNapiOpenDialog::None); if(openDialog.selectDirectory()) dir = openDialog.selectedFiles().first(); if(!dir.isEmpty() && QDir().exists(dir)) ui.leSelectDirectory->setText(dir); } void frmUpload::leSelectDirectoryChanged() { ui.pbScan->setEnabled(!ui.leSelectDirectory->text().isEmpty() ? QDir().exists(ui.leSelectDirectory->text()) : false); } void frmUpload::pbScanClicked() { if(!scanThread.isRunning()) { ui.leSelectDirectory->setEnabled(false); ui.pbSelectDirectory->setEnabled(false); ui.pbScan->setText(tr("Przerwij")); ui.lbAction->setText(tr("Skanowanie folderów...")); ui.lbFoldersCount->setEnabled(false); ui.lbFoldersCount->setText(tr("Folderów: 0")); ui.lbMoviesCount->setEnabled(false); ui.lbMoviesCount->setText(tr("Filmów: 0")); ui.lbSubtitlesCount->setEnabled(false); ui.lbSubtitlesCount->setText(tr("Napisów: 0")); ui.pbProgress->setEnabled(false); ui.pbUpload->setEnabled(false); scanThread.setSearchPath(ui.leSelectDirectory->text()); scanThread.start(); } else { scanThread.requestAbort(); ui.lbAction->setText(tr("Przerywanie skanowania...")); ui.pbScan->setEnabled(false); qApp->processEvents(); scanThread.wait(); ui.pbScan->setEnabled(true); scanFinished(false); } } void frmUpload::scanFinished(bool result) { ui.leSelectDirectory->setEnabled(true); ui.pbSelectDirectory->setEnabled(true); ui.pbScan->setText(tr("Skanuj")); ui.lbAction->setText(""); if(result) { if(scanThread.fileList.size() == 0) { QMessageBox::warning(this, tr("Nie znaleziono napisów"), tr("W wybranym folderze nie znaleziono żadnych napisów!")); } else { ui.lbAction->setText(tr("Teraz możesz wysłać napisy na serwer.")); ui.lbFoldersCount->setEnabled(true); ui.lbFoldersCount->setText(tr("Folderów: ") + "" + QString::number(scanThread.folders) + ""); ui.lbMoviesCount->setEnabled(true); ui.lbMoviesCount->setText(tr("Filmów: ") + "" + QString::number(scanThread.movies) + ""); ui.lbSubtitlesCount->setEnabled(true); ui.lbSubtitlesCount->setText(tr("Napisów: ") + "" + QString::number(scanThread.subtitles) + ""); ui.pbProgress->setEnabled(true); ui.pbUpload->setEnabled(true); } } } void frmUpload::pbUploadClicked() { if(!uploadThread.isRunning()) { ui.lbSelectDirectory->setEnabled(false); ui.leSelectDirectory->setEnabled(false); ui.pbSelectDirectory->setEnabled(false); ui.pbScan->setEnabled(false); ui.pbUpload->setText(tr("Przerwij wysyłanie")); ui.pbProgress->setValue(0); uploadThread.setMovieList(scanThread.fileList); uploadThread.start(); } else { uploadThread.requestAbort(); ui.lbAction->setText(tr("Przerywanie wysyłania...")); ui.pbUpload->setEnabled(false); qApp->processEvents(); } } void frmUpload::folderChange(const QString & folder) { ui.lbAction->setText(tr("Skanowanie katalogu ") + folder + ""); } void frmUpload::fileNameChange(const QString & filename) { ui.lbAction->setText(tr("Wysyłanie napisów dla ") + filename + ""); } void frmUpload::checkingUserPass() { ui.lbAction->setText(tr("Sprawdzanie nazwy użytkownika i hasła...")); } void frmUpload::uploadFinished() { ui.lbSelectDirectory->setEnabled(true); ui.leSelectDirectory->setEnabled(true); ui.pbSelectDirectory->setEnabled(true); ui.pbScan->setEnabled(true); ui.pbUpload->setEnabled(true); ui.pbUpload->setText(tr("Wyślij napisy do serwera")); ui.pbProgress->setValue(0); if(!uploadThread.invalidUP) { ui.lbAction->setText(tr("Zakończono wysyłanie napisów.")); QString msg = tr("Wysłano napisów: %1\n").arg(uploadThread.added_new+uploadThread.added_ok) + tr("W tym zupełnie nowych: %1\n").arg(uploadThread.added_new) + tr("Nie udało się wysłać: %1\n").arg(uploadThread.failed); QMessageBox::information(this, tr("Rezultat wysyłania"), msg); } } void frmUpload::invalidUserPass() { ui.lbAction->setText(tr("Nazwa użytkownika lub hasło jest niepoprawne.")); QMessageBox::information(this, tr("Błąd!"), QString(tr("Nazwa użytkownika lub hasło jest niepoprawne."))); } void ScanThread::run() { abort = false; folders = movies = subtitles = 0; fileList.clear(); searchFilters.clear(); searchFilters << "*.avi" << "*.asf" << "*.divx" << "*.dat" << "*.mkv" << "*.mov" << "*.mp4" << "*.mpeg" << "*.mpg" << "*.ogm" << "*.rm" << "*.rmvb" << "*.wmv"; emit scanFinished(doScan(searchPath)); } bool ScanThread::doScan(const QString & path) { QString myPath = QFileInfo(path).absoluteFilePath(); if(!QDir().exists(myPath)) return false; emit folderChange(myPath); ++folders; QFileInfoList list = QDir(myPath).entryInfoList(searchFilters, QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::Hidden); for(QFileInfoList::iterator p=list.begin(); p != list.end(); p++) { if(abort) return false; if((*p).isDir() && ((*p).absoluteFilePath() != myPath)) { if(!doScan((*p).absoluteFilePath())) return false; } else { if(!QFile::exists((*p).absoluteFilePath())) continue; ++movies; if(QFile::exists((*p).absolutePath() + "/" + (*p).completeBaseName() + ".txt")) { ++subtitles; fileList << (*p).absoluteFilePath(); } } } return true; } void UploadThread::run() { added_new = added_ok = failed = 0; abort = false; invalidUP = false; emit checkingUserPass(); if(!QNapiProjektEngine::checkUser(GlobalConfig().nick(), GlobalConfig().pass())) { invalidUP = true; emit invalidUserPass(); return; } if(abort) return; int size = movieList.size(); QNapiProjektEngine *napi; for(int i = 0; i < size; i++) { QFileInfo fi(movieList[i]); napi = new QNapiProjektEngine(movieList[i], fi.path() + "/" + fi.completeBaseName() + ".txt"); if(!napi) continue; emit fileNameChange(fi.fileName()); emit progressChange(i * 100 / size); switch( napi->uploadSubtitles(GlobalConfig().language(), GlobalConfig().nick(), GlobalConfig().pass(), false ) ) { case QNapiProjektEngine::NAPI_ADDED_NEW: ++added_new; break; case QNapiProjektEngine::NAPI_FAIL: ++failed; break; default: ++added_ok; break; } delete napi; if(abort) break; } emit progressChange(100); } qnapi-0.1.5/src/frmprogress.cpp0000644000175000017500000002121711014605667016110 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmprogress.h" #include "qnapiapp.h" frmProgress::frmProgress(QWidget * parent, Qt::WFlags f) : QWidget(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_DeleteOnClose, false); setAttribute(Qt::WA_QuitOnClose, false); setBatchMode(false); connect(&getThread, SIGNAL(fileNameChange(const QString &)), ui.lbFileName, SLOT(setText(const QString &))); connect(&getThread, SIGNAL(actionChange(const QString &)), ui.lbAction, SLOT(setText(const QString &))); connect(&getThread, SIGNAL(progressChange(int, int, float)), this, SLOT(updateProgress(int, int, float))); connect(&getThread, SIGNAL(finished()), this, SLOT(downloadFinished())); } void frmProgress::receiveRequest(const QString & request) { enqueueFile(request); if(!getThread.isRunning()) download(); raise(); activateWindow(); } void frmProgress::enqueueFile(const QString & file) { static QMutex locker; locker.lock(); if(QFile::exists(file)) { getThread.queue << file; updateProgress(-1, getThread.queue.size(), -1); } locker.unlock(); } void frmProgress::enqueueFiles(const QStringList & fileList) { for(int i = 0; i < fileList.size(); i++) { enqueueFile(fileList.at(i)); } } bool frmProgress::download() { if(!QNapiAbstractEngine::checkP7ZipPath()) { QMessageBox::warning(0, tr("Brak programu p7zip!"), tr("Ścieżka do programu p7zip jest nieprawidłowa!")); return false; } if(!QNapiAbstractEngine::checkTmpPath()) { QMessageBox::warning(0, tr("Nieprawidłowy katalog tymczasowy!"), tr("Nie można pisać do katalogu tymczasowego! Sprawdź swoje ustawienia.")); return false; } if(getThread.queue.isEmpty()) { QMessageBox::warning(0, tr("Brak plików!"), tr("Nie wskazano filmów do pobrania napisów!")); return false; } if(!isVisible()) { move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); show(); } showSummary = true; closeRequested = false; ui.pbCancel->setEnabled(true); getThread.start(); return true; } void frmProgress::updateProgress(int current, int all, float stageProgress) { static int lastCurrent, lastAll; static float lastStageProgress; static QMutex m; m.lock(); if(current >= 0) lastCurrent = current; if(all >= 0) lastAll = all; if(stageProgress >= 0) lastStageProgress = stageProgress; QString windowTitle = (lastAll > 1) ? QString(tr("QNapi - pobieranie napisów (%1/%2)")).arg(lastCurrent + 1).arg(lastAll) : QString(tr("QNapi - pobieranie napisów...")); setWindowTitle(windowTitle); ui.pbProgress->setMaximum(lastAll * 100); ui.pbProgress->setValue(lastCurrent * 100 + (int)(lastStageProgress * 100)); m.unlock(); } void frmProgress::downloadFinished() { hide(); QStringList queue = getThread.queue; getThread.queue.clear(); mutex.lock(); if(showSummary) { if(!getThread.criticalMessage.isEmpty()) { QMessageBox::critical(0, tr("Błąd krytyczny!"), getThread.criticalMessage); } else if(queue.size() > 1) { bool mac = #ifdef Q_WS_MAC true; #else false; #endif if(mac || batchMode) { if(getThread.napiSuccess > 0) { frmSummary summary; summary.setSuccessList(getThread.gotList); summary.setFailedList(getThread.failedList); summary.exec(); } else { QString msg = tr("Nie udało się dopasować napisów dla %1 %2!") .arg(getThread.napiFail) .arg(tr((getThread.napiFail == 1) ? "pliku" : "plików")); QMessageBox::information(0, tr("Zakończono pobieranie napisów"), msg); } } else { QString msg; if(getThread.napiSuccess > 0) msg += tr("Dopasowano napisy dla %1 %2.%3").arg(getThread.napiSuccess) .arg(tr((getThread.napiSuccess > 1) ? "plików" : "pliku")) .arg((getThread.napiFail > 0) ? "\n" : ""); if(getThread.napiFail > 0) msg += tr("Nie udało się dopasować napisów dla %1 %2!").arg(getThread.napiFail) .arg(tr((getThread.napiFail > 1) ? "plików" : "pliku")); #ifndef Q_WS_MAC if(QSystemTrayIcon::supportsMessages() && !batchMode) ((QNapiApp*)qApp)->showTrayMessage(tr("Zakończono pobieranie napisów"), msg); else #endif QMessageBox::information(0, tr("Zakończono pobieranie napisów"), msg); } } else { if(getThread.napiSuccess == 1) { QString msg = tr("Pobrano napisy dla pliku '%1'.").arg(QFileInfo(queue[0]).fileName()); #ifndef Q_WS_MAC if(QSystemTrayIcon::supportsMessages() && !batchMode) ((QNapiApp*)qApp)->showTrayMessage(tr("Pobrano napisy"), msg); else #endif QMessageBox::information(0, tr("Pobrano napisy"), msg); } else { QString msg = tr("Nie znaleziono napisów dla:\n%1.").arg(QFileInfo(queue[0]).fileName()); #ifndef Q_WS_MAC if(QSystemTrayIcon::supportsMessages() && !batchMode) ((QNapiApp*)qApp)->showTrayMessage(tr("Nie znaleziono napisów"), msg); else #endif QMessageBox::information(0, tr("Nie znaleziono napisów"), msg); } } } if(closeRequested) close(); mutex.unlock(); if(batchMode) qApp->quit(); } void frmProgress::closeEvent(QCloseEvent *event) { if(getThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać pobieranie napisów?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes ) { event->ignore(); return; } else { mutex.lock(); showSummary = false; getThread.requestAbort(); ui.lbAction->setText(tr("Kończenie zadań...")); ui.lbFileName->setText("..."); ui.pbCancel->setEnabled(false); qApp->processEvents(); closeRequested = true; mutex.unlock(); event->ignore(); } } else { event->accept(); } } void frmProgress::dragEnterEvent(QDragEnterEvent *event) { QUrl url(event->mimeData()->urls().at(0)); QFileInfo fi(url.toLocalFile()); if(fi.exists() && fi.isFile()) event->acceptProposedAction(); } void frmProgress::dropEvent(QDropEvent *event) { QList urlList; QFileInfo info; urlList = event->mimeData()->urls(); foreach(QUrl url, urlList) { info.setFile(url.toLocalFile()); if(!info.exists() || !info.isFile()) continue; enqueueFile(url.toLocalFile()); } } void GetThread::run() { abort = false; criticalMessage.clear(); if(queue.size() <= 0) return; QString windowTitle, md5; napiSuccess = napiFail = 0; gotList.clear(); failedList.clear(); QNapiProjektEngine *napi; emit progressChange(0, queue.size(), 0.0f); for(int i = 0; i < queue.size(); i++) { napi = new QNapiProjektEngine(queue[i]); if(!napi) continue; QFileInfo fi(queue[i]); emit fileNameChange(fi.fileName()); emit progressChange(i, queue.size(), 0.1); emit actionChange(tr("Sprawdzanie uprawnień do katalogu z filmem...")); if(!napi->checkWritePermissions()) { emit criticalError(tr("Brak uprawnień zapisu do katalogu '%1'!").arg(QFileInfo(queue[i]).path())); delete napi; break; } emit progressChange(i, queue.size(), 0.3); emit actionChange(tr("Obliczanie sumy kontrolnej pliku...")); napi->checksum(); if(abort) { delete napi; return; } emit progressChange(i, queue.size(), 0.5f); emit actionChange(tr("Pobieranie napisów dla pliku...")); // pobieranie if(!napi->tryDownload()) { if(abort) { delete napi; return; } ++napiFail; failedList << queue[i]; delete napi; continue; } if(abort) { delete napi; return; } emit progressChange(i, queue.size(), 0.7f); emit actionChange(tr("Dopasowywanie napisów...")); // dopasowywanie if(!napi->tryMatch()) { if(abort) { delete napi; return; } ++napiFail; failedList << queue[i]; delete napi; continue; } if(abort) { delete napi; return; } ++napiSuccess; gotList << queue[i]; if(GlobalConfig().ppEnabled()) { emit progressChange(i, queue.size(), 0.9); emit actionChange(tr("Przetwarzanie napisów...")); napi->doPostProcessing(); } emit progressChange(i, queue.size(), 1); delete napi; } emit progressChange(queue.size() - 1, queue.size(), 1); } qnapi-0.1.5/src/qdraglistwidget.h0000644000175000017500000000301511014772247016375 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QDRAGLISTWIDGET__H__ #define __QDRAGLISTWIDGET__H__ #include class QDragListWidget : public QListWidget { Q_OBJECT public: QDragListWidget(QWidget *parent = 0, const QIcon & widgetIcon = QIcon()) : QListWidget(parent) { setAcceptDrops(true); setWidgetIcon(widgetIcon); } void addItem(const QString & label); void addItem(QListWidgetItem * item); void addItems(const QStringList & labels); void setWidgetIcon(const QIcon & icon) { widgetIcon = icon; } void MoveAll(QDragListWidget *another); void MoveSelected(QDragListWidget *another); signals: void dragFinished(); protected: void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); QStringList mimeTypes() const; Qt::DropActions supportedDropActions () const; void mouseMoveEvent(QMouseEvent *event); private: QPoint dragStartPosition; QIcon widgetIcon; }; #endif qnapi-0.1.5/src/qnapiconfig.h0000644000175000017500000000524611005156740015477 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPICONFIG__H__ #define __QNAPICONFIG__H__ #include #include #include #include #include #include #include #include #include "version.h" class QNapiConfig { public: void reload(); void save(); bool firstRun(); QString version(); QString p7zipPath(); void setP7zipPath(const QString & path); QString tmpPath(); void setTmpPath(const QString & path); QString nick(); void setNick(const QString & nick); QString pass(); void setPass(const QString & pass); QString language(); void setLanguage(const QString & language); bool noBackup(); void setNoBackup(bool noBackup); bool useBrushedMetal(); void setUseBrushedMetal(bool use); bool ppEnabled(); void setPpEnabled(bool enable); bool ppChangeEncoding(); void setPpChangeEncoding(bool change); bool ppAutoDetectEncoding(); void setPpAutoDetectEncoding(bool change); QString ppEncodingFrom(); void setPpEncodingFrom(const QString & encoding); QString ppEncodingTo(); void setPpEncodingTo(const QString & encoding); bool ppShowAllEncodings(); void setPpShowAllEncodings(bool show); bool ppRemoveLines(); void setPpRemoveLines(bool remove); QStringList ppRemoveWords(); void setPpRemoveWords(const QStringList & words); bool ppChangePermissions(); void setPpChangePermissions(bool change); QString ppPermissions(); void setPpPermissions(const QString & permissions); QString previousDialogPath(); void setPreviousDialogPath(const QString & path); QStringList scanFilters(); void setScanFilters(const QStringList & filters); QString scanSkipFilters(); void setScanSkipFilters(const QString & filters); bool scanSkipIfSubtitlesExists(); void setScanSkipIfSubtitlesExists(bool skip); QString lastScanDir(); void setLastScanDir(const QString & dir); private: QNapiConfig(); QNapiConfig(const QNapiConfig &); ~QNapiConfig(); QSettings *settings; friend QNapiConfig& GlobalConfig(); }; QNapiConfig & GlobalConfig(); #endif qnapi-0.1.5/src/frmprogress.h0000644000175000017500000000454611014556643015562 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMPROGRESS__H__ #define __FRMPROGRESS__H__ #include "ui_frmprogress.h" #include #include #include #include #include #include #include #include #include "frmsummary.h" #include "qnapithread.h" #include "qnapiconfig.h" #include "qnapiprojektengine.h" #include "qnapiopendialog.h" class GetThread : public QNapiThread { Q_OBJECT signals: void fileNameChange(const QString & newfileName); void actionChange(const QString & newAction); void progressChange(int current, int all, float stageProgress); void criticalError(const QString & message); private slots: void setCriticalMessage(const QString & msg) { criticalMessage = msg; } public: GetThread() { connect(this, SIGNAL(criticalError(const QString &)), this, SLOT(setCriticalMessage(const QString &))); } void run(); QStringList queue, gotList, failedList; int napiSuccess, napiFail; QString criticalMessage; }; class frmProgress: public QWidget { Q_OBJECT public: frmProgress(QWidget *parent = 0, Qt::WFlags f = 0); ~frmProgress(){}; public slots: void receiveRequest(const QString & request); void enqueueFile(const QString &file); void enqueueFiles(const QStringList &fileList); bool download(); void updateProgress(int current, int all, float stageProgress); void downloadFinished(); void setBatchMode(bool value) { batchMode = value; } bool isBatchMode() { return batchMode; } private: void closeEvent(QCloseEvent *event); void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); Ui::frmProgress ui; GetThread getThread; bool batchMode, showSummary, closeRequested; QMutex mutex; }; #endif qnapi-0.1.5/src/frmabout.h0000644000175000017500000000165011000145225015002 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMABOUT__H__ #define __FRMABOUT__H__ #include #include "ui_frmabout.h" #include "version.h" #include "qnapiconfig.h" class frmAbout: public QDialog { Q_OBJECT public: frmAbout(QWidget *parent = 0, Qt::WFlags f = 0); ~frmAbout() {}; private: Ui::frmAbout ui; }; #endif qnapi-0.1.5/src/qnapiprojektengine.h0000644000175000017500000000541011014347755017077 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPIPROJEKTENGINE__H__ #define __QNAPIPROJEKTENGINE__H__ #include #include #ifdef Q_WS_WIN // for SetFileAttributes #include #endif #include #include "qnapiabstractengine.h" #include "synchttp.h" #include "movieinfo.h" const unsigned long NAPI_10MB = 10485760; const QString napiZipPassword = "iBlm8NTigvru0Jr0"; const QString napiDownloadUrlTpl= "http://www.napiprojekt.pl/unit_napisy/dl.php" "?l=%1&f=%2&t=%3&v=other&kolejka=false&napios=Linux&nick=%4&pass=%5"; const QString napiCheckUserUrlTpl = "http://www.napiprojekt.pl/users_check.php?nick=%1&pswd=%2"; const QString napiUploadUrlTpl = "http://www.napiprojekt.pl/unit_napisy/upload.php" "?m_length=%1&m_resolution=%2x%3&m_fps=%4&m_hash=%5&m_filesize=%6"; const QString napiUploadUrlSimpleTpl = "http://www.napiprojekt.pl/unit_napisy/upload.php" "?m_hash=%5&m_filesize=%6"; const QString napiReportBadUrlTpl = "http://www.napiprojekt.pl/unit_napisy/zlenapisyadd.php"; const QString napiCreateUserUrlTpl = "http://www.napiprojekt.pl/users_add.php"; class QNapiProjektEngine : public QNapiAbstractEngine { public: enum UploadResult { NAPI_ADDED_NEW, NAPI_OK, NAPI_FAIL, NAPI_UNKNOWN }; enum ReportResult { NAPI_REPORTED, NAPI_NO_SUBTITLES, NAPI_NOT_REPORTED }; QNapiProjektEngine(const QString & movieFile, const QString & subtitlesFile = ""); ~QNapiProjektEngine(); QString checksum(const QString & filename, bool limit10M = true); QString checksum(); bool tryDownload(); bool tryMatch(); void cleanup(); static bool createUser(const QString & nick, const QString & pass, const QString & email, QString * response); static bool checkUser(const QString & nick, const QString & pass); UploadResult uploadSubtitles(const QString & language, const QString & nick, const QString & pass, bool correct = false, const QString & comment = ""); ReportResult reportBad(const QString & language, const QString & nick, const QString & pass, const QString & comment, QString *response); private: QString p7zipPath, lang, nick, pass, tmpFile; bool noBackup; QString napiFDigest(const QString & input); }; #endif qnapi-0.1.5/src/synchttp.h0000644000175000017500000000670410777410517015067 0ustar patrykpatryk/************************************************************************* Copyright (C) 2005 by Iulian M eti@erata.net syncRequest added by Krzemin Copyright (C) 2008 Krzemin This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *************************************************************************/ #ifndef ETKSYNCHTTP_H #define ETKSYNCHTTP_H #include #include #include /** * Provide a synchronous api over QHttp * Uses a QEventLoop to block until the request is completed * @author Iulian M */ class SyncHTTP: public QHttp { Q_OBJECT public: /// structors SyncHTTP( QObject * parent = 0 ) :QHttp(parent),requestID(-1),status(false){} SyncHTTP( const QString & hostName, quint16 port = 80, QObject * parent = 0 ) :QHttp(hostName,port,parent),requestID(-1),status(false){} virtual ~SyncHTTP(){} /// send GET request and wait until finished bool syncGet ( const QString & path, QIODevice * to = 0 ) { ///connect the requestFinished signal to our finished slot connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool))); /// start the request and store the requestID requestID = get(path, to); /// block until the request is finished loop.exec(); /// return the request status return status; } /// send POST request and wait until finished bool syncPost ( const QString & path, QIODevice * data, QIODevice * to = 0 ) { ///connect the requestFinished signal to our finished slot connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool))); /// start the request and store the requestID requestID = post(path, data , to); /// block until the request is finished loop.exec(); /// return the request status return status; } bool syncPost ( const QString & path, const QByteArray& data, QIODevice * to = 0 ) { /// create io device from QByteArray QBuffer buffer; buffer.setData(data); return syncPost(path,&buffer,to); } bool syncRequest ( const QHttpRequestHeader & header, QIODevice * data, QIODevice * to = 0 ) { connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool))); requestID = request(header, data , to); loop.exec(); return status; } bool syncRequest ( const QHttpRequestHeader & header, const QByteArray & data, QIODevice * to = 0 ) { QBuffer buffer; buffer.setData(data); return syncRequest(header, &buffer, to); } protected slots: virtual void finished(int idx, bool err) { /// check to see if it's the request we made if(idx!=requestID) return; /// set status of the request status = !err; /// end the loop loop.exit(); } private: /// id of current request int requestID; /// error status of current request bool status; /// event loop used to block until request finished QEventLoop loop; }; #endif qnapi-0.1.5/src/qmultiparthttprequest.cpp0000644000175000017500000000557611005072142020246 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qmultiparthttprequest.h" void QMultipartHttpRequest::addBoundary() { addElement(requestElement::ET_BOUNDARY); } void QMultipartHttpRequest::addEndingBoundary() { addElement(requestElement::ET_ENDING_BOUNDARY); } void QMultipartHttpRequest::addContentDisposition(const QString & contentDisposition) { addElement(requestElement::ET_CONTENT_DISPOSITION, contentDisposition.toAscii()); } void QMultipartHttpRequest::addContentType(const QString & contentType) { addElement(requestElement::ET_CONTENT_TYPE, contentType.toAscii()); } void QMultipartHttpRequest::addData(const QByteArray & data) { addElement(requestElement::ET_DATA, data); } void QMultipartHttpRequest::addData(const QString & data) { addElement(requestElement::ET_DATA, data.toAscii()); } QByteArray & QMultipartHttpRequest::requestStream() { generateBoundary(); QVector::iterator el; const char *endl = "\r\n"; buffer.clear(); for(el = elements.begin(); el != elements.end(); el++) { switch((*el).type) { case requestElement::ET_CONTENT_DISPOSITION: buffer += QString("Content-Disposition: form-data; ") + (*el).elementData + endl; break; case requestElement::ET_CONTENT_TYPE: buffer += QString("Content-Type: ") + (*el).elementData + endl; break; case requestElement::ET_BOUNDARY: buffer += QString("--") + boundary + endl; break; case requestElement::ET_ENDING_BOUNDARY: buffer += endl + QString("--") + boundary + QString("--") + endl; break; case requestElement::ET_DATA: buffer += endl + (*el).elementData + endl; break; } } return buffer; } QString & QMultipartHttpRequest::boundaryTxt() { return boundary; } void QMultipartHttpRequest::generateBoundary() { bool binarySafe; QVector::iterator el; QTime midnight(0, 0, 0); qsrand(midnight.secsTo(QTime::currentTime())); do { boundary = QString::number(qrand()); binarySafe = true; for(el = elements.begin(); el != elements.end(); el++) { if((*el).elementData.indexOf(boundary) >= 0) { binarySafe = false; break; } } } while (!binarySafe); } void QMultipartHttpRequest::addElement(requestElement::elementType type, const QByteArray & data) { requestElement el; el.type = type; el.elementData = data; elements.push_back(el); } qnapi-0.1.5/src/frmsummary.h0000644000175000017500000000206111011700631015362 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMSUMMARY__H__ #define __FRMSUMMARY__H__ #include #include #include #include "qnapiconfig.h" #include "ui_frmsummary.h" class frmSummary: public QDialog { Q_OBJECT public: frmSummary(QWidget *parent = 0, Qt::WFlags f = 0); ~frmSummary() {}; void setSuccessList(const QStringList & list); void setFailedList(const QStringList & list); private: Ui::frmSummary ui; }; #endif qnapi-0.1.5/src/qnapiconfig.cpp0000644000175000017500000001763411014646704016042 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qnapiconfig.h" QNapiConfig::QNapiConfig() { settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "qnapi"); } QNapiConfig::~QNapiConfig() { if(settings) delete settings; } void QNapiConfig::reload() { if(settings) delete settings; settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "qnapi"); } void QNapiConfig::save() { settings->setValue("qnapi/version", QNAPI_VERSION); settings->setValue("qnapi/firstrun", false); settings->sync(); } bool QNapiConfig::firstRun() { return settings->value("qnapi/firstrun", true).toBool(); } QString QNapiConfig::version() { return settings->value("qnapi/version", "").toString(); } QString QNapiConfig::p7zipPath() { // Odczytujemy z konfiguracji QString p7z_path = settings->value("qnapi/7z_path", "").toString(); if(!p7z_path.isEmpty() && QFileInfo(p7z_path).isExecutable()) return p7z_path; // Przeszukiwanie sciezek systemowych QString path = QProcess::systemEnvironment().filter(QRegExp("^PATH=(.*)$")).value(0); QStringList paths = path.mid(5).split(":"); paths.removeAll(""); if(paths.size() == 0) paths << "/usr/bin" << "/usr/local/bin"; QStringList binaries; binaries << "7z" << "7za" << "7zr"; for(QStringList::iterator i = paths.begin(); i != paths.end(); i++) { for(QStringList::iterator j = binaries.begin(); j != binaries.end(); j++) { p7z_path = (*i) + "/" + (*j); if(QFileInfo(p7z_path).isExecutable()) return p7z_path; } } #ifdef Q_WS_MAC // Pakiet binarny dla OS X, ktory przygotowal adrian5632 zawiera // program 7z w odpowiednim katalogu p7z_path = QFileInfo(QApplication::applicationDirPath() + "/../Resources/7z").absoluteFilePath(); if(QFileInfo(p7z_path).isExecutable()) return p7z_path; #endif #ifdef Q_WS_WIN // Pod systemem Windows program 7za.exe musi byc w tym samym katalogu, // co qnapi.exe p7z_path = QFileInfo(QApplication::applicationDirPath() + "/7za.exe").absoluteFilePath(); if(QFileInfo(p7z_path).isExecutable()) return p7z_path; #endif // Jesli wszystko inne zawiodlo...;) return "7z"; } void QNapiConfig::setP7zipPath(const QString & path) { settings->setValue("qnapi/7z_path", path); } QString QNapiConfig::tmpPath() { return settings->value("qnapi/tmp_path", QDir::tempPath()).toString(); } void QNapiConfig::setTmpPath(const QString & path) { settings->setValue("qnapi/tmp_path", path); } QString QNapiConfig::nick() { return settings->value("qnapi/nick", "").toString(); } void QNapiConfig::setNick(const QString & nick) { settings->setValue("qnapi/nick", nick); } QString QNapiConfig::pass() { return settings->value("qnapi/pass", "").toString(); } void QNapiConfig::setPass(const QString & pass) { settings->setValue("qnapi/pass", pass); } QString QNapiConfig::language() { return settings->value("qnapi/language", "PL").toString(); } void QNapiConfig::setLanguage(const QString & language) { settings->setValue("qnapi/language", language); } bool QNapiConfig::noBackup() { return settings->value("qnapi/no_backup", false).toBool(); } void QNapiConfig::setNoBackup(bool noBackup) { settings->setValue("qnapi/no_backup", noBackup); } bool QNapiConfig::useBrushedMetal() { return settings->value("qnapi/use_brushed_metal", true).toBool(); } void QNapiConfig::setUseBrushedMetal(bool use) { settings->setValue("qnapi/use_brushed_metal", use); } bool QNapiConfig::ppEnabled() { return settings->value("qnapi/post_processing", false).toBool(); } void QNapiConfig::setPpEnabled(bool enable) { settings->setValue("qnapi/post_processing", enable); } bool QNapiConfig::ppChangeEncoding() { return settings->value("qnapi/change_encoding", false).toBool(); } void QNapiConfig::setPpChangeEncoding(bool change) { settings->setValue("qnapi/change_encoding", change); } bool QNapiConfig::ppAutoDetectEncoding() { return settings->value("qnapi/auto_detect_encoding", false).toBool(); } void QNapiConfig::setPpAutoDetectEncoding(bool change) { settings->setValue("qnapi/auto_detect_encoding", change); } QString QNapiConfig::ppEncodingFrom() { return settings->value("qnapi/enc_from", "windows-1250").toString(); } void QNapiConfig::setPpEncodingFrom(const QString & encoding) { settings->setValue("qnapi/enc_from", encoding); } QString QNapiConfig::ppEncodingTo() { return settings->value("qnapi/enc_to", "UTF-8").toString(); } void QNapiConfig::setPpEncodingTo(const QString & encoding) { settings->setValue("qnapi/enc_to", encoding); } bool QNapiConfig::ppShowAllEncodings() { return settings->value("qnapi/show_all_encodings", false).toBool(); } void QNapiConfig::setPpShowAllEncodings(bool show) { settings->setValue("qnapi/show_all_encodings", show); } bool QNapiConfig::ppRemoveLines() { return settings->value("qnapi/remove_lines", false).toBool(); } void QNapiConfig::setPpRemoveLines(bool remove) { settings->setValue("qnapi/remove_lines", remove); } QStringList QNapiConfig::ppRemoveWords() { QStringList defaultRemoveWords; defaultRemoveWords << "movie info" << "synchro "; return settings->value("qnapi/remove_words", defaultRemoveWords).toStringList(); } void QNapiConfig::setPpRemoveWords(const QStringList & words) { settings->setValue("qnapi/remove_words", words); } bool QNapiConfig::ppChangePermissions() { return settings->value("qnapi/change_permissions", false).toBool(); } void QNapiConfig::setPpChangePermissions(bool change) { settings->setValue("qnapi/change_permissions", change); } QString QNapiConfig::ppPermissions() { bool ok; int perm = settings->value("qnapi/permissions", 644).toInt(&ok); if(!ok || perm > 777) perm = 644; QString str = QString("%1").arg(perm); while(str.size() < 3) str = QString("0") + str; return str; } void QNapiConfig::setPpPermissions(const QString & permissions) { bool ok; int perm = permissions.toInt(&ok); if(ok && perm <= 777) { QString str = QString("%1").arg(perm); while(str.size() < 3) str = QString("0") + str; settings->setValue("qnapi/permissions", str); } } QString QNapiConfig::previousDialogPath() { QString path = settings->value("qnapi/prev_dialog_path", "").toString(); return (QDir(path).exists() ? path : QDir::homePath()); } void QNapiConfig::setPreviousDialogPath(const QString & path) { settings->setValue("qnapi/prev_dialog_path", path); } QStringList QNapiConfig::scanFilters() { QStringList defaultScanFilters; defaultScanFilters << "*.avi *.asf *.divx *.dat *.mkv *.mov *.mp4 *.mpeg" " *.mpg *.ogm *.rm *.rmvb *.wmv" << "*.*"; return settings->value("scan/filters", defaultScanFilters).toStringList(); } void QNapiConfig::setScanFilters(const QStringList & filters) { settings->setValue("scan/filters", filters); } QString QNapiConfig::scanSkipFilters() { return settings->value("scan/skip_filters", "PL dubbing").toString(); } void QNapiConfig::setScanSkipFilters(const QString & filters) { settings->setValue("scan/skip_filters", filters); } bool QNapiConfig::scanSkipIfSubtitlesExists() { return settings->value("scan/skip_if_subtitles_exists", false).toBool(); } void QNapiConfig::setScanSkipIfSubtitlesExists(bool skip) { settings->setValue("scan/skip_if_subtitles_exists", skip); } QString QNapiConfig::lastScanDir() { return settings->value("scan/last_scan_dir", "").toString(); } void QNapiConfig::setLastScanDir(const QString & dir) { settings->setValue("scan/last_scan_dir", dir); } QNapiConfig & GlobalConfig() { static QNapiConfig cfg; return cfg; } qnapi-0.1.5/src/frmoptions.cpp0000644000175000017500000001664511014334373015741 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmoptions.h" #include "qnapiapp.h" frmOptions::frmOptions(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC if ( QSysInfo::MacintoshVersion == QSysInfo::MV_10_5) // bo na Leopardzie nie ma juz stylu BM { ui.cbUseBrushedMetal->setText(tr("Używaj przyciemnionych okien (Mac OS X Leopard)")); } setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #else ui.cbUseBrushedMetal->hide(); #endif #ifdef Q_WS_WIN // Pod Windowsami chowamy kontrolki odpowiadajace za zmiane uprawnien - i tak sie nie przydadza ui.cbChangePermissions->hide(); ui.lePermissions->hide(); #endif setAttribute(Qt::WA_QuitOnClose, false); connect(ui.le7zPath, SIGNAL(textChanged(const QString &)), this, SLOT(le7zPathChanged())); connect(ui.pb7zPathSelect, SIGNAL(clicked()), this, SLOT(select7zPath())); connect(ui.leTmpPath, SIGNAL(textChanged(const QString &)), this, SLOT(leTmpPathChanged())); connect(ui.pbTmpPathSelect, SIGNAL(clicked()), this, SLOT(selectTmpPath())); connect(ui.pbRegister, SIGNAL(clicked()), this, SLOT(pbRegisterClicked())); connect(ui.cbChangeEncoding, SIGNAL(clicked()), this, SLOT(changeEncodingClicked())); connect(ui.cbAutoDetectEncoding, SIGNAL(clicked()), this, SLOT(autoDetectEncodingClicked())); connect(ui.cbShowAllEncodings, SIGNAL(clicked()), this, SLOT(showAllEncodingsClicked())); connect(ui.cbUseBrushedMetal, SIGNAL(clicked()), this, SLOT(useBrushedMetalClicked())); showAllEncodings(); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmOptions::le7zPathChanged() { QFileInfo f(ui.le7zPath->text()); ui.le7zPath->setStyleSheet( f.isFile() && f.isExecutable() ? "" : "color:red;" ); } void frmOptions::select7zPath() { QString path7z = QFileDialog::getOpenFileName(this, tr("Wskaż ścieżkę do programu 7z"), QFileInfo(ui.le7zPath->text()).path()); if(!path7z.isEmpty()) { if(!QFileInfo(path7z).isExecutable()) QMessageBox::warning(this, tr("Niepoprawna ścieżka"), tr("Wskazana przez Ciebie ścieżka do programu 7z jest niepoprawna. Jeśli nie możesz " "odnaleźć programu 7z, spróbuj zainstalować pakiet p7zip-full.")); else ui.le7zPath->setText(path7z); } } void frmOptions::leTmpPathChanged() { QFileInfo f(ui.leTmpPath->text()); ui.leTmpPath->setStyleSheet( f.isDir() && f.isWritable() ? "" : "color:red;" ); } void frmOptions::selectTmpPath() { QString tmpDir = QFileDialog::getExistingDirectory(this, tr("Wskaż katalog tymczasowy"), QFileInfo(ui.leTmpPath->text()).path(), QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks); if(!tmpDir.isEmpty()) ui.leTmpPath->setText(QFileInfo(tmpDir).path()); } void frmOptions::pbRegisterClicked() { ((QNapiApp*)qApp)->showCreateUser(); readConfig(); } void frmOptions::changeEncodingClicked() { bool checked = ui.cbChangeEncoding->isChecked(); ui.cbEncFrom->setEnabled(checked); ui.lbConvert->setEnabled(checked); ui.lbConvertFrom->setEnabled(checked); ui.cbEncTo->setEnabled(checked); ui.cbAutoDetectEncoding->setEnabled(checked); ui.cbShowAllEncodings->setEnabled(checked); autoDetectEncodingClicked(); } void frmOptions::autoDetectEncodingClicked() { bool checkedCE = ui.cbChangeEncoding->isChecked(); bool checkedADE = ui.cbAutoDetectEncoding->isChecked(); ui.cbEncFrom->setEnabled(checkedCE && !checkedADE); ui.lbConvertFrom->setEnabled(checkedCE && !checkedADE); } void frmOptions::showAllEncodingsClicked() { QString encFrom = ui.cbEncFrom->currentText(); QString encTo = ui.cbEncTo->currentText(); if(ui.cbShowAllEncodings->isChecked()) { showAllEncodings(); } else { ui.cbEncFrom->clear(); ui.cbEncTo->clear(); QStringList codecs; codecs << "windows-1250" << "windows-1257" << "ISO-8859-2" << "ISO-8859-13" << "ISO-8859-16" << "UTF-8"; ui.cbEncFrom->addItems(codecs); ui.cbEncTo->addItems(codecs); } ui.cbEncFrom->setCurrentIndex(ui.cbEncFrom->findText(encFrom)); ui.cbEncTo->setCurrentIndex(ui.cbEncTo->findText(encTo)); } void frmOptions::showAllEncodings() { ui.cbEncFrom->clear(); ui.cbEncTo->clear(); QList codecs = QTextCodec::availableCodecs(); qSort(codecs.begin(), codecs.end()); for(QList::iterator i = codecs.begin(); i != codecs.end(); i++) { ui.cbEncFrom->addItem(*i); ui.cbEncTo->addItem(*i); } } void frmOptions::useBrushedMetalClicked() { setAttribute(Qt::WA_MacBrushedMetal, ui.cbUseBrushedMetal->isChecked()); } void frmOptions::writeConfig() { GlobalConfig().setP7zipPath(ui.le7zPath->text()); GlobalConfig().setTmpPath(ui.leTmpPath->text()); GlobalConfig().setNick(ui.leNick->text()); GlobalConfig().setPass(ui.lePass->text()); GlobalConfig().setLanguage((ui.cbLang->currentIndex() == 0) ? "PL" : "ENG"); GlobalConfig().setNoBackup(ui.cbNoBackup->isChecked()); GlobalConfig().setUseBrushedMetal(ui.cbUseBrushedMetal->isChecked()); GlobalConfig().setPpEnabled(ui.gbPpEnable->isChecked()); GlobalConfig().setPpChangeEncoding(ui.cbChangeEncoding->isChecked()); GlobalConfig().setPpAutoDetectEncoding(ui.cbAutoDetectEncoding->isChecked()); GlobalConfig().setPpEncodingFrom(ui.cbEncFrom->currentText()); GlobalConfig().setPpEncodingTo(ui.cbEncTo->currentText()); GlobalConfig().setPpShowAllEncodings(ui.cbShowAllEncodings->isChecked()); GlobalConfig().setPpRemoveLines(ui.cbRemoveLines->isChecked()); GlobalConfig().setPpRemoveWords(ui.teRemoveWords->toPlainText().split("\n")); GlobalConfig().setPpChangePermissions(ui.cbChangePermissions->isChecked()); GlobalConfig().setPpPermissions(ui.lePermissions->text()); GlobalConfig().save(); } void frmOptions::readConfig() { GlobalConfig().reload(); ui.le7zPath->setText(GlobalConfig().p7zipPath()); ui.leTmpPath->setText(GlobalConfig().tmpPath()); ui.leNick->setText(GlobalConfig().nick()); ui.lePass->setText(GlobalConfig().pass()); ui.cbLang->setCurrentIndex((GlobalConfig().language() == "PL") ? 0 : 1); ui.cbNoBackup->setChecked(GlobalConfig().noBackup()); ui.cbUseBrushedMetal->setChecked(GlobalConfig().useBrushedMetal()); ui.cbChangeEncoding->setChecked(GlobalConfig().ppChangeEncoding()); ui.cbAutoDetectEncoding->setChecked(GlobalConfig().ppAutoDetectEncoding()); ui.cbEncFrom->setCurrentIndex(ui.cbEncFrom->findText(GlobalConfig().ppEncodingFrom())); ui.cbEncTo->setCurrentIndex(ui.cbEncTo->findText(GlobalConfig().ppEncodingTo())); ui.cbShowAllEncodings->setChecked(GlobalConfig().ppShowAllEncodings()); ui.cbRemoveLines->setChecked(GlobalConfig().ppRemoveLines()); ui.teRemoveWords->setText(GlobalConfig().ppRemoveWords().join("\n")); ui.cbChangePermissions->setChecked(GlobalConfig().ppChangePermissions()); ui.lePermissions->setText(GlobalConfig().ppPermissions()); changeEncodingClicked(); showAllEncodingsClicked(); ui.gbPpEnable->setChecked(GlobalConfig().ppEnabled()); } qnapi-0.1.5/src/qcumber/0000755000175000017500000000000011015004532014447 5ustar patrykpatrykqnapi-0.1.5/src/qcumber/qcumber.h0000644000175000017500000000161110771434110016264 0ustar patrykpatryk/**************************************************************************** ** ** Created using Edyuk IDE 0.8.0 ** ** File : qcumber.h ** Date : Fri Feb 2 21:07:45 2007 ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef _QCUMBER_H_ #define _QCUMBER_H_ //#ifdef _QCUMBER_BUILD_ //#if (defined(QT_DLL) || defined(QT_SHARED)) && !defined(QT_PLUGIN) //#define QCUMBER_EXPORT Q_DECL_EXPORT //#else #define QCUMBER_EXPORT //#endif //#else //#define QCUMBER_EXPORT Q_DECL_IMPORT //#endif #include namespace QCumber { enum Events { FirstEvent = QEvent::User + 100, SystemRequestEvent = FirstEvent, CustomRequestEvent, LastEvent }; } #include #endif // _QCUMBER_H_ qnapi-0.1.5/src/qcumber/qinterprocesschannel.h0000644000175000017500000000360210771513632021071 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef _QINTER_PROCESS_CHANNEL_H_ #define _QINTER_PROCESS_CHANNEL_H_ #include "qcumber.h" /*! \file qinterprocesschannel.h \brief Definition of the QInterProcessChannel class. */ #include #include #include #include class QTimer; class QTcpServer; class QManagedSocket; class QCUMBER_EXPORT QInterProcessChannel : public QThread { Q_OBJECT public: QInterProcessChannel(QObject *p = 0); virtual ~QInterProcessChannel(); bool isServer() const; QString messageBuffer() const; public slots: void close(); void reconnect(); void sendMessage(); void sendMessage(const QString& s); void sendMessage(const QByteArray& b); void setMessageBuffer(const QString& s); signals: void connectionLost(); void message(const QString& s); void request(const QStringList& l); void gotServerRole(); void serverRoleChanged(bool y); protected: virtual void run(); private slots: void init(); void check(); void connection(); void message(const QString& m, QManagedSocket *s); private: QString sMsg; QHostAddress m_addr; quint16 m_port, m_max; QTcpServer *pServer; QTimer *pServerTimer; }; #endif // !_QINTER_PROCESS_CHANNEL_H_ qnapi-0.1.5/src/qcumber/qsingleapplication.cpp0000644000175000017500000000756211014303670021057 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "qsingleapplication.h" #include "qmanagedrequest.h" #include "qinterprocesschannel.h" #include /*! \brief Constructor */ QSingleApplication::QSingleApplication(int& argc, char **argv, bool useGui) : QApplication(argc, argv, useGui) { pChannel = new QInterProcessChannel(this); connect(pChannel, SIGNAL( message(QString) ), this , SLOT ( message(QString) ) ); connect(pChannel, SIGNAL( request(QStringList) ), this , SLOT ( request(QStringList) ) ); setMessagingPolicy(Signals); setInstanciationPolicy(None); } /*! \brief Destructor */ QSingleApplication::~QSingleApplication() { pChannel->close(); } /*! \return Wheter the creation of an instance is allowed. */ bool QSingleApplication::isInstanceAllowed() const { return pChannel->isServer(); } /*! \return The current messaging policy */ QSingleApplication::MessagingPolicy QSingleApplication::messagingPolicy() const { return m_messaging; } /*! \brief Sets the messaging policy \see messagingPolicy() */ void QSingleApplication::setMessagingPolicy(MessagingPolicy p) { m_messaging = p; } /*! \return The current instanciation policy */ QSingleApplication::InstanciationPolicy QSingleApplication::instanciationPolicy() const { return m_instanciation; } /*! \brief Sets the instanciation policy \see instanciationPolicy() */ void QSingleApplication::setInstanciationPolicy(InstanciationPolicy p) { m_instanciation = p; } /*! \brief Launchs the application if allowed \see instanciationPolicy() */ int QSingleApplication::exec() { int ret = -1; if ( isInstanceAllowed() ) { ret = QApplication::exec(); } else { switch ( instanciationPolicy() ) { case ForwardArguments : qWarning("QSingleApplication : forwarding parameters"); sendRequest(arguments()); break; default: qWarning("QSingleApplication : all instances already occupied"); break; } } return ret; } /*! \overload */ void QSingleApplication::sendRequest(const QString& s) { sendRequest(QStringList(s)); } /*! \brief sends a message to the running instance of the application \param l A list of arguments that make up a request to be sent. */ void QSingleApplication::sendRequest(const QStringList& l) { if ( !pChannel || l.isEmpty() ) return; /* qDebug("sending message to %s:%i over TCP/IP : \"%s\"", qPrintable(pManager->address().toString()), pManager->port(), msg.constData()); */ pChannel->sendMessage(QManagedRequest::joinArguments("--request", l)); } /*! \internal */ void QSingleApplication::message(const QString& s) { if ( s.isEmpty() ) return; switch ( messagingPolicy() ) { case Events : /* QRequestEvent *e = new QRequestEvent(s); postEvent(s); */ break; case Signals : emit request(s); break; default: break; } } /*! \internal */ void QSingleApplication::request(const QStringList& l) { if ( l.isEmpty() ) return; switch ( messagingPolicy() ) { case Events : /* QRequestEvent *e = new QRequestEvent(s); postEvent(s); */ break; case Signals : emit request(l.join(" | ")); break; default: break; } } /*! \internal */ bool QSingleApplication::event(QEvent *e) { return QApplication::event(e); } qnapi-0.1.5/src/qcumber/qmanagedrequest.cpp0000644000175000017500000000474110774664662020402 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "qmanagedrequest.h" /*! \file qmanagedrequest.cpp \brief Implementation of the QManagedRequest class. */ QManagedRequest::QManagedRequest(const QString& cmd, const QStringList& args) : sCommand(cmd), lArguments(args) { } QManagedRequest::QManagedRequest(const QManagedRequest& r) : sCommand(r.sCommand), lArguments(r.lArguments) { } QManagedRequest::~QManagedRequest() { sCommand.clear(); lArguments.clear(); } QManagedRequest QManagedRequest::createSystemRequest(const QStringList& args, int id) { QManagedRequest r("--request"); r.lArguments = args; r.lArguments.prepend( QString::number(id) ); return r; } QManagedRequest& QManagedRequest::operator = (const QManagedRequest& r) { sCommand = r.sCommand; lArguments = r.lArguments; return *this; } QString QManagedRequest::toString() const { return QString::fromLocal8Bit(joinArguments(sCommand, lArguments)); } QManagedRequest QManagedRequest::fromString(const QString& s) { QManagedRequest r(""); r.lArguments = splitArguments(s); r.sCommand = r.lArguments.takeAt(0); return r; } QStringList QManagedRequest::splitArguments(const QString& s) { int i = -1; QStringList d, l = s.split(QRegExp("\\s")); while ( ++i < l.count() ) { if ( l.at(i).startsWith("\"") ) { QString arg; do { arg += " "; arg += l.at(i); } while ( !arg.endsWith("\"") && (++i < l.count()) ); arg.remove(0, 2); if ( arg.endsWith("\"") ) arg.chop(1); d << arg; } else { d << l.at(i); } } return d; } QByteArray QManagedRequest::joinArguments(const QString& cmd, const QStringList& l) { QByteArray msg; msg += cmd.toLocal8Bit(); foreach ( QString a, l ) { if ( a.isEmpty() ) continue; if ( a.contains(QRegExp("\\s")) ) a = "\"" + a + "\""; msg += " "; msg += a.toLocal8Bit(); } return msg; } qnapi-0.1.5/src/qcumber/qinterprocesschannel_win32.cpp0000644000175000017500000001264310774673324022463 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2008 Krzemin ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "qinterprocesschannel_win32.h" /*! \class QInterProcessChannel \brief A generic network-based communication channel for applications. QInterProcessChannel offers communication facilities between several instances of the same application. It initializes itself so that the first created instance acts as a "server" which recieve messages from the others instances. This is particularly handy when creating a single-instance application which, for example, uses file association through a command line interface. \see QSingleApplication */ /*! \brief Constructor Check for a valid server and create one if none found. */ QInterProcessChannel::QInterProcessChannel(QObject *p) : QThread(p) { uniqPrefix = QApplication::applicationName(); pipeName = QString("\\\\.\\pipe\\%1%2").arg(uniqPrefix).arg("_uniquePipeName"); globalMutexStr = uniqPrefix + QString("_globalMutexId"); blockerMutexStr = uniqPrefix + QString("_blockerMutexId"); init(); } /*! \brief Destructor */ QInterProcessChannel::~QInterProcessChannel() { //while(isRunning()) // quit(); close(); } /*! \return Wether the instance has a server role */ bool QInterProcessChannel::isServer() const { return serverMode; } /*! \return The current buffered message */ QString QInterProcessChannel::messageBuffer() const { return sMsg; } /*! \brief Sets a buffered message */ void QInterProcessChannel::setMessageBuffer(const QString& s) { sMsg = s; } /*! \overload Sends the content of the current message buffer */ void QInterProcessChannel::sendMessage() { sendMessage(sMsg); sMsg.clear(); } /*! \overload */ void QInterProcessChannel::sendMessage(const QString& s) { sendMessage(s.toLocal8Bit()); } /*! \brief Send a message to server instance */ void QInterProcessChannel::sendMessage(const QByteArray& msg) { if(msg.count()) { // a lot of simultaneous clients cause that pipe sometimes omits // some of these clients despite results of writing functions are ok ;/ // workaround: reserve mutex, wait 100ms before every write operation HANDLE mutex = CreateMutexA(NULL, FALSE, qPrintable(blockerMutexStr)); WaitForSingleObject(mutex, INFINITE); Sleep(100); HANDLE hPipe; // loop to get pipe's handle for(;;) { hPipe = CreateFileA( qPrintable(pipeName), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(hPipe != INVALID_HANDLE_VALUE) break; if(GetLastError() != ERROR_PIPE_BUSY) { ReleaseMutex(mutex); return; } // wait max 1s and retry WaitNamedPipeA(qPrintable(pipeName), 1000); } // ok, now we have pipe's handle, we can prepare buffers and write to the pipe char buffer[bufferSize]; strncpy(buffer, msg.constData(), bufferSize); buffer[bufferSize-1] = 0; DWORD bytesWritten; bool writeSuccess = WriteFile( hPipe, buffer, strlen(buffer) + 1, &bytesWritten, NULL); if (!writeSuccess) { ReleaseMutex(mutex); return; } CloseHandle(hPipe); ReleaseMutex(mutex); } else { //qWarning("::sendMessage(%d): Empty messages are not carried out...", GetCurrentProcessId()); } } /*! \brief Closes the communication channel */ void QInterProcessChannel::close() { if(serverMode) { // if we want to quit pipe server thread, we have to send --quit message sendMessage(QString("--quit")); } } /*! \internal */ void QInterProcessChannel::run() { if(!serverMode) return; HANDLE hPipe; char buffer[bufferSize]; bool connected, readSuccess; DWORD bytesRead; // thread loop for(;;) { hPipe = CreateNamedPipeA( qPrintable(pipeName), PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 0, bufferSize, 0, NULL); if(hPipe == INVALID_HANDLE_VALUE) break; connected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); if(!connected) { CloseHandle(hPipe); continue; } readSuccess = ReadFile( hPipe, buffer, bufferSize, &bytesRead, NULL); buffer[bufferSize - 1] = 0; if(!readSuccess || !bytesRead) { CloseHandle(hPipe); continue; } QStringList argv = QManagedRequest::splitArguments(QString(buffer)); const QString cmd = argv.at(0); // if server instance is going to suspend thread... if ( cmd == "--quit" ) { CloseHandle(hPipe); break; } else if ( cmd == "--request" ) { argv.removeAt(0); emit request(argv); } else { emit message(QString(buffer)); } CloseHandle(hPipe); } } /*! \internal */ void QInterProcessChannel::init() { //while(isRunning()) // quit(); // create global mutex to check single instance CreateMutexA(NULL, FALSE, qPrintable(globalMutexStr)); serverMode = !(GetLastError() == ERROR_ALREADY_EXISTS); // start listening thread in single instance mode if(serverMode) start(); } qnapi-0.1.5/src/qcumber/qmanagedrequest.h0000644000175000017500000000275110771513632020031 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef _QMANAGED_REQUEST_H_ #define _QMANAGED_REQUEST_H_ #include "qcumber.h" /*! \file qmanagedrequest.h \brief Definition of the QManagedRequest class. */ #include class QCUMBER_EXPORT QManagedRequest { public: QManagedRequest(const QString& cmd, const QStringList& args = QStringList()); QManagedRequest(const QManagedRequest& r); ~QManagedRequest(); static QManagedRequest createSystemRequest(const QStringList& args, int id = -1); QManagedRequest& operator = (const QManagedRequest& r); QString toString() const; static QManagedRequest fromString(const QString& s); static QStringList splitArguments(const QString& s); static QByteArray joinArguments(const QString& cmd, const QStringList& l); private: QString sCommand; QStringList lArguments; }; #endif // _QMANAGED_REQUEST_H_ qnapi-0.1.5/src/qcumber/qinterprocesschannel_win32.h0000644000175000017500000000323610777410436022122 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2008 Krzemin ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef _QINTER_PROCESS_CHANNEL_H_ #define _QINTER_PROCESS_CHANNEL_H_ #include "qcumber.h" #include "qmanagedrequest.h" #include #include #include #include #include /*! \file qinterprocesschannel.h \brief Definition of the QInterProcessChannel class. */ // buffer size for input/output pipes static const int bufferSize = 2048; class QCUMBER_EXPORT QInterProcessChannel : public QThread { Q_OBJECT public: QInterProcessChannel(QObject *p = 0); virtual ~QInterProcessChannel(); bool isServer() const; QString messageBuffer() const; public slots: void close(); void sendMessage(); void sendMessage(const QString& s); void sendMessage(const QByteArray& b); void setMessageBuffer(const QString& s); signals: void message(const QString& s); void request(const QStringList& l); protected: virtual void run(); private slots: void init(); private: QString uniqPrefix, pipeName, globalMutexStr, blockerMutexStr; QString sMsg; bool serverMode; }; #endif // _QINTER_PROCESS_CHANNEL_H_ qnapi-0.1.5/src/qcumber/qsingleapplication.h0000644000175000017500000000362211014303670020515 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef _QSINGLE_APPLICATION_H_ #define _QSINGLE_APPLICATION_H_ #include "qcumber.h" /*! \file qsingleapplication.h \brief Definition of the QSingleApplication class. */ #include class QInterProcessChannel; class QCUMBER_EXPORT QSingleApplication : public QApplication { Q_OBJECT public: enum InstanciationPolicy { None, ForwardArguments }; enum MessagingPolicy { Ignore, Events, Signals }; QSingleApplication(int& argc, char **argv, bool useGui); virtual ~QSingleApplication(); bool isInstanceAllowed() const; MessagingPolicy messagingPolicy() const; void setMessagingPolicy(MessagingPolicy p); InstanciationPolicy instanciationPolicy() const; void setInstanciationPolicy(InstanciationPolicy p); public slots: virtual int exec(); void sendRequest(const QString& s); void sendRequest(const QStringList& l); signals: void request(const QString& s); protected: virtual bool event(QEvent *e); protected slots: virtual void message(const QString& msg); virtual void request(const QStringList& r); private: QInterProcessChannel *pChannel; MessagingPolicy m_messaging; InstanciationPolicy m_instanciation; }; #endif // !_QSINGLE_APPLICATION_H_ qnapi-0.1.5/src/qcumber/qinterprocesschannel.cpp0000644000175000017500000001634410771676476021453 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "qinterprocesschannel.h" /*! \file qinterprocesschannel.cpp \brief Implementation of the QInterProcessChannel class. */ #include "qmanagedsocket.h" #include "qmanagedrequest.h" #include #include #include #include #include #include #include #define WAIT_TIMEOUT 5000 /*! \class QInterProcessChannel \brief A generic network-based communication channel for applications. QInterProcessChannel offers communication facilities between several instances of the same application. It initializes itself so that the first created instance acts as a "server" which recieve messages from the others instances. This is particularly handy when creating a single-instance application which, for example, uses file association through a command line interface. \see QSingleApplication */ /*! \brief Constructor Check for a valid server and create one if none found. */ QInterProcessChannel::QInterProcessChannel(QObject *p) : QThread(p), pServer(0), pServerTimer(0) { init(); } /*! \brief Destructor */ QInterProcessChannel::~QInterProcessChannel() { while ( isRunning() ) quit(); close(); } /*! \return Wether the instance has a server role */ bool QInterProcessChannel::isServer() const { return pServer; } /*! \return The current buffered message */ QString QInterProcessChannel::messageBuffer() const { return sMsg; } /*! \brief Sets a buffered message */ void QInterProcessChannel::setMessageBuffer(const QString& s) { sMsg = s; } /*! \overload Sends the content of the current message buffer */ void QInterProcessChannel::sendMessage() { sendMessage(sMsg); sMsg.clear(); } /*! \overload */ void QInterProcessChannel::sendMessage(const QString& s) { sendMessage(s.toLocal8Bit()); } /*! \brief Send a message to server instance */ void QInterProcessChannel::sendMessage(const QByteArray& msg) { if ( !pServer && msg.count() ) { //qDebug("Sending msg : %s", msg.constData()); QTcpSocket *pSocket = new QTcpSocket(this); pSocket->connectToHost(m_addr, m_port); pSocket->waitForConnected(WAIT_TIMEOUT); pSocket->write(msg); pSocket->waitForBytesWritten(WAIT_TIMEOUT); } else { //qWarning("Empty messages are not carried out..."); } } /*! \brief Closes the communication channel \see reconnect() */ void QInterProcessChannel::close() { if ( pServer ) { pServer->close(); delete pServer; pServer = 0; QString ini = QDir::tempPath() + QDir::separator() + QApplication::applicationName() + "rc"; QFile::remove(ini); } } /*! \brief Attemps to reconnect When the server instance is closed (or crashes...) the connectionLost() signal is emitted. As an alternative to closing the client instances it is possible to try a reconnection so that one of theclient will become a server. \note When several clients are running side by side this function is very likely to cause a fork and create several (independant) clients whose only one will be reachable by newer clients... \see connectionLost() */ void QInterProcessChannel::reconnect() { //qDebug("attempting to reconnect"); init(); } /*! \internal */ void QInterProcessChannel::run() { /* There we check that the server lives... If connection fails notify it... */ if ( pServer ) return; //qDebug("timer setup..."); pServerTimer = new QTimer; pServerTimer->setInterval(100); pServerTimer->setSingleShot(false); connect(pServerTimer, SIGNAL( timeout() ), this , SLOT ( check() ) ); pServerTimer->start(); exec(); } /*! \internal */ void QInterProcessChannel::check() { //qDebug("checking connection..."); QTcpSocket *pSocket = new QTcpSocket(this); pSocket->connectToHost(m_addr, m_port); if ( pSocket->error() != -1 ) { emit connectionLost(); return; } pSocket->waitForConnected(WAIT_TIMEOUT); if ( pSocket->error() != -1 ) { emit connectionLost(); return; } } /*! \internal */ void QInterProcessChannel::init() { while ( isRunning() ) quit(); if ( pServerTimer ) { pServerTimer->stop(); delete pServerTimer; pServerTimer = 0; } bool ok = true; m_port = 0; m_addr = QHostAddress::LocalHost; QString ini = QDir::tempPath() + QDir::separator() + QApplication::applicationName() + "rc"; pServer = new QTcpServer(this); pServer->listen(m_addr, m_port); connect(pServer , SIGNAL( newConnection() ), this , SLOT ( connection() ) ); if ( QFile::exists(ini) ) { /* found a server config file, let us assume it is from a running server */ //qDebug("checking old server..."); QSettings conf(ini, QSettings::IniFormat); m_port = conf.value("port").toUInt(); m_addr = QHostAddress(conf.value("address").toString()); QTcpSocket *pSocket = new QTcpSocket(this); if ( !m_addr.isNull() && m_port ) { pSocket->connectToHost(m_addr, m_port); ok = pSocket->waitForConnected(WAIT_TIMEOUT); if ( ok ) ok &= (bool)pSocket->write("--check"); if ( ok ) ok &= (bool)pSocket->waitForBytesWritten(WAIT_TIMEOUT); if ( ok ) ok &= (bool)pSocket->waitForReadyRead(WAIT_TIMEOUT); if ( ok ) ok &= (pSocket->readAll() == "[ALIVE]"); } else { ok = false; } if ( !ok ) { QFile::remove(ini); } pSocket->disconnectFromHost(); delete pSocket; } if ( !QFile::exists(ini) ) { // no server found... Create one //qDebug("setting up new server..."); m_port = pServer->serverPort(); m_addr = pServer->serverAddress(); QSettings conf(ini, QSettings::IniFormat); conf.setValue("port", m_port); conf.setValue("address", m_addr.toString()); emit gotServerRole(); emit serverRoleChanged(true); } else { // server found we'll hook on it later on... pServer->close(); pServer = 0; emit serverRoleChanged(false); } start(); } /*! \internal */ void QInterProcessChannel::message(const QString& msg, QManagedSocket *s) { if ( !pServer ) return; //qDebug("message from Inter Process channel : %s", qPrintable(msg)); QStringList argv = QManagedRequest::splitArguments(msg); const QString cmd = argv.at(0); //const int argc = argv.count(); if ( cmd == "--check" ) { s->send("[ALIVE]"); } else if ( cmd == "--request" ) { argv.removeAt(0); emit request(argv); } else { emit message(msg); } } /*! \brief internal */ void QInterProcessChannel::connection() { if ( !pServer ) return; //qDebug("incoming Inter Process connection"); while ( pServer->hasPendingConnections() ) { QManagedSocket *s = new QManagedSocket(pServer->nextPendingConnection(), this); connect(s , SIGNAL( message(QString, QManagedSocket*) ), this, SLOT ( message(QString, QManagedSocket*) ) ); } } qnapi-0.1.5/src/qcumber/qmanagedsocket.cpp0000644000175000017500000000260210771513632020157 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "qmanagedsocket.h" /*! \file qmanagedsocket.cpp \brief Implementation of the QManagedSocket class. */ #include QManagedSocket::QManagedSocket(QTcpSocket *s, QObject *p) : QObject(p), pSocket(s) { if ( !s ) qFatal("QManagedSocket fed with invalid socket descriptor..."); connect(s , SIGNAL( readyRead() ), this, SLOT ( readyRead() ) ); connect(s , SIGNAL( disconnected() ), this, SLOT ( deleteLater() ) ); } QManagedSocket::~QManagedSocket() { } void QManagedSocket::send(const QByteArray& msg) { pSocket->write(msg); } void QManagedSocket::readyRead() { if ( pSocket ) { QString msg = QString::fromLocal8Bit(pSocket->readAll()); emit message(msg); emit message(msg, this); } } qnapi-0.1.5/src/qcumber/qmanagedsocket.h0000644000175000017500000000240610771513632017626 0ustar patrykpatryk/**************************************************************************** ** ** Copyright (C) 2006-2008 fullmetalcoder ** ** This file is part of the Edyuk project ** ** This file may be used under the terms of the GNU General Public License ** version 2 as published by the Free Software Foundation and appearing in the ** file GPL.txt included in the packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef _QMANAGED_SOCKET_H_ #define _QMANAGED_SOCKET_H_ #include "qcumber.h" /*! \file qmanagedsocket.h \brief Definition of the QManagedSocket class. */ #include class QTcpSocket; class QCUMBER_EXPORT QManagedSocket : public QObject { Q_OBJECT public: QManagedSocket(QTcpSocket *s, QObject *p = 0); virtual ~QManagedSocket(); virtual void send(const QByteArray& msg); signals: void message(const QString& m); void message(const QString& m, QManagedSocket *s); protected slots: virtual void readyRead(); private: QTcpSocket *pSocket; }; #endif // _QMANAGED_SOCKET_H_ qnapi-0.1.5/src/frmreport.h0000644000175000017500000000356711014576076015235 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMREPORT__H__ #define __FRMREPORT__H__ #include "ui_frmreport.h" #include #include #include #include #include #include #include #include "qnapithread.h" #include "qnapiconfig.h" #include "qnapiprojektengine.h" #include "qnapiopendialog.h" class ReportThread : public QNapiThread { Q_OBJECT public: void run(); void setReportParams(const QString & movie_file, const QString & lang, const QString & comment_txt) { movie = movie_file; language = lang; comment = comment_txt; } QNapiProjektEngine::ReportResult taskResult; signals: void reportFinished(bool interrupt = false); void serverMessage(QString msg); void invalidUserPass(); private: QString movie, language, comment; }; class frmReport: public QDialog { Q_OBJECT public: frmReport(QWidget *parent = 0, Qt::WFlags f = 0); ~frmReport() {}; private: void closeEvent(QCloseEvent *event); Ui::frmReport ui; ReportThread reportThread; private slots: void selectMovie(); void checkReportEnable(); void cbProblemChanged(); void pbReportClicked(); void reportFinished(bool interrupt = false); void serverMessage(QString msg); void invalidUserPass(); }; #endif qnapi-0.1.5/src/frmreport.cpp0000644000175000017500000001354111015000613015535 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmreport.h" frmReport::frmReport(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); connect(ui.pbMovieSelect, SIGNAL(clicked()), this, SLOT(selectMovie())); connect(ui.leMovieSelect, SIGNAL(textChanged(QString)), this, SLOT(checkReportEnable())); connect(ui.cbProblem, SIGNAL(currentIndexChanged(int)), this, SLOT(cbProblemChanged())); connect(ui.leProblem, SIGNAL(textChanged(QString)), this, SLOT(checkReportEnable())); connect(ui.pbReport, SIGNAL(clicked()), this, SLOT(pbReportClicked())); connect(&reportThread, SIGNAL(reportFinished(bool)), this, SLOT(reportFinished(bool))); connect(&reportThread, SIGNAL(serverMessage(QString)), this, SLOT(serverMessage(QString))); connect(&reportThread, SIGNAL(invalidUserPass()), this, SLOT(invalidUserPass())); ui.cbProblem->setCurrentIndex(4); cbProblemChanged(); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmReport::closeEvent(QCloseEvent *event) { if(reportThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać wysyłanie raportu?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { pbReportClicked(); } event->ignore(); } else event->accept(); } void frmReport::selectMovie() { QString fileName; QNapiOpenDialog openDialog(this, tr("Wskaż plik z filmem"), GlobalConfig().previousDialogPath(), QNapiOpenDialog::Movies); if(openDialog.selectFile()) { fileName = openDialog.selectedFiles().first(); GlobalConfig().setPreviousDialogPath(openDialog.directory().path()); } if(!fileName.isEmpty() && QFile::exists(fileName)) ui.leMovieSelect->setText(fileName); } void frmReport::checkReportEnable() { ui.pbReport->setEnabled( QFile::exists(ui.leMovieSelect->text()) && ((ui.cbProblem->currentIndex() == 4) ? !ui.leProblem->text().isEmpty() : true) ); ui.lbAction->setText(ui.pbReport->isEnabled() ? tr("Teraz możesz wysłać raport.") : tr("Wskaż plik z filmem oraz opisz problem.")); } void frmReport::cbProblemChanged() { ui.leProblem->setEnabled(ui.cbProblem->currentIndex() == 4); checkReportEnable(); } void frmReport::pbReportClicked() { if(!reportThread.isRunning()) { QFileInfo fi(ui.leMovieSelect->text()); if(!QFile::exists(fi.path() + "/" + fi.completeBaseName() + ".txt")) { ui.lbAction->setText(tr("Brak pliku z napisami dla podanego filmu!")); QMessageBox::warning(this, tr("Brak pliku z napisami!"), tr("Brak pliku z napisami dla podanego filmu!")); } else { ui.leMovieSelect->setEnabled(false); ui.pbMovieSelect->setEnabled(false); ui.cbLanguage->setEnabled(false); ui.cbProblem->setEnabled(false); ui.leProblem->setEnabled(false); ui.pbReport->setText(tr("Zatrzymaj")); ui.lbAction->setText(tr("Wysyłanie raportu do serwera...")); reportThread.setReportParams(ui.leMovieSelect->text(), (ui.cbLanguage->currentIndex() == 0) ? "PL" : "ENG", (ui.cbProblem->currentIndex() < 4 ? ui.cbProblem->currentText() : ui.leProblem->text()) ); reportThread.start(); } } else { reportThread.requestAbort(); ui.lbAction->setText(tr("Przerywanie wysyłania...")); ui.pbReport->setEnabled(false); qApp->processEvents(); } } void frmReport::reportFinished(bool interrupted) { ui.leMovieSelect->setEnabled(true); ui.pbMovieSelect->setEnabled(true); ui.cbLanguage->setEnabled(true); ui.cbProblem->setEnabled(true); ui.leProblem->setEnabled(true); ui.pbReport->setEnabled(true); cbProblemChanged(); ui.pbReport->setText(tr("Wyślij raport")); if(interrupted) { ui.lbAction->setText(tr("Przerwano wysyłanie poprawki.")); } else { switch(reportThread.taskResult) { case QNapiProjektEngine::NAPI_NO_SUBTITLES: ui.lbAction->setText(tr("Brak napisów dla wskazanego pliku.")); break; case QNapiProjektEngine::NAPI_NOT_REPORTED: ui.lbAction->setText(tr("Błąd podczas wysyłania raportu.")); break; default: ui.lbAction->setText(tr("Raport wysłany.")); } } } void frmReport::serverMessage(QString msg) { if(msg.indexOf("NPc0") == 0) msg = tr("Zgłoszono raport do serwera."); else msg = tr("Odpowiedź serwera: ") + tr(qPrintable(msg)); QMessageBox::information(this, tr("Raport wysłany"), msg); } void frmReport::invalidUserPass() { QMessageBox::information(this, tr("Błąd!"), QString(tr("Nazwa użytkownika lub hasło jest niepoprawne."))); } void ReportThread::run() { abort = false; if(!QNapiProjektEngine::checkUser(GlobalConfig().nick(), GlobalConfig().pass())) { emit invalidUserPass(); emit reportFinished(true); return; } if(abort) { emit reportFinished(true); return; } QNapiProjektEngine *napi; if(!(napi = new QNapiProjektEngine(movie))) { emit reportFinished(true); return; } QString *response = new QString(); taskResult = napi->reportBad(language, GlobalConfig().nick(), GlobalConfig().pass(), comment, response); if(taskResult == QNapiProjektEngine::NAPI_REPORTED) emit serverMessage(*response); delete response; delete napi; emit reportFinished(); } qnapi-0.1.5/src/qnapicli.h0000644000175000017500000000217711005156662015004 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPICLI__H__ #define __QNAPICLI__H__ #include #include #include #include "version.h" #include "qnapiprojektengine.h" class QNapiCli { public: QNapiCli(int argc, char **argv) : m_argc(argc), m_argv(argv), mode(CM_UNSET) {} bool analyze(); int exec(); private: int m_argc; char **m_argv; QStringList movieList; enum CliMode { CM_UNSET, CM_HELP, CM_CONSOLE, CM_QUIET }; CliMode mode; void printHelp(); void printCli(const QString & string); }; #endif qnapi-0.1.5/src/frmcreateuser.cpp0000644000175000017500000001206611014601063016372 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmcreateuser.h" frmCreateUser::frmCreateUser(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); connect(ui.pbCreate, SIGNAL(clicked()), this, SLOT(pbCreateClicked())); connect(ui.leLogin, SIGNAL(textChanged(QString)), this, SLOT(checkCreateEnable())); connect(ui.lePass, SIGNAL(textChanged(QString)), this, SLOT(checkCreateEnable())); connect(ui.leRepeatPass, SIGNAL(textChanged(QString)), this, SLOT(checkCreateEnable())); connect(ui.leMail, SIGNAL(textChanged(QString)), this, SLOT(checkCreateEnable())); connect(&createUserThread, SIGNAL(creatingFinished(bool)), this, SLOT(creatingFinished(bool))); connect(&createUserThread, SIGNAL(serverMessage(QString)), this, SLOT(serverMessage(QString))); connect(&createUserThread, SIGNAL(terminated()), this, SLOT(creatingFinished())); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmCreateUser::closeEvent(QCloseEvent *event) { if(createUserThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać zakładanie konta?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { pbCreateClicked(); event->accept(); } event->ignore(); } else event->accept(); } bool frmCreateUser::validEmail(const QString & email) { return QRegExp("^(.+)@(.+)\\.(.+)$").exactMatch(email); } void frmCreateUser::checkCreateEnable() { bool e = true; e &= !ui.leLogin->text().isEmpty(); e &= !ui.lePass->text().isEmpty(); e &= !ui.leRepeatPass->text().isEmpty(); e &= !ui.leMail->text().isEmpty(); e &= validEmail(ui.leMail->text()); e &= (ui.lePass->text().length() >= 5); e &= (ui.lePass->text() == ui.leRepeatPass->text()); ui.pbCreate->setEnabled(e); if (!ui.lePass->text().isEmpty() && (ui.lePass->text().length() < 5)) ui.lbStatus->setText(tr("Hasło musi mieć conajmniej 5 znaków!")); else if(ui.lePass->text() != ui.leRepeatPass->text()) ui.lbStatus->setText(tr("Wpisane hasła różnią się od siebie!")); else if(!ui.leMail->text().isEmpty() && !validEmail(ui.leMail->text())) ui.lbStatus->setText(tr("Wpisz poprawny adres e-mail.")); else ui.lbStatus->setText(tr("Wpisz dane potrzebne do założenia konta")); if(e) ui.lbStatus->setText(tr("Teraz możesz założyć konto na serwerze NAPI-PROJEKT")); } void frmCreateUser::pbCreateClicked() { if(!createUserThread.isRunning()) { ui.pbCreate->setEnabled(false); ui.lbStatus->setText(tr("Zakładanie konta na serwerze NAPI...")); ui.leLogin->setEnabled(false); ui.lePass->setEnabled(false); ui.leRepeatPass->setEnabled(false); ui.leMail->setEnabled(false); createUserThread.setUserParams(ui.leLogin->text(), ui.lePass->text(), ui.leMail->text()); createUserThread.start(); } else { ui.lbStatus->setText(tr("Oczekiwanie na zakończenie zadania...")); qApp->processEvents(); } } void frmCreateUser::creatingFinished(bool result) { ui.lbStatus->setText(result ? tr("Operacja zakończona") : tr("Zakładanie konta nie powiodło się")); ui.pbCreate->setEnabled(true); ui.leLogin->setEnabled(true); ui.lePass->setEnabled(true); ui.leRepeatPass->setEnabled(true); ui.leMail->setEnabled(true); } void frmCreateUser::serverMessage(QString msg) { QRegExp extract("", Qt::CaseInsensitive); if(extract.indexIn(msg) > -1) msg = extract.cap(1).replace("%20", " "); if((msg.indexOf("NPc0") == 0) || (msg.indexOf("Konto zostalo zalozone!") == 0)) { msg = tr("Konto na serwerze NAPI zostało założone!"); QMessageBox::information(this, tr("Konto założone"), msg); if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz uaktualnić ustawienia w programie?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { GlobalConfig().setNick(ui.leLogin->text()); GlobalConfig().setPass(ui.lePass->text()); GlobalConfig().save(); } if(createUserThread.isRunning()) createUserThread.wait(); close(); } else { msg = tr("Odpowiedź serwera: ") + tr(qPrintable(msg)); QMessageBox::information(this, tr("Operacja zakończona"), msg); } } void CreateUserThread::run() { QString *response = new QString(); bool r; if((r = QNapiProjektEngine::createUser(nick, pass, mail, response))) emit serverMessage(*response); delete response; emit creatingFinished(r); } qnapi-0.1.5/src/napi.h0000644000175000017500000000645011000145225014115 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __NAPI__H__ #define __NAPI__H__ #include #include #include #include #include #include #include #include #include #include #include #include #include "synchttp.h" #include "multipartdata.h" #include "movieinfo.h" #include "version.h" #include "qnapiconfig.h" #ifdef Q_WS_WIN // for SetFileAttributes #include #endif const QString napiZipPassword = "iBlm8NTigvru0Jr0"; const QString napiDownloadUrlTpl= "http://www.napiprojekt.pl/unit_napisy/dl.php" "?l=%1&f=%2&t=%3&v=other&kolejka=false&napios=Linux&nick=%4&pass=%5"; const QString napiCheckUserUrlTpl = "http://www.napiprojekt.pl/users_check.php?nick=%1&pswd=%2"; const QString napiUploadUrlTpl = "http://www.napiprojekt.pl/unit_napisy/upload.php" "?m_length=%1&m_resolution=%2x%3&m_fps=%4&m_hash=%5&m_filesize=%6"; const QString napiReportBadUrlTpl = "http://www.napiprojekt.pl/unit_napisy/zlenapisyadd.php"; const QString napiCreateUserUrlTpl = "http://www.napiprojekt.pl/users_add.php"; const unsigned long NAPI_10MB = 10485760; enum napiUploadResult { NAPI_ADDED_NEW, NAPI_OK, NAPI_FAIL, NAPI_UNKNOWN }; enum napiReportResult { NAPI_REPORTED, NAPI_NO_SUBTITLES, NAPI_NOT_REPORTED }; QString napiFileMd5Sum(const QString & filename, unsigned long max_size = 0); QString napiFDigest(QString input); bool napiDownload(const QString & md5sum, const QString & path, const QString & language = "PL", const QString & nick = "", const QString & pass = ""); bool napiMatchSubtitles(const QString & md5sum, const QString & zip_file, const QString & movie_file, bool noBackup = false, const QString & tmp_path = "/tmp", const QString & p7zip_path = "/usr/bin/7z"); bool napiCheckUser(const QString & nick, const QString & pass); napiUploadResult napiUploadSubtitles(const QString & movie_file, const QString & subtitles_file, const QString & language, const QString & nick, const QString & pass, bool correct = false, const QString & comment = "", const QString & tmp_path = "/tmp", const QString & p7zip_path = "/usr/bin/7z"); napiReportResult napiReportBad(const QString & movie_file, const QString & language, const QString & nick, const QString & pass, const QString & comment, QString *response); bool napiConvertFile(const QString & file, const QString & enc_from, const QString & enc_to); bool napiConvertFile(const QString & file, const QString & enc_to); bool napiCreateUser(const QString & nick, const QString & pass, const QString & email, QString * response); bool napiCheck7Zip(); bool napiCheckTmpPath(); #endif qnapi-0.1.5/src/qnapiapp.h0000644000175000017500000000432211014772332015005 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPIAPP__H__ #define __QNAPIAPP__H__ #include #include #include #include #include #include #include #include "qcumber/qsingleapplication.h" #include "frmprogress.h" #include "frmabout.h" #include "frmoptions.h" #include "frmupload.h" #include "frmcorrect.h" #include "frmreport.h" #include "frmscan.h" #include "frmcreateuser.h" #include "frmsummary.h" #include "qnapiconfig.h" #include "qnapiopendialog.h" class QNapiApp : public QSingleApplication { Q_OBJECT public: QNapiApp(int & argc, char **argv, bool useGui); ~QNapiApp(); void createTrayIcon(); void showTrayMessage(QString title, QString msg); frmProgress * progress(); public slots: void showOpenDialog(); void showScanDialog(); void showUploadDialog(); void showCorrectDialog(); void showReportDialog(); void showOptions(); void showCreateUser(); void showAbout(); void tryQuit(); signals: void downloadFile(const QString & fileName); private: bool event(QEvent *ev); QSystemTrayIcon *trayIcon; QMenu *trayIconMenu, *napiSubMenu; QAction *getAction, *scanAction, *addNewAction, *addCorrectedAction, *reportBadAction, *optionsAction, *createUserAction, *aboutAction, *quitAction; QNapiOpenDialog *openDialog; frmProgress *f_progress; frmOptions *f_options; frmCreateUser *f_createUser; frmAbout *f_about; frmScan *f_scan; frmUpload *f_upload; frmCorrect *f_correct; frmReport *f_report; private slots: void trayIconActivated(QSystemTrayIcon::ActivationReason reason); }; #endif qnapi-0.1.5/src/frmupload.h0000644000175000017500000000445211014655601015170 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMUPLOAD__H__ #define __FRMUPLOAD__H__ #include "ui_frmupload.h" #include #include #include #include #include #include #include "qnapithread.h" #include "qnapiconfig.h" #include "qnapiprojektengine.h" #include "qnapiopendialog.h" class ScanThread : public QNapiThread { Q_OBJECT public: void run(); void setSearchPath(const QString & path) { searchPath = path; } QStringList fileList; unsigned int folders, movies, subtitles; signals: void scanFinished(bool result); void folderChange(const QString & folder); private: bool doScan(const QString & path); QString searchPath; QStringList searchFilters; }; class UploadThread : public QNapiThread { Q_OBJECT public: void run(); void setMovieList(const QStringList & list) { movieList = list; } unsigned int added_new, added_ok, failed; bool invalidUP; signals: void progressChange(int progress); void fileNameChange(const QString & filename); void checkingUserPass(); void invalidUserPass(); private: QStringList movieList; }; class frmUpload: public QDialog { Q_OBJECT public: frmUpload(QWidget *parent = 0, Qt::WFlags f = 0); ~frmUpload() {}; private: void closeEvent(QCloseEvent *event); Ui::frmUpload ui; ScanThread scanThread; UploadThread uploadThread; private slots: void selectDirectory(); void leSelectDirectoryChanged(); void pbScanClicked(); void folderChange(const QString & folder); void scanFinished(bool result); void pbUploadClicked(); void fileNameChange(const QString & filename); void checkingUserPass(); void uploadFinished(); void invalidUserPass(); }; #endif qnapi-0.1.5/src/version.h0000644000175000017500000000131111000145225014642 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __VERSION__H__ #define __VERSION__H__ #define QNAPI_VERSION "0.1.5" #endif qnapi-0.1.5/src/frmcreateuser.h0000644000175000017500000000341511014601063016035 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMCREATEUSER__H__ #define __FRMCREATEUSER__H__ #include "ui_frmcreateuser.h" #include #include #include #include //#include "napi.h" #include "qnapithread.h" #include "qnapiconfig.h" #include "qnapiprojektengine.h" class CreateUserThread : public QNapiThread { Q_OBJECT public: void run(); void setUserParams(const QString & u_nick, const QString & u_pass, const QString & u_mail) { setTerminationEnabled(true); nick = u_nick; pass = u_pass; mail = u_mail; } QNapiProjektEngine::ReportResult taskResult; signals: void creatingFinished(bool result); void serverMessage(QString msg); private: QString nick, pass, mail; }; class frmCreateUser: public QDialog { Q_OBJECT public: frmCreateUser(QWidget *parent = 0, Qt::WFlags f = 0); ~frmCreateUser() {}; private: void closeEvent(QCloseEvent *event); bool validEmail(const QString & email); Ui::frmCreateUser ui; CreateUserThread createUserThread; private slots: void checkCreateEnable(); void pbCreateClicked(); void creatingFinished(bool result = false); void serverMessage(QString msg); }; #endif qnapi-0.1.5/src/frmsummary.cpp0000644000175000017500000000366411011700631015727 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmsummary.h" frmSummary::frmSummary(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmSummary::setSuccessList(const QStringList & list) { if(list.isEmpty()) { ui.tabSuccess->hide(); return; } ui.lwSuccess->clear(); foreach(QString item, list) { ui.lwSuccess->addItem(new QListWidgetItem(QIcon(":/ui/icon_accept.png"), QFileInfo(item).fileName())); } ui.lwSuccess->sortItems(); ui.tabWidget->setTabText(0, tr("Dopasowano napisy dla %1 %2") .arg(list.size()).arg(tr(list.size() > 1 ? "plików" : "pliku"))); } void frmSummary::setFailedList(const QStringList & list) { if(list.isEmpty()) { ui.tabFail->hide(); return; } ui.lwFail->clear(); foreach(QString item, list) { ui.lwFail->addItem(new QListWidgetItem(QIcon(":/ui/icon_cancel.png"), QFileInfo(item).fileName())); } ui.lwFail->sortItems(); ui.tabWidget->setTabText(1, tr("Nie udało się dopasować napisów dla %1 %2") .arg(list.size()).arg(tr(list.size() > 1 ? "plików" : "pliku"))); } qnapi-0.1.5/src/qnapiapp.cpp0000644000175000017500000001572111015002516015334 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qnapiapp.h" QNapiApp::QNapiApp(int & argc, char **argv, bool useGui) : QSingleApplication(argc, argv, useGui) { openDialog = 0; f_progress = 0; f_options = 0; f_createUser = 0; f_about = 0; f_scan = 0; f_upload = 0; f_correct = 0; f_report = 0; getAction = 0; scanAction = 0; addNewAction = 0; addCorrectedAction = 0; reportBadAction = 0; optionsAction = 0; createUserAction = 0; aboutAction = 0; quitAction = 0; napiSubMenu = 0; trayIconMenu = 0; trayIcon = 0; } QNapiApp::~QNapiApp() { if(openDialog) delete openDialog; if(f_progress) delete f_progress; if(f_options) delete f_options; if(f_createUser) delete f_createUser; if(f_about) delete f_about; if(f_scan) delete f_scan; if(f_upload) delete f_upload; if(f_correct) delete f_correct; if(f_report) delete f_report; if(getAction) delete getAction; if(scanAction) delete scanAction; if(addNewAction) delete addNewAction; if(addCorrectedAction) delete addCorrectedAction; if(reportBadAction) delete reportBadAction; if(optionsAction) delete optionsAction; if(createUserAction) delete createUserAction; if(aboutAction) delete aboutAction; if(quitAction) delete quitAction; if(napiSubMenu) delete napiSubMenu; if(trayIconMenu) delete trayIconMenu; if(trayIcon) delete trayIcon; } frmProgress * QNapiApp::progress() { if(!f_progress) { f_progress = new frmProgress(); if(!f_progress) abort(); connect(this, SIGNAL(request(QString)), f_progress, SLOT(receiveRequest(QString))); connect(this, SIGNAL(downloadFile(const QString &)), f_progress, SLOT(receiveRequest(const QString &))); } return f_progress; } void QNapiApp::createTrayIcon() { getAction = new QAction(tr("Pobierz"), 0); connect(getAction, SIGNAL(triggered()), this, SLOT(showOpenDialog())); scanAction = new QAction(tr("Skanuj katalogi i dopasuj napisy"), 0); connect(scanAction, SIGNAL(triggered()), this, SLOT(showScanDialog())); addNewAction = new QAction(tr("Dodaj nowe"), 0); connect(addNewAction, SIGNAL(triggered()), this, SLOT(showUploadDialog())); addCorrectedAction = new QAction(tr("Dodaj poprawione"), 0); connect(addCorrectedAction, SIGNAL(triggered()), this, SLOT(showCorrectDialog())); reportBadAction = new QAction(tr("Zgłoś niepasujące"), 0); connect(reportBadAction, SIGNAL(triggered()), this, SLOT(showReportDialog())); optionsAction = new QAction(tr("Opcje"), 0); connect(optionsAction, SIGNAL(triggered()), this, SLOT(showOptions())); createUserAction = new QAction(tr("Załóż konto"), 0); connect(createUserAction, SIGNAL(triggered()), this, SLOT(showCreateUser())); aboutAction = new QAction(tr("O programie"), 0); connect(aboutAction, SIGNAL(triggered()), this, SLOT(showAbout())); quitAction = new QAction(tr("Zakończ"), 0); connect(quitAction, SIGNAL(triggered()), this, SLOT(tryQuit())); napiSubMenu = new QMenu(0); napiSubMenu->setTitle(tr("Napisy")); napiSubMenu->addAction(getAction); napiSubMenu->addAction(scanAction); napiSubMenu->addSeparator(); napiSubMenu->addAction(addNewAction); napiSubMenu->addAction(addCorrectedAction); napiSubMenu->addSeparator(); napiSubMenu->addAction(reportBadAction); trayIconMenu = new QMenu(0); trayIconMenu->addMenu(napiSubMenu); trayIconMenu->addSeparator(); trayIconMenu->addAction(optionsAction); trayIconMenu->addAction(createUserAction); trayIconMenu->addAction(aboutAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); trayIcon = new QSystemTrayIcon(0); trayIcon->setContextMenu(trayIconMenu); #ifdef Q_WS_MAC trayIcon->setIcon(QIcon(":/icon/qnapi-22-mono.png")); #else trayIcon->setIcon(QIcon(":/icon/qnapi.png")); #endif connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); trayIcon->show(); } void QNapiApp::showTrayMessage(QString title, QString msg) { trayIcon->showMessage(title, msg); } void QNapiApp::showOpenDialog() { QStringList fileList; if(!openDialog) { if( !(openDialog = new QNapiOpenDialog(0, tr("Wybierz jeden lub więcej plików z filmami"), GlobalConfig().previousDialogPath(), QNapiOpenDialog::Movies)) ) return; } if(openDialog->selectFiles()) { fileList = openDialog->selectedFiles(); GlobalConfig().setPreviousDialogPath(openDialog->directory().path()); } delete openDialog; openDialog = 0; if(!fileList.isEmpty()) { progress()->enqueueFiles(fileList); progress()->download(); } else if(progress()->isBatchMode()) quit(); } void QNapiApp::showScanDialog() { if(!f_scan) f_scan = new frmScan(); if(f_scan->isVisible()) { f_scan->raise(); return; } f_scan->exec(); delete f_scan; f_scan = 0; } void QNapiApp::showUploadDialog() { if(!f_upload) f_upload = new frmUpload(); if(f_upload->isVisible()) { f_upload->raise(); return; } f_upload->exec(); delete f_upload; f_upload = 0; } void QNapiApp::showCorrectDialog() { if(!f_correct) f_correct = new frmCorrect(); if(f_correct->isVisible()) { f_correct->raise(); return; } f_correct->exec(); delete f_correct; f_correct = 0; } void QNapiApp::showReportDialog() { if(!f_report) f_report = new frmReport(); if(f_report->isVisible()) { f_report->raise(); return; } f_report->exec(); delete f_report; f_report = 0; } void QNapiApp::showOptions() { if(!f_options) { f_options = new frmOptions(); f_options->readConfig(); } if(f_options->isVisible()) { f_options->raise(); return; } if(f_options->exec() == QDialog::Accepted) f_options->writeConfig(); delete f_options; f_options = 0; } void QNapiApp::showCreateUser() { if(!f_createUser) f_createUser = new frmCreateUser(); if(f_createUser->isVisible()) { f_createUser->raise(); return; } f_createUser->exec(); delete f_createUser; f_createUser = 0; } void QNapiApp::showAbout() { if(!f_about) f_about = new frmAbout(); if(f_about->isVisible()) { f_about->raise(); return; } f_about->exec(); delete f_about; f_about = 0; } void QNapiApp::tryQuit() { if(progress()->isVisible() && !progress()->close()) return; quit(); } void QNapiApp::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { if(reason == QSystemTrayIcon::Trigger) #ifndef Q_WS_MAC showOpenDialog() #endif ; } bool QNapiApp::event(QEvent *ev) { if(ev->type() == QEvent::FileOpen) emit downloadFile(static_cast(ev)->file()); else return QApplication::event(ev); return true; } qnapi-0.1.5/src/qnapiprojektengine.cpp0000644000175000017500000002660211015004443017421 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qnapiprojektengine.h" // konstruktor klasy QNapiProjektEngine::QNapiProjektEngine(const QString & movieFile, const QString & subtitlesFile) : QNapiAbstractEngine(movieFile, subtitlesFile) { p7zipPath = GlobalConfig().p7zipPath(); lang = GlobalConfig().language(); nick = GlobalConfig().nick(); pass = GlobalConfig().pass(); noBackup = GlobalConfig().noBackup(); tmpFile = tmpPath + "/QNapi.napisy.7z"; } // destruktor klasy QNapiProjektEngine::~QNapiProjektEngine() { cleanup(); } // oblicza sume kontrolna dla pliku filmowego (md5 z pierwszych 10MB pliku) QString QNapiProjektEngine::checksum(const QString & filename, bool limit10M) { QFile file(filename); QByteArray fileArray; if(!file.open(QIODevice::ReadOnly)) return QString(""); fileArray = limit10M ? file.read(NAPI_10MB) : file.readAll(); file.close(); QByteArray b = QCryptographicHash::hash(fileArray, QCryptographicHash::Md5); fileArray.clear(); QString out; char next[3]; for(int i = 0; i < 16; i++) { snprintf(next, 3, "%.2x", (unsigned char)b[i]); out += next; } checkSum = out; return checkSum; } QString QNapiProjektEngine::checksum() { return checksum(moviePath); } // Probuje pobrac napisy do filmu z serwera NAPI bool QNapiProjektEngine::tryDownload() { if(checkSum.isEmpty()) checksum(); SyncHTTP http; QString urlTxt = napiDownloadUrlTpl.arg(lang).arg(checkSum).arg(napiFDigest(checkSum)).arg(nick).arg(pass); QUrl url(urlTxt); http.setHost(url.host()); http.syncGet(url.path() + "?" + url.encodedQuery()); QByteArray buffer = http.readAll(); if(buffer.indexOf("NPc") == 0) return false; QFile file(tmpFile); if(file.exists()) file.remove(); if(!file.open(QIODevice::WriteOnly)) return false; int r = file.write(buffer); file.close(); return (bool)r; } // Probuje dopasowac napisy do filmu bool QNapiProjektEngine::tryMatch() { if(!QFile::exists(tmpFile)) return false; if(!QFile::exists(moviePath)) return false; if(!checkP7ZipPath()) return false; QStringList args; args << "x" << "-y" << ("-p" + napiZipPassword) << ("-o" + tmpPath) << tmpFile; QProcess p7zip; p7zip.start(p7zipPath, args); if(!p7zip.waitForFinished()) return false; QString subtitleFile = tmpPath + "/" + checkSum + ".txt"; if(!QFile::exists(subtitleFile)) return false; QFileInfo mf(moviePath); QString newName = mf.path() + "/" + mf.completeBaseName() + ".txt"; if(QFile::exists(newName)) { if(!noBackup) { QFileInfo nn(newName); QFile::copy(newName, nn.path() + "/" + nn.completeBaseName() + "_kopia.txt"); } QFile::remove(newName); } bool r; #ifdef Q_WS_WIN // Pod windowsem, aby "wyczyscic" atrybuty pliku, tworzymy go na nowo QFile f(newName), f2(subtitleFile); if(!f.open(QIODevice::WriteOnly) || !f2.open(QIODevice::ReadOnly)) { r = false; f.close(); } else { r = f.write(f2.readAll()) > 0; f2.close(); f.close(); } #else // pod normalnymi OS-ami nie trzeba sie gimnastykowac z atrybutami r = QFile::copy(subtitleFile, newName); #endif subtitlesPath = newName; QFile::remove(subtitleFile); QFile::remove(tmpFile); return r; } void QNapiProjektEngine::cleanup() { QFile::remove(tmpFile); } // Tworzy konto uzytkownika na serwerze NAPI bool QNapiProjektEngine::createUser(const QString & nick, const QString & pass, const QString & email, QString * response) { QMultipartHttpRequest postData; postData.addBoundary(); postData.addContentDisposition("name=\"login\""); postData.addData(nick); postData.addBoundary(); postData.addContentDisposition("name=\"haslo\""); postData.addData(pass); postData.addBoundary(); postData.addContentDisposition("name=\"mail\""); postData.addData(email); postData.addBoundary(); postData.addContentDisposition("name=\"z_programu\""); postData.addData(QString("true")); postData.addEndingBoundary(); QByteArray data = postData.requestStream(); QUrl url(napiCreateUserUrlTpl); QHttpRequestHeader header("POST", url.path()); header.setValue("Host", url.host()); header.setValue("Accept", "text/html, */*"); header.setValue("Content-Type", "multipart/form-data; boundary=" + postData.boundaryTxt()); header.setValue("Connection", "keep-alive"); header.setValue("User-Agent", QString("QNapi ") + QNAPI_VERSION); SyncHTTP http; http.setHost(url.host()); if(!http.syncRequest(header, data)) return false; *response = QTextCodec::codecForName("windows-1250")->toUnicode(http.readAll()); return true; } // Sprawdza uzytkownika w bazie bool QNapiProjektEngine::checkUser(const QString & nick, const QString & pass) { SyncHTTP http; QString urlTxt = napiCheckUserUrlTpl.arg(nick).arg(pass); QUrl url(urlTxt); http.setHost(url.host()); http.syncGet(url.path() + "?" + url.encodedQuery()); QString buffer = http.readAll(); if(buffer.indexOf("ok") == 0) return true; return false; } // Wrzuca napisy do bazy NAPI QNapiProjektEngine::UploadResult QNapiProjektEngine::uploadSubtitles(const QString & language, const QString & nick, const QString & pass, bool correct, const QString & comment) { if(!QFile::exists(moviePath) || !QFile::exists(subtitlesPath)) return NAPI_FAIL; MovieInfo movieInfo(moviePath); unsigned long movie_size = QFileInfo(moviePath).size(); QString movie_md5 = checksum(moviePath); QString subtitles_md5 = checksum(subtitlesPath, false); QString newSubtitlesName = tmpPath + "/" + movie_md5 + ".txt"; if(QFile::exists(newSubtitlesName)) QFile::remove(newSubtitlesName); if(!QFile::copy(subtitlesPath, newSubtitlesName)) return NAPI_FAIL; QString zipFileName = QFileInfo(newSubtitlesName).path() + "/" + QFileInfo(newSubtitlesName).completeBaseName() + ".zip"; if(QFile::exists(zipFileName)) QFile::remove(zipFileName); QStringList args; args << "a" << "-t7z" << "-bd" << "-y"; #ifndef Q_WS_WIN args << "-l"; #endif args << zipFileName << (QString("-p")+napiZipPassword) << newSubtitlesName; QProcess p7zip; p7zip.start(p7zipPath, args); if(!p7zip.waitForFinished()) return NAPI_FAIL; QFile::remove(newSubtitlesName); if(!QFile::exists(zipFileName)) return NAPI_FAIL; // Przygotowujemy dane do zapytania POST QMultipartHttpRequest postData; postData.addBoundary(); postData.addContentDisposition("name=\"kmt\""); postData.addData(comment); postData.addBoundary(); postData.addContentDisposition("name=\"poprawka\""); postData.addData(QString(correct ? "true" : "false")); postData.addBoundary(); postData.addContentDisposition("name=\"v\""); postData.addData(QString("other")); postData.addBoundary(); postData.addContentDisposition("name=\"l\""); postData.addData(language); postData.addBoundary(); postData.addContentDisposition("name=\"t\""); postData.addData(napiFDigest(movie_md5)); postData.addBoundary(); postData.addContentDisposition("name=\"m_filename\""); postData.addData(QFileInfo(moviePath).fileName()); postData.addBoundary(); postData.addContentDisposition("name=\"nick\""); postData.addData(nick); postData.addBoundary(); postData.addContentDisposition("name=\"pass\""); postData.addData(pass); postData.addBoundary(); postData.addContentDisposition("name=\"s_hash\""); postData.addData(subtitles_md5); postData.addBoundary(); postData.addContentDisposition("name=\"MAX_FILE_SIZE\""); postData.addData(QString("512000")); postData.addBoundary(); postData.addContentDisposition("name=\"plik\"; filename=\"" + QFileInfo(zipFileName).fileName() + "\""); postData.addContentType("subtitles/zip"); QFile fZip(zipFileName); if(!fZip.open(QIODevice::ReadOnly)) return NAPI_FAIL; postData.addData(fZip.readAll()); postData.addEndingBoundary(); fZip.close(); QFile::remove(zipFileName); QByteArray data = postData.requestStream(); QString movie_fps = QString::number((int)ceil(movieInfo.fps * 100)); movie_fps.insert(2, ','); QString urlTxt; if(movieInfo.isErr) { urlTxt = napiUploadUrlSimpleTpl.arg(movie_md5).arg(movie_size); } else { urlTxt = napiUploadUrlTpl.arg(movieInfo.time).arg(movieInfo.width) .arg(movieInfo.height).arg(movie_fps) .arg(movie_md5).arg(movie_size); } QUrl url(urlTxt); QHttpRequestHeader header("POST", url.path() + "?" + url.encodedQuery()); header.setValue("Host", url.host()); header.setValue("Accept", "text/html, */*"); header.setValue("Content-Type", "multipart/form-data; boundary=" + postData.boundaryTxt()); header.setValue("Connection", "keep-alive"); header.setValue("User-Agent", QString("QNapi ") + QNAPI_VERSION); SyncHTTP http; http.setHost(url.host()); if(!http.syncRequest(header, data)) return NAPI_FAIL; QString response = http.readAll(); if(response.indexOf("NPc0") == 0) return NAPI_ADDED_NEW; if((response.indexOf("NPc2") == 0) || (response.indexOf("NPc3") == 0)) return NAPI_OK; return NAPI_UNKNOWN; } // Wysyla blad o niepasujacyh napisach QNapiProjektEngine::ReportResult QNapiProjektEngine::reportBad(const QString & language, const QString & nick, const QString & pass, const QString & comment, QString *response) { QFileInfo fi(moviePath); subtitlesPath = fi.path() + "/" + fi.completeBaseName() + ".txt"; if(!QFile::exists(subtitlesPath)) return NAPI_NO_SUBTITLES; checksum(); QMultipartHttpRequest postData; postData.addBoundary(); postData.addContentDisposition("name=\"nick\""); postData.addData(nick); postData.addBoundary(); postData.addContentDisposition("name=\"pass\""); postData.addData(pass); postData.addBoundary(); postData.addContentDisposition("name=\"l\""); postData.addData(language); postData.addBoundary(); postData.addContentDisposition("name=\"md5\""); postData.addData(checkSum); postData.addBoundary(); postData.addContentDisposition("name=\"kmt\""); postData.addData(comment); postData.addEndingBoundary(); QByteArray data = postData.requestStream(); QUrl url(napiReportBadUrlTpl); QHttpRequestHeader header("POST", url.path()); header.setValue("Host", url.host()); header.setValue("Accept", "text/html, */*"); header.setValue("Content-Type", "multipart/form-data; boundary=" + postData.boundaryTxt()); header.setValue("Connection", "keep-alive"); header.setValue("User-Agent", QString("QNapi ") + QNAPI_VERSION); SyncHTTP http; http.setHost(url.host()); if(!http.syncRequest(header, data)) return NAPI_NOT_REPORTED; *response = QTextCodec::codecForName("windows-1250")->toUnicode(http.readAll()); return NAPI_REPORTED; } // Tajemnicza funkcja f() :D QString QNapiProjektEngine::napiFDigest(const QString & input) { if(input.size() != 32) return ""; int idx[] = {0xe, 0x3, 0x6, 0x8, 0x2}, mul[] = {2, 2, 5, 4, 3}, add[] = {0x0, 0xd, 0x10, 0xb, 0x5}, a, m, i, t, v; QString b; char tmp[2] = { 0, 0 }; for(int j = 0; j <= 4; j++) { a = add[j]; m = mul[j]; i = idx[j]; tmp[0] = input[i].toAscii(); t = a + (int)(strtol(tmp, NULL, 16)); v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16)); snprintf(tmp, 2, "%x", (v * m) % 0x10); b += tmp; } return b; } qnapi-0.1.5/src/qnapiopendialog.cpp0000644000175000017500000000523511014334373016704 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qnapiopendialog.h" QNapiOpenDialog::QNapiOpenDialog( QWidget * parent, const QString & caption, const QString & init_path, FilterMode filterMode ) : QFileDialog(parent) { setAttribute(Qt::WA_QuitOnClose, false); setWindowTitle(caption); if(filterMode == Movies) { setFilter(tr("Filmy (*.avi *.asf *.divx *.dat *.mkv *.mov *.mp4 *.mpeg *.mpg *.ogm " "*.rm *.rmvb *.wmv);; Wszystkie pliki (*.*)")); } else if(filterMode == Subtitles) { setFilter(tr("Napisy (*.txt);; Wszystkie pliki (*.*)")); } if(QFileInfo(init_path).isDir()) setDirectory(init_path); else setDirectory(QDir::currentPath()); QStringList sideUrls; #ifdef Q_WS_MAC sideUrls << "/Volumes"; setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif sideUrls << QString(QDir::homePath() + "/Movies") << QString(QDir::homePath() + "/movies") << QString(QDir::homePath() + "/Video") << QString(QDir::homePath() + "/video") << QString(QDir::homePath() + "/Filmy") << QString(QDir::homePath() + "/filmy") << QString(QDir::homePath() + "/Wideo") << QString(QDir::homePath() + "/wideo"); QList urls = sidebarUrls(); foreach(QString sideUrl, sideUrls) { if(!QDir().exists(sideUrl)) continue; QUrl url = QUrl::fromLocalFile(sideUrl); if(!urls.contains(url)) urls << url; } setSidebarUrls(urls); } bool QNapiOpenDialog::selectFile() { if(!placeWindow()) return false; setFileMode(QFileDialog::ExistingFile); return exec(); } bool QNapiOpenDialog::selectFiles() { if(!placeWindow()) return false; setFileMode(QFileDialog::ExistingFiles); return exec(); } bool QNapiOpenDialog::selectDirectory() { if(!placeWindow()) return false; // QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks ? setFileMode(QFileDialog::DirectoryOnly); return exec(); } bool QNapiOpenDialog::placeWindow() { if(isVisible()) { raise(); return false; } // workaround dla compiza move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); return true; } qnapi-0.1.5/src/qnapiabstractengine.cpp0000644000175000017500000001305211014764477017564 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qnapiabstractengine.h" #include // Sprawdza poprawnosc sciezki do 7zipa (z konfiguracji) bool QNapiAbstractEngine::checkP7ZipPath() { return QFileInfo(GlobalConfig().p7zipPath()).isExecutable(); } // Sprawdza poprawnosc sciezki do katalogu tymczasowego (z konfiguracji) bool QNapiAbstractEngine::checkTmpPath() { QFileInfo f(GlobalConfig().tmpPath()); return f.isDir() && f.isWritable(); } // Sprawdza uprawnienia zapisu do katalogu docelowego (katalogu z filmem) bool QNapiAbstractEngine::checkWritePermissions() { return QFileInfo(QFileInfo(moviePath).path()).isWritable(); } // Dokonuje post-przetwarzania pliku z napisami (na podstawie konfiguracji) void QNapiAbstractEngine::doPostProcessing() { // Usuwanie linii z plikow z napisami if(GlobalConfig().ppRemoveLines()) { ppRemoveLinesContainingWords(GlobalConfig().ppRemoveWords()); } // Zmiana kodowania pobranych napisow if(GlobalConfig().ppChangeEncoding()) { // Jesli automatycznie nie uda mu sie wykryc kodowania, to jako kodowania // zrodlowego uzywa kodowania wybranego przez uzytkownika if (!GlobalConfig().ppAutoDetectEncoding() || !ppChangeSubtitlesEncoding(GlobalConfig().ppEncodingTo())) { ppChangeSubtitlesEncoding(GlobalConfig().ppEncodingFrom(), GlobalConfig().ppEncodingTo()); } } #ifndef Q_WS_WIN // Zmiana uprawnien do pliku if(GlobalConfig().ppChangePermissions()) { bool validPermissions; int permInt = GlobalConfig().ppPermissions().toInt(&validPermissions, 8); if(validPermissions) { int perm = 0; perm |= (permInt & 0700) << 2; perm |= (permInt & 0070) << 1; perm |= (permInt & 0007); ppChangeSubtitlesPermissions(QFile::Permissions(perm)); } } #endif } QString QNapiAbstractEngine::ppDetectEncoding(const QString & fileName, int testBufferSize) { QString from; QStringList codecs; // Tylko takie kodowania obsługuja polskie litery codecs << "windows-1250" << "windows-1257" << "ISO-8859-2" << "ISO-8859-13" << "ISO-8859-16" << "UTF-8"; QFile f(fileName); if(!f.open(QIODevice::ReadOnly)) return ""; QByteArray testData = (testBufferSize > 0) ? f.read(testBufferSize) : f.readAll(); f.close(); foreach(QString codec, codecs) { QTextStream ts(testData); ts.setCodec(qPrintable(codec)); QString encodedData = ts.readAll(); QStringList chars = QString::fromUtf8("ą/ś/ż/ć/ń/ł/ó/ę").split("/"); int i; for (i = 0; i < chars.count(); i++) { if(!encodedData.contains(chars[i], Qt::CaseInsensitive)) break; } if(i == chars.count()) { from = codec; break; } } return from; } // Konwertuje napisy z jednego kodowania na inne bool QNapiAbstractEngine::ppChangeSubtitlesEncoding(const QString & from, const QString & to) { QFile f(subtitlesPath); if(!f.open(QIODevice::ReadOnly)) return false; QByteArray fileContent = f.readAll(); QString contentStr = QTextCodec::codecForName(qPrintable(from))->toUnicode(fileContent); f.close(); if(to.compare("UTF-8", Qt::CaseInsensitive)) { fileContent = QTextCodec::codecForName(qPrintable(to)) ->fromUnicode(contentStr.constData(), contentStr.size()); } if(!f.open(QIODevice::WriteOnly)) return false; f.write(fileContent); f.close(); return true; } // Konwertuje napisy z jednego kodowania na inne, dokonujac proby autodetekcji // kodowania zrodlowego bool QNapiAbstractEngine::ppChangeSubtitlesEncoding(const QString & to) { if(!QFileInfo(subtitlesPath).exists()) return false; QString from = ppDetectEncoding(subtitlesPath); if(from.isEmpty()) return false; return ppChangeSubtitlesEncoding(from, to); } // Usuwanie linii zawierajacych podane slowa z pliku z napisami bool QNapiAbstractEngine::ppRemoveLinesContainingWords(QStringList wordList) { if(!QFileInfo(subtitlesPath).exists()) return false; wordList = wordList.filter("^(.+)$"); QString fromCodec = ppDetectEncoding(subtitlesPath); if(fromCodec.isEmpty()) fromCodec = GlobalConfig().ppEncodingFrom(); QFile f(subtitlesPath); if(!f.open(QIODevice::ReadOnly)) return false; QList lines = f.readAll().split('\n'); QList out; foreach(QByteArray line, lines) { int i; while((i = line.indexOf('\r')) >= 0) line.remove(i, 1); QTextStream ts(line); ts.setCodec(qPrintable(fromCodec)); QString encLine = ts.readAll(); if(encLine.isEmpty()) continue; bool found = false; foreach(QString word, wordList) { if(encLine.contains(word, Qt::CaseInsensitive)) { found = true; break; } } if(found) continue; out << line; } f.close(); if(!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; foreach(QByteArray line, out) { f.write(line); f.write("\r\n", 2); } f.close(); return true; } #ifndef Q_WS_WIN // Zmienia uprawnienia do pliku z napisami bool QNapiAbstractEngine::ppChangeSubtitlesPermissions(QFile::Permissions permissions) { if(!QFileInfo(subtitlesPath).exists()) return false; return QFile::setPermissions(subtitlesPath, permissions); } #endif qnapi-0.1.5/src/qdraglistwidget.cpp0000644000175000017500000000717711014772247016745 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qdraglistwidget.h" void QDragListWidget::addItem(const QString & label) { QListWidgetItem *item = new QListWidgetItem(widgetIcon, label, this); if(!item) return; QListWidget::addItem(item); } void QDragListWidget::addItem(QListWidgetItem * item) { if(!item) return; item->setIcon(widgetIcon); QListWidget::addItem(item); } void QDragListWidget::addItems(const QStringList & labels) { foreach(QString label, labels) addItem(label); } void QDragListWidget::MoveAll(QDragListWidget *another) { for(int i = 0; i < count(); i++) { another->addItem(item(i)->text()); } clear(); } void QDragListWidget::MoveSelected(QDragListWidget *another) { QList selected = selectedItems(); for(QList::iterator i = selected.begin(); i != selected.end(); i++) { another->addItem((*i)->text()); } QStringList currentList; for(int i = 0; i < count(); i++) { currentList << item(i)->text(); } int j; for(QList::iterator i = selected.begin(); i != selected.end(); i++) { j = currentList.indexOf((*i)->text()); if(j >= 0) currentList.removeAt(j); } clear(); addItems(currentList); } void QDragListWidget::dragEnterEvent(QDragEnterEvent *event) { if(event->source() != this) event->acceptProposedAction(); } void QDragListWidget::dropEvent(QDropEvent *event) { if(event->source() == this) return; QList urlList; QListWidgetItem *item; QFileInfo info; urlList = event->mimeData()->urls(); foreach(QUrl url, urlList) { info.setFile(url.toString()); if(!info.exists() || !info.isFile()) continue; item = new QListWidgetItem(info.absoluteFilePath()); addItem(item); } QDragListWidget *sourceList = dynamic_cast(event->source()); if(!sourceList) return; /// TODO: przydaloby sie to przepisac z uzyciem MVC, wtedy ponizszy fragment bylby banalny QStringList currentList; for(int i = 0; i < sourceList->count(); i++) { currentList << sourceList->item(i)->text(); } QList selected = sourceList->selectedItems(); int j; for(QList::iterator i = selected.begin(); i != selected.end(); i++) { j = currentList.indexOf((*i)->text()); if(j >= 0) currentList.removeAt(j); } sourceList->clear(); sourceList->addItems(currentList); emit dragFinished(); } QStringList QDragListWidget::mimeTypes () const { QStringList list; list.append("text/uri-list"); return list; } Qt::DropActions QDragListWidget::supportedDropActions () const { return Qt::CopyAction | Qt::MoveAction; } void QDragListWidget::mouseMoveEvent(QMouseEvent *event) { if (!(event->buttons() & Qt::LeftButton)) return; if (currentItem() == NULL) return; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; QList list; QList selected = selectedItems(); for(QList::iterator i = selected.begin(); i != selected.end(); i++) { list << QUrl((*i)->text()); } mimeData->setUrls(list); drag->setMimeData(mimeData); drag->start(Qt::CopyAction | Qt::MoveAction); } qnapi-0.1.5/src/frmscan.cpp0000644000175000017500000002657711014772157015205 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmscan.h" frmScan::frmScan(QWidget *parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); connect(ui.pbCancel, SIGNAL(clicked()), this, SLOT(pbCancelClicked())); connect(ui.pbDirectorySelect, SIGNAL(clicked()), this, SLOT(selectDirectory())); connect(ui.leDirectory, SIGNAL(textChanged(QString)), this, SLOT(leDirectoryTextChanged())); connect(ui.pbScan, SIGNAL(clicked()), this, SLOT(pbScanClicked())); connect(&scanThread, SIGNAL(addFile(QString)), this, SLOT(addFile(QString))); connect(&scanThread, SIGNAL(scanFinished(bool)), this, SLOT(scanFinished())); connect(ui.pbAddAll, SIGNAL(clicked()), this, SLOT(pbAddAllClicked())); connect(ui.pbAdd, SIGNAL(clicked()), this, SLOT(pbAddClicked())); connect(ui.pbRemove, SIGNAL(clicked()), this, SLOT(pbRemoveClicked())); connect(ui.pbRemoveAll, SIGNAL(clicked()), this, SLOT(pbRemoveAllClicked())); connect(ui.lwFound, SIGNAL(dragFinished()), this, SLOT(checkPbGetEnabled())); connect(ui.lwSelected, SIGNAL(dragFinished()), this, SLOT(checkPbGetEnabled())); connect(ui.pbGet, SIGNAL(clicked()), this, SLOT(pbGetClicked())); connect(&getThread, SIGNAL(fileNameChange(QString)), this, SLOT(fileNameChange(QString))); connect(&getThread, SIGNAL(progressChange(int)), ui.pbProgress, SLOT(setValue(int))); connect(&getThread, SIGNAL(finished()), this, SLOT(downloadFinished())); if(QFileInfo(GlobalConfig().lastScanDir()).isDir()) ui.leDirectory->setText(GlobalConfig().lastScanDir()); QList scanFilters = GlobalConfig().scanFilters(); ui.cbFilters->clear(); for(int i = 0; i < scanFilters.size(); i++) { ui.cbFilters->addItem(scanFilters[i]); } ui.leSkipFilters->setText(GlobalConfig().scanSkipFilters()); ui.cbSkipIfSubtitlesExists->setChecked(GlobalConfig().scanSkipIfSubtitlesExists()); QIcon iconFilm(":/ui/film.png"); ui.lwFound->setWidgetIcon(iconFilm); ui.lwSelected->setWidgetIcon(iconFilm); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } void frmScan::closeEvent(QCloseEvent *event) { QList scanFilters; for(int i = 0; i < ui.cbFilters->count(); i++) { scanFilters << ui.cbFilters->itemText(i); } GlobalConfig().setLastScanDir(ui.leDirectory->text()); GlobalConfig().setScanFilters(scanFilters); GlobalConfig().setScanSkipFilters(ui.leSkipFilters->text()); GlobalConfig().setScanSkipIfSubtitlesExists(ui.cbSkipIfSubtitlesExists->isChecked()); GlobalConfig().save(); if(pbCancelClicked()) event->accept(); else event->ignore(); closeRequested = true; } bool frmScan::pbCancelClicked() { if(scanThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać skanowanie katalogów?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { scanThread.requestAbort(); ui.lbAction->setText(tr("Kończenie zadań...")); qApp->processEvents(); scanThread.wait(); return true; } return false; } if(getThread.isRunning()) { if( QMessageBox::question(this, tr("QNapi"), tr("Czy chcesz przerwać pobieranie napisów?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes ) { pbGetClicked(); } return false; } close(); return true; } void frmScan::selectDirectory() { QString dir = QFileInfo(ui.leDirectory->text()).path(); dir = QDir().exists(dir) ? dir : GlobalConfig().lastScanDir(); QNapiOpenDialog openDialog(this, tr("Wskaż katalog do skanowania"), dir, QNapiOpenDialog::None); if(openDialog.selectDirectory()) dir = openDialog.selectedFiles().first(); if(!dir.isEmpty() && QDir().exists(dir)) ui.leDirectory->setText(dir); } void frmScan::leDirectoryTextChanged() { ui.pbScan->setEnabled(!ui.leDirectory->text().isEmpty() ? QDir().exists(ui.leDirectory->text()) : false); } void frmScan::pbScanClicked() { if(!scanThread.isRunning()) { ui.leDirectory->setEnabled(false); ui.pbDirectorySelect->setEnabled(false); ui.pbScan->setText(tr("Przerwij")); ui.lbAction->setText(tr("Skanowanie folderów...")); ui.pbProgress->setEnabled(false); ui.pbGet->setEnabled(false); ui.lwFound->clear(); ui.lwSelected->clear(); enableControlWidgets(false); enableFilesWidgets(false); scanThread.setSearchPath(ui.leDirectory->text()); scanThread.setFilters(ui.cbFilters->currentText()); scanThread.setSkipFilters(ui.leSkipFilters->text()); scanThread.setSkipIfSubtitlesExists(ui.cbSkipIfSubtitlesExists->isChecked()); scanThread.start(); } else { scanThread.requestAbort(); ui.lbAction->setText(tr("Przerywanie skanowania...")); ui.pbScan->setEnabled(false); qApp->processEvents(); scanThread.wait(); ui.pbScan->setEnabled(true); scanFinished(); } } void frmScan::addFile(const QString & fileName) { ui.lwFound->addItem(fileName); } void frmScan::scanFinished() { enableControlWidgets(true); enableFilesWidgets(ui.lwFound->count() > 0); ui.pbScan->setText("Skanuj"); ui.lbAction->setText(tr((ui.lwFound->count() > 0) ? "Przenieś pliki z listy znalezionych do listy wybranych." : "Nie znaleziono plików z filmami.")); } void frmScan::enableControlWidgets(bool enable) { ui.lbDirectory->setEnabled(enable); ui.leDirectory->setEnabled(enable); ui.pbDirectorySelect->setEnabled(enable); ui.lbFilter->setEnabled(enable); ui.cbFilters->setEnabled(enable); ui.lbSkip->setEnabled(enable); ui.leSkipFilters->setEnabled(enable); ui.cbSkipIfSubtitlesExists->setEnabled(enable); } void frmScan::enableFilesWidgets(bool enable) { ui.lbFound->setEnabled(enable); ui.lwFound->setEnabled(enable); ui.pbAddAll->setEnabled(enable); ui.pbAdd->setEnabled(enable); ui.pbRemove->setEnabled(enable); ui.pbRemoveAll->setEnabled(enable); ui.lbSelected->setEnabled(enable); ui.lwSelected->setEnabled(enable); } void frmScan::pbAddAllClicked() { ui.lwFound->MoveAll(ui.lwSelected); checkPbGetEnabled(); } void frmScan::pbAddClicked() { ui.lwFound->MoveSelected(ui.lwSelected); checkPbGetEnabled(); } void frmScan::pbRemoveClicked() { ui.lwSelected->MoveSelected(ui.lwFound); checkPbGetEnabled(); } void frmScan::pbRemoveAllClicked() { ui.lwSelected->MoveAll(ui.lwFound); checkPbGetEnabled(); } void frmScan::checkPbGetEnabled() { ui.pbGet->setEnabled(ui.lwSelected->count() > 0); ui.pbProgress->setEnabled(ui.lwSelected->count() > 0); } void frmScan::pbGetClicked() { if(!getThread.isRunning()) { closeRequested = false; enableControlWidgets(false); enableFilesWidgets(false); ui.pbScan->setEnabled(false); ui.pbGet->setText(tr("Przerwij")); ui.pbProgress->setValue(0); getThread.queue.clear(); for(int i = 0; i < ui.lwSelected->count(); i++) { getThread.queue << ui.lwSelected->item(i)->text(); } getThread.start(); } else { getThread.requestAbort(); ui.lbAction->setText(tr("Przerywanie pobierania...")); ui.pbGet->setEnabled(false); qApp->processEvents(); } } void frmScan::fileNameChange(const QString & fileName) { ui.lbAction->setText(tr("Pobieranie napisów dla %1...").arg(fileName)); } void frmScan::downloadFinished() { enableControlWidgets(true); enableFilesWidgets(true); ui.pbGet->setEnabled(true); ui.pbScan->setEnabled(true); ui.pbGet->setText(tr("Pobierz napisy")); ui.pbProgress->setValue(0); if(!getThread.criticalMessage.isEmpty()) { ui.lbAction->setText(getThread.criticalMessage); QMessageBox::critical(0, tr("Błąd krytyczny!"), getThread.criticalMessage); } else if(getThread.napiSuccess + getThread.napiFail > 0) { ui.lbAction->setText(tr("Napisy pobrano.")); if(getThread.napiSuccess > 0) { frmSummary summary; summary.setSuccessList(getThread.gotList); summary.setFailedList(getThread.failedList); summary.exec(); } else { QString msg = tr("Nie udało się dopasować napisów dla %1 %2!").arg(getThread.napiFail) .arg(tr((getThread.napiFail == 1) ? "pliku" : "plików")); QMessageBox::information(0, tr("Zakończono pobieranie napisów"), msg); } } else ui.lbAction->setText(tr("Zakończono.")); if(closeRequested) close(); } void ScanFilesThread::run() { abort = false; fileList.clear(); emit scanFinished(doScan(searchPath)); } bool ScanFilesThread::doScan(const QString & path) { QString myPath = QFileInfo(path).absoluteFilePath(); if(!QDir().exists(myPath)) return false; emit folderChange(myPath); QFileInfoList list = QDir(myPath).entryInfoList(scanFilters, QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::Hidden); for(QFileInfoList::iterator p=list.begin(); p != list.end(); p++) { if(abort) return false; if((*p).isDir() && ((*p).absoluteFilePath() != myPath)) { if(!doScan((*p).absoluteFilePath())) return false; } else { if(!QFile::exists((*p).absoluteFilePath())) continue; if(skipIfSubtitlesExists && QFile::exists((*p).absolutePath() + "/" + (*p).completeBaseName() + ".txt")) { continue; } bool skip = false; for(QStringList::iterator s = skipFilters.begin(); s != skipFilters.end(); s++) { if((*s).isEmpty()) continue; if((*p).fileName().indexOf(*s) >= 0) { skip = true; break; } } if(skip) continue; fileList << (*p).absoluteFilePath(); emit addFile((*p).absoluteFilePath()); } } return true; } void GetFilesThread::run() { abort = false; criticalMessage.clear(); gotList.clear(); failedList.clear(); int size = queue.size(); if(size <= 0) return; float step = 100.0f / size; QString windowTitle, md5; napiSuccess = napiFail = 0; QNapiProjektEngine *napi; emit progressChange(0); for(int i = 0; i < size; i++) { napi = new QNapiProjektEngine(queue[i]); if(!napi) continue; QFileInfo fi(queue[i]); emit fileNameChange(fi.fileName()); if(!napi->checkWritePermissions()) { emit criticalError(tr("Brak uprawnień zapisu do katalogu '%1'!").arg(QFileInfo(queue[i]).path())); delete napi; break; } napi->checksum(); if(abort) { delete napi; return; } emit progressChange((int)ceil(step * i + step / 3)); // pobieranie if(!napi->tryDownload()) { if(abort) { delete napi; return; } ++napiFail; failedList << queue[i]; delete napi; continue; } if(abort) { delete napi; return; } emit progressChange((int)ceil(step * i + 2 * step / 3)); // dopasowywanie if(!napi->tryMatch()) { if(abort) { delete napi; return; } ++napiFail; failedList << queue[i]; delete napi; continue; } if(abort) { delete napi; return; } ++napiSuccess; gotList << queue[i]; if(GlobalConfig().ppEnabled()) { emit progressChange((int)ceil(step * i + 5 * step / 6)); napi->doPostProcessing(); } emit progressChange((int)ceil(step * (i + 1))); delete napi; } emit progressChange(100); } qnapi-0.1.5/src/frmabout.cpp0000644000175000017500000000641111014541610015340 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "frmabout.h" frmAbout::frmAbout(QWidget * parent, Qt::WFlags f) : QDialog(parent, f) { ui.setupUi(this); #ifdef Q_WS_MAC setAttribute(Qt::WA_MacBrushedMetal, GlobalConfig().useBrushedMetal()); #endif setAttribute(Qt::WA_QuitOnClose, false); ui.lbTitle->setText(QString("QNapi ") + QNAPI_VERSION); const QString aboutText = tr( "

QNapi jest nieoficjalnym, wolnym klonem programu NAPI-PROJEKT, " "napisanym z myślą o użytkownikach systemów Linux, Mac OS X oraz innych, pod które " "oryginalny klient NAPI nie jest dostępny.

Ten program rozprowadzany " "jest na licencji GNU General Public License w wersji 2. lub każdej nowszej.

" "

Autor: Krzemin <" "pkrzemin@o2.pl>

Prawa autorskie: Copyright (C) 2008 Krzemin

" "

WWW: http://krzemin.iglu.cz/qnapi

" ""); const QString thanksText = tr( "

Podziękowania należą się wszystkim osobom, które aktywnie wsparły rozwój " "QNapi, a w szczególności:

A także paczkującym dla różnych " "dystrybucji:

obi_gl, Jakub Schmidtke, Jan Stępień, Łukasz Jagiełło, Patryk Cisek

" "...oraz wszystkim tym, o których zapomniałem ;)

"); const QString supportText = tr( "

QNapi zaoszczędził Ci sporo wysiłku przy szukaniu napisów do filmów? " "Uważasz, że to dobry program i powinien się dalej rozwijać?

" "

Ty również możesz wesprzeć dalszy rozwój programu!

" "

Oprócz promowania go wśród znajomych, na forach internetowych, blogach itp., rozważ drobne wsparcie " "finansowe autora projektu, motywując go do dalszych prac nad programem, poprzez dokonanie przelewu na " "podany niżej nr konta:

" "

73 1020 3974 0000 5202 0098 8774

" "

lub za pośrednictwem serwisu PayPal:

" "

" "http://www.qt-apps.org/content/donate.php?content=76259

" "

Będę wdzięczny nawet za najmniejsze wpłaty ;)

" ); ui.tbAbout->setText(aboutText); ui.tbThanks->setText(thanksText); ui.tbSupport->setText(supportText); // workaround dla compiza? move((QApplication::desktop()->width() - width()) / 2, (QApplication::desktop()->height() - height()) / 2); } qnapi-0.1.5/src/qnapiabstractengine.h0000644000175000017500000000346711014764477017242 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPIABSTRACTENGINE__H__ #define __QNAPIABSTRACTENGINE__H__ #include #include #include #include #include #include "qnapiconfig.h" #include "qmultiparthttprequest.h" class QNapiAbstractEngine { protected: QString moviePath, subtitlesPath, tmpPath, checkSum; QNapiAbstractEngine(const QString & movieFile, const QString & subtitlesFile = "") : moviePath(movieFile), subtitlesPath(subtitlesFile) { tmpPath = GlobalConfig().tmpPath(); }; virtual ~QNapiAbstractEngine() { cleanup(); }; virtual QString checksum() = 0; virtual bool tryDownload() = 0; virtual bool tryMatch() = 0; virtual void cleanup() {}; public: static bool checkP7ZipPath(); static bool checkTmpPath(); bool checkWritePermissions(); static bool ppEnabled(); void doPostProcessing(); QString ppDetectEncoding(const QString & fileName, int testBufferSize = 10240); bool ppChangeSubtitlesEncoding(const QString & from, const QString & to); bool ppChangeSubtitlesEncoding(const QString & to); bool ppRemoveLinesContainingWords(QStringList wordList); #ifndef Q_WS_WIN bool ppChangeSubtitlesPermissions(QFile::Permissions permissions); #endif }; #endif qnapi-0.1.5/src/qnapicli.cpp0000644000175000017500000000717211015002461015323 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "qnapicli.h" bool QNapiCli::analyze() { QString p; for(int i = 1; i < m_argc; i++) { p = m_argv[i]; if((p == "--help") || (p == "-h")) { mode = CM_HELP; return true; } else if((p == "--console") || (p == "-c")) { if(mode == CM_UNSET) mode = CM_CONSOLE; } else if((p == "--quiet") || (p == "-q")) { mode = CM_QUIET; } else if(QFileInfo(p).isFile()) { movieList << p; } } #ifdef Q_WS_X11 if((getenv("DISPLAY") == 0) && (mode == CM_UNSET)) mode = CM_CONSOLE; #endif return (mode == CM_CONSOLE) || (mode == CM_QUIET); } int QNapiCli::exec() { if(mode != CM_QUIET) printCli(QString("QNapi %1, (C) 2008 Krzemin, http://krzemin.iglu.cz\n").arg(QNAPI_VERSION)); if(mode == CM_HELP) { printHelp(); return 0; } if(movieList.empty()) { printCli("Nie podano sciezki do pliku z filmem!"); return 1; } if(!QNapiAbstractEngine::checkP7ZipPath()) { printCli("Sciezka do programu p7zip jest nieprawidlowa! Sprawdz swoje ustawienia."); return 2; } if(!QNapiAbstractEngine::checkTmpPath()) { printCli("Nie można pisac do katalogu tymczasowego! Sprawdz swoje ustawienia."); return 3; } QNapiProjektEngine *napi; foreach(QString movie, movieList) { napi = new QNapiProjektEngine(movie); if(!napi) continue; if(!napi->checkWritePermissions()) { printCli(QString("Brak uprawnien zapisu do katalogu '%1'").arg(QFileInfo(movie).path())); delete napi; continue; } printCli(QString(QString(" * Pobieranie napisow dla '%1'")).arg(QFileInfo(movie).fileName())); printCli(QString(QString(" obliczanie sumy kontrolnej..."))); napi->checksum(); printCli(QString(QString(" pobieranie napisow z serwera..."))); if(!napi->tryDownload()) { printCli(QString(QString(" ! nie znaleziono napisow"))); delete napi; continue; } printCli(QString(QString(" dopasowywanie napisow..."))); if(!napi->tryMatch()) { printCli(QString(QString(" ! nie udalo sie dopasowac napisow"))); delete napi; continue; } if(GlobalConfig().ppEnabled()) { printCli(QString(QString(" przetwarzanie pobranych napisow..."))); napi->doPostProcessing(); } delete napi; } return 0; } void QNapiCli::printHelp() { printCli(QString("QNapi jest programem do automatycznego pobierania i dopasowywania")); printCli(QString("napisow do filmow, korzystajacym z bazy programu NAPI-PROJEKT.\n")); printCli(QString("QNapi rozprowadzany jest na warunkach licencji GNU General Public License v2.\n")); printCli(QString("Uzycie programu: %1 [opcje] [lista plikow]").arg(m_argv[0])); printCli(QString("Dostepne opcje:")); printCli(QString(" -c, --console pobieranie napisow z konsoli")); printCli(QString(" -q, --quiet pobiera napisy nie wypisujac zadnych komunikatow")); printCli(QString(" ani nie pokazujac zadnych okien")); printCli(QString(" -h, --help tekst pomocy, ktory wlasnie czytasz\n")); } void QNapiCli::printCli(const QString & string) { if(mode != CM_QUIET) qDebug(qPrintable(string)); } qnapi-0.1.5/src/frmcorrect.h0000644000175000017500000000356111014572705015350 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMCORRECT__H__ #define __FRMCORRECT__H__ #include "ui_frmcorrect.h" #include #include #include #include #include #include #include #include "qnapithread.h" #include "qnapiconfig.h" #include "qnapiprojektengine.h" #include "qnapiopendialog.h" class PostThread : public QNapiThread { Q_OBJECT public: void run(); void setPostParams(const QString & movie_file, const QString & subtitles_file, const QString & comment_txt, const QString & lang) { movie = movie_file; subtitles = subtitles_file; comment = comment_txt; language = lang; } QNapiProjektEngine::UploadResult taskResult; signals: void postFinished(bool interrupted = false); void invalidUserPass(); private: QString movie, subtitles, comment, language; }; class frmCorrect: public QDialog { Q_OBJECT public: frmCorrect(QWidget *parent = 0, Qt::WFlags f = 0); ~frmCorrect() {}; private: void closeEvent(QCloseEvent *event); Ui::frmCorrect ui; PostThread postThread; private slots: void selectMovie(); void selectSubtitles(); void checkPostEnable(); void pbPostClicked(); void postFinished(bool interrupt = false); void invalidUserPass(); }; #endif qnapi-0.1.5/src/frmoptions.h0000644000175000017500000000264611000145225015371 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMOPTIONS__H__ #define __FRMOPTIONS__H__ #include #include #include #include #include #include #include #include "ui_frmoptions.h" #include "qnapiconfig.h" #include "frmcreateuser.h" class frmOptions: public QDialog { Q_OBJECT public: frmOptions(QWidget *parent = 0, Qt::WFlags f = 0); ~frmOptions() {}; public slots: void writeConfig(); void readConfig(); private slots: void le7zPathChanged(); void select7zPath(); void leTmpPathChanged(); void selectTmpPath(); void pbRegisterClicked(); void changeEncodingClicked(); void autoDetectEncodingClicked(); void showAllEncodingsClicked(); void useBrushedMetalClicked(); private: Ui::frmOptions ui; void showAllEncodings(); }; #endif qnapi-0.1.5/src/napi.cpp0000644000175000017500000003145511002345600014454 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #include "napi.h" // Zwraca sume md5 z pierwszych max_size bajtow z pliku // lub calego, jesli max_size == 0 QString napiFileMd5Sum(const QString & filename, unsigned long max_size) { QFile file(filename); QByteArray fileArray; file.open(QIODevice::ReadOnly); fileArray = ( max_size == 0 ) ? file.readAll() : file.read(max_size); file.close(); QByteArray b = QCryptographicHash::hash(fileArray, QCryptographicHash::Md5); fileArray.clear(); QString out; char next[3]; for(int i = 0; i < 16; i++) { sprintf(next, "%.2x", (unsigned char)b[i]); out += next; } return out; } // Tajemnicza funkcja f() :D QString napiFDigest(QString input) { if(input.size() != 32) return ""; int idx[] = {0xe, 0x3, 0x6, 0x8, 0x2}, mul[] = {2, 2, 5, 4, 3}, add[] = {0x0, 0xd, 0x10, 0xb, 0x5}, a, m, i, t, v; QString b; char tmp[2] = { 0, 0 }; for(int j = 0; j <= 4; j++) { a = add[j]; m = mul[j]; i = idx[j]; tmp[0] = input[i].toAscii(); t = a + (int)(strtol(tmp, NULL, 16)); v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16)); sprintf(tmp, "%x", (v * m) % 0x10); b += tmp; } return b; } // Zasysa napisy o sumie md5sum w jezyku language i zapisuje je w pliku path bool napiDownload(const QString & md5sum, const QString & path, const QString & language, const QString & nick, const QString & pass) { SyncHTTP http; QString urlTxt = napiDownloadUrlTpl.arg(language).arg(md5sum).arg(napiFDigest(md5sum)).arg(nick).arg(pass); QUrl url(urlTxt); http.setHost(url.host()); http.syncGet(url.path() + "?" + url.encodedQuery()); QByteArray buffer = http.readAll(); if(buffer.indexOf("NPc") == 0) return false; QFile file(path); if(file.exists()) file.remove(); if(!file.open(QIODevice::WriteOnly)) return false; int r = file.write(buffer); file.close(); return r; } // Dopasowuje napisy i usuwa pliki tymczasowe bool napiMatchSubtitles(const QString & md5sum, const QString & zip_file, const QString & movie_file, bool noBackup, const QString & tmp_path, const QString & p7zip_path) { if(!QFile::exists(zip_file)) return false; if(!QFile::exists(movie_file)) return false; QFileInfo fi(p7zip_path); if(!fi.isExecutable()) return false; QStringList args; args << "x" << "-y" << ("-p"+napiZipPassword) << ("-o"+tmp_path) << zip_file; QProcess p7zip; p7zip.start(p7zip_path, args); if(!p7zip.waitForFinished()) return false; QString subtitleFile = tmp_path + "/" + md5sum + ".txt"; if(!QFile::exists(subtitleFile)) return false; QFileInfo mf(movie_file); QString newName = mf.path() + "/" + mf.completeBaseName() + ".txt"; if(QFile::exists(newName)) { if(!noBackup) { QFileInfo nn(newName); QFile::copy(newName, nn.path() + "/" + nn.completeBaseName() + "_old.txt"); } QFile::remove(newName); } bool r; #ifdef Q_WS_WIN // Pod windowsem, aby "wyczyscic" atrybuty pliku, tworzymy go na nowo QFile f(newName), f2(subtitleFile); if(!f.open(QIODevice::WriteOnly) || !f2.open(QIODevice::ReadOnly)) { r = false; f.close(); } else { r = f.write(f2.readAll()) > 0; f2.close(); f.close(); } #else // pod normalnymi OS-ami nie trzeba sie gimnastykowac z atrybutami r = QFile::copy(subtitleFile, newName); #endif QFile::remove(subtitleFile); QFile::remove(zip_file); return r; } // Sprawdza uzytkownika w bazie bool napiCheckUser(const QString & nick, const QString & pass) { SyncHTTP http; QString urlTxt = napiCheckUserUrlTpl.arg(nick).arg(pass); QUrl url(urlTxt); http.setHost(url.host()); http.syncGet(url.path() + "?" + url.encodedQuery()); QString buffer = http.readAll(); if(buffer.indexOf("ok") == 0) return true; return false; } // Wysyla napisy do bazy napiUploadResult napiUploadSubtitles(const QString & movie_file, const QString & subtitles_file, const QString & language, const QString & nick, const QString & pass, bool correct, const QString & comment, const QString & tmp_path, const QString & p7zip_path) { if(!QFile::exists(movie_file) || !QFile::exists(subtitles_file)) return NAPI_FAIL; MovieInfo movieInfo(movie_file); if(movieInfo.isErr) return NAPI_FAIL; unsigned long movie_size = QFileInfo(movie_file).size(); QString movie_md5 = napiFileMd5Sum(movie_file, NAPI_10MB); QString subtitles_md5 = napiFileMd5Sum(subtitles_file, NAPI_10MB); QString newSubtitlesName = tmp_path + "/" + movie_md5 + ".txt"; if(QFile::exists(newSubtitlesName)) QFile::remove(newSubtitlesName); if(!QFile::copy(subtitles_file, newSubtitlesName)) return NAPI_FAIL; QString zipFileName = QFileInfo(newSubtitlesName).path() + "/" + QFileInfo(newSubtitlesName).completeBaseName() + ".zip"; QStringList args; args << "a" << "-l" << "-y" << zipFileName << ("-p"+napiZipPassword) << newSubtitlesName; QProcess p7zip; p7zip.start(p7zip_path, args); if(!p7zip.waitForFinished()) return NAPI_FAIL; QFile::remove(newSubtitlesName); if(!QFile::exists(zipFileName)) return NAPI_FAIL; // Przygotowujemy dane do zapytania POST MultipartData postData; postData.addBoundary(); postData.addContentDisposition("name=\"kmt\""); postData.addData(comment); postData.addBoundary(); postData.addContentDisposition("name=\"poprawka\""); postData.addData(QString(correct ? "true" : "false")); postData.addBoundary(); postData.addContentDisposition("name=\"v\""); postData.addData(QString("other")); postData.addBoundary(); postData.addContentDisposition("name=\"l\""); postData.addData(language); postData.addBoundary(); postData.addContentDisposition("name=\"t\""); postData.addData(napiFDigest(movie_md5)); postData.addBoundary(); postData.addContentDisposition("name=\"m_filename\""); postData.addData(QFileInfo(movie_file).fileName()); postData.addBoundary(); postData.addContentDisposition("name=\"nick\""); postData.addData(nick); postData.addBoundary(); postData.addContentDisposition("name=\"pass\""); postData.addData(pass); postData.addBoundary(); postData.addContentDisposition("name=\"s_hash\""); postData.addData(subtitles_md5); postData.addBoundary(); postData.addContentDisposition("name=\"MAX_FILE_SIZE\""); postData.addData(QString("512000")); postData.addBoundary(); postData.addContentDisposition("name=\"plik\"; filename=\"" + QFileInfo(zipFileName).fileName() + "\""); postData.addContentType("subtitles/zip"); QFile fZip(zipFileName); if(!fZip.open(QIODevice::ReadOnly)) return NAPI_FAIL; postData.addData(fZip.readAll()); postData.addEndingBoundary(); fZip.close(); QFile::remove(zipFileName); QByteArray data = postData.requestStream(); QString movie_fps = QString::number((int)ceil(movieInfo.fps * 100)); movie_fps.insert(2, ','); QString urlTxt = napiUploadUrlTpl.arg(movieInfo.time).arg(movieInfo.width).arg(movieInfo.height) .arg(movie_fps).arg(movie_md5).arg(movie_size); QUrl url(urlTxt); QHttpRequestHeader header("POST", url.path() + "?" + url.encodedQuery()); header.setValue("Host", url.host()); header.setValue("Accept", "text/html, */*"); header.setValue("Content-Type", "multipart/form-data; boundary=" + postData.boundaryTxt()); header.setValue("Connection", "keep-alive"); header.setValue("User-Agent", QString("QNapi ") + QNAPI_VERSION); SyncHTTP http; http.setHost(url.host()); if(!http.syncRequest(header, data)) return NAPI_FAIL; QString response = http.readAll(); if(response.indexOf("NPc0") == 0) return NAPI_ADDED_NEW; if((response.indexOf("NPc2") == 0) || (response.indexOf("NPc3") == 0)) return NAPI_OK; return NAPI_UNKNOWN; } // Zglasza raport o niepasujacych napisach napiReportResult napiReportBad(const QString & movie_file, const QString & language, const QString & nick, const QString & pass, const QString & comment, QString *response) { QString subtitles_file = QFileInfo(movie_file).path() + "/" + QFileInfo(movie_file).completeBaseName() + ".txt"; if(!QFile::exists(subtitles_file)) return NAPI_NO_SUBTITLES; MultipartData postData; postData.addBoundary(); postData.addContentDisposition("name=\"nick\""); postData.addData(nick); postData.addBoundary(); postData.addContentDisposition("name=\"pass\""); postData.addData(pass); postData.addBoundary(); postData.addContentDisposition("name=\"l\""); postData.addData(language); postData.addBoundary(); postData.addContentDisposition("name=\"md5\""); postData.addData(napiFileMd5Sum(movie_file, NAPI_10MB)); postData.addBoundary(); postData.addContentDisposition("name=\"kmt\""); postData.addData(comment); postData.addEndingBoundary(); QByteArray data = postData.requestStream(); QUrl url(napiReportBadUrlTpl); QHttpRequestHeader header("POST", url.path()); header.setValue("Host", url.host()); header.setValue("Accept", "text/html, */*"); header.setValue("Content-Type", "multipart/form-data; boundary=" + postData.boundaryTxt()); header.setValue("Connection", "keep-alive"); header.setValue("User-Agent", QString("QNapi ") + QNAPI_VERSION); SyncHTTP http; http.setHost(url.host()); if(!http.syncRequest(header, data)) return NAPI_NOT_REPORTED; *response = QTextCodec::codecForName("windows-1250")->toUnicode(http.readAll()); return NAPI_REPORTED; } // Konwertuje napisy z jednego kodowania na inne bool napiConvertFile(const QString & file, const QString & enc_from, const QString & enc_to) { QFile f(file); if(!f.open(QIODevice::ReadOnly)) return false; QByteArray fileContent = f.readAll(); QString contentStr = QTextCodec::codecForName(qPrintable(enc_from))->toUnicode(fileContent); f.close(); if(enc_to.compare("UTF-8", Qt::CaseInsensitive)) { fileContent = QTextCodec::codecForName(qPrintable(enc_to)) ->fromUnicode(contentStr.constData(), contentStr.size()); } if(!f.open(QIODevice::WriteOnly)) return false; f.write(fileContent); f.close(); return true; } // Robi to samo co powyzsza funkcja, z tym ze stara sie automatycznie wykryc kodowanie // zrodlowe konwertowanego pliku bool napiConvertFile(const QString & file, const QString & enc_to) { QString enc_from; QStringList codecs; // Tylko takie kodowania obsługuja polskie litery codecs << "windows-1250" << "windows-1257" << "ISO-8859-2" << "ISO-8859-13" << "ISO-8859-16" << "UTF-8"; QFile f(file); if(!f.open(QIODevice::ReadOnly)) return false; QByteArray testData = f.read(5000); f.close(); foreach(QString codec, codecs) { QTextStream ts(testData); ts.setCodec(qPrintable(codec)); QString encodedData = ts.readAll(); QStringList chars = QString::fromUtf8("ą/ś/ż/ć/ń/ł/ó/ę").split("/"); int i; for (i = 0; i < chars.count(); i++) { if(!encodedData.contains(chars[i], Qt::CaseInsensitive)) break; } if(i == chars.count()) { enc_from = codec; break; } } if(enc_from.isEmpty()) return false; return napiConvertFile(file, enc_from, enc_to); } // Zakladanie kont uzytkownikow na serwerze napi bool napiCreateUser(const QString & nick, const QString & pass, const QString & email, QString * response) { MultipartData postData; postData.addBoundary(); postData.addContentDisposition("name=\"login\""); postData.addData(nick); postData.addBoundary(); postData.addContentDisposition("name=\"haslo\""); postData.addData(pass); postData.addBoundary(); postData.addContentDisposition("name=\"mail\""); postData.addData(email); postData.addBoundary(); postData.addContentDisposition("name=\"z_programu\""); postData.addData(QString("true")); postData.addEndingBoundary(); QByteArray data = postData.requestStream(); QUrl url(napiCreateUserUrlTpl); QHttpRequestHeader header("POST", url.path()); header.setValue("Host", url.host()); header.setValue("Accept", "text/html, */*"); header.setValue("Content-Type", "multipart/form-data; boundary=" + postData.boundaryTxt()); header.setValue("Connection", "keep-alive"); header.setValue("User-Agent", QString("QNapi ") + QNAPI_VERSION); SyncHTTP http; http.setHost(url.host()); if(!http.syncRequest(header, data)) return false; *response = QTextCodec::codecForName("windows-1250")->toUnicode(http.readAll()); return true; } // Sprawdza poprawnosc sciezki do 7zipa (z konfiguracji) bool napiCheck7Zip() { return QFileInfo(GlobalConfig().p7zipPath()).isExecutable(); } // Sprawdza poprawnosc sciezki do katalogu tymczasowego (z konfiguracji) bool napiCheckTmpPath() { QFileInfo f(GlobalConfig().tmpPath()); return f.isDir() && f.isWritable(); } qnapi-0.1.5/src/qnapithread.h0000644000175000017500000000154511014566711015502 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPITHREAD__H__ #define __QNAPITHREAD__H__ #include class QNapiThread : public QThread { Q_OBJECT public: QNapiThread() : abort(false) {} void requestAbort() { abort = true; } protected: bool abort; }; #endif qnapi-0.1.5/src/movieinfo.h0000644000175000017500000000220211000145225015150 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __MOVIEINFO__H__ #define __MOVIEINFO__H__ #include #include #include struct MainAVIHeader { int dwMicroSecPerFrame; int dwMaxBytesPerSec; int dwReserved1; int dwFlags; int dwTotalFrames; int dwInitialFrames; int dwStreams; int dwSuggestedBufferSize; int dwWidth; int dwHeight; int dwReserved[4]; }; const char RIFF_HEADER[4] = {'R','I','F','F'}; class MovieInfo { public: int width, height, time; float fps; bool isErr; MovieInfo(const QString & filename); }; #endif qnapi-0.1.5/src/frmscan.h0000644000175000017500000000564111014564335014634 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __FRMSCAN__H__ #define __FRMSCAN__H__ #include "ui_frmscan.h" #include #include #include #include #include #include "qnapithread.h" #include "qnapiconfig.h" #include "qnapiprojektengine.h" #include "qnapiopendialog.h" #include "frmsummary.h" class ScanFilesThread : public QNapiThread { Q_OBJECT public: void run(); void setSearchPath(const QString & path) { searchPath = path; } void setFilters(const QString & filters) { scanFilters = filters.split(" "); } void setSkipFilters(const QString & filters) { skipFilters = filters.split(" "); } void setSkipIfSubtitlesExists(bool skip) { skipIfSubtitlesExists = skip; } QStringList fileList; signals: void addFile(const QString & fileName); void scanFinished(bool result); void folderChange(const QString & folder); private: bool doScan(const QString & path); QString searchPath; QStringList scanFilters, skipFilters; bool skipIfSubtitlesExists; }; class GetFilesThread : public QNapiThread { Q_OBJECT signals: void fileNameChange(const QString & newfileName); void progressChange(int newValue); void criticalError(const QString & message); private slots: void setCriticalMessage(const QString & msg) { criticalMessage = msg; } public: GetFilesThread() { connect(this, SIGNAL(criticalError(const QString &)), this, SLOT(setCriticalMessage(const QString &))); } void run(); QStringList queue, gotList, failedList; int napiSuccess, napiFail; QString criticalMessage; }; class frmScan: public QDialog { Q_OBJECT public: frmScan(QWidget *parent = 0, Qt::WFlags f = 0); ~frmScan(){}; private: void closeEvent(QCloseEvent *event); Ui::frmScan ui; ScanFilesThread scanThread; GetFilesThread getThread; bool closeRequested; private slots: bool pbCancelClicked(); void selectDirectory(); void leDirectoryTextChanged(); void pbScanClicked(); void addFile(const QString & fileName); void scanFinished(); void enableControlWidgets(bool enable); void enableFilesWidgets(bool enable); void pbAddAllClicked(); void pbAddClicked(); void pbRemoveClicked(); void pbRemoveAllClicked(); void checkPbGetEnabled(); void pbGetClicked(); void fileNameChange(const QString & fileName); void downloadFinished(); }; #endif qnapi-0.1.5/src/qnapiopendialog.h0000644000175000017500000000233411013604343016342 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QNAPIOPENDIALOG__H__ #define __QNAPIOPENDIALOG__H__ #include #include #include #include #include #include #include #include "qnapiconfig.h" class QNapiOpenDialog : public QFileDialog { Q_OBJECT public: enum FilterMode { None, Movies, Subtitles }; QNapiOpenDialog( QWidget * parent = 0, const QString & caption = QString(), const QString & init_path = QString(), FilterMode filterMode = None ); bool selectFile(); bool selectFiles(); bool selectDirectory(); private: bool placeWindow(); }; #endif qnapi-0.1.5/src/qmultiparthttprequest.h0000644000175000017500000000277411005072142017710 0ustar patrykpatryk/***************************************************************************** ** QNapi ** Copyright (C) 2008 Krzemin ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** *****************************************************************************/ #ifndef __QMULTIPARTHTTPREQUEST__H__ #define __QMULTIPARTHTTPREQUEST__H__ #include #include #include class QMultipartHttpRequest { public: void addBoundary(); void addEndingBoundary(); void addContentDisposition(const QString & contentDisposition); void addContentType(const QString & contentType); void addData(const QByteArray & data); void addData(const QString & data); QByteArray & requestStream(); QString & boundaryTxt(); private: struct requestElement { enum elementType { ET_CONTENT_DISPOSITION, ET_CONTENT_TYPE, ET_DATA, ET_BOUNDARY, ET_ENDING_BOUNDARY, }; elementType type; QByteArray elementData; }; void generateBoundary(); void addElement(requestElement::elementType type, const QByteArray & data = ""); QVector elements; QString boundary; QByteArray buffer; }; #endif qnapi-0.1.5/qnapi.pro0000644000175000017500000000636211014600471014066 0ustar patrykpatrykCONFIG += warn_on \ thread \ qt \ resources \ release TEMPLATE = app SOURCES += src/main.cpp \ src/frmprogress.cpp \ src/frmabout.cpp \ src/frmoptions.cpp \ src/frmupload.cpp \ src/frmcorrect.cpp \ src/frmreport.cpp \ src/frmscan.cpp \ src/frmcreateuser.cpp \ src/frmsummary.cpp \ src/qnapiconfig.cpp \ src/qnapiapp.cpp \ src/qdraglistwidget.cpp \ src/movieinfo.cpp \ src/qmultiparthttprequest.cpp \ src/qcumber/qmanagedrequest.cpp \ src/qcumber/qmanagedsocket.cpp \ src/qcumber/qsingleapplication.cpp \ src/qnapiabstractengine.cpp \ src/qnapiprojektengine.cpp \ src/qnapicli.cpp \ src/qnapiopendialog.cpp HEADERS += src/frmprogress.h \ src/frmabout.h \ src/frmoptions.h \ src/frmupload.h \ src/frmcorrect.h \ src/frmreport.h \ src/frmscan.h \ src/frmcreateuser.h \ src/frmsummary.h \ src/version.h \ src/qnapiconfig.h \ src/qnapiapp.h \ src/qdraglistwidget.h \ src/movieinfo.h \ src/qmultiparthttprequest.h \ src/qnapithread.h \ src/synchttp.h \ src/qcumber/qmanagedrequest.h \ src/qcumber/qmanagedsocket.h \ src/qcumber/qsingleapplication.h \ src/qcumber/qcumber.h \ src/qnapiabstractengine.h \ src/qnapiprojektengine.h \ src/qnapicli.h \ src/qnapiopendialog.h FORMS += ui/frmprogress.ui \ ui/frmabout.ui \ ui/frmoptions.ui \ ui/frmupload.ui \ ui/frmcorrect.ui \ ui/frmreport.ui \ ui/frmscan.ui \ ui/frmcreateuser.ui \ ui/frmsummary.ui RESOURCES += res/resources.qrc QT += network gui core UI_DIR = tmp MOC_DIR = tmp RCC_DIR = tmp OBJECTS_DIR = tmp macx { QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.4u.sdk CONFIG += x86 ppc ICON = macx/qnapi.icns QMAKE_INFO_PLIST = macx/Info.plist TARGET = QNapi #7ZIP_BINARY.files = macx/7z macx/7z.so #7ZIP_BINARY.path = Contents/Resources #QMAKE_BUNDLE_DATA += 7ZIP_BINARY } unix { INSTALL_PREFIX = /usr target.path = $${INSTALL_PREFIX}/bin doc.path = $${INSTALL_PREFIX}/share/doc/$${TARGET} doc.files = doc/ChangeLog \ doc/changelog.gz \ doc/README \ doc/README.pl \ doc/LICENSE \ doc/LICENSE.pl \ doc/COPYRIGHT \ doc/qnapi-download.desktop \ doc/qnapi-download.schemas man.path = $${INSTALL_PREFIX}/share/man/man1 man.files = doc/$${TARGET}.1.gz icons.path = /usr/share/icons icons.files = res/qnapi.png res/qnapi-48.png res/qnapi-128.png res/qnapi-512.png desktop.path = /usr/share/applications desktop.files = doc/$${TARGET}.desktop dolphin_integration.path = /usr/share/apps/dolphin/servicemenus dolphin_integration.files = doc/$${TARGET}-download.desktop d3lphin_integration.path = /usr/share/apps/d3lphin/servicemenus d3lphin_integration.files = doc/$${TARGET}-download.desktop konqueror_integration.path = /usr/share/apps/konqueror/servicemenus konqueror_integration.files = doc/$${TARGET}-download.desktop kde4_integration.path = /usr/lib/kde4/share/kde4/services/ServiceMenus kde4_integration.files = doc/$${TARGET}-download.desktop INSTALLS = target \ doc \ man \ icons \ desktop \ dolphin_integration \ d3lphin_integration \ konqueror_integration \ kde4_integration } win32 { RC_FILE = win32/qnapi.rc SOURCES += src/qcumber/qinterprocesschannel_win32.cpp HEADERS += src/qcumber/qinterprocesschannel_win32.h } !win32 { SOURCES += src/qcumber/qinterprocesschannel.cpp HEADERS += src/qcumber/qinterprocesschannel.h } qnapi-0.1.5/doc/0000755000175000017500000000000011015026722012774 5ustar patrykpatrykqnapi-0.1.5/doc/ChangeLog0000644000175000017500000000512411015026716014553 0ustar patrykpatrykQNapi ChangeLog: ================ 2008-05-21 v0.1.5: * uregulowane kwestie licencyjne; od tej chwili program wydawany jest na licencji GNU General Public License w wersji 2. lub pozniejszej (thx Patryk Cisek) * usuniety blad powodujacy niemoznosc uruchomienia programu na terminalu tekstowym (TTY) * poprawione wysylanie napisow do serwera * sprawdzanie uprawnien zapisu do katalogu przy pobieraniu napisow * zunifikowane opcje pozwalajace na wykonywanie przetwarzania pobranych napisow (m.in usuwanie linii zawierajacych podane slowa, zmiana uprawnien do pliku) * bardziej szczegolowe podsumowanie pobierania napisow * mnostwo zmian w kodzie programu umozliwiajacych dalszy, swobodny rozwoj * sporo usprawnien w interfejsie uzytkownika * automatyczna (na razie eksperymentalna) integracja z GNOME (Nautilus) 2008-04-08 v0.1.4: * rejestracja nowych uzytkownikow za pomoca programu * port na systemy Windows * sprawdzanie poprawnosci ustawien p7zip oraz katalogu tymczasowego * bardziej rozbudowane podsumowanie pobierania plikow w niektorych przypadkach * w danej chwili moze byc uruchomiona tylko jedna instancja programu * liczne usprawnienia w interfejsie uzytkownika * pobieranie wielu plikow naraz po przeciagnieciu ich na ikone programu (Mac OS X) * obsluga drag-n-drop na okno pobierania (na razie nie dziala pod Mac OS X) * automatyczna (na razie eksperymentalna) integracja z KDE (Dolphin, Konqueror) * prostsza instalacja/deinstalacja programu przy kompilacji ze zrodel 2008-03-01 v0.1.3: * skanowanie katalogow i dopasowywanie napisow do znalezionych filmow * rozwiazanie problemu z pozycja okienek dialogowych pod compizem * odswiezona ikona programu * balonikowe notyfikacje w tray-u * pokazywanie okna do otwierania plikow z filmami przy kliknieciu LPM na ikone w tray-u * ulepszenie automatycznej detekcji programu 7z * obsluga przeciagania plikow na ikone w doku pod Mac OS X * konfigurowalny wybor stylu BrushedMetal na Mac OS X * inne usprawnienia i poprawki znalezionych bledow 2008-02-19 v0.1.2: * liczne usprawnienia w interfejsie uzytkownika * poprawiony blad podczas wysylania raportu o bledzie (thx badenov) * dodano mozliwosc automatyczej detekcji kodowania znakow z pliku * ulepszenia w obsludze protokolu NAPI * uzycie stylu BrushedMetal pod Mac OS X (thx adrian5632) * sporo innych, mniejszych poprawek 2008-02-16 v0.1.1: * lepsza integracja z Mac OS X * w oknie do wysylania poprawek mozna wybrac jezyk napisow * obsluga zmiany kodowania pobranych napisow * integracja z Nautilusem * zmiany kosmetyczne 2008-02-14 v0.1: * pierwsza udostepniona wersja programu qnapi-0.1.5/doc/qnapi.desktop0000644000175000017500000000036611001413614015477 0ustar patrykpatryk[Desktop Entry] Exec=qnapi Name=QNapi Icon=/usr/share/icons/qnapi-48.png Type=Application Categories=AudioVideo Comment=Program do pobierania napisów do filmów GenericName=Program do pobierania napisów do filmów Encoding=UTF-8 Terminal=false qnapi-0.1.5/doc/qnapi-download.desktop0000644000175000017500000000105210776467076017332 0ustar patrykpatryk[Desktop Entry] Version=1.0 Encoding=UTF-8 Actions=QNapiDownload; Name=Pobierz napisy do filmu z QNapi GenericName=Pobierz napisy do filmu z QNapi Icon=/usr/share/icons/qnapi-48.png ServiceTypes=video/x-msvideo,video/x-ms-asf,video/mpeg,video/x-ms-wmv,video/mp4,video/quicktime,video/x-theora,video/x-matroska,video/3gpp,application/vnd.rn-realmedia,application/vnd.rn-realmedia-vbr X-KDE-ServiceTypes=KonqPopupMenu/Plugin Type=Service [Desktop Action QNapiDownload] Name=Pobierz napisy do filmu z QNapi Exec=qnapi %F Icon=/usr/share/icons/qnapi-48.png qnapi-0.1.5/doc/qnapi.1.gz0000644000175000017500000000100311015026754014604 0ustar patrykpatryk32HmRMo0 W=t9 0M4H&A5=Ȳ˖MEaX~M1 nz s!8 @<C1°B2%6`!b%L8ϛt]r^cy*Uɲb̰yspXv86Cq<ʴf9a2,JTش!40Q<ץZSXFmzqz@o`=!εD_BlZ)i%zǞa^2c6j̘b&ES'u"wjWܡr^Ncm SRF`ieu~Czuw>-5oXlLHEY\Z O%{\PaJaJhX4%iiEگa5}P@^_7b! R"nErbO֝*6\ќ_j IUp)>~U9tO'''חW7+|yquqs{B(z ' Ʉjle\5XSovTmm,u7^2'Dzg񪡇+ Dt}AM\SY W/z?S|!D?кQS@E4 5j˭5Ϊ=(z[TTOw^%(< ah2"i`<*9Dg<8r6ZMy@EqNrdhijʑf7r >)/w*Ɉ|C ?cDcna;r[})Vᚹ [BZy\eaBb}]jYW cv\e@xnl{LZ5!YB,n=DAG8DC(*ܪ~2:ſWr1Z㠉Sg%T;Ex #61/J[x#|GQZfzuSxjyb]j{Q*ێEvꇶ DC#:KH I:Cҵ>GCwC)Can(NU3p̺Ug sTqqe'*t-'q cީ>N:4qH{YI ׎>A&Oddoat[=Y$!O 66󇹪2Ajn;+/ІgmS.85MO݉qqk(1Ҋmӎm,]hO5t55i;0Mi6m@șy$kĕLB%#0lXMS<nJr9ЪUvwScc:lIA>(*/u<ݣDY 4S@#Eǰ5@)ɳ iiTX6;zuoisXm\-PZis]4N{3K[T4YvБHsqc5~-I@ K%FJ{쥛ϯA9vW1Y80ԗ#W#MwR$ I+Ҍ8ZYÂglCКr^rJ1z*I9!T+4[t4T qnapi-0.1.5/doc/qnapi-download.schemas0000644000175000017500000002327610757772770017317 0ustar patrykpatryk /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/label /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/label nautilus-actions string Pobierz napisy do filmu z QNapi The label of the menu item The label of the menu item that will appear in the Nautilus popup menu when the selection matches the appearance condition settings /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/tooltip /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/tooltip nautilus-actions string Pobiera i dopasowuje napisy do filmu z bazy NAPI-PROJEKT The tooltip of the menu item The tooltip of the menu item that will appear in the Nautilus statusbar when the user points to the Nautilus popup menu item with his/her mouse /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/icon /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/icon nautilus-actions string The icon of the menu item The icon of the menu item that will appear next to the label in the Nautilus popup menu when the selection matches the appearance conditions settings /usr/share/icons/qnapi.png /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/path /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/path nautilus-actions string The path of the command The path of the command to start when the user select the menu item in the Nautilus popup menu qnapi /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/parameters /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/parameters nautilus-actions string The parameters of the command The parameters of the command to start when the user selects the menu item in the Nautilus popup menu. The parameters can contain some special tokens which are replaced by Nautilus information before starting the command: %d: base folder of the selected file(s) %f: the name of the selected file or the first one if many are selected %m: space-separated list of the basenames of the selected file(s)/folder(s) %M: space-separated list of the selected file(s)/folder(s), with their full paths %u: GnomeVFS URI %s: scheme of the GnomeVFS URI %h: hostname of the GnomeVFS URI %U: username of the :%s/GnomeVFS URI %%: a percent sign %M /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/basenames /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/basenames nautilus-actions list string The list of pattern to match the selected file(s)/folder(s) A list of strings with joker '*' or '?' to match the name of the selected file(s)/folder(s). Each selected items must match at least one of the filename patterns for the action to appear [*.avi,*.asf,*.divx,*.dat,*.mkv,*.mov,*.mp4,*.mpeg,*.mpg,*.ogm,*.rm,*.rmvb,*.wmv] /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/matchcase /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/matchcase nautilus-actions bool 'true' if the filename patterns have to be case sensitive, 'false' otherwise If you need to match a filename in a case-sensitive manner, set this key to 'true'. If you also want, for example '*.jpg' to match 'photo.JPG', set 'false' false /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/mimetypes /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/mimetypes nautilus-actions list string The list of patterns to match the mimetypes of the selected file(s) A list of strings with joker '*' or '?' to match the mimetypes of the selected file(s). Each selected items must match at least one of the mimetype patterns for the action to appear [video/x-msvideo,video/x-ms-asf,video/mpeg,video/x-ms-wmv,video/mp4,video/quicktime,video/x-theora,video/x-matroska,video/3gpp,application/vnd.rn-realmedia,application/vnd.rn-realmedia-vbr] /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/isfile /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/isfile nautilus-actions bool 'true' if the selection can have files, 'false' otherwise This setting is tied in with the 'isdir' setting. The valid combinations are: isfile=TRUE and isdir=FALSE: the selection may hold only files isfile=FALSE and isdir=TRUE: the selection may hold only folders isfile=TRUE and isdir=TRUE': the selection may hold both files and folders isfile=FALSE and isdir=FALSE: this is an invalid combination (your configuration will never appear) true /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/isdir /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/isdir nautilus-actions bool 'true' if the selection can have folders, 'false' otherwise This setting is tied in with the 'isfile' setting. The valid combinations are: isfile=TRUE and isdir=FALSE: the selection may hold only files isfile=FALSE and isdir=TRUE: the selection may hold only folders isfile=TRUE and isdir=TRUE': the selection may hold both files and folders isfile=FALSE and isdir=FALSE: this is an invalid combination (your configuration will never appear) false /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/accept-multiple-files /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/accept-multiple-files nautilus-actions bool 'true' if the selection can have several items, 'false' otherwise If you need one or more files or folders to be selected, set this key to 'true'. If you want just one file or folder, set 'false' true /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/schemes /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/schemes nautilus-actions list string The list of GnomeVFS schemes where the selected files should be located Defines the list of valid GnomeVFS schemes to be matched against the selected items. The GnomeVFS scheme is the protocol used to access the files. The keyword to use is the one used in the GnomeVFS URI. Examples of GnomeVFS URI include: file:///tmp/foo.txt sftp:///root@test.example.net/tmp/foo.txt The most common schemes are: 'file': local files 'sftp': files accessed via SSH 'ftp': files accessed via FTP 'smb': files accessed via Samba (Windows share) 'dav': files accessed via WebDav All GnomeVFS schemes used by Nautilus can be used here. [file] /schemas/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/version /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/version nautilus-actions string The version of the configuration format The version of the configuration format that will be used to manage backward compatibility 1.1 qnapi-0.1.5/doc/LICENSE0000644000175000017500000004310311000145037013775 0ustar patrykpatryk GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. qnapi-0.1.5/doc/qnapi.10000644000175000017500000000147711014535463014205 0ustar patrykpatryk.TH "qnapi" 1 .SH NAZWA qnapi \- program do pobierania napisow z bazy NAPI-PROJEKT. .SH SKLADNIA \fBqnapi\fP [opcje] [lista plikow] .SH OPIS \fBqnapi\fP potrafi pracowac w dwoch trybach: GUI oraz konsolowym. Podanie listy plikow (filmowych) zmusi program do pobrania napisow dla zadanych filmow. .SH OPCJE -c, --console pobieranie napisow z konsoli -q, --quiet pobiera napisy nie wypisujac zadnych komunikatow ani nie pokazujac zadnych okien -h, --help pokazuje pomoc programu .SH AUTOR Copyright (C) 2008 Krzemin .SH LICENCJA Program QNapi rozprowadzany jest na licencji GNU General Public License w wersji 2. lub kazdej pozniejszej. .SH BLEDY Wszelkie zauwazone bledy w programie mozna zglaszac w trackerze na sourceforge.net: http://sourceforge.net/projects/qnapi qnapi-0.1.5/doc/LICENSE.pl0000644000175000017500000006165311014252326014426 0ustar patrykpatryk Powszechna Licencja Publiczna GNU Tłumaczenie [1]GNU General Public License Uwaga! To jest nieoficjalne tłumaczenie Powszechnej Licencji Publicznej GNU na język polski. Nie zostało opublikowane przez Free Software Foundation i pod względem prawnym nie stanowi warunków rozpowszechniania oprogramowania stosującego GNU GPL -- ustanawia je wyłącznie [2]oryginalny angielski tekst licencji GNU GPL. Jednak mamy nadzieję, że pomoże ono lepiej zrozumieć Licencję osobom mówiącym po polsku. Note! This is an unofficial translation of the GNU General Public License into Polish. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU GPL--only the [3]original English text of the GNU GPL does that. However, we hope that this translation will help Polish speakers understand the GNU GPL better. Powszechna Licencja Publiczna GNU Wersja 2, czerwiec 1991 Copyright (c) 1989, 1991 Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Zezwala się na kopiowanie i rozpowszechnianie wiernych kopii niniejszego dokumentu licencyjnego, jednak bez prawa wprowadzania zmian. Preambuła Większość licencji na oprogramowanie pomyślana jest po to, aby odebrać użytkownikowi możliwość swobodnego udostępniania innym i zmieniania danego software'u. Natomiast w wypadku Powszechnej Licencji Publicznej GNU (GNU General Public License, GPL) celem jest zagwarantowanie użytkownikowi swobody udostępniania i zmieniania tego wolnego oprogramowania, a więc danie pewności, iż oprogramowanie jest wolno dostępne dla wszystkich użytkowników. Niniejsza Powszechna Licencja Publiczna dotyczy większości oprogramowania wydawanego przez Fundację Wolnego Oprogramowania (Free Software Foundation) oraz wszelkich innych programów, których autorzy zobowiązują się do jej stosowania. (Niektóre rodzaje oprogramowania wydawanego przez Fundację objęte są Powszechną Licencją Publiczną GNU dla Bibliotek, GNU Library General Public License). Użytkownik może stosować ją również do swoich programów. Mówiąc o wolnym oprogramowaniu mamy na myśli swobodę, a nie cenę. Nasze Powszechne Licencje Publiczne wprowadzono po to, aby zapewnić Państwu swobodę rozpowszechniania kopii tego oprogramowania (i - jeśli ktoś chce - pobierania za tę usługę opłaty), jak również aby udostępnić kod źródłowy oraz umożliwić dokonywanie zmian tego oprogramowania lub wykorzystywania jego fragmentów w nowych, wolnych programach. Nie bez znaczenia jest też sama możliwość dotarcia do Państwa z informacją o wszystkich tych udogodnieniach. W celu ochrony praw użytkownika jesteśmy zmuszeni wprowadzać ograniczenia zabraniające komukolwiek kwestionowanie jego praw albo sugerowanie rezygnacji z tych praw. Ograniczenia te sprowadzają się do pewnych dla Państwa obowiązków w przypadku rozpowszechniania przez Was kopii naszego oprogramowania bądź dokonywania w nim zmian. Na przykład, jeśli rozprowadzacie Państwo kopie takiego programu, niezależnie czy gratisowo, czy za opłatą, musicie Państwo odbiorcy udzielić wszelkich tych praw, jakie mieliście sami. Musicie zapewnić mu również otrzymanie kodu źródłowego (lub możliwość otrzymania) oraz przedstawić niniejsze Warunki, aby mógł on poznać swoje prawa. Ochrona Państwa praw przebiega w dwóch etapach: 1. zastrzegamy prawo własności autorskiej do oprogramowania, 2. oferujemy Państwu niniejszą licencję, która daje Wam sankcjonowane prawem zezwolenie na kopiowanie, rozpowszechnianie i/lub modyfikowanie tego oprogramowania. Ponadto dla ochrony tak autora, jak i naszej, pragniemy mieć pewność, że każdy zrozumie, iż na niniejsze wolne oprogramowanie nie udziela się gwarancji. W razie dokonania w nim przez kogoś modyfikacji i puszczenia dalej do obrotu, pragniemy, aby dalsi odbiorcy zdawali sobie sprawę z tego, że problemy wprowadzone przez inne osoby nie są wyrazem oryginalnych działań twórców. I rzecz ostatnia: każdemu wolnemu programowi stale zagrażają patenty na oprogramowanie. Naszym pragnieniem jest unikanie takiego niebezpieczeństwa, kiedy redystrybutorzy wolnego programu indywidualnie uzyskują prawa patentowe, nadając tym samym programowi charakter prawnie zastrzeżony. W celu zapobieżenia takim zjawiskom jednoznacznie wyjaśniliśmy, że każdy patent musi być wydawany albo dla swobodnego użytku przez wszystkich, albo nie wydawany wcale. Poniżej podajemy dokładne zasady i warunki kopiowania, rozpowszechniania i modyfikowania. Zasady i warunki kopiowania, rozpowszechniania i modyfikowania 0. Niniejsza Licencja dotyczy programów i innych prac, na których umieszczona jest pochodząca od właściciela praw autorskich informacja, że dany program lub praca może być rozpowszechniana na warunkach niniejszej Powszechnej Licencji Publicznej. Używane poniżej słowo "Program" oznacza właśnie takie programy lub prace, zaś określenie "praca oparta na Programie" dotyczy albo Programu, albo pochodzącej od niego pracy w rozumieniu prawa autorskiego, to jest pracy zawierającej Program lub jego część dosłowną, bądź zmodyfikowaną i/lub przełożoną na inny język. (W dalszym ciągu niniejszego, pojęcie przekładu włącza się bez ograniczeń do terminu "modyfikacja"). Do każdego licencjobiorcy będziemy zwracać się "per Ty". Niniejsza Licencja nie obejmuje działań innych niż kopiowanie, rozprowadzanie i modyfikowanie - nie mieszczą się one w jej zakresie. Czynność używania Programu nie jest poddana ograniczeniom, a produkty uzyskane z Programu objęte są Licencją tylko wtedy, gdy ich treść stanowi pracę opartą na Programie (niezależnie od stworzenia jej przy użyciu Programu). To, czy fakt taki jest prawdą, zależy od tego, co dany Program wykonuje. 1. Możesz kopiować i rozprowadzać w dowolnych mediach wierne kopie kodu źródłowego Programu w otrzymanej formie pod warunkiem, że w widoczny sposób i odpowiednio podasz na każdej kopii właściwą informację o prawie autorskim i zrzeczenie się uprawnień z tytułu gwarancji; wszelkie napisy informacyjne na temat Licencji i faktu nieudzielania gwarancji musisz chronić przed uszkodzeniem, zaś wszystkim innym odbiorcom Programu musisz wraz z Programem wręczać egzemplarz niniejszej Licencji. Możesz pobierać opłatę za fizyczną czynność przekazania kopii i według własnej decyzji możesz za opłatą proponować ochronę gwarancyjną. 2. Możesz modyfikować swoją kopię czy kopie Programu oraz dowolne jego części, tworząc przez to pracę opartą na Programie, jak również kopiować i rozprowadzać takie modyfikacje i pracę na warunkach podanych w pkt.1 powyżej - pod warunkiem przestrzegania całości poniższych wymogów: a. Musisz spowodować umieszczenie na zmodyfikowanych plikach widocznej informacji o tym, że dane pliki zostały przez ciebie zmienione, wraz z datą dokonania zmian. b. Musisz doprowadzić do tego, aby każda rozpowszechniana lub publikowana przez ciebie praca, która w całości lub części zawiera Program, albo pochodzi od niego lub jego części, była w całości i bezpłatnie licencjonowana dla wszelkich stron trzecich na warunkach niniejszej Licencji. c. Jeżeli zmodyfikowany program podczas korzystania z niego w normalnym trybie odczytuje polecenia interaktywnie, musisz spowodować, aby po uruchomieniu (użyty w interaktywny sposób w najzwyklejszym trybie), wydrukowywał on lub wyświetlał powiadomienie o odnośnym prawie autorskim i braku gwarancji (ewentualnie o zapewnianiu gwarancji przez ciebie), oraz o tym, że użytkownicy mogą redystrybuować ten program na niniejszych warunkach wraz z informacją, jak użytkownik może zapoznać się z treścią niniejszej Licencji. (Wyjątek: jeśli sam Program jest interaktywny, ale normalnie nie drukuje takiego powiadomienia, twoja praca oparta na nim też nie musi wydrukowywać takiego powiadomienia). Niniejsze wymogi odnoszą się do zmodyfikowanej pracy jako całości. Jeśli dające się ustalić sekcje danej pracy nie pochodzą od Programu i mogą być racjonalnie uważane za samodzielne i odrębne same w sobie, to niniejsza Licencja i jej warunki nie mają zastosowania do takich sekcji przy rozprowadzaniu ich przez ciebie jako odrębne prace. Jeśli jednak rozprowadzasz je jako część całości, będącej pracą opartą na Programie, rozpowszechnianie tej całości musi być dokonywane na warunkach niniejszej Licencji, której zezwolenia dla innych licencjobiorców rozciągają się w całej szerokości na tę całość, a tym samym i na każdą indywidualną jej część, niezależnie od jej autorstwa. Dlatego też intencją tego fragmentu nie jest roszczenie sobie praw albo podważanie twych praw do pracy napisanej w całości przez ciebie. Chodzi nam raczej o korzystanie z prawa kontrolowania dystrybucji pochodnych i zbiorowych prac opartych na Programie. I jeszcze jedno: samo tylko połączenie z Programem (lub z pracą opartą na Programie) innej pracy - nie opartej na Programie, w ramach wolumenu nośnika przechowywania lub dystrybucji, nie powoduje objęcia takiej pracy zakresem niniejszej Licencji. 3. Możesz kopiować i rozprowadzać Program (lub opartą na nim pracę - zgodnie z pkt.2 w kodzie wynikowym lub w formie wykonywalnej w myśl postanowień pkt.1 i 2 powyżej, pod warunkiem zrealizowania również poniższych wymogów: a. Musisz dołączyć do niego odpowiadający mu, kompletny i możliwy do odczytania przez urządzenia cyfrowe kod źródłowy, który musi być rozpowszechniany na warunkach pkt.1 i 2 powyżej i na nośniku zwyczajowo używanym dla wzajemnej wymiany oprogramowania; lub b. dołączyć do niego pisemną ofertę, ważną co najmniej 3 lata, przyznającą każdej stronie trzeciej - za opłatą nie przekraczającą twego kosztu fizycznego wykonywania dystrybucji źródła - kompletną, odczytywalną przez urządzenia cyfrowe kopię odpowiadającego mu kodu źródłowego, rozprowadzaną na warunkach pkt.1 i 2 powyżej, na nośniku zwyczajowo używanym do wzajemnej wymiany oprogramowania; lub c. dołączyć do niego informację, jaką otrzymałeś na temat oferty rozprowadzania odpowiedniego kodu źródłowego. (Ta możliwość dozwolona jest tylko dla dystrybucji niehandlowej i jedynie wtedy, gdy otrzymałeś dany program w kodzie wynikowym lub formie wykonywalnej wraz z wymienioną ofertą - zgodnie z podpunktem "b" powyżej). Określenie kod źródłowy dla pracy oznacza formę pracy preferowaną dla wprowadzania do niej modyfikacji. Dla wykonanej pracy, kompletny kod źródłowy oznacza cały kod źródłowy wszystkich modułów, wszelkie sprzężone z nią pośredniczące pliki opisujące oraz zbiory komend stosowane do sterowania kompilacją i instalowaniem programów. Niemniej jednak, jako wyjątek specjalny, dystrybuowany (w formie źródłowej albo binarnej) kod źródłowy nie musi obejmować niczego, co jest normalnie rozprowadzane przy pomocy głównych komponentów (kompilator, jądro itd.) systemu operacyjnego, na którym pracuje część wykonywalna, o ile sam taki komponent towarzyszy tej części. Jeśli dystrybucja części wykonywalnej albo kodu wynikowego realizowana jest poprzez oferowanie dostępu do kopii z wyznaczonego miejsca, to oferowanie równoważnego dostępu dla kopiowania kodu źródłowego z tego samego miejsca liczy się jako rozpowszechnianie kodu źródłowego, nawet gdy strony trzecie nie są zmuszone do kopiowania źródła wraz z kodem wynikowym. 4. Poza przypadkami jednoznacznie dozwolonymi w niniejszej Licencji, nie możesz kopiować, modyfikować, sublicencjonować ani rozpowszechniać Programu. We wszystkich pozostałych wypadkach, każda próba skopiowania, sublicencjonowania lub rozpowszechnienia Programu jest nieważna i powoduje automatyczne wygaśnięcie twoich praw z tytułu Licencji. Niemniej jednak, stronom, które już otrzymały od ciebie kopie albo prawa w ramach niniejszej Licencji, licencje nie wygasają tak długo, jak długo strony te w pełni stosują się do nich. 5. Nie musisz akceptować niniejszej Licencji, jeżeli jej nie podpisałeś. Niemniej jednak, nic innego nie zapewni ci zezwolenia na modyfikowanie lub rozprowadzanie Programu i pochodzących od niego prac. Działania takie są prawnie zabronione, jeżeli nie przyjmujesz niniejszej Licencji. Dlatego też, poprzez modyfikowanie bądź rozpowszechnianie Programu (lub pracy na nim opartej) dajesz wyraz swojej akceptacji dla Licencji i wszelkich jej postanowień i warunków dotyczących kopiowania, rozprowadzania i modyfikowania Programu lub opartych na nim prac. 6. W każdym przypadku redystrybucji przez ciebie Programu (albo opartej na nim pracy), odbiorca automatycznie otrzymuje od pierwotnego licencjodawcy licencję na kopiowanie, rozpowszechnianie i modyfikowanie Programu na niniejszych zasadach i warunkach. Na korzystanie przez odbiorcę z udzielonych w niniejszej Licencji praw nie możesz narzucać już dalszych ograniczeń. Nie jesteś stroną odpowiedzialną za kontrolę przestrzegania Licencji przez osoby trzecie. 7. Jeśli na skutek wyroku sądowego lub zarzutu naruszenia patentu, jak też z każdej innej przyczyny (nie ograniczonej do kwestii patentowych) zostaną narzucone na ciebie (niezależnie czy to mocą wyroku sądowego, umowy, czy w inny sposób) warunki sprzeczne z warunkami niniejszej Licencji, to nie zwalniają one ciebie z warunków Licencji. Jeśli nie możesz prowadzić dystrybucji tak, aby wypełniać jednocześnie swoje obowiązki z tytułu niniejszej Licencji i inne odnośne obowiązki, to w rezultacie nie możesz wcale rozprowadzać Programu. Na przykład, gdyby licencja patentowa nie zezwalała na wolną od opłat licencyjnych redystrybucję Programu przez wszystkie osoby, które otrzymały kopie bezpośrednio lub pośrednio od ciebie, to jedynym sposobem pozwalającym ci na przestrzeganie i licencji patentowej, i Licencji niniejszej, byłoby całkowite powstrzymanie się od jakiejkolwiek dystrybucji Programu. Jeżeli w jakichś szczególnych okolicznościach któryś fragment niniejszego punktu stałby się nieważny lub niewykonywalny, to intencją jest, aby znajdowała zastosowanie pozostała część punktu, a treść całego punktu była stosowana w pozostałych okolicznościach. Celem niniejszego punktu nie jest zachęcanie do naruszania patentów czy innych praw własności, albo też do podważania ich ważności; niniejszy punkt za swój jedyny cel ma ochronę integralności systemu rozpowszechniania wolnego oprogramowania, realizowanego za pomocą publicznych licencji. Wielu ludzi bezinteresownie wniosło swój wkład do stworzenia szerokiego zakresu oprogramowania upowszechnianego w tym systemie, mając zaufanie do konsekwentnego jego stosowania; wyłącznie do autora/ofiarodawcy należy decyzja, czy życzy on sobie rozprowadzania oprogramowania za pośrednictwem innego systemu i licencjobiorca nie może tego prawa wyboru ograniczać. Intencją niniejszego punktu jest jasne i wyraźne przedstawienie tego, co uważa się za skutki, jakie rodzi pozostała część niniejszej Licencji. 8. W przypadku, gdy dystrybucja i/lub używanie Programu w niektórych krajach poddane jest ograniczeniom patentowym lub zastrzeżeniom prawami autorskimi, początkowy posiadacz praw autorskich, który poddaje Program pod oddziaływanie niniejszej Licencji, może dodać wyraźnie zakreślone geograficzne ograniczenie rozpowszechniania wyłączające te kraje, dzięki czemu dystrybucja dozwolona będzie wyłącznie w krajach czy wśród krajów nie objętych takim wyłączeniem. W przypadku takim, niniejsza Licencja obejmuje dane ograniczenie tak, jakby było ono wpisane w jej treść. 9. W miarę potrzeby Fundacja Wolnego Oprogramowania może publikować poprawione i/lub nowe wersje Powszechnej Licencji Publicznej. Takie nowe wersje będą napisane w duchu podobnym do obecnej wersji, ale mogą różnić się w szczegółach poruszających nowe problemy czy zagadnienia. Każdej wersji nadaje się wyróżniający ją numer. Jeżeli Program podaje numer wersji niniejszej Licencji, odnoszący się do tej wersji i "wszelkich wersji następnych", masz do wyboru albo stosować się do postanowień i warunków tej wersji, albo którejkolwiek wersji późniejszej wydanej przez Fundację Wolnego Oprogramowania. O ile Program nie podaje numeru wersji niniejszej Licencji, możesz wybrać dowolną wersję kiedykolwiek opublikowaną przez Fundację. 10. Jeśli chcesz włączyć części Programu do innych wolnych programów, których warunki rozpowszechniania są inne, zwróć się pisemnie do autora z prośbą o pozwolenie. W przypadku oprogramowania objętego przez Fundację prawem autorskim, napisz do Fundacji; czasami czynimy od tego odstępstwa. W naszej decyzji kierujemy się dwoma celami: utrzymania wolnego statusu wszystkich pochodnych naszego wolnego oprogramowania oraz - generalnie - promowania współudziału i wielokrotnego stosowania oprogramowania. WYRÓB BEZ GWARANCJI 11. PONIEWAŻ PROGRAM JEST LICENCJONOWANY BEZPŁATNIE, NIE JEST OBJĘTY GWARANCJĄ W ZAKRESIE DOZWOLONYM PRZEZ OBOWIĄZUJĄCE PRZEPISY. O ILE NA PIŚMIE NIE STANOWI SIĘ INACZEJ, POSIADACZE PRAW AUTORSKICH I/LUB INNE STRONY ZAPEWNIAJĄ PROGRAM W STANIE, W JAKIM JEST ("JAK WIDAĆ") BEZ JAKIEJKOLWIEK GWARANCJI, ANI WYRAŹNEJ, ANI DOMYŚLNEJ, W TYM MIĘDZY INNYMI DOMYŚLNYCH GWARANCJI CO DO PRZYDATNOŚCI HANDLOWEJ I PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. CAŁOŚĆ RYZYKA W ZAKRESIE JAKOŚCI I SKUTECZNOŚCI DZIAŁANIA PROGRAMU PONOSISZ SAM. W RAZIE GDYBY PROGRAM OKAZAŁ SIĘ WADLIWY, PONOSISZ KOSZT CAŁEGO NIEZBĘDNEGO SERWISU, NAPRAWY I KORYGOWANIA. 12. O ILE OBOWIĄZUJĄCE PRAWO NIE STANOWI INACZEJ ALBO CZEGOŚ INNEGO NIE UZGODNIONO W FORMIE PISEMNEJ, ŻADEN POSIADACZ PRAW AUTORSKICH ANI INNA STRONA MODYFIKUJĄCA I/LUB REDYSTRYBUJĄCA PROGRAM ZGODNIE Z POWYŻSZYMI ZEZWOLENIAMI, W ŻADNYM WYPADKU NIE JEST ODPOWIEDZIALNA WOBEC CIEBIE ZA SZKODY, W TYM SZKODY OGÓLNE, SPECJALNE, UBOCZNE LUB SKUTKOWE, WYNIKŁE Z UŻYCIA BĄDŹ NIEMOŻLIWOŚCI UŻYCIA PROGRAMU (W TYM, MIĘDZY INNYMI, ZA UTRATĘ DANYCH LUB POWSTANIE DANYCH NIEDOKŁADNYCH, ALBO ZA STRATY PONIESIONE PRZEZ CIEBIE LUB STRONY TRZECIE, JAK TEŻ NIEDZIAŁANIE PROGRAMU Z INNYMI PROGRAMAMI), NAWET JEŚLI DANY POSIADACZ BĄDŹ INNA STRONA ZOSTALI POWIADOMIENI O MOŻLIWOŚCI POWSTANIA TAKICH SZKÓD. KONIEC ZASAD I WARUNKÓW Jak stosować niniejsze Warunki do Twoich nowych programów Jeśli opracowujesz nowy program i chciałbyś, aby stał się on przydatny dla szerokiego ogółu, najlepszą drogą do osiągnięcia tego będzie nadanie twemu programowi charakteru wolnego oprogramowania, które każdy może redystrybuować i zmieniać na niniejszych warunkach. W tym celu do programu dołącz poniższe informacje. Bezpieczniej jest dołączyć je na początku każdego pliku źródłowego, dzięki czemu najskuteczniej można przekazać fakt nieistnienia gwarancji; każdy plik powinien przy tym nosić uwagę "copyright" i odnośnik, gdzie można znaleźć pełną informację. nazwa programu i informacja, do czego on służy. Copyright (C) 19../20.. nazwisko autora Niniejszy program jest wolnym oprogramowaniem; możesz go rozprowadzać dalej i/lub modyfikować na warunkach Powszechnej Licencji Publicznej GNU, wydanej przez Fundację Wolnego Oprogramowania - według wersji 2-giej tej Licencji lub którejś z późniejszych wersji. Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. W celu uzyskania bliższych informacji - Powszechna Licencja Publiczna GNU. Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz Powszechnej Licencji Publicznej GNU (GNU General Public License); jeśli nie - napisz do Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Podaj też informacje o sposobie kontaktowania się z tobą pocztą elektroniczną lub zwykłą. Jeśli dany program jest interaktywny, spraw, aby w momencie wchodzenia w tryb interaktywny wyświetlał on komunikat jak w poniższym przykładzie: Gnomovision wersja 69, Copyright C 19.. nazwisko autora Gnomovision wydawany jest ABSOLUTNIE BEZ ŻADNEJ GWARANCJI - w celu uzyskania dalszych szczegółów wpisz "show w". To jest wolne oprogramowanie i mile widziane jest dalsze rozpowszechnianie go przez ciebie na określonych warunkach - w celu uzyskania bliższych szczegółów wpisz "show c". Powyższe hipotetyczne polecenia "show w" i "show c" winny powodować wyświetlenie odpowiednich części Powszechnej Licencji Publicznej. Oczywiście możesz używać innych poleceń niż "show w" i "show c"; mogą to być nawet kliknięcia myszą lub pozycje menu - co tylko sobie uznasz za stosowne. Powinieneś też poprosić swego pracodawcę (jeśli pracujesz jako programista) czy też swoją szkołę (jeśli jesteś uczniem), o podpisanie, w razie potrzeby, "Rezygnacji z praw autorskich" do programu. Poniżej podajemy przykład (zmień nazwy/nazwiska): My, firma Jojodyne Sp. z o.o. niniejszym zrzekamy się i rezygnujemy z wszelkich interesów prawnych w zakresie praw autorskich do programu "Gnomovision" (który realizuje następujące funkcje...), napisanego przez p.Jana Kowalskiego. Podpis: /-/ Gniewosław Wielkoważny Gniewosław Wielkoważny, Prezes...itp Powszechna Licencja Publiczna nie zezwala na włączanie twego programu do programów prawnie zastrzeżonych. Jeśli twój program jest biblioteką podprogramów, możesz rozważyć, czy nie będzie korzystniej zezwolić na powiązanie prawnie zastrzeżonych aplikacji z biblioteką. Jeśli chciałbyś właśnie tego dokonać, zamiast niniejszej Licencji zastosuj Powszechną Licencję Publiczną GNU dla Bibliotek. _________________________________________________________________ References 1. http://www.fsf.org/copyleft/gpl.html 2. http://www.fsf.org/copyleft/gpl.html 3. http://www.fsf.org/copyleft/gpl.html qnapi-0.1.5/doc/README0000644000175000017500000001107611014536365013671 0ustar patrykpatrykQNapi ===== Author: Krzemin WWW home page: http://krzemin.iglu.cz/qnapi This program is distributed under the terms of GNU General Pulic License; either version 2 or (at your opinion) any later version. QNapi is unofficial clone of NAPI-PROJEKT program (http://napiprojekt.pl) written using Qt4. It's focused to be functional on GNU/Linux and other Unix-like systems, for which NAPI-PROJEKT is not available. Since 0.1.4 version it has also Windows port. For more information visit project's website. Requirements ============ * Qt version 4.3.0, or higher. * p7zip. More info about this program can be found here: http://p7zip.sourceforge.net/ Installation =========== First check if there's a package of QNapi for your distribution: http://krzemin.iglu.cz/qnapi If there's no package for your distro, you'll have to compile QNapi from source. To do this you'll need Qt4 libraries and 7z, which you can find in p7zip-full (see http://p7zip.sourceforge.net/ for more details). First off, fetch and unpack the tarball: $ tar -zxvf qnapi-XXX.tar.gz where XXX is a version of QNapi. Then enter the directory and build makefiles: $ cd qnapi-XXX $ qmake If you also have Qt3 installed, please type qmake-qt4 instead of qmake (which may be a symlink to qmake-qt3). Now build the program: $ make If compilation fails, go to "Compilation Errors" section to look for possible reasons and solutions. If everything went fine, install QNapi: $ sudo make install Now you can run the program with the following command: $ qnapi If you will later want to uninstall QNapi, type the following command from QNapi's source directory: $ sudo make uninstall Compilation Errors ================== If make command throws an error similar to the following: "make: *** No rules to make object" It means that Makefile has to be regenerated. To do so run qmake/qmake-qt4 again. Afterwards, if qmake did not throw any error, try to build the program one more time (see 'Installation' section above). Integration with file managers ============================== If you want to integrate QNapi with your window manager, follow instruction presented below for your WM. KDE (Dolphin/Konqueror) ----------------------- WARNING: Since version 0.1.4 QNapi should automatically integrate with Dolphin and Konqueror. However it does not integrate, to the following: You'll need qnapi-download.dekstop, which you can get from /usr/share/doc/qnapi or from http://krzemin.iglu.cz/qnapi Copy it to the following directories: * ~/.kde/share/apps/konqueror/servicemenus/ * ~/.kde/share/apps/d3lphin/servicemenus/ * ~/.kde/share/apps/dolphin/servicemenus/ Or globally (needs superuser priviledges): * /usr/share/apps/konqueror/servicemenus/ * /usr/share/apps/d3lphin/servicemenus/ * /usr/share/apps/dolphin/servicemenus/ For KDE4: * ~/.kde4/share/kde4/services/ServiceMenus/ Globally for KDE4: * /usr/lib/kde4/share/kde4/services/ServiceMenus/ Above-mentioned directories may differ in your distribution, depends on where KDE is installed. Nautilus -------- WARNING: Since 0.1.5 version QNapi should automatically integrate with Nautilus after you had installed qnapi-gnome package, proper for your distribution. Restart of the system (or reload gconfd daemon) is required. If automatic integration doesn't work or you don't want (can't) install additional package, you can use alternative way to integrate QNapi with Nautilus: You need to install nautilus-actions package and qnapi-download.schemas file, which can be found in /usr/share/doc/qnapi or on QNapi's home page (http://krzemin.iglu.cz/qnapi). You only need to copy it to /usr/share/gconf/schemas/ and execute following command: $ sudo gconf-schemas --register /usr/share/gconf/schemas/qnapi-download.schemas If this does not help, you can also try to import file qnapi-download.schemas using nautilus-actions-config tool. Thunar ------ Integration with Tunar requires to run the program choose "Edit" -> "Configure custom actions". In the dialog box press a "plus" button. New "Create Action" dialog will appear. In this dialog on "Basic" tab set: Name: "Fetch subtitles with QNapi" Description: (whatever) Command: qnapi %F You can choose icon from a file (e. g. /usr/share/icons/qnapi-48.png). On the "Appearance Conditions" tab you only have to check "Video Files". Then clink OK and it's done. Bugs Reporting =============== Any bugs found may be reported using sourceforge bugtracker: http://sourceforge.net/tracker/?group_id=218384&atid=1043757 Contact ======= If you want to send a package for your distro, or have any suggestions or notices, write me at pkrzemin@o2.pl qnapi-0.1.5/doc/COPYRIGHT0000644000175000017500000000054011014251452014265 0ustar patrykpatrykCopyright (C) 2008 Krzemin This software contains some parts of code written by: Copyright (C) 2006-2008 fullmetalcoder Copyright (C) 2005 Iulian M This software uses icons from Silk project licensed under Creative Commons Attribution 2.5 License http://www.famfamfam.com/lab/icons/silk/ qnapi-0.1.5/doc/README.pl0000644000175000017500000001253011014536365014277 0ustar patrykpatrykQNapi ===== Autor: Krzemin Strona WWW: http://krzemin.iglu.cz/qnapi Ten program rozprowadzany jest na licencji GNU General Public License. QNapi jest nieoficjalnym klonem programu NAPI-PROJEKT (http://napiprojekt.pl) napisanym w bibliotece Qt4 z myślą o użytkownikach Linuksa oraz innych systemów, pod które oryginalny NAPI-PROJEKT nie jest dostępny. Od wersji 0.1.4 istnieje także port na systemy Windows. Po więcej informacji zapraszam na stronę WWW projektu. Wymagania ========= * Biblioteka Qt w wersji conajmniej 4.3.0. Jeśli w Twoim systemie jest starsza wersja, musisz ją zaktualizować lub własnoręcznie skompilować źródła, pobrane ze strony http://trolltech.com/developer/downloads/qt/x11 * Program p7zip. Więcej informacji na stronie http://p7zip.sourceforge.net/ Instalacja ========== Aby zainstalować program, skorzystaj z pakietów dla swojej dystrybucji, które możesz znależć na stronie programu: http://krzemin.iglu.cz/qnapi Jeśli na stronie nie ma pakietów pod Twoją dystrybucję, możesz zainstalować program ze źródeł. Do tego będą potrzebne biblioteki Qt4 (libqt4-core, libqt4-gui, a do kompilacji także libqt4-dev) oraz program 7z (który znajdziesz w pakiecie p7zip-full). Ściągnij i rozpakuj archiwum .tar.gz ze źródłami programu: $ tar -zxvf qnapi-wersja.tar.gz Przejdź do katalogu ze źródłami: $ cd qnapi-wersja Aby skompilować program, wykonaj po kolei polecenia: $ qmake (lub qmake-qt4, jeśli masz zainstalowane również Qt3) $ make Jeśli komenda make zakończy się niepowodzeniem, przejdź do sekcji 'Błędy kompilacji' w tym dokumencie, aby zobaczyć możliwe przyczyny i rozwiązania. Po prawidłowej kompilacji możesz zainstalować program: $ sudo make install W tej chwili możesz uruchomić program poleceniem: $ qnapi Aby odinstalować program, wpisz: $ sudo make uninstall Błędy kompilacji ================ Jeśli polecenie make wyrzuci błąd podobny do tego: "make: *** Brak reguł do zrobienia obiektu" Oznacza to, że trzeba ponownie wygenerowac plik Makefile. W tym celu wykonaj polecenie: $ qmake (lub qmake-qt4, jesli masz zainstalowane takze Qt3) Po prawidłowym uruchomieniu programu qmake, nowy plik Makefile powinien zostać wygenerowany. Wtedy możesz przystąpić do kompilacji programu. (Szczegóły w sekcji 'Instalacja') Integracja z menedżerami plików =============================== Jeśli chcesz zintegrować QNapi ze swoim menedżerem plików, aby po kliknięciu prawym przyciskiem myszy na plik z filmem, w menu pojawiła się opcja "Pobierz napisy do filmu z QNapi", wykonaj poniższe instrukcje, adekwatne do uzywanego przez Ciebie programu. KDE (Dolphin/Konqueror) ----------------------- UWAGA: Od wersji 0.1.4 QNapi powinien automatycznie integrować się z programami Dolphin oraz Konqueror. Jesli natomiast automatyczna integracja nie bedzie działać, możesz skorzystac z drugiego sposobu: Będzie potrzebny plik qnapi-download.dekstop, który możesz znaleźć w katalogu /usr/share/doc/qnapi lub na stronie domowej programu (http://krzemin.iglu.cz/qnapi). Należy skopiować ów plik do katalogów: * ~/.kde/share/apps/konqueror/servicemenus/ * ~/.kde/share/apps/d3lphin/servicemenus/ * ~/.kde/share/apps/dolphin/servicemenus/ Lub globalnie (wymaga uprawnień administratora): * /usr/share/apps/konqueror/servicemenus/ * /usr/share/apps/d3lphin/servicemenus/ * /usr/share/apps/dolphin/servicemenus/ Dla KDE4: * ~/.kde4/share/kde4/services/ServiceMenus/ Globalnie dla KDE4: * /usr/lib/kde4/share/kde4/services/ServiceMenus/ Powyższe katalogi mogą być nieco inne w Twojej dystrybucji, w zależności od tego, gdzie zostało zainstalowane KDE. Nautilus -------- UWAGA: Od wersji 0.1.5 QNapi powinien automatycznie integrować sie z Nautilusem po zainstalowaniu pakietu qnapi-gnome, wlaściwego dla Twojej dystrybucji oraz po ponownym uruchomieniu systemu (lub przeładowaniu demona gconfd). Jeśli automatyczna integracja nie zadziała, bądź nie chcesz (nie możesz) zainstalować dodatkowego pakietu, możesz skorzystać z alternatywnego spososbu na integrację QNapi z Nautilusem: Potrzebny bedzie zainstalowany pakiet nautilus-actions oraz plik qnapi-download.schemas, który znajdziesz w katalogu /usr/share/doc/qnapi lub na stronie domowej programu (http://krzemin.iglu.cz/qnapi). Wystarczy skopiować plik qnapi-download.schemas do katalogu /usr/share/gconf/schemas/ i wykonać polecenie: $ sudo gconf-schemas --register /usr/share/gconf/schemas/qnapi-download.schemas Jeśli to by nie zadziałało, można spróbować zaimportować plik qnapi-download.schemas narzędziem nautilus-actions-config. Thunar ------ Integracja z Thunarem wymaga uruchomienia programu i wybrania opcji Edycja -> Konfiguruj akcje... Na zakładce "Podstawowe" należy ustawić: Nazwa: "Pobierz napisy do filmu z QNapi" Opis: (dowolny) Polecenie: qnapi %F Można wybrać ikonę z pliku graficznego (np. /usr/share/icons/qnapi-48.png). Na zakładce "Warunki pokazywania" należy zaznaczyć tylko "Filmy wideo". Potem OK i gotowe. Raportowanie błędów ==================== Wszelkie znalezione błędy można raportować za pomocą bugtrackera na sourceforge.net: http://sourceforge.net/tracker/?group_id=218384&atid=1043757 Kontakt ======= Jeśli chcesz przygotować pakiet dla swojej dystrybucji bądź masz inne uwagi/propozycje - napisz do mnie na pkrzemin@o2.pl qnapi-0.1.5/doc/10_qnapi0000644000175000017500000000276611014311664014343 0ustar patrykpatryk/apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/label Pobierz napisy do filmu z QNapi /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/tooltip Pobiera i dopasowuje napisy do filmu z bazy NAPI-PROJEKT /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/icon /usr/share/icons/qnapi.png /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/path qnapi /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/parameters %M /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/basenames [*.avi,*.asf,*.divx,*.dat,*.mkv,*.mov,*.mp4,*.mpeg,*.mpg,*.ogm,*.rm,*.rmvb,*.wmv] /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/matchcase false /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/mimetypes [video/x-msvideo,video/x-ms-asf,video/mpeg,video/x-ms-wmv,video/mp4,video/quicktime,video/x-theora,video/x-matroska,video/3gpp,application/vnd.rn-realmedia,application/vnd.rn-realmedia-vbr] /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/isfile true /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/isdir false /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/accept-multiple-files true /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/schemes [file] /apps/nautilus-actions/configurations/12e76756-c203-4a27-830f-af5a1527869e/version "1.1"