QList to QQmlListProperty - qt

I'm trying to pass QList into QML using QQmlListProperty, as official documentation says:
QQmlListProperty::QQmlListProperty(QObject *object, void *data, CountFunction count, AtFunction at)
My code is:
QQmlListProperty<TTimingDriver> TTiming::getDrivers()
{
return QQmlListProperty<TTimingDriver>(this, &m_drivers, &TTiming::count, &TTiming::driverAt);
}
int TTiming::count(QQmlListProperty<TTimingDriver> *property)
{
TTiming * timing = qobject_cast<TTiming *>(property->object);
return timing->m_drivers.count();
}
TTimingDriver * TTiming::driverAt(QQmlListProperty<TTimingDriver> *property, int i)
{
TTiming * timing = qobject_cast<TTiming *>(property->object);
return timing->m_drivers.at(i);
}
But I'm getting an error:
no matching function for call to 'QQmlListProperty<TTimingDriver>::QQmlListProperty(TTiming*, QList<TTimingDriver*>*, int (TTiming::*)(QQmlListProperty<TTimingDriver>*), TTimingDriver* (TTiming::*)(QQmlListProperty<TTimingDriver>*, int))'
return QQmlListProperty<TTimingDriver>(this, &m_drivers, &TTiming::count, &TTiming::driverAt);

I think <ou are mixing two of the QQmlListProperty constructor overloads.
The one that takes the QList<T*> does not need pointers to functions.
So this should be sufficient
QQmlListProperty<TTimingDriver> TTiming::getDrivers()
{
return QQmlListProperty<TTimingDriver>(this, &m_drivers);
}
Assuming that m_drivers is of type QList<TTimingDriver*>

Related

MQL4/5 CList Search method always returning null pointer

I'm trying to use the CList Search method in an application. I have attached a very simple example below.
In this example, I always get a null pointer in the variable result. I tried it in MQL4 and MQL5. Has anyone ever made the Search method work? If so, where is my mistake? With my question, I refer to this implementation of a linked list in MQL (it's the standard implementation). Of course, in my application, I do not want to find the first list item, but items that match specific criteria. But even this trivial example does not work for me.
#property strict
#include <Arrays\List.mqh>
#include <Object.mqh>
class MyType : public CObject {
private:
int val;
public:
MyType(int val);
int GetVal(void);
};
MyType::MyType(int val): val(val) {}
int MyType::GetVal(void) {
return val;
}
void OnStart() {
CList *list = new CList();
list.Add(new MyType(3));
// This returns a valid pointer with
// the correct value
MyType* first = list.GetFirstNode();
// This always returns NULL, even though the list
// contains its first element
MyType* result = list.Search(first);
delete list;
}
CList is a kind of linked list. A classical arraylist is CArrayObj in MQL4/5 with Search() and some other methods. You have to sort the list (so implement virtual int Compare(const CObject *node,const int mode=0) const method) before calling search.
virtual int MyType::Compare(const CObject *node,const int mode=0) const {
MyType *another=(MyType*)node;
return this.val-another.GetVal();
}
void OnStart(){
CArrayObj list=new CArrayObj();
list.Add(new MyType(3));
list.Add(new MyType(4));
list.Sort();
MyType *obj3=new MyType(3), *obj2=new MyType(2);
int index3=list.Search(obj3);//found, 0
int index2=list.Search(obj2);//not found, -1
delete(obj3);
delete(obj2);
}

How to create a QFuture with an immediately available value?

I have a function which returns QFuture object as a result of a QtConcurrent::run computation. However, there could be some conditions before running the concurrent method where I need to manually return a value-holding future from my function.
QFuture<bool> foo(const QString &bar)
{
if (bar.isEmpty()) {
return QFuture<bool>(false); // This does not work.
// Here I need to return from the function, but I don't know how to do it.
}
return QtConcurrent::run([=]() -> bool {
// Asynchronous computations...
});
}
How to manually create the QFuture object?
Or (more globally) how to properly return from such method?
When there's no data to return, things are easy - this should be the first thing to try anyway in modern C++:
return {};
Or, if you're targeting some obsolete platform (<Qt 5.6):
return QFuture<bool>();
That way you get an invalid future. There's no way to directly create a future that carries preset data, you'd have to use QFutureInterface for that:
// https://github.com/KubaO/stackoverflown/tree/master/questions/qfuture-immediate-50772976
#include <QtConcurrent>
template <typename T> QFuture<T> finishedFuture(const T &val) {
QFutureInterface<T> fi;
fi.reportFinished(&val);
return QFuture<T>(&fi);
}
QFuture<bool> foo(bool val, bool valid) {
if (!valid)
return {};
return finishedFuture(val);
}
int main() {
Q_ASSERT(foo(true, true));
Q_ASSERT(!foo(false, true));
Q_ASSERT(foo(false, false).isCanceled());
Q_ASSERT(foo(true, false).isCanceled());
}

Qt novice: base class for QLineEdit and QTextEdit

Is there another class besides QWidget which holds all generic functions for both? Something like QEdit...
As an example I'd like to reference cut(), copy() and paste(), but it looks like I have to dynamic cast the QWidget. Is there any other way?
There is no other way besides QWidget. The reason is that QLineEdit is inherited directly from QWidget. You can see the full hierarchy of Qt classes here
You don't have to dynamic-cast anything: this is typically a sign of bad design. Qt generally has very few interface classes - they usually have the word Abstract somewhere in the name, and are not really pure interfaces as they have non-abstract base classes, like e.g. QObject. Thus there was no pattern to follow, and no need for abstracting out the edit operations into an interface.
There are several approaches to overcome this:
Leverage the fact that the methods in question are known by the metaobject system. Note that invokeMethod takes a method name, not signature.
bool cut(QWidget * w) {
return QMetaObject::invokeMethod(w, "cut");
}
bool copy(QWidget * w) {
return QMetaObject::invokeMethod(w, "copy");
}
//...
You can use the free-standing functions such as above on any widget that supports the editing operations.
As above, but cache the method lookup not to pay its costs repeatedly. Note that indexOfMethod takes a method signature, not merely its name.
static QMetaMethod lookup(QMetaObject * o, const char * signature) {
return o->method(o->indexOfMethod(signature));
}
struct Methods {
QMetaMethod cut, copy;
Methods() {}
explicit Methods(QMetaObject * o) :
cut(lookup(o, "cut()")),
copy(lookup(o, "copy()")) {}
Methods(const Methods &) = default;
};
// Meta class names have unique addresses - they are effectively memoized.
// Dynamic metaobjects are an exception we can safely ignore here.
static QMap<const char *, Methods> map;
static const Methods & lookup(QWidget * w) {
auto o = w->metaObject();
auto it = map.find(o->className());
if (it == map.end())
it = map.insert(o->className(), Methods(o));
return *it;
}
bool cut(QWidget * w) {
lookup(w).cut.invoke(w);
}
bool copy(QWidget * w) {
lookup(w).copy.invoke(w);
}
//...
Define an interface and provide implementations specialized for widget types. This approach's only benefit is that it's a bit faster than QMetaMethod::invoke. It makes little sense to use this code for clipboard methods, but it could be useful to minimize overhead for small methods that are called very often. I'd advise not to over-engineer it unless a benchmark shows that it really helps. The previous approach (#2 above) should be quite sufficient.
// Interface
class IClipboard {
public:
virtual cut(QWidget *) = 0;
virtual copy(QWidget *) = 0;
virtual paste(QWidget *) = 0;
};
class Registry {
// all meta class names have unique addresses - they are effectively memoized
static QMap<const char *, IClipboard*> registry;
public:
static void register(const QMetaObject * o, IClipboard * clipboard) {
auto name = o->className();
auto it = registry.find(name);
if (it == registry.end())
registry.insert(name, clipboard);
else
Q_ASSERT(it->value() == clipboard);
}
static IClipboard * for(QWidget * w) {
auto it = registry.find(w->metaObject()->className());
Q_ASSERT(registry.end() != it);
return it->value();
}
static void unregister(const QMetaObject * o) {
registry.remove(o->className());
}
};
template <class W> class ClipboardWidget : public IClipboard {
Q_DISABLE_COPY(ClipboardWidget)
public:
cut(QWidget * w) override { static_cast<W*>(w)->cut(); }
copy(QWidget * w) override { static_cast<W*>(w)->copy(); }
paste(QWidget * w) override { static_cast<W*>(w)->paste(); }
ClipboardWidget() {
Registry::register(&W::staticMetaObject(), this);
}
~ClipboardWidget() {
Registry::unregister(&W::staticMetaObject());
}
};
// Implementation
QMap<const char *, IClipboard*> Registry::registry;
static ClipboardWidget<QTextEdit> w1;
static ClipboardWidget<QLineEdit> w2;
void yourCode() {
//...
Registry::for(widget)->cut(widget);
}

Nor base nor derived virtual function being properly called

I have this base class:
// put the display in a macro on a .h file for less headache.
class Gadget {
protected:
int x, y;
U8GLIB * u8g;
virtual int f_focus() {return 0;};
virtual int f_blur() {return 0;};
virtual void f_draw() {};
virtual void f_select() {};
public:
Gadget(U8GLIB * u8g, int x, int y) :
u8g(u8g),
x(x),
y(y)
{
Serial.println(F("Gadget(U8GLIB * u8g, int x, int y)"));
};
Gadget() {
Serial.println(F("Gadget()"));
};
int focus(){return f_focus();};
int blur(){return f_blur();};
void draw(){f_draw();};
void operator()(){f_select();};
};
And this derived class:
class WakeUp :
public Gadget
{
public:
WakeUp(U8GLIB * u8g) :
Gadget(u8g, 0, 0)
{
Serial.println(F("WakeUp(U8GLIB * u8g)"));
};
};
Then I instantiate the WakeUp class inside an array like this:
Gadget gadgets[1] = {
WakeUp(&u8g)
};
Then I try to access this member like this:
void focus() {
Serial.println(gadgets[0].focus());
}
It is supposed to display 0. However it is displaying -64. Even if I override the f_focus() method on WakeUp class. If I remove the virtual specifier from f_focus() it works fine, displaying 0, but I will not be able to access the derived class implementation of this method.
I wish to understand what is causing this strange behavior and what can I do to avoid it.
EDIT:
The function runs fine if I call it from the Gadget Constructor.
You're slicing your WakeUp object.
You essentially have the following:
Gadget g = WakeUp(...);
What this code does is the following:
Construct a WakeUp object.
Call Gadget(const Gadget& other) with the base from the WakeUp object.
Destroy the temporary WakeUp object, leaving only the copy of the Gadget base.
In order to avoid this, you need to create an array of pointers (this is better if they are smart pointers).
Gadget* gadgets[1] = { new WakeUp(&u8g) }; // If you choose this method, you need to call
// delete gadget[0] or you will leak memory.
Using a pointer will correctly preserve the Gadget and WakeUp instances instead of slicing them away.
With smart pointers:
std::shared_ptr<Gadget> gadgets[1] = { std::make_shared<WakeUp>(&u8g) };

Call by reference with QVector

I have in an Object an QVector of Coordinates (my type) that I want to transfer to an other Vector ( I validate and than want to use ist ).
Header
bool getVector(QVector<Coordinates> &getCoordinates );
C File
static QVector<Coordinates> current;
int getVector( QVector<Coordinates> &getCoordinates)
{
.... stuff ...
getCoordinates = current;
.... stuff ....
return 0;
}
And I use it like
....
QVector<Coordinates> currentCoordinates;
getVector(currentCoordinates);
currentCoordinates.X // CRASH
The debugger goes to this line where an Live Crash happens
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
So my how can I fix this? As I can use this to get all the other Variables with this methode.
A likely cause of your problem is that current has not been constructed before getVector is called. Initialization of static objects in C++ is a thorny area, and a frequent source of bugs - for more information, see this question, and the static initialization order fiasco FAQ entry.
A simple solution to this problem is to provide access to current via a function, i.e. replace
static QVector<Coordinates> current;
with
static QVector<Coordinates>& getCurrent()
{
static QVector<Coordinates> current;
return current;
}
Note, however, that the function as written above is not thread-safe. If multiple threads may call getCurrent, then it should be protected with a QMutex.
For gareth and the Forum :
the header:
typedef QVector<Coordinates> VesselCoordinates;
bool (*getVessel)(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates );
later i bind tis function pointer to an static function ( cause this part of my Program will be one day convertet to c)
cpp file lower layer:
static struct {
Charakter currentPlayerVessel;
VesselCoordinates possibility;
}data;
static bool getVessel(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates );
// funktion to bind the funktion pointer to this static funktion so it can be called outside the File
static bool serverNamespace::getVessel(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates )
{
bool retValue= false;
if ( forCharakter == data.currentPlayerVessel){
// TODO abfragen ob die Adresse regestriert ist!
if ((true == minSize()) and ((true == shipsInRow())or (true == shipsInLine())))
{
retValue = true;
Vessel test = (Vessel)data.possibility.size();
getVessel = test;
getCoordinates = data.possibility;
}
}
return retValue;
}
And then i can use this in the upper layer cpp file to get the information i need:
// in an Funktion :
VesselCoordinates currentCoordinates;
currentCoordinates.clear();
Vessel currentVessel;
if (true == basicFleet->getVessel(currentCharakter,currentVessel, currentCoordinates ))
// doing stuff to it
so its worik fine but your idea worked just as fine. Maybe you can see why my idea is also working.
Thank you
elektor

Resources