Mon p’tit coin du web
Accueil du site > Code > Méthodes d’entrée sous Qt

Méthodes d’entrée sous Qt

dimanche 4 janvier 2009, par Nicolas

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 :

Notes

[1] En pratique, cette solution permettra de saisir n’importe quelle langue pourvu que le support soit disponible sur le système.

[2] J’utilise la version 4.4.2 sous Linux, mais j’imagine que ce n’est pas trop différent pour les autres versions.

[3] Sous Linux, une « méthode d’entrée » est une façon d’entrer du texte. Pour de l’alphabet romain, il n’y a rien de spécial à faire, mais pour entrer des kanjis, il faut pouvoir par exemple entrer la phonétique et choisir les caractères voulus.

Répondre à cet article

SPIP | squelette | | Plan du site | Suivre la vie du site RSS 2.0