create and set custom read only attached properties from cpp - c++

say i have some custom view class in c++ which defines a set of attached properties. A component delegate to instantiate a viewItem for when a model object is added. How would i make the Attached properties work properly, to keep external data the attache cannot set itself?
Demo code example
class someModel: public QObject
{
QOBJECT
Q_PROPERTY(data_1 ...)
Q_PROPERTY(data_2 ...)
public:
SomeView(QObject* parent);
};
class SomviewViewAttached: public QObject
{
QOBJECT
// read only properties with signals
Q_PROPERTY(SomeView view...)
Q_PROPERTY(SomeModel model...)
Q_PROPERTY(int index ...)
public:
SomviewViewAttached(QObject* parent);
};
class SomeView : public QQuickItem
{
QOBJECT
// ill skip giving the full get setter implementation
Q_PROPERTY(QQmlCommponent delegate .........)
public:
SomeView(QObject* parent);
Q_INVOKABLE void addToView(SomeModel* model);
private:
List<SomeModel*> items;
static SomviewViewAttached *qmlAttachedProperties(QObject *item)
{
return new SomeViewAttached(item);
}
};
QML_DECLARE_TYPEINFO(SomeView,QML_HAS_ATTACHED_PROPERTIES)
in qml the usage would be
SomeView{
id: view
Component{
Item{
foo1: model.data_1
foo2: model.data_2
number : SomeView.index
condition : SomeView.view.something...
}
}
Component.onCompleted: view.addToView(new someModel)
}

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;
};

How to access qabstractlistmodel derived class object as a property of another class from qml?

Iam designing a qml page which consists of 3 lists. I want the data to be displayed in these lists as model from cpp. Can i have all these 3 models as properties from a single class.
I have a class derived from qabstractlistmodel to use as model. I want this model as a property from another class which is bind to qml using qqmlcontextproperty.
ie. I could be able to access this model as a property.
class ToDoModel : public QAbstractListModel
{
Q_OBJECT
...
}
class HelperClass : public QObject
{
Q_OBJECT
Q_PROPERTY(ToDoModel todoModel READ todoModel CONSTANT)
public:
explicit HelperClass(QObject *parent = nullptr);
ToDoModel* todoModel() const;
signals:
public slots:
private:
ToDoModel *_todoModel;
};
int main(int argc, char *argv[])
{
HelperClass helperClass;
engine.rootContext()->setContextProperty(QStringLiteral("helperClass"), &helperClass);
...
}
It shows the error :
Unable to handle unregistered datatype 'ToDoModel' for property 'HelperClass::todoModel'
A QObject, like the QAbstractListModel, is not copied, so in that case you must return the pointer. So in general if T is a QObject then if you expose it as a property it must be Q_Property(T* name ...).
So in your case it changes to:
class HelperClass : public QObject
{
Q_OBJECT
Q_PROPERTY(ToDoModel* todoModel READ todoModel CONSTANT)
// ...
You can use friend class to allow access to private and protected members of other class

qt - send signal between objects in a class with different parents

I have a class ("controller" for example)
and in this class, I have created many objects of different other classes
with different parents.
How to send signal between that classes and "controller" to call a function in "controller" class?
#include "controller.h"
Controller::Controller(QObject *parent) : QObject (parent){
connect(sender(), SIGNAL(recivedCall(QString)), this, SLOT(alert(QString)));
}
void Controller::onCall(QJsonObject callinfo){
nodes[callinfo["username"].toString()]= new PanelManager();
nodes[callinfo["username"].toString()]->handleCallStateChanged(callinfo);
}
void Controller::alert(QString callinfo){
qDebug()<<callinfo;
}
For example, how to send signal from "recivedCall" in each "PanelManager" object to call "alert" function in "controller" class ?
The object which creates your two components has to set the connections between your signal and your slot. But, you shouldn't expose inner components (i.e. create getter to return a pointer on a attribute).
A way to tackle the last problem with Qt is to create a signal in your parent and let it broadcast the calls.
For example, if I need to connect a QCheckBox to a QLineEdit in two different widgets:
class Parent1: public QWidget
{
Q_OBJECT
public:
Parent1(): QWidget(), myCheckBox(new QCheckBox("Edit", this))
{
connect(myCheckBox, &QCheckBox::clicked, this, &Parent1::editForbidden);
}
private:
QCheckBox* myCheckBox;
signals:
void editForbidden(bool);
};
class Parent2: public QWidget
{
Q_OBJECT
public:
Parent2(): QWidget(), myLineEdit(new QLineEdit("Edit", this))
{
connect(this, &Parent2::forbidEdit, myLineEdit, &QLineEdit::setReadOnly);
}
private:
QLineEdit* myLineEdit;
signals:
void forbidEdit(bool);
};
// In the parent of Parent1 and Parent2 (or in the main if there is no parent)
QObject::connect(p1, &Parent1::editForbidden, p2, &Parent2::forbidEdit);
In this example, when I click on the checkbox in parent1, the lineEdit in parent2 is disabled. But, Parent1 doesn't know anything about Parent2.

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.

Qt QML C++ Plugin Singleton

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.