Nested "role" possible in Model/View/QML?

Forum for posting problems using QxOrm library

Nested "role" possible in Model/View/QML?

Postby SteveW » Thu Apr 28, 2016 4:48 pm

Hi, thanks for helps so far in getting things at last runinng. We are now starting to code..

So a quick question (sorry if I missed it in the documentation, or if its out of scope for your help), if we have a nested table, is it possible to access that data via the standard QML "role" functionallity?

Using the Relation string to give dependant table data, a section of out server output is:

Code: Select all
       "list": [
            {
                "key": 1,
                "value": {
                    "cmr_business_name": "Test 1",
                    "cmr_comment": "",
                    "cmr_default_cad_id": {
                        "cad_address_1": "Address Line 1",
                        "cad_address_2": "Address Line 2",
                        "cad_cco_id": {
        ...


And then in eg a QML TreeView we can set the model directly to the QxModel dervied class and populate direct fields simply using the "role" property of the QML object.

Eg:

[code]TableViewColumn {
role: "cmr_business_name"
...
[code]

Is it possible to use the same "role" property to access nested data in 1-1 and 1-n relationships. Using the role "cmr_default_cad_id" gives the raw id back to the QML, but is there anyway to get the data from the table via "role"?

For 1-n relationships, I see the "list_of_xxxx" properties, so if 1-1 is possible via the "role" property is it also possible to obtain the list elements via "role" too?

Thanks.
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Re: Nested "role" possible in Model/View/QML?

Postby SteveW » Fri Apr 29, 2016 12:59 pm

Hi again, I have been experimenting but not with success yet...

In my TreeView, I have created a delegate for the nested data..

Code: Select all
QML:

Item {
   id: root
   CustomersModel {
      id: customersModel
   }
   Component.onCompleted: {
                customersModel.qxFetchAll_("*")
   }

   TreeView {
               model: customersModel
...


        TableViewColumn {
      title: "Address"
          delegate: customerAddressDelegate
      }


and then the delegate itself is defined later as:

Code: Select all
   Component {
      id: customerAddressDelegate
      Item {
         Label {
            id: customerAddressLabel
            anchors.verticalCenter: parent.verticalCenter
            //check if the data is valid
            Text {
               text: model.cmr_default_cad_id
            }
         }
      }
   }



that code, I sucessfully get the crm_default_cad_id (integer value) displayed where expected.

However I would expect that I should be able to say something like:

Code: Select all
text: model.cmr_default_cad_id.cad_address_1


To obtain the relation data in the child table.

Or simply use:

Code: Select all
 role: "cmr_default_cad_id.cad_address_1"


Within the Table view column and not need the delegate at all.

However these attempts just generated QML runtime errors:

Code: Select all
"Unable to assign [undefined] to QString"


Which I can understand if cmr_default_cad_id is simply an integer and not an object.

The QxORM Manual's "Model/View" blog example (Section 7.3), only explains how to get simple data directly from the top level model. ie.

Code: Select all
Item {
   ListView {
      model: myModel
      delegate: Row {
         height: 20
         spacing: 10
         Text { text: "id: " + author_id }
         TextField {
            text: name
            onTextChanged: name = text
         }
      }
   }
}


And not how to get child or dependant list data.

I've been trying to work this out for 2 days now, any help greatly appreciated.
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Re: Nested "role" possible in Model/View/QML?

Postby qxorm » Fri Apr 29, 2016 2:16 pm

Hello,

The QxORM Manual's "Model/View" blog example (Section 7.3), only explains how to get simple data directly from the top level model

About models and relationships, you should read this part of the manual : http://www.qxorm.com/qxorm_en/manual.html#manual_920

Relationships cannot be managed using roles.
By default, QxOrm library exposes to QML engine just simple types (not relationships).
To work with relationships, you have to generate the model/view source code with QxEntityEditor.

Then, there is a hierarchy of models :
- you have a model parent (the root instance you fetch) ;
- each relationship is a child model (you can access to the child models with Q_INVOKABLE methods generated by QxEntityEditor).

So this is a notion of nested models : there is a tutorial (in french, sorry) here : http://christophe-dumez.developpez.com/ ... imbriques/

About QML TreeView, this is not an easy part.
I don't know this component and I don't know if you can use it with nested models.
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: Nested "role" possible in Model/View/QML?

Postby SteveW » Tue May 03, 2016 10:05 am

Hello again,

I have narrowed it down to a very simple question (which I don't know the answer too)...

So first forget "roles", and TreeView, I have now followed the French example and used a ListView. And yes I am using have QxEE generated code, which has generated Q_INVOKABLEs for the child models.

The QxEE Model/Viiew generated clases of interest are:

Code: Select all
class CRM_MODEL_VIEW_EXPORT customer_main_record_model : public customer_main_record_model_base_class
{

   Q_OBJECT

public:

   customer_main_record_model(QObject * parent = 0);
   customer_main_record_model(qx::IxModel * other, QObject * parent);
   virtual ~customer_main_record_model();

   Q_INVOKABLE QObject * list_of_contact_name_link(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_customer_client_consultant(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_customer_client_consultant_1(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_customer_job(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * cmr_default_cad_id(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_customer_type_link(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_dataset_operator(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_sum_it_licence(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());

   /* List of properties exposed by the model (6) :
      - cmr_id
      - cmr_business_name
      - cmr_sort_sequence
      - cmr_user_ref
      - cmr_comment
      - cmr_note
   */

protected:

   virtual void syncNestedModel(int row, const QStringList & relation);
   virtual void syncAllNestedModel(const QStringList & relation);

};


The interesting one here is
Code: Select all
   Q_INVOKABLE QObject * cmr_default_cad_id(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());


And the QeEE generated code for the secondary table is:

Code: Select all
class CRM_MODEL_VIEW_EXPORT contact_address_model : public contact_address_model_base_class
{

   Q_OBJECT

public:

   contact_address_model(QObject * parent = 0);
   contact_address_model(qx::IxModel * other, QObject * parent);
   virtual ~contact_address_model();

   Q_INVOKABLE QObject * cad_cco_id(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_contact_address_link(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
   Q_INVOKABLE QObject * list_of_customer_main_record(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());

   /* List of properties exposed by the model (6) :
      - cad_id
      - cad_address_1
      - cad_address_2
      - cad_village
      - cad_town
      - cad_postcode
   */

protected:

   virtual void syncNestedModel(int row, const QStringList & relation);
   virtual void syncAllNestedModel(const QStringList & relation);

};

} // namespace crm


So first we issue "fetchALL(*)" request which populates the data model with the dependant table data (as my first post here showed in the Server output)...

Code: Select all
      "list": [
            {
                "key": 1,
                "value": {
                    "cmr_business_name": "Company 1",
                    "cmr_comment": "",
                    "cmr_default_cad_id": {
                        "cad_address_1": "Address Line 1",
                        "cad_address_2": "Address Line 2",
                        "cad_cco_id": {
                            "cco_abbreviation": "",
                            "cco_ccu_id": null,
                            "cco_county": "",
                            "cco_id": 35,
                            "list_of_contact_address": [
                            ]
                        },
                        "cad_id": 1,
...


You can see here "cmr_default_cad_id" (value ="1") from our main table refers to another table "contact_address", (and this secondard data model is populated with data "Address Line 1", "Address Line 2").

Now in our QML I tried 2 things...

First was to simply display the raw "crm_default_cmr_id" which comes from the primary table with the QML and this works fine:

Code: Select all
QML:

Item {
   id: root

   CustomersModel {
      id: customersModel
   }

   property int rowHeight: 30

   Component.onCompleted: {
        customersModel.qxFetchAll_("*")
   }

   Component {
      id: customersAddressDelegate

      Rectangle {
         id: customersAddressCell

         height: updateCol.height
         color: "#c0c0c0"
 
         Column {
            id: updateCol
            width: parent.width
 
            Text {
               id: updateText
               text: "Address 1 = " + cmr_default_cad_id
            }
         }
      }
   }
 
   Rectangle {
      width: 360
      height: 360
 
      ListView {
        id: customerAddressView
        anchors.fill: parent
        model: customersModel
        delegate: customersAddressDelegate
      }
   }
}


It gives the following screen outout (see attachment).

Next I changed that QML to attempt to populate list with "cad_address_1" from the secondary table instead of the raw id:

Code: Select all
Item {
   id: root

   CustomersModel {
      id: customersModel
   }

   property int rowHeight: 30

   Component.onCompleted: {
        customersModel.qxFetchAll_("*")
   }

   Component {
      id: customersAddressDelegate

      Rectangle {
         id: customersAddressCell

         height: updateCol.height
         color: "#c0c0c0"
 
         Column {
            id: updateCol
            width: parent.width
 
            Text {
               id: updateText
               text: "Address 1 = " + cmr_default_cad_id(0).cad_address_1
            }
         }
      }
   }
 
   Rectangle {
      width: 360
      height: 360
 
      ListView {
        id: customerAddressView
        anchors.fill: parent
        model: customersModel
        delegate: customersAddressDelegate
      }
   }
}


Hence, I changed:
Code: Select all
               text: "Address 1 = " + cmr_default_cad_id


To:
Code: Select all
               text: "Address 1 = " + cmr_default_cad_id(0).cad_address_1


My thinking was that "cmr_default_cad_id(0)" should give me the first object (INDEX=0) from the cmr_default_cad_id "collection", and then I would use that object to obtain the "cad_address_1" member.

However this generates the following outout errors in the debug output window:

Code: Select all
qrc:/pages/customersPage.qml:37: TypeError: Property 'cmr_default_cad_id' of object [object Object] is not a function


(I have also tried various alternatives, such as using "Repeater"s in the QML, but always I get the same error about "cmr_default_cad_id" not being a function and all I can access is the raw integer ID)

So it is telling me that I cannot use "cmr_default_cad_id" as a function to get to the child model? If that is true, what must I do to get it?

Later we will be using the "list_of_xxxx" models, but until I have understood how to get a simple child model, the rest is on hold.
Attachments
crm1.jpg
crm1.jpg (16.09 KiB) Viewed 10560 times
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Re: Nested "role" possible in Model/View/QML?

Postby SteveW » Tue May 03, 2016 10:58 am

I also have now tried simply

Code: Select all
               text: "Address 1 = " + cmr_default_cad_id.cad_address_1


Thinking possibly "crm_default_cad_id" is not a collection, but can be accessed as single model class. This gives no error in the debug ouput, "undefined" results in the program's Listview:
Attachments
crm2.jpg
crm2.jpg (19.58 KiB) Viewed 10552 times
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Re: Nested "role" possible in Model/View/QML?

Postby qxorm » Tue May 03, 2016 10:59 am

Hello,

Hence, I changed:
Code: Select all
text: "Address 1 = " + cmr_default_cad_id

To:
Code: Select all
text: "Address 1 = " + cmr_default_cad_id(0).cad_address_1


cmr_default_cad_id(0) returns a model, so you have to pass the model to another QML component.

My thinking was that "cmr_default_cad_id(0)" should give me the first object (INDEX=0) from the cmr_default_cad_id "collection"

Yes exactly, it gives you the model associated to the item 0 of your collection.

EDIT : here is another topic (sorry, again in french) about model/view : http://www.developpez.net/forums/d14879 ... modelview/
Maybe this topic could help you.
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: Nested "role" possible in Model/View/QML?

Postby qxorm » Tue May 03, 2016 11:04 am

Moreover, since all models are based on qx::IxModel class, this code should work :
Code: Select all
cmr_default_cad_id(0).getModelValue(0, "cad_address_1")


The getModelValue() method is defined as Q_INVOKABLE in the qx::IxModel model base class.
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: Nested "role" possible in Model/View/QML?

Postby SteveW » Tue May 03, 2016 11:26 am

Hi

The error is still the same:

Code: Select all
qrc:/pages/customersPage.qml:37: TypeError: Property 'cmr_default_cad_id' of object [object Object] is not a function


It seems the problem is that "cmr_default_cad_id" is returning an integer, and is not "invokable" as a function?
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Re: Nested "role" possible in Model/View/QML?

Postby SteveW » Tue May 03, 2016 11:35 am

And if I try to put Index (0) as the model of another delegate

eg:

Code: Select all
   Component {
      id: addressDelegate
      Rectangle {
         id: customersAddressCell

         height: updateCol.height
         color: "#c0c0c0"
 
         Column {
            id: updateCol
            width: parent.width

            Text {      
               text: "Address 1 = " + cad_address_1
            }   
         }
      }
   }


and in later in the QML


Code: Select all
            Repeater {
               id: updateText
               model: cmr_default_cad_id(0)
               delegate: addressDelegate
            }   


Then i get the same error

Code: Select all
qrc:/pages/customersPage.qml:56: TypeError: Property 'cmr_default_cad_id' of object [object Object] is not a function


For the line
Code: Select all
               model: cmr_default_cad_id(0)



As I said I in my earlier post, I have tried many alternative ways to obtain my child data, but simply "cmr_default_cad_id" only acts as an integer even though it is defined as Q_INVOKABLE.
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Re: Nested "role" possible in Model/View/QML?

Postby SteveW » Tue May 03, 2016 11:47 am

Maybe a clue? If i right click on Q_INVOKABLE, in Visual Studio and "go to definition" it takes me to this section of the .H file... (see screenshot)

So if Q_INVOKABLE is "undefined" default it will be an integer return type for the methods definitions in the class.

Is it possible I missing some compiler definitions in the build somewhere?
Attachments
q_in.jpg
q_in.jpg (226.28 KiB) Viewed 10543 times
SteveW
 
Posts: 53
Joined: Tue Jan 19, 2016 4:12 pm

Next

Return to QxOrm - Help

Who is online

Users browsing this forum: No registered users and 13 guests