SpinalCore Qt SDK

Installation

Qt Connector

Download the SpinalCore Qt connector from http://resources.spinalcom.com/SpinalCoreQT.zip. 
The SDK is exposed in a global file named SpinalCore.h. Include it in your main.cpp file:

#include "SpinalCoreQT/SpinalCore.h"

The SpinalCoreQT resources contains the Qt connector and pre-completed files that you can use to build your first organ :

  • the main file ( main.cpp )
  • a process class (process.cpp and process.h )
Connecting to the hub

QString IP = "127.0.0.1";
QHostAddress adress( IP );
QString port = "8890";
SpinalCore* myConnector = new SpinalCore( adress, port.toInt(), userid, password );

This method establishes a connection with the hub. It returns an object (myConnector ) containing the connection information, which will be used in the other SDK methods that communicate with the hub.

The string parameters are the following:

  • IP: address of the hub
  • port: port number where the hub is running
  • userid: a user id that has access to the data; beware that the user has the needed rights to manage the data (read more about it here)
  • password: the password of the user
Synchronizing models with the hub

SpinalCoreQT SDK offers three different methods to access and replicate objects with SpinalHub.

Synchronize a specific model:
ModelPointer myModel = myConnector->load( "__myApp__/myModel" );

Once an object has been saved in the hub using the JavaScript SDK, this command is used to fetch it and start the synchronization process. The parameter accepted is a string which contains the path of the object in the virtual filesystem of the hub.

Synchronize all the models of a specific type:
myConnector->load_type( "MyModelClassName" );

This command is used for synchronizing all the models with the specified type MyModelClassName. The parameter accepted is a string corresponding to the name of the model class you want to synchronize.

Synchronize a specific pointed model:
ModelPointer myModel = myConnector->load_ptr( ptr_id );

In some cases big models need to be splited in different parts. SpinalCore offers a generic way to create weak links between these parts and the Ptr Model. Models linked with Ptr are not directly loaded in the connector. You have to explicitelly load them using the load_ptr method. Once a Ptr has been saved in the hub using the JavaScript SDK, use this method to synchronize the associated model. The parameter accepted is an integer comming from the Ptr Model.

Getting data using the ModelPointer object

ModelPointer myModelPointer = myModel[ "attribute" ]; //instanciate a ModelPointer from an attribute of the ModelPointer myModel 
ModelPointer mySubSubAttribute = myModel[ "attribute" ][ "sub-attribute" ][ "sub-sub-attribute" ];

int myInt       = myModel[ "Val_attribute" ]; //instanciate an integer from an attribute of the ModelPointer myModel 
double myDouble = myModel[ "Val_attribute" ]; //instanciate an double from an attribute of the ModelPointer myModel 

Qstring myString = myModel[ "Str_attribute" ]; //instanciate an Qstring from an attribute of the ModelPointer myModel 

double myDouble = myModel[ "list" ][i]; //instanciate an double from an element of the attribute list of type Lst of the ModelPointer myModel 

Here are some examples of how to get data from a ModelPointer. To obtain an attribute of a model, use this syntax: myModel[ "attributeName" ].

Setting data using the ModelPointer object

ModelPointer myModelPointer = myModel[ "attribute" ];
myModelPointer = anotherModelPointer; //Modifie the pointed model  

myModel[ "Bool_attribute" ] = true; //Modifie the data of the attribute Bool_attribute 

ModelPointer myList = myModel[ "Lst_attribute" ];
myList << element; // add a new element at the end of a list Lst

Here are some examples of how to set data in a ModelPointer. The operators "=" and "<<" of the class ModelPointer have been overloaded. They include the observation process that automaticaly synchronizes the model with the hub.

Creating new models

ModelPointer myObj = new_obj( "aModelClassName" );
ModelPointer myLst = new_lst();
ModelPointer myPath = new_path( path );
ModelPointer myFile = new_file( "fileName", aModelPointer );
ModelPointer myPtr = new_ptr( aModelPointer );       

These methods will create models in your Qt organ. 
The new_obj() method can create every kind of model. The parameter is the name of the model class (the name of the class in JavaScript). The created model does not have any attribute at this stage. You can set new attributes using the former defined operator ("=" and "<<"). 
The other methods allows to create specific atomic models with predefined prototype.
Note that these models are NOT synchronized with the hub yet. You will have to store them into an existing synchronized container model (File, Lst...). For example:

ModelPointer mySyncModel = myConnector->load( "__myApp__/myModel" );
ModelPointer myObj  = new_obj( "myModelClassName" ); 
ModelPointer myList = new_lst(); 
myList << myObj; 
mySyncModel["myList"] = myList;
Using a process

A Process is a class prepared to interact with changes in the models and to run the specific function of the organ (1 connector + 1 process = 1 organ).

// Process.h

#ifndef PROCESS_H
#define PROCESS_H
#include <SpinalCoreQT/SpinalCore.h>
#include <QtCore/QList>

class Process : public QObject {
    public:
        Process();
        ~Process();
        void onchange(SpinalCore::Event event);   // function to load
        SpinalCore* connector;                  // binded connector
        QList<ModelPointer> models;             // binded model(s)
};

#endif // PROCESS_H
// Process.cpp

#include "Process.h"

Process::Process(){}
Process::~Process(){}

void Process::onchange( SpinalCore::Event event ){
    ModelPointer model = models[0];
    // process code here
}        

To listen to changes in the model, SpinalCore offers a dedicated event loop that you can use as follows in the main file:

Process *myProcess = new Process();
myProcess->connector = myConnector;
myProcess->models << myModel;

while ( SpinalCore::Event event = myConnector->event() ){
    myProcess->onchange( event );
}

Each time a model in the hub is modified, an event is sent to the connector. Then the condition in the while() is true and the onchange() method of the process is called.