Search code examples
c++wt

Wt - How to retrieve selected record from WTableView?


I'm learning the basis of Web Toolkit (Wt, AKA "Witty"). Now I'm struggling with WTableViews and QueryModels. I'm unable to retrieve the record selected from it.

I have this table TableTag defined as:

class TableTag
{
public:
    static const unsigned int tableVersion = 1;
    std::string name;

    TableTag();
    ~TableTag();
    static void initTableRecords(Wt::Dbo::Session &_session);

    template<class Action>
    void persist(Action &_action)
    {
        Wt::Dbo::field(_action, name, "Name");

        //Wt::Dbo::hasMany(_action, tablePosts, Wt::Dbo::ManyToMany, "Post");
    }
};
typedef Wt::Dbo::collection< Wt::Dbo::ptr<TableTag> > TableTags;

I show it this way:

DDBBApp::DDBBApp(const WEnvironment& _env) : WApplication(_env),
    ddbbBackend_(DDBBApp::DDBB_DATA_NAME)
{
    DDBBApp::setDDBBBackendAndSession(ddbbBackend_,ddbbSession_);
    ctrNotice_ = new WText("Notice text"); //Informative text

    //QueryModel    
    Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > * qmTags1 = new Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> >();
    qmTags1->setQuery(ddbbSession_.find<TableTag>());
    qmTags1->addAllFieldsAsColumns();

    //WTableView    
    ctrGridTags_ = new WTableView();
    ctrGridTags_->setModel(qmTags1);
    ctrGridTags_->setSelectionMode(Wt::SelectionMode::SingleSelection);
    this->root()->addWidget(ctrGridTags_);
    this->root()->addWidget(new WBreak);

    //Info text
    this->root()->addWidget(ctrNotice_);

    //Conection SIGNAL - SLOT
    ctrGridTags_->selectionChanged().connect(this, &DDBBApp::onSelectionChanged);
}

I want to retrieve the record selected by user:

void DDBBApp::onSelectionChanged()
{
    WString str("Select done: ");

    WModelIndexSet indexSet_Tags = ctrGridTags_->selectedIndexes();
    for (WModelIndexSet::iterator index_iterator = indexSet_Tags.begin(); index_iterator != indexSet_Tags.end(); ++index_iterator)
    {
        //Here I get the idx of the record selected in WTableView
        WModelIndex index = *index_iterator;
        str += WString(std::to_string(index.row()));

        boost::any data = ctrGridTags_->model()->data(index);
        if (data.type() == typeid(__int64))
        {
            //Here I get the Id of record
            __int64 dataint64 = boost::any_cast<__int64>(data);
            str += " " + WString(std::to_string(dataint64));
        }
        else
        {
            std::string dataTypeName(data.type().name());
            str += " (" + dataTypeName + ")";
        }

        //THIS IS THE PROBLEMATIC SECTION
        Wt::WAbstractItemModel * aim = ctrGridTags_->model(); //OK but it's not specifically related to TableTags (it's general)
        Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > qmtt1(aim); //NULL ¿?

        Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > queryModel = ctrGridTags_->model(); //NULL too ¿?

        Wt::Dbo::QueryModel<Wt::Dbo::ptr<TableTag>> modelus = static_cast<Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> >> (ctrGridTags_->model()); //NULL... no way :-(          

                              v-- error due to null value (qmtt1, queryModel, modelus) 
        std::string tagName = queryModel.resultRow(index.row()).get()->name;
        str += " " + tagName ;
    }

    ctrNotice_->setText(str);
}

I think the code is auto-descritpive enough. The clearest reference I found was this: How to get at underlying data in a WTableView based on a QueryModel?. If try as suggested there, several compile errors arise.

Debugging, I see WTableView's member Model as type Wt::Dbo::QueryModel< Wt::Dbo::ptr >. But, when it's assigned to other variable of same type, that variable doesn't get it. why?

Can anybody point me the right way, please?

EDIT 1

I point some extra details:

My code includes these headers:

#include <Wt/Dbo/Dbo>
#include <Wt/Dbo/Backend/Sqlite3>
#include <Wt/Dbo/Query>
#include <Wt/Dbo/QueryModel>
#include <Wt/Dbo/SqlTraits>
#include <Wt/Dbo/Types>
#include <Wt/Dbo/WtSqlTraits>

If I try this way (similar to the one proposed by Koen):

Wt::Dbo::QueryModel<TableTag> *modelKoen = dynamic_cast<Wt::Dbo::QueryModel<TableTag> *> (ctrGridTags_->model());

I get this compilation error:

C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/SqlTraits_impl.h(50): error C2039: 'read' : is not a member of 'Wt::Dbo::sql_value_traits<Result,void>'
          with
          [
              Result=TableTag
          ]
***
*** NOT TRANSLATED FROM SPANISH ***
***
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/SqlTraits_impl.h(48) : durante la compilación de la función miembro de plantilla de clase 'TableTag Wt::Dbo::query_result_traits<Result>::load(Wt::Dbo::Session &,Wt::Dbo::SqlStatement &,int &)'
          with
          [
              Result=TableTag
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/collection_impl.h(186) : vea la referencia a la creación de instancias de plantilla de función 'TableTag Wt::Dbo::query_result_traits<Result>::load(Wt::Dbo::Session &,Wt::Dbo::SqlStatement &,int &)' que se está compilando
          with
          [
              Result=TableTag
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/SqlTraits_impl.h(27) : durante la compilación de la función miembro de plantilla de clase 'void Wt::Dbo::query_result_traits<Result>::getFields(Wt::Dbo::Session &,std::vector<std::string,std::allocator<_Ty>> *,std::vector<Wt::Dbo::FieldInfo,std::allocator<Wt::Dbo::FieldInfo>> &)'
          with
          [
              Result=TableTag
  ,            _Ty=std::string
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/Query_impl.h(106) : vea la referencia a la creación de instancias de plantilla de función 'void Wt::Dbo::query_result_traits<Result>::getFields(Wt::Dbo::Session &,std::vector<std::string,std::allocator<_Ty>> *,std::vector<Wt::Dbo::FieldInfo,std::allocator<Wt::Dbo::FieldInfo>> &)' que se está compilando
          with
          [
              Result=TableTag
  ,            _Ty=std::string
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/Query_impl.h(102) : durante la compilación de la función miembro de plantilla de clase 'std::vector<Wt::Dbo::FieldInfo,std::allocator<_Ty>> Wt::Dbo::Impl::QueryBase<Result>::fields(void) const'
          with
          [
              _Ty=Wt::Dbo::FieldInfo
  ,            Result=TableTag
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/Query_impl.h(133) : vea la referencia a la creación de instancias de plantilla de función 'std::vector<Wt::Dbo::FieldInfo,std::allocator<_Ty>> Wt::Dbo::Impl::QueryBase<Result>::fields(void) const' que se está compilando
          with
          [
              _Ty=Wt::Dbo::FieldInfo
  ,            Result=TableTag
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/Query_impl.h(124) : durante la compilación de la función miembro de plantilla de clase 'std::pair<Wt::Dbo::SqlStatement *,Wt::Dbo::SqlStatement *> Wt::Dbo::Impl::QueryBase<Result>::statements(const std::string &,const std::string &,const std::string &,int,int) const'
          with
          [
              Result=TableTag
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/Query_impl.h(483) : vea la referencia a la creación de instancias de plantilla de función 'std::pair<Wt::Dbo::SqlStatement *,Wt::Dbo::SqlStatement *> Wt::Dbo::Impl::QueryBase<Result>::statements(const std::string &,const std::string &,const std::string &,int,int) const' que se está compilando
          with
          [
              Result=TableTag
          ]
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/QueryModel_impl.h(137) : durante la compilación de la función miembro de plantilla de clase 'void Wt::Dbo::QueryModel<TableTag>::setCurrentRow(int) const'
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/QueryModel_impl.h(127) : vea la referencia a la creación de instancias de plantilla de función 'void Wt::Dbo::QueryModel<TableTag>::setCurrentRow(int) const' que se está compilando
          C:\Opt\Wt 3.3.3 msvs2013 x64\include\Wt/Dbo/QueryModel_impl.h(126) : durante la compilación de la función miembro de plantilla de clase 'boost::any Wt::Dbo::QueryModel<TableTag>::data(const Wt::WModelIndex &,int) const'

As far as I've seen in Internet, the common errors are

'read' : is not a member of 'Wt::Dbo::sql_value_traits<long,void>  
'read' : is not a member of 'Wt::Dbo::sql_value_traits<string,void> 

and so on. Compare those with my

'read' : is not a member of 'Wt::Dbo::sql_value_traits<Result,void>

They are usually solved including headers

#include <Wt/Dbo/SqlTraits
#include <Wt/Dbo/WtSqlTraits>

but not in my case.

Any suggestion?


Solution

  • Oh my, I finally got it myself.

    The right way was:

    Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > * qmTags = static_cast<Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > *>(ctrGridTags_->model());
    

    instead of:

    Wt::Dbo::QueryModel<Wt::Dbo::ptr<TableTag>> modelus = static_cast<Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> >> (ctrGridTags_->model());
    

    The resulting working code becomes as follows:

    void DDBBApp::onSelectionChanged()
    {
        WString str("Select done: ");
    
        WModelIndexSet indexSet_Tags = ctrGridTags_->selectedIndexes();
        for (WModelIndexSet::iterator index_iterator = indexSet_Tags.begin(); index_iterator != indexSet_Tags.end(); ++index_iterator)
        {
            WModelIndex index = *index_iterator;
            str += WString(std::to_string(index.row()));
    
            boost::any data = ctrGridTags_->model()->data(index);
            if (data.type() == typeid(int))
            {
                int dataInt = boost::any_cast<int>(data);
                str += " " + WString(std::to_string(dataInt));
            }
            else if (data.type() == typeid(std::string))
            {
                std::string dataString = boost::any_cast<std::string>(data);
                str += " " + WString(dataString);
            }
            else if (data.type() == typeid(long))
            {
                long dataLong = boost::any_cast<long>(data);
                str += " " + WString(std::to_string(dataLong));
            }
            else if (data.type() == typeid(__int64))
            {
                __int64 dataint64 = boost::any_cast<__int64>(data);
                str += " " + WString(std::to_string(dataint64));
            }
            else
            {
                std::string dataTypeName(data.type().name());
                str += " (" + dataTypeName + ")";
            }
    
            Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > * qmTags = static_cast<Wt::Dbo::QueryModel< Wt::Dbo::ptr<TableTag> > *>(ctrGridTags_->model());
            std::string tagName = qmTags->resultRow(index.row()).get()->name;
            str += " " + tagName;
        }
    
        ctrNotice_->setText(str);
    }