WItemDelegate, how to use it?
Added by Ulf Johnsson over 3 years ago
Hi.
I have a bunch of custom delegates that derrive from WItemDelegate that use to work in Wt3,
but no longer work in Wt4.
I dont know if Im doing something wrong or if this is a bug?
It seems like if the widget pointer that is sent to WItemDelegate is always deallocated no matter what I do (if the pointer is != nullptr).
Can I not reuse the widget? I would have thought that if the widget was already valid I could just update its data based on index.
Example, press the button and a crasch occurrs:
class Delegate : public Wt::WItemDelegate
{
public:
Delegate() : Wt::WItemDelegate() {}
std::unique_ptr<Wt::WWidget> update(Wt::WWidget* widget, const Wt::WModelIndex& index, Wt::WFlags<Wt::ViewItemRenderFlag> flags) override
{
if(widget)
{
std::unique_ptr<Wt::WWidget> w(widget);
return std::move(w);
}
std::unique_ptr<Wid> wid(new Wid);
wid->setText(Wt::cpp17::any_cast<Wt::WString>(index.data()));
return std::move(wid);
}
};
class App : public Wt::WApplication {
public:
App(const Wt::WEnvironment& env) : Wt::WApplication(env)
{
}
void initialize() override
{
Wt::WApplication::initialize();
auto tree = root()->addWidget(std::make_unique<Wt::WTreeView>());
tree->resize(400, 600);
std::shared_ptr<Wt::WStringListModel> _model(new Wt::WStringListModel);
std::vector<Wt::WString> data;
for(int index = 0; index < 1000; ++index)
{
Wt::WString d(QString::number(index).toStdString());
data.push_back(d);
}
_model->setStringList(data);
tree->setModel(_model);
tree->setItemDelegate(std::make_shared<Delegate>());
_tree = tree;
auto btn = root()->addWidget(std::make_unique<Wt::WPushButton>());
btn->resize(100, 100);
btn->clicked().connect(this, &App::onBtnClicked);
}
void onBtnClicked()
{
_tree->model()->dataChanged().emit(_tree->model()->index(0,0), _tree->model()->index(0, 0));
}
private:
Wt::WTreeView* _tree;
};
Replies (4)
RE: WItemDelegate, how to use it? - Added by Ulf Johnsson over 3 years ago
Am I supposed to use it like this if I wanna reuse the widget?
class Delegate : public Wt::WItemDelegate
{
public:
Delegate() : Wt::WItemDelegate() {}
std::unique_ptr<Wt::WWidget> update(Wt::WWidget* widget, const Wt::WModelIndex& index, Wt::WFlags<Wt::ViewItemRenderFlag> flags) override
{
if(widget)
{
auto w = widget->removeFromParent();
auto t = dynamic_cast<Wid*>(w.get())->setText("updated text!");
return w;
}
std::unique_ptr<Wid> wid(new Wid);
wid->setText(Wt::cpp17::any_cast<Wt::WString>(index.data()));
return std::move(wid);
}
};
RE: WItemDelegate, how to use it? - Added by Roel Standaert over 3 years ago
You only need to return a non-null pointer if you're creating the original widget, or you want to replace the widget. If you want to keep the widget, you can just return nullptr
.
The only situation where you'd use removeFromParent
on the widget
argument is if you'd want to reuse it, e.g. return a new widget that contains the old widget.
RE: WItemDelegate, how to use it? - Added by Ulf Johnsson over 3 years ago
Thanks for your reply.
That should definitly be in the documentation though, it does seem ovious that that is how it works.
BR, Ulf.
RE: WItemDelegate, how to use it? - Added by Roel Standaert over 3 years ago
As far as I can tell, that is what the documentation of the update
function says, though. I don't know how you think we should further clarify it?