152 lines
4.0 KiB
C++
152 lines
4.0 KiB
C++
![]() |
#include "QskPinyinCompositionModel.h"
|
||
|
|
||
|
#include "pinyin/zh.h"
|
||
|
|
||
|
#include <QVector>
|
||
|
|
||
|
class QskPinyinCompositionModel::PrivateData
|
||
|
{
|
||
|
public:
|
||
|
PrivateData():
|
||
|
groups( 5 )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
QVector< Qt::Key > groups;
|
||
|
|
||
|
char currentVowel;
|
||
|
uchar currentSubtones;
|
||
|
|
||
|
int candidateCount;
|
||
|
const PinyinCandidateSection* candidates; // pointer to 6 values, unless null
|
||
|
};
|
||
|
|
||
|
QskPinyinCompositionModel::QskPinyinCompositionModel():
|
||
|
QskInputCompositionModel(),
|
||
|
m_data( new PrivateData )
|
||
|
{
|
||
|
m_data->candidateCount = 0;
|
||
|
m_data->candidates = nullptr;
|
||
|
m_data->currentVowel = -1;
|
||
|
m_data->currentSubtones = NoTone;
|
||
|
}
|
||
|
|
||
|
QskPinyinCompositionModel::~QskPinyinCompositionModel()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
int QskPinyinCompositionModel::candidateCount() const
|
||
|
{
|
||
|
return qMax( 0, m_data->candidateCount );
|
||
|
}
|
||
|
|
||
|
Qt::Key QskPinyinCompositionModel::candidate( int index ) const
|
||
|
{
|
||
|
Q_ASSERT( m_data->candidates[ groupIndex() ].data
|
||
|
&& m_data->candidates[ groupIndex() ].size > index );
|
||
|
|
||
|
return static_cast< Qt::Key >( m_data->candidates[ groupIndex() ].data[ index ] );
|
||
|
}
|
||
|
|
||
|
QVector< Qt::Key > QskPinyinCompositionModel::groups() const
|
||
|
{
|
||
|
return m_data->groups;
|
||
|
}
|
||
|
|
||
|
bool QskPinyinCompositionModel::hasIntermediate() const
|
||
|
{
|
||
|
return m_data->currentVowel == 0
|
||
|
|| ( m_data->currentVowel > 0 && m_data->candidates
|
||
|
&& m_data->candidates[0].data );
|
||
|
}
|
||
|
|
||
|
QString QskPinyinCompositionModel::polishPreedit( const QString& preedit )
|
||
|
{
|
||
|
if ( preedit.isEmpty() )
|
||
|
{
|
||
|
m_data->candidates = nullptr;
|
||
|
m_data->candidateCount = 0;
|
||
|
Q_EMIT candidatesChanged();
|
||
|
|
||
|
std::fill( m_data->groups.begin(), m_data->groups.end(), Qt::Key( 0 ) );
|
||
|
Q_EMIT groupsChanged( m_data->groups );
|
||
|
|
||
|
return QString();
|
||
|
}
|
||
|
|
||
|
const PinyinCandidates candidates = pinyinCandidates( preedit.toUtf8() );
|
||
|
|
||
|
QString displayText = preedit;
|
||
|
displayText.replace( 'v', QChar(0x00FC), Qt::CaseInsensitive );
|
||
|
|
||
|
if ( candidates.vowel > 0 && groupIndex() != 0
|
||
|
&& ( candidates.subtones & ( 1 << ( groupIndex() - 1 ) ) ) )
|
||
|
{
|
||
|
const int vowelIndex = preedit.indexOf(candidates.vowel);
|
||
|
Q_ASSERT(vowelIndex >= 0);
|
||
|
QChar replacement = vowelWithTone(candidates.vowel, groupIndex() );
|
||
|
|
||
|
displayText.replace(vowelIndex, 1, replacement);
|
||
|
}
|
||
|
else if ( groupIndex() != 0 )
|
||
|
{
|
||
|
setGroupIndex( 0 );
|
||
|
}
|
||
|
|
||
|
m_data->candidates = candidates.sections;
|
||
|
m_data->candidateCount = m_data->candidates[ groupIndex() ].size;
|
||
|
Q_EMIT candidatesChanged();
|
||
|
|
||
|
if ( candidates.vowel == m_data->currentVowel
|
||
|
&& candidates.subtones == m_data->currentSubtones )
|
||
|
{
|
||
|
return displayText;
|
||
|
}
|
||
|
|
||
|
m_data->currentVowel = candidates.vowel;
|
||
|
m_data->currentSubtones = candidates.subtones;
|
||
|
|
||
|
QVector< Qt::Key > groups =
|
||
|
{
|
||
|
( m_data->currentSubtones & FlatTone )
|
||
|
? vowelWithTone( m_data->currentVowel, 1 ) : Qt::Key( 0 ),
|
||
|
( m_data->currentSubtones & RisingTone )
|
||
|
? vowelWithTone( m_data->currentVowel, 2 ) : Qt::Key( 0 ),
|
||
|
( m_data->currentSubtones & LowTone )
|
||
|
? vowelWithTone( m_data->currentVowel, 3 ) : Qt::Key( 0 ),
|
||
|
m_data->groups[4] = ( m_data->currentSubtones & FallingTone )
|
||
|
? vowelWithTone( m_data->currentVowel, 4 ) : Qt::Key( 0 ),
|
||
|
( m_data->currentSubtones & NeutralTone )
|
||
|
? vowelWithTone( m_data->currentVowel, 0 ) : Qt::Key( 0 )
|
||
|
};
|
||
|
|
||
|
if ( groups != m_data->groups )
|
||
|
{
|
||
|
m_data->groups = groups;
|
||
|
Q_EMIT groupsChanged( m_data->groups );
|
||
|
}
|
||
|
|
||
|
return displayText;
|
||
|
}
|
||
|
|
||
|
bool QskPinyinCompositionModel::isComposable(const QStringRef& preedit) const
|
||
|
{
|
||
|
const QByteArray text = preedit.toUtf8();
|
||
|
PinyinCandidates candidates = pinyinCandidates( text );
|
||
|
|
||
|
if ( candidates.vowel < 0 )
|
||
|
return false;
|
||
|
|
||
|
if ( candidates.vowel == 0 )
|
||
|
return true;
|
||
|
|
||
|
return candidates.sections[ 0 ].data;
|
||
|
}
|
||
|
|
||
|
void QskPinyinCompositionModel::handleGroupIndexChanged()
|
||
|
{
|
||
|
m_data->candidateCount = m_data->candidates[ groupIndex() ].size;
|
||
|
}
|
||
|
|
||
|
#include "moc_QskPinyinCompositionModel.cpp"
|