quinta-feira, novembro 23, 2006

Hotmail no Mozilla Thunderbird

Se você usa o Mozilla Thunderbird e tem conta no Hotmail, provavelmente já teve vontade de baixar suas mensagens pelo software cliente.

Existem vários programas que intermediam a conexão entre o cliente e o Hotmail. Já usei alguns, mas não me agradaram muito. Enfim, encontrei hoje uma extensão para o Thunderbird.

O nome da extensão é WebMail. Basta você instalar a extensão mais o módulo do Hotmail. Essa extensão possui também módulos para outros serviços de webmails.

O primeiro passo é baixar a extensão do WebMail na página de download. Em seguida, baixe o módulo do Hotmail na mesma página. Após instalar as extensões, reinicie o Thunderbird.

O passo seguinte, é configurar a extensão. Clique em Ferramentas -> Extensões. Selecione a extensão do WebMail e clique em Preferências.

Na janela de preferências, certifique-se de que POP e SMTP estão OK (bola verde e texto Running). Caso não estejam rodando, pode ser que você não esteja com permissões para usar portas baixas. Neste caso, clique na aba Ports e escolha portas acima de 1024 para POP e SMTP. Se você precisar modificar as portas, reinicie o Thunderbird novamente.

Por último, adicione sua conta do Hotmail. Basta adicionar a conta normalmente, como você faria com qualquer outra conta POP3. Só que no momento de especificar o servidor POP de entrada, use localhost. Termine o resto do assistente de nova conta normalmente.

Se você mudou as portas POP e SMTP na extensão, você terá que fazer o mesmo na configuração da sua conta. Clique em Editar -> Configuração de contas. Procure sua conta do Hotmail e clique na seção Configurações do servidor. Configure a porta para o mesmo número que você escolheu na configuração da extensão. Em seguida, vá para Servidor de saída (SMTP), lá no final, e adicione o servidor SMTP localhost com a porta SMTP que você escolheu nas configurações da extensão.

Pronto! Seu Thunderbird está pronto para baixar e-mails do Hotmail. :)

segunda-feira, novembro 20, 2006

Curso de wxWidgets, post 10: Mais sobre arquivos com wxTextFile

Agora será apresentada a classe wxTextFile. Essa classe permite manipular arquivos de texto e possui alguns métodos bastante úteis. Como eu havia comentado no post 8, eu senti falta de alguns métodos interessantes em wxFile, como por exemplo, ler uma linha inteira de um arquivo. Só depois que eu descobri a wxTextFile :P

A abertura de um arquivo para leitura se dá com o método wxTextFile::Open():

wxTextFile File;
File.Open("arquivo.txt");


Caso o arquivo não possa ser aberto ou não exista, wxTextFile::Open() retornará falso.

Agora, basta caminharmos pelas linhas e ler o conteúdo do arquivo. Podemos saber o número de linhas em um arquivo com wxTextFile::GetLineCount() (retornando o número de linhas) e ler cada linha com wxTextFile::GetLine() (retornando um objeto wxString com o conteúdo da linha lida). Veja um exemplo de leitura linha a linha:

for (unsigned int line = 0; line < File.GetLineCount(); line++)
txt_file->AppendText(File.GetLine(line) + wxT("\n"));


O laço acima percorre cada linha do arquivo e adiciona em um objeto do tipo wxTextCtrl.

Após ter lido todo o arquivo, podemos fechá-lo com wxTextFile::Close():

File.Close();


Já no caso de gravações, temos que criar o arquivo com wxTextFile::Create():

wxTextFile File;
File.Create("arquivo.txt");


Caso o arquivo não possa ser criado, wxTextFile::Create() retornará falso.

Agora, basta chamar wxTextFile::AddLine() para adicionar linhas no arquivo:

File.AddLine(wxT("Linha 1"));
File.AddLine(wxT("Linha 2"));
File.AddLine(wxT("Linha 3"));


Por último, devemos gravar as alterações no disco e fechar o arquivo:

File.Write();
File.Close();


Existem também outros métodos interessantes:

wxTextFile::GoToLine(size_t n) leva você até a linha n.

wxTextFile::GetFirstLine(), GetNextLine(), GetPrevLine(), GetLastLine() retornam a primeira linha, a próxima, a anterior e a última respectivamente.

Você também pode inserir uma linha em um local específico com wxTextFile::InsertLine() e pode remover qualquer linha com wxTextFile::RemoveLine().

O exemplo de editor de textos

Modifiquei o programa do post 9 para usar wxTextFile no lugar de wxFile. Vejam o programa alterado abaixo:

/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Exemplo de um editor de textos usando wxTextFile
*
* O objetivo deste código é demonstrar o uso da classe wxTextFile
* para efetuar leitura e escrita em um arquivo de texto, além
* de mostrar o uso básico das classes wxApp, wxFrame, wxStaticText,
* wxButton, wxTextCtrl e wxBoxSizer, assim como o tratamento de
* eventos e as funções wxFileSelector() e wxMessageBox()
* (tópicos abordados do post 2 ao post 8 do curso).
*
* wxTextCtrl possui dois métodos para carregar e salvar um arquivo
* (wxTextCtrl::LoadFile() e wxTextCtrl::SaveFile()), porém, wxTextFile
* é utilizado para demonstrar seu uso. No trecho onde a leitura e
* escrita são feitas, existem comentários explicando como utilizar
* estes métodos.
*
* Copyright (c) João Paulo Just <jpjust@justsoft.com.br>
* A Casa de Just - http://jpjust.blogspot.com
* 20 de novembro de 2006, 20:25, Ilhéus, BA, Brasil.
*/

#include <wx/wx.h>
#include <wx/textfile.h>

// IDs
enum
{
ID_BTNLOAD,
ID_BTNSAVE
};

// Classe do programa
class MeuPrograma: public wxApp
{
public:
// Método principal
virtual bool OnInit(void);
};

// Classe do frame
class MeuFrame: public wxFrame
{
public:
// Construtor
MeuFrame(void);

// Eventos
void OnLoadClick(wxCommandEvent &event);
void OnSaveClick(wxCommandEvent &event);

DECLARE_EVENT_TABLE()

private:
// Widgets do frame
wxButton *btn_load;
wxButton *btn_save;

wxStaticText *lb_filename;

wxTextCtrl *txt_file;
};

// Inicialização do programa
bool MeuPrograma::OnInit(void)
{
MeuFrame *frame = new MeuFrame();
frame->Show();
SetTopWindow(frame);
return true;
}

// Tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
EVT_BUTTON(ID_BTNLOAD, MeuFrame::OnLoadClick)
EVT_BUTTON(ID_BTNSAVE, MeuFrame::OnSaveClick)
END_EVENT_TABLE()

// Construtor do frame
MeuFrame::MeuFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Arquivos"))
{
// Sizer e widgets
wxBoxSizer *sizer_h = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);

btn_load = new wxButton(this, ID_BTNLOAD, wxT("Abrir"));
btn_save = new wxButton(this, ID_BTNSAVE, wxT("Salvar"));

lb_filename = new wxStaticText(this, wxID_ANY,
wxT("Sem titulo.txt"));

txt_file = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);

// Posicionamento
sizer_h->Add(btn_load, 0, wxALL, 5);
sizer_h->Add(btn_save, 0, wxALL, 5);
sizer_h->Add(lb_filename, 1, wxALL, 5);

sizer_v->Add(sizer_h, 0, wxALL, 0);
sizer_v->Add(txt_file, 1, wxALL | wxEXPAND, 5);

SetSizerAndFit(sizer_v);

// Boas-vindas
wxMessageBox(wxT("Seja bem-vindo(a) a mais um maravilhoso programa! :)"),
wxT("Bem-vindo(a)!"), wxICON_INFORMATION);
}

// Botão de leitura
void MeuFrame::OnLoadClick(wxCommandEvent &event)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxOPEN | wxFILE_MUST_EXIST);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

// Tenta abrir o arquivo com wxTextFile
wxTextFile File;
if (File.Open(Filename) == false)
return;

// Lê o conteúdo do arquivo linha a linha
for (unsigned int line = 0; line < File.GetLineCount(); line++)
txt_file->AppendText(File.GetLine(line) + wxT("\n"));

// Não é preciso todo este código para ler um arquivo
// e exibí-lo em um wxTextCtrl. O trecho acima foi
// escrito apenas para que você entenda a classe wxTextFile.
// wxTextCtrl possui um método próprio para ler o
// conteúdo de um arquivo. Tente comentar o trecho acima
// e usar o método abaixo para fazer a leitura:

//txt_file->LoadFile(Filename);

// Fecha o arquivo
File.Close();

// Atualiza o nome
lb_filename->SetLabel(Filename);
}

// Botão de salvamento
void MeuFrame::OnSaveClick(wxCommandEvent &event)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxSAVE | wxOVERWRITE_PROMPT);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

// Tenta criar o arquivo com wxTextFile
wxTextFile File;
if (File.Create(Filename) == false)
return;

// Limpa o arquivo, caso exista conteúdo nele
File.Clear();

// Percorre a caixa de texto gravando o conteúdo
// no arquivo aberto, linha a linha
for (unsigned int line = 0; line < txt_file->GetNumberOfLines(); line++)
File.AddLine(txt_file->GetLineText(line));

// Neste ponto, eu também poderia usar um método
// de wxTextCtrl para salvar o arquivo. Tente
// comentar o trecho de gravação acima e descomente
// a linha abaixo para testar:

//txt_file->SaveFile(Filename);

// Salva o arquivo em disco e fecha
File.Write();
File.Close();

// Atualiza o nome do arquivo
lb_filename->SetLabel(Filename);
}

IMPLEMENT_APP(MeuPrograma)

sábado, novembro 11, 2006

Curso de wxWidgets, post 9: Um exemplo de um editor de textos

Resolvi fazer um exemplo de um editor de textos, usando a maioria das classes estudadas até agora. Além de mostrá-las em ação, vou pagar a semana que fiquei sem postar no mês passado :P. O código completo do exemplo está abaixo. Compile e veja o programa funcionando. Não deixe de ler os comentários, existem algumas informações importantes neles.

/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Exemplo de um editor de textos usando wxFile
*
* O objetivo deste código é demonstrar o uso da classe wxFile
* para efetuar leitura e escrita em um arquivo de texto, além
* de mostrar o uso básico das classes wxApp, wxFrame, wxStaticText,
* wxButton, wxTextCtrl e wxBoxSizer, assim como o tratamento de
* eventos e as funções wxFileSelector() e wxMessageBox()
* (tópicos abordados do post 2 ao post 8 do curso).
*
* wxTextCtrl possui dois métodos para carregar e salvar um arquivo
* (wxTextCtrl::LoadFile() e wxTextCtrl::SaveFile()), porém, wxFile
* é utilizado para demonstrar seu uso. No trecho onde a leitura e
* escrita são feitas, existem comentários explicando como utilizar
* estes métodos.
*
* Copyright (c) João Paulo Just
* A Casa de Just - http://jpjust.blogspot.com
* 8 de novembro de 2006, 21:03, Ilhéus, BA, Brasil.
*/

#include <wx/wx.h>
#include <wx/file.h>

#define BUF_SIZE 128 // Tamanho do buffer de leitura/escrita

// IDs
enum
{
ID_BTNLOAD,
ID_BTNSAVE
};

// Classe do programa
class MeuPrograma: public wxApp
{
public:
// Método principal
virtual bool OnInit(void);
};

// Classe do frame
class MeuFrame: public wxFrame
{
public:
// Construtor
MeuFrame(void);

// Eventos
void OnLoadClick(wxCommandEvent &event);
void OnSaveClick(wxCommandEvent &event);

DECLARE_EVENT_TABLE()

private:
// Widgets do frame
wxButton *btn_load;
wxButton *btn_save;

wxStaticText *lb_filename;

wxTextCtrl *txt_file;
};

// Inicialização do programa
bool MeuPrograma::OnInit(void)
{
MeuFrame *frame = new MeuFrame();
frame->Show();
SetTopWindow(frame);
return true;
}

// Tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
EVT_BUTTON(ID_BTNLOAD, MeuFrame::OnLoadClick)
EVT_BUTTON(ID_BTNSAVE, MeuFrame::OnSaveClick)
END_EVENT_TABLE()

// Construtor do frame
MeuFrame::MeuFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Arquivos"))
{
// Sizer e widgets
wxBoxSizer *sizer_h = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);

btn_load = new wxButton(this, ID_BTNLOAD, wxT("Abrir"));
btn_save = new wxButton(this, ID_BTNSAVE, wxT("Salvar"));

lb_filename = new wxStaticText(this, wxID_ANY,
wxT("Sem titulo.txt"));

txt_file = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);

// Posicionamento
sizer_h->Add(btn_load, 0, wxALL, 5);
sizer_h->Add(btn_save, 0, wxALL, 5);
sizer_h->Add(lb_filename, 1, wxALL, 5);

sizer_v->Add(sizer_h, 0, wxALL, 0);
sizer_v->Add(txt_file, 1, wxALL | wxEXPAND, 5);

SetSizerAndFit(sizer_v);

// Boas-vindas
wxMessageBox(wxT("Seja bem-vindo(a) a mais um maravilhoso programa! :)"),
wxT("Bem-vindo(a)!"), wxICON_INFORMATION);
}

// Botão de leitura
void MeuFrame::OnLoadClick(wxCommandEvent &event)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxOPEN | wxFILE_MUST_EXIST);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

// Abre o arquivo para leitura com wxFile
wxFile File(Filename, wxFile::read);

// Verifica se o arquivo foi aberto
if (!File.IsOpened())
return;

// Lê o conteúdo do arquivo em partes
// do tamanho de BUF_SIZE
char buffer[BUF_SIZE] = {0};
txt_file->Clear();

while (!File.Eof())
{
// Lê BUF_SIZE - 1 bytes (deixa um espaço
// para o \0 do final da string
if (File.Read(buffer, BUF_SIZE - 1) > 0)
{
// Converte o conteúdo de buffer, que
// deve estar em UTF8 (ANSI) para o formato
// da sua compilação do wxWidgets
wxString Buf(buffer, wxConvUTF7);
txt_file->AppendText(Buf);
memset(buffer, 0, BUF_SIZE);
}
else
{
wxMessageBox(wxT("Erro de leitura!"),
wxT("Erro"), wxICON_ERROR);
return;
}
}

// Não é preciso todo este código para ler um arquivo
// e exibí-lo em um wxTextCtrl. O trecho acima foi
// escrito apenas para que você entenda a classe wxFile.
// wxTextCtrl possui um método próprio para ler o
// conteúdo de um arquivo. Tente comentar o trecho acima
// e usar o método abaixo para fazer a leitura:

//txt_file->LoadFile(Filename);

// Fecha o arquivo
File.Close();

// Atualiza o nome
lb_filename->SetLabel(Filename);
}

// Botão de salvamento
void MeuFrame::OnSaveClick(wxCommandEvent &event)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxSAVE | wxOVERWRITE_PROMPT);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

// Abre o arquivo para escrita com wxFile
wxFile File(Filename, wxFile::write);

// Verifica se o arquivo foi aberto
if (!File.IsOpened())
return;

// Percorre a caixa de texto gravando o conteúdo
// no arquivo aberto
for (unsigned int line = 0; line <>GetNumberOfLines(); line++)
{
wxString Buf = txt_file->GetLineText(line);
if (File.Write(Buf + wxT("\n"), wxConvUTF7) < 0)
{
wxMessageBox(wxT("Erro de gravação!"),
wxT("Erro"), wxICON_ERROR);
return;
}
}

// Neste ponto, eu também poderia usar um método
// de wxTextCtrl para salvar o arquivo. Tente
// comentar o trecho de leitura acima e descomente
// a linha abaixo para testar:

//txt_file->SaveFile(Filename);

// Fecha o arquivo
File.Close();

// Atualiza o nome do arquivo
lb_filename->SetLabel(Filename);
}

IMPLEMENT_APP(MeuPrograma)


Screenshot

terça-feira, novembro 07, 2006

Curso de wxWidgets, post 8: Manipulando arquivos

Manipular arquivos em C não é complicado, mas de qualquer forma, irei apresenter uma classe do wxWidgets que o ajuda nesta tarefa, a wxFile.

wxFile é simples de usar. Seu construtor:

wxFile(const char* filename, wxFile::OpenMode mode = wxFile::read)

filename: O caminho do arquivo a ser aberto.

mode: Modo de acesso. Pode ser wxFile::read, wxFile::write ou wxFile::read_write.


Para abrir um arquivo para leitura, basta especificar o caminho do arquivo e usar o modo wxFile::read:

wxFile arquivo("c:\\arquivo.txt", wxFile::read);


Leitura e escrita? Use wxFile::read_write:

wxFile arquivo("c:\arquivo.txt", wxFile::read_write);


Após aberto, já podemos manipular o arquivo. A leitura é feita com o método wxFile::Read():

char linha[256];
int lido, max = 255;

wxFile arquivo("c:\\arquivo.txt", wxFile::read);
lido = arquivo.Read(linha, max);


lido irá conter a quantidade de bytes lidos pelo método. linha irá guardar o conteúdo lido e max indica o máximo de bytes a ser lido (neste caso, usado para delimitar a quantidade de dados que será guardado em linha). No caso de leitura de arquivos de texto, a quantidade de bytes a serem lidos deve ser o tamanho do buffer menos 1, para deixar espaço para o \0 de final de string em C.

Para gravar, simplesmente use o método wxFile::Write()

wxString Linha = wxT("Nova linha de texto!");
bool gravado;

wxFile arquivo("c:\\arquivo.txt", wxFile::read);
gravado = arquivo.Write(Linha);


Este método usa como argumento um wxString. Existe um segundo argumento, usado para fazer conversão do tipo da string. A conversão é utilizada caso você esteja usando wxWidgets em uma compilação (UNICODE, por exemplo) e deseja gravar o arquivo em outro formato (no caso, ANSI).

Se você prefere gravar no formato cru, como no C puro, existe também o método wxFile::Write(const void* buffer, wxFileOffset count) que funciona de forma semelhante ao wxFile::Read(). Ele recebe como argumento uma variável qualquer com algum conteúdo e um valor indicando a quantidade de bytes a serem gravados.

É preciso saber que essas operações serão feitas no início do arquivo. Ou seja, se você pede para ler 10 bytes, a classe wxFile irá ler os primeiros 10 bytes do arquivo. Se logo em seguida você solicitar uma escrita, seu buffer será gravado a partir do 11º byte. Para fazer leituras e escritas em outras partes do arquivo, use wxFile::Seek():

wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart)

ofs: Offset a percorrer.

mode: Origem da busca. Pode ser wxFromStart, wxFromEnd ou wxFromCurrent.


Se você quiser fazer uma leitura a partir do 20º byte, por exemplo, basta usar o método wxFile::Seek() antes do wxFile::Read():

arquivo.Seek(20, wxFromStart);
arquivo.Read(buffer, 100);


O exemplo acima lê 100 bytes a partir do 20°, guardando o conteúdo em buffer. O mesmo vale para escritas, basta usar wxFile::Seek() antes de wxFile::Write().

Caso queira gravar no final do arquivo, use wxFile::SeekEnd():

arquivo.SeekEnd();
arquivo.Write(Linha);


Após ter feito todas as leituras e escritas desejadas, feche o arquivo com wxFile::Close().

Outros métodos interessantes

Além de leitura e escrita, podemos fazer outras coisas com wxFile. Por exemplo, obter o tamanho do arquivo aberto com wxFile::Length():

int tamanho = arquivo.Length();


Ou até verificar se o arquivo existe com wxFile::Exists():

bool existe = wxFile::Exists("c:\\arquivo.txt");


Finalizando

Na minha opinião pessoal, não há uma vantagem grandiosa em usar wxFile. Quero dizer, usar wxFile não nos dá tanta vantagem para tratar arquivos quanto wxString nos dá para tratar strings. Eu senti falta de um método que lesse n bytes, gravando-os em um wxString ou algum método que pudesse ler toda uma linha de uma vez.

Olhei o manual da próxima versão (2.7.2, futuramente 2.8.0) e não vi nada deste tipo em wxFile. Acabei ficando com vontade de implementar isso. :)