add keyboard layout switch selector
This commit is contained in:
parent
1b235e56a3
commit
1ac3459afa
@ -160,6 +160,7 @@ Config::Config( QObject* parent )
|
||||
, m_keyboardModelsModel( new KeyboardModelsModel( this ) )
|
||||
, m_keyboardLayoutsModel( new KeyboardLayoutModel( this ) )
|
||||
, m_keyboardVariantsModel( new KeyboardVariantsModel( this ) )
|
||||
, m_keyboardGroupsModel( new KeyboardGroupsModel( this ) )
|
||||
{
|
||||
m_setxkbmapTimer.setSingleShot( true );
|
||||
|
||||
@ -190,25 +191,40 @@ Config::Config( QObject* parent )
|
||||
emit prettyStatusChanged();
|
||||
} );
|
||||
|
||||
connect( m_keyboardVariantsModel, &KeyboardVariantsModel::currentIndexChanged, this, &Config::xkbChanged );
|
||||
connect( m_keyboardVariantsModel,
|
||||
&KeyboardVariantsModel::currentIndexChanged,
|
||||
[ & ]( int index )
|
||||
{
|
||||
m_selectedVariant = m_keyboardVariantsModel->key( index );
|
||||
Config::xkbChanged();
|
||||
emit prettyStatusChanged();
|
||||
} );
|
||||
connect( m_keyboardGroupsModel,
|
||||
&KeyboardGroupsModel::currentIndexChanged,
|
||||
[ & ]( int index )
|
||||
{
|
||||
m_selectedGroup = m_keyboardGroupsModel->key( index );
|
||||
Config::xkbChanged();
|
||||
emit prettyStatusChanged();
|
||||
} );
|
||||
|
||||
// If the user picks something explicitly -- not a consequence of
|
||||
// a guess -- then move to UserSelected state and stay there.
|
||||
connect( m_keyboardModelsModel, &KeyboardModelsModel::currentIndexChanged, this, &Config::selectionChange );
|
||||
connect( m_keyboardLayoutsModel, &KeyboardLayoutModel::currentIndexChanged, this, &Config::selectionChange );
|
||||
connect( m_keyboardVariantsModel, &KeyboardVariantsModel::currentIndexChanged, this, &Config::selectionChange );
|
||||
connect( m_keyboardGroupsModel, &KeyboardGroupsModel::currentIndexChanged, this, &Config::selectionChange );
|
||||
|
||||
m_selectedModel = m_keyboardModelsModel->key( m_keyboardModelsModel->currentIndex() );
|
||||
m_selectedLayout = m_keyboardLayoutsModel->item( m_keyboardLayoutsModel->currentIndex() ).first;
|
||||
m_selectedVariant = m_keyboardVariantsModel->key( m_keyboardVariantsModel->currentIndex() );
|
||||
m_selectedGroup = m_keyboardGroupsModel->key( m_keyboardGroupsModel->currentIndex() );
|
||||
}
|
||||
|
||||
void
|
||||
Config::xkbChanged( int index )
|
||||
Config::xkbChanged()
|
||||
{
|
||||
// Set Xorg keyboard layout + variant
|
||||
m_selectedVariant = m_keyboardVariantsModel->key( index );
|
||||
|
||||
if ( m_setxkbmapTimer.isActive() )
|
||||
{
|
||||
m_setxkbmapTimer.stop();
|
||||
@ -271,8 +287,15 @@ Config::xkbApply()
|
||||
|
||||
if ( !m_additionalLayoutInfo.additionalLayout.isEmpty() )
|
||||
{
|
||||
m_additionalLayoutInfo.groupSwitcher = xkbmap_query_grp_option();
|
||||
if ( !m_selectedGroup.isEmpty() )
|
||||
{
|
||||
m_additionalLayoutInfo.groupSwitcher = "grp:" + m_selectedGroup;
|
||||
}
|
||||
|
||||
if ( m_additionalLayoutInfo.groupSwitcher.isEmpty() )
|
||||
{
|
||||
m_additionalLayoutInfo.groupSwitcher = xkbmap_query_grp_option();
|
||||
}
|
||||
if ( m_additionalLayoutInfo.groupSwitcher.isEmpty() )
|
||||
{
|
||||
m_additionalLayoutInfo.groupSwitcher = "grp:alt_shift_toggle";
|
||||
@ -315,6 +338,12 @@ Config::keyboardVariants() const
|
||||
return m_keyboardVariantsModel;
|
||||
}
|
||||
|
||||
KeyboardGroupsModel*
|
||||
Config::keyboardGroups() const
|
||||
{
|
||||
return m_keyboardGroupsModel;
|
||||
}
|
||||
|
||||
static QPersistentModelIndex
|
||||
findLayout( const KeyboardLayoutModel* klm, const QString& currentLayout )
|
||||
{
|
||||
@ -647,7 +676,8 @@ Config::finalize()
|
||||
if ( !m_additionalLayoutInfo.additionalLayout.isEmpty() )
|
||||
{
|
||||
gs->insert( "keyboardAdditionalLayout", m_additionalLayoutInfo.additionalLayout );
|
||||
gs->insert( "keyboardAdditionalLayout", m_additionalLayoutInfo.additionalVariant );
|
||||
gs->insert( "keyboardAdditionalVariant", m_additionalLayoutInfo.additionalVariant );
|
||||
gs->insert( "keyboardGroupSwitcher", m_additionalLayoutInfo.groupSwitcher );
|
||||
gs->insert( "keyboardVConsoleKeymap", m_additionalLayoutInfo.vconsoleKeymap );
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class Config : public QObject
|
||||
Q_PROPERTY( KeyboardModelsModel* keyboardModelsModel READ keyboardModels CONSTANT FINAL )
|
||||
Q_PROPERTY( KeyboardLayoutModel* keyboardLayoutsModel READ keyboardLayouts CONSTANT FINAL )
|
||||
Q_PROPERTY( KeyboardVariantsModel* keyboardVariantsModel READ keyboardVariants CONSTANT FINAL )
|
||||
Q_PROPERTY( KeyboardGroupsModel* keyboardGroupsModel READ keyboardGroups CONSTANT FINAL )
|
||||
Q_PROPERTY( QString prettyStatus READ prettyStatus NOTIFY prettyStatusChanged FINAL )
|
||||
|
||||
public:
|
||||
@ -58,6 +59,9 @@ public:
|
||||
* (dvorak).
|
||||
*/
|
||||
KeyboardVariantsModel* keyboardVariants() const;
|
||||
/* A group describes a toggle groups of change layouts
|
||||
*/
|
||||
KeyboardGroupsModel* keyboardGroups() const;
|
||||
|
||||
/** @brief Call this to change application language
|
||||
*
|
||||
@ -87,7 +91,7 @@ private:
|
||||
* xkbChanged() is called when the selection changes, and triggers
|
||||
* a delayed call to xkbApply() which does the actual work.
|
||||
*/
|
||||
void xkbChanged( int index );
|
||||
void xkbChanged();
|
||||
void xkbApply();
|
||||
void locale1Apply();
|
||||
|
||||
@ -97,10 +101,12 @@ private:
|
||||
KeyboardModelsModel* m_keyboardModelsModel;
|
||||
KeyboardLayoutModel* m_keyboardLayoutsModel;
|
||||
KeyboardVariantsModel* m_keyboardVariantsModel;
|
||||
KeyboardGroupsModel* m_keyboardGroupsModel;
|
||||
|
||||
QString m_selectedLayout;
|
||||
QString m_selectedModel;
|
||||
QString m_selectedVariant;
|
||||
QString m_selectedGroup;
|
||||
|
||||
// Layout (and corresponding info) added if current one doesn't support ASCII (e.g. Russian or Japanese)
|
||||
AdditionalLayoutInfo m_additionalLayoutInfo;
|
||||
|
@ -823,3 +823,58 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/* This returns a reference to local, which is a terrible idea.
|
||||
* Good thing it's not meant to be compiled.
|
||||
*/
|
||||
class kb_groups : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
const QStringList& table()
|
||||
{
|
||||
return QStringList {
|
||||
tr("Alt+Caps Lock", "kb_group"),
|
||||
tr("Alt+Ctrl", "kb_group"),
|
||||
tr("Alt+Shift", "kb_group"),
|
||||
tr("Alt+Space", "kb_group"),
|
||||
tr("Any Win (while pressed)", "kb_group"),
|
||||
tr("Both Alts together", "kb_group"),
|
||||
tr("Both Alts together; AltGr alone chooses third level", "kb_group"),
|
||||
tr("Both Ctrls together", "kb_group"),
|
||||
tr("Both Shifts together", "kb_group"),
|
||||
tr("Caps Lock", "kb_group"),
|
||||
tr("Caps Lock (while pressed), Alt+Caps Lock for the original Caps Lock action", "kb_group"),
|
||||
tr("Caps Lock to first layout; Shift+Caps Lock to second layout", "kb_group"),
|
||||
tr("Ctrl+Left Win to first layout; Ctrl+Menu to second layout", "kb_group"),
|
||||
tr("Ctrl+Shift", "kb_group"),
|
||||
tr("Ctrl+Space", "kb_group"),
|
||||
tr("Left Alt", "kb_group"),
|
||||
tr("Left Alt (while pressed)", "kb_group"),
|
||||
tr("Left Alt+Left Shift", "kb_group"),
|
||||
tr("Left Ctrl", "kb_group"),
|
||||
tr("Left Ctrl to first layout; Right Ctrl to second layout", "kb_group"),
|
||||
tr("Left Ctrl+Left Shift", "kb_group"),
|
||||
tr("Left Ctrl+Left Win", "kb_group"),
|
||||
tr("Left Shift", "kb_group"),
|
||||
tr("Left Win", "kb_group"),
|
||||
tr("Left Win (while pressed)", "kb_group"),
|
||||
tr("Left Win to first layout; Right Win/Menu to second layout", "kb_group"),
|
||||
tr("Menu", "kb_group"),
|
||||
tr("Menu (while pressed), Shift+Menu for Menu", "kb_group"),
|
||||
tr("None", "kb_group"),
|
||||
tr("Right Alt", "kb_group"),
|
||||
tr("Right Alt (while pressed)", "kb_group"),
|
||||
tr("Right Alt+Right Shift", "kb_group"),
|
||||
tr("Right Ctrl", "kb_group"),
|
||||
tr("Right Ctrl (while pressed)", "kb_group"),
|
||||
tr("Right Ctrl+Right Shift", "kb_group"),
|
||||
tr("Right Shift", "kb_group"),
|
||||
tr("Right Win", "kb_group"),
|
||||
tr("Right Win (while pressed)", "kb_group"),
|
||||
tr("Scroll Lock", "kb_group"),
|
||||
tr("Shift+Caps Lock", "kb_group"),
|
||||
tr("Win+Space", "kb_group"),
|
||||
QString()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,3 +272,23 @@ KeyboardVariantsModel::setVariants( QMap< QString, QString > variants )
|
||||
m_currentIndex = -1;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
KeyboardGroupsModel::KeyboardGroupsModel( QObject* parent )
|
||||
: XKBListModel( parent )
|
||||
{
|
||||
m_contextname = "kb_groups";
|
||||
|
||||
// The groups map is from human-readable names (!) to xkb identifier
|
||||
const auto groups = KeyboardGlobal::getKeyboardGroups();
|
||||
m_list.reserve( groups.count() );
|
||||
int index = 0;
|
||||
for ( const auto& key : groups.keys() )
|
||||
{
|
||||
// So here *key* is the key in the map, which is the human-readable thing,
|
||||
// while the struct fields are xkb-id, and human-readable
|
||||
m_list << ModelInfo { groups[ key ], key };
|
||||
index++;
|
||||
}
|
||||
|
||||
cDebug() << "Loaded" << m_list.count() << "keyboard groups";
|
||||
}
|
||||
|
@ -154,6 +154,20 @@ public:
|
||||
void setVariants( QMap< QString, QString > variants );
|
||||
};
|
||||
|
||||
/** @brief A list of variants (xkb id and human-readable)
|
||||
*
|
||||
* The variants that are available depend on the Layout that is used,
|
||||
* so the `setVariants()` function can be used to update the variants
|
||||
* when the two models are related.
|
||||
*/
|
||||
class KeyboardGroupsModel : public XKBListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit KeyboardGroupsModel( QObject* parent = nullptr );
|
||||
};
|
||||
|
||||
/** @brief Adjust to changes in application language.
|
||||
*/
|
||||
void retranslateKeyboardModels();
|
||||
|
@ -68,6 +68,12 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent )
|
||||
ui->variantSelector->setCurrentIndex( model->index( model->currentIndex() ) );
|
||||
cDebug() << "Variants now total=" << model->rowCount() << "selected=" << model->currentIndex();
|
||||
}
|
||||
{
|
||||
auto* model = config->keyboardGroups();
|
||||
ui->groupSelector->setModel( model );
|
||||
ui->groupSelector->setCurrentIndex( model->currentIndex() );
|
||||
cDebug() << "Groups now total=" << model->rowCount() << "selected=" << model->currentIndex();
|
||||
}
|
||||
|
||||
connect( ui->buttonRestore,
|
||||
&QPushButton::clicked,
|
||||
@ -107,6 +113,16 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent )
|
||||
ui->variantSelector->setCurrentIndex( m_config->keyboardVariants()->index( index ) );
|
||||
m_keyboardPreview->setVariant( m_config->keyboardVariants()->key( index ) );
|
||||
} );
|
||||
|
||||
connect( ui->groupSelector,
|
||||
QOverload< int >::of( &QComboBox::currentIndexChanged ),
|
||||
config->keyboardGroups(),
|
||||
QOverload< int >::of( &XKBListModel::setCurrentIndex ) );
|
||||
connect( config->keyboardGroups(),
|
||||
&KeyboardGroupsModel::currentIndexChanged,
|
||||
ui->groupSelector,
|
||||
&QComboBox::setCurrentIndex );
|
||||
|
||||
CALAMARES_RETRANSLATE_SLOT( &KeyboardPage::retranslate );
|
||||
}
|
||||
|
||||
|
@ -117,6 +117,30 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Keyboard Switch:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="groupSelector">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="LE_TestKeyboard">
|
||||
<property name="font">
|
||||
@ -142,6 +166,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<tabstop>physicalModelSelector</tabstop>
|
||||
<tabstop>layoutSelector</tabstop>
|
||||
<tabstop>variantSelector</tabstop>
|
||||
<tabstop>groupSelector</tabstop>
|
||||
<tabstop>LE_TestKeyboard</tabstop>
|
||||
<tabstop>buttonRestore</tabstop>
|
||||
</tabstops>
|
||||
|
@ -199,6 +199,48 @@ parseKeyboardLayouts( const char* filepath )
|
||||
return layouts;
|
||||
}
|
||||
|
||||
static KeyboardGlobal::GroupsMap
|
||||
parseKeyboardGroups( const char* filepath )
|
||||
{
|
||||
KeyboardGlobal::GroupsMap models;
|
||||
|
||||
QFile fh( filepath );
|
||||
fh.open( QIODevice::ReadOnly );
|
||||
|
||||
if ( !fh.isOpen() )
|
||||
{
|
||||
cDebug() << "X11 Keyboard model definitions not found!";
|
||||
return models;
|
||||
}
|
||||
|
||||
bool modelsFound = findSection( fh, "! option" );
|
||||
// read the file until the end or until we break the loop
|
||||
while ( modelsFound && !fh.atEnd() )
|
||||
{
|
||||
QByteArray line = fh.readLine();
|
||||
|
||||
// check if we start a new section
|
||||
if ( line.startsWith( '!' ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// here we are in the model section, otherwise we would continue or break
|
||||
QRegExp rx;
|
||||
rx.setPattern( "^\\s+grp:(\\S+)\\s+(\\w.*)\n$" );
|
||||
|
||||
// insert into the model map
|
||||
if ( rx.indexIn( line ) != -1 )
|
||||
{
|
||||
QString modelDesc = rx.cap( 2 );
|
||||
QString model = rx.cap( 1 );
|
||||
models.insert( modelDesc, model );
|
||||
}
|
||||
}
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
|
||||
KeyboardGlobal::LayoutsMap
|
||||
KeyboardGlobal::getKeyboardLayouts()
|
||||
@ -212,3 +254,9 @@ KeyboardGlobal::getKeyboardModels()
|
||||
{
|
||||
return parseKeyboardModels( XKB_FILE );
|
||||
}
|
||||
|
||||
KeyboardGlobal::GroupsMap
|
||||
KeyboardGlobal::getKeyboardGroups()
|
||||
{
|
||||
return parseKeyboardGroups( XKB_FILE );
|
||||
}
|
||||
|
@ -30,9 +30,11 @@ public:
|
||||
|
||||
using LayoutsMap = QMap< QString, KeyboardInfo >;
|
||||
using ModelsMap = QMap< QString, QString >;
|
||||
using GroupsMap = QMap< QString, QString >;
|
||||
|
||||
static LayoutsMap getKeyboardLayouts();
|
||||
static ModelsMap getKeyboardModels();
|
||||
static GroupsMap getKeyboardGroups();
|
||||
};
|
||||
|
||||
#endif // KEYBOARDGLOBAL_H
|
||||
|
@ -15,14 +15,15 @@ Prints out a few tables of keyboard model, layout, variant names for
|
||||
use in translations.
|
||||
"""
|
||||
|
||||
def scrape_file(file, modelsset, layoutsset, variantsset):
|
||||
def scrape_file(file, modelsset, layoutsset, variantsset, groupsset):
|
||||
import re
|
||||
# These RE's match what is in keyboardglobal.cpp
|
||||
model_re = re.compile("^\\s+(\\S+)\\s+(\\w.*)\n$")
|
||||
layout_re = re.compile("^\\s+(\\S+)\\s+(\\w.*)\n$")
|
||||
variant_re = re.compile("^\\s+(\\S+)\\s+(\\S+): (\\w.*)\n$")
|
||||
group_re = re.compile("^\\s+grp:(\\S+)\\s+(\\w.*)\n$")
|
||||
|
||||
MODEL, LAYOUT, VARIANT = range(3)
|
||||
MODEL, LAYOUT, VARIANT, GROUP = range(4)
|
||||
state = None
|
||||
for line in file.readlines():
|
||||
# Handle changes in section
|
||||
@ -35,6 +36,9 @@ def scrape_file(file, modelsset, layoutsset, variantsset):
|
||||
elif line.startswith("! variant"):
|
||||
state = VARIANT
|
||||
continue
|
||||
elif line.startswith("! option"):
|
||||
state = GROUP
|
||||
continue
|
||||
elif not line.strip():
|
||||
state = None
|
||||
# Unchanged from last blank
|
||||
@ -53,6 +57,12 @@ def scrape_file(file, modelsset, layoutsset, variantsset):
|
||||
v = variant_re.match(line)
|
||||
name = v.groups()[2]
|
||||
variantsset.add(name)
|
||||
if state == GROUP:
|
||||
v = group_re.match(line)
|
||||
if v is None:
|
||||
continue
|
||||
name = v.groups()[1]
|
||||
groupsset.add(name)
|
||||
|
||||
|
||||
def write_set(file, label, set):
|
||||
@ -85,12 +95,15 @@ if __name__ == "__main__":
|
||||
models=set()
|
||||
layouts=set()
|
||||
variants=set()
|
||||
groups=set()
|
||||
variants.add( "Default" )
|
||||
groups.add( "None" )
|
||||
with open("/usr/local/share/X11/xkb/rules/base.lst", "r") as f:
|
||||
scrape_file(f, models, layouts, variants)
|
||||
scrape_file(f, models, layouts, variants, groups)
|
||||
with open("KeyboardData_p.cxxtr", "w") as f:
|
||||
f.write(cpp_header_comment)
|
||||
write_set(f, "kb_models", models)
|
||||
write_set(f, "kb_layouts", layouts)
|
||||
write_set(f, "kb_variants", variants)
|
||||
write_set(f, "kb_groups", groups)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user