2013-08-12 6 views
0

Comment utiliser la fonction d'annulation/de rétablissement intégrée de QLineEdit lors de la mise en œuvre de la logique d'entrée personnalisée?Comment implémenter l'annulation dans un héritier QLineEdit?

Je suis en train de mettre en œuvre un éditeur personnalisé pour les montants d'argent pour le travail efficace d'un caissier. Les caractéristiques de base sont:

  • Le format est toujours ^\d+,\d{2}$;
  • Lorsque le curseur est laissé à la virgule, il modifie la partie entière (par exemple, lorsque 0,00 est édité, la première entrée de chiffre remplace le zéro, c'est-à-dire 0,00 devient 1,00 après la saisie de '1');
  • Une virgule ou une période entrée déplace le curseur sur la partie décimale;
  • Les suppressions et les espaces de retour respectent le format.

Je ne peux pas utiliser de masques car ils ne peuvent pas gérer une longueur arbitraire sans espaces inutiles. Je ne peux pas utiliser de validateurs car ils ne sont pas assez flexibles pour gérer la logique d'édition menant à zéro en place. C'est pourquoi j'ai sous-traité QLineEdit et j'ai écrit moi-même la logique nécessaire.

La question est: existe-t-il un moyen de prendre en charge la fonctionnalité d'annulation de la propre logique de QLineEdit? J'utilise setText(), qui réinitialise l'historique d'annulation/rétablissement. Je pourrais faire deux piles d'états et écraser undo() et redo() en conséquence, ou faire des séquences de sélections et d'insertions/suppressions (ce qui peut causer des clignotements inutiles), mais je pense qu'il pourrait y avoir un moyen encore plus simple.

class MoneyLineEdit : public QLineEdit { 
    Q_OBJECT 
public: 
    MoneyLineEdit(QWidget *parent = 0); 

protected: 
    void keyPressEvent(QKeyEvent * event); 
}; 

void MoneyLineEdit::keyPressEvent(QKeyEvent *event) { 
    if (event->key() == Qt::Key_Comma || event->key() == Qt::Key_Period) { 
     setCursorPosition(text().length() - 2); 
    } else { 
     QString text = this->text(); 
     int pos = cursorPosition(); 
     if (event->key() == Qt::Key_Backspace) { 
      if (pos == text.length()) { 
       text.replace(text.length() - 1, 1, QChar('0')); 
       --pos; 
      } else if (pos == text.length() - 1) { 
       text.replace(text.length() - 2, 1, text.at(text.length() - 1)); 
       text.replace(text.length() - 1, 1, QChar('0')); 
       --pos; 
      } else if (pos == text.length() - 2) { 
       --pos; 
      } else if (text.length() == 4 && pos == 1) { 
       text.replace(0, 1, QChar('0')); 
      } 
      setText(text); 
      setCursorPosition(pos); 
     } else if ((pos == text.length() - 3 || pos == text.length() - 2) && event->key() == Qt::Key_Delete && selectionStart() == -1){ 
      text.replace(text.length() - 2, 1, text.at(text.length() - 1)); 
      text.replace(text.length() - 1, 1, QChar('0')); 
      setText(text); 
      setCursorPosition(pos); 
     } else if (pos >= text.length() - 2 && pos <= text.length() - 1 && !event->text().isEmpty()){ 
      text.replace(cursorPosition(), 1, event->text()); 
      ++pos; 
      setText(text); 
      setCursorPosition(pos); 
     } else if ((pos == 0 || pos == 1) && !text.isEmpty() && text.length() == 4 && text.at(0) == QChar('0') && !event->text().isEmpty()) { 
      text.replace(0, 1, event->text()); 
      setText(text); 
      setCursorPosition(1); 
     } else { 
      QLineEdit::keyPressEvent(event); 
     } 
    } 
} 

Répondre

0

De toute évidence, deux piles de paire (texte, cursorPosition) pour undo()/redo() surchargé suffisent.

Questions connexes