#App is Gurra’s root component. It manages the lifecycle of a Gurra app.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import Org.Yasser.Gurra 1.0
import Gurra 1.0
import "qrc:/qml"
import "qrc:/qml/pages"
import "popups"
import "customs" as Custom
App
{
id: app
title: qsTr("Hello Gurra!")
view: mainStack
api: Custom.Api{}
logic: Custom.Logic{}
pages: Custom.Pages{}
colors: Custom.Colors{}
urls: Custom.Urls{}
headers: Custom.Headers{}
models: Custom.Models{}
settings: Custom.Settings{}
params: Custom.Params{}
fonts: Custom.Fonts{}
production: true
}
#Properties
###production: bool
default: true
This property holds whether the app is running in production mode or debug mode.
Gurra make no use of this property internally right now, but you may use it to change the behavior of your code depending whether it is running in production or debug
Urls
{
root: app.production? "http://www.example.com:8080" : http://localhost:8080"
pictures: app.production? "http://example.com/uploads/" : "http://localhost/uploads/"
}
###api: QtObject
This property holds all app restful api.
Following the structure of Gurra app, you are encouraged to put your network-related code in one .qml file and reference this file using api
property, this makes your code more readable and easily maintainable.
Example:
var user = {
name: 'Jhon Due',
email: 'some.email@example.com',
password: 'pass'
}
// use app.api to access network-related code
app.api.users.create(user).then(function(response){
console.log(response)
})
###logic: QtObject
This property holds all app logic
Just like api
, following the structure of Gurra app, you are encouraged to put your logic code in one .qml file and reference this file using logic
property, this makes your code more readable and easily maintainable.
// log user in
app.logic.login(user_id)
// do somthing
app.logic.doSomthing()
###pages: Item
This property holds all app pages
/Custom/Pages.qml
import QtQuick 2.0
import Gurra 1.0
import "../pages"
Item
{
property Home home: Home{} // not lazy, need to be loaded at startup
// lazy pages will be loaded when pushed using app.pushPage()
//lazy pages with high priority will be loaded after main.qml is loaded
property LazyPage contactUsPage: LazyPage{
source: "qrc:/qml/pages/ContactUsPage.qml"
}
property LazyPage aboutPage: LazyPage{
source: "qrc:/qml/pages/AboutPage.qml"
}
property LazyPage loginPage: LazyPage{
source: "qrc:/qml/pages/LoginPage.qml"
}
property LazyPage joinUser: LazyPage{
source: "qrc:/qml/pages/JoinUser.qml"
}
property LazyPage search: LazyPage{
priority: high //load this after laoding main.qml
source: "qrc:/qml/pages/Search.qml"
}
}
main.qml
import "customs" as Custom
App
{
id: app
pages: Custom.Pages{}
}
Usage:
app.pushPage(app.pages.search)
###headers: Item
This property holds headers for all app pages
/Custom/Headers.qml
import QtQuick 2.5
import Gurra 1.0
Item {
property PageTitle home: PageTitle {
title: qsTr("Gurra")
onClose: app.popPage()
}
property PageTitle listings: PageTitle {
title: qsTr("Listings")
rightIcon: app.icons.fontAwesome.bars
onClose: app.popPage()
}
property PageTitle search: PageTitle {
title: qsTr("Search")
onClose: app.popPage()
}
property PageTitle contactUs: PageTitle {
title: qsTr("Contact Gurra")
onClose: app.popPage()
}
property PageTitle imageUploader: PageTitle {
title: qsTr("Images")
onClose: app.popPage()
}
property PageTitle about: PageTitle {
title: qsTr("About Mzadat")
onClose: app.popPage()
}
property PageTitle joinUser: PageTitle {
title: qsTr("Join Gurra")
onClose: app.popPage()
}
property PageTitle login: PageTitle {
title: qsTr("Login")
onClose: app.popPage()
}
}
main.qml
import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
/Pages/Search.qml
import Gurra 1.0
AnaPage
{
header: app.headers.search
}
See footers
###footers: Item
This property holds footer for all pages of the app
See headers
###Urls urls: This property holds all urls of the app
default: Urls{}
Example:
Image {
Layout.fillWidth: true
Layout.fillHeight: true
fillMode: Image.PreserveAspectFit
source = app.urls.pictures + image_id
}
###fonts: Fonts
default: Fonts{}
This property holds all app loaded fonts
Defining Custom fonts
/Custom/Fonts.qml
Fonts
{
property string digital: _digital.name
FontLoader
{
id: _digital
source: "qrc:/assets/fonts/DS-DIGI.TTF"
}
}
main.qml
import "customs" as Custom
App
{
id: app
fonts: Custom.Fonts{}
}
Usage
Label
{
text: qsTr("Volla!!")
font.pointSize: app.sizes.h5
color: app.colors.white
font.family: app.fonts.digital
}
###icons: Icons
default: Icons{}
This property holds all available app icons
###iconFonts: IconFonts
default: IconFonts{}
This property holds all available icon fonts. Icon fonts can be used to display icons for labels and buttons. Gurra provides all icon fonts availabe at https://icomoon.io/
Note: only fontAwesome and icomoon fonts are loaded by default, you can load other icon fonts easily.
Available fonts
primary: fontAwesome // default icon font
afiado
brankit
entipoPlus
feather
fontAwesome
hawcons
icomoon
linecons
material
meteocons
octicons
typicons
wpzoom
Loading other icon fonts
/Custom/Fonts.qml
IconFonts // inherit default icon fonts
{
meteocons: myloader.name // let meteocons refer to loaded font name
FontLoader
{
id: myloader
source: meteocons_file // meteocons_file is a IconFonts property and holds the path of the font file in Gurra's assets
}
}
// main.qml
import "customs" as Custom
App
{
id: app
iconFonts: Custom.IconFonts{}
}
Usage:
Icon
{
font.pointSize: app.sizes.h3
color: app.colors.foreground
font.family: app.iconFonts.meteocons
}
###colors: AppColors
default: AppColors{} This property all app colors available:
primary: black
background: grey
string foreground: grey
accent: "red"
primaryFont: "black"
secondaryFont: "black"
accentFont: "white"
// these to increase readability and avoid mistyping
white: "white"
black: "black"
cyan: "cyan"
darkCyan: "darkCyan"
red: "red"
darkRed: "darkRed"
magenta: "magenta"
darkMagenta: "darkMagenta"
green: "green"
darkGreen: "darkGreen"
yellow: "yellow"
darkYellow: "darkYellow"
orange: "orange"
darkOrange: "darkOrange"
blue: "blue"
darkBlue: "darkBlue"
grey: "grey"
darkGrey: "darkGrey"
lightGrey: "lightGrey"
transparent: "transparent"
Usage:
Text
{
id: _icon
font.pointSize: app.sizes.h6
color: app.colors.blue
}
Defining Custom Colors
/Custom/Colors.qml
import QtQuick 2.0
import Gurra 1.0
AppColors
{
primary: "#090050"
background: googlePalette.grey200
foreground: app.colors.black
accent: "#89beff"
}
main.qml
import "customs" as Custom
App
{
id: app
colors: Custom.Colors{}
}
###soundEffects: SoundEffects
default: undefined
This property holds app avialable sound effects
###margins: Margins
default: Margins{}
A convenient type that holds some margins sizes
Available sizes:
none: 0
xxSmall: 1
xSmall: 3
normal: 10
small: 5
medium: 15
large: 20
xLarge: 30
xxLarge: 40
xxxLarge: 50
Usage:
import QtQuick 2.0
Rectangle {
anchors.fill: parent
anchors.margins: app.margins.large // instead of hardcoding 20
color: app.colors.primary
}
###spacing: Spacing
default: Spacing{}
A convenient type that holds some spaces sizes
Available sizes:
none: 0
xxSmall: 1
xSmall: 3
normal: 10
small: 5
medium: 15
large: 20
xLarge: 30
xxLarge: 40
xxxLarge: 50
Usage:
Column
{
spacing: app.spacing.small
Label
{
text: "Hello Gurra!"
}
Row
{
height: app.sizes.xxLarge
spacing: app.spacing.large
IconLabel
{
spacing: app.spacing.xSmall
icon.icon: app.icons.fontAwesome.map_marker
icon.color: app.colors.background
icon.font.pointSize: app.sizes.h4
label.text: "IconLabel"
label.font.pointSize: app.sizes.h4
label.color: app.colors.primary
}
IconLabel
{
spacing: app.spacing.xSmall
icon.icon: app.icons.fontAwesome.clock_o
icon.color: app.colors.background
icon.font.pointSize: app.sizes.h4
label.text: "IconLabel"
label.font.pointSize: app.sizes.h5
label.color: app.colors.primary
}
}
}
###sizes: Sizes
default: Sizes{}
A convenient type that holds some sizes
Available sizes:
none: 0
xxSmall: 6
xSmall: 8
normal: 12
small: 10
medium: 14
large: 16
xLarge: 20
xxLarge: 24
xxxLarge: 28
h1: 28
h2: 24
h3: 18
h4: 14
h5: 12
h6: 10
h7: 8
h8: 6
Usage:
import QtQuick 2.0
import Gurra 1.0
Icon {
color: app.colors.accent
font.pointSize: app.sizes.h1
}
###settings: Settings
default: undefined
This property holds common app settings
###strings: Strings
default: Strings{} This property holds common used strings like Ok, Yes, No, Cancel and so on
Important: This property may be removed from the next release
###models: var
default: undefined
This property holds app available data models
/Custom/Models.qml
Item
{
property var yesNo: [qsTr("Yes"), qsTr("No")]
property var kmMile: [qsTr("KM"), qsTr("Mile")]
property var cities: ["Cairo", "Tokyo", "Paris", "New York"]
property var colors: [qsTr("Blue"), qsTr("White"), qsTr("Green"), qsTr("Yellow"), qsTr("Red"), qsTr("Orange"), qsTr("Black"), qsTr("Brown"), qsTr("Orange")]
} *main.qml*
import "customs" as Custom
App
{
id: app
models: Custom.Models{}
}
Usage:
app.pick(qsTr("Select City"), app.models.cities, function(index, city){
console.log("you selected", index, city)
})
###params: Params
default: Params{}
This property holds all dialog params available
Defining Custom Params
import QtQuick 2.0
import Gurra 1.0
Params
{
property DialogParams logout: DialogParams {
title: qsTr("Logout")
message: qsTr("Are you sure you want to logout?")
button1: qsTr("Yes")
button2: qsTr("No")
yesCallback: function(){
app.logic.logout()
app.replacePage([app.pages.home])
}
}
property DialogParams invalidEmail: DialogParams {
title: qsTr("Invalid")
message: qsTr("Please type a valid email.")
button1: qsTr("Ok")
}
property DialogParams deletePic: DialogParams {
title: qsTr("Delete?")
message: qsTr("Are you sure you want to delete your picture?")
button1: qsTr("Ok")
button2: qsTr("Cancel")
}
main.qml
import "customs" as Custom
App
{
id: app
params: Custom.Params{}
}
Usage:
app.confirm(app.params.deletePic, function(){
app.api.pics.remove(picture_id).then(function(){
app.done()
})
})
###layoutDirection: int
default: Qt.LeftToRight
This property holds the default layout direction of the app
###layoutMirroring: bool
default: false
This property holds whether layout mirroring is enabled or not
###childrenInherit: bool
default: false
This property holds whether items children should inherit layout mirroring is enabled or not
###confirmExit: bool
default: false
If true, App will confirm the user before exit
###view: StackView
default: undefined
This property holds the main StackView of the app. Gurra page routing currently supports StackView only
###restConsumer: RestConsumer2
default: RestConsumer2 {}
This property holds the central RESFful network consumer, all Gurra componets use this RestConsumer2 to connect to restful services to do GET, POST, PUT or DELETE operations
###restConsumer3: RestConsumer3
default: RestConsumer3 {} This property holds the central upload RESFful consumer, it's used by Uploader to upload files
#Functions
###ready(callback)
Loads Lazy
items and LazyPage
’s with high
priority. You should call this function after the main.qml
file has completely loaded. callback
is optional
Loading order:
Lazy
items withhigh
priorityLazy
items withlow
priorityLazyPage
items withhigh
priority
`LazyPage` items with `low` priority will be loaded by `app.pushPage()` before they get pushed onto `view`
Usage
// delay creating lazy items until all app Components are ready
Timer {
interval: 500
running: true
onTriggered: {
app.ready(function(){
//more startup code
})
}
}
Note: you shouldn’t call this function in main.qml Component.onCompleted because Component.onCompleted running order is undefined and can not be used here.
###pushPage (page)
Pushs a page onto view
, page can be normal AnaPage
, LazyPage
, or an arrays of pages (normal or lazy or mixed)
app.pushPage(app.pages.search)
If pushed page is LazyPage
and it is not loaded it will be loaded first before pushed on the view. All parameters found in LazyPage.params
will be passed to the loaded page
The loaded page will receive beforeEnter
and enter
signals before and after pushed on the view respectively .
###popPage (page)
Pops a page off view
, page can be normal AnaPage
, LazyPage
, or an arrays of pages (normal or lazy or mixed)
app.popPage(app.pages.search)
The popped off page will receive beforeLeave
and leave
signals before and after popped off the view respectively .
###replacePage (pages)
Replaces all pages in view
with pages
, pages
can be normal AnaPage
, LazyPage
, or an arrays of pages (normal or lazy or mixed)
app.replacePage([app.pages.search, app.pages.login])
The current page of view
will receive beforeLeave
and leave
signals before and after popped off the view respectively .
###back ()
Pops a page off view
. NobeforeLeave
nor leave
signals will be emited
###snack(message, action, actionCallback) Displays a Snackbar at the bottom of the app
app.snack(qsTr("Deleted message"), "UNDO", function(){
console.log("undoing...")
}) If `action` was provided `actionCallback` signal will be emited if users clicks on the action label
###inform(params, yesCallback, noCallback) Displays a popup to inform the user
if (app.settings.member_id === 0){
app.inform(app.params.loginFirst)
return
}
Note: if provided,
yesCallback
andnoCallback
will overrideparams.yesCallback
andparams.noCallback
###message(title, message, button, okCallback) Displays a popup to inform the user
app.message(qsTr("Error"), qsTr("Select at least one image."), function(){
console.log("will be called when popup is dismissed ")
})
###confirm(params, yesCallback, noCallback) Displays a confirmation dialog
/Custom/Params.qml
property DialogParams logout: DialogParams {
title: qsTr("Logout?")
message: qsTr("Are you sure you want to logout?")
button1: qsTr("Yes")
button2: qsTr("No")
yesCallback: function(){
app.logic.logout()
app.replacePage([app.pages.home])
}
}
//usage
app.confirm( app.params.logout )
Note: if provided,
yesCallback
andnoCallback
will overrideparams.yesCallback
andparams.noCallback
###confirm2(params, yesCallback, noCallback)
Displays a confirmation dialog, just like confirm
but params are a JavaScript object instead of DialogParams.
var params = {
title: qsTr("Delete image?"),
message: qsTr("Are you sure you want to delete this image?"),
button1: qsTr("Yes"),
button2: qsTr("No")
}
app.confirm2(params, function(){
app.api.images.remove(image_id).then(function(){
app.done()
},
function(){
app.inform(app.params.imageDeleteError)
})
})
Note: if provided,
yesCallback
andnoCallback
will overrideparams.yesCallback
andparams.noCallback
###done() Displays a popup to inform the user that an operation has been done
###loading(message)
Displays a loading popup with BusyIndicator item along with message
, message
is optional
app.loading()
###notLoading() Hides the loading popup
app.notLoading()
###input(params, yesCallback, noCallback) Displays an input dialog to allow user to enter data
Example:
//add this to /Custom/Params.qml
property DialogParams age: DialogParams {
title: qsTr("Enter you name")
message: qsTr("e.g. 60")
button1: qsTr("Ok")
button2: qsTr("Cancel")
}
// usage
app.input(app.params.age, function(value){
console.log("your age is", value)
}
Note: the
inputMethodHints
property of the text field is set toQt.ImhNone
###inputNumber(params, yesCallback, noCallback)
Same as input
with inputMethodHints
property set to Qt.ImhDigitsOnly
###inputDate(params, yesCallback, noCallback)
Same as input
with inputMethodHints
property set to Qt.imhDate
###inputTime(params, yesCallback, noCallback)
Same as input
with inputMethodHints property set to Qt.ImhTime
###inputPhone(params, yesCallback, noCallback)
Same as input
with inputMethodHints
property set to Qt.ImhDialableCharactersOnly
###inputEmail(params, yesCallback, noCallback)
Same as input
with inputMethodHints
property set to Qt.ImhEmailCharactersOnly
###inputMultiline(params, yesCallback, noCallback)
Same as input
with inputMethodHints
property set to Qt.ImhMultiLine
###inputUrl(params, yesCallback, noCallback)
Same as input
with inputMethodHints
property set to Qt.ImhUrlCharactersOnly
###pick(title, model, callback)
Displays a popup dialog to allow user to pick one item from model
app.pick(qsTr("Select City"), app.models.cities, function(index, city){
console.log("you selected", index, city)
})