Pour permettre de saisir du japonais [1] sous un dialogue Qt [2], j’ai trouvé une solution à base de QInputContextFactory, classe donnant accès aux méthodes d’entrée [3] disponibles.
Et tant qu’à faire j’ai mis un menu contextuel dans la zone de saisie pour changer de méthode de saisie.
Conventions :
widget est la zone de saisie sur laquelle on veut permettre la saisie en japonais
MyDialog est la classe de dialogue qui contient widget
Le dialogue doit avoir les slots suivants :
class MyDialog : public QDialog
{
...
protected slots:
void onWidgetContextMenu(const QPoint& pos);
void onInputContextChange(QAction* action);
}Quand on construit le dialogue et ses zones de saisie, il faut rajouter les lignes suivantes (dans une fonction de MyDialog :
widget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(widget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onWidgetContextMenu(const QPoint&)));L’implémentation du menu contextuel, affichant la liste des méthodes d’entrée, est assez simple :
void MyDialog::onWidgetContextMenu(const QPoint& pos)
{
QWidget* edit = getMyCurrentWidget(); /** à nous de savoir quelle zone est concernée */
QMenu popup(tr("Propriétés"));
QMenu* context = popup.addMenu(tr("Méthode d'entrée"));
QAction* def = context->addAction(tr("(défaut: %1)").arg(QInputContextFactory::displayName(qApp->inputContext()->identifierName())));
def->setCheckable(true);
if (edit->inputContext()->identifierName() == qApp->inputContext()->identifierName())
{
def->setChecked(true);
}
foreach(QString key, QInputContextFactory::keys())
{
if (key == qApp->inputContext()->identifierName())
continue;
QAction* action = context->addAction(QInputContextFactory::displayName(key));
action->setCheckable(true);
action->setData(key);
if (edit->inputContext()->identifierName() == key)
{
action->setChecked(true);
}
}
connect(&popup, SIGNAL(triggered(QAction*)), this, SLOT(onInputContextChange(QAction*)));
popup.exec(edit->mapToGlobal(pos));
}Et enfin la gestion du changement de méthode d’entrée n’a plus grand-chose à faire :
void MyDialog::onInputContextChange(QAction* action)
{
QString input = action->data().toString();
QWidget* edit = getMyCurrentWidget();
if (edit->inputContext()->identifierName() == input || (input.isEmpty() && edit->inputContext()->identifierName() == qApp->inputContext()->identifierName()))
// pas la peine de changer pour rien
return;
if (input.isEmpty())
{
edit->setInputContext(QInputContextFactory::create(qApp->inputContext()->identifierName(), edit));
}
else
{
QInputContext* context = QInputContextFactory::create(input, edit);
if (context)
edit->setInputContext(context);
}
// pour une raison inconnue, il y a des problèmes de saisie, en solution de contournement on joue avec le focus
edit->nextInFocusChain()->setFocus();
edit->setFocus();
}Et voici le résultat :
