How to dynamically store QList<QString> into a QTableView after opening a connection with a QSqlDatabse - qt5

I have a small GUI where I have a QTableView and a QPuchButton.
The function of the QPushButton is mainly dinamyc, which means that the operations that needs to happen when clicking the button would be following:
Create a database file dynamically (.db)
Create a temporary Database connection
Create some dinamically tabular data using the subclassed QAbstractTableModel
Store the data into the database file created at 1)
Read the file.db with the data and show it into the QTableView on the ui
The problem is that the database does not open and consequenlty, no files are temporarliy stored in the NewFile.db and I cannot read/show the data in the QTableView
void writeTemporaryFilesOnDatabase::on_addMsgBtn_clicked()
{
// 1 - Create a database file dinamically and store the file.db in the following document folder as an example
QString path("/home/to/Documents/");
QDir dir; // Initialize to the desired dir if 'path' is relative
// We create the directory if needed
if (!dir.exists(path))
dir.mkpath(path); // You can check the success if needed
QFile file(path + "NewFile.db");
file.open(QIODevice::WriteOnly); // Or QIODevice::ReadWrite
// 2 - Create a table in runtime mode and fill out with temporary data
QList<QString> contactNames;
QList<QString> contactPhoneNums;
contactNames.append("Thomas");
contactNames.append("Richard");
contactNames.append("Harrison");
contactPhoneNums.append("123");
contactPhoneNums.append("222");
contactPhoneNums.append("333");
// 3 - Create a database in runtime mode and fill out with temporary data just created
QSqlDatabase *database = new QSqlDatabase();
database->QSqlDatabase::addDatabase("QSQLITE","/home/to/Documents/NewFile.db");
database->open();
if (database->open()) {
qDebug() << __LINE__ << QString("Open Db!");
} else {
qDebug() << __LINE__ << QString("Db not opening!");
}
// Create Phone Book with subclassed QAbstractTableModel:
TestModel *PhoneBookModel = new TestModel(this);
// Populate model with data:
PhoneBookModel->populateData(contactNames,contactPhoneNums);
// Connect model to table view:
QSqlTableModel *tableModel = nullptr;
QTableView *tView = new QTableView;
tView->setModel(PhoneBookModel);
// Make table header visible and display table:
tView->horizontalHeader()->setVisible(true); // <-- This run correctly and appears as soon as I launch the application (I did it for debugging reasons and the table is correctly created)
tView->show();
if (database->open()) {
qDebug() << __LINE__ << QString("Open Db or not?????");
QSqlQuery query;
query.exec("DROP TABLE items");
query.exec(
"CREATE TABLE items ("
"Name TEXT NOT NULL,"
"Phone INTEGER NOT NULL ''"
")"
);
query.prepare("INSERT INTO items (Name, Phone) VALUES (?,?)");
query.addBindValue(newItem->name());
query.addBindValue(newItem->phone().toInt());
tableModel = new QSqlTableModel(this, *database);
tableModel->setTable("items");
tableModel->setEditStrategy(QSqlTableModel::OnFieldChange);
tableModel->select();
tView->setModel(PhoneBookModel);
// Read the data created in the `TestModel *PhoneBookModel = new TestModel(this);`
if( file.open( QIODevice::WriteOnly ) )
{
QTextStream ts( &file );
QStringList strList;
for (int i=0; i<PhoneBookModel->rowCount(); i++)
{
strList.clear();
for (int j=0; j<PhoneBookModel->columnCount(); j++)
strList << PhoneBookModel->data(PhoneBookModel->index(i,j)).toString();
ts << strList.join(" ") + "\n";
}
ts << &strList;
file.close();
}
} else {
qDebug() << __FUNCTION__ << QString("Error!");
return;
}
// 4 - LOOP THROUGH THE HEADERS OF THAT FILE AND SHOW THE TABLE
for(int i=0; i< ui->tableWidget->rowCount(); i++)
{
QString viewFieldName = ui->tableView->item(i, 0)->text();
mModel->setHeaderData(i, Qt::Horizontal, viewFieldName);
mModel->submitAll();
}
}
Specifically, the Qt Objects QAbstractTableModel (sub-classed in this example) and QTableView are used mostly for practice on how to use the QAbstractTableModel but I am not sure what I am doing wrong here. Any help would be very appreciated.
In case you are wondering how I subclassed the QAbstractTableModel see below:
class TestModel : public QAbstractTableModel
{
Q_OBJECT
public:
TestModel(QObject *parent = 0);
void populateData(const QList<QString> &contactName,const QList<QString> &contactPhone);
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
bool addItem(itemExample *newItem);
private:
QList<QString> tm_contact_name;
QList<QString> tm_contact_phone;
QString mError;
};
Thanks for any help!
Sources I consulted to help me but without solving the problems are: this, this one and also this one.

Related

Point cloud library (PCL) C++ exception when tying to run

i am trying to use PCL with a V1 Microsoft Kinect camera to do 3D mapping. I have installed it and used Cmake to create the project using visual studio 2019 when i try to run the file "openni_grabber.cpp" i get the exception shown below and i cannot figure out what is causing it and how to fix it. I'm not very experience with PCL so any help would be very appreciated
I have tried searching and cannot find anyone else who has had this error or any info on how to fix it
The code im using is shown below
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/openni2_grabber.h>
#include <pcl/common/time.h>
class SimpleOpenNIProcessor
{
public:
void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
{
static unsigned count = 0;
static double last = pcl::getTime ();
if (++count == 30)
{
double now = pcl::getTime ();
std::cout << "distance of center pixel :" << cloud->points [(cloud->width >> 1) * (cloud->height + 1)].z << " mm. Average framerate: " << double(count)/double(now - last) << " Hz" << std::endl;
count = 0;
last = now;
}
}
void run ()
{
// create a new grabber for OpenNI devices
pcl::Grabber* interface = new pcl::io::OpenNI2Grabber();
// make callback function from member function
boost::function<void (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
boost::bind (&SimpleOpenNIProcessor::cloud_cb_, this, _1);
// connect callback function for desired signal. In this case its a point cloud with color values
boost::signals2::connection c = interface->registerCallback (f);
// start receiving point clouds
interface->start ();
// wait until user quits program with Ctrl-C, but no busy-waiting -> sleep (1);
while (true)
boost::this_thread::sleep (boost::posix_time::seconds (1));
// stop the grabber
interface->stop ();
}
};
int main ()
{
SimpleOpenNIProcessor v;
v.run ();
return (0);
}
The details of the exception are
"Unhandled exception at 0x00007FFBEB9206BC in openni_grabber.exe: Microsoft C++ exception: pcl::IOException at memory location 0x00000043E9EFF378."

How to notify ListView that DataModel has changed

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).

How to acquire skeletal joint data to text file from two kinect cameras in SkeletalViewer? (C++)

I am currently working on a project to use multiple kinect cameras to acquire x,y,z coordinates of skeletal data in SkeletalViewer. I have an idea to use the KinectID or index of different kinect cameras to extract the sets of skeletal joints data into 2 different text files. But I am not sure if I am doing right. Please help to take a look at the modification below, or I will appreciate all your kind advice on other method to solve this problem.
In SkeletalViewer.h, I modified as following:
public:
FILE* mp3DFile0;
FILE* mp3DFile1;
char mText[1024];
INuiSensor * m_pNuiSensor;
BSTR m_instanceId;
array SensorIndex;
In NuiImpl.cpp, I modified as following:
1) define array
ref class MyClass {
public:
int m_i;
};
array<MyClass^>^ arrSensor() {
int i;
array< MyClass^ >^ local = gcnew array< MyClass^ >(2);
for (i = 0; i < 2; i++) {
local[i] = gcnew MyClass;
local[i]->m_i = i;
}
return local;
}
2) create array to store sensor index to do for loop later
HRESULT CSkeletalViewerApp::Nui_Init( )
{
HRESULT hr;
bool result;
//create an array to store two file pointers
FILE* mp3DFile[] = { mp3DFile0, mp3DFile1 };
fopen_s(mp3DFile0, "D:/Kinect/KinectCam0.txt", "w+");
fopen_s(mp3DFile1, "D:/Kinect/KinectCam1.txt", "w+");
.
.
if ( !m_pNuiSensor )
{
hr = NuiCreateSensorByIndex(0, &m_pNuiSensor);
//I am not sure about how to utilize this index in this case
.
.
}
if (NuiGetSensorCount(&m_pNuiSensor) > 1)
{
array< MyClass^ >^ SensorIndex;
SensorIndex = arrSensor();
}
}
3) use for loop to store data to different text file using index
void CSkeletalViewerApp::Nui_DrawSkeleton( const NUI_SKELETON_DATA & skel, int windowWidth, int windowHeight )
{
int i;
int h;
for (h = 0; h < 2; h++)
{
//when index point to the current kinect
if (SensorIndex[h] == &m_pNuiSensor)
{
for (i = 0; i < NUI_SKELETON_POSITION_COUNT; i++)
{
m_Points[i] = SkeletonToScreen(skel.SkeletonPositions[i], windowWidth, windowHeight);
memset(mText, 0, 1024);
sprintf(mText, "(%0.3f,%0.3f,%0.3f)", skel.SkeletonPositions[i].x, skel.SkeletonPositions[i].y, skel.SkeletonPositions[i].z);
if (mp3DFile[h]) {
fputs((const char*)mText, mp3DFile[h]);
}
}
if (mp3DFile[h]) {
fputs("\n", mp3DFile[h]);
}
}
}
.
.
}
I am a newbie in this Kinect programming. Thank you very much for your help! :)

How do i copy to a List?

I have this code in CLI
List<Codec^> ^GetCodecs()
{
List<Codec^> ^l = gcnew List<Codec^>;
bool KeepLooping = Encoder_MoveToFirstCodec();
while (KeepLooping)
{
Codec ^codec = gcnew Codec(); // here... and that call encoder_init many times... which call register codec many times... which is a mass...
codec->Name = gcnew String(Encoder_GetCurrentCodecName());
codec->Type = Encoder_GetCurrentCodecType();
char pix_fmts[200]; // array of 200 is probably enough
int actual_pix_fmts_sz = Encoder_GetCurrentCodecPixFmts( pix_fmts , 200 );
for (int i = 0 ; i < actual_pix_fmts_sz ; i++)
{
//copy from pix_fmts to the :List
codec->SupportedPixelFormats->Add(pix_fmts[i]);
}
This is the Encoder_GetCurrentCodecPixFmts function in C:
int Encoder_GetCurrentCodecPixFmts( char *outbuf , int buf_sz )
{
int i=0;
while ( (i<buf_sz) && (codec->pix_fmts[i]!=-1) )
{
outbuf[i] = codec->pix_fmts[i];
i++;
}
return i;
}
This is a new class i did:
#pragma once
using namespace System;
using namespace System::Collections::Generic;
public ref class Codec
{
public:
String^ Name;
int ID; // this is the index
int Type; // this is the type
List<int> ^SupportedPixelFormats;
Codec(void)
{
SupportedPixelFormats = gcnew List<int>;
// do nothing in the constructor;
}
};
Which contain also the: SupportedPixelFormats
The constructor in this new class should be empty but i needed somewhere to make an instance for the List make a NEW for the List.
Now in the C++ i need to transfer from pix_fmts char array to codec->Supported
Or to copy from pix_fmts to the :List
So i did as above:
codec->SupportedPixelFormats->Add(pix_fmts[i]);
But i'm not sure if this the meaning of copy.
Is that right what i did ?
It works, it's a kind of a deep copy. What makes you think it doesn't work? Do the results turn out wrong? If they do, put a breakpoint in there and try to get what is wrong.
Instead of copying one by one perhaps you can use the Enumerable::ToList extension method.
I hope this helped you.

Using Point Cloud Library to store Point Clouds from Kinect

Using Point Cloud Library on Ubuntu, I am trying to take multiple point clouds from the Kinect and store them in memory for later use in the program. My code shown at the bottom of this post is designed to store the first Point Cloud from the Kinect and output its width and height. The program gives me a runtime error:
/usr/include/boost/smart_ptr/shared_ptr.hpp:418: T* boost::shared_ptr<T>::operator->() const [with T = pcl::PointCloud<pcl::PointXYZ>]: Assertion `px != 0' failed.
All help is greatly appreciated and I always accept an answer!
The code:
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
class SimpleOpenNIViewer
{
public:
SimpleOpenNIViewer () : viewer ("PCL OpenNI Viewer") {}
pcl::PointCloud<pcl::PointXYZ>::Ptr prevCloud;
void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
{
if (!viewer.wasStopped())
viewer.showCloud (cloud);
//ICP start
if(!prevCloud) {
pcl::PointCloud<pcl::PointXYZ>::Ptr prevCloud( new pcl::PointCloud<pcl::PointXYZ>());
pcl::copyPointCloud<pcl::PointXYZ, pcl::PointXYZ>(*cloud, *prevCloud);
}
cout << prevCloud->width << " by " << prevCloud->height << endl;
}
void run ()
{
pcl::Grabber* interface = new pcl::OpenNIGrabber();
boost::function<void (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> f =
boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);
interface->registerCallback (f);
interface->start ();
while (!viewer.wasStopped())
{
boost::this_thread::sleep (boost::posix_time::seconds (1));
}
interface->stop ();
}
pcl::visualization::CloudViewer viewer;
};
int main ()
{
SimpleOpenNIViewer v;
v.run ();
return 0;
}
Try this, I don't have the Kinect drivers installed so I can't test. Basically in my version prevCloud is instantiated in the constructor so (!prevCloud) will always equal 'false'. Which is to say prevCloud.get() != NULL.
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
class SimpleOpenNIViewer
{
typedef pcl::PointXYZ Point;
typedef pcl::PointCloud<Point> PointCloud;
public:
SimpleOpenNIViewer () : viewer ("PCL OpenNI Viewer") {
prevCloud = PointCloud::Ptr(NULL);
}
void cloud_cb_ (const PointCloud::ConstPtr &cloud)
{
if (!viewer.wasStopped())
viewer.showCloud (cloud);
if (!prevCloud) // init previous cloud if first frame
prevCloud = PointCloud::Ptr(new PointCloud);
else. // else RunICP between cloud and prevCloud
//RunICP(cloud,prevCloud);
//Copy new frame in to prevCloud
pcl::copyPointCloud<Point, Point>(*cloud, *prevCloud);
cout << prevCloud->width << " by " << prevCloud->height << endl;
}
void run ()
{
pcl::Grabber* interface = new pcl::OpenNIGrabber();
boost::function<void (const PointCloud::ConstPtr&)> f =
boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);
interface->registerCallback (f);
interface->start ();
while (!viewer.wasStopped())
{
boost::this_thread::sleep (boost::posix_time::seconds (1));
}
interface->stop ();
}
PointCloud::Ptr prevCloud;
pcl::visualization::CloudViewer viewer;
};
int main ()
{
SimpleOpenNIViewer v;
v.run ();
return 0;
}
You're creating a new local variable prevCloud and copying cloud into it, rather than copying into the prevCloud field. So, if the field's value was null before the if {}, it is still null after the if {} and so it throws an error when you try to dereference it.
May be this code can help you, the cloud is saved in a "pcd" file, take a look here
And other option is work with the "Kinfu" project from PCL