Qt QML C++ Plugin Singleton - c++

Is it possible to make MyObject be always equal (one same instance) in all it's qml definitions?
C++:
class MyObject : public QObject {
Q_OBJECT
Q_DISABLE_COPY(MyObject)
Q_PROPERTY(QString test READ test NOTIFY testChanged)
public:
explicit MyObject(QObject *parent = 0);
signals:
void testChanged();
private:
QString test() const {
return _test;
}
QString _test;
};
QML:
Item {
MyObject { id: myObject1 }
MyObject { id: myObject2 }
}
I want myObject1 to be equal myObject2. Some kind of singleton (but no qmlRegisterSingletonType)

I can interpret your question as if you want more than one entry of MyObject in QML code referring to the same C++ object. You also know what singleton is. How about the wrapper over the singleton that you can use with QML like:
class MyObject : public QObject {
Q_OBJECT
Q_DISABLE_COPY(MyObject)
Q_PROPERTY(QString test READ test NOTIFY testChanged)
public:
explicit MyObject(QObject *parent = 0);
signals:
void testChanged();
private:
QString test() const {
return MySingleton::instance().test();
}
// QString _test; // this supposed to be implemented in MySingleton
};
Or I in my application for many different types of communication between C++ and QML use some kind of MessageBoard from the article Exposing Attributes of C++ Types to QML. That one is even more convenient considering many uses.

Related

Q_PROPERTY with private setter

I have an QObject with properties accessible from QML.
Something like:
Class C : public QObject {
Q_OBJECT
public:
explicit C(QObject * parent = nullptr);
Q_PROPERTY(QString ro_text READ ro_text WRITE setRo_text NOTIFY ro_textChanged)
};
Is it possible to make the setter(setRo_text) "private", so the property cannot by modified from QML, but can still be set from C++ code(inside the class)?
if you don't want it to be modified from QML then don't declare the WRITE, and create a method that every time the property changes it emits the signal, the setter method can be public or private but it can't be accessed in QML
class C: public QObject{
Q_OBJECT
Q_PROPERTY(QString ro_text READ ro_text NOTIFY ro_textChanged)
public:
C(QObject *parent=nullptr): QObject(parent){
}
QString ro_text() const {
return m_ro_text;
}
Q_SIGNALS:
void ro_textChanged();
private:
void setRo_text(const QString & text){
if(m_ro_text == text)
return;
m_ro_text = text;
Q_EMIT ro_textChanged();
}
QString m_ro_text;
};

Qt property outside of base class

Im using a QML frontend for my C++ App which worked fine so far. However, I planned to tidy up my code and split functions into smaller classes
At first, my Property decleration looked like this:
class mainBoard : public QObject
{
Q_OBJECT
Q_PROPERTY(double baroAltitude MEMBER baroAltitude NOTIFY pressureChanged)
public:
explicit mainBoard(QObject *parent = 0);
void start();
private:
double baroAltitude = 0;
signals:
void pressureChanged();
};
Now, I do have this external class, with my getter method.
#include "pressuresensor.h"
class mainBoard : public QObject
{
Q_OBJECT
Q_PROPERTY(double baroAltitude READ pressureSensors.getBaroAltitude NOTIFY pressureSensors.pressureChanged)
public:
explicit mainBoard(QObject *parent = 0);
void start();
private:
pressureSensor pressureSensors;
};
But now, all I get is:
mainboard.h:25: Parse error at "pressureSensors"
error: [moc_mainboard.cpp] Error 1
Is there a better, or correct (because its working :D ) way for it?
thanks!
Q_PROPERTY does not support getters/setters methods which are not part of the class in question.
If you really want to keep the pressureSensor class you have to provide getters/setters in the mainBoard class and forward the calls.
class mainBoard : public QObject
{
Q_OBJECT
Q_PROPERTY(double baroAltitude READ getBaroAltitude)
public:
double getBaroAltitude() const {
return pressureSensors.getBaroAlitude();
}
private:
pressureSensor pressureSensors;
};

How to instantiate my C++ class from QtScript? My class inherits QObject

I am researching possibilities of QtScript. I understand that it is possible to create QObject in C++ and then pass it into QScriptEngine:
QObject *someObject = new WindowWithText;
QScriptValue objectValue = engine.newQObject(someObject);
engine.globalObject().setProperty("window", objectValue);
This works - I was able to call my methods defined in C++:
WindowWithText declaration:
#include <QWidget>
namespace Ui {
class WindowWithText;
}
class WindowWithText : public QWidget
{
Q_OBJECT
public:
explicit WindowWithText(QWidget *parent = 0);
~WindowWithText();
public slots:
void setHeading(const QString&);
void setContents(const QString&);
QString getHeading() const;
private:
Ui::WindowWithText *ui;
};
But I would like to instantiate windows from qtscript itself, like this:
var window = new WindowWithText();
I understand I will probably have to write some proxy between constructor and QtCcript, but how to do it?
So far, I just created static method newInstance that creates the object, but that's no new:
QScriptValue WindowWithText::newInstance(QScriptContext *context, QScriptEngine *engine)
{
QObject *someObject = new WindowWithText;
QScriptValue objectValue = engine->newQObject(someObject);
return objectValue;
}
I exported it to the engine as follows:
engine.globalObject().setProperty("WindowWithText", engine.newFunction(WindowWithText::newInstance));
This does not use new though and isn't true javascript pseudoclass:
Following code will fail:
function Subclass() {
this.setHeading("bla bla");
}
Subclass.prototype = Object.create(WindowWithText.prototype);
var window = new dd();
window.show();
Error caused by the fact that WindowWithText.prototype doesn't have anything to do with WindowWithText:
TypeError: Result of expression 'this.setHeading' [undefined] is not a function.
Is there more reliable and less tedious way of exporting C++ classes to my engine?

How pass data with signal/slot from one QObject to another QQuickItem object in qml?

i have a class like this:
class MyClass : public QObject
{
Q_OBJECT
public:
CircularList<unsigned char> buffer_[2];
explicit MyClass(QObject *parent = 0);
signals:
void dataReady(short *buff,int len);
};
and the other one is:
class WaveItem:public QQuickItem
{
Q_OBJECT
public:
WaveItem(QQuickItem *parent = 0);
public slots:
void setSamples(short *buff,int len);
protected:
QSGNode * updatePaintNode(QSGNode *node, UpdatePaintNodeData *data);
};
i need to connect this class in qml with signal(dataReady)/slot(setSamples). how is it possible?
If you check qt docs about exposing signals it describes very well.
First, you need to register your QObject derived class to QML engine.
qmlRegisterType<Myclass>("MyclassLib", 1, 0, "Myclass");
This way, you can create Myclass objects in QML.
But if you like to create objects in C++ and use that particular object in QML then you need to use QQmlContext::setContextProperty
QQuickView view;
Myclass myClass;
view.engine()->rootContext()->setContextProperty("myclass", &myClass);
After you registered type or set your object to QML, you can now use them.
Myclass {
onDataReady: waveItem.setSamples(buff, len);
}
Alternatively, you can also use connect(),
Myclass {
id: myClass
Component.onCompleted: myClass.dataReady.connect(waveItem.setSamples);
}
Note: You might also look to Connections.

how to implement OOP using QT

this is a simple OOP QT question.
my app consists of main window (QMainWindow) and a table (QTableWidget).
in the main window i have arguments and variables which i would like to pass to the table class, and to access methods in main widnow class from the table class, how should i do it ?
mainwindow.h
class MainWindow : public QMainWindow {
Q_OBJECT
private:
int a;
int b;
Spreadsheet *spreadsheet;
public:
void set_a(int);
void set_b(int);
spreadsheet.h
class Spreadsheet : public QTableWidget {
Q_OBJECT
public:
Spreadsheet(QWidget *parent = 0);
atm i define Spreadsheet like this:
spreadsheet = new Spreadsheet(this);
and i'd like to access set_a() from spreadsheet.cpp...
You should consider a different design, you are tightly coupling your code.
Maybe something like the following...
class Spreadsheet : public QTableWidget
{
Q_OBJECT
signals:
void aValueChanged(int value);
void bValueChanged(int value);
public:
void doSomething()
{
emit aValueChanged(100);
}
};
class MainWindow : public QMainWindow
{
public:
MainWindow() :
a(0),
b(0)
{
connect(&spreadsheet, SIGNAL(aValueChanged(int)), this, SLOT(setA(int)));
connect(&spreadsheet, SIGNAL(bValueChanged(int)), this, SLOT(setB(int)));
spreadsheet.doSomething();
}
slots:
void setA(int value) { a = value; }
void setB(int value) { b = value; }
private:
Spreadsheet spreadsheet;
int a;
int b;
};
This is completely untested but gives you an idea.
You can use the parent() method in the Spreadsheet object to get a pointer to your MainWindow.
For example,
// spreadsheet.cpp
MainWindow* mainWindow = (MainWindow*) this->parent();
mainWindow->set_a(123);
Of course, the parent object passed to Spreadsheet's constructor should be your MainWindow instance for this to work.
However, you should seriously consider oscode's suggestion, since it also points you towards creating a more Qt-like API.