Como Manipular uma Classe Qualquer?



  • Eu queria saber se ''e possivel manipular qualquer classe usando o Qt?

    Quero fazer um metodo, que seja capaz de receber uma classe qualquer, onde seja possivel saber todos ou parte dos atributos de uma classe, se possivel identificar os tipos desses atributos...

    Pensei em usar "templates" mas, a classe QObject nnao suporta templates, ao menos na versao 4.7 do Qt...

    Me deem uma luz... :D



  • Bom dia,

    Será um pouco complicado, pois se você pretende receber objetos de classes derivadas de QObject, você terá que recebê-los através de ponteiros, visto que QObject possui o construtor por cópia e o operador "=" declarados como privados, o que impossibilita a passagem por valores para métodos e/ou funções de objetos desta categoria. Acredito também que o não funcionamento de templates para QObject e derivados seja causado também pela característica citada anteriormente.
    Qual o seu objetivo com este método? Visto que você manipulará objetos tão diferentes entre si, não seria melhor fazer versões especializadas do método para cada um dos tipos de objetos que pretende manipular?

    Até mais.



  • Eu pretendo fazer uma classe que faça o INSERT, DELETE e o SELECT de um objeto qualquer...



  • Cara, também estou procurando uma alternativa que faça exatamente o que você quer. Uma classe especializada em mapear objetos de c++ para entidades do banco de dados de forma que execute todas as operações de gerenciamento (criar, deletar, editar, consultar) automaticamente, o que também é conhecido como padrão de projeto DAO (data access object). Pesquisei bastante na internet e descobri sobre alguns projetos para C++ que prometem fazer isso, o que mais me interessou foi o "QxOrm":http://www.qxorm.com/qxorm_en/home.html (construído usando Qt) mas ainda não tive tempo de estudar esta ferramenta.

    Outra alternativa é você tentar implementar o padrão DAO, o que é o que estou fazendo atualmente. Criei uma classe base chamada DAO que contém um QSqlDatabase (referência de acesso ao banco), QSqlQuery (para executar comandos). A partir desta classe eu derivo outras que são especializadas em fazer as operações de banco para determinada classe, como por exemplo CidadeDAO, que implementa os métodos criar, deletar, editar e encontrar. Porém esta abordagem está se mostrando altamente improdutiva, pois é preciso se codificar muito (comandos sql). Estou pensando bastante em estudar o qxorm, o que ainda me faz continuar usando a segunda abordagem está no fato de o desempenho e customização serem facilmente manipuláveis.



  • Eu consegui alguma coisa aqui... Quando eu faço um metodo assim:

    @bool inserir(QObject meuObjeto)@

    depois so usar os signals e Slots para trocar mensagens com os objetos...

    eu estava comendo barriga aqui com isso, dai lembrei que fiz algo parecido, mas foi para fazer buscas..

    vou fazer um exemplo aqui e te falo o resultado...



  • Você quer serializar o QObject para gravar num BLOB por exemplo?

    Usamos aqui uma abordagem de serializar o objeto semelhante ao "protobuf":https://code.google.com/p/protobuf/) ou o "boost::serialization":http://www.boost.org/doc/libs/1_53_0/libs/serialization/doc/index.html) mas do nosso jeito aqui (por questões de dependências e performance).



  • Desculpe, nao entendi o que você quis dizer... se possivel de um exemplo...



  • Quando vc disse

    bq. @bool inserir(QObject meuObjeto)@

    me lembrei que usamos aqui um mecanismo para serializar o objeto: transformar a classe em um vetor de bytes. Aí usamos para transmitir (via socket). No seu caso, você poderia armazenar o objeto no banco de dados, numa coluna BLOB. Algo +- assim:

    @
    class Message : public Serializable
    {
    public:
    virtual ~Message( void ) { }
    inline Header & getHeader( void ) { return header; }
    virtual bool Read( Reader & br );
    virtual void Write(Writer & bw );

    private:
    Header header;
    };
    @

    cada classe implementa os Read e Write escrevendo a sua estrutura. Mas aqui não usamos o Qt (estou tentando convencer a galera aqui :-) )

    Acho que talvez, o QMetaObject forneça o que você quer fazer, +- assim:

    @
    class C1 : public QObject
    {
    Q_OBJECT
    private:

    public:
    explicit C1(QObject *parent = 0);

    QString campo1() const; //Tem que existir o método de leitura
    
    Q_PROPERTY(QString campo1 READ campo1)    //Aqui vc declara a propriedade
    

    };
    @

    E depois vc pode enumerar as propriedades:

    @
    int main(int argc, char *argv[])
    {
    C1 *c1 = new C1();

    const QMetaObject* metaObject = c1->metaObject();
    
    for(int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i)
        qDebug() << QString::fromLatin1(metaObject->property(i).name());
    

    }
    @

    Vc poderia listar as propriedades, e mapear as propriedades para cada campo em uma tabela.

    Dê uma olhada "aqui":http://qt-project.org/doc/qt-4.8/properties.html e "aqui":http://qt-project.org/doc/qt-4.8/qmetaobject.html



  • Esou implementando algo aqui para ver se entendo... Voce pode me dizer como que eu faço para identificar o tipo de dado?



  • Sabendo o nome das properties, vc pode acessar via

    @QVariant v = obj->property("nome")@

    onde o valor é "encapsulado" no "QVariant":http://qt-project.org/doc/qt-4.8/qvariant.html.

    Você pode usar o type() ou typeName() do QVariant para saber o tipo.



  • Se nao pedir muito, como faço para pegar o conteudo?

    Ha, consegui por pra imprimir o tipo... To entendendo muito sobre o assunto... vou vazerum tuto ensinando o que eu aprendi... acredito que isso seja duvida de muida gente...



  • Consegui!!!

    header da classe c1:
    @#ifndef C1_H
    #define C1_H

    #include <QObject>

    class C1 : public QObject
    {
    Q_OBJECT
    private:

    public:
    explicit C1(QObject *parent = 0);

    QString campo1();//const; //Tem que existir o método de leitura
    int campo2();
    Q_PROPERTY(QString campo1 READ campo1)//Aqui vc declara a propriedade
    Q_PROPERTY(int campo2 READ campo2)
    

    private:

    };

    #endif // C1_H
    @

    Meu cpp da classe c1
    @#include "c1.h"

    C1::C1(QObject *parent) :
    QObject(parent)
    {
    }

    QString C1::campo1()
    {
    return "Consegui";
    }

    int C1::campo2()
    {
    return 1;
    }@

    Meu main.c ficou assim:

    @#include "mainwindow.h"
    #include <QApplication>
    #include <QDebug>
    #include <QMetaProperty>
    #include <QObject>
    #include <QVariant>
    #include <c1.h>

    static void testeprint(QObject c1)
    {
    const QMetaObject
    metaObject = c1->metaObject();

    for(int i = metaObject->propertyOffset(); i &lt; metaObject-&gt;propertyCount(); ++i)
    {
        QVariant v = c1->property(metaObject->property(i).name());
        qDebug() << QString::fromLatin1(metaObject->property(i).name())<<v.toString()<<v.type();
    
    }
    

    }
    int main(int argc, char *argv[])
    {
    C1 *c1 = new C1;
    testeprint(c1);
    return 0;
    }@

    resultado do qDebug() :

    "campo1" "Consegui" QVariant::QString
    "campo2" "1" QVariant::int

    ObrigadoTioRoy, suas dicas ajudaram muito!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.