How to notify ListView that DataModel has changed - qml

I created a ListView and I want to use it with a custom DataModel. However, I have a problem: at the moment the view gets created, I don't have the data loaded into the model. The model data is set after the view is created and when I set the data onto the model, the view doesn't update and doesn't read again the model data. This is my ListView:
ListViewCountainer.qml
Container {
// countryModelData is set after ListViewCountainer gets created
// when countryModelData gets set, the model is populated with data
property variant countryModelData
leftPadding: 20.0
rightPadding: 20.0
topPadding: 20.0
bottomPadding: 20.0
CountryDetailsListView {
id: countryDetailsListView
dataModel: CountryDataModel {
countryData: countryModelData
}
}
}
And here is my model:
countrydatamodel.h
#ifndef COUNTRYDATAMODEL_H_
#define COUNTRYDATAMODEL_H_
#include <QtCore/QAbstractListModel>
#include <QtCore/QList>
#include <QObject>
#include <QtCore/QVariant>
#include <bb/cascades/DataModel>
#include <bb/data/JsonDataAccess>
class CountryDataModel : public bb::cascades::DataModel
{
Q_OBJECT
Q_PROPERTY(QVariant countryData READ getCountryData WRITE setCountryData)
public:
CountryDataModel(QObject* parent = 0);
virtual ~CountryDataModel();
Q_INVOKABLE int childCount(const QVariantList& indexPath);
Q_INVOKABLE QVariant data(const QVariantList& indexPath);
Q_INVOKABLE bool hasChildren(const QVariantList& indexPath);
Q_INVOKABLE QString itemType(const QVariantList& indexPath);
Q_INVOKABLE void removeItem(const QVariantList& indexPath);
Q_INVOKABLE QVariant getCountryData();
Q_INVOKABLE void setCountryData(QVariant data);
private:
QVariantList m_elements;
};
#endif /* COUNTRYDATAMODEL_H_ */
countrydatamodel.cpp
#include <src/countrydatamodel.h>
#include <QtCore/QtAlgorithms>
#include <QtCore/QDebug>
#include <bb/cascades/DataModel>
#include <bb/data/JsonDataAccess>
CountryDataModel::CountryDataModel(QObject* parent) : bb::cascades::DataModel(parent)
{
}
CountryDataModel::~CountryDataModel()
{
}
bool CountryDataModel::hasChildren(const QVariantList &indexPath)
{
qDebug() << "==== CountryDataModel::hasChildren" << indexPath;
if ((indexPath.size() == 0))
{
return true;
}
else
{
return false;
}
}
int CountryDataModel::childCount(const QVariantList &indexPath)
{
qDebug() << "==== CountryDataModel::childCount" << indexPath;
if (indexPath.size() == 0)
{
qDebug() << "CountryDataModel::childCount" << m_elements.size();
return m_elements.size();
}
qDebug() << "==== CountryDataModel::childCount" << 0;
return 0;
}
QVariant CountryDataModel::data(const QVariantList &indexPath)
{
qDebug() << "==== CountryDataModel::data" << indexPath;
if (indexPath.size() == 1) {
return m_elements.at(indexPath.at(0).toInt());
}
QVariant v;
return v;
}
QString CountryDataModel::itemType(const QVariantList &indexPath)
{
Q_UNUSED(indexPath);
return "";
}
void CountryDataModel::removeItem(const QVariantList& indexPath)
{
if(indexPath.size() == 1) {
m_elements.removeAt(indexPath.at(0).toInt());
}
emit itemRemoved(indexPath);
}
QVariant CountryDataModel::getCountryData()
{
return QVariant(m_elements);
}
void CountryDataModel::setCountryData(QVariant data)
{
m_elements = data.toList();
qDebug() << "================== CountryDataModel: " << m_elements;
}
I put some debug messages in the childCount function for example and it gets called only once, which means that the ListView asks the model for the data just once, when the model is created.
Is it possible to force ListView to read again the data from the model after the model gets populated with data? Or how could I make this approach work and load the data in the view?
Thanks!

In order for the model to be updated, the setCountryData member function needs to be updated like so:
void CountryDataModel::setCountryData(QVariant data)
{
m_elements = data.toList();
emit itemsChanged(bb::cascades::DataModelChangeType::AddRemove, QSharedPointer< bb::cascades::DataModel::IndexMapper >(0));
}
FML...

You need to declare a signal for the property you want to update in backend.
Q_PROPERTY(QVariant countryData READ getCountryData WRITE setCountryData NOTIFY contryDataChanged)
add its declaration as well.
Then you say -
emit contryDataChanged();
wherever you feel like list should re-read contents. (normally setter methods).

Related

passing a class variable to API function

I want to track a global variable that I am passing into an API function. I found that one could do it using a class:
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
//T operator T() const { return m_value; }
const MonitoredVariable& operator = (const T& value)
{
PlugIn::gResultOut << "value changed " << std::endl;
m_value = value;
return *this;
}
private:
T m_value;
};
The API function takes variables as
bool APIFunction(double time, bool *is_done, double *fraction_done);
The following gives me an error:
ImagePtr Im;
bool is_done;
MonitoredVariable<double*> fraction_done;
bool frameready = Im->APIFunction(2.1, is_done, fraction_done);
ERROR:
error C2664: cannot convert argument 3 from 'MonitoredVariable<double *>' to 'double *'
what would I have to change here?
thx!
I'm not really sure if this is what you want:
#include <iostream>
using namespace std;
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
//T operator T() const { return m_value; }
const MonitoredVariable& operator = (const T& value)
{
//PlugIn::gResultOut << "value changed " << std::endl;
m_value = value.m_value;
return *this;
}
void printValue() {
std::cout << m_value;
}
T& getValue() {
return m_value;
}
private:
T m_value;
};
bool func(double firstDouble, bool *is_done, double* fraction_done) {
// do stuff
*fraction_done = firstDouble + (40.23 * 5);
*is_done = true;
return true;
}
int main()
{
bool is_done = true;
MonitoredVariable<double> fraction_done;
func(2.10, &is_done, &fraction_done.getValue());
fraction_done.printValue();
return 0;
}
So basically we have a Class called MonitoredVariable which has a variable called m_value. I'm not really sure why you wanted it to be a pointer, because we can also take the address of a normal double variable.
In the following it makes perhaps more sense what I want to achieve. I want to input a class variable into an API function and monitor the variable in real time. This value goes from zero to 1 every 3 ms or so. Yet I try to avoid using while loop and track it within the class with overloaded = operator.
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <future>
using namespace std;
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
void printValue() {
std::cout << m_value;
}
const MonitoredVariable& operator = (const T& value)
{
m_value = value.m_value;
if(m_value> 0.8) std::cout << m_value; // *THIS NEVER GETS PRINTED!!!*
return *this;
}
T& getValue() {
return m_value;
}
private:
T m_value;
};
bool func(bool *is_done, double* fraction_done) {
unsigned long c = 1;
while (*is_done)
{
*fraction_done = (double) 0.01*c;
this_thread::sleep_for(chrono::milliseconds(10));
c++;
if (*fraction_done >= 1) *is_done = false;
}
return true;
}
int main()
{
bool is_done = true;
MonitoredVariable<double> *MonitoredVariablePtr = new MonitoredVariable<double>();
std::future<bool> fu = std::async(std::launch::async,func, &is_done, &MonitoredVariablePtr->getValue());
// IF I UNCOMMENT THIS, IT PRINTS...
/*
while(is_done)
{
if(MonitoredVariablePtr->getValue() > 0.8) MonitoredVariablePtr->printValue();
}
*/
return 0;
}
Why does not the (if(m_value> 0.8) std::cout << m_value) line within the class never gets printed when the value is updated?
THX!

Port not bound SystemC (E112)

I am trying to implement a producer (master) speaking to a memory element (slave) through the memory controller (which implements the interface simple_mem_interface).
Note: Some functions details and include statements are not fully mentioned in the code attached.
Searching for bugs in the code.
Adding debugging tools to find the fault in Write Enable Port.
binding.cpp
int sc_main(int argc, char* argv[])
{
sc_signal<unsigned int> d_out,d_in,address_d;
sc_signal<bool> wen, ren, ack;
sc_clock ClkFast("ClkFast", 100, SC_NS);
sc_clock ClkSlow("ClkSlow", 50, SC_NS);
Memory_Controller Controller1 ("Controller");
d_out = Controller1.data_mem_read;
ren.write(Controller1.REN);
ack.write(Controller1.ack);
d_in.write(Controller1.data_write);
address_d.write(Controller1.address);
wen.write(Controller1.WEN);
producer P1("Producer");
P1.out(Controller1);
P1.Clk(ClkFast);
Memory_module MEM("Memory");
MEM.Wen(wen);
MEM.Ren(ren);
MEM.ack(ack);
MEM.Clock(ClkSlow);
MEM.data_in(d_in);
MEM.data_out(d_out);
MEM.address(address_d);
sc_start(5000, SC_NS);
return 0;
Memory_controller.h
#define MEM_SIZE 100
#include <interface_func.h>
class Memory_Controller : public sc_module, public simple_mem_if
{
public:
// Ports
sc_in <unsigned int> data_mem_read{ "Data_Read_from_Memory" };
sc_out<bool> REN { "Read_Enable" };
sc_out<bool> WEN { "Write_Enable" };
sc_out <bool> ack{ "ACK_Bool" };
sc_out<unsigned int> address{ "Memory_Address" }, data_write{
"Data_Written_to_Memory" };
// constructor
Memory_Controller(sc_module_name nm) : sc_module(nm)
{ // Creating a 2 dimentional array holding adresses and data
WEN.write(false);
REN.write(false);
ack.write(false);
}
~Memory_Controller() //destructor
{
}
bool Write(unsigned int address_i, unsigned int datum) // blocking write
{
WEN.write(true);
REN.write(false);
data_write.write(datum);
address.write(address_i);
if (ack == true)
return true;
else
return false;
}
bool Read(unsigned int address_i, unsigned int& datum_i) // blocking read
{
WEN.write(false);
REN.write(true);
datum_i=data_mem_read;
address.write(address_i);
if (ack == true)
return true;
else
return false;
}
void register_port(sc_port_base& port, const char* if_typename)
{
cout << "binding " << port.name() << " to "
<< "interface: " << if_typename << endl;
}
};
Memory.h
#define MEM_SIZE 100
#include "interface_func.h"
class Memory_module : public sc_module
{
public:
sc_in<bool> Wen,Ren;
sc_in <unsigned int> address, data_in ;
sc_in<bool> Clock;
sc_out <unsigned int> data_out;
sc_out <bool> ack;
bool fileinput = false;
ifstream myfile;
unsigned int item [MEM_SIZE];
Memory_module()
{
}
void Write() // blocking write
{
while (true)
{
wait();
if (Wen==true)
{
if (address >= MEM_SIZE || address < 0)
{
ack=false;
}
else
{
item[address]=data_in;
ack=true;
}
}
}
}
void Read() // blocking read
{
while (true)
{
wait();
if (Ren)
{
if (address >= MEM_SIZE || address < 0)
ack=false;
else
{
data_out.write(item[address]);
ack=true;
}
}
}
}
SC_CTOR(Memory_module)
{
SC_THREAD(Read);
sensitive << Clock.pos();
SC_THREAD(Write);
sensitive << Clock.pos();
}
};
interface_func.h
class simple_mem_if : virtual public sc_interface
{
public:
virtual bool Write(unsigned int addr, unsigned int data) = 0;
virtual bool Read(unsigned int addr, unsigned int& data) = 0;
};
After debugging the SystemC binder.cpp code, the following error arises:
(E112) get interface failed: port is not bound : port 'Controller.Write_Enable' (sc_out)
You cannot drive your unconnected ports in the Memory_Controller constructor. If you want to explicitly drive these ports during startup, move these calls to a start_of_simulation callback:
Memory_Controller(sc_module_name nm) : sc_module(nm)
{}
void start_of_simulation()
{
WEN.write(false);
REN.write(false);
ack.write(false);
}

OpenKinect acquire raw depth image

I am trying to use the example code from here.
I have made some changes in order to save the images to the computer. When I read the data in MATLAB it seems like values that should be 0 are set to 2047, and overall it does not seem to be correct when I reconstruct the 3D points using the default intrinsic camera parameters.
What I want to achieve is to save the images so that I can use
img = single(imread(depth.png'))/ 1000
and have the depth values in meters, and pixels with no measurements should be zero.
It is the Kinect V1 by the way.
Here is the code with comments where I have tried to change.
#include "libfreenect.hpp"
#include <iostream>
#include <vector>
#include <cmath>
#include <pthread.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace cv;
using namespace std;
class myMutex {
public:
myMutex() {
pthread_mutex_init( &m_mutex, NULL );
}
void lock() {
pthread_mutex_lock( &m_mutex );
}
void unlock() {
pthread_mutex_unlock( &m_mutex );
}
private:
pthread_mutex_t m_mutex;
};
// Should one use FREENECT_DEPTH_REGISTERED instead of FREENECT_DEPTH_11BIT?
class MyFreenectDevice : public Freenect::FreenectDevice {
public:
MyFreenectDevice(freenect_context *_ctx, int _index)
: Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(FREENECT_DEPTH_11BIT),
m_buffer_rgb(FREENECT_VIDEO_RGB), m_gamma(2048), m_new_rgb_frame(false),
m_new_depth_frame(false), depthMat(Size(640,480),CV_16UC1),
rgbMat(Size(640,480), CV_8UC3, Scalar(0)),
ownMat(Size(640,480),CV_8UC3,Scalar(0)) {
for( unsigned int i = 0 ; i < 2048 ; i++) {
float v = i/2048.0;
v = std::pow(v, 3)* 6;
m_gamma[i] = v*6*256;
}
}
// Do not call directly even in child
void VideoCallback(void* _rgb, uint32_t timestamp) {
std::cout << "RGB callback" << std::endl;
m_rgb_mutex.lock();
uint8_t* rgb = static_cast<uint8_t*>(_rgb);
rgbMat.data = rgb;
m_new_rgb_frame = true;
m_rgb_mutex.unlock();
};
// Do not call directly even in child
void DepthCallback(void* _depth, uint32_t timestamp) {
std::cout << "Depth callback" << std::endl;
m_depth_mutex.lock();
uint16_t* depth = static_cast<uint16_t*>(_depth);
// Here I use memcpy instead so I can use uint16
// memcpy(depthMat.data,depth,depthMat.rows*depthMat.cols*sizeof(uint16_t));
depthMat.data = (uchar*) depth;
m_new_depth_frame = true;
m_depth_mutex.unlock();
}
bool getVideo(Mat& output) {
m_rgb_mutex.lock();
if(m_new_rgb_frame) {
cv::cvtColor(rgbMat, output, CV_RGB2BGR);
m_new_rgb_frame = false;
m_rgb_mutex.unlock();
return true;
} else {
m_rgb_mutex.unlock();
return false;
}
}
bool getDepth(Mat& output) {
m_depth_mutex.lock();
if(m_new_depth_frame) {
depthMat.copyTo(output);
m_new_depth_frame = false;
m_depth_mutex.unlock();
return true;
} else {
m_depth_mutex.unlock();
return false;
}
}
private:
// Should it be uint16_t instead or even higher?
std::vector<uint8_t> m_buffer_depth;
std::vector<uint8_t> m_buffer_rgb;
std::vector<uint16_t> m_gamma;
Mat depthMat;
Mat rgbMat;
Mat ownMat;
myMutex m_rgb_mutex;
myMutex m_depth_mutex;
bool m_new_rgb_frame;
bool m_new_depth_frame;
};
int main(int argc, char **argv) {
bool die(false);
string filename("snapshot");
string suffix(".png");
int i_snap(0),iter(0);
Mat depthMat(Size(640,480),CV_16UC1);
Mat depthf (Size(640,480),CV_8UC1);
Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0));
Mat ownMat(Size(640,480),CV_8UC3,Scalar(0));
// The next two lines must be changed as Freenect::Freenect
// isn't a template but the method createDevice:
// Freenect::Freenect<MyFreenectDevice> freenect;
// MyFreenectDevice& device = freenect.createDevice(0);
// by these two lines:
Freenect::Freenect freenect;
MyFreenectDevice& device = freenect.createDevice<MyFreenectDevice>(0);
namedWindow("rgb",CV_WINDOW_AUTOSIZE);
namedWindow("depth",CV_WINDOW_AUTOSIZE);
device.startVideo();
device.startDepth();
while (!die) {
device.getVideo(rgbMat);
device.getDepth(depthMat);
// Here I save the depth images
std::ostringstream file;
file << filename << i_snap << suffix;
cv::imwrite(file.str(),depthMat);
cv::imshow("rgb", rgbMat);
depthMat.convertTo(depthf, CV_8UC1, 255.0/2048.0);
cv::imshow("depth",depthf);
if(iter >= 1000) break;
iter++;
}
device.stopVideo();
device.stopDepth();
return 0;
}
Thanks in advance!
Erik
I dont have any experience with OpenKinect in particular; but should your depth buffer be uint16?
std::vector<uint8_t> m_buffer_depth;
Also; for Matlab, do check if the image that you are reading is a uint16 or uint8. If its the latter then convert it to uint16
uint16(imread('depth.png'));
Sorry couldn't help more. Hope this helps.
The values you have are the raw depth values. You need to remap those into MM for the numbers to make sense. Kinect 1 can see up to 10 meters. So I would go with raw_values/2407*10000.
If the values are saturated at 2047, you are probably using the FREENECT_DEPTH_11BIT_PACKED depth format.
For work in Matlab, it is always easier to use FREENECT_DEPTH_MM or FREENECT_DEPTH_REGISTERED.
Enjoy.

SystemC - How can I get the module name to which sc_signal connected?

I'd like to print out the name of sc_module to which sc_signal connected.
How can I get the module name, "module_a" in the following code, from "sig_out"?
#include "systemc.h"
class sig_if : virtual public sc_interface
{
};
class my_sig : public sc_module, public sig_if
{
public:
my_sig(sc_module_name nm) : sc_module(nm)
{
}
};
SC_MODULE(test_module)
{
sc_port<sig_if> out;
SC_CTOR(test_module)
{
}
};
int sc_main(int argc, char* argv[]) {
test_module module_a("module_a");
my_sig sig_out("sig_out");
module_a.out(sig_out);
// std::cout << sig_out.get_parent() << std::endl;
sc_start();
return 0;
}
You could override sc_interface::register_port() in the my_sig class to save a reference to the bound port. The parent of the bound port is the module that contains the port.
#include <iostream>
#include <cassert>
#include "systemc.h"
class sig_if : virtual public sc_interface
{
};
class my_sig : public sc_module, public sig_if
{
public:
my_sig(sc_module_name nm) : sc_module(nm), bound_port(NULL)
{
}
void register_port(sc_port_base& port, const char*) {
bound_port = &port;
}
sc_object* get_bound_module() const {
assert(bound_port);
return bound_port->get_parent_object();
};
sc_port_base* bound_port;
};
SC_MODULE(test_module)
{
sc_port<sig_if> out;
SC_CTOR(test_module)
{
}
};
int sc_main(int argc, char* argv[]) {
test_module module_a("module_a");
my_sig sig_out("sig_out");
module_a.out(sig_out);
sc_start(0, SC_NS);
std::cout << sig_out.get_bound_module()->name() << std::endl;
return 0;
}
The above code prints the name of module_a. Note that sig::get_bound_module() can only be called after elaboration, that is, after sc_start() has been called, because sc_interface::register_port() is only called during elaboration.

override signal handler in gtkmm

I struggled with the following code. My signal handler on_button_press_event() is never called but I have no idea why. Could someone have a look on it? Maybe someone is able to run through the gtkmm lib with debug infos. I only have the pre-installed gtkmm packages which could not be used for debugging into the library itself.
#include <iostream>
using namespace std;
#include <gtkmm.h>
#include <goocanvasmm.h>
bool MyExternalHandler( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev )
{
cout << "External Handler" << endl;
return false;
}
class MyRect : public Goocanvas::Rect
{
public:
MyRect( double x, double y, double w, double h)
//: Goocanvas::Rect( x,y,w,h)
{
property_x()=x;
property_y()=y;
property_width()=w;
property_height()=h;
}
public:
virtual void nonsens() {}
bool on_button_press_event(const Glib::RefPtr<Item>& target, GdkEventButton* event) override
{
cout << "override handler" << endl;
return false;
}
bool Handler( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev )
{
cout << "via mem_fun" << endl;
return false;
}
bool on_enter_notify_event(const Glib::RefPtr<Item>& target, GdkEventCrossing* event) override
{
cout << "override enter notify" << endl;
return false;
}
};
int main(int argc, char* argv[])
{
Gtk::Main app(&argc, &argv);
Goocanvas::init("example", "0.1", argc, argv);
Gtk::Window win;
Goocanvas::Canvas m_canvas;
m_canvas.set_size_request(640, 480);
m_canvas.set_bounds(0, 0, 1000, 1000);
MyRect* ptr;
Glib::RefPtr<MyRect> m_rect_own(ptr=new MyRect(225, 225, 150, 150));
m_rect_own->property_line_width() = 1.0;
m_rect_own->property_stroke_color() = "black";
m_rect_own->property_fill_color_rgba() = 0x555555ff;
Glib::RefPtr<Goocanvas::Item> root = m_canvas.get_root_item();
root->add_child( m_rect_own);
((Glib::RefPtr<Goocanvas::Item>&)m_rect_own)->signal_button_press_event().connect(sigc::ptr_fun(&MyExternalHandler));
((Glib::RefPtr<Goocanvas::Item>&)m_rect_own)->signal_button_press_event().connect(sigc::mem_fun(*ptr, &MyRect::Handler));
win.add(m_canvas);
win.show_all_children();
Gtk::Main::run(win);
return 0;
}
Your on_button_press_event() method is not an override, because it has the wrong parameters:
https://developer.gnome.org/gtkmm/unstable/classGtk_1_1Widget.html#aba72b7f8655d1a0eb1273a26894584e3