terça-feira, 22 de janeiro de 2013
Threads
Deparei-me com uma discussão bastante interessante sobre o uso de thread. Achei por bem compartilhar o link:
http://extremeprogramming.wordpress.com/2011/12/19/o-que-voce-precisa-saber-sobre-threads-delphi/
É isto.
sábado, 15 de setembro de 2012
Utilizando o Corretor Ortográfico do Google
Recentemente tive a necessidade de implementar um corretor ortográfico em uma solução Delphi.
Pedi algumas indicações e me sugeriram:
http://www.devmedia.com.br/corretor-ortografico-no-delphi/2544
http://devexpress.com/Products/VCL/ExSpellChecker/
Não cheguei a testá-los mas foram muito bem recomendados.
Mas durante minhas pesquisas acabei me deparando com uma solução do Google.
Eu não tenho certeza, e se algum leitor for mais bem informado e puder fazer a gentileza de colocar as suas considerações nos comentários, mas o Google tem um recurso chamado Google Tool Bar Proxy e um dos recursos oferecidos é justamente o de correção ortográfica.
A URL do serviço é:
http://www.google.com/tbproxy/spell?lang=pt&hl=pt
Basicamente deve-se fazer um POST (HTTP) com um conteúdo XML e analisar o retorno.
Vamos imaginar então a palavra "coracao". O XML de requisição seria:
coracao
E uma resposta válida seria algo como:
coração
Indo ao ponto, desenvolvi o código abaixo devidamente comentado. É um projeto do tipo console.
É um ótimo exemplo pois tem uma pitada de XML e Expressão Regular.
Confesso que levei algumas boas horas para desenvolver este exemplo.
Me atrapalhei com o TXMLDocument e o UTF-8. Graças a este post de Caio Oliveira consegui resolver e me dei conta de um aparente bug. Achei estranho, mas de fato foi a solução.
Neste projeto foi desenvolvido a classe TCorretor onde efetivamente esta a solução.
program CorretorOrtografico;
{$APPTYPE CONSOLE}
{$R *.res}
uses System.SysUtils,
Xml.XMLDoc,
Xml.XMLIntf,
IdHTTP,
System.Classes,
WinApi.ActiveX,
System.RegularExpressions,
IdGlobal;
type
///
/// Implementa o recurso de correção ortográfica oferecido pelo Google
///
///
/// Descende de TComponent para servir de base para o XMLDocument
///
///
/// José Mário Silva Guedes - jmarioguedes@gmail.com - eugostododelphi.blogspot.com
///
TCorretor = class(TComponent)
private
///
/// Estrutura do documento XML
///
FXML: TXMLDocument;
///
/// Comunicação HTTP
///
FHTTP: TidHTTP;
public
procedure AfterConstruction; override;
///
/// Processa efetivamente o corretor ortográfico
///
/// /// Texto de entrada
/// /// /// Possibilidades de correção
/// /// /// Motivo de um eventual insucesso
/// ///
/// Indica o sucesso da operação
///
function Processar(AEntrada: string; ASaida: TStrings; AMotivo: string): Boolean;
end;
var
bRet : Boolean;
oCorretor: TCorretor;
sEntrada : string;
slSaida : TStringList;
sMotivo : string;
sPalavra : string;
cSaida : Char;
{ TCorretor }
procedure TCorretor.AfterConstruction;
begin
inherited;
Self.FHTTP := TidHTTP.Create(Self);
Self.FXML := TXMLDocument.Create(TDataModule.Create(Self));
end;
function TCorretor.Processar(AEntrada: string; ASaida: TStrings; AMotivo: string): Boolean;
const
C_URL = 'http://www.google.com/tbproxy/spell?lang=pt&hl=pt';
var
oRequest : TStringStream;
oResponse : TStringStream;
sResponse : string;
sRequest : string;
sResultado: string;
_raiz : IXMLNode;
_texto : IXMLNode;
_resultado: IXMLNode;
aPartes : TArray;
begin
oRequest := nil;
oResponse := nil;
try
{$REGION 'Preparando o pedido'}
Self.FXML.Active := False;
Self.FXML.Active := True;
Self.FXML.Version := '1.0';
Self.FXML.Encoding := 'UTF-16';
_raiz := Self.FXML.AddChild('spellrequest');
_raiz.Attributes['textalreadyclipped'] := '0';
_raiz.Attributes['ignoredups'] := '0';
_raiz.Attributes['ignoredigits'] := '1';
_raiz.Attributes['ignoreallcaps'] := '0';
_texto := Self.FXML.CreateNode('text');
_texto.Text := AEntrada;
_raiz.ChildNodes.Add(_texto);
{$ENDREGION}
{$REGION 'Gambiarra do UTF-8'}
Self.FXML.SaveToXML(sRequest);
// http://www.caiooliveira.com.br/?p=422
// http://qc.embarcadero.com/wc/qcmain.aspx?d=37433
sRequest := TRegEx.Replace(sRequest, 'UTF-16', 'UTF-8');
oRequest := TStringStream.Create;
oRequest.WriteString(sRequest);
oRequest.Seek(0, 0);
{$ENDREGION}
{$REGION 'Request\Response'}
Self.FHTTP.Request.Accept := 'text/xml';
Self.FHTTP.Request.ContentType := 'text/xml';
Self.FHTTP.Request.ContentEncoding := 'utf-8';
oResponse := TStringStream.Create;
Self.FHTTP.Post(C_URL, oRequest, oResponse);
sResponse := UTF8ToString(RawByteString(oResponse.DataString));
Self.FXML.Active := False;
Self.FXML.LoadFromXML(sResponse);
{$ENDREGION}
{$REGION 'Analisando a resposta'}
_resultado := Self.FXML.DocumentElement.ChildNodes.FindNode('c');
while (Assigned(_resultado)) do
begin
sResultado := _resultado.Text;
aPartes := TRegEx.Split(sResultado, #9);
for sResultado in aPartes do
begin
ASaida.Add(sResultado);
end;
_resultado := _resultado.NextSibling;
end;
Result := True;
{$ENDREGION}
finally
if (Assigned(oRequest)) then
begin
oRequest.Free;
end;
if (Assigned(oResponse)) then
begin
oResponse.Free;
end;
end;
end;
begin
oCorretor := nil;
slSaida := nil;
ReportMemoryLeaksOnShutdown := True;
CoInitialize(nil);
try
Writeln('/--------------------------------------------------------------\');
Writeln('| .:: DEMONSTRAÇÃO DE USO DO CORRETOR ORTOGRÁFICO GOOGLE ::. |');
Writeln('| jmarioguedes@gmail.com - http://eugostododelphi.blogspot.com |');
Writeln('\--------------------------------------------------------------/');
Writeln('');
Writeln('');
oCorretor := TCorretor.Create(nil);
slSaida := TStringList.Create;
repeat
write('Digite um texto: ');
Readln(sEntrada);
Writeln('');
slSaida.Clear;
bRet := oCorretor.Processar(sEntrada, slSaida, sMotivo);
if (bRet) then
begin
if (slSaida.Count > 0) then
begin
for sPalavra in slSaida do
begin
Writeln('-> ' + sPalavra);
end;
Writeln('');
end
else
begin
Writeln('Não houve resultados');
end;
end
else
begin
Writeln(Format('Insucesso na correção: ', [sMotivo]));
end;
Write('Tecle X para cancelar ou qualquer outra tecla para continuar: ');
ReadLn(cSaida);
until (CharInSet(cSaida, ['X', 'x']));
finally
if (Assigned(oCorretor)) then
begin
oCorretor.Free;
end;
if (Assigned(slSaida)) then
begin
slSaida.Free;
end;
Writeln('- Fim do Sistema - ');
Readln;
end;
end.
quarta-feira, 27 de junho de 2012
Livro de Delphi ... 2!
Navegando pelo pai Google encontrei-a de novo. Ou foi ele que me encontrou?
:)
http://www.greantoniobraga.seed.pr.gov.br/redeescola/escolas/13/870/10/arquivos/File/Adenildo/Biblia-Delphi-7-PtBr.pdf
sexta-feira, 22 de junho de 2012
Artigos sobre Expressão Regular
Durante este primeiro semestre de 2012 escrevi seis artigos sobre Expressão Regular na Active Delphi abordando desde os conceitos básicos até algumas questões mais avançadas.
Foi muito gratificante.
São as edições 95 à 100 (esta última ainda está para sair).
Foi desenvolvido um aplicativo que pode ser útil e que está sendo compartilhando através do link:
https://code.google.com/p/regex-in-delphi/
Se quiser, baixe diretamente do SVN: http://regex-in-delphi.googlecode.com/svn/trunk/
É isto.
sábado, 28 de abril de 2012
Delphi Meeting 2012
Link para a inscrição: http://www.edobrasil.net/delphimeeting/
Até lá!
sexta-feira, 16 de março de 2012
Instalação de um Servidor SVN
Eu uso o SVN a vários anos mas nunca configurei um servidor.
Mas sempre há a primeira vez e compartilho aqui, com você, a minha experiência.
Meu ponto de partida obviamente foi o Google e fiquei um pouco surpreso em perceber que o SVN tomou vários caminhos, forks e etc.
Não sei se estou falando alguma besteira mas é de fato um pouco confuso.
Tive que escolher um ponto inicial e o escolhido foi: http://subversion.apache.org/
Até onde entedi aqui é o lugar certo para iniciar.
Para o efetivo download cheguei neste link: http://subversion.apache.org/packages.html#windows
Dai veio o dilema. Qual escolher? Optei pelo projeto Win32SVN (Subversion for Windows).
O download desta distribuição pode ser feito em: http://alagazam.net/ onde optei pelo instalador MSI, disponível na seguinte URL:
http://sourceforge.net/projects/win32svn/files/1.7.2/Setup-Subversion-1.7.2.msi/download
Após a instalação temos que, manualmente, instalar o SVN como serviço do Windows. O comando para isto é:
sc create svn binpath= "\"c:\program files (x86)\Subversion\bin\svnserve.exe\" --service -r c:\Repositorio" displayname= "Servidor Subversion" depend= Tcpip start= auto
Importante: Execute o prompt de comando como Administrador e coloque um espaço entre o sinal de igual e o valor.
Vamos ao client. O Delphi XE2 dá suporte à interação direta com o SVN. Mas vou continuar usando o Tortoise por enquanto.
O download pode ser feito em: http://tortoisesvn.net/downloads.html
Um post que achei bem completo está em: http://moisesfontana.blogspot.com/2007/09/instalar-e-configurar-um-servidor.html
É isto,
terça-feira, 21 de fevereiro de 2012
Trabalhando com Atributos (Custom Attributes)
Antes de mais nada quero esclarecer que não estou me referindo aos atributos de uma classe e sim de um conceito novo (Delphi 2010) mas já existente em outras plataformas de desenvolvimento.
Do que NÃO estamos falando:
TPessoa = class
private
FNome: string;
FIdade: Integer; {<== Isto é um atributo de uma classe e NÃO é disto que estamos falando}
public
property Nome: string read FNome write FNome;
property Idade: Integer read FIdade write FIdade;
end;
Do que estamos falando:
TPessoa = class
private
FNome: string;
public
property Nome: string read FNome write FNome;
[TIdadeMinima(21)] {<== É disto que estamos falando!}
property Idade: Byte read FIdade write FIdade;
end;
Mas o que significa atributo?
No dicionário:
S. m. 1. Aquilo que é próprio de um ser. 2. Emblema distintivo; símbolo. 3. Característica, qualitativa ou quantitativa, que identifica um membro de um conjunto observado. ...
Ou seja, atributo é, basicamente, uma qualidade atribuída a um elemento.
Usando no Delphi
O uso mais recorrente é em frameworks ORM. Mas as possibilidades são muitos mais amplas que isso. Poderíamos utilizar esta facilidade para atender regras de formatação de um documento eletrônico, como por exemplo o EFD Pis/Cofins ou um protocolo de comunicação com algum equipamento.
Então, indo ao ponto, os atributos são classes descendentes de TCustomAttribute. O TCustomAttribute por sua vez não implementa nada de especial.
Seguindo o nosso exemplo inicial, o atributo TIdadeMinima seria declarado da seguinte maneira:
TIdadeMinima= class(TCustomAttribute)
private
FIdadeMinima: Byte;
public
constructor Create(AIdadeMinima: Byte);
function IsIdadeMaior(AIdade: Byte): Boolean;
property IdadeMinima: Byte read FIdadeMinima;
end;
//Implementação//
{ TIdadeMinima }
constructor TIdadeMinima.Create(AIdadeMinima: Byte);
begin
Self.FIdadeMinima := AIdadeMinima;
end;
function TIdadeMinima.IsIdadeMaior(AIdade: Byte): Boolean;
begin
Result := AIdade >= Self.FIdadeMinima;
end;
No que devemos focar?
O construtor da classe deve solicitar os parâmetros que fazem parte do escopo do atributo. No exemplo, o atributo está especificando uma idade mínima para a instância de TPessoa. Portanto o constructor do atributo pede justamente a idade mínima.
Para efetivamente tiramos proveito do atributo temos que recorrer à RTTI, pois só com ela temos acesso a um atributo. No exemplo abaixo, temos o código completo de um programa console, que pede o nome e a idade do usuário e valida a idade.
program UsandoAtributos;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, Rtti;
type
TIdadeMinima= class(TCustomAttribute)
private
FIdadeMinima: Byte;
public
constructor Create(AIdadeMinima: Byte);
function IsIdadeMaior(AIdade: Byte): Boolean;
property IdadeMinima: Byte read FIdadeMinima;
end;
TPessoa = class
private
FNome: string;
FIdade: Byte;
public
property Nome: string read FNome write FNome;
[TIdadeMinima(21)]
property Idade: Byte read FIdade write FIdade;
end;
{ TIdadeMinima }
constructor TIdadeMinima.Create(AIdadeMinima: Byte);
begin
Self.FIdadeMinima := AIdadeMinima;
end;
function TIdadeMinima.IsIdadeMaior(AIdade: Byte): Boolean;
begin
Result := AIdade >= Self.FIdadeMinima;
end;
var
oPessoa : TPessoa;
sNome : string;
bIdade : Byte;
_ctx : TRttiContext;
_typ : TRttiType;
_pro : TRttiProperty;
oAtt : TCustomAttribute;
begin
Writeln('****************************');
Writeln('*** Bem vindo ao sistema ***');
Writeln('****************************');
Writeln(EmptyStr);
oPessoa := nil;
try
oPessoa := TPessoa.Create;
Write('Digite o seu nome: ');
Readln(sNome);
oPessoa.Nome := sNome;
Write('Digite a sua idade: ');
Readln(bIdade);
oPessoa.Idade := bIdade;
Writeln(EmptyStr);
Writeln('Dados');
Writeln(oPessoa.Nome,' - ',oPessoa.Idade);
_ctx := TRttiContext.Create;
_typ := _ctx.GetType(oPessoa.ClassType);
for _pro in _typ.GetProperties do
begin
for oAtt in _pro.GetAttributes do
begin
if oAtt is TIdadeMinima then
begin
Writeln('A idade mínima é de: ',TIdadeMinima(oAtt).IdadeMinima);
if (TIdadeMinima(oAtt).IsIdadeMaior(oPessoa.Idade)) then
begin
Writeln('A idade de ',oPessoa.Nome,' passou!');
end else
begin
Writeln('A idade de ',oPessoa.Nome,' nao passou!');
end;
end;
end;
end;
finally
if (Assigned(oPessoa)) then
begin
oPessoa.Free;
end;
_ctx.Free;
end;
Writeln(EmptyStr);
Writeln('Tecle [ENTER] para encerrar');
Readln;
end.
Vale ressaltar que os atributos podem ser atribuídos a qualquer elemento da sua classe. É o seu código RTTI que terá que ser moldado para tirar proveito delas. Outro ponto importante é que um elemento pode ter vários atributos.
Uso prático
Como mencionei no decorrer, muitos exemplos sobre este tema esta ligado diretamente com a ORM, onde um atributo para a classe indica uma tabela enquanto que alguns atributos para as propriedades seriam os campos e as constraints.
Mas no meu caso, onde precisei gerar um documento eletrônico (EFD Pis/Cofins) baseado em regras, eu criei uma classe base e para cada tipo de registro criei uma classe descendente com os campos e, principalmente, seus atributos: tamanho, tamanho exato, se somente números etc e etc. Por fim, na tal classe base, foi disponibilizado um método chamado GetLine que tanto valida as informações da classe quanto gera a linha correspondente. Esta solução foi ótima pois o código ficou mais limpo e tenho certeza que mudanças ou implementações futuras será muito tranquilas.
Também poderíamos usar para implementar uma validação em uma tela de entrada, afinal, o TForm é uma classe como qualquer outra. Este seria um ótimo uso.
É isto.
Minha lista de blogs
-
Um pouquim da net - Linux, Facebook, Internet, Android, etc.Há uma hora
-
-
HTML5 BuilderHá 5 horas
-
Pós em Engenharia de SoftwareHá 14 horas
-
PaciênciaHá um dia
-
-
-
Links úteis - SaúdeHá 3 dias
-
-
Virada Hacker 2013Há 3 dias
-
-
Lançamento do Audiobook - O Homem que ChoviaHá uma semana
-
fdasfasfHá uma semana
-
-
-
-
-
-
Saiba tudo sobre a nova versão: Delphi XE4Há 3 semanas
-
-
O que há de novo no Delphi XE4Há 3 semanas
-
-
-
-
-
-
-
-
-
-
Teste seu conhecimento #18Há um mês
-
-
Águas de Março (versão TI)Há 2 meses
-
-
-
Legacy Code: ScopingHá 3 meses
-
PHP MailHá 3 meses
-
-
-
Generic array sliceHá 4 meses
-
-
-
-
Cartas Náuticas no AndroidHá 9 meses
-
-
Medidas de desempenho (Comandos)Há 9 meses
-
Novo endereçoHá 10 meses
-
-
Sugestões de PostsHá 11 meses
-
The Developers Conference 2012Há 11 meses
-
-
-
wpd-banner-180x150Há um ano
-
-
-
-
-
Oxygene for JavaHá um ano
-
TESTANDO O BLOGHá um ano
-
-
-
-
-
-
-
-
Mudança de Endereço morfikBRHá um ano
-
-
-
-
-
Exibindo HTML em um .RDLHá 2 anos
-
Vídeo aula disponívelHá 2 anos
-
-
-
-
Novo BlogHá 2 anos
-
-
Manifesto em sambaHá 2 anos
-
MySQL WorkbenchHá 2 anos
-
-
-
ErrorManager - MicroframeworkHá 3 anos
-
-
Windows 7 Components - SorryHá 3 anos
-
-
-
Destaques do diaHá 4 anos
-
-
