Project

General

Profile

Using two Models in WCartesianChart

Added by Christian Meyer over 2 years ago

Hi there

Is there any Example about using two Models?
I can't seem to get the second to show...

I found here https://redmine.webtoolkit.eu/boards/2/topics/16703
that it should be possible ...

The Examples are all using a new Column for the Data, but as the primary source for me is a QueryModel, how would I go about that?

And given the Info from the Post linked above, there would be just 2 Rows in the Second Model to create a Line, this Line would be broken up anyway.

Might be special case as I map to DateTime on xAxis...

Idea is to have a bunch of Points with WDateTime field, which works fine with a QueryModel.
Showing a Line in a certain TimeRange with two Points does not happen for me...

here's my code if someone has a chance to look it through?


auto timeQuery = trackPtr->dataPoints.find()
                    .where("datetime BETWEEN ? AND ?")
                    .bind(tPtr->getStartTime())
                    .bind(endTime);

// dataModel is QueryModel

dataModel->setQuery(timeQuery);
dataModel->addColumn("datetime");  // type WDateTime
dataModel->addColumn("value");     // type int


tChart->setModel(dataModel);
tChart->setAutoLayoutEnabled(true);
tChart->setXSeriesColumn(0);
tChart->xAxis(0).setScale(Wt::Chart::AxisScale::DateTime);


auto dataSeries = 
    std::make_unique<Wt::Chart::WDataSeries>(1, Wt::Chart::SeriesType::Point, 0);
dataSeries->setPen(Wt::WPen(Wt::StandardColor::Red));

tChart->addSeries(std::move(dataSeries)); 
// The dataSeries shows up Fine and uses dataModel



// Probably overkill, but currently not sure how to create this differently
// or for that matter apparently correctly

auto startItem = std::make_unique<Wt::WStandardItem>();
{
    auto startDateItem = std::make_unique<Wt::WStandardItem>();
    startDateItem->setData(tPtr->getStartTime());
    auto startValueItem = std::make_unique<Wt::WStandardItem>();
    startValueItem->setData(tPtr->getTargetValue());

    startItem->setChild(0, 0, std::move(startDateItem));
    startItem->setChild(0, 1, std::move(startValueItem));
}

auto endItem = std::make_unique<Wt::WStandardItem>();
{
    auto endDateItem = std::make_unique<Wt::WStandardItem>();

    if(tPtr->getTargetTime().isValid())
        endDateItem->setData(tPtr->getTargetTime());
    else
        endDateItem->setData(Wt::WDateTime::currentDateTime(), Wt::ItemDataRole::User);

    auto endValueItem = std::make_unique<Wt::WStandardItem>();
    endValueItem->setData(tPtr->getTargetValue());

    endItem->setChild(0, 0, std::move(endDateItem));
    endItem->setChild(0, 1, std::move(endValueItem));
}
targetModel->appendRow(std::move(startItem));
targetModel->appendRow(std::move(endItem));

Wt::log("targetSeries") << "Items: " << targetModel->rowCount(); 
// Shows 2 Items, as expected;

auto targetSeries = std::make_unique<Wt::Chart::WDataSeries>(1, Wt::Chart::SeriesType::Point, 1); // or ::Line
targetSeries->setModel(
    std::make_shared<Wt::Chart::WStandardChartProxyModel>(targetModel));
targetSeries->setPen(Wt::WPen(Wt::StandardColor::Blue));
targetSeries->setXSeriesColumn(0);


tChart->addSeries(std::move(targetSeries));
// These two Points do not show up! Not even if they are alone in the Chart!
// I would like to Paint a Line with this Series

I have no Idea where to look anymore.
In the examples is nothing that would help me.

Thanks!


Replies (2)

RE: Using two Models in WCartesianChart - Added by Roel Standaert over 2 years ago

Hello Christian,

I think you're not creating your model correctly. WStandardItemModel can create tree table structures, and that's what you're doing here. Your code creates a model that's structured like this:

  • startItem / (empty)
    • startDateItem / startValueItem
  • endItem / (empty)
    • endDateItem / endValueItem

Instead, you want to create a table structure like this:

  • startDateItem / startValueItem
  • endDateItem / endValueItem

You could do that like this:

{
    auto startDateItem = std::make_unique<Wt::WStandardItem>();
    startDateItem->setData(tPtr->getStartTime());
    auto startValueItem = std::make_unique<Wt::WStandardItem>();
    startValueItem->setData(tPtr->getTargetValue());

    targetModel->appendRow({std::move(startDateItem), std::move(startValueItem)});
}

{
    auto endDateItem = std::make_unique<Wt::WStandardItem>();

    if(tPtr->getTargetTime().isValid())
        endDateItem->setData(tPtr->getTargetTime());
    else
        endDateItem->setData(Wt::WDateTime::currentDateTime(), Wt::ItemDataRole::User);

    auto endValueItem = std::make_unique<Wt::WStandardItem>();
    endValueItem->setData(tPtr->getTargetValue());

    targetModel->appendRow({std::move(endDateItem), std::move(endValueItem)});
}

Regards,
Roel

RE: Using two Models in WCartesianChart - Added by Christian Meyer over 2 years ago

Thank you for your fast Reply!

I tried it but could not even compile...
Error: static assertion failed: result type must be constructible from value type of input range
here: targetModel->appendRow({std::move(startDateItem), std::move(startValueItem)});

I tried creating a std::vector

  • with Initializer List
  • and push_back / emplace_back in the items before doing appendRow

-> same Error so maybe the way to append a row is not the best?

I tried

targetModel->invisibleRootItem()->setChild(0, 0, std::move(startDateItem));
targetModel->invisibleRootItem()->setChild(0, 1, std::move(startValueItem));

This compiled, but still did not show up in the chart...

UNTIL

I tried to show the Model in a WTableView.
The row and columnCount was correct, but nothing to be seen ...
Then I tried to add Wt::ItemDataRole::Display to the setData calls ... and oh wonder ...
Both TableView and Chart had the Data!

THANK YOU SO MUCH!

That did drive me crazy the last few days.

Cheers

    (1-2/2)