logsui/logscntfinder/src/logscntentry.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 02 Sep 2010 20:27:05 +0300
changeset 16 c5af8598d22c
parent 4 e52d42f9500c
child 17 90fe74753f71
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

#include <QListIterator>
#include <QStringList>
#include <QVector>

#include "logscntentry.h"
#include "logspredictivetranslator.h"
#include "logslogger.h"



// -----------------------------------------------------------------------------
// LogsCntEntry::richText()
// -----------------------------------------------------------------------------
//
QString LogsCntText::richText( QString startTag, 
                               QString endTag ) const
{
    QString str = text();
    if ( str.length() > 0 && highlights() > 0 ) {
        str.insert( highlights() , endTag );
        str.insert( 0, startTag );
    }

    return str;
    
}

// -----------------------------------------------------------------------------
// LogsCntEntry::LogsCntEntry()
// -----------------------------------------------------------------------------
//
LogsCntEntry::LogsCntEntry( LogsCntEntryHandle& handle, 
                            quint32 cid )
    : mType( EntryTypeHistory ), mCid( cid ), 
      mCached( true ),mHandle(&handle)
{
    LogsCntText empty;
    mFirstName.append( empty );
    mLastName.append( empty );
    mAvatarPath = "";
}

// -----------------------------------------------------------------------------
// LogsCntEntry::LogsCntEntry()
// -----------------------------------------------------------------------------
//
LogsCntEntry::LogsCntEntry( quint32 cid )
    : mType( EntryTypeContact ), mCid( cid ), 
      mCached( false ),mHandle(0)
{
    LogsCntText empty;
    mFirstName.append( empty );
    mLastName.append( empty );
    mAvatarPath = "";
}

// -----------------------------------------------------------------------------
// copy LogsCntEntry::LogsCntEntry()
// -----------------------------------------------------------------------------
//
LogsCntEntry::LogsCntEntry( const LogsCntEntry& entry )
    : mType(entry.mType),
      mCid(entry.mCid),
      mFirstName(entry.mFirstName),
      mLastName(entry.mLastName),
      mCached(entry.mCached),
      mHandle(entry.mHandle),
      mPhoneNumber(entry.mPhoneNumber),
      mAvatarPath(entry.mAvatarPath)
{
}

// -----------------------------------------------------------------------------
// LogsCntEntry::~LogsCntEntry()
// -----------------------------------------------------------------------------
//
LogsCntEntry::~LogsCntEntry()
{
}

// -----------------------------------------------------------------------------
// LogsCntEntry::firstName()
// -----------------------------------------------------------------------------
//
const LogsCntTextList& LogsCntEntry::firstName() const 
{
    return mFirstName;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::lastName()
// -----------------------------------------------------------------------------
//
const LogsCntTextList& LogsCntEntry::lastName() const
{
    return mLastName;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::avatarPath()
// -----------------------------------------------------------------------------
//
const QString& LogsCntEntry::avatarPath() const
{
    return mAvatarPath;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::phoneNumber()
// -----------------------------------------------------------------------------
//
const LogsCntText& LogsCntEntry::phoneNumber() const
{
    return mPhoneNumber;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::speedDial()
// -----------------------------------------------------------------------------
//
const QString& LogsCntEntry::speedDial() const
{
    return mSpeedDial;
}



// -----------------------------------------------------------------------------
// LogsCntEntry::contactId()
// -----------------------------------------------------------------------------
//
quint32 LogsCntEntry::contactId() const
{
    return mCid;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::handle()
// -----------------------------------------------------------------------------
//
LogsCntEntryHandle* LogsCntEntry::handle() const
{
    return mHandle;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::setFirstName()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::setFirstName( const QString& name ) 
{
    mCached=true;
    mFirstName.clear();
    doSetText( name, mFirstName );
}

// -----------------------------------------------------------------------------
// LogsCntEntry::setLastName()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::setLastName( const QString& name ) 
{
    mCached=true;
    mLastName.clear();
    doSetText( name, mLastName );
}

// -----------------------------------------------------------------------------
// LogsCntEntry::setAvatarPath()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::setAvatarPath( const QString& avatarpath ) 
{
    mCached=true;
    mAvatarPath.clear();
    mAvatarPath = avatarpath;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::setPhoneNumber()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::setPhoneNumber( const QString& number )
{
    LogsPredictiveTranslator* translator = LogsPredictiveTranslator::instance();
    
    mCached=true;
    mPhoneNumber.mText = number;
    mPhoneNumber.mTranslatedText = translator->translateText( mPhoneNumber.mText );
    
}


// -----------------------------------------------------------------------------
// LogsCntEntry::doSetText()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::doSetText( const QString& text, LogsCntTextList& textlist ) 
{
    LogsPredictiveTranslator* translator = LogsPredictiveTranslator::instance();
    
    QListIterator<QString> iter( translator->nameTokens( text ) );

    while( iter.hasNext() ) {
        LogsCntText txt;
        txt.mText = iter.next();
        txt.mTranslatedText = translator->translateText( txt.mText );
        textlist.append( txt );
    }
    if ( textlist.count() == 0 ) {
        textlist.append( LogsCntText() );
    }
}


// -----------------------------------------------------------------------------
// LogsCntEntry::resetHighlights()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::resetHighlights( LogsCntTextList& nameArray )
{
    QMutableListIterator<LogsCntText> names( nameArray ); 
    while( names.hasNext() ) {
        names.next().mHighlights = 0;
    }
    
}


// -----------------------------------------------------------------------------
// LogsCntEntry::setHighlights()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::setHighlights( const QString& pattern )
{
    resetHighlights( mFirstName );
    resetHighlights( mLastName );
    
    mPhoneNumber.mHighlights =
              mPhoneNumber.mTranslatedText.startsWith( pattern ) &&
              mPhoneNumber.mTranslatedText.length() >= pattern.length() ?
            pattern.length(): 0;
    
    doSetHighlights( pattern, mFirstName );
    doSetHighlights( pattern, mLastName );
    
}

// -----------------------------------------------------------------------------
// LogsCntEntry::doSetHighlights()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::doSetHighlights( const QString& pattern, 
                                    LogsCntTextList& nameArray )
{
    
    LogsPredictiveTranslator* translator = LogsPredictiveTranslator::instance();
    QMutableListIterator<LogsCntText> names( nameArray ); 
    bool hasSeparators = translator->hasPatternSeparators( pattern );
    
    //simple
    while( names.hasNext() ) {
        LogsCntText& nameItem = names.next();
        //must use non-optimized version with whole pattern
        nameItem.mHighlights = startsWith( nameItem, pattern, false );
    }
    
    //complex
    QListIterator<QString> patternArray( translator->patternTokens( pattern ) );
    while( hasSeparators && patternArray.hasNext() ) {
        QString patternItem = patternArray.next();
        names.toFront();
        while( names.hasNext() ) {
            LogsCntText& nameItem = names.next();
            int matchSize = startsWith( nameItem, patternItem, !hasSeparators );
            nameItem.mHighlights = matchSize > nameItem.mHighlights ?
                                   matchSize : nameItem.mHighlights; 
        }
    }
}


// -----------------------------------------------------------------------------
// LogsCntEntry::startsWith()
// -----------------------------------------------------------------------------
//
int LogsCntEntry::startsWith( const LogsCntText& nameItem, 
                              const QString& pattern, bool optimize ) const
{
    LOGS_QDEBUG( "logs [FINDER] -> LogsCntEntry::startsWith()" )
    //assumed that text has found based on pattern, thus only checking with
    //first char is enough, if mightContainZeroes eq false
    const QString& text = nameItem.mTranslatedText;
    
    int matchCount = pattern.length();
    if ( text.isEmpty() || matchCount > text.length() ) {
        matchCount = 0;
    } else {
        if ( !optimize ) {
            matchCount = text.startsWith( pattern ) ? matchCount : 0; 
        } else {
            matchCount = *text.data() == *pattern.data() ? 
                         matchCount : 0;
        }
    }
    LOGS_QDEBUG( "logs [FINDER] -> LogsCntEntry::startsWith()" )
    return matchCount;
}


// -----------------------------------------------------------------------------
// LogsCntEntry::setSpeedDial()
// -----------------------------------------------------------------------------
//
void LogsCntEntry::setSpeedDial( const QString& number )
{
    mSpeedDial = number;
}



// -----------------------------------------------------------------------------
// LogsCntEntry::match()
// -----------------------------------------------------------------------------
//
bool LogsCntEntry::match( const QString& pattern ) const
{
    bool match = false;
    if ( pattern.length() > 0 ) {
        LogsPredictiveTranslator* translator = LogsPredictiveTranslator::instance();
        
        //direct match with phone number is enough
        match = ( type() == EntryTypeHistory && 
                  mPhoneNumber.mTranslatedText.startsWith( pattern ) ) ||
                doSimpleMatch( pattern );
        
        match = !match && translator->hasPatternSeparators( pattern ) ? 
                doComplexMatch( translator->patternTokens( pattern) ) : match;
    }
    
    return match;
}

// -----------------------------------------------------------------------------
// LogsCntEntry::doSimpleMatch()
// -----------------------------------------------------------------------------
//
bool LogsCntEntry::doSimpleMatch( const QString& pattern ) const
{
    LogsCntTextList nameArray = mFirstName + mLastName; //with empties
    QListIterator<LogsCntText> names( nameArray ); 
    int matchCount = 0;

    while( names.hasNext() && !matchCount ) {
        matchCount = (int)names.next().mTranslatedText.startsWith( pattern );
    }

    return matchCount > 0;
}


// -----------------------------------------------------------------------------
// LogsCntEntry::doComplexMatch()
// -----------------------------------------------------------------------------
//
bool LogsCntEntry::doComplexMatch( QStringList patternArray ) const
{
    const bool zero = false;

    LogsCntTextList nameArray = mFirstName + mLastName; //with empties

    int targetMatchCount = patternArray.count();
    int namesCount = nameArray.count();

    //if pattern has more tokens than name(s), it is a missmatch
    if ( namesCount < targetMatchCount ) {
        return false;
    }

    QListIterator<LogsCntText> names( nameArray ); 
    QListIterator<QString> patterns( patternArray );
    QVector<bool> matchVector(targetMatchCount, zero );
    int currentPattern = 0;
    int matchCount = 0;
    bool match = false;
    
    while( names.hasNext() && matchCount < targetMatchCount ) {
        LogsCntText name = names.next();
        currentPattern = 0;
        patterns.toFront();
        match = false;
        while ( !name.mText.isEmpty() && 
                 patterns.hasNext() && !match ) {
            QString pattern = patterns.next();
            //unique match check
            if ( !matchVector.at( currentPattern ) ) {
                match = matchVector[ currentPattern ] 
                      = name.mTranslatedText.startsWith( pattern );
                matchCount = match ? matchCount+1 : matchCount;
            }
            currentPattern++;
        }
    }
    return matchCount >= targetMatchCount;

    }
    
    

// -----------------------------------------------------------------------------
// LogsCntEntry::isCached()
// -----------------------------------------------------------------------------
//
bool LogsCntEntry::isCached() const
{
    return mCached;
}


// -----------------------------------------------------------------------------
// LogsCntEntry::type()
// -----------------------------------------------------------------------------
//
LogsCntEntry::EntryType LogsCntEntry::type() const
{
    return mType;
}