# Capítulo 2. As Bibliotecas KDE e Qt

A empresa Norueguesa Troll Tech (\|\|) disponibiliza um chamado conjunto de ferramentas de GUI, chamado Qt . Assim, GUI significa "Graphical User Interface - Interface Gráfico de Utilizador", e assim, as aplicações baseadas na Qt representam-se com botões, janelas etc, permitindo inserção de dados do utilizador visualizando as funções que a aplicação disponibiliza. Este conjunto de ferramentas é necessário para o desenvolvimento de aplicações gráficas que corram no Interface X-Window em Sistemas Unix, porque o X não contém um interface de utilizador pré-definido em si. Apesar de outros conjuntos de ferramentas estarem também disponíveis para criar Interfaces de Utilizador, a Qt oferece algumas vantagens técnicas que tornam o desenho de aplicações muito fácil. Adicionalmente, o conjunto de ferramentas Qt também está disponível para o sistema Microsoft Windows, o que permite aos programadores disponibilizarem as suas aplicações para ambas as plataformas.

A Equipa KDE (\|\|) juntou-se com o objectivo de tornar a utilização de Sistemas Unix mais amigável, e decidiu utilizar o conjunto de ferramentas Qt para o desenvolvimento de um gestor de janelas no X-Window, mais uma variedade de ferramentas incluídas com os pacotes KDE. O Ambiente de Trabalho K contém assim o gestor de janelas kwm, o gestor de ficheiros kfm e o painel de controlo kpanel como sendo os componentes principais mais uma variedade de utilitários e aplicações de primeira classe. Depois do KDE ter saido, muitos dos programadores voltaram os seus olhos no sentido deste novo ambiente e do que tem para lhes oferecer. As bibliotecas KDE estão a disponibilizar métodos e classes fundamentais que fazem com que todas as aplicações desenhadas com elas tenham um aspecto similar e consistente, e o utilizador tem a grande vantagem de apenas ter de se acostumar com a utilização específica de uma aplicação, não com o manuseamento de diálogos ou botões. Também, os programas KDE integram-se no ambiente de trabalho e são capazes de interagir com o gestor de ficheiros através do arrastar e largar (drag and drop), oferecer gestão de sessões e muito mais, se todas as funcionalidades oferecidas pelas bibliotecas KDE forem utilizadas.

Ambos, o conjunto de ferramentas Qt e as bibliotecas KDE , são implementadas na linguagem de programação C++; assim aplicações que façam uso destas bibliotecas são também maioritariamente escritas em C++. No capítulo seguinte, faremos uma breve viagem através das bibliotecas para ver o que já é disponibilizado e como as aplicações Qt e KDE são criadas em geral.

# 2.1. O Conjunto de Ferramentas GUI Qt

Como foi dito, a biblioteca Qt é um conjunto de ferramentas que oferece elementos gráficos que são utilizados para criar GUI's de aplicações e são necessárias para programação X-Window. Adicionalmente, este conjunto de ferramentas oferece:

- Um conjunto completo de classes e métodos prontos a utilizar para questões de programação não-gráfica,

- Uma boa solução no sentido da interacção do utilizador através de métodos virtuais e mecanismos sinal/espaço,

- Um conjunto de elementos GUI pré-definidos, chamados "widgets", que podem ser facilmente utilizados para criar elementos visíveis

- Diálogos adicionais completamente pré-definidos que são muitas vezes utilizados em aplicaçãis tais como diálogos de progresso e de ficheiros.

Posto isto conhecer as classes Qt é essêncial, mesmo se você apenas deseja programar aplicações KDE. Para ter uma ideia do conceito basico sobre como as aplicações GUI são construidas e compiladas, iremos primeiro observar um programa exemplo apenas Qt ; depois extende-lo-emos para um programa KDE.

## 2.1.1. A Primeira Aplicação Qt

Como normalmente, programas em C++ têm de conter a função `main()`, que é o ponto de partida para a execução da aplicação. Como queremos que seja graficamente visível em janelas e ofereça interacção do utilizador, temos primeiro que saber, como se podem mostrar a si próprias ao utilizador. Por exemplo, iremos observar o primeiro programa de tutor incluido com a Documentação Electrónica de Referência Qt e explicar os passos de execução básicos; também como e porquê as janelas da aplicação aparecem:

     #include <qapplication.h>
     #include <qpushbutton.h>

     int main( int argc, char **argv )
     {
     QApplication a( argc, argv );

     QPushButton hello( "Hello world!" );
     hello.resize( 100, 30 );

     a.setMainWidget( &&;hello );
     hello.show();
     return a.exec();
     }

Esta aplicação meramente pinta uma janela contendo um botão com "Hello world" ("Olá Mundo") como texto. Como todas as aplicações baseadas na Qt , primeiro tem de declarar uma instância da classe `QApplication`, representada por `a`.

Depois, o programa cria uma instância da classe `QPushButton` chamada `hello`, isto será o botão. O constructor do `hello` obtém uma string (conjunto de caracteres) como parâmetro, que é o conteudo do widget visível como sendo o texto do botão.

Depois o método `resize()` é chamado sobre o botão `hello`. Isto muda o tamanho de defeito que um widget (que é neste caso o QPushButton) tem quando criado para o comprimento de 100 pixels e a altura de 30 pixels. Finalmente, o método `setMainWidget()` é chamado para `a` e o método `show()` para `hello`. A `QApplication` é finalmente executada por `a.exec()`, entra no ciclo de acontecimento principal e aguarda até que tenha de devolver um valor inteiro para a camada do Sistema Operativo assinalando que a aplicação terminou.

## 2.1.2. A Documentação de Referência para a Qt

Agora, vamos observar rapidamente a documentação de referência da biblioteca Qt . Para fazer isto, inicie o KDevelop e seleccione "biblioteca Qt " a partir do menu "Ajuda" na barra de menu. O navegador de documentação abre e mostra-lhe a página inicial da referência Qt . Isto irá ser o seu primeiro local para obter informação sobre a Qt , suas classes e as funções disponíveis que oferece. Também, o programa acima mostrado é o primeiro que é incluído na secção dos tutores. Para obter as classes que desejamos observar, `QApplication` e `QPushButton`, seleccione "Lista Alfabética de Classes" e procure os nomes correspondentes. Siga qualquer uma delas para observar a documentação de classes .

Para a `QApplication`, verá o construtor e todos os outros métodos que esta classe disponibiliza. Se seguir uma hiper-ligação, irá obter mais informação sobre a utilização e significado dos métodos, o que é muito útil quando você às vezes não consegue detectar a utilização correcta ou deseja ver um exemplo. Isto também vale para a documentação da biblioteca KDE, que utiliza um tipo de documentação similar; assim isto é praticamente tudo o que tem de saber sobre a utilização da referência de classes com o navegador de documentação.

## 2.1.3. Interpretação do Exemplo

Começando com a `QApplication`, você irá ver todos os métodos utilizados no nosso primeiro exemplo:

- o construtor `QApplication()`,

- o método `setMainWidget()` e

- o método `exec()`.

A interpretação sobre porque utilizamos estes métodos é muito simples:

1. primeiro criamos uma instância da classe `QApplication` com o construtor, para que possamos utilizar os elementos GUI disponibilizados pela Qt ,

2. criamos um widget que será o contentor da janela do nosso programa,

3. definimos o widget como sendo o widget principal para `a`,

4. executamos a instância `a` da `QApplication`.

O segundo objecto do nosso programa é o botão, como uma instância da classe `QPushButton`. Dos dois construtores dados para criar uma instância, nós utilizamos o segundo: este aceita um texto, que é a etiqueta do conteudo do botão; aqui, a etiqueta é o texto "Hello world!". Depois chamamos o método `resize()` para modificar o tamanho do botão de acordo com o seu conteudo- o botão tem de ser maior para tornar o texto completamente visível.

Mas e então o método `show()`? Agora, você vê que tal como a maior parte dos outros widgets, `QPushButton` é baseado numa herança única- aqui, a documentação diz, Herda `QButton`. Siga a hiper-ligação para a classe `QButton`. Isto irá mostrar-lhe imensos outros métodos que são herdados pelo QPushButton, que iremos utilizar mais tarde para explicar o mecanismo sinal/espaço. De qualquer modo, o método `show()` não está listado, pelo que, tem de ser um método que é disponibilizado também por herança. A classe que o `QButton` herda, é `QWidget`. Basta seguir de novo a hiper-ligação, e irá ver imensos métodos que a classe `QWidget` disponibiliza; incluindo o método `show()`. Agora nós compreendemos o que foi feito no exemplo com o botão:

1. criar uma instância do `QPushButton`, utilizar uma segunda construção para definir o texto do botão,

2. redimensionar o widget para o seu conteudo,

3. definir o widget como sendo o widget principal da instância `a` da `QApplication`,

4. dizer ao widget para se mostrar no ecrã chamando `show()`, um método herdado de `QWidget`.

Após chamar o método `exec()`, a aplicação é visível para o utilizador, mostrando uma janela com um botão apresentando "Hello world!". Agora, programas GUI comportam-se de um modo ligeiramenta diferente das aplicações processuais. A coisa principal aqui é que a aplicação entra num chamado "ciclo de evento principal". Isto significa que o programa tem de aguardar por acções do utilizador e depois reagir a estas, também que para uma aplicação Qt , o programa tem de estar no ciclo de evento principal para iniciar o manuseamento de eventos. A secção seguinte diz-lhe de forma breve o que isto significa para o utilizador e o que a Qt oferece para processar eventos do utilizador.

(Para utilizadores já avançados: O botão não tem pai declarado no construtor, por isso é por si só um widget de nível superior e corre num ciclo de evento local que não tem de aguardar pelo ciclo de evento principal, veja a documentação de classe `QWidget` e O Guia de Referência da Biblioteca KDE)

Sumário:

Uma aplicação Qt tem sempre de ter uma instância da classe `QApplication`. Isto permite que possamos criar janelas que são a representação gráfica de programas para o utilizador final e permitem interacção. O conteudo da janela em si é chamado o "Widget Principal", significando que todos os elementos gráficos são baseados na classe `QWidget` e podem ser qualquer tipo de widget que sirva as necessidades da aplicação para comunicar com o utilizador. Assim, todos os elementos de utilizador têm de herdar de uma forma ou de outra `QWidget` para serem visíveis.

## 2.1.4. Interacção do Utilizador

Após ler as secções anteriores, você já deverá saber:

- o que a biblioteca Qt disponibiliza em termos de aplicações GUI,

- como é que um programa que utilize a Qt é criado e

- onde e como obter informação sobre classes que deseja utilizar com o navegador de documentação

Agora iremos começar a dar "vida" à aplicação através do processamento de eventos do utilizador. Geralmente, o utilizador tem duas formas de interagir com o programa: o rato e o teclado. Para ambas as formas, um interface gráfico de utilizador (GUI) tem de disponibilizar métodos que detectem acções e métodos que façam alguma coisa como reacção a estas acções.

O sistema de Janelas assim envia todos os eventos de interacção para a respectiva aplicação. A QApplication envia-os então para a janela activa como um `QEvent` e os prórpios widgets têm de decidir o que fazer com os eventos. Um widget recebe o evento e processa `QWidget`::event(QEvent*)/, que então decide que evento foi executado e como reagir; event() é assim quem faz o manuseamento principal de eventos. Depois, a função `event()` passa o evento para os chamados filtros de eventos, que determinam que aconteceu e o que fazer com o evento. Se nenhum filtro encontra um responsável pelo evento, os manuseadores especializados de eventos são chamados. Assim podemos decidir entre:

a) Eventos de Teclado -- teclas TAB e Shift-TAB:

muda o focus de entrada do teclado do widget actual para o widget seguinte na ordem de focus. O focus pode ser atribuido aos widgets chamando `setFocusPolicy()` e processar os seguintes indicadores de eventos:

- `virtual void focusInEvent ( QFocusEvent * )`

- `virtual void focusOutEvent ( QFocusEvent * )`

b) todos os restantes eventos de teclado:

- `virtual void keyPressEvent ( QKeyEvent * )`

- `virtual void keyReleaseEvent ( QKeyEvent * )`

c) movimentos do rato:

- `virtual void mouseMoveEvent ( QMouseEvent * )`

- `virtual void enterEvent ( QEvent * )`

- `virtual void leaveEvent ( QEvent * )`

d) acções de botões do rato:

- `virtual void mousePressEvent ( QMouseEvent * )`

- `virtual void mouseReleaseEvent ( QMouseEvent * )`

- `virtual void mouseDoubleClickEvent ( QMouseEvent * )`

e) eventos da janela que contém o widget:

- `virtual void moveEvent ( QMoveEvent * )`

- `virtual void resizeEvent ( QResizeEvent * )`

- `virtual void closeEvent ( QCloseEvent * )`

Note que todas as funções de eventos são virtuais e protegidas; assim você pode re-implementar os eventos que necessitar nos seus próprios widgets e especificar como o seu widget tem de reagir. O `QWidget` também contém alguns outros métodos virtuais que podem ser úteis nos seus programas; de qualquer modo, é suficiente saber sobre o `QWidget` de uma forma geral.

## 2.1.5. Interacção de Objectos através de Sinais e Espaços

Agora estamos a chegar às vantagens mais óbvias do conjunto de ferramentas Qt : o mecanismo sinal/espaço. Isto oferece uma solução bastante "à-mão" e útil para interacção de objectos, que é normalmente resolvido através de funções de `callback` para conjuntos de ferramentas X-Window. Como esta comunicação requer uma programação estrita e às vezes torna a criação de interfaces gráficos muito difícil (como referido pela documentação Qt e explicado em Programação com Qt por K.Dalheimer), a Troll Tech inventou um novo sistema onde objectos podem emitir sinais que podem ser conectados a métodos declarados como espaços. Para a parte C++ do programador, ele apenas tem de saber algumas coisas sobre este mecanismo:

1. a declaração de classe da classe que utiliza sinais/espaços tem de conter a macro `Q&_;OBJECT` no início (sem o ponto e vírgula); e tem de derivar da classe `QObject`,

2. um sinal pode ser emitido por uma palavra-chave `emit`, por ex. `emit signal(parâmetros);` a partir de qualquer função membra de uma classe que permita sinais/espaços,

3. todos os sinais utilizados pelas classes que não são herdadas têm de ser adicionados à declaração da classe através de uma secção `signals:`,

4. todos os métodos que podem ser conectados com um sinal são declarados em secções com a palavra-chave adicional `slot`, por ex. `public slots:` dentro da declaração da classe,

5. o compilador de meta-objectos `moc` tem de correr sobre o ficheiro header para expandir as macros e produzir a implementação (que não é necessário saber.). Os ficheiros resultantes do `moc` são compilados também pelo compilador C++.

Outra forma de utilizar sinais sem derivar de `QObject` é utilizar a classe `QSignal`- veja a documentação de referência para mais informação e exemplos de utilização. Nos exemplos seguintes, nós assumimos que você está a derivar da `QObject`.

Desta forma, a sua classe é capaz de enviar sinais para qualquer lado e de disponibilizar espaços a onde se possam conectar sinais. Utilizando os sinais, você não tem de se preocupar com quem os está a receber- você apenas tem de emitir o sinal e qualquer que seja o espaço que lhe queira conectar poderá reagir à emissão. Também os espaços podem ser utilizados como métodos normais durante a implementação.

Agora, para conectar um sinal a um espaço, tem de utilizar os métodos `connect()` que são disponibilizados através do `QObject` ou, onde disponível, métodos especiais que os objectos disponibilizam para definir a conecção para um certo sinal.

### 2.1.5.1. Exemplo de Utilização

Para explicar a forma como definir interacção de objectos, iremos agarrar de novo no nosso primeiro exemplo e extende-lo através de uma conecção simples:

     #include <qapplication.h>
     #include <qpushbutton.h>

     int main( int argc, char **argv )
     {
     QApplication a( argc, argv );

     QPushButton hello( "Hello world!" );
     hello.resize( 100, 30 );

     a.setMainWidget( &&;hello );

     connect(&&;hello, SIGNAL( clicked() ), &&;a, SLOT( quit() ));

     hello.show();
     return a.exec();
     }

Como vê, a única adição para dar ao botão mais interacção é utilizar um método `connect()`: `connect(&&;hello, SIGNAL( clicked() ), &&;a, SLOT( quit() ));` é tudo o que temos de acrescentar. Qual é o significado agora? A declaração da classe de `QObject` diz sobre o método `connect()`:

`bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * member )`

Isto significa, você tem de especificar um ponteiro de uma instância de QObject que é o emissor do sinal, significando que pode emitir este sinal como primeiro parâmetro; depois você tem de especificar o sinal a que se deseja conectar. Os dois últimos parâmetros são o objecto receptor que disponibiliza um espaço, seguido pela função membro que é na realidade o espaço que será executado aquando da emissão do sinal.

Utilizando sinais e espaços, os objectos do seu programa podem interagir entre eles facilmente sem dependerem explicitamente do tipo de objecto receptor. Você irá aprender mais sobre a utilização deste mecanismo para utilização produtiva mais tarde neste manual. Mais informação sobre o mecanismo Sinal/Espaço pode ser encontrado no Guia de Referência da Biblioteca KDE e na referência electrónica Qt .