close Warning: HTML preview using PatchRenderer failed (ValueError: need more than 1 value to unpack)

Ticket #6470: fulltextsearch.diff

File fulltextsearch.diff, 25.4 KB (added by Markus Schulz <msc@…>, 15 years ago)

patch@20413

Line 
1diff --git a/mythplugins/mythvideo/mythvideo/videofilter.cpp b/mythplugins/mythvideo/mythvideo/videofilter.cpp
2index 16317b5..7e722cb 100644
3--- a/mythplugins/mythvideo/mythvideo/videofilter.cpp
4+++ b/mythplugins/mythvideo/mythvideo/videofilter.cpp
5@@ -5,6 +5,7 @@
6 #include <mythtv/libmythui/mythuibuttonlist.h>
7 #include <mythtv/libmythui/mythuibutton.h>
8 #include <mythtv/libmythui/mythuitext.h>
9+#include <mythtv/libmythui/mythuitextedit.h>
10 
11 #include "globals.h"
12 #include "videolist.h"
13@@ -72,6 +73,7 @@ VideoFilterSettings::VideoFilterSettings(bool loaddefaultsettings,
14     userrating(kUserRatingFilterAll), browse(kBrowseFilterAll),
15     m_inetref(kInetRefFilterAll), m_coverfile(kCoverFileFilterAll),
16     orderby(kOrderByTitle), m_parental_level(ParentalLevel::plNone),
17+    fulltextsearch(""), season(-1), episode(-1), re_season("(\\d+)[xX](\\d*)"),
18     m_changed_state(0)
19 {
20     if (_prefix.isEmpty())
21@@ -192,6 +194,18 @@ VideoFilterSettings::operator=(const VideoFilterSettings &rhs)
22         m_parental_level = rhs.m_parental_level;
23     }
24 
25+    if (fulltextsearch != rhs.fulltextsearch)
26+    {
27+       fulltextsearch = rhs.fulltextsearch;
28+       m_changed_state |= kFilterTextsearchChanged;
29+    }
30+    if (season != rhs.season || episode != rhs.episode)
31+    {
32+       season = rhs.season;
33+       episode = rhs.episode;
34+       m_changed_state |= kFilterTextsearchChanged;
35+    }
36+
37     return *this;
38 }
39 
40@@ -214,7 +228,20 @@ bool VideoFilterSettings::matches_filter(const Metadata &mdata) const
41 {
42     bool matches = true;
43 
44-    if (genre != kGenreFilterAll)
45+    //fulltext search
46+    if (!fulltextsearch.isEmpty())
47+    {
48+       matches = false;
49+       matches = matches || mdata.GetTitle().contains(fulltextsearch, Qt::CaseInsensitive);
50+       matches = matches || mdata.GetSubtitle().contains(fulltextsearch, Qt::CaseInsensitive);
51+       matches = matches || mdata.GetPlot().contains(fulltextsearch, Qt::CaseInsensitive);
52+    }
53+    //search for season with optionally episode nr.
54+    if (matches && season != -1) {
55+       matches = season == mdata.GetSeason();
56+       matches = matches && (episode == -1 || episode == mdata.GetEpisode());
57+    }
58+    if (matches && genre != kGenreFilterAll)
59     {
60         matches = false;
61 
62@@ -424,6 +451,37 @@ bool VideoFilterSettings::meta_less_than(const Metadata &lhs,
63     return ret;
64 }
65 
66+void VideoFilterSettings::setFulltextSearch(QString val)
67+{
68+       m_changed_state |= kFilterTextsearchChanged;
69+       if (re_season.indexIn(val) != -1)
70+       {
71+               bool res;
72+               QStringList list = re_season.capturedTexts();
73+               season = list[1].toInt(&res);
74+               if (!res)
75+                       season = -1;
76+               if (list.size() > 2) {
77+                       episode = list[2].toInt(&res);
78+                       if (!res)
79+                               episode = -1;
80+               }
81+               else {
82+                       episode = -1;
83+               }
84+               //clear \dX\d from string for string-search in plot/title/subtitle
85+               fulltextsearch = val;
86+               fulltextsearch.replace(re_season, "");
87+               fulltextsearch = fulltextsearch.simplified ();
88+       }
89+       else
90+       {
91+       fulltextsearch = val;
92+               season = -1;
93+               episode = -1;
94+       }
95+}
96+
97 /////////////////////////////////
98 // VideoFilterDialog
99 /////////////////////////////////
100@@ -432,7 +490,7 @@ VideoFilterDialog::VideoFilterDialog(MythScreenStack *lparent, QString lname,
101     m_browseList(0), m_orderbyList(0), m_yearList(0), m_userratingList(0),
102     m_categoryList(0), m_countryList(0), m_genreList(0), m_castList(0),
103     m_runtimeList(0), m_inetrefList(0), m_coverfileList(0), m_saveButton(0),
104-    m_doneButton(0), m_numvideosText(0), m_videoList(*video_list)
105+    m_doneButton(0), m_numvideosText(0), m_fulltextsearch(0), m_videoList(*video_list)
106 {
107     m_fsp = new BasicFilterSettingsProxy<VideoList>(*video_list);
108     m_settings = m_fsp->getSettings();
109@@ -449,6 +507,7 @@ bool VideoFilterDialog::Create()
110         return false;
111 
112     bool err = false;
113+    UIUtilE::Assign(this, m_fulltextsearch, "fulltextsearch_input", &err);
114     UIUtilE::Assign(this, m_yearList, "year_select", &err);
115     UIUtilE::Assign(this, m_userratingList, "userrating_select", &err);
116     UIUtilE::Assign(this, m_categoryList, "category_select", &err);
117@@ -500,6 +559,8 @@ bool VideoFilterDialog::Create()
118             SLOT(SetCoverFile(MythUIButtonListItem*)));
119     connect(m_orderbyList, SIGNAL(itemSelected(MythUIButtonListItem*)),
120             SLOT(setOrderby(MythUIButtonListItem*)));
121+    connect(m_fulltextsearch, SIGNAL(valueChanged()),
122+               SLOT(setFulltextSearch()));
123 
124     connect(m_saveButton, SIGNAL(Clicked()), SLOT(saveAsDefault()));
125     connect(m_doneButton, SIGNAL(Clicked()), SLOT(saveAndExit()));
126@@ -778,3 +839,9 @@ void VideoFilterDialog::setOrderby(MythUIButtonListItem *item)
127             .setOrderby((VideoFilterSettings::ordering)item->GetData().toInt());
128     update_numvideo();
129 }
130+
131+void VideoFilterDialog::setFulltextSearch()
132+{
133+       m_settings.setFulltextSearch(m_fulltextsearch->GetText());
134+       update_numvideo();
135+}
136diff --git a/mythplugins/mythvideo/mythvideo/videofilter.h b/mythplugins/mythvideo/mythvideo/videofilter.h
137index c3839bf..1e51470 100644
138--- a/mythplugins/mythvideo/mythvideo/videofilter.h
139+++ b/mythplugins/mythvideo/mythvideo/videofilter.h
140@@ -30,7 +30,8 @@ class VideoFilterSettings
141         kFilterInetRefChanged = (1 << 8),
142         kFilterCoverFileChanged = (1 << 9),
143         kFilterParentalLevelChanged = (1 << 10),
144-        kFilterCastChanged = (1 << 11)
145+        kFilterCastChanged = (1 << 11),
146+        kFilterTextsearchChanged = (1 << 12)
147     };
148 
149   public:
150@@ -121,6 +122,9 @@ class VideoFilterSettings
151         orderby = lorderby;
152     }
153 
154+    QString getFulltextSearch() const { return fulltextsearch;}
155+    void setFulltextSearch(QString val);
156+
157     ParentalLevel::Level getParentalLevel() const { return m_parental_level; }
158     void setParentalLevel(ParentalLevel::Level parental_level)
159     {
160@@ -163,6 +167,11 @@ class VideoFilterSettings
161     ordering orderby;
162     ParentalLevel::Level m_parental_level;
163     QString prefix;
164+    QString fulltextsearch;
165+    int season;
166+    int episode;
167+    QRegExp re_season;
168+
169 
170     unsigned int m_changed_state;
171 };
172@@ -223,6 +232,7 @@ class VideoFilterDialog : public MythScreenType
173     void SetInetRef(MythUIButtonListItem *item);
174     void SetCoverFile(MythUIButtonListItem *item);
175     void setOrderby(MythUIButtonListItem *item);
176+    void setFulltextSearch();
177 
178  private:
179     void fillWidgets();
180@@ -243,6 +253,7 @@ class VideoFilterDialog : public MythScreenType
181     MythUIButton    *m_saveButton;
182     MythUIButton    *m_doneButton;
183     MythUIText      *m_numvideosText;
184+    MythUITextEdit     *m_fulltextsearch;
185 
186     const VideoList &m_videoList;
187     FilterSettingsProxy *m_fsp;
188diff --git a/mythtv/themes/Terra/video-ui.xml b/mythtv/themes/Terra/video-ui.xml
189index 390a99c..387d03d 100644
190--- a/mythtv/themes/Terra/video-ui.xml
191+++ b/mythtv/themes/Terra/video-ui.xml
192@@ -95,7 +95,7 @@
193     </window>
194 
195     <window name="filter">
196-        <area>0,42,1280,515</area>
197+        <area>0,42,1280,555</area>
198         <imagetype name="fade">
199             <filename>popups/fade_background.png</filename>
200         </imagetype>
201@@ -120,116 +120,126 @@
202 
203         <!-- Labels -->
204 
205+        <textarea name="fullsearch_text">
206+            <area>269,235,180,30</area>
207+            <value>Fulltext search:</value>
208+           <font>basemedium</font>
209+        </textarea>
210+       
211+       <textedit name="fulltextsearch_input" from="baseshorttextedit">
212+         <position>450,225</position>
213+       </textedit>
214+
215         <textarea name="category_text">
216-            <area>269,228,220,30</area>
217+            <area>269,268,220,30</area>
218             <value>Category</value>
219             <align>hcenter</align>
220             <font>basemedium</font>
221         </textarea>
222 
223         <textarea name="genre_text" from="category_text">
224-            <position>269,296</position>
225+            <position>269,336</position>
226             <value>Genre</value>
227         </textarea>
228 
229         <textarea name="country_text" from="category_text">
230-            <position>269,364</position>
231+            <position>269,404</position>
232             <value>Country</value>
233         </textarea>
234 
235         <textarea name="cast_text" from="category_text">
236-            <position>269,432</position>
237+            <position>269,472</position>
238             <value>Actor/Actress</value>
239         </textarea>
240 
241         <textarea name="year_text" from="category_text">
242-            <position>526,228</position>
243+            <position>526,268</position>
244             <value>Year</value>
245         </textarea>
246 
247         <textarea name="runtime_text" from="category_text">
248-            <position>526,296</position>
249+            <position>526,336</position>
250             <value>Runtime</value>
251         </textarea>
252 
253         <textarea name="userrating_text" from="category_text">
254-            <position>526,364</position>
255+            <position>526,404</position>
256             <value>User Rating</value>
257         </textarea>
258 
259         <textarea name="browse_text" from="category_text">
260-            <position>526,432</position>
261+            <position>526,472</position>
262             <value>Browse</value>
263         </textarea>
264 
265         <textarea name="inetref_text" from="category_text">
266-            <position>784,228</position>
267+            <position>784,268</position>
268             <value>InetRef</value>
269         </textarea>
270 
271         <textarea name="coverfile_text" from="category_text">
272-            <position>784,296</position>
273+            <position>784,336</position>
274             <value>Cover File</value>
275         </textarea>
276 
277         <textarea name="orderby_text" from="category_text">
278-            <position>784,364</position>
279+            <position>784,404</position>
280             <value>Sort by</value>
281         </textarea>
282 
283         <!-- Widgets -->
284 
285         <buttonlist name="category_select" from="baseselector">
286-            <position>269,255</position>
287+            <position>269,295</position>
288         </buttonlist>
289 
290         <buttonlist name="genre_select" from="baseselector">
291-            <position>269,323</position>
292+            <position>269,363</position>
293         </buttonlist>
294 
295         <buttonlist name="country_select" from="baseselector">
296-            <position>269,391</position>
297+            <position>269,431</position>
298         </buttonlist>
299 
300         <buttonlist name="cast_select" from="baseselector">
301-            <position>269,459</position>
302+            <position>269,499</position>
303         </buttonlist>
304 
305         <buttonlist name="year_select" from="baseselector">
306-            <position>526,255</position>
307+            <position>526,295</position>
308         </buttonlist>
309 
310         <buttonlist name="runtime_select" from="baseselector">
311-            <position>526,323</position>
312+            <position>526,363</position>
313         </buttonlist>
314 
315         <buttonlist name="userrating_select" from="baseselector">
316-            <position>526,391</position>
317+            <position>526,431</position>
318         </buttonlist>
319 
320         <buttonlist name="browse_select" from="baseselector">
321-            <position>526,459</position>
322+            <position>526,499</position>
323         </buttonlist>
324 
325         <buttonlist name="inetref_select" from="baseselector">
326-            <position>784,255</position>
327+            <position>784,295</position>
328         </buttonlist>
329 
330         <buttonlist name="coverfile_select" from="baseselector">
331-            <position>784,323</position>
332+            <position>784,363</position>
333         </buttonlist>
334 
335         <buttonlist name="orderby_select" from="baseselector">
336-            <position>784,391</position>
337+            <position>784,431</position>
338         </buttonlist>
339 
340         <button name="done_button" from="basebutton">
341-            <position>693,515</position>
342+            <position>693,560</position>
343             <value>Done</value>
344         </button>
345 
346         <button name="save_button" from="basebutton">
347-            <position>363,515</position>
348+            <position>363,560</position>
349             <value>Make default</value>
350         </button>
351 
352diff --git a/mythtv/themes/Terra/video/filters_background.png b/mythtv/themes/Terra/video/filters_background.png
353index 5470bb3ceed1c1bc15a07465004a212e5be2eca3..162fc1a3e67d0581f45b336ae5902bf9e24d5ed0 100644
354GIT binary patch
355literal 6911
356zcmb_g2|Sx=w@;U;E>t^arY(kc8ceIDt(MxSE3r<g+S1S>=?H?3oy1i4QX{mfYG`Y#
357zHG>8jg3{91QoGnvEpmfUA&5wFpXfJc{M!4?-0$9>NS>U$?|IJo|IhY5w|=xTk=ZD}
358z5dwk8z)VltKp<;0AduDS>(>Fvh7C=*;A7Qg8<XRZ{ANWq__FSzxyeb0Sn~Inni(&-
359z%GcEKGWgJw{IB}pjyD5Bsh?q%r=%Ebzm)lURfTfWaR@{n2RnJ}Y;X^!-#OZyf1zuN
360zS*a0`IKgh18E?!F>SB<;y<zG5rOE2mukn^^?_Ldlw`=tabHtYQ<6CVM(@b}sa@Zns
361zn-ll#2Gd{Hn_Ue#Y5MEUUw`;9dYk^Sz;|Uu0}S2-yew=1(P0-5{A{#8nVrl?PMpY}
362zct|(Vdw9;8o~0$WH9XJcr--v`?Cg{}ht&xg@!>~lCh?2D_)Sq9I6elN1XIG+soii3
363zTC5$I(w|i`@msvx->r|W!?`v=wW7KNI_r8npyJ&$jIgiHD1!HT9p^&zF!!FhGK@P7
364z6Pe+WMY{J-Qxij}aiP>?8&B-wDoEAqoK{X?8z-=p6VT>^@p$t!)0C?Y6LIJf<899A
365z35Id!4C@<d$7+`JSaI*bj1C)V$I)nP3oEP4Gnk_&2;@T=%EHbAjW$$p9%J;ut?hXE
366zc6K}xB8;~{3ZJ!2!7%L%qSR%Sv|W|9YY<5Aho=6zG-E}Dq}P3o$7}1<h&vz<SC@W-
367zj=K6CM`st9O$4u*+r#7!84JjmiH(E-*Bm8P#Ds$6-q1ZXTyBS_v7T|zE|h8}@e2s#
368z?GJiH&OQyMX%3lEP+ZKn#!hV$HIZbi)05J)=6O}CiZG?{3V-$*7`CKkyK}JTVB%qU
369z%iXdNh(SVjc40UR+1Y9D&uZ?eoF6h4lIfeDrW4c1>aGI^5wlkt01?>lX<|j?l=5Iv
370zpH^1KK*)=TlHR7kF#Ud?F2*WI<W~Efj@C=sZC*-VO@h%L|NE1D^+}k%1y;&JI&)qY
371zR*cV;#d<445x|uOdkvyBS1cb>fYLPL^{q+u2=UWxFmG^lL|A6F`ON}vHrSfcW*AwG
372zjZMhGMap5NEr){6`Jg-kvKHb=*tu;YAxT6KKXecH%{$Flz^w|V1kqEnIy~t{WM6UO
373z{myghqzeBdXmxb+SHQs++1d4@^-kyPJN<<*V<DnztV5LtDkr;|oA<egm7Nzg%2s}u
374zo)o@dRq*;Tm7-95=)xr0)}yPj0gDsm=~2RmTV1TVB`lUkUyx-(6Iy4QN5Y<X4iYGc
375z{j*-kus*XvorxW;uy-fw2OV^4DqvLdwTyYO@dih_k@1gUIGglhW>{tU*Anis)%bng
376z-7h01m1g@fSRE2|Ar!=6(P{`}9Q~7@u8W|)tF6bA6BBFG(AY?Mg!7!x6t<g)7jNL<
377zrv64W3;Zo<r0eV*0&xeSGHys}1WBJ1ywxG~Hxh@xMy-NCf=!4VD}=BuM<5z#PXr`4
378zEzVn)i&LX6h3ut;<FlYm$I6GWgWNd~b6Q5)1*}a@&UxWtvQD%S1mf$8&OuZBIJL=i
379zg3Tc<!<0?i=t2f+AV5SpR=RI!!jWJ|i0;sEq0CG`m8ndXivZ@1;R_H*)rqk8WSu#x
380zyVphkz3B-HH;lM)#)(6HJK-a(E@Q2Y`Q&-bHFJFBgER{(3l3wj^<Ck$d2riqHZN3w
381zpxTi-fGu&7jjqk0oW5zTgnQ}Hx*yxtQwO<jO(PDYJn9@Afq-lGNN#d=L@?$y=HI%N
382z)ksgFJ`nZXr@YW6iiR)7^c9&_-XE${;EhBmuLW^*h8IfB&Ci|Sho`nQCT87Y6lvL_
383z;vZS!Mm+Rr!2?(vVSF=T+ia3IAd($ec3K_)xGyhnHkr;j{JM?4uQ9W-*h5dqAWTUQ
384zw0Q)Tx8vJ^DM5;3UO~|ZK+<;?mz2zHAYh{sMC0}IJDr+`IOeY=oF2QF<85a5_2~2h
385zUKMZqpfJwuX2$SrY<#rL6_1M_{8E{RF{H~`J5Gb7zgfTYY;9{w2qQ$Uo~i{3JLH5k
386zVPPjCu$ai(kID1<Ns+ac?9B1<^2+G<%xvSN^|I5m%PA@lh_t4H*(lj*H0Jcfrqil)
387z3#7mQcXQ=_Lcf>h-d%zA&lR0ZbMx|0A?&+fhyl6p&awl-7y}dTXf4O{j^=w*P^b(o
388z9i1d6p@T;2UV)cxvF}eMC6~u)^PcziCWF%8>tvIWUFeTG0-_?(SSO`OtF4arW{x<b
389zTj<N^?rzLeC}|zDYc_yD9v!D5?)8>@)8<oh+2?|&R8zUEA+AvXY#ym4Cp`rP>U0%I
390zL7)Co!*;i$GrkNZxDsey(RX>gn0=c4JBYp%HWvW89oAqT)apsL!U4<k9d807c6+gB
391zxola&1*>mCc$;9*Iro}kn%WdJoSpN2);o{-66o$*Sg2*o5Mp*I0$Y3+t$5Mq=$v8c
392z)sQN=$GsenFhOuvao6U_x93&Crq&kaiqnU-4gzWno?Fd*b=};~E~`9X6Zm>C+YLKe
393z`*4>O1ake^`fY$5sO0^JQb5Xz1w?YUMDlS#SW{sO_^3Ki13X>6+BM-T$z_l9s)2Ni
394zgxD2};EVTcu7X_;$V=XL!olw=7LmTdUx{SpLZWC%@~OsU$y>jg^zFb^*X{MI&@ZEb
395z4&Qeh{&2+L>UUtTNL!f1D~Ux*1}`sG__^%MN{5$>mH77IrrB0tPnGEktNusxU<aka
396z#W2}FfLqq%d$K;?<&MN*tNlyF>=?A^I|Eu`^7q3J<lg!s;bu0Zq;k+`)J{<m#@7Z9
397zU0nl6y4r98t)0}Y1gKkO29s~9eZm=Ys2Of-Pt#fth>pB<>sGsGUD?^8H%i{z#-Reu
398zH(-am%mb?XH}8jglASW>R{D1U1J$EEr;N;4ae(+q^JHTaJ>#4f2Y8q2>4VkwSWn{1
399z9)XYYLPzLLx=G;bE46C1Hv;c<JRv>P)xWHbLctFKtW(okp0TQ5P47A3)QyFftaflX
400zN?^11pn$KZcR4+bfrpP&|Hv#W@Pmf!r|~y!`swbGqUWXK7Hc3?dyX8`joY-XIrAJz
401zhIdrngfh*bBw8dVHnzUA(bg$`6aax7RgsSg9cgYNK2Xn+HxWYI+?wFw3&)-E&UJQa
402z7ZwyGHV4*eN#J|nl;`g6e+ZSKdKo#|_@=W+S_K{$9UF@Z4>w?aGtxFT+sc-VI<~yf
403z<Xym-ed%ckQaS>Yc7~*;Hq&n@UlaVsiF&^vbU&<34g^Oq>-qsuNtY>IUMz*q_FsJW
404zTnF23zaCXVOWy%}efv`Gj{pr`8+86e=h61__V)(AfJDYw-+u3+in}xjX1n6f&POM~
405zZGKHtQ-^D7tx%=o!L!#;wmB3D>CsP<x_r`m4MpmCn++w%dmb?dBbMt|_Y$CW${HKj
406z06eBPN7N42D(IA_tAHDx1?CV#Q$s>)(i24A5q;>ySK#uq9STjLT!T^p)1B1^NdU24
407zhnA$7B*K<M@6*Ivl3dS}B*Ne3f27-b!o}?XpLnG|68xW}QzX@Fk0j%^%d98~%L%+v
408z$LDi%WlBn{jg(W?cm=8`M9om*=JltFzVfFeS+17+4{FIuX8+EV@tlOEG7`5E$Yp3(
409zl(L<0{QnXp>0?WE<=H>0E5OBNjFuOlFJzH*G9L-M@cpo>?!{U_!qKT^V+W2==yehe
410zM-7){D;7&2NhB*5E6n_}%*SS={i7)QR~JznC+-EwbbZGsq4f6VJp)%Eb*VraNHCVD
411zT^Rrd1@%G<R8>;i+m=XQ24Z>fc|=yK`IJuIcmJ-Lq<w5ACjSr3M6z|{R=a=LQR=q*
412zHP-)zl0RcR?A}sSj$Ze96hC!;N%A)_P<2c8uT|j0nfe#1OTGOsZFdFuD=}XtbLH+U
413zHeEKOs^TL+msZ5wpAJgcUQXUE8lP*qk!OCC==Swoo(WbM_x6^Z<mUr>KQ-WbUfj^r
414z3zFLMq$|hhf%|Tn89p;UT7?Z|n6+B9n%gA$fdIDpG(;m)ZR%fC<i`y;;ZZW6#2;9T
415zOK{&q%Y!m4xN5L`RYyzl#6`Q0>G;K``${A$Gj3V30){_RZyAP~Gq)vab2{oDl|a~S
416ziFa0^l5k$8CHl(8AUFSfkXz?2{d{KE=X=Y*vE8&&H9(&<O)B0C>Iman;0vHcs57hw
417z77E)dnfR-2b(#7b(#oU(cYh*d#;sdI1~-!4vw=|8$@$raxA(+mFcRms<3m$*6Y7i-
418zeA&-SY;#n2q5X`tAbHv)#~5cb_2KxvmsulPhFY9xFa)o6a&~NZ$4P%;Sn-O#wA<0#
419zZ+Y1W@Zh->H0G`CIoAbFm2qhXvk0@oV7G&JbiN^;0nO<QIn|*JQU6Qm(2q!Xt*UB#
420z{rOj*C#Kyy^!$d8V)GQ?iAV+T(t`8@&yLFhy1e)g2|MvG!mj=w2)q4}uzxe+zD?UJ
421zU<w^1jAq7uey89_o2AgPGWySI#og1HZCRV;H4G(B1=1%v==c2}`(|ZR<7{&hqd`b2
422zF|pnSImhbrIWGoV#{%XSPp7sVs0RGFq3?3M@A#0~WFMR*EBe+B^L$E*bl?wT5^SOm
423zfuTEiuvM{FK_hA%C1Tnt%)az&lsD6t--;cyF{8E5B%A@$s8RzXksVQ!-ap_IA?7JK
424z3$B`zF{RH-oWcI+8P*6YMxy9-vjq`$IhVqk&g(?_3^@FLFU@E@VZhKi08?5H2V+{X
425z_UyRVVAi$6NtUTHV9Lg4rbL9&S>Qlrr1LZa$Ekg{6P^w2hxWqs%BqL+g0mvty-(pI
426z@dTaX&bjg52A;9{HH|RO!Q6f$(B}e{nNwQqq>z=3sQ4go3E7RQJY^pCo44$DBl+gl
427zffMGljHV{ucuA*6AXb~zoT4=fu=wRjQj@`4wJ3h)*qAzBgx1Ngm=Y!tXEfz{tqPBH
428zJ26n59%^urtsT#&-|>83P#s-dby;Hv7!fy*^S7l~r=DR>^UtBRlAOo*)nZY7Q2gPx
429zl=BR;LZj~Db-Rj!YKP^N#TM!`wXQDvLTdj&(R65PvhqUQ9BaJM5e%J>QWCN#ajrsa
430zI7e;i;?{Heey4<U%r$Y|9&dK{M!7m#7HY32SWTRNUx-$=$A@3=<1b7E6@)i*&pTj0
431zq|Xfl08&D!Bhf%rP@>BNy1DU!4RTU$e-65V(bMx^Sdk7^FpMC{D_^A{@%pg)lN$&T
432zU8O@3t2Al!;@-T@cib3(QX_v8Yr0hmQBS!RvI=<T?ispwGDLhQWGX^)JS@Zk@8#|7
433z&Tr0JWQwQBn$(5*Bv`8{?jShud<8XU(|>>7S{Xi`zk}dExf#c9Qx-66>PgMbkJPnL
434z%H`izW@qQ-<)(LddX!O#J|(PNa3*?Foea)O6AKEE8O>Ii3@?KZV<jcM6u&WEc_42=
435zJw-T7$5DDY&6}TsIzERF-%TrtFV~*$8_5r57{l=iIDQsxW)4m6VP#|@wRFOa(!WB1
436zN4DTgfC)!<d9uzxDW6Igaaon!J{Wq2ac|-Mp%^F=#?6D0pp=92;rerprQ`as(@fmh
437zuqJMZB%<gOeFP+OkF&?ci+joM3c;lN_U*ZIgu>_HySwuHe_x<jM~LolW@jxHg1$tn
438zP>4f3C`px%#XFZhO)t@R0*9wCu70JE+khL?#JwGM+ON#$hU+Fl-Q47mE})P}^>})Z
439z%)TS%Vsd9hAIzEa+)6>0m>*kGqOS$3U3a1I=*@ffZIuS&p$nU4f=C$JFV!kAzDuRx
440z2Fb$Wu5jeqooRYd7)RNW>0pUJJQ~yPiF5^OE5HG3$EaqNi=$&Bmpj^u5iQ^ZRHlHa
441zscCO_#PCvVr(ui#5n2+Pgl3qEJ70HH_;DZm?(m9%#^c5&MKjhF^8-P`s6+-kCBLJ-
442z+u^c-oSf}Xhvl=nz-w#|xkrEe%gC*QgTu^-NVOsxaFi`M#|H177$h3K+s<ydmY0rp
443zS&SlKS+ZEMdP!OT#QbBm>|+o1sZz9W-tQ;e<WwX%OkSw*V9lYUr1az6XCo$Yq6p=M
444z4^lWJGH|pGiOfJeG73XJDaC>(_+-<hq`a739Rgt>e0r8ka1kx=jD^i(zyr4|aKNQ6
445zB&+MUa2H&|rjsu*rZeJY<uuCPrzg4}0_T_4pw?<3;G}Ail9}QdY;9+!MMVT;WM>yZ
446z$)3KCRkCbaEzL+!V#17>8Lq%GWbARalyX(ejTWKO6TLLCnZanW`tUPxLy@${qAW&i
447zB3OSS>`L<eDc#{UKTFf;bpv%#qCEL)V#n+Oe%NoJxkCGn7A0K3(C)Luk@qAk{)T7%
448zzt^$0C#RT1gvJJkXS*%V?(Z0k6+IDtQJ+t|FB%hO7yn+^a^4Bf&cN+(h<GETB6N)B
449z%wW*v(?<Kdqzbsmg&<jH#kEcPryFV(4SK)Td=JZrZ<JX*avYzzPMNNvtH1tH!3@eX
450zQ1d#QqxX2XSo@dwzVCvY57;bP)J)%0n_?jtU+?wk8WURK^JX+<dT-r#j&h(Riuzwp
451zNMkD_e!WE7xo`7A%yU~y>I}&cExXY(!1us(S+z&#7R~n|VGp0p*UlV&9a7UBwXM8)
452zRr8>!sIR|&Q{J(JTop$puRCnbs>*oxh%MT^A%e{pJ8BHNYZB}twivoa{g5dCvVP|6
453zd#xzCwRE)ys^|5lUAUm=vH~g12anb~ifU1a>W^2@A1pMwN$7Y%QiyW>iN!fJFIDm7
454z*cq(p<YHn^ek6l(b$lR?q7J{k?F+=o9bu1jK3tSywamv3b#tzoqwLF{uX|EBJvE!}
455z$~GK-VB9Rr$Cr`3b0#+?*5=2K&4uqrti8fg3~pJM9F-a{k$wJHD}&5=X@TjQHDw9J
456ZYwqFmq5P+rcA#29V5h83<{x*x^4|?f1^NI0
457
458literal 7443
459zcmcgx2~^W(wvS^AE)}%;L<&M31K5rPW#2;DYSGA6ixm+B7Xq>)K>{QJEu+{9qCs|(
460zjAfHiLAF3-69H)m5G6ub0%1wO2qBO_VnUYp;k<X+u`^nG<~<Ia9CGgees}rZ-@V`c
461z|L~3bfeq_ESqFhYHXsk~{}uvS4TC`bw0eyO_+~<KND4kaK!1fivIhL%)&yJu|F4ZY
462z=#2&+_A7s@<^u?az?Zr)UmuI{j0}vyoQg(4Fc=IhI3g5%=2R3478xCsKj-)f1fqW(
463zx&O-}akm5`!B<c+JZD@;buk_3>zi5ZI%pwD-A%u--E3if!3Q72D!#f5-MFR&3XOFA
464z6l&YKaif+kbZq~iF@^i3^$v<Zw54rbqVAft-fOgu-uv13-~b^US>SEyV%FE!SK~E;
465z6-^vnI@$;CW7fV@J$xBI_D%bJ=JYM>-G?)Y@+8%?W%%&a;YLNL3mTbdNi!kfA_;T{
466z`X%UHWIw@Cet9NpHbV?GRA=C3f0!f}n#cyylLLD-=W|Hh$s|HLJianrjdYT<EqHv3
467zpy8Z_((>8e<t8#iq>5hRBpYODhjw%q{FP2GZ&*BoOf;sE-Fk)6lHM5!Qy}RT#4;_3
468zt@iE^$lp?}lUqJbZi&@s{nFZoRmJ=-e-{xQnaJ}bD`pdzme@bv$0K%{*qy9v0Hz}H
469zxYGn2E+NFYstTP;B)XIjV-d?AKp@v{P{OO4nh1SMnfLDBFAPr+R);T_kH!f`{8j8A
470zr{;L+-yP^XHM{n;@_1f;c}P(-flSKFqfup7b4et;p~r_1i0xWnLsr(-%7)6Dh04zE
471zc3!iDpR^d7R43+H)1rcc4UPN^w!zGrMZE_y6wW0~*+ua*Z2I{u`-~HKe5`O_bhPvF
472zL}pmnz56h;a;1{IJeVXFny<_Lk{}?aYii}-U!N{lLDf~P{D-few+At2mO7SqLm(H<
473zl!p)R9&O0uWfrj;s0xOYQaee2*8Q3uNJwL^&5@>N!^cIUznI}Y2x==he0i~GJ)@Wz
474zFI+1H;q%G&(fvq6DE@2}1mf|ddr5|0GdWRx5<MDeY8JRKRnwsCuSpW+CN0dUooES!
475zOk#Sz-4_k)&98kaf~w0|`SLNQ2VDB}thev6u8Fkv-KL|R5{cxZ);16qr@UesJC~V@
476zz*y^;oj54mu>+0fCuBv8oJ~^yh4X4KY5A_2k1(OuRNV`-l#8CmQIqJ+1N;~#;Gt%E
477zb=bW~ZjF~eL)0r;jthZ69-Vte36C%}o$l|A9>vd$II16`?UEK0O*157bI$$y-BTVo
478z;d+Gl1V_m>#80Mka280Lg5{xVYA6@gj7X|?_e<mzA+ovUBm_ow5q-R@32o)C>}2g<
479z4}nCb3j~4&`BEgW50SWZF(}|f-F!^3+%rhs>!EtZaS=W5iMFPdrfPg=zdW*RG`Kc9
480z+dsZEpPOA=9B2@?^dM3(ZX<dU8X0J-?<C3i6F^pp-ukPuWV0kIy%{}hQ-831F1h)-
481ziwAMp0-^fBP!>m^BVk6l9_AUuO*zU56sC=529@=ogUkf=;=4lM?(X)Y1;@<*AIFAA
482zhk8OeI6SAE=wwCqD<>Pu$J23tE;t+iIZXyF$yl`bF&iG+%8PXOU<4+F1TxlvBV`i3
483z$h7hKRgeoAr)B-oWesQ)W73TokT{2fA@JiKPRkcv7^p2U9klQco#gq%eg&TxsH`p7
484zeG^vD$08a45_7Dq9gV|sJf8#xdXxm`&2=QrrXaGoUpbFQ!wRS{CEH3T$;*UBcJJ-#
485zxiwnV0$etpSPg*)=~1?9>FoW8l6-z?t|K_gEWolidT#-<eTv|Udj6U8S{+o@l9=@Q
486z$lPcs%nY{snsRK#)HA{7f;kp-fr0MR3YmpRkYz28-D95pjDNb3ZG&vi;HD&uD9w@@
487z0={yBK<2kyZao!YIx-}VD`zoEnHE8eF0xYw*VTEa85&uPo>swX&l4IRaL&>tl30!8
488zmL2+lb)yIXSab1VwO^9rB@?pLDM}a0Qf^KpVjptL;`mU0Og*;TmeN?Gb~^*8*`U3@
489zzn|0*t5>L-R^}SC#k3@P`bY)V_yvYg7%XuevKa!&PHjJljr57hJ6u;?V4T~z>sVl{
490zlMrP&6pba(M^A(5vbA?}zHOfQ>}UF%+b-ZdQ0#gz<M5rux#O|ZwQSO4CFZDV#}Ip<
491z>*dSi);88v@PVF_*c{4vv<n21lT(bWWg=@?F3lYJZ0TTEPY<_Ak7X!791x_!OMb}W
492zUU`g)k2kt%6OlKs4T12gb+s-J4h{9lk4J|F+qp5hT?*eGqC>vB^q_lhh{SvD+@0}C
493zDm63Is|<xk3%>(Icp-0y(%swb<K0wqORUo~-KAh37RWEQI;L!e-Mt%1jpZG`+$wnx
494z3w+W4Y5YO=Qt0|YHoNQ6)#-HkVg**evyK5Q2Ppfl8dU1uC~z*T%$NLPZz|lE66>xF
495zKyfWSGqZ2^Xq{b!G9B()W)J@ed{@-2XH!*CvG)c(-O4vB(lq}HaG+x#ZRYCcLE*7h
496z6k*>1pl{sApY!w3%b^=WOxSp3Q_~HBpry`Q69U;%Q(2k7UDo%hyXQW(f}jHF{`9)A
497zdme!VEs*MJjpS1l%C*>t<$=ejJyCgpm2PcG-bph4voCP@00rMBRCjy~3m+~%KeH8N
498zY46a^Cd}kO<QHoJy4K_+--E8miT(-*;u}&F@V#?0Xz*XeKL)(L%VQ;rytO)@899yv
499z5Zp9*Eo^T$M*JLz8n<70<1s62an+hP#oy5VsLisQwEl{~<zFj*L;CHO{7zvOve#Aq
500zDeyC+)b3>3wsZgN=A8geM#t~e^p60%kMP<M5M-l25M-oQObM8rE+F?#{1W<KPBt#3
501z&P=YJ=B)oE+%{QJ!M=xeArSYQQ&%>hbleGZ>lJ*`u);b&4GRqTswYSF4&cWC+PIDt
502z<6!9MsQC<}_CYZ+K{+}=IluAD`fSgVp#S+cH#axN{(!@G0b$sDxD}SWIR+S0VDrP5
503zS1T^LlrTZxqn--~5ZrZVSP&2~_ktr$KaZPc%c}S>AJwn)vh#C_LCei?3`BnvKepa3
504zX`F3q15meRFWdrNQFZT$Q^8c1BKKA<rW1fx-=xvcCY#)JGw`d;!`i%WAv$J$KeO5V
505z)&Wa^^0ow}A1P5H+AkcjC0#Y+lp|p$nsQV}5H?%4YNJ2|9*yVc5@|eob}!#Rz)Kfm
506zY{x4nXQ{F-QeJo3B|UGS6Ns)8Anj+K&zwikJ*JumeY-uR4oZ7|1mS@|+v(})d3*bH
507zgZie_QnazPK;h1pF?oQ7rk?W$Z`tERPK&)I=ojOap$Q50OeT{WwSc<}Do-={BaP(h
508z*73vJL5`xD0gDZTUod>Ry{ztpU)$|F*UyhN?-M}z9;c;1>*l~pi!e}BT3@^c{eC8>
509z^5=j$^f8)^w4zPFB=|M@ew?#Qxo6YwRx3DWv%(KCkK#X@w4_7@4_nXB>61hHppuUy
510zCD=EXmhK#xjyvE>z|CLME@qy)Z4T=H8W;&olUtsVgRLYhY2nAX5&=La?;ta{FIvAo
511zwNmhD_%>drj~Bc5V?bY}-D%x1SmjQRaNu!KuyaO?#y+pDtHBe0AD$^;3Jhe49kvs_
512z`m#(w7#A{H^xv@doy>BQ@V+F(qOFR21;V}OGw1g&tCa%Uv)7HOe-{2LM*F3#eh2-%
513zm#{rD4`~Rx&!g7Yv}0UsH@4@;-^sJ@b<n>Q&bd__tW}x!{^!j=?VkP{j(=-wSg~Ty
514z-tJYbcXyG0Y4E>mId2m_Pq55zS_8(&06?|8D{s~dGSpyR7XG$=_BQ3eX?|}AKjK>c
515z(FkkSdl~^?6u#My{t<)!vW)*(fqfT7b8@CybUv<6dH)Rmfdmnu-G$nq@N9GQR`>rV
516z&LNUpUl{+fg8aRc2Q4^n>eIXLO36Qs4Ce{@FD{z_R?9fu_Lh<6jjaA!#b#!q-P45s
517zEByTWB;Nlb`9jL;p6}|))DQdg>$h}@-#f9r#l2sRcdqV$7Oma|x!;y33mN^u=Q{ul
518z*WZBRa|7G7cRFA^buoKWefobE!z{fHXN}?E;1q$aHAwuHz8FG8IRXsfM!poA+Fm|%
519zBm$$K4~F(1!Gb_Htkxs84jSHb!j?>xQ5V8i<{DIdu-$rAq-&UZ>U9dzg4>LADXkx+
520zwEko62^esfG$xuM#RERUgiC)}?_F0p|LOqX`kT+~Qtbq8=)W20(y!2;cZKyn{QJs?
521z6RH`Sx^FKS(((d-@>r>(QP&>O!T-}O=a*y~1NNu<0gM3lA8UL);kUjy;TtWxqc*+s
522zhOlA+Xag!Q#OS{NKlpZmJ23Y8l0EWr3Jz?JAj=^K274P=2}EcsWkk=8c&!CwVQfLb
523z+KRC{h-Qh#!lAlaDammE7fT80_zU0(Wocvh-fa;k$f0VYepDN;yX7R7p#z4`yeYWa
524z5s>x1rDad7!EpHX8L!BQDfhZ+2f6_f>OW-W3pPP~D)Wr}k(GUyy#=Cnx}xQzLw>%G
525z9w$-UnIO4LCxNTCtaqy4c_>z>uS8EXt}R_ynaz36`JQ}_C8=XmMMc(KuLxh4-tJw#
526zm!+oCHWw3`&M>80E`Lc%JAr$7TCQw#08^~(l^~~AU8D|hp&gQkjN&Fc!M>u`SQk2Y
527zsFLU~9_`>~PnL6o)O%<;UMw$3*n{DjDF;8C>KhX9F{<H2U0foks;=MWD3j8P8?S9r
528z9GzqTghB@mcJ4YoXJ-^9eHcLY@$sQ0qEGaY5c%t~VX0DZt$=hKZ{{%2X0wPjm6eq@
529zBb(3hmTH^u=N$@|Z4|;i;ch)@=<}ixYJ@1FPSHWx?pGfldWy3Fp(ZlyP+*?5eK75h
530zb87U%Fedf%LcM+bX*w!tcJqxw^0OD6E6X<&yx{tv!-S~RBQbU-t;FkSR%J~MHE43g
531z&xRw$8`5%R7H1N{g5%LSaCs4*FqA!AZMIlb7XxRN!J5QHW~!ENo#B<4haa#HRo*&W
532z7dEZ3gJHraGok*+j^U(p^~Xl7t>BqL)r%DIb~7h(1V%_STgiYx(Jq#~(8gH?8E!PK
533z&C&t;Qu|kmay83LD@73Fe5x{w8%Stp>%o?L&e2wOxTgr@AvSy9*s%uDqhxA~>{}<f
534z(y$w>3O)pGUT309#JAHMa&!=i$4w<EMl`uRWNV}!U9ChU%@?u!@D9iXUAHIxhbpgg
535zot+C{db&iXSZtyT!BU!Drl9*P>JfdG-Q{5C_q2-~|Ef>{Hn<Jdx6;zm!onj^dj_y(
536zD>#k|ws(^&6N`)GcKAS;GEsPYCNeyHs<XyM{A5PhB&YhnQV6v)lB;ynDC~ox`%thx
537z?m&(X#D|&E#%_=ITDplD2r))=6s&8DsLUYr+-#Ah8(7C(I8Z}rB3!zJ5%>FeH7~u^
538z6BZFc>^@tKvZMJRn@HSrLPH+6vu84&8rg>O_@pL$*xF58uI4k;i;JSpZZc<RGz{h!
539zXFSrQ+6UHHkY(?O=Xcs<mrajg%9>R!WSK(8#-?`4BIJ5ns`JrNq$rkfSC?oWi#?r)
540z<*cETHf0A`z9bZiwN(q8S8Z%|sXu?|p`on>#wlp3M;8xDz#s&F#?%G`^~sccUfQ%+
541z!&&ZD&vX2@f20v){!p>tOqkInZk41#Ij*9qo-=omlp)H9g(iv<g(MUQ+an()smu};
542zqIBHsvXg~{gEG5*#IL7|NG~0v#?)&g(l-FO+JX9#KMBe5iU`Ext!lH5Mk=Nv6}4u#
543zC8__&A@lrams+gN^RB1`V8hmscevV@e)hB~kT9++Fr~G&7SUe7vKpaPNxX7(TZf;b
544zOj{w4RiP2j_?DiYN`6<@E%$PkOD)r-cG!){pH*yvxL>wbjcD3l90H5~m94)<vLGz1
545z3<b^xFC;qaZAN88j;fQDv|QVS!|&PV8uWZ~xO2g0>vf3+lA#`vfc-;OTB<Quh;1*|
546zyzCM^eY1i{Bp!;Ev>L{%S`F3D5K9^2AP@DJLc!OW?z#1Fz%~iM)xEH$CarJAODD2H
547zDOqagC?~u)$|)Adm;U1B19#_^%FJhfT^>0bj}D4=kUG<w&_1znOJ4$ZqKN!#BLhdc
548ziX<ULv$L~{Xoe$pVPE)gk9LZnloDP-h#4ZT4kuW<X&^1a2m(u8>)^|}@TPikioyPj
549zR_y{!!R_tLBqM{^VXN*_>g?&;hUy)W>L}@+3d5%r;i~KYWD~`Q_TQ5k9ivZLRrl?+
550z)K!b~oFho_=v_zLvT&h({@ixalr~;F1+UOf$S{AhU4L#$`}|CbTCU&1m>!R4gtNEn
551zOVXzsITr$F9YQ;#+ndBQg>D&z%whri`0?%RW5+&$^5=Hfmz>;Su`a8IP4%GH>$Z0e
552z>z;sz?I`$LJmV}<Ya@(CipzC3&*u6%uR`0=JRQhnmuTaHN4cG63#aDlk6inn*Yl_E
553zwx>uF^i2^KCi$G;)MWBb611Lq$R2|yrH%?CgJRA<=mXga1<LzUjmJ4`nLJQyqbbcP
554zd*3Ld$B2Nr8=UiuxZB3!^E*BcnrJ7?V-&0)F1Lqx>Zkgo(&el1dq&s5b8#Hwj!*`Y
555zCw<A4892&t+J+-ap%8;TwX<NCw|iw>)$V{8*<?QQsQJ45`>78n-~~o@V^`>cOrh(5
556zFmMapQ}@G8e(Gsd#I)GcA)OJh1y<kc?C}$LWAg%vkRnA7J+84x$c4+nBAm7{LpnxF
557z+%RXr9@vnbnL5Gi@9F4E{T?)lkyBdROldm-z!=ndB6tHc;`#HOznr=mhSA<}ZjWC%
558zZD9xjY_%;Vacvyf<IA?*erjnXrW$qqS+IZoLgkIacV-it93Go@t%k)b_N42>YSm-J
559zXW1j@;aC&yVr<sj2}7Y@wn>Um=Rh|@-}RbJxN9D{#e_AdSUNS=b#CxP?3utgmZ%A4
560zztGgmlW5GPK4K&6N-`QV&VL-~dSQ~*9Bz_t<NF91qi)87134Ym@eOym@Yp)`=+j1)
561zILu&v6DV)eTyr1oOh@O)ldZ7j2zDBHM>MwI?jBYfY=!`5rM9XyGgmFH`lR3{xYa-)
562O$gkb^mwk2e`~L<f3D@8N
563