13 * |
13 * |
14 * Description: |
14 * Description: |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 #include <QListIterator> |
|
19 |
|
20 #include <qcontactdetailfilter.h> |
18 #include <qcontactdetailfilter.h> |
21 #include <qcontactphonenumber.h> |
19 #include <qcontactphonenumber.h> |
22 #include <qcontactname.h> |
20 #include <qcontactname.h> |
23 #include <qcontactmanager.h> |
21 #include <qcontactmanager.h> |
24 #include <qcontactavatar.h> |
22 #include <qcontactavatar.h> |
25 #include <QVector> |
23 |
26 |
24 #include "logscntentry.h" |
27 #include "logscntfinder.h" |
25 #include "logscntfinder.h" |
28 #include "logspredictivetranslator.h" |
26 #include "logspredictivetranslator.h" |
29 #include "logslogger.h" |
27 #include "logslogger.h" |
30 |
28 |
31 const int MaxPredSearchPatternLen = 15; |
29 const int MaxPredSearchPatternLen = 15; |
32 const QChar ZeroSepar('0'); |
30 |
33 |
31 |
34 |
|
35 // ----------------------------------------------------------------------------- |
|
36 // LogsCntEntry::richText() |
|
37 // ----------------------------------------------------------------------------- |
|
38 // |
|
39 QString LogsCntText::richText( QString startTag, |
|
40 QString endTag ) const |
|
41 { |
|
42 QString str = text(); |
|
43 if ( str.length() > 0 && highlights() > 0 ) { |
|
44 str.insert( highlights() , endTag ); |
|
45 str.insert( 0, startTag ); |
|
46 } |
|
47 |
|
48 return str; |
|
49 |
|
50 } |
|
51 |
|
52 // ----------------------------------------------------------------------------- |
|
53 // LogsCntEntry::LogsCntEntry() |
|
54 // ----------------------------------------------------------------------------- |
|
55 // |
|
56 LogsCntEntry::LogsCntEntry( LogsCntEntryHandle& handle, |
|
57 quint32 cid ) |
|
58 : mType( EntryTypeHistory ), mCid( cid ), |
|
59 mCached( true ),mHandle(&handle) |
|
60 { |
|
61 LogsCntText empty; |
|
62 mFirstName.append( empty ); |
|
63 mLastName.append( empty ); |
|
64 mAvatarPath = ""; |
|
65 } |
|
66 |
|
67 // ----------------------------------------------------------------------------- |
|
68 // LogsCntEntry::LogsCntEntry() |
|
69 // ----------------------------------------------------------------------------- |
|
70 // |
|
71 LogsCntEntry::LogsCntEntry( quint32 cid ) |
|
72 : mType( EntryTypeContact ), mCid( cid ), |
|
73 mCached( false ),mHandle(0) |
|
74 { |
|
75 LogsCntText empty; |
|
76 mFirstName.append( empty ); |
|
77 mLastName.append( empty ); |
|
78 mAvatarPath = ""; |
|
79 } |
|
80 |
|
81 // ----------------------------------------------------------------------------- |
|
82 // copy LogsCntEntry::LogsCntEntry() |
|
83 // ----------------------------------------------------------------------------- |
|
84 // |
|
85 LogsCntEntry::LogsCntEntry( const LogsCntEntry& entry ) |
|
86 : mType(entry.mType), |
|
87 mCid(entry.mCid), |
|
88 mFirstName(entry.mFirstName), |
|
89 mLastName(entry.mLastName), |
|
90 mCached(entry.mCached), |
|
91 mHandle(entry.mHandle), |
|
92 mPhoneNumber(entry.mPhoneNumber), |
|
93 mAvatarPath(entry.mAvatarPath) |
|
94 { |
|
95 } |
|
96 |
|
97 // ----------------------------------------------------------------------------- |
|
98 // LogsCntEntry::~LogsCntEntry() |
|
99 // ----------------------------------------------------------------------------- |
|
100 // |
|
101 LogsCntEntry::~LogsCntEntry() |
|
102 { |
|
103 } |
|
104 |
|
105 // ----------------------------------------------------------------------------- |
|
106 // LogsCntEntry::firstName() |
|
107 // ----------------------------------------------------------------------------- |
|
108 // |
|
109 const LogsCntTextList& LogsCntEntry::firstName() const |
|
110 { |
|
111 return mFirstName; |
|
112 } |
|
113 |
|
114 // ----------------------------------------------------------------------------- |
|
115 // LogsCntEntry::lastName() |
|
116 // ----------------------------------------------------------------------------- |
|
117 // |
|
118 const LogsCntTextList& LogsCntEntry::lastName() const |
|
119 { |
|
120 return mLastName; |
|
121 } |
|
122 |
|
123 // ----------------------------------------------------------------------------- |
|
124 // LogsCntEntry::avatarPath() |
|
125 // ----------------------------------------------------------------------------- |
|
126 // |
|
127 const QString& LogsCntEntry::avatarPath() const |
|
128 { |
|
129 return mAvatarPath; |
|
130 } |
|
131 |
|
132 // ----------------------------------------------------------------------------- |
|
133 // LogsCntEntry::phoneNumber() |
|
134 // ----------------------------------------------------------------------------- |
|
135 // |
|
136 const LogsCntText& LogsCntEntry::phoneNumber() const |
|
137 { |
|
138 return mPhoneNumber; |
|
139 } |
|
140 |
|
141 // ----------------------------------------------------------------------------- |
|
142 // LogsCntEntry::speedDial() |
|
143 // ----------------------------------------------------------------------------- |
|
144 // |
|
145 const QString& LogsCntEntry::speedDial() const |
|
146 { |
|
147 return mSpeedDial; |
|
148 } |
|
149 |
|
150 |
|
151 |
|
152 // ----------------------------------------------------------------------------- |
|
153 // LogsCntEntry::contactId() |
|
154 // ----------------------------------------------------------------------------- |
|
155 // |
|
156 quint32 LogsCntEntry::contactId() const |
|
157 { |
|
158 return mCid; |
|
159 } |
|
160 |
|
161 // ----------------------------------------------------------------------------- |
|
162 // LogsCntEntry::handle() |
|
163 // ----------------------------------------------------------------------------- |
|
164 // |
|
165 LogsCntEntryHandle* LogsCntEntry::handle() const |
|
166 { |
|
167 return mHandle; |
|
168 } |
|
169 |
|
170 // ----------------------------------------------------------------------------- |
|
171 // LogsCntEntry::setFirstName() |
|
172 // ----------------------------------------------------------------------------- |
|
173 // |
|
174 void LogsCntEntry::setFirstName( const QString& name ) |
|
175 { |
|
176 mCached=true; |
|
177 mFirstName.clear(); |
|
178 doSetText( name, mFirstName ); |
|
179 } |
|
180 |
|
181 // ----------------------------------------------------------------------------- |
|
182 // LogsCntEntry::setLastName() |
|
183 // ----------------------------------------------------------------------------- |
|
184 // |
|
185 void LogsCntEntry::setLastName( const QString& name ) |
|
186 { |
|
187 mCached=true; |
|
188 mLastName.clear(); |
|
189 doSetText( name, mLastName ); |
|
190 } |
|
191 |
|
192 // ----------------------------------------------------------------------------- |
|
193 // LogsCntEntry::setAvatarPath() |
|
194 // ----------------------------------------------------------------------------- |
|
195 // |
|
196 void LogsCntEntry::setAvatarPath( const QString& avatarpath ) |
|
197 { |
|
198 mCached=true; |
|
199 mAvatarPath.clear(); |
|
200 mAvatarPath = avatarpath; |
|
201 } |
|
202 |
|
203 // ----------------------------------------------------------------------------- |
|
204 // LogsCntEntry::tokens() |
|
205 // ----------------------------------------------------------------------------- |
|
206 // |
|
207 QStringList LogsCntEntry::tokens( const QString& source, |
|
208 const QChar& separ ) const |
|
209 { |
|
210 QStringList target = source.split( separ, QString::SkipEmptyParts ); |
|
211 if ( target.length() > 1 && separ == ZeroSepar ) { |
|
212 QString& first = target[0]; |
|
213 QString& last = target[target.length()-1]; |
|
214 padWithZeros( first, source, 0 ); |
|
215 padWithZeros( last, source, last.length() ); |
|
216 } |
|
217 return target; |
|
218 |
|
219 } |
|
220 |
|
221 |
|
222 // ----------------------------------------------------------------------------- |
|
223 // LogsCntEntry::padWithLeadingZeros() |
|
224 // ----------------------------------------------------------------------------- |
|
225 // |
|
226 void LogsCntEntry::padWithZeros( QString& token, |
|
227 const QString& source, int padIndex ) const |
|
228 { |
|
229 const QChar* content = source.data(); |
|
230 int index = !padIndex ? 0 : source.length()-1; |
|
231 |
|
232 while( index >= 0 && index < source.length() ) { |
|
233 if ( content[ index ] == ZeroSepar ) { |
|
234 token.insert( padIndex, ZeroSepar ); |
|
235 index = !padIndex ? index+1 : index-1; |
|
236 } else { |
|
237 index = -1; |
|
238 } |
|
239 } |
|
240 } |
|
241 |
|
242 |
|
243 |
|
244 // ----------------------------------------------------------------------------- |
|
245 // LogsCntEntry::doSetText() |
|
246 // ----------------------------------------------------------------------------- |
|
247 // |
|
248 void LogsCntEntry::doSetText( const QString& text, LogsCntTextList& textlist ) |
|
249 { |
|
250 QListIterator<QString> iter( tokens( text ) ); |
|
251 |
|
252 while( iter.hasNext() ) { |
|
253 LogsCntText txt; |
|
254 txt.mText = iter.next(); |
|
255 txt.mTranslatedText = |
|
256 LogsPredictiveTranslator::instance()->translate( txt.mText ); |
|
257 textlist.append( txt ); |
|
258 } |
|
259 if ( textlist.count() == 0 ) { |
|
260 textlist.append( LogsCntText() ); |
|
261 } |
|
262 } |
|
263 |
|
264 // ----------------------------------------------------------------------------- |
|
265 // LogsCntEntry::setPhoneNumber() |
|
266 // ----------------------------------------------------------------------------- |
|
267 // |
|
268 void LogsCntEntry::setPhoneNumber( const QString& number ) |
|
269 { |
|
270 mCached=true; |
|
271 mPhoneNumber.mText = number; |
|
272 } |
|
273 |
|
274 // ----------------------------------------------------------------------------- |
|
275 // LogsCntEntry::resetHighlights() |
|
276 // ----------------------------------------------------------------------------- |
|
277 // |
|
278 void LogsCntEntry::resetHighlights( LogsCntTextList& nameArray ) |
|
279 { |
|
280 QMutableListIterator<LogsCntText> names( nameArray ); |
|
281 while( names.hasNext() ) { |
|
282 names.next().mHighlights = 0; |
|
283 } |
|
284 |
|
285 } |
|
286 |
|
287 |
|
288 // ----------------------------------------------------------------------------- |
|
289 // LogsCntEntry::setHighlights() |
|
290 // ----------------------------------------------------------------------------- |
|
291 // |
|
292 void LogsCntEntry::setHighlights( const QString& pattern ) |
|
293 { |
|
294 resetHighlights( mFirstName ); |
|
295 resetHighlights( mLastName ); |
|
296 |
|
297 mPhoneNumber.mHighlights = |
|
298 mPhoneNumber.text().startsWith( pattern ) && |
|
299 mPhoneNumber.text().length() >= pattern.length() ? |
|
300 pattern.length(): 0; |
|
301 |
|
302 doSetHighlights( pattern, mFirstName ); |
|
303 doSetHighlights( pattern, mLastName ); |
|
304 |
|
305 } |
|
306 |
|
307 // ----------------------------------------------------------------------------- |
|
308 // LogsCntEntry::doSetHighlights() |
|
309 // ----------------------------------------------------------------------------- |
|
310 // |
|
311 void LogsCntEntry::doSetHighlights( const QString& pattern, |
|
312 LogsCntTextList& nameArray ) |
|
313 { |
|
314 |
|
315 LogsPredictiveTranslator* translator = |
|
316 LogsPredictiveTranslator::instance(); |
|
317 QMutableListIterator<LogsCntText> names( nameArray ); |
|
318 bool hasZeros = pattern.contains( ZeroSepar ); |
|
319 |
|
320 //simple |
|
321 while( names.hasNext() ) { |
|
322 LogsCntText& nameItem = names.next(); |
|
323 nameItem.mHighlights = |
|
324 translator->startsWith( nameItem.mText, pattern, false ); |
|
325 } |
|
326 |
|
327 //complex |
|
328 QStringList tokenArray = tokens( pattern, ZeroSepar ); |
|
329 QListIterator<QString> patternArray( tokenArray ); |
|
330 while( hasZeros && patternArray.hasNext() ) { |
|
331 QString patternItem = patternArray.next(); |
|
332 names.toFront(); |
|
333 while( names.hasNext() ) { |
|
334 LogsCntText& nameItem = names.next(); |
|
335 int matchSize = translator->startsWith( nameItem.mText, |
|
336 patternItem, !hasZeros ); |
|
337 nameItem.mHighlights = matchSize > nameItem.mHighlights ? |
|
338 matchSize : nameItem.mHighlights; |
|
339 } |
|
340 } |
|
341 } |
|
342 |
|
343 // ----------------------------------------------------------------------------- |
|
344 // LogsCntEntry::setSpeedDial() |
|
345 // ----------------------------------------------------------------------------- |
|
346 // |
|
347 void LogsCntEntry::setSpeedDial( const QString& number ) |
|
348 { |
|
349 mSpeedDial = number; |
|
350 } |
|
351 |
|
352 |
|
353 |
|
354 // ----------------------------------------------------------------------------- |
|
355 // LogsCntEntry::match() |
|
356 // ----------------------------------------------------------------------------- |
|
357 // |
|
358 bool LogsCntEntry::match( const QString& pattern ) const |
|
359 { |
|
360 bool match = false; |
|
361 |
|
362 //direct match with phone number is enough |
|
363 match = mPhoneNumber.text().startsWith( pattern ) || |
|
364 doSimpleMatch( pattern ); |
|
365 |
|
366 if ( !match && pattern.contains( ZeroSepar ) ) { |
|
367 QStringList patternArray = tokens( pattern, ZeroSepar ); |
|
368 match = doComplexMatch( patternArray ); |
|
369 } |
|
370 |
|
371 return match; |
|
372 } |
|
373 |
|
374 // ----------------------------------------------------------------------------- |
|
375 // LogsCntEntry::doSimpleMatch() |
|
376 // ----------------------------------------------------------------------------- |
|
377 // |
|
378 bool LogsCntEntry::doSimpleMatch( const QString& pattern ) const |
|
379 { |
|
380 LogsCntTextList nameArray = mFirstName + mLastName; //with empties |
|
381 QListIterator<LogsCntText> names( nameArray ); |
|
382 int matchCount = 0; |
|
383 |
|
384 while( names.hasNext() && !matchCount ) { |
|
385 matchCount = (int)names.next().mTranslatedText.startsWith( pattern ); |
|
386 } |
|
387 |
|
388 return matchCount > 0; |
|
389 } |
|
390 |
|
391 |
|
392 // ----------------------------------------------------------------------------- |
|
393 // LogsCntEntry::doComplexMatch() |
|
394 // ----------------------------------------------------------------------------- |
|
395 // |
|
396 bool LogsCntEntry::doComplexMatch( QStringList patternArray ) const |
|
397 { |
|
398 const bool zero = false; |
|
399 |
|
400 LogsCntTextList nameArray = mFirstName + mLastName; //with empties |
|
401 |
|
402 int targetMatchCount = patternArray.count(); |
|
403 int namesCount = nameArray.count(); |
|
404 |
|
405 //if pattern has more tokens than name(s), it is a missmatch |
|
406 if ( namesCount < targetMatchCount ) { |
|
407 return false; |
|
408 } |
|
409 |
|
410 QListIterator<LogsCntText> names( nameArray ); |
|
411 QListIterator<QString> patterns( patternArray ); |
|
412 QVector<bool> matchVector(targetMatchCount, zero ); |
|
413 int currentPattern = 0; |
|
414 int matchCount = 0; |
|
415 bool match = false; |
|
416 |
|
417 while( names.hasNext() && matchCount < targetMatchCount ) { |
|
418 LogsCntText name = names.next(); |
|
419 currentPattern = 0; |
|
420 patterns.toFront(); |
|
421 match = false; |
|
422 while ( !name.mText.isEmpty() && |
|
423 patterns.hasNext() && !match ) { |
|
424 QString pattern = patterns.next(); |
|
425 //unique match check |
|
426 if ( !matchVector.at( currentPattern ) ) { |
|
427 match = matchVector[ currentPattern ] |
|
428 = name.mTranslatedText.startsWith( pattern ); |
|
429 matchCount = match ? matchCount+1 : matchCount; |
|
430 } |
|
431 currentPattern++; |
|
432 } |
|
433 } |
|
434 return matchCount >= targetMatchCount; |
|
435 |
|
436 } |
|
437 |
|
438 |
|
439 |
|
440 // ----------------------------------------------------------------------------- |
|
441 // LogsCntEntry::isCached() |
|
442 // ----------------------------------------------------------------------------- |
|
443 // |
|
444 bool LogsCntEntry::isCached() const |
|
445 { |
|
446 return mCached; |
|
447 } |
|
448 |
|
449 |
|
450 // ----------------------------------------------------------------------------- |
|
451 // LogsCntEntry::type() |
|
452 // ----------------------------------------------------------------------------- |
|
453 // |
|
454 LogsCntEntry::EntryType LogsCntEntry::type() const |
|
455 { |
|
456 return mType; |
|
457 } |
|
458 |
32 |
459 // ----------------------------------------------------------------------------- |
33 // ----------------------------------------------------------------------------- |
460 // LogsCntFinder::LogsCntFinder() |
34 // LogsCntFinder::LogsCntFinder() |
461 // ----------------------------------------------------------------------------- |
35 // ----------------------------------------------------------------------------- |
462 // |
36 // |