Project

General

Profile

Help needed with Combo boxes inside database WTableViews

Added by John Davidson almost 10 years ago

I want to display a WT QueryModel of an database table using a WTableView, in such a way that some of the columns in the WTableView are presented as WComboBox dropdowns populated by queries to other tables. But I don't know how to do this.

I believe Koen will tell me I need to specialise the WTableView, but I don't know how to do this. I'm not a very advanced programmer and I'm not sure I've ever "specialised" anything before.

To get me started on the path to understanding, can anyone point me to/copy and paste an example of a WTableView with combo boxes in one or more of the columns? Or even WTableViews containing other widgets, so I know where to begin. Anything! I've searched and searched.

thanks in advance

John


Replies (8)

RE: Help needed with Combo boxes inside database WTableViews - Added by John Davidson almost 10 years ago

Actually it's not Koen but Wim:

There are two possibilities:

If you want to show the WComboBox only when in 'edit' mode, and just the text while not editing, specialize WItemDelegate and reeimplement createEditor, editState and setEditState.
If you always want to show the combobox, specialize WAbstractItemDelegate, and implement update() so that it always renders a combobox.
Then in your WTableView, call the appropriate method to tell the view to use this delegate (e.g. WAbstractItemView::setItemDelegateForColumn())

Wim.

I read that, but I don't know how to do it!

RE: Help needed with Combo boxes inside database WTableViews - Added by John Davidson almost 10 years ago

And Koen too!

Hey Mohammed,

You need to specialize WItemDelegate and use that item delegate for the particular column(s).

Regards,
koen

Please, Wim or Koen, a quick example?

RE: Help needed with Combo boxes inside database WTableViews - Added by Koen Deforche almost 10 years ago

Hey John,

An example for this is indeed missing, although we've done it a few times in different internal projects.

I've created a feature request for it:

http://redmine.emweb.be/issues/3243

Regards,

koen

RE: Help needed with Combo boxes inside database WTableViews - Added by T Y almost 10 years ago

Hi,

The issue is marked as resolved, but I cannot find either link to example or example coming with distribution.

I would appreciate help on the above.

Thank you.

Kind regards,

TY

RE: Help needed with Combo boxes inside database WTableViews - Added by T Y almost 10 years ago

Ok. After a search for content it is found: examples/widgetgallery/examples/ComboDelegateTable.cpp

This brings me to following observation: After working with Qt and Wt, it is obvious that Wt needs to rethink presentation of documentation.

It would not hurt to provide complete examples (including configuration files). Again, Qt has good was of presenting it.

Otherwise -> Great product. I was looking for /waiting for Wt a long time.

Thank you.

Kind regards,

TY

RE: Help needed with Combo boxes inside database WTableViews - Added by Joseph Witanto over 8 years ago

Hi, I am new to Wt C (a few weeks), and I am also trying to implement combobox at tableview

The query is from two tables (master-detail)

The combobox did appear, but it seems that when the option is selected, it isn't saved and the tableview (or the querymodel) is not changed

Anybody knows what is the problem?

Thanks for the time

#ifndef COMBO_DELEGATE_H_
#define COMBO_DELEGATE_H_

#include <Wt/WStringListModel>
#include <Wt/WTableView>
#include <Wt/WItemDelegate>
#include <Wt/WContainerWidget>
#include <Wt/WComboBox>

/*
 * This delegate demonstrates how to override the editing behaviour of a
 * table cell.
 *
 * It takes a list of possible items on construction and, when edited, saves
 * the selected item from the list to the Wt::DisplayRole in the model for
 * Wt::WItemDelegate to render.
 * It also saves the items index for future editing (rather than each time
 * searching the item in the list). This is done using the general purpose
 * Wt::UserRole in the model.
 */
class ComboDelegate : public Wt::WItemDelegate {
public:
    ComboDelegate(Wt::WAbstractItemModel* items)
    : items_(items)
    { }

    void setModelData(const boost::any &editState, Wt::WAbstractItemModel* model,
              const Wt::WModelIndex &index) const
    {
        int stringIdx = (int)Wt::asNumber(editState);
        model->setData(index, items_->data(stringIdx, 0, Wt::UserRole), Wt::UserRole);
        model->setData(index, items_->data(stringIdx, 0, Wt::UserRole), Wt::DisplayRole);
    }

    boost::any editState(Wt::WWidget* editor) const
    {
        Wt::WComboBox* combo = dynamic_cast<Wt::WComboBox*>
            (dynamic_cast<Wt::WContainerWidget*>(editor)->widget(0));
        return combo->currentIndex();
    }

    void setEditState(Wt::WWidget* editor, const boost::any &value) const
    {
        Wt::WComboBox* combo = dynamic_cast<Wt::WComboBox*>
            (dynamic_cast<Wt::WContainerWidget*>(editor)->widget(0));
        combo->setCurrentIndex((int)Wt::asNumber(value));
    }

protected:
    virtual Wt::WWidget* createEditor(const Wt::WModelIndex &index,
                      Wt::WFlags<Wt::ViewItemRenderFlag> flags) const
    {
        Wt::WContainerWidget *const container = new Wt::WContainerWidget();
        Wt::WComboBox* combo = new Wt::WComboBox(container);
        combo->setModel(items_);
        combo->setCurrentIndex((int)Wt::asNumber(index.data(Wt::UserRole)));

        combo->changed().connect(boost::bind(&ComboDelegate::doCloseEditor, this,
                             container, true));
        combo->enterPressed().connect(boost::bind(&ComboDelegate::doCloseEditor,
                                  this, container, true));
        combo->escapePressed().connect(boost::bind(&ComboDelegate::doCloseEditor,
                               this, container, false));

        return container;
    }

private:
    Wt::WAbstractItemModel* items_;

    void doCloseEditor(Wt::WWidget *editor, bool save) const
    {
        closeEditor().emit(editor, save);
    }
};

#endif

//at main
            qmDetail_ = new dbo::QueryModel<Item>();
            qmDetail_->setQuery(session_.query<Item>
                ("select ActivityTemplateDetail, Category.name "
                "from activity_template_detail ActivityTemplateDetail join category Category "
                "on ActivityTemplateDetail.categoryTemplate_id = Category.id")
                .where("ActivityTemplateDetail.activityTemplate_id = ?").bind(id));


            qmDetail_->addColumn("ActivityTemplateDetail.id", "ID", Wt::ItemIsSelectable);
            qmDetail_->addColumn("ActivityTemplateDetail.value", "ValueWt::ItemIsEditable);
            qmDetail_->addColumn("categoryTemplate_id", "Category", Wt::ItemIsEditable);

            WTableView * tableView = new WTableView();
            tableView->setModel(qmDetail_);
            WStandardItemModel *si = new WStandardItemModel();

            WStandardItem *i = new WStandardItem();
            i->setData(1, UserRole);
            i->setText("Def");
            si->appendRow(i);

            i = new WStandardItem();
            i->setData(2, UserRole);            
            i->setText("Abc");
            si->appendRow(i);

            ComboDelegate* customdelegate = new ComboDelegate(si);
            tableView->setItemDelegateForColumn(2, customdelegate);

RE: Help needed with Combo boxes inside database WTableViews - Added by Mark O'Donovan over 7 years ago

I am having the same issue.

I believe the WTableview will not call setModelData() because editing has not been triggered.

Normally clicking/double-clicking etc. a WItemDelegate would cause WTableView to call edit().

edit() adds the index to editedItems_.

This causes isEditing() to return true in WTableView::renderWidget().

In this case renderWidget() sets the RenderEditing flag when requesting a widget from the delegate.

A WItemDelegate will then return an WLineEdit instead of a WText.

The WItemDelegate's closeEditor() signal is connected to WAbstractItemView::closeEditorWidget.

closeEditorWidget() looks something like this:

if( editor in editedItems_ )

delegate->setModelData(editState, model(), index)

So getting the delegate to return an editor is not enough, we also need to get that editor into editedItems_

Perhaps one of the experts could tell us what to do here??

RE: Help needed with Combo boxes inside database WTableViews - Added by Koen Deforche over 7 years ago

Hey,

I modified the widget gallery example just to check but the modified value is there correctly set to the model?

Wt::WPushButton *button = new Wt::WPushButton("Test", example);
button->clicked().connect(std::bind([=]() {
      for (int r = 0; r < model->rowCount(); ++r) {
    for (int c = 0; c < model->columnCount(); ++c) {
      std::cerr << "\t" << Wt::asString(model->data(r, c));
    }
    std::cerr << "\n";
      }
    }));

gives after changing the first value:

    pears   apples
    apples  apples

Regards,

koen

    (1-8/8)