SailfishOS Logic: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[[Category:SailfishOS::Developer_guide]]
[[Category:SailfishOS::Developer_guide]]


[toc align_right="yes" depth="2"]
[toc align_right="yes" depth="2"]


'''English''' | [[:SailfishOS_Polish|Polski]]
'''English''' | [[:SailfishOS_Polish|Polski]]
Line 13: Line 13:
Currently there are three languages supported for implementing business logic. However SailfishOS offically support two of them(which are btw. standard solution for Qt/QML apps):
Currently there are three languages supported for implementing business logic. However SailfishOS offically support two of them(which are btw. standard solution for Qt/QML apps):


* *C+''*<br />* '''Javascript'''
* *C+''*
<br />Except C''+ and Javascript there is also partial support for '''Python''' scripts. However it is not available to put apps based on python into &quot;jolla harbour&amp;quot;:https://harbour.jolla.com/ yet, but you can still install them on devices manually. More info &quot;here&amp;quot;:https://wiki.merproject.org/wiki/Sailfish/Python_Development.  
* '''Javascript'''
 
Except C''+ and Javascript there is also partial support for '''Python''' scripts. However it is not available to put apps based on python into "jolla harbour":https://harbour.jolla.com/ yet, but you can still install them on devices manually. More info "here":https://wiki.merproject.org/wiki/Sailfish/Python_Development.  


== How can I put logic into my apps? ==
== How can I put logic into my apps? ==
Line 30: Line 32:
==== Importing external logic - .qml ====
==== Importing external logic - .qml ====


<code>[…]<br />import &quot;content/calculator.js&amp;quot; as CalcEngine<br />[…]<br />Rectangle {<br /> […]<br /> function operatorPressed(operator) { CalcEngine.operatorPressed(operator) }<br /> function digitPressed(digit) { CalcEngine.digitPressed(digit) }<br />[…]</code>
<code>[…]
import "content/calculator.js" as CalcEngine
[…]
Rectangle {
[…]
function operatorPressed(operator) { CalcEngine.operatorPressed(operator) }
function digitPressed(digit) { CalcEngine.digitPressed(digit) }
[…]</code>


==== Implicit behaviour code - .qml. ====
==== Implicit behaviour code - .qml. ====


<code>[…]<br />Item {<br /> […]<br /> function displayOperator(operator)<br /> {<br /> listView.model.append({ &quot;operator&amp;quot;: operator, &quot;operand&amp;quot;: &quot;&quot; })<br /> enteringDigits = true<br /> }<br /> […]<br /> function appendDigit(digit)<br /> {<br /> if (!enteringDigits)<br /> listView.model.append({ &quot;operator&amp;quot;: &quot;&quot;, &quot;operand&amp;quot;: &quot;&quot; })<br /> var i = listView.model.count - 1;<br /> listView.model.get(i).operand = listView.model.get(i).operand + digit;<br /> enteringDigits = true<br /> }<br />[…]</code>
<code>[…]
Item {
[…]
function displayOperator(operator)
{
listView.model.append({ "operator": operator, "operand": "" })
enteringDigits = true
}
[…]
function appendDigit(digit)
{
if (!enteringDigits)
listView.model.append({ "operator": "", "operand": "" })
var i = listView.model.count - 1;
listView.model.get(i).operand = listView.model.get(i).operand + digit;
enteringDigits = true
}
[…]</code>


==== Calling external functions - .qml. ====
==== Calling external functions - .qml. ====


<code>[…]<br />MouseArea {<br /> […]<br /> onClicked: {<br /> //parent.clicked()<br /> if (operator)<br /> window.operatorPressed(parent.text)<br /> else<br /> window.digitPressed(parent.text)<br /> }<br /> }<br />[…]</code>
<code>[…]
MouseArea {
[…]
onClicked: {
//parent.clicked()
if (operator)
window.operatorPressed(parent.text)
else
window.digitPressed(parent.text)
}
}
[…]</code>


==== External module with logic - .js. ====
==== External module with logic - .js. ====


<code>[…]<br />function disabled(op) {<br /> if (op  &amp;quot;.&amp;quot; &amp;amp;&amp;amp; digits.toString().search(/\./) != -1) &amp;#123;
<code>[…]
function disabled(op) {
if (op  "." &amp;amp;&amp;amp; digits.toString().search(/\./) != -1) {
         return true
         return true
     &amp;#125; else if (op  window.squareRoot &amp;&amp; digits.toString().search(/-/) != <s>1) {<br /> return true<br /> } else {<br /> return false<br /> }<br />}
     } else if (op  window.squareRoot &amp;&amp; digits.toString().search(/-/) != -1) {
<br />function digitPressed(op)<br />{<br /> if (disabled(op))<br /> return<br /> if (digits.toString().length &gt;= 14)<br /> return<br /> if (lastOp.toString().length  1 &amp;amp;&amp;amp; ((lastOp &amp;gt;= &amp;quot;0&amp;quot; &amp;amp;&amp;amp; lastOp &amp;lt;= &amp;quot;9&amp;quot;) || lastOp  &quot;.&quot;) ) {<br /> digits = digits + op.toString()<br /> display.appendDigit(op.toString())<br /> } else {<br /> digits = op<br /> display.appendDigit(op.toString())<br /> }<br /> lastOp = op<br />}<br />[…]</code>
return true
<br />
} else {
return false
}
}
 
function digitPressed(op)
{
if (disabled(op))
return
if (digits.toString().length >= 14)
return
if (lastOp.toString().length  1 &amp;amp;&amp;amp; ((lastOp >= "0" &amp;amp;&amp;amp; lastOp <= "9") || lastOp  ".") ) {
digits = digits + op.toString()
display.appendDigit(op.toString())
} else {
digits = op
display.appendDigit(op.toString())
}
lastOp = op
}
[…]</code>
 


<br />h2. Python
<br />Currently the best approach to develop with python on SailfishOS is to use PyOtherSide qml plugin, as it was mentioned before it should be supported in jolla harbour soon. &quot;Here&amp;quot;:http://pyotherside.readthedocs.org/en/latest/ you can find documentation of PyOtherSide. It contains some examples and describes general idea.
<br />Before deploying apps with PyOtherSide on targets with SailfishOS you need to follow guides from &quot;this article&amp;quot;:https://lists.sailfishos.org/pipermail/devel/2013-September/000782.html. Generally you need to instal python3 and PyOtherSide plugin on target machine(either device or emulator). Please read it before trying to build example code presented below.
<br />h4. External module with logic</s> ProjectName\qml\pages\duration.py


<code>import os<br />import struct<br />import pyotherside
h2. Python


def get_item_list(count):<br /> items = [<br /> { 'name': 'first' },<br /> { 'name': 'second' },<br /> { 'name': 'third' },<br /> { 'name': 'fourth' },<br /> { 'name': 'fifth' },<br /> { 'name': 'sixth' },<br /> { 'name': 'seventh' },<br /> { 'name': 'eight' },<br /> { 'name': 'ninth' },<br /> { 'name': 'tenth' },<br /> ]<br /> return items[:count]
Currently the best approach to develop with python on SailfishOS is to use PyOtherSide qml plugin, as it was mentioned before it should be supported in jolla harbour soon. "Here":http://pyotherside.readthedocs.org/en/latest/ you can find documentation of PyOtherSide. It contains some examples and describes general idea.


def get_other_item_list():<br /> items = [<br /> { 'name': 'it works' },<br /> { 'name': 'like' },<br /> { 'name': 'charm' },<br /> { 'name': 'really!' },<br /> ]<br /> return items[:]
Before deploying apps with PyOtherSide on targets with SailfishOS you need to follow guides from "this article":https://lists.sailfishos.org/pipermail/devel/2013-September/000782.html. Generally you need to instal python3 and PyOtherSide plugin on target machine(either device or emulator). Please read it before trying to build example code presented below.


pyotherside.atexit(get_item_list)<br />pyotherside.atexit(get_other_item_list)</code>
h4. External module with logic- ProjectName\qml\pages\duration.py
 
<code>import os
import struct
import pyotherside
 
def get_item_list(count):
items = [
{ 'name': 'first' },
{ 'name': 'second' },
{ 'name': 'third' },
{ 'name': 'fourth' },
{ 'name': 'fifth' },
{ 'name': 'sixth' },
{ 'name': 'seventh' },
{ 'name': 'eight' },
{ 'name': 'ninth' },
{ 'name': 'tenth' },
]
return items[:count]
 
def get_other_item_list():
items = [
{ 'name': 'it works' },
{ 'name': 'like' },
{ 'name': 'charm' },
{ 'name': 'really!' },
]
return items[:]
 
pyotherside.atexit(get_item_list)
pyotherside.atexit(get_other_item_list)</code>


==== Calling external functions - .qml. ====
==== Calling external functions - .qml. ====


<code>import QtQuick 2.0<br />import Sailfish.Silica 1.0<br />import io.thp.pyotherside 1.0
<code>import QtQuick 2.0
import Sailfish.Silica 1.0
import io.thp.pyotherside 1.0


Page {<br /> id: page
Page {
id: page


Python {<br /> id:py<br /> Component.onCompleted: {
Python {
id:py
Component.onCompleted: {


addImportPath(Qt.resolvedUrl('.').substr('file://'.length));
addImportPath(Qt.resolvedUrl('.').substr('file://'.length));


importModule('duration', function() {<br /> call('duration.get_item_list', [5], function(result){<br /> for (var i=0; i&amp;lt;result.length; i+'') {<br /> listModel.append(result[i]);<br /> }<br /> });<br /> });<br /> }<br /> onError: console.log('Python error: ''' traceback)<br /> }
importModule('duration', function() {
call('duration.get_item_list', [5], function(result){
for (var i=0; i<result.length; i+'') {
listModel.append(result[i]);
}
});
});
}
onError: console.log('Python error: ''' traceback)
}
 
SilicaListView {
PullDownMenu {
MenuItem {
text: "Option 1"
onClicked: py.call('duration.get_other_item_list',[], function(result){
for (var i=0; i<result.length; i+'') {
listModel.append(result[i]);
}
});
}
}
id: listView
model: ListModel{
id: listModel
}
 
anchors.fill: parent
 
delegate: BackgroundItem {
id: delegate


SilicaListView {<br /> PullDownMenu {<br /> MenuItem {<br /> text: &quot;Option 1&amp;quot;<br /> onClicked: py.call('duration.get_other_item_list',[], function(result){<br /> for (var i=0; i&amp;lt;result.length; i+'') {<br /> listModel.append(result[i]);<br /> }<br /> });<br /> }<br /> }<br /> id: listView<br /> model: ListModel{<br /> id: listModel<br /> }
Label {
<br /> anchors.fill: parent
x: Theme.paddingLarge
<br /> delegate: BackgroundItem {<br /> id: delegate
text: name'' " item"
<br /> Label {<br /> x: Theme.paddingLarge<br /> text: name'' &quot; item&amp;quot;<br /> anchors.verticalCenter: parent.verticalCenter<br /> color: delegate.highlighted ? Theme.highlightColor : Theme.primaryColor<br /> }<br /> onClicked: console.log(&quot;Clicked &quot; + name)<br /> }<br /> VerticalScrollDecorator {}
anchors.verticalCenter: parent.verticalCenter
color: delegate.highlighted ? Theme.highlightColor : Theme.primaryColor
}
onClicked: console.log("Clicked " + name)
}
VerticalScrollDecorator {}


}<br />}</code>
}
}</code>


==== Entry point for qml pages - .qml. ====
==== Entry point for qml pages - .qml. ====


<code>import QtQuick 2.0<br />import Sailfish.Silica 1.0<br />import &quot;pages&amp;quot;
<code>import QtQuick 2.0
import Sailfish.Silica 1.0
import "pages"


ApplicationWindow<br />{<br /> initialPage: Component { Page { } }<br />}</code>
ApplicationWindow
{
initialPage: Component { Page { } }
}</code>



Revision as of 10:59, 25 February 2015


[toc align_right="yes" depth="2"]

English | Polski

Logic

Except showing nice pages containig widgets full of data usually application has to do some tasks to manipulate the data(in fact it is very common to treat providing data as a task itself). Obviously complexity of tasks vary between diffrent applications and use cases, but even the simplest ones maybe very important. For example the 'add two given numbers' opration in a calculator app is a very simple logic but without it the calculator app wouldn't be very useful.

Available technology

Currently there are three languages supported for implementing business logic. However SailfishOS offically support two of them(which are btw. standard solution for Qt/QML apps):

  • *C+*
  • Javascript

Except C+ and Javascript there is also partial support for Python scripts. However it is not available to put apps based on python into "jolla harbour":https://harbour.jolla.com/ yet, but you can still install them on devices manually. More info "here":https://wiki.merproject.org/wiki/Sailfish/Python_Development.

How can I put logic into my apps?

You can do it either implicitly - write logic as a functions in qml file or explicitly - call logic from external file. The implicit approach is only available with Javascript and it's recommended only with simple routines. The external solution can be done with all of the supported technology and it's considered as better approach. It lets you decouple code responsible for logic and code responsible for behaviour or appearence which is significat advantage while working on bigger projects.

C++

Javascript

Presented sinippets come from tutorial project 'calqlator' which is appeneded to SailfishOS IDE.

Importing external logic - .qml

[]
import "content/calculator.js" as CalcEngine
[]
Rectangle {
 []
 function operatorPressed(operator) { CalcEngine.operatorPressed(operator) }
 function digitPressed(digit) { CalcEngine.digitPressed(digit) }
[]

Implicit behaviour code - .qml.

[]
Item {
 []
 function displayOperator(operator)
 {
 listView.model.append({ "operator": operator, "operand": "" })
 enteringDigits = true
 }
 []
 function appendDigit(digit)
 {
 if (!enteringDigits)
 listView.model.append({ "operator": "", "operand": "" })
 var i = listView.model.count - 1;
 listView.model.get(i).operand = listView.model.get(i).operand + digit;
 enteringDigits = true
 }
[]

Calling external functions - .qml.

[]
MouseArea {
 []
 onClicked: {
 //parent.clicked()
 if (operator)
 window.operatorPressed(parent.text)
 else
 window.digitPressed(parent.text)
 }
 }
[]

External module with logic - .js.

[]
function disabled(op) {
 if (op  "." &amp;amp;&amp;amp; digits.toString().search(/\./) != -1) {
        return true
    } else if (op  window.squareRoot &amp;&amp; digits.toString().search(/-/) != -1) {
 return true
 } else {
 return false
 }
}

function digitPressed(op)
{
 if (disabled(op))
 return
 if (digits.toString().length >= 14)
 return
 if (lastOp.toString().length  1 &amp;amp;&amp;amp; ((lastOp >= "0" &amp;amp;&amp;amp; lastOp <= "9") || lastOp  ".") ) {
 digits = digits + op.toString()
 display.appendDigit(op.toString())
 } else {
 digits = op
 display.appendDigit(op.toString())
 }
 lastOp = op
}
[]


h2. Python

Currently the best approach to develop with python on SailfishOS is to use PyOtherSide qml plugin, as it was mentioned before it should be supported in jolla harbour soon. "Here":http://pyotherside.readthedocs.org/en/latest/ you can find documentation of PyOtherSide. It contains some examples and describes general idea.

Before deploying apps with PyOtherSide on targets with SailfishOS you need to follow guides from "this article":https://lists.sailfishos.org/pipermail/devel/2013-September/000782.html. Generally you need to instal python3 and PyOtherSide plugin on target machine(either device or emulator). Please read it before trying to build example code presented below.

h4. External module with logic- ProjectName\qml\pages\duration.py

import os
import struct
import pyotherside

def get_item_list(count):
 items = [
 { 'name': 'first' },
 { 'name': 'second' },
 { 'name': 'third' },
 { 'name': 'fourth' },
 { 'name': 'fifth' },
 { 'name': 'sixth' },
 { 'name': 'seventh' },
 { 'name': 'eight' },
 { 'name': 'ninth' },
 { 'name': 'tenth' },
 ]
 return items[:count]

def get_other_item_list():
 items = [
 { 'name': 'it works' },
 { 'name': 'like' },
 { 'name': 'charm' },
 { 'name': 'really!' },
 ]
 return items[:]

pyotherside.atexit(get_item_list)
pyotherside.atexit(get_other_item_list)

Calling external functions - .qml.

import QtQuick 2.0
import Sailfish.Silica 1.0
import io.thp.pyotherside 1.0

Page {
 id: page

Python {
 id:py
 Component.onCompleted: {

addImportPath(Qt.resolvedUrl('.').substr('file://'.length));

importModule('duration', function() {
 call('duration.get_item_list', [5], function(result){
 for (var i=0; i<result.length; i+'') {
 listModel.append(result[i]);
 }
 });
 });
 }
 onError: console.log('Python error: ''' traceback)
 }

SilicaListView {
 PullDownMenu {
 MenuItem {
 text: "Option 1"
 onClicked: py.call('duration.get_other_item_list',[], function(result){
 for (var i=0; i<result.length; i+'') {
 listModel.append(result[i]);
 }
 });
 }
 }
 id: listView
 model: ListModel{
 id: listModel
 }

 anchors.fill: parent

 delegate: BackgroundItem {
 id: delegate

 Label {
 x: Theme.paddingLarge
 text: name'' " item"
 anchors.verticalCenter: parent.verticalCenter
 color: delegate.highlighted ? Theme.highlightColor : Theme.primaryColor
 }
 onClicked: console.log("Clicked " + name)
 }
 VerticalScrollDecorator {}

}
}

Entry point for qml pages - .qml.

import QtQuick 2.0
import Sailfish.Silica 1.0
import "pages"

ApplicationWindow
{
 initialPage: Component { Page { } }
}