Tutorial Qt -Capitulo 09 – Validação de entrada de dados

Todos os softwares precisam de uma entrada adequada para serem capazes de produzir um resultado adequado. Por esse motivo precisamos verificar todos os dados que nossa aplicação recebe de fontes não-confiáveis (como usuários, outros softwares, arquivos, etc). Esse processo é chamado de validação de entrada de dados.

Existe ainda um outra razão: segurança. Muitos sistemas de hoje suportam scripts e, por exemplo, pegam a entrada do usuário e colocam em consultas SQL em banco de dados centrais. Aqui é importante proteger o sistema de injeções de scripts e tal.

Como a entrada pode ser validade? Algumas coisas são fáceis de validar, como números que consistem de caracteres entre 0 e 9 e talvez os sinais + – . e/E se desejamos permitir valores em notação científica e valores reais. Outros dados como endereços de e-mail, URLs, são mais difíceis de checar, mas ainda sendo um padrão, mesmo assim é complexo. Quando lidamos com a linguagem humana, esses padrões são tão variados e complexos que não podem ser expressos como um programa de computador – tente usar a checagem gramatical do processador de texto para ver quão estúpido ele é. Nesses casos, podemos ao menos tentar algumas validações como garantir que os dados não contenham caracteres ilegais.

Todos esses casos podem ser executados usando expressões regulares, ou regexps, ou mesmo REs. Quando estiver escrevendo uma expressão regular, você estará escrevendo o padrão no qual a entrada deve concordar.
Antes que possamos ver qualquer coisa desse capitulo existem algumas poucas coisas que devem ser observadas. Primeiro, existem muitos dialetos de expressões regulares, todas elas funcionam quase da mesma forma, mas diferem em alguns detalhes. Esse capitulo trabalha com a implementação do Qt. Em segundo lugar, expressões regulares podem ser usadas em muitos contextos, por exemplo separando a entrada em pedaços menores. Essa capitulo lida apenas com a validação de dados. Em último lugar, esse capitulo cobrirá apenas a parte básica e apenas arranha a superfície do assunto. Para mais assunto, dê uma olhada nos links no final desse capitulo.

A expressão regular mais simples possível é um único caractere, por exemplo, A. Essa expressão regular irá coincidir qualquer string que contenha a letra A. O A não tem que estar em uma posição particular da string, mas tem que haver pelo menos um A.

Com um único caractere a expressão regular é bastante limitada, então podemos coincidir mais caracteres. Para permitir isso, simplesmente coloque um grupo deles em volta de chaves. A expressão ergular [ABC] irá coincidir qualquer string que contenha A, B ou C. Como no caso com um único caractere, apenas é preciso um e podemos ter mais de um. Para evitar de ter que escrever o alfabeto inteiro para permitir todas as letras, ou [0123456789] para permitir qualquer número, existem as faixas de caracteres especiais, como [A-Z[ (letras maisuculas), [a-z] (letras minusculas) e [0-9] (numeros).

Existem três pontos importantes a entender para ser capaz de usar expressões regulares para coincidir mais casos da entrada.
Primeiro, colocando muitos caracteres únicos ou caracteres agrupados juntos, forçamos a coincidência nessa ordem. Por exemplo [ABC][123]a coincide A1a, xB3a, ycC1ax mas não x1Aay, ya1A nem a. Usando mail pega mailbox, junkmail, email, etc.

Em segundo lugar, podemos coincidir o inicio de uma string com ^ e o final com $. Isso significa que ^[ABC][123]$ coincide apenas com A1, A2, A3, B1, B2, B3, C1, C2 e C3. Como coincidimos o início e fim da string, nada mais é permitido antes ou depois da expressão regular.

Em terceiro lugar, podemos controlar a quantidade de aparições que permitimos de cada caractere ou grupo de caractere. Assim, [A-Z]{0,15} coincide com 15 letras maiúsculas, [0-9]{1,3} coincide com todos os valores entre 0 e 999.

Ao invés de colocar {limite inferior, limite superior} é possível o uso da versão {contagem exata} ou omitir tanto o limite inferior quanto o superior (e assim fazer eles serem ignorados pelo QRegExp). Também é possível escrever, por exemplo, [0-9]+. Isso coincide um ou mais dígitos. [0-9]* coincide zero ou mais dígitos enquanto [0-9]? coincide zero ou um dígito.
Colocando um ^ como primeiro caractere dentro de um grupo nós negamos o efeito. Por exemplo, [^0-9]$  garante que o último caractere da string não seja um número.

Existem mais dois caracteres que são usados. O primeiro é o “-“, que precisa ser o último em um grupo  senão será interpretado como um grupo de caracteres (como a-z). Depois existe o espaço, que precisa estar no final de um grupo (mas antes do traço).

Vamos partir para o desenvolvimento de um novo padrão de número serial. O número é formatado assim: Um caractere W, S ou G especifica a série do produto (workstation, server ou gaming), um número de quatro dígitos em seguida, depois uma barra e dois dígitos numéricos seguido por um traço e um número. W1003/01-26 e G9900/03-801 são exemplos válidos. Assim, primeiro nós coincidimos o início da string usando um ^, depois coincidimos W, S ou G com [WSG]. Os quatro números são fáceis de coincidir: [0-9]{4}, assim como a barra (observe que uma barra invertida é um caractere especial). Os dois dígitos numéricos e o traço são fáceis também: [0-9]{2}-. O último número é coincidido com [0-9]+. Depois simplesmente coincidimos o final da string usando $. A expressão regular final seria ^[SWG][0-9]{4}/[0-9]{2}-[0-9]+$.

O RegExpExperiment

Para tornar fácil desenvolver e testar expressões regulares esse capitulo inclui  uma aplicação de teste bem trivial chamada RegExp Experiment. A implementação dela é descrita abaixo.

A aplicação consiste de uma caixa de diálogo como linedits, uma para o texto a ser coincidido e outra para a expressão regular. O resultado será mostrado e haverá dois botões: check e close. Assim, vamos adiante.
Primeiro: cire uma nova pasta e nessa pasta, crie um novo projeto do QtDesigner.

Adicione uma caixa de diálogo ao novo projeto e coloque 2 botões, 2 lineedits, 4 labels e 2 spacers como mostrado na figura abaixo. A figura também mostra os layouts. Os widgets da parte de cima são colocados em um layout de grid.  OS botões e os spacers horizontais em um layout horizontal. Finalmente, o  que sobra é colocado em um layout vertical.

The Widgets and the Layout
The Widgets and the Layout

Agora, altere os textos de acordo com a próxima figura. Nomeie a lineedit do topo como leText e a outra como leRE. O botão da esquerda é chamado bCheck e o que fica a direita bClose. O label abaixo dos linedits é chamado lResult. Além desses, nomeie a caixa de dialogo como fRegExpExperiment e ajuste o titulo dela. Salve tudo como fregexpexperiment.ui.

The Captions
The Captions

Agora dê um clique duplo no formulário para criar fregexpexperiment.ui.h. Adicione dois slots protegidos: init() e check() (usando o object explorer). Ligue os singnals aos slots como mostrado abaixo:

The Connections
The Connections

O exemplo abaixo mostra a implementação dos dois slots. init() inicializa lResult para não mostrar nenhum texto estranho enquanto check() usa o QRegExp para tentar coincidir a expressão regular com o texto. Certifique-se de incluir <qregexp.h> na implementação da caixa de diálogo.


void fRegExpExperiment::init()
{
lResult->setText( "n/a" );
}

void fRegExpExperiment::check()
{
QRegExp re( leRE->text() );


lResult->setText( QString::number( re.search( leText->text() ) ) );
}

O método QRegExp::search(…) retornará a primeira posição onde a expressão regular é encontrada, ou -1 se não puder ser encontrada. Quando coincidindo com o início da string o valor deve ser 0 ou -1, senão pode ser >=0 se coincide.

Para completar o projeto, adicione um arquivo de código fonte C++  e implemente o main() abaixo:


#include <qapplication.h>

#include "fregexpexperiment.h"
int main( int argc, char **argv )
{
QApplication a( argc, argv );


fRegExpExperiment *m = new fRegExpExperiment();
a.setMainWidget( m );
m->show();


 
return a.exec();
}

Finalmente, execute “qmake && make” no terminal e tudo deve funcionar. Agora experimente com as expressões regulares da primeira seção desse capitulo.

Validando a entrada do usuário com QValidator

Agora sabemos como coincidir expressões regulares e como criar uma. Precisamos agora aplicar isso em nossos projetos Qt sem muito trabalho. Isso é feito usando métodos derivados de QValidator como QRegExpValidator e QDoubleValidator.

Um validador pode ser associado a lineedits, comboboxes, spinboxes, etc. Quando associados, valida a entrada e classifica-a como válida, corrigível ou inválida. Se a entrada é inválida o usuário precisa corrigir ela antes que possa deixar o widget. Se for corrigível, o usuário pode corrigir ou  o validador corrigirá quando o usuário pressiona Enter. Nenhuma ação é necessária para dados válidos. O exemplo abaixo mostra como associas nossa expressão regular para o número serial a uma lineedit usando QRegExpValidator.


QRegExp re( "^[SWG][0-9]{4}/[0-9]{2}-[0-9]+$" );
QRegExpValidator *validator = new QRegExpValidator( re, 0 );


QLineEdit *leSN = new QLineEdit( parent );
leSN->setValidator( validator );

Os validadores QIntValidator e QDoubleValidator estão disponíveis para checar se a entrada é um número válido e se está dentro de uma faixa válida. Se não puder validar sua entrada usando alguns desses validadores, é bem simples criar um. Existe uma descrição detalhada de como fazer isso na documentação oficial do QValidator.

Existe ainda um último detalhe a notar. Quando estiver usando setText para alterar o texto, por exemplo, de uma linedit, o validador não é usado. Essa entrada precisa ser validada manualmente para garantir que esteja correta.

Sumário

O código fonte desse capitulo pode ser baixado aqui ex10.tar
Traduzido de http://www.digitalfanatics.org/projects/qt_tutorial/chapter10.html