Revista Do Linux
 
  
  
EDIÇÃO DO MÊS
 CD do Mês


 Capa
 Entrevista
 Estudo de Caso
 Serviço Público
 Documentação
 Hardware
 Passo a Passo
 Programação
 Redes
 Ferramenta
 Solução
 Estudo de Caso
 

Construa seu navegador

Nesta série de artigos, vamos conhecer e desmistificar as APIs que fazem o KDE

Muito se fala sobre desenvolvimento de aplicações gráficas para Linux e outros Unices em geral, mas geralmente as conversas giram em torno de toolkits como a Qt e o GTK+. A grande maioria dos programadores não está familiarizada com a complexa API do KDE, que pode ser de grande utilidade para o desenvolvimento de sistemas gráficos.

Esta série não vai cobrir os básicos da Qt, por isso, sugerimos que você visite o link de documentação da Trolltech (doc.trolltech.com) para conhecer mais sobre o assunto.

Para começar, é interessante conhecer um pouco das bibliotecas. As kdelibs são um grande conjunto de bibliotecas, cada uma com uma API própria. Algumas das bibliotecas mais importantes são:

  • kdecore: esta biblioteca é a base de um programa KDE. Ela dá acesso às configurações do sistema, parâmetros de linha de comando, carregamento de ícones, IPC (comunicação inter processos) e vários utilitários.
  • kdeui: biblioteca que contém os objetos gráficos que não existiam na Qt ou que tiveram mais características acrescentadas.
  • kio: esta é uma biblioteca interessante, pois ela é responsável por fazer com que a rede seja totalmente transparente para qualquer aplicação KDE. Isso quer dizer que eu posso abrir em editor de textos do KDE um arquivo de um servidor HTTP, FTP, Samba, etc.
  • kdeprint: sistema de impressão do KDE.
  • khtml: esta biblioteca contém funções para “renderização” de HTML.

Existem muitas outras bibliotecas, mas estas são as essenciais para o desenvolvimento de um programa relativamente complexo.

No decorrer desta série de artigos, vamos criar um browser HTML com Javascript, suporte a plugins e “automatizável”, isto é, que poderá ser controlado a partir de outra aplicação ou mesmo um shell script. Sugestões de features são bem-vindas.

Inicialização

Antes de continuar nosso projeto, devemos dizer que não há espaço suficiente na Revista para reproduzirmos todo o código da aplicação. Assim sendo, vamos resumir a mostrar o que é mais relevante ao assunto e deixar o resto disponível para o leitor no site (vide final do artigo e o CD desta edição).

Agora podemos começar realmente nosso projeto. Vamos comentar partes do arquivo main.cpp, que cuida da parte de inicialização da nossa aplicação:



#include “krdlgator.h”    // nossa classe principal

#include <kapp.h>         // KApplication

#include <dcopclient.h>   // DCOP == automatização da aplicação

#include <kaboutdata.h>   // tela “Ajuda->Sobre”

#include <kcmdlineargs.h> // manuseio dos parâmetros

#include <klocale.h>      // internacionalização

Esta parte dispensa grandes explicações, já que será clara para qualquer programador C ou C++. De qualquer modo, inclui comentários ao lado de cada include explicando o que usamos nos headers incluídos.



static const char *description =

    I18N_NOOP(“Web browser for Revista do Linux”);



static const char *version = “v0.1”;

Apenas declaramos duas constantes que representam respectivamente a descrição do nosso programa e sua versão. Você poderá perceber que usamos textos em inglês dentro do programa, isto ficará mais lógico quando entrarmos no assunto de internacionalização de programas (e explicarmos o que é aquele I18N_NOOP encontrado várias vezes no código).



static KCmdLineOptions options[] =

{

    { “+[URL]”, I18N_NOOP( “Document to open.” ), 0 },

    { 0, 0, 0 }

};


Usamos este array para listar todas as opções de linha de comando que nossa aplicação irá usar. No nosso caso, temos apenas a opção de um arquivo para ser aberto.



int main(int argc, char **argv)

{

 KAboutData about(“krdlgator”, I18N_NOOP(“Krdlgator”), 

                     version, description, KAboutData::License_BSD,

             “(C) 2001 Roberto Teixeira”, 0, 0,

                     “maragato@kde.org”);

    about.addAuthor( “Roberto Teixeira”, 0, “maragato@kde.org” );

A classe KAboutData contém informações sobre a aplicação e as pessoas que colaboraram para criá-la. Neste caso, estou informando que o programa se chama krdlgator, a versão e sua descrição. Digo também que sua licença é BSD e que o copyright é meu. Por fim, nós adicionamos um autor à lista de autores do programa.



KCmdLineArgs::init(argc, argv, &about);

KCmdLineArgs::addCmdLineOptions(options);

Processamos as opções de linha de comando. O KDE, a Qt e o X aceitam diversas opções de linha de comando que podem ser acessadas com um --help. Após estas opções terem sido processadas, nós processamos as nossas próprias opções. Mais sobre isto abaixo.



KApplication app;

O objeto KApplication é importante para nós, pois ele é o esqueleto básico de toda a aplicação KDE. Tudo gira em torno desta classe, embora muitas vezes isto possa passar desapercebido, pois muita coisa acontece “por baixo dos panos”, sem a necessidade explícita de código.



app.dcopClient()->registerAs(app.name(), false);

Aqui nós registramos nossa aplicação junto ao servidor DCOP. Vamos conhecer o DCOP mais tarde, mas por enquanto basta saber que o DCOP é a estrutura global do KDE para comunicação de interprocessos. É com ele que poderemos permitir que um shell script ou uma outra aplicação controle nosso programa remotamente. Mas isso fica para depois, vamos em frente.



if (app.isRestored())

RESTORE(Krdlgator)

Veja que interessante: nosso programa tem a capacidade de se recuperar, ou seja, se o usuário fechar a sessão tendo escolhido salvar a sessão, nosso programa vai voltar no mesmo ponto em que parou, sem a necessidade de fazermos mais inicializações.



else

{

  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  if (args->count() == 0)

   {

     Krdlgator *widget = new Krdlgator;

     widget->show();

     }

     else

     {

    int i = 0;

    for (; i < args->count(); i++)

     {

      Krdlgator *widget = new Krdlgator;

                widget->show();

                widget->load(args->url(i));

            }

        }

        args->clear();

    }


Caso nosso programa não tenha sido restaurado, então continuamos com a inicialização efetivamente executando os comandos correspondentes às opções de linha de comando lidas acima. Note que depois que KCmdLineArgs()parseArgs() retorna, todas as opções correspondentes ao KDE, à Qt e ao X terão sido lidas, executadas e retiradas da lista de parâmetros. Isso quer dizer que a variável args irá conter exclusivamente os parâmetros específicos da aplicação; em nosso caso, uma URL contendo o arquivo a ser aberto. Aí é só questão de verificar se o parâmetro está presente e, em caso negativo, criar nossa janela principal, representada pelo objeto Krdlgator. Em caso de termos uma URL para abrir, a única diferença é que chamamos o método load() da nossa janela principal passando a URL como parâmetro. Vamos ver este método e a estrutura da janela mais tarde.




return app.exec();

}

Por fim, o método exec() de KApplication é chamado. Este método faz o que é normalmente conhecido como loop de execução de um programa gráfico. O programador não tem realmente de se preocupar com o que exec() faz, bastando saber que ele irá processar todos os eventos da aplicação e retornar quando a aplicação for fechada (pelo usuário ou pelo sistema).

Embora possa parecer um tanto complicado a princípio, este código de inicialização é praticamente um copiar e colar de outros programas já prontos, e modificar os nomes de classes e informações sobre o programa. Tudo muito automático.

Configurações

Entre as várias guidelines do KDE está aquela que diz que toda a aplicação KDE deve ser sempre personalizável pelo usuário. A personalização é facilitada pela classe KConfig, que nem sequer precisamos inicializar em nossos programas. Qualquer aplicação KDE tem acesso global ao método kapp->config() (kapp é uma variável que aponta para o nosso KApplication) que retorna o objeto KConfig referente à aplicação corrente. Além disso, a classe KMainWindow, de quem tanto Krdlgator, nossa janela principal, como praticamente qualquer janela principal de qualquer programa KDE, herdam características, possui dois métodos interessantes: saveProperties ( KConfig *config ) e readProperties (KConfig *config ), que são chamados automaticamente, quando necessário, para salvar ou ler informações necessárias para recuperar um programa após uma sessão ter sido reiniciada. Deste modo, basta que o programador coloque o código para salvar ou ler as configurações dentro destas funções e tudo estará pronto. Um exemplo de um saveProperties() poderia ser:



void Krdlgator::saveProperties( KConfig *config )

{

  if (m_view->currentURL() != QString::null)

    config->writeEntry(“lastURL”, m_view->currentURL());

}

Isso salvaria a URL aberta, para que na próxima sessão pudéssemos abrir a mesma URL. Já para configurações de usuário, tudo o que o programador tem de fazer é algo assim:



void Krdlgator::saveSettings()

{

  KConfig *config = kapp->config();

  config->writeEntry( “UserName”, mUserName );

  config->writeEntry( “ID”, 123 );

}

É simples gravar informações de configuração. A leitura dos valores é igualmente simples, como pode ser visto na função abaixo:




void Krdlgator::readSettings()  

{

  KConfig *config = kapp->config();

  // se não achar UserName, retorna “Sem Nome”

  mUserTextBox.setText( config->readEntry( “UserName”, “Sem Nome” ) );

  int i = config->readNumEntry( “Numero”, 0 );

  bool b = config->readBoolEntry( “Booleano”, false );

}

Esta é apenas uma introdução ao sistema de configuração do KDE. Mas, com ela, é possível guardar praticamente qualquer tipo de informação necessária às configurações. Para guardar outros tipos de dados mais complexos, outras APIs existem e serão vistas futuramente.

E agora?

No próximo mês, vamos partir para algo mais interessante: vamos colocar o KPart de HTML na nossa aplicação e vamos ver como controlá-lo.

Criando um Desktop

Muitas pessoas acreditam que o desenvolvimento de um software livre é um processo pouco organizado, com muita gente fazendo muita coisa e depois tentando colar tudo junto.

Se isto é verdade em algum projeto, certamente não é no caso do KDE. O ciclo de desenvolvimento do KDE é muito bem planejado, contando com datas rígidas e um coordenador global além dos vários mantenedores do projeto.

O coordenador de uma versão é responsável por definir as datas para lançamentos e freezes além de ter a palavra final quando alguém quer incluir uma feature não planejada fora da época aberta para isso. O ciclo de desenvolvimento de um versão começa bem antes do lançamento da versão anterior. É quando muitas alterações (patches) maiores são barradas por causa da proximidade do lançamento de uma versão, momento em que o desenvolvimento está em “freeze”. Estes freezes ocorrem para que se possa ter um mínimo de estabilidade antes de lançar uma versão. Durante um freeze, nenhuma característica pode ser adicionada e qualquer alteração não trivial tem de ser aprovada pelo coordenador da release antes de ser incluída. Durante o freeze é comum que algum desenvolvedor crie alguma nova característica que deseje incluir, mas estas têm de esperar pelo fim do freeze para entrar apenas na versão seguinte; são os primeiros desenvolvimentos para uma nova versão. Ainda durante o freeze, as discussões nas listas de desenvolvimento começam a esquentar com propostas para as mudanças que a nova versão irá sofrer. No dia em que o freeze acaba, é criado um “branch” no CVS para que mudanças na versão recém lançada possam ser feitas ainda, mas a árvore do CVS (o HEAD) fica aberta a qualquer tipo de alteração. Geralmente nesta semana o CVS do KDE é inundado por alterações que estavam na fila há um certo tempo, tornando o sistema absurdamente instável e efetivamente inutilizável. As semanas seguintes são destinadas à arrumar os problemas que aparecem. No caso do KDE 3, há um acordo de que qualquer mudança grande só pode ser feita nas sextas-feiras, evitando, assim, que o KDE fique muito tempo sem funcionar. Depois de um tempo, entra-se no primeiro “feature freeze”. Neste ponto, ninguém pode mais incluir nenhuma característica nova que não tenha sido previamente planejada (há uma lista de features desejadas). O próximo passo é o lançamento de uma versão beta, isso faz com que um freeze rígido impere na árvore do KDE por um curto período de tempo.

Apenas bugfixes são permitidos. Após o lançamento da versão beta1, o CVS está novamente aberto à modificação, ainda obedecendo as regras do “feature freeze”. A partir deste momento, modificações nos textos da interface devem ser mantidas ao mínimo para não sobrecarregar as diversas equipes de tradutores. Chega então o momento para o lançamento das release candidatas. Estas RCs são candidatas a serem lançadas como versões finais se se mostrarem confiáveis. A partir desde momento, alterações de strings são veemente proibidas, o que por si só já evita um grande número de alterações de código, que, por sua vez, só podem ser bugfixes ou modificações menores. Características que não entraram até aqui deverão esperar pela próxima versão. Cerca de duas semanas antes do anúncio oficial, os pacotes contendo os arquivos fonte são criados e enviados aos empacotadores para a criação dos pacotes binários. Estes só podem ser distribuídos após o anúncio oficial. As maiores distribuições do mundo como Red Hat, Conectiva, SuSE e Mandrake são suportadas e têm seus respectivos pacotes distribuidos a partir dos sites do KDE. As datas para o KDE 3.0 estão no site de desenvolvimento do KDE.

Como ajudar

A equipe brasileira de tradução do KDE está precisando muito de ajuda. A equipe é liderada por Lisiane Sztoltz e Fernando Boaglio e podem ser contatados através do endereço de email <ldp-br@bazar.conectiva.com.br>. O KDE agradece.


Para saber mais

Código completo dos artigos - www.conectiva.com.br/~maragato/rdl/
Documentação QT - doc.trolltech.com
Desenvolvedores do KDE - developer.kde.org
Projeto KDE - www.kde.org


Roberto Teixeira - maragato@kde.org


A Revista do Linux é editada pela Conectiva S/A
Todos os Direitos Reservados.

Política de Privacidade
Anuncie na Revista do Linux