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?
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);
}