DEVELOPERS BLOG

Charts with Cascades: Integration through jQuery

The following guest post comes from Alessandro Bellotti, BlackBerry Developer Elite.
In applications that manipulate and display a huge amount of data, it is very useful to integrate charts to provide a better user experience while showing that data to the user.

Currently in Cascades, the Qt class Graph can’t be used. Several solutions have been used, including the use of a background image with overlaying text written by using a Label {}, but this approach never led to optimal results.

Fortunately, thanks to the great flexibility of the BlackBerry 10 Native SDK and to Angelo Gallarello, a member of our BlackBerry Dev Group in Milan who has shown us a great JavaScript library called jQuery Sparklines, we can solve the problem of using graphs in a very simple, fast and effective way.

jQuery is very flexible and easy to use. It supports seven different chart types and all of them are easily customizable.

A very cool feature is the possibility to test the custom parameters in real time thanks to the dedicated box and very detailed documentation on customizing charts.

charts with cascades

The integration into a Cascades project is very easy: the first step is to create an HTML file with a simple text editor. In our case, we name it “grafico.html” and it looks like the following:

charts with cascades_code

Minified can be downloaded here:

Select all the text in the two links and paste between:

<script type=”text/javascript”>  e </script>

of the “grafico.html” file.

To display the graph, you just need to add a WebView to your project (in the QML file that should display the graph), setting its URL to the location of your HTML file.

WebView {
     id: idWebView
     objectName: "idWebView"
     url: "local:///assets/webview/grafico.html"
     verticalAlignment: VerticalAlignment.Fill
     horizontalAlignment: HorizontalAlignment.Fill
}

The next step is to create the string with the values ​​that will be inserted in the grafico.html file to produce the graph.

In our case, I took a SQLLite database, and while rushing records with a Select, I created the string using the method of creating a function callable from the QML in the header file (HPP):

Q_INVOKABLE void readData (QString search);

and a Q_SIGNALS

void gotSparky(QString Sparky);

In CPP, I scrolled the database and for each record found and built the string in the global variable Sparky, maintaining the structure required by the jQuery library.

Finally, after reading all the records, I finished the creation by integrating the Sparky string with Sparky_Full which also contains the parameters for the creation of the chart. So I have set the string in QML “emit gotSparky(Sparky_Full);

void ApplicationUI::readData(QString search)
{
      QSqlDatabase database = QSqlDatabase::database();
      SqlDataAccess *sqlda = new SqlDataAccess(database.databaseName());
      QString appo = search;
      QVariant result = sqlda->execute(appo);
      Sparky_Full = "";
      Sparky = "[";
    if (!sqlda->hasError()) {
        int recordsRead = 0;
        if( !result.isNull() ) {
            QVariantList list = result.value<QVariantList>();
            recordsRead = list.size();
            for(int i = 0; i < recordsRead; i++) {
                QVariantMap map = list.at(i).value<QVariantMap>();
                if (i == 0){
                  Sparky = Sparky +  map.value("quantita").toString();
                }
                else {
                  Sparky = Sparky + "," + map.value("quantita").toString();
                }
            }
            Sparky = Sparky + "]";
Sparky_Full = QString("$('.sparkline').sparkline(")+ Sparky + QString(",{type: 'line', chartRangeMin: '0', fillColor: false, width: '720', height: '250'});");
            emit gotSparky(Sparky_Full);
        }
        if (recordsRead == 0) {
        //  showToast("NO Data!");
        }
    } else {
        alert(tr("Read records failed: %1").arg(sqlda->error().errorMessage()));
    }
}

In the QML file you just need to add a few lines of code. I created two “property” that have the task of checking if the app is already connected to the “onGotSparky” signal (because in that case the data is duplicated), and a support string for the output string coming from the C++ function.

import bb.cascades 1.0
import bb.system 1.0
 
Page {
    property variant connessoSparky:0
    property string sparky_String: ""
 
onCreationCompleted: 
        if (connessoSparky == 0){
            _app.gotSparky.connect(onGotSparky)
            connessoSparky = 1 
        }
            _app.readData(“SELECT * FROM myDataBase”)
    }
 
function onGotSparky(stringa) {
        sparky_String = stringa
}

I put in the evaluateJavaScript() in a ActionItem to keep everything separate. In practice, when onTriggered:{} is issued, the string is passed to the HTML page that elaborates it and gives the graph.

    actions: [
        ActionItem {
            id: actGraph
            title: "Titolo"
            imageSource: "asset:///images/menuicons/ic_chart.png"
            ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
                                 waterWebView.evaluateJavaScript(sparky_String)
            }
        }
   ]

That’s all! Let us know if you have any questions in the comments below, and happy coding!

About lfiligheddu