Pass QScopedPointer to function - qt

How can I pass a QScopedPointer object to another function like that:
bool addChild(QScopedPointer<TreeNodeInterface> content){
TreeNode* node = new TreeNode(content);
}
TreeNode:
TreeNode::TreeNode(QScopedPointer<TreeNodeInterface> content)
{
mContent.reset(content.take());
}
I get:
error: 'QScopedPointer::QScopedPointer(const QScopedPointer&) [with T = TreeNodeInterface; Cleanup = QScopedPointerDeleter]' is private
How can I solve it? Thanks!

You can do it by accepting a reference to the pointer - that way you can swap the null local pointer with the one that was passed to you:
#include <QScopedPointer>
#include <QDebug>
class T {
Q_DISABLE_COPY(T)
public:
T() { qDebug() << "Constructed" << this; }
~T() { qDebug() << "Destructed" << this; }
void act() { qDebug() << "Acting on" << this; }
};
void foo(QScopedPointer<T> & p)
{
using std::swap;
QScopedPointer<T> local;
swap(local, p);
local->act();
}
int main()
{
QScopedPointer<T> p(new T);
foo(p);
qDebug() << "foo has returned";
return 0;
}
Output:
Constructed 0x7ff5e9c00220
Acting on 0x7ff5e9c00220
Destructed 0x7ff5e9c00220
foo has returned

Related

Call QtDBus method with array-of-strings arguments

I try to call a method with arguments.
For example, list services.
This code
#include <QtDBus>
#include <QDebug>
QDBusMessage callDbusMethod(QString method, QList<QVariant> args= {}) {
QDBusMessage msg;
if(QDBusConnection::systemBus().isConnected()) {
QDBusInterface iface("org.freedesktop.systemd1", "/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager", QDBusConnection::systemBus());
if(iface.isValid())
msg= args.isEmpty() ? iface.call(QDBus::AutoDetect, method.toLatin1())
: iface.callWithArgumentList(QDBus::AutoDetect, method.toLatin1(), args);
if(msg.type() == QDBusMessage::ErrorMessage)
qDebug() << msg.errorMessage(); }
return msg;
}
typedef struct {
QString path, state; } UnitFile;
int main() {
QDBusMessage msg= callDbusMethod("ListUnitFilesByPatterns",
QList<QVariant>{ QVariant(""), QVariant("*.service") });
//QDBusMessage msg= callDbusMethod("ListUnitFiles");
if(msg.arguments().size()) {
const QDBusArgument argUnitFiles= msg.arguments().at(0).value<QDBusArgument>();
argUnitFiles.beginArray();
while(!argUnitFiles.atEnd()) {
UnitFile unit;
argUnitFiles.beginStructure();
argUnitFiles >> unit.path >> unit.state;
argUnitFiles.endStructure();
qDebug() << unit.path; }
argUnitFiles.endArray(); }
}
Return
"Invalid arguments 'ss' to call org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns(), expecting 'asas'."
And how to call the method correctly.
You already answered your question in the comments. But I figured I'd explain more here.
In the submission you are passing the argument list of ss since your QList has two QVariants which are strings. The signature of org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns is asas or two array of strings. According to qt's dbus typesystem, as is automatically de-marshaled into a QStringList. Therefore you'd want a QList of QVariants which are QStringLists.
So..
QList<QVariant> args = { QVariant(""), QVariant("*.service") };
should be
QList<QVariant> args = { QStringList() << "", QStringList() << "*.service" };

Constant container (map) - eliminate heap allocation

If I create a static const std::map, it will allocate memory on heap. Following code throws bad_alloc:
#include <iostream>
#include <map>
class A {
public:
static const std::map<int, int> a;
};
const std::map<int, int> A::a = { { 1, 3} , { 2, 5} };
void* operator new ( std::size_t count )
{
throw std::bad_alloc();
}
int
main (void)
{
for(auto &ai: A::a) {
std::cout << ai.first << " " << ai.second << "\n";
}
return 0;
}
Is it possible to create this constant map somehow without having memory allocation?
As Igor Tandetnik suggested, a custom allocator would do the trick. The following is a quick'n'dirty example of a simple linear allocator, which returns memory slots from a static buffer:
#include <iostream>
#include <map>
#include <cassert>
template <typename T>
class LinearAllocator {
static constexpr size_t _maxAlloc = 1<<20;
using Buffer = std::array<T, _maxAlloc>;
using FreeList = std::array<bool, _maxAlloc>;
static Buffer _buffer;
static FreeList _allocated;
public:
typedef T* pointer;
typedef T value_type;
template<typename U>
struct rebind { typedef LinearAllocator<U> other; };
pointer allocate(size_t /*n*/, const void *hint=0) {
for(size_t i = 0; i < _maxAlloc; ++i) {
if(!_allocated[i]) {
_allocated[i] = true;
return &_buffer[i];
}
}
throw std::bad_alloc();
}
void deallocate(pointer p, size_t /*n*/) {
assert(p >= &_buffer[0] && p < &_buffer[_maxAlloc]);
_allocated[p-&_buffer[0]] = false;
}
LinearAllocator() throw() { }
LinearAllocator(const LinearAllocator &a) throw() { }
template <class U>
LinearAllocator(const LinearAllocator<U> &a) throw() { }
~LinearAllocator() throw() { }
};
template <typename T>
typename LinearAllocator<T>::Buffer LinearAllocator<T>::_buffer;
template <typename T>
typename LinearAllocator<T>::FreeList LinearAllocator<T>::_allocated;
using MyMap = std::map<int, int, std::less<int>,
LinearAllocator<std::pair<int,int> > >;
// make sure we notice if new gets called
void* operator new(size_t size) {
std::cout << "new called" << std::endl;
}
int main() {
MyMap m;
m[0] = 1; m[1] = 3; m[2] = 8;
for(auto & p : m)
std::cout << p.first << ": " << p.second << std::endl;
return 0;
}
Output:
0: 1
1: 3
2: 8
Note that this allocator will only handle requests for single slots at a time. I'm sure you will figure out how to extend it according to your requirements.

how to pick two points from viewer in PCL

I would like to pick two points from pointcloud and return coordinates of the two points. In order to get down to the problem, I have used the PointPickingEvent of PCL, and written a class containing pointcloud, visualizer, and a vector to store selected points. My code:
#include <pcl/point_cloud.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/io.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/visualization/pcl_visualizer.h>
using namespace pcl;
using namespace std;
class pickPoints {
public:
pickPoints::pickPoints () {
viewer.reset (new pcl::visualization::PCLVisualizer ("Viewer", true));
viewer->registerPointPickingCallback (&pickPoints::pickCallback, *this);
}
~pickPoints () {}
void setInputCloud (PointCloud<PointXYZ>::Ptr cloud)
{
cloudTemp = cloud;
}
vector<float> getpoints() {
return p;
}
void simpleViewer ()
{
// Visualizer
viewer->addPointCloud<pcl::PointXYZ>(cloudTemp, "Cloud");
viewer->resetCameraViewpoint ("Cloud");
viewer->spin();
}
protected:
void pickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
if (event.getPointIndex () == -1)
return;
PointXYZ picked_point1,picked_point2;
event.getPoints(picked_point1.x,picked_point1.y,picked_point1.z,
picked_point2.x,picked_point2.y,picked_point2.z);
p.push_back(picked_point1.x); // store points
p.push_back(picked_point1.y);
p.push_back(picked_point1.z);
p.push_back(picked_point2.x);
p.push_back(picked_point2.y);
p.push_back(picked_point2.z);
//cout<<"first selected point: "<<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;
//cout<<"second selected point: "<<p[3]<<" "<<p[4]<<" "<<p[5]<<endl;
}
private:
// Point cloud data
PointCloud<pcl::PointXYZ>::Ptr cloudTemp;
// The visualizer
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
// The picked point
vector<float> p;
};
int main()
{
//LOAD;
PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ> ());
pcl::PolygonMesh mesh;
pcl::io::loadPolygonFilePLY("test.ply", mesh);
pcl::fromPCLPointCloud2(mesh.cloud, *cloud);
pickPoints pickViewer;
pickViewer.setInputCloud(cloud); // A pointer to a cloud
pickViewer.simpleViewer();
vector<float> pointSelected;
pointSelected= pickViewer.getpoints();
cout<<pointSelected[0]<<" "<<pointSelected[1]<<" "<<pointSelected[2]<<endl;
cout<<pointSelected[3]<<" "<<pointSelected[4]<<" "<<pointSelected[5]<<endl;
cin.get();
return 0;
}
But when the code was debugged, I got nothing. Also I know that when picking points with the left button, the SHIFT button should be pressed. Thank you in advance for any help!
I found that the getPoints() method does not work as I expected. However, getPoint() worked well. Here is code to print out the selected points and store them is a vector:
std::vector<pcl::PointXYZ> selectedPoints;
void pointPickingEventOccurred(const pcl::visualization::PointPickingEvent& event, void* viewer_void)
{
float x, y, z;
if (event.getPointIndex() == -1)
{
return;
}
event.getPoint(x, y, z);
std::cout << "Point coordinate ( " << x << ", " << y << ", " << z << ")" << std::endl;
selectedPoints.push_back(pcl::PointXYZ(x, y, z));
}
void displayCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, const std::string& window_name)
{
if (cloud->size() < 1)
{
std::cout << window_name << " display failure. Cloud contains no points\n";
return;
}
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(window_name));
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> point_cloud_color_handler(cloud, "intensity");
viewer->addPointCloud< pcl::PointXYZI >(cloud, point_cloud_color_handler, "id");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "id");
viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)viewer.get());
viewer->registerPointPickingCallback(pointPickingEventOccurred, (void*)&viewer);
while (!viewer->wasStopped() && !close_window){
viewer->spinOnce(50);
}
close_window = false;
viewer->close();
}
You can also find distances between the points pretty easily once they are selected.
if (selectedPoints.size() > 1)
{
float distance = pcl::euclideanDistance(selectedPoints[0], selectedPoints[1]);
std::cout << "Distance is " << distance << std::endl;
}
The selectedPoints vector can be emptied with a keyboardEvent if you want to start over picking points.

send Qevent from thread

Please can some-one suggest on this question..? I have to send data from my TX thread to mainwindow using class derived from QEvent.
I want my RX thread to throw an event whenever some data is received so hat i can display that data in the Mainwindow.
I start a main thread when button start is pressed. I save the pointer to my mainwindow inside the object of main thread. I will use this pointer to post events to the mainwindow object.
When first time i enter the Qthread function dowork_rx(). Event is thrown & i am able to catch it in customEvent() handler. But when dowork_rx() while loop starts when i throws the event it does not trigger the customEvent() function.
Please suggest how to resolve this problem.
My qevent class :---
//String event derived class
template <typename T> class StringEvent : public QEvent
{
QString m_str;
public:
explicit StringEvent(const QString val) : QEvent(staticType()), m_str(val)
{
}
void setvalue(QString val)
{
m_str = val;
}
QString value() const
{
return m_str;
}
static QEvent::Type staticType()
{
static int type = QEvent::registerEventType();
return static_cast<QEvent::Type>(type);
/*
static int type;
if(type == 0)
{
type = QEvent::registerEventType();
}
return static_cast<QEvent::Type>(type);*/
}
static bool is(const QEvent * ev)
{
return ev->type() == staticType();
}
};
class UpdateEvent : public StringEvent<UpdateEvent>
{
public:
explicit UpdateEvent(QString val): StringEvent(val)
{
//qDebug() << "hello";
}
};
class ClearEvent : public StringEvent<ClearEvent>
{
public:
explicit ClearEvent(QString val): StringEvent(val)
{
}
};
Dowork function of the thread :----
// Common slot for the rx - thread
void RxThreadObject::dowork_rx()
{
int i =0;
qDebug() << "\nrx start \n";
myUpdateEvent_rx = new UpdateEvent("UpdateEventObject - dowork_rx");
//myUpdateEvent_rx->setvalue("first");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
qDebug() << "\nrx throw event - done \n";
while(!m_bQuitRx)
{
SleepTimerDelay::sleep(2);
if(i==0){
//qDebug() << "\nrx throw event - done 11 \n";
myUpdateEvent_rx = new UpdateEvent("first");
myUpdateEvent_rx->setvalue("first");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
i++;
}else{
//qDebug() << "\nrx throw event - done 22 \n";
myUpdateEvent_rx = new UpdateEvent("second");
myUpdateEvent_rx->setvalue("second");
QCoreApplication::postEvent(m_pMainThreadObj->ptrmainwindow, myUpdateEvent_rx);
i=0;
}
}
qDebug() << "\nrx end \n";
}
Event handler :----
/*!
** Custom event handler
*/
void MainWindow::customEvent(QEvent *event)
{
qDebug() << "oo customEvent";
if (UpdateEvent::is(event)) {
UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
qDebug() << tempUpdateEvent->value();
}
else if (ClearEvent::is(event)) {
ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
qDebug() << tempClearEvent->value();
}
}
/*!
** event filter handler
*/
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "oo eventFilter";
if (UpdateEvent::is(event)) {
UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
qDebug() << tempUpdateEvent->value();
}
else if (ClearEvent::is(event)) {
ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
qDebug() << tempClearEvent->value();
}
return true;
}

error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Car' (or there is no acceptable conversion)

Queue class
#ifndef Queue_H
#define Queue_H
#include "Car.h"
#include <iostream>
#include <string>
using namespace std;
const int Q_MAX_SIZE = 20;
class Queue {
private:
int size; // size of the queue
Car carQueue[Q_MAX_SIZE];
int front, rear;
public:
Queue();
~Queue();
bool isEmpty();
bool isFull();
void enqueue(Car c);
void dequeue(); // just dequeue the last car in the queue
void dequeue(Car c); // if a certain car wants to go out of the queue midway.
// Condition: Car is not in washing. Meaning is not the 1st item in the queue
void dequeue(int index); // same as the previous comment
Car getFront();
void getCarQueue(Queue);
int length();
Car get(int);
};
Queue::Queue() {
size = 0;
front = 0;
rear = Q_MAX_SIZE -1;
}
Queue::~Queue() {
while(!isEmpty()) {
dequeue();
}
}
void Queue::enqueue(Car c) {
if (!isFull()) {
rear = (rear + 1) % Q_MAX_SIZE; // circular array
carQueue[rear] = c;
size++;
} else {
cout << "Queue is currently full.\n";
}
}
void Queue::dequeue() {
}
void Queue::dequeue(int index) {
if(!isEmpty()) {
front = (front + 1) % Q_MAX_SIZE;
if(front != index) {
carQueue[index-1] = carQueue[index];
rear--;
size--;
} else {
cout << "Not allowed to dequeue the first car in the queue.\n";
}
} else {
cout << "There are no cars to dequeue.\n";
}
}
bool Queue::isEmpty() {
return size == 0;
}
bool Queue::isFull() {
return (size == Q_MAX_SIZE);
}
Car Queue::getFront() {
return carQueue[front];
}
int Queue::length() {
return size;
}
Car Queue::get(int index) {
return carQueue[index-1];
}
void Queue::getCarQueue(Queue q) {
for(int i = 0; i< q.length(); i++)
cout << q.get(i) << endl; // Error here
}
#endif
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Car' (or there is no acceptable conversion)
I get this error which is kind of odd. so is there anything wrong? Thanks!
cout has no idea how to process a car object; it has never seen a car object and doesn't know how you output a car as text. cout can only process types it knows about, string, char, int, etc. The specific error is because there is version of operator << that takes an ostream and a car.
There are two options:
Creation an overload for operator<< that takes an ostream and a car. That will show cout how to output a car. This isn't usually done becuase there is usually more than one way your would want to display a car.
Write the output statement so that it manually prints out car properties like
cout << c.getMake() << " " << c.getModel()

Resources