|
|
|
@ -75,144 +75,6 @@ KeyboardPage::~KeyboardPage()
|
|
|
|
|
delete ui;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KeyboardPage::guessLayout( const QStringList& langParts )
|
|
|
|
|
{
|
|
|
|
|
const KeyboardLayoutModel* klm = dynamic_cast< KeyboardLayoutModel* >( ui->listLayout->model() );
|
|
|
|
|
bool foundCountryPart = false;
|
|
|
|
|
for ( auto countryPart = langParts.rbegin(); !foundCountryPart && countryPart != langParts.rend(); ++countryPart )
|
|
|
|
|
{
|
|
|
|
|
cDebug() << Logger::SubEntry << "looking for locale part" << *countryPart;
|
|
|
|
|
for ( int i = 0; i < klm->rowCount(); ++i )
|
|
|
|
|
{
|
|
|
|
|
QModelIndex idx = klm->index( i );
|
|
|
|
|
QString name
|
|
|
|
|
= idx.isValid() ? idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString() : QString();
|
|
|
|
|
if ( idx.isValid() && ( name.compare( *countryPart, Qt::CaseInsensitive ) == 0 ) )
|
|
|
|
|
{
|
|
|
|
|
cDebug() << Logger::SubEntry << "matched" << name;
|
|
|
|
|
ui->listLayout->setCurrentIndex( idx );
|
|
|
|
|
foundCountryPart = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( foundCountryPart )
|
|
|
|
|
{
|
|
|
|
|
++countryPart;
|
|
|
|
|
if ( countryPart != langParts.rend() )
|
|
|
|
|
{
|
|
|
|
|
cDebug() << "Next level:" << *countryPart;
|
|
|
|
|
for ( int variantnumber = 0; variantnumber < ui->listVariant->count(); ++variantnumber )
|
|
|
|
|
{
|
|
|
|
|
LayoutItem* variantdata = dynamic_cast< LayoutItem* >( ui->listVariant->item( variantnumber ) );
|
|
|
|
|
if ( variantdata && ( variantdata->data.compare( *countryPart, Qt::CaseInsensitive ) == 0 ) )
|
|
|
|
|
{
|
|
|
|
|
ui->listVariant->setCurrentItem( variantdata );
|
|
|
|
|
cDebug() << Logger::SubEntry << "matched variant" << variantdata->data << ' '
|
|
|
|
|
<< variantdata->text();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KeyboardPage::onActivate()
|
|
|
|
|
{
|
|
|
|
|
/* Guessing a keyboard layout based on the locale means
|
|
|
|
|
* mapping between language identifiers in <lang>_<country>
|
|
|
|
|
* format to keyboard mappings, which are <country>_<layout>
|
|
|
|
|
* format; in addition, some countries have multiple languages,
|
|
|
|
|
* so fr_BE and nl_BE want different layouts (both Belgian)
|
|
|
|
|
* and sometimes the language-country name doesn't match the
|
|
|
|
|
* keyboard-country name at all (e.g. Ellas vs. Greek).
|
|
|
|
|
*
|
|
|
|
|
* This is a table of language-to-keyboard mappings. The
|
|
|
|
|
* language identifier is the key, while the value is
|
|
|
|
|
* a string that is used instead of the real language
|
|
|
|
|
* identifier in guessing -- so it should be something
|
|
|
|
|
* like <layout>_<country>.
|
|
|
|
|
*/
|
|
|
|
|
static constexpr char arabic[] = "ara";
|
|
|
|
|
static const auto specialCaseMap = QMap< std::string, std::string >( {
|
|
|
|
|
/* Most Arab countries map to Arabic keyboard (Default) */
|
|
|
|
|
{ "ar_AE", arabic },
|
|
|
|
|
{ "ar_BH", arabic },
|
|
|
|
|
{ "ar_DZ", arabic },
|
|
|
|
|
{ "ar_EG", arabic },
|
|
|
|
|
{ "ar_IN", arabic },
|
|
|
|
|
{ "ar_IQ", arabic },
|
|
|
|
|
{ "ar_JO", arabic },
|
|
|
|
|
{ "ar_KW", arabic },
|
|
|
|
|
{ "ar_LB", arabic },
|
|
|
|
|
{ "ar_LY", arabic },
|
|
|
|
|
/* Not Morocco: use layout ma */
|
|
|
|
|
{ "ar_OM", arabic },
|
|
|
|
|
{ "ar_QA", arabic },
|
|
|
|
|
{ "ar_SA", arabic },
|
|
|
|
|
{ "ar_SD", arabic },
|
|
|
|
|
{ "ar_SS", arabic },
|
|
|
|
|
/* Not Syria: use layout sy */
|
|
|
|
|
{ "ar_TN", arabic },
|
|
|
|
|
{ "ar_YE", arabic },
|
|
|
|
|
{ "ca_ES", "cat_ES" }, /* Catalan */
|
|
|
|
|
{ "as_ES", "ast_ES" }, /* Asturian */
|
|
|
|
|
{ "en_CA", "us" }, /* Canadian English */
|
|
|
|
|
{ "el_CY", "gr" }, /* Greek in Cyprus */
|
|
|
|
|
{ "el_GR", "gr" }, /* Greek in Greeze */
|
|
|
|
|
{ "ig_NG", "igbo_NG" }, /* Igbo in Nigeria */
|
|
|
|
|
{ "ha_NG", "hausa_NG" } /* Hausa */
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
ui->listLayout->setFocus();
|
|
|
|
|
|
|
|
|
|
// Try to preselect a layout, depending on language and locale
|
|
|
|
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
|
|
|
|
QString lang = gs->value( "localeConf" ).toMap().value( "LANG" ).toString();
|
|
|
|
|
|
|
|
|
|
cDebug() << "Got locale language" << lang;
|
|
|
|
|
if ( !lang.isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
// Chop off .codeset and @modifier
|
|
|
|
|
int index = lang.indexOf( '.' );
|
|
|
|
|
if ( index >= 0 )
|
|
|
|
|
{
|
|
|
|
|
lang.truncate( index );
|
|
|
|
|
}
|
|
|
|
|
index = lang.indexOf( '@' );
|
|
|
|
|
if ( index >= 0 )
|
|
|
|
|
{
|
|
|
|
|
lang.truncate( index );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lang.replace( '-', '_' ); // Normalize separators
|
|
|
|
|
}
|
|
|
|
|
if ( !lang.isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
std::string lang_s = lang.toStdString();
|
|
|
|
|
if ( specialCaseMap.contains( lang_s ) )
|
|
|
|
|
{
|
|
|
|
|
QString newLang = QString::fromStdString( specialCaseMap.value( lang_s ) );
|
|
|
|
|
cDebug() << Logger::SubEntry << "special case language" << lang << "becomes" << newLang;
|
|
|
|
|
lang = newLang;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( !lang.isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
const auto langParts = lang.split( '_', SplitSkipEmptyParts );
|
|
|
|
|
|
|
|
|
|
// Note that this his string is not fit for display purposes!
|
|
|
|
|
// It doesn't come from QLocale::nativeCountryName.
|
|
|
|
|
QString country = QLocale::countryToString( QLocale( lang ).country() );
|
|
|
|
|
cDebug() << Logger::SubEntry << "extracted country" << country << "::" << langParts;
|
|
|
|
|
|
|
|
|
|
guessLayout( langParts );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KeyboardPage::updateVariants( const QPersistentModelIndex& currentItem, QString currentVariant )
|
|
|
|
|
{
|
|
|
|
|