quinta-feira, 24 de julho de 2014

Criar um menu de Recent Files no Qt.

Olá pessoal,



Ando ocupado no emprego, mas como desenvolvi alguns programas para facilitar as coisas no trabalho, estou postando dicas que usei nesses programas. Segue mais um abaixo ;-)


A biblioteca do Qt anda muito bem, gosto muito desse framework. Estava lendo algumas notícias relacionadas a desenvolvimento e me deparei com um componente chamado QSettings, na hora me veio a ideia de utiliza-lo, pesquisei na net e descobri algumas pessoas já fazendo uso. Segue abaixo meu código:

Primeiro, o QSettings usa arquivos .ini para guardar informações do formulário e recuperá-los. Por tanto criei uma lista dos ultimos arquivos abertos:

QAction *separatorAct;
enum { MaxRecentFiles = 10 };

QAction *recentFileActs[MaxRecentFiles];


Segundo, criei duas funções para guardar e recuperar essas info do arquivo .ini:

Recuperar:
void MainWindow::updateRecentFileActions()
{
    QSettings settings("demosetting.ini", QSettings::IniFormat);
    QStringList files = settings.value("recentFileList").toStringList();
    //qDebug() << "carregando de settings: " << files;
    int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);

    for (int i = 0; i < numRecentFiles; i++) {
        QString text = QString("&%1 %2").arg(i).arg(files[i]);
        recentFileActs[i]->setText(text);
        recentFileActs[i]->setData(files[i]);
        recentFileActs[i]->setVisible(true);
    }

}

Guardar:
void MainWindow::setCurrentFile(const QString &fileName)
{
    //curFile = fileName;
    setWindowFilePath(fileName);

    QSettings settings("demosetting.ini", QSettings::IniFormat);
    QStringList files = settings.value("recentFileList").toStringList();
    files.removeAll(fileName);
    files.prepend(fileName);
    while (files.size() > MaxRecentFiles)
        files.removeLast();

    settings.setValue("recentFileList", files);
    //qDebug() << "salvando em " << settings.fileName() << ": " << files;

}

E o código para adicionar o menu "Recent files":

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // recent files
    QMenu *r = this->menuBar()->addMenu("Recent files");

    for (int i = 0; i < MaxRecentFiles; i++) {
        recentFileActs[i] = new QAction(this);
        recentFileActs[i]->setVisible(false);
        connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));
    }
    for (int i = 0; i < MaxRecentFiles; ++i)
        r->addAction(recentFileActs[i]);
    updateRecentFileActions();
    separatorAct = r->addSeparator();

}

void MainWindow::openRecentFile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
        loadFile(action->data().toString());

}

Implementem a função loadFile() ou substitua a chamada pela sua função e lembrando que estou usando o Qt versão 5.2 (no Qt Creator 3.1.1).
Espero ter ajudado novamente.

Até a próxima

Abç, Emanuel

terça-feira, 22 de julho de 2014

Abrindo e usando banco de dados SQLite com o Qt.

Boa tarde pessoal,


Dúvidas chegaram ao meu email, então estou postando como utilizar banco de dados SQLite com o Qt.

Primeiramente o include que deve ser feito:

// lib for read sqlite database
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>

#include <QtSql/QSqlQueryModel>

Segundo o código para abrir o banco de dados:

// open database
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("database.db");
db.open();
if (dbDoni.lastError().isValid())
{
    QMessageBox::critical(0, "error:", db.lastError().text());
    return;
}

Terceiro, executando algumas consultas na base de dados:

QSqlQuery query;
query = db->exec("SELECT * FROM PLUTax");

Vocês podem verificar se resultado de um campo é vazio pelo índice
if (!query.isNull(2)) {
       // error

    }
ou pelo nome:
if (!query.isNull("campo")) {
        // error

    }

Pegar os valores

qDebug() << query.value(2).toString();


E no final fechar a conexão:

dbDoni.close();



Simples e fácil heim ;-)
Só lembrando... estou utilizando o Qt Creator 3.1.1 e Qt 5.2

Abraços

segunda-feira, 21 de julho de 2014

Deploy de programas em Qt.

Boa noite pessoal,



Estou escrevendo este post mais pelo intuito de revolta, da forma como a comunidade www.qt-project.org definiu o deploy dos programas... mas também para ajudar meu amigos programadores.
Para não ficarem sofrendo sem saber porque o programa não roda após liberarem o primeiro release.

Eu crirei um programa usando o Qt Creator 3.1.1 (versão Qt 5.2), algo bem básico, controlar alguma informações de preços, indíces e números de lojas em um arquivo xml, comparar essas informações com planilhas em excel e controlar um pequeno Banco de dados em SQLite.

Segue o link, caso alguns queiram baixar o código fonte, fuçar e comentar:
www.sourceforge.net (ótimo sistema de versionamento do site, recomendo)
https://svn.code.sf.net/p/doni/code/
Quem tiver uma conta no site posso liberar o acesso via SVN.

Bem, após terminar uma versão inicial, fui fazer o release do programa, liberar pro pessoal utilizar e reportar bugs. Lógico que algumas lib's teriam que ser copiadas para a pasta com o executável. E AQUI vem minha frustração, li um post no site do próprio Qt (qt-project.org) e eles recomandam copiar todas as libs presentes na instalação do Qt para a pasta contendo o executável.

Ou seja..

Coloquei o executável na pasta /Users/emanuel/Doni/
Copiar todo o conteúdo de /Users/emanuel/Qt/5.2/mingw_32/bin para /Users/emanuel/Doni/
Sim, o deploy foi para windows
E copiar a pasta /Users/emanuel/Qt/5.2/plugins para /Users/emanuel/Doni/

Ficamos com o diretório da seguinte forma:

/Users/emanuel/Doni/doni.exe
/Users/emanuel/Doni/*.dll
/Users/emanuel/Doni/plugins/*

Tudo isso dá um montante de 125MB... Um absurdo para mim!!! Um programinha de poucas funcionalidades ser deste tamanho! Só por causa de dependências. Se vocês utilizarem o Dependency Walker.exe (windows) ou o comando ldd (Linux) vão ver que as dependências estão todas lá.

Após fazer a cópia pode remover as libs com 'd' no final, pois são bibliotecas de debug.

E após ficar chateado com o fato de meu SIMPLES programa ter esse tamanho, obtive dois problemas e aqui vem minha contribuição para vocês programadores.

1)
Dependendo pra qual plataforma vocês vão desenvolver, no meu caso, fiz no meu Mac mas seria para usuários Windows. Tive que colocar uma biblioteca específica para windows, qwindows.dll, em uma pasta chamada platform/
Ou seja para cada plataforma tem o seu qwindows.dll e deve ser colocado na pasta plataform, se não o programa da erros e nem abre.
2)
O meu programa utiliza um drive para abrir o banco de dados SQLite. Após alguns dias sem entender o erro "DRIVER NOT LOADED" descobri que a biblioteca qsqlite.dll estava no lugar errado. Basta mover a pasta sqldrivers da pasta plugins para um diretório acima. Ficamos assim então:

/Users/emanuel/Doni/doni.exe
/Users/emanuel/Doni/*.dll
/Users/emanuel/Doni/plugins/*
/Users/emanuel/Doni/sqldrivers/*.dll


É isso ai pessoal,

espero que tenha ajudado e até a próxima.