Project

General

Profile

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?

    (1-4/4)