terça-feira, 30 de setembro de 2008

Nova arma contra phishing: Língua Portuguesa...

.
O pessoal que faz phishing pode até saber muito de computação, mas de língua portuguesa...

Recebi dois desses emails hoje. Vejam que pérolas:

... acredito que a verdade tem que vim (!?!) em primeiro lugar ...

... eu tava perto e consigui (argh!) fotos através de meu celular ...

... Estou mandando as fotos anexada (!!!) quero ...

Tragetoria (aff!!) de Osama Bin Laden Chega ao Fim!!!

Dá até vergonha....

Abraços!
Carlão

segunda-feira, 22 de setembro de 2008

Dica para programadores GTK: DevHelp

.
Na atividade de programação usando GTK (e qualquer outra biblioteca) é necessário uma constante consulta à documentação da API, seja na busca por um método que faça o que precisamos, seja para conferir os tipos dos parâmetros ou do valor retornado.

No caso da biblioteca GTK (e suas bibliotecas parceiras), podemos baixar um pacotão com a documentação, ou consultar online em http://library.gnome.org/devel/references.

Descobri ontem uma outra forma, offline, proporcionada pelo programa DevHelp. Instalável sem dores-de-cabeça pelo seu gerenciador de pacotes, fornece, no caso da GTK, a mesma documentação disponível online.

Para utilizá-lo, não basta instalar apenas o DevHelp. Você precisa também instalar os pacotes de documentação das bibliotecas que você vai usar. No meu caso (Ubuntu), esses pacotes terminam com "-doc" (cheque o nome correto na sua distribuição, em especial se ela não for debian-based), como por exemplo:

libatk1.0-doc
libcairo2-doc
libglib2.0-doc
libgnomecanvas2-doc
libgnomeui-doc
libgtk2.0-doc
libpango1.0-doc


Abraços!
Carlão

sábado, 20 de setembro de 2008

Roteiro para criação de uma janela no GLADE

.
Continuo ralando aqui com o GLADE. Depois de muitas cabeçadas e quase desistência, começei a gostar do bichinho. Talvez o grande problema seja a falta de um roteiro passo-a-passo, pois por mais que se leia sobre os widgets, em especial os que gerenciam o layout (vbox, hbox, table, etc.), e sobre suas propriedades, é difícil visualizar claramente qual será o efeito final.

Tentando "começar" a preencher essa lacuna, apresento este passo-a-passo. O objetivo é criar a seguinte tela:


Vou listar então todos os passos que executei para construir esta tela. O objetivo aqui é que alguém refaça esses passos e com isso possa ter um exemplo das alterações no visual causadas por cada widget ou propriedade manipulada. Ressalto ainda que muitas das escolhas que fiz nessa construção foram baseadas no meu "senso" estético, e devem ser entendidas apenas como sugestões. Como de costume, sugestões e principalmente correções são extremamente bemvindas.

Como este roteiro usa e abusa de identação, para mostrar a hierarquia entre widgets (quem vai dentro de quem, a que widget pertence tal propriedade, etc), resolvi não colocar direto aqui no post, mas sim disponibilizar um arquivo texto.

Lá pelo meio do roteiro, tem uma referência a uma figura. É esta aqui:


Gostaria de aproveitar este momento para registrar um grande agradecimento ao Bruno Boaventura, que tem me ajudado muitíssimo em diversos aspectos da programação com GTK.

Grande abraço a todas e a todos!
Carlão

sexta-feira, 19 de setembro de 2008

Como preencher uma GtkComboBox criada no GLADE

.
Penei com isso ontem um tempão. A GTK tem a função gtk_combo_box_append_text() (entre outras) com o objetivo de facilitar a criação de drop-downs de texto. Porém para usar esta função, o drop-down (GtkComboBox) tem que ter sido criado via gtk_combo_box_new_text() , o que parece não ser o caso dos drop-downs criados via Glade. Na net, encontrei muita referência disso para outras linguagens (PHP por exemplo), mas nada para o velho e bom C... Felizmente, após muita procura, encontrei um pedaço de código que resolveu meu problema. Coloco ele aqui, comentado, na esperança de ajudar outros "desesperados" como eu ... :-)

Em linhas gerais, você precisa criar uma GtkListStore, para armazenar a lista de itens que vai aparecer no drop-down. Depois, associe esta lista ao drop-down, e finalmente defina COMO esta lista vai aparecer na tela ("ser renderizada"). UFA! Bem que podia ter uma opção no GLADE para escolher como o drop-down vai ser criado na hora do uso, se via gtk_combo_box_new_text para simples drop-downs de texto, ou da forma default, para drop-downs mais elaboradas.

No código abaixo, a variável "drop_bds" é um GtkWidget*, e contém minha drop-down (GtkComboBox).

[ OBS!! Sugiro que você copie o programa abaixo e cole em um editor de texto-puro, para melhor visualização da identação e dos comentários linha-a-linha. Não sei como colocar aquela janelinha de código que se encontra em blogs por aí, se alguém puder me ajudar, agradeço! ]

// um GtkComboBox implementa a GtkCellLayout. O comando abaixo apaga este layout.
// Precisei fazer isso porque o conteúdo do meu drop-down é o resultado do click em um botão.
// Se eu não apagar o layout logo no início, cada vez que aperto o botão o drop-down vai
// crescendo, pois vai mantendo o layout anterior e adicionando o novo.

gtk_cell_layout_clear(GTK_CELL_LAYOUT(drop_bds));


// outras variaveis necessarias:

// inteiro, para ir contando os elementos que vamos inserir no drop-down
int cont;

// a GtkListStore que vai armazenar os elementos do drop-down
GtkListStore *list_store;

// o "renderizador" que vai mostrar o conteúdo da lista dentro do drop-down
GtkCellRenderer *renderer;

// um iterador, uma espécie de ponteiro que indica em que lugar da lista
// vamos inserir o novo conteúdo
GtkTreeIter iter;


// cria a GtkListStore, com apenas 1 coluna, conteúdo do tipo string
list_store = gtk_list_store_new (1, G_TYPE_STRING);


// laço que vai preencher a lista com as strings que vão compor o drop-down:

for(cont=0; cont < ...numero de elementos a inserir... ; cont++)
{

// string que vai armazenar o texto a ser inserido no drop-down
char conteudo[50];

// defina o conteudo da string acima
// no meu caso, a string seria uma combinacao de outras strings e outros dados,
// provenientes de outras partes do programa. Optei por usar a função sprintf para
// "montar" essa string. Veja o que é melhor no seu caso!

sprintf(conteudo, "%s", ...o conteudo que voce quer na string... );


// Adiciona uma linha ( VAZIA! ) na lista (list_store), e faz o iterador (variável iter)
// apontar para ela, para que depois possamos "encher" essa linha vazia de conteúdo

gtk_list_store_append (list_store, &iter);

// armazena um valor na lista, na linha apontada por iter, nas colunas indicadas.
// A lista de colunas termina com um -1. Como só tenho 1 coluna na minha lista, fica:
// 0 (primeira e única coluna) , conteudo (a string a inserir nessa linha) , -1 (fim!)

gtk_list_store_set (list_store, &iter, 0, conteudo, -1);
}


// insere a lista que acabamos de montar dentro do drop-down:
gtk_combo_box_set_model(GTK_COMBO_BOX(drop_bds), GTK_TREE_MODEL(list_store));

//
// falta agora definir como essa lista irá aparecer na tela, isto é, ser renderizada.
//

// criação de um renderizador de textos:
renderer = gtk_cell_renderer_text_new();

// insere o renderizador criado no drop-down
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(drop_bds), renderer, TRUE);

// define as propriedades (atributos) deste renderizados. Lista-se cada propriedade
// e terminamos a lista com um NULL
// Neste caso, estamos definindo a propriedade "text" e seu valor 0 (não consegui encontrar na
// documentação da API os atributos possíveis e seus valores.... alguém me ajuda nisso?)
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(drop_bds), renderer, "text", 0, NULL);

// até aqui está pronto, seu drop-down estará com o conteúdo desejado.

// no meu caso, eu quero mostrar ao usuário que agora temos dados
// no drop-down para ele escolher
// (a primeira vez que o usuário vê minha janela, o drop-down está vazio)
// Desta forma, vou usar um comando para tornar o primeiro item do
// drop-down como item ativo.

gtk_combo_box_set_active(GTK_COMBO_BOX(drop_bds), 0);



Pronto. Divirtam-se!

Grande abraço a todas e a todos!
Carlão

quinta-feira, 18 de setembro de 2008

Continue mantendo sua sanidade com o Glade

.
Pra quem está começando a trabalhar com GTK e GLADE, recomendo a leitura do excelente tutorial de Marcelo Lira, "Mantendo A Sanidade Com O Glade". Ele dá uma visão completa de todo o processo, desde o desenho da interface no GLADE até a compilação final, com exemplos em várias linguagens.

O objetivo deste texto é complementar este tutorial, mostrando alguns problemas que aparecem no desenho da interface no GLADE, e as soluções que encontrei. Infelizmente este texto não é lá muito “básico”... será preciso algum conhecimento de GTK e até do próprio GLADE. Espero que seja útil mesmo assim. Outros textos introdutórios de GTK virão por aí em algum momento no futuro.

Criaremos com o GLADE a seguinte caixa de diálogo:


Uma caixa de diálogo em GTK possui 2 áreas: uma superior, onde colocaremos nossos widgets, e outra inferior, com espaço para os botões. Podemos começar, então, inserindo no GLADE uma dialog box:


Qual gerenciador de layout colocaremos na parte superior? Vamos analisar nossa interface: ela está mais ou menos organizada “por linhas”, como, por exemplo, a primeira linha (label “tipo de servidor” e drop-down para a escolha do tipo de servidor), ou a última linha (botão “listar bancos de dados”, e drop-down para escolher o banco de dados). Para organizar em linhas, utilizaremos então uma “vbox”.

Agora, outra dúvida: quantas linhas teremos na vbox? Vemos 3 linhas óbvias (primeira, “tipo de servidor”; penúltima, “usuário e senha”; e última, “listar bancos de dados”). Mas, e quanto a localização do servidor? Serão mais 3 linhas?

Na verdade, configura apenas mais 1 linha, pois as 3 linhas que vemos ("endereço ip", "nome" e "nesta máquina") estão AGRUPADAS dentro de um único widget, chamado frame (“localização do servidor”). Precisaremos então de apenas mais uma linha, para inserir a frame. Dentro da frame, aí sim, teremos que criar 3 linhas.

Vemos então na figura abaixo, nossa interface com a vbox configurada para 4 itens:


A primeira linha possui 2 widgets, organizados horizontalmente. Logo utilizaremos uma hbox, com 2 espaços disponíveis.

Na segunda linha, como já falamos, colocaremos uma frame.

Na terceira linha teremos 4 widgets, também organizados horizontalmente. Usaremos então uma hbox de 4 itens.

Finalmente, a última linha terá 2 itens, organizados horizontalmente. Nova hbox, de 2 itens.

Nossa interface fica como apresentado na figura abaixo:


Vamos pensar um pouco como ficará o interior da nossa frame na linha 2. Podemos pensar numa organização também por linhas, mas se olharmos mais atentamente poderemos perceber a existência de linhas E colunas (temos uma coluna de radio buttons, e outra de dados extras, ligados a esses radio buttons). Assim, ao invés de usar uma vbox, usaremos uma table, com 3 linhas e 2 colunas. Nossa interface fica como na figura abaixo:


Ainda sobre esta tabela, notemos a área localizada na primeira linha, segunda coluna: aqui teremos um conjunto de 7 widgets, composto por caixas de texto e labels (pontos), organizados horizontalmente. Vamos inserir então a última hbox de nossa interface, com 7 itens.


Agora que o layout da interface está planejado, podemos inserir seus diversos widgets (labels, caixas de texto, botões, drop-down). Apenas inseri os widgets, colocando os textos corretos, sem mexer ainda em outras configurações. Nesse momento, algo estranho acontece: a janela cresce demais! Se fizermos um teste de apresentação real da janela (usando libglade), vemos que ela está longe de ser visualmente agradável:

Glade:

Programa compilado:

Vamos começar então a “arrumar a casa”. O primeiro problema é o tamanho default das caixas de texto. Na linha do “endereço ip”, cada caixa só precisa armazenar (e exibir) no máximo 3 caracteres. Para as outras, vamos definir exibição de 10 caracteres. A propriedade “maximum length” define o número máximo de caracteres que a caixa poderá armazenar, e a propriedade “width in chars” é o tamanho (em caracteres) da caixa.

Outro problema está relacionado a configuração de expansão dos widgets. Por default, está definido que cada widget vai expandir e ocupar todo o espaço livre disponível. Note na figura acima, por exemplo, a primeira linha (“tipo de servidor”). Como todo o diálogo está aumentado por causa das caixas de texto, o gerenciador de layout dividiu o espaço extra igualmente pelo label “Tipo de servidor” e o drop-down ao seu lado. Precisamos, portanto, desligar a propriedade “expand” de alguns widgets. Cada caso é um caso, mas podemos ter como regra geral fazer isso nos widgets “da esquerda”, e em especial nos labels. Se sobrar espaço na direita, deixamos as caixas de texto e drop-down ocuparem o espaço extra.

Assim, desligaremos a propriedade “expand” dos seguintes widgets:

- label “Tipo de servidor”;
- radio “endereço ip”;
- labels dos pontinhos no endereço ip;
- radio “nome”;
- radio “nesta máquina”;
- label “usuário”;
- label “senha”;
- botão “listar bancos de dados”.

Após essas alterações, o GLADE continuou mostrando o diálogo aumentado (pelo menos no meu caso). Também não consegui diminuir seu tamanho arrastando as bordas. Neste momento fechei o projeto e reabri, e aí sim, ele mostrou o diálogo no seu novo tamanho real. De qualquer modo, é sempre bom ir testando “ao vivo”, através de um programa. Como a interface é desenhada “na hora” (dinamicamente), não precisa nem recompilar, basta salvar o arquivo .glade e rodar o programa para ver o resultado. O estado atual de nossa interface é apresentada na figura abaixo:


Bem melhor, não é? Agora só precisamos passar um “pente fino”. Vamos colocar um espaço após os dois-pontos dos labels “Tipo de servidor” e “usuário”, para aumentar a separação entre eles e o widget ao seu lado. No label “senha”, vamos colocar um espaço antes da palavra e outro depois dos dois-pontos. Vamos também colocar um espaço antes e outro depois do texto no botão “Listar bancos de dados”. Vamos aproveitar e tirar os dois-pontos depois do label “nesta máquina” ( só vi o erro agora... :-) )


As “linhas” que compõem a interface estão muito apertadas, muito próximas umas das outras. Vamos então aumentar o espaçamento entre elas. Lembra da vbox que inserimos no início do processo? Vamos aumentar a propriedade “spacing” para 6:


Note que o conteúdo da frame não foi espaçado, pois está todo em apenas uma “célula” da vbox. Para espaçar este conteúdo, precisamos alterar a propriedade “row spacing” da tabela que inserimos na frame. Coloquei o valor 4. Ainda na frame, podemos ligar o contorno, para desenhar uma caixa. Para isso, vamos alterar a propriedade “frame shadow”, colocando “etched in”.


Podemos notar mais 2 probleminhas dentro da frame: o primeiro é que todos os radio buttons estão ativos! Isso acontece porque o GTK não sabe que eles pertencem a um mesmo grupo, ele acha que são 3 radios separados! Para resolver este problema é preciso estabelecer uma ligação entre eles. Para isso, alteramos a propriedade “group”. Por exemplo, vamos no radio “nome”, e na propriedade group marcaremos o radiobutton1 (“endereço IP”). Faremos o mesmo com o radio “nesta máquina”. Resumindo: radiobutton2 e radiobutton3 fazem referência a radiobutton1, e com isso, todos os 3 ficam no mesmo grupo.

O segundo problema é estético: há um espaço grande, no lado esquerdo da frame, e um espaço mínimo no lado direito (ambos por dentro da frame). Isto pode ser ajustado através das propriedades “left padding” e “right padding” do widget “alignment” (é um dos widgets que compõem a frame). Colocaremos o valor 6 tanto na direita como na esquerda.

Uma última coisa a ser feita, definir o título da janela, na propriedade “window title” do diálogo.


Prontinho! Não esqueça de definir os nomes das callback functions nos widgets correspondentes.

A propósito... tive um problema ao tentar utilizar a função glade_xml_signal_autoconnect (liga automaticamente os eventos gerados pelos widgets às funções callback que definimos no nosso programa principal), pois o programa que estou fazendo é um “híbrido” C/C++. Estou programando em C, usando GTK em C, porém também preciso usar uma biblioteca específica (TerraLib) feita em C++. Logo, estou compilando em C++, e por causa de características específicas desta linguagem acerca de nomes de funções, o autoconnect não consegue encontrar as funções callback. A solução é bem simples: basta definir as funções como “extern C”, assim:

extern "C" void bot_conct(GtkButton *bt, GtkWidget *win)
{
printf("teste...");
getchar();
}

Também precisa adicionar a opção -rdynamic ou -export-dynamic no linkeditor.

Bem, é isso aí. Não deixem de comentar com dúvidas e/ou correções.

Abraços a todas e a todos!
Carlão

terça-feira, 2 de setembro de 2008

Abraçe um programador hoje!

.
Demais!

Obs: Se você acessar o vídeo no site do YouTube, poderá ligar as legendas. Clique, no canto inferior direito, em "CC" (closed caption).

Abraços!
Carlão