Check out this quick tour to find the best demos and examples for you, and to see how the Felgo SDK can help you to develop your next app or game!
After installing the Felgo SDK, you can receive updates with the Maintenance Tool. The Maintenance Tool is located at the installation directory of your Felgo SDK and is called
MaintenanceTool
.
Run this application and select Update components
to check if any updates are available for the Felgo SDK.
You then see a list of packages for which an update is available. To update the packages, click Continue
and then Update
on the following screen. After all packages were downloaded and installed,
you can close the Maintenance Tool by clicking the Done
button.
Note: After you updated the SDK, you need to Clean your project so the updated Felgo version is used. To clean your project, open Qt Creator and select Clean Project
from the Build
menu. Afterwards you can run your project and the updated Felgo version is used.
With your Felgo signup, you get access to all Felgo updates for free. Some of the components are available exclusively for Felgo customers - to upgrade to a Felgo license click here.
Highlights Blog Post: Release 3.7.0: Bluetooth LE (Low Energy) with QML
Felgo 3.7.0 adds new QML APIs to use Bluetooth LE from QML in your Qt and Felgo apps. This gives you a convenient way to use Bluetooth LE to connect to IoT, wearables and other custom devices, directly from QML, without any C++ code.
Felgo 3.7.0 comes as a free update for all Felgo developers.
This update contains important migration hints for Felgo projects created with earlier versions of the Felgo SDK.
Theme.navigationTabBar
instead of Theme.tabBar
. You can find more information in the detailed list of changes below.Project-Info.plist
located in the ios
folder of your project, also if you do not use Bluetooth.
This will not be visible for your users, unless you actually use Bluetooth. Apple scans uploaded apps for their capabilities, and since the new APIs enable any Felgo app to make use of Bluetooth, it is required to add this
purpose string, also if not actively used.
<key>NSBluetoothPeripheralUsageDescription</key> <string>App would like to access Bluetooth.</string> <key>NSBluetoothAlwaysUsageDescription</key> <string>App would like to access Bluetooth.</string>
android:minSdkVersion="21"
and android:targetSdkVersion="29"
.If you make use of the Live Client Module in a new project on iOS, as described here, please create a folder
FelgoLive
in your project, download this Imports.qml file and paste it into this folder. This will ensure that Qt picks up all the Qt module imports
that the Live Client Module prepares. The result should look like this:
This allows you to easily communicate with IoT, wearables and other custom devices using Bluetooth. You can find more information and examples in the documentation Use Bluetooth Low Energy and in the release blog post.
Here is an example of how such a Bluetooth implementation could look like:
import Felgo 3.0 import QtQuick 2.0 App { NavigationStack { Page { title: qsTr("BLE Battery") Rectangle { anchors.centerIn: parent width: parent.width * 0.6 height: parent.height * 0.8 radius: dp(30) border.color: 'black' border.width: dp(5) Rectangle { anchors.bottom: parent.bottom width: parent.width height: parent.height * batteryCharacteristic.value / 100 color: batteryCharacteristic.value > 80 ? 'green' : (batteryCharacteristic.value > 30 ? 'orange' : 'red') radius: parent.radius } } AppText { anchors.centerIn: parent text: batteryCharacteristic.value + '%' fontSize: dp(15) } } } BluetoothLeManager { discoveryRunning: true BluetoothLeDevice{ id: myBleDevice BluetoothLeService { uuid: 0x180F // Battery Service BluetoothLeCharacteristic { id: batteryCharacteristic uuid: 0x2A19 // Battery Characteristic dataFormat: 4 // 0x04 for uint8 onValueChanged: { // Value updates console.log('Battery Level Changed', value) } onValidChanged: { // Read initial value once characteristic is valid if (valid) { read() } } } } onConnectedChanged: { // Reconnect logic if (!connected) { console.log('Trying to reconnect') connect() } } } onDeviceDiscovered: { // Match device with service UUID if (device.services.indexOf('{0000180f-0000-1000-8000-00805f9b34fb}') > -1) { myBleDevice.setDevice(device, true) discoveryRunning = false } } } }
iOS | Android |
---|---|
|
|
This extensive example shows how to create various different common list item layouts using the AppListItem component.
import QtQuick 2.8 import QtQuick.Controls 2.2 as QC2 import Felgo 3.0 App { id: app NavigationStack { Page { title: "Custom AppListItem" backgroundColor: Theme.colors.secondaryBackgroundColor AppFlickable { anchors.fill: parent contentHeight: column.height Column { id: column width: parent.width bottomPadding: 2*dp(Theme.contentPadding) SimpleSection { title: "Standard Items" } AppListItem { text: "First" rightText: "Longer rightText, really long" } AppListItem { text: "Second with longer text" rightText: "Hi" } AppListItem { text: "An active item" detailText: "This is disabled so it cannot be clicked" active: true enabled: false lastInSection: true } SimpleSection { title: "Images" } AppListItem { text: "Using an image" image: "https://via.placeholder.com/300" } AppListItem { text: "Muted with image" image: "https://via.placeholder.com/300" muted: true } AppListItem { text: "Image with" detailText: "some detailText" image: "https://via.placeholder.com/300" lastInSection: true } SimpleSection { title: "Custom Items" } AppListItem { text: "Oh look, an icon" rightText: "Nice!" showDisclosure: false leftItem: Icon { icon: IconType.heart anchors.verticalCenter: parent.verticalCenter width: dp(26) } } AppListItem { text: "Wi-Fi" rightText: "Connected" leftItem: Rectangle { color: Theme.colors.tintColor radius: dp(5) width: dp(26) height: width anchors.verticalCenter: parent.verticalCenter Icon { icon: IconType.wifi anchors.centerIn: parent color: "white" } } } AppListItem { text: "General" leftItem: Rectangle { color: "grey" radius: dp(5) width: dp(26) height: width anchors.verticalCenter: parent.verticalCenter Icon { icon: IconType.cog anchors.centerIn: parent color: "white" } } rightItem: Rectangle { color: "red" radius: width/2 width: dp(22) height: width anchors.verticalCenter: parent.verticalCenter AppText { anchors.centerIn: parent color: "white" text: "1" } } } AppListItem { text: "Some Wifi Name" showDisclosure: false leftItem: Icon { icon: IconType.check color: Theme.colors.tintColor width: dp(26) anchors.verticalCenter: parent.verticalCenter } rightItem: Row { spacing: dp(5) anchors.verticalCenter: parent.verticalCenter Icon { icon: IconType.lock width: sp(26) height: width anchors.verticalCenter: parent.verticalCenter } Icon { icon: IconType.wifi width: sp(26) height: width anchors.verticalCenter: parent.verticalCenter } IconButton { icon: IconType.info width: sp(26) height: width size: dp(22) anchors.verticalCenter: parent.verticalCenter } } } AppListItem { id: listItem showDisclosure: false mouseArea.enabled: false topPadding: 0 bottomPadding: 0 leftItem: Icon { icon: IconType.moono width: sp(26) height: width anchors.verticalCenter: parent.verticalCenter } textItem: AppSlider { height: dp(45) width: listItem.textItemAvailableWidth value: 0.3 } rightItem: Icon { icon: IconType.suno width: sp(26) height: width anchors.verticalCenter: parent.verticalCenter } } AppListItem { text: "Custom detailText item" image: "https://via.placeholder.com/300" textVerticalSpacing: dp(10) lastInSection: true detailTextItem: Row { spacing: dp(10) Icon { icon: IconType.heart } Icon { icon: IconType.paperplane } Icon { icon: IconType.automobile } } } SimpleSection { title: "Switches" } AppListItem { text: "This is a switch" showDisclosure: false mouseArea.enabled: false rightItem: AppSwitch { anchors.verticalCenter: parent.verticalCenter checked: true } } AppListItem { text: "Whole item toggles switch" detailText: "Switch checked: " + innerSwitch.checked showDisclosure: false rightItem: AppSwitch { id: innerSwitch anchors.verticalCenter: parent.verticalCenter enabled: false } onSelected: { innerSwitch.toggle() } } AppListItem { text: "A muted item" muted: true showDisclosure: false lastInSection: true rightItem: AppSwitch { anchors.verticalCenter: parent.verticalCenter } } SimpleSection { title: "Radio Button Selected: " + ratioButtonGroup.checkedButton.value } QC2.ButtonGroup { id: ratioButtonGroup buttons: [radio1, radio2, radio3] } AppListItem { text: "First Option" showDisclosure: false leftItem: AppRadio { id: radio1 checked: true value: "Option 1" anchors.verticalCenter: parent.verticalCenter } onSelected: { if(!radio1.checked) radio1.toggle() } } AppListItem { text: "Second Option" showDisclosure: false leftItem: AppRadio { id: radio2 value: "Option 2" anchors.verticalCenter: parent.verticalCenter } onSelected: { if(!radio2.checked) radio2.toggle() } } AppListItem { text: "Third Option" showDisclosure: false lastInSection: true leftItem: AppRadio { id: radio3 value: "Option 3" anchors.verticalCenter: parent.verticalCenter } onSelected: { if(!radio3.checked) radio3.toggle() } } SimpleSection { title: "Checkboxes" } AppListItem { text: "First Option" showDisclosure: false rightItem: AppCheckBox { id: checkBox1 anchors.verticalCenter: parent.verticalCenter } onSelected: { checkBox1.checked = !checkBox1.checked } } AppListItem { text: "Second Option" showDisclosure: false rightItem: AppCheckBox { id: checkBox2 checked: true anchors.verticalCenter: parent.verticalCenter } onSelected: { checkBox2.checked = !checkBox2.checked } } AppListItem { text: "Third Option" showDisclosure: false lastInSection: true rightItem: AppCheckBox { id: checkBox3 anchors.verticalCenter: parent.verticalCenter } onSelected: { checkBox3.checked = !checkBox3.checked } } } } } } }
This plugin offers you 2 new components AppleSignIn and AppleSignInButton to handle signing in with an Apple ID. Here is an example usage:
import QtQuick 2.0 import Felgo 3.0 App { NavigationStack { Page { title: "Apple Sign In" Column { anchors.centerIn: parent spacing: dp(15) AppleSignInButton { id: appleSignInButton anchors.horizontalCenter: parent.horizontalCenter } AppText { anchors.horizontalCenter: parent.horizontalCenter text: !appleSignInButton.enabled ? "Apple Sign-in unavailable." : appleSignInButton.appleSignIn.isLoggedIn ? "Signed in: " + appleSignInButton.appleSignIn.userName : "Click above to sign in with Apple user" } } } } }
import Felgo 3.0 import QtQuick 2.0 App { AppButton { text: "Store in Keychain" onClicked: nativeUtils.setKeychainValue("identifier", "value") } AppButton { text: "Read Keychain" onClicked: nativeUtils.getKeychainValue("identifier") } AppButton { text: "Delete from Keychain" onClicked: nativeUtils.clearKeychainValue("identifier") } }
Here is an example:
import QtQuick 2.3 import Felgo 3.0 App { Navigation { // Use tabs on Android, else default (which is tabs on iOS and drawer on desktop) navigationMode: Theme.isAndroid ? navigationModeTabs : navigationModeDefault // On Android, only the selected label is shown by default. You can change that by accessing the internal tabs or using the theming //tabs.showOnlySelectedLabel: false // can also be changed with Theme.navigationTabBar.showOnlySelectedLabel NavigationItem { title: "First" icon: IconType.heart NavigationStack { Page { title: "First Page" } } } NavigationItem { title: "Second" icon: IconType.book NavigationStack { Page { title: "Second Page" } } } NavigationItem { title: "Third" icon: IconType.bolt NavigationStack { Page { title: "Third Page" } } } } }
The new bottom tab navigation replaces the top tab navigation if used with the Navigation component. You can still create the top tabs (also known as "segments") using the AppTabBar component.
You can change the theming values of the bottom tab navigation on all platforms using the new Theme.navigationTabBar
. Note that this was previously done using Theme.tabBar
, you can find details
about this theming change in the list of improvements below.
Here is an example of how to use the new control, and how it can be combined with the new AppListItem for a native UI/UX:
import QtQuick 2.8 import QtQuick.Controls 2.3 as QC2 import Felgo 3.0 App { NavigationStack { Page { title: "AppRadio" backgroundColor: Theme.secondaryBackgroundColor Column { width: parent.width SimpleSection { title: "As list items: " + ratioButtonGroup1.checkedButton.value + " selected" } QC2.ButtonGroup { id: ratioButtonGroup1 buttons: [radio1, radio2, radio3] } AppListItem { text: "First Option" showDisclosure: false leftItem: AppRadio { id: radio1 checked: true value: "Option 1" anchors.verticalCenter: parent.verticalCenter } onSelected: { if(!radio1.checked) radio1.toggle() } } AppListItem { text: "Second Option" showDisclosure: false leftItem: AppRadio { id: radio2 value: "Option 2" anchors.verticalCenter: parent.verticalCenter } onSelected: { if(!radio2.checked) radio2.toggle() } } AppListItem { text: "Third Option" showDisclosure: false lastInSection: true leftItem: AppRadio { id: radio3 value: "Option 3" anchors.verticalCenter: parent.verticalCenter } onSelected: { if(!radio3.checked) radio3.toggle() } } SimpleSection { title: "Inline: " + ratioButtonGroup2.checkedButton.value + " selected" } QC2.ButtonGroup { id: ratioButtonGroup2 buttons: [radio4, radio5] } Rectangle { width: parent.width height: contentCol.height Column { id: contentCol width: parent.width padding: dp(Theme.contentPadding) AppRadio { id: radio4 value: "Option 1" text: "First Option" checked: true } AppRadio { id: radio5 value: "Option 2" text: "Second Option" } } } } } } }
import QtQuick 2.8 import Felgo 3.0 App { NavigationStack { Page { title: "AppButton" Column { width: parent.width AppButton { text: "Icon" flat: false icon: IconType.heart } AppButton { text: "Left Icon" flat: false iconLeft: IconType.heart } AppButton { text: "Right Icon" flat: false iconRight: IconType.heart } AppButton { id: customButton text: "Custom left item" flat: false leftItem: Rectangle { width: dp(15) height: width rotation: 45 color: "green" // Handling the pressed state on iOS in the custom item opacity: Theme.isIos && customButton.pressed ? 0.5 : 1 } } AppButton { text: "Full width" flat: false width: parent.width iconRight: IconType.heart } AppButton { text: "Circle" flat: false icon: IconType.heart height: width radius: width/2 } } } } }
Theme.tabBar
. This resulted in potential issues when using both controls at the same time, but trying to apply different theming. With
the introduction of a new style for a bottom tab navigation on Android (see detailed change above), we also split up the themes properly. You can now use Theme.navigationTabBar
to style your bottom tab navigation
and Theme.tabBar
to style general tabs.
For migrating existing projects that already apply theming to the bottom navigation using Theme.tabBar
, simply replacing it with Theme.navigationTabBar
should be sufficient.
import Felgo 3.0 App { onInitTheme: { // Replace tabBar with navigationTabBar to style the bottom tab navigation //Theme.tabBar.titleColor = "red" Theme.navigationTabBar.titleColor = "red" } }
import QtQuick 2.8 import Felgo 3.0 App { NavigationStack { Page { title: "Pull to refresh" rightBarItem: ActivityIndicatorBarItem { visible: refreshSimulator.running } Timer { id: refreshSimulator interval: 1500 } AppFlickable { id: flickable anchors.fill: parent contentWidth: width contentHeight: column.height Column { id: column width: parent.width Repeater { model: 30 AppListItem { text: "Item " + index } } } PullToRefreshHandler { listView: flickable onRefresh: { refreshSimulator.restart() } } } } } }
This includes:
Highlights Blog Post: Release 3.6.0: Modal Dialog and iOS Storyboard Support for Qt & Felgo
Felgo 3.6.0 adds the new AppModal component to display modal dialogs in your apps. You can use this component for both full-screen and custom-height modal dialogs. On iOS, you can now use Storyboard files to create your app launch screen. This update also adds new components and several improvements and fixes.
Felgo 3.6.0 comes as a free update for all Felgo developers.
This update contains important migration hints for Felgo projects created with earlier versions of the Felgo SDK.
iOS | Android |
---|---|
|
|
Newly created projects already contain an empty launch screen file. You can change the launch screen using Xcode:
<build-folder>/<project>.xcodeproj
in Xcode.Launch Screen.storyboard
under Bundle Data.
You can add any default UI elements to the launch screen Storyboard.
You can also migrate existing Felgo projects to use the new launch screen Storyboard:
ios/Launch Screen.storyboard
to your existing project's <project>/ios
directory.<project>/ios/Assets.xcassets/LaunchImage.launchimage
.<project>/ios/Project-Info.plist
, inside the <dict>
tag:
<key>UILaunchStoryboardName</key> <string>Launch Screen</string>
Note: For existing apps, make sure to add and update all the required frameworks listed in Integration Guide.
Note: This new version requires new integration steps.
GoogleMobileAds
, GoogleAppMeasurement
, GoogleUtilities
, nanopb
and FBLPromises
from PluginDemo/ios
to your
project/ios
directory.ios/Project-Info.plist
:
<key>GADApplicationIdentifier</key> <string>ca-app-pub-(your-app-id)</string>
For more information, see the Integration Guide.
Note: For existing apps, make sure to add and update all the required frameworks listed in Integration Guide.
This update also requires additional migration steps for this plugin:
Add the following repository to the allprojects -> repositories
node:
maven { url "https://chartboostmobile.bintray.com/Chartboost" }
Add the following code as child of the android
node, before the defaultConfig
node:
compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 }
Highlights Blog Post: Release 3.5.0: Run your Qt and Felgo Apps in the Browser with WebAssembly (WASM)
Felgo 3.5.0 adds support for WebAssembly (WASM) as a new export platform. This allows you to use Felgo and Qt to build applications that also run in the browser, served over the web. With this update you get access to a new target platform, with the same source code and skills you already used to develop mobile, desktop and embedded apps with Felgo and Qt.
Felgo 3.5.0 comes as a free update for all Felgo developers.
With Felgo for WebAssembly, you get an improved version of the Qt WASM port, with several fixes and additional features. You can find a detailed list of the improvements, and much more information about WASM, in the release blog post. You can also use Felgo for WebAssembly with plain Qt applications, that do not include any Felgo components, to benefit from the improvements.
import Felgo 3.0 import QtQuick 2.0 App { id: app Page { // ... UI items go here ... } // Simply place the FpsMeter on top of other UI elements, no additional // configuration is required as all properties are set to sensible defaults. FpsMeter { } }
Note that the Amplitude plugin will now also send events during development on desktop by default. If that is not desired, make sure to remove the apiKey
during development, or e.g. check if
system.publishBuild
is set.
"on"
-Syntax. You can add Property Value Sources like PropertyAnimation on x
and Property Value Interceptors like
Behavior on x
at runtime using Hot Reloading.
Highlights Blog Post: Release 3.4.0: QML Hot Reload with Felgo Live
Felgo 3.4.0 adds hot reloading for QML. This is a major improvement of live reloading, further speeding up development speed with Felgo and Qt.
Felgo 3.4.0 comes as a free update for all Felgo developers.
Hot Reload with Felgo Live allows you to change your QML & JavaScript source code and view the result in realtime. It applies QML, JavaScript and asset changes instantly on every connected device, immediately after saving. This reduces the long waiting times for build and deployment steps to only a couple of seconds.
Hot Reload applies changes in your source code without losing the state of your application. If you are currently working on a sub page, you will not have to navigate back to it after every change, you will stay exactly where you are in your app.
Learn more in the official docs here.
v5.13.0
on iOS.
Deprecated API Usage
warning for UIWebView when uploading an app to the Apple Store.requestTags
method.
Highlights Blog Post: Release 3.3.0: Update to Qt 5.13.2 and Qt Creator 4.10.2, Jira Tima App Demo
Felgo 3.3.0 adds support for Qt 5.13.2 and Qt Creator 4.10.2, which brings many features and improvements. This update also adds many new APIs, improvements and fixes to the Felgo components.
Felgo 3.3.0 comes as a free update for all Felgo developers.
android:minSdkVersion="21"
and
android:targetSdkVersion="28"
.If you plan to target devices running Android 5, please download this file and overwrite the existing file in <Path to Felgo
installation>\Felgo\android_armv7\mkspecs\features\
, as well as <Path to Felgo installation>\Felgo\android_arm64_v8a\mkspecs\features\
. Also rename the following files in both <Path to
Felgo installation>\Felgo\android_armv7\lib\
and <Path to Felgo installation>\Felgo\android_arm64_v8a\lib\
:
If you use the OneSignal plugin requestTags
method, please replace your maven import URL in the build.gradle
file, located in the android
folder of
your project directory, so it looks like this:
maven { url 'https://sdk.v-play.net/maven-internal/' }
With Felgo 3.3.0, you need an additional line in your *.pro file, to use the Facebook plugin with iOS. The integration will look like this:
FELGO_PLUGINS += facebook ios { LIBS += -framework Accelerate }
You can find more information in the plugin integration guide.
This demo shows best practices for UI design with a shared code-base across Android, iOS and desktop. It works with dummy data based on the Jira time tracking software. It uses several of the latest APIs released with Felgo 3.3.0.
It is based on the official Jira Tima mobile app developed by Felgo.
iOS | Android | Desktop |
---|---|---|
|
|
|
import QtQuick 2.0 import Felgo 3.0 App { onInitTheme: { // You can add custom styles for dialogs now //Theme.dialog.backgroundColor = "yellow" dialog.open() } NavigationStack { Page { title: "Dialog" } } Dialog { id: dialog title: "Do you think this is awesome?" autoSize: true positiveActionLabel: "Yes" negativeActionLabel: "No" onCanceled: title = "Think again!" onAccepted: close() // You can use Theme.dialog.defaultContentPadding to align your // custom content with the rest of the dialog UI. AppText { padding: dp(Theme.dialog.defaultContentPadding) wrapMode: Text.WordWrap width: parent.width text: "This is a very long sentence to get some line breaks in this content!" // Colors and alignment are platform depending for the best appearance color: Theme.isIos ? Theme.colors.textColor : Theme.colors.secondaryTextColor horizontalAlignment: Theme.isIos ? Text.AlignHCenter : Text.AlignLeft } } }
You can now also access the title item with Dialog::titleItem alias as well as manually set Dialog::titleDividerVisible.
import QtQuick 2.0 import Felgo 3.0 App { NavigationStack { Page { title: "AppTextField::inputMode" AppTextField { width: parent.width inputMode: inputModeEmail } } } }
You can find details on other new properties like AppTextField::passwordVisible and AppTextField::showPasswordVisibleButton in the associated documentation.
Note: This also applies to SearchBar which uses an AppTextField internally.
import QtQuick 2.0 import Felgo 3.0 App { NavigationStack { Page { title: "AppTextField::clickEnabled" AppTextField { id: textField width: parent.width placeholderText: "Select date" clickEnabled: true onClicked: { nativeUtils.displayDatePicker() } Connections { target: nativeUtils onDatePickerFinished: { if(accepted) textField.text = date } } } } } }
import QtQuick 2.0 import Felgo 3.0 App { NavigationStack { Page { title: "TextFieldRow" Column { id: column width: parent.width TextFieldRow { width: parent.width label: "Text" placeHolder: "Add some text" } TextFieldRow { id: dateRow width: parent.width label: "Date" placeHolder: "Select date" clickEnabled: true onClicked: { nativeUtils.displayDatePicker() } Connections { target: nativeUtils onDatePickerFinished: { if(accepted) dateRow.value = date } } } } } } }
Note: This property must be used with dp()
.
The item uses the following paddings:
anchors.leftMargin: nativeUtils.safeAreaInsets.left + dp(Theme.contentPadding) anchors.rightMargin: nativeUtils.safeAreaInsets.right + dp(Theme.contentPadding) anchors.topMargin: nativeUtils.safeAreaInsets.top + dp(Theme.contentPadding) anchors.bottomMargin: nativeUtils.safeAreaInsets.bottom
You can anchor to it or just use its properties like margins or width for your layouts.
import QtQuick 2.0 import Felgo 3.0 App { NavigationStack { Page { id: page title: "Page::contentPaddingAnchorItem" Column { id: column spacing: dp(Theme.contentPadding) anchors.fill: parent.contentPaddingAnchorItem AppText { width: parent.width text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." } // Toggle the padding with this button AppButton { text: "Toggle padding" horizontalMargin: 0 property bool toggle: true onClicked: { column.anchors.fill = toggle ? column.parent : column.parent.contentPaddingAnchorItem toggle = !toggle } } } } } }
Additionally you can display the drawer in a minified sidebar version containing only icons, with Navigation::drawerMinifyEnabled.
import QtQuick 2.0 import Felgo 3.0 App { Navigation { id: navigation NavigationItem { title: "Item1" icon: IconType.heart NavigationStack { Page { title: "Page1" Column { anchors.centerIn: parent spacing: dp(15) Row { AppText { text: "drawerInline " } AppSwitch { checked: navigation.drawerInline updateChecked: false onToggled: navigation.drawerInline = !navigation.drawerInline } } Row { AppText { text: "drawerFixed " } AppSwitch { checked: navigation.drawerFixed updateChecked: false onToggled: navigation.drawerFixed = !navigation.drawerFixed } } Row { AppText { text: "drawerMinifyEnabled " } AppSwitch { checked: navigation.drawerMinifyEnabled updateChecked: false onToggled: navigation.drawerMinifyEnabled = !navigation.drawerMinifyEnabled } } } } } } NavigationItem { title: "Item2" icon: IconType.star NavigationStack { Page { title: "Page2" } } } } }
App { onInitTheme: Theme.colors.statusBarStyle = Theme.colors.statusBarStyleSystem }
Note: For this to work on Android, add the following line to android/res/xml/file_paths.xml
:
<files-path name="files" path="."/>
build.gradle
file if you use Cloud Builds to distribute a 64-bit Android app. For that, have a look at the Android Integration Steps on how to set the new abiFilters
definition.
Highlights Blog Post: Release 3.2.0: Update to Qt 5.12.3 with ECMAScript 7, Image Picker and Qt Creator 4.8.2
Felgo 3.2.0 adds support for Qt 5.12.3 and Qt Creator 4.8.2, which brings many features and improvements. The new long term supported Qt release includes lots of fixes, new modules and adds JavaScript support for ECMAScript 7. The updated Felgo IDE Qt Creator version 4.8.2 is more stable and adds compatibility with the latest toolchains and platforms.
Felgo 3.2.0 comes as a free update for all Felgo developers.
This update contains important migration hints for Felgo projects created with earlier versions of the Felgo SDK.
Please see the Android deployment guide if you are not sure how to install and use the new NDK.
We also recommend to delete the old shadow build folders and perform a clean/qmake of your project, to avoid Android build caching issues. You can find the shadow build folder path in the Projects
tab of Qt
Creator.
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el
, please update your gradle version to
com.android.tools.build:gradle:3.2.1
. You can find this version if you open android/build.gradle
in your project folder. You can find more info in the Gradle Build
System guide.
libSoomlaiOSStore.a
libKeeva.a
libcrypto.a
libssl.a
AppleIncRootCertificate.cer
Qt 5.12.3 is the third patch version for Qt 5.12 LTS, which is a long-term-supported release. It incorporates more than 2000 bugs fixes since the previous Qt LTS version, Qt 5.9.7. On top of Qt 5.12.3, the new LTS version will receive many patch releases throughout the coming years. The latest Qt 3D Studio version is based on Qt 5.12 LTS as well.
QML performance and memory consumption improved a lot over the previous Qt versions. Memory usage with Qt 5.12 is 30% lower than with Qt 5.9, the previous LTS version. Qt focuses a lot on improving the QML engine performance, you can read more about Qt 5.12 performance improvements here.
With the new release, you can also take advantage of major improvements to the JavaScript engine that supports QML. Previously compatible with ECMAScript 5, it now fully supports ECMAScript 7. This allows the usage of modern JavaScript and simplifies the integration of Javascript libraries. ECMAScript modules are now also supported and can be loaded both from C++ as well as QML/JS.
Along with the Qt 5.12.3 update, Felgo 3.2.0 also presents you with Qt Creator 4.8.2. The new IDE version is more stable and adds support for the latest build tools and platforms.
On iOS, the IDE now better detects later iPhone models like the iPhone XS. The update also includes many improvements and fixes for macOS Mojave.
For Android, you can now connect and use the debugger on API level 24 and later. The new Qt Creator is also fully compatible with Android SDK 28.
Note: The Android Build Kit now uses the Clang compiler instead of GCC, which got removed with NDK r18b. Thus, older NDK versions are no longer supported and we recommend to upgrade to NDK r19c. You can download it here.
Make sure to configure the new NDK in the Qt Creator settings for Android:
Before you can build projects, we also recommend to clean previous build folders and project settings:
Qt 5.12 and Qt Creator 4.8 also add basic support for the Android ARMv8 architecture. However, there are no pre-built libraries for this architecture with Felgo 3.2.0 yet. If you require early access to Felgo Android ARMv8 support, don’t hesitate to get in touch.
On Windows, Qt Creator does no longer force the use of ANGLE for OpenGL on user applications. You can also expect less issues with antivirus programs on Windows systems. Read more about the bigger improvements of Qt Creator 4.8 in the official release post.
You can now set your Felgo license key as configuration variable from your project file. The Felgo project configuration now supports the PRODUCT_LICENSE_KEY
settings:
CONFIG += felgo # Optionally set a license key that is used instead of the license key from # main.qml file (App::licenseKey for your app or GameWindow::licenseKey for your game) PRODUCT_LICENSE_KEY = ""
New projects created with the Qt Creator wizards use this setup by default. If you want to update your existing project, add the following line of code to your main.cpp
file right below the
felgo.initialize()
method:
// Set an optional license key from project file // This does not work if using Felgo Live, only for Felgo Cloud Builds and local builds felgo.setLicenseKey(PRODUCT_LICENSE_KEY);
Setting the license key from within the project file with PRODUCT_LICENSE_KEY
requires you to do a full rebuild (clean) of your project.
Note: Setting the license key with PRODUCT_LICENSE_KEY
is not possible if using the Felgo Live Client. Felgo Live Client still picks up the license key set with App::licenseKey for your app or GameWindow::licenseKey for your game.
For more information, have a look at our publishing guide section about the license key.
The in-app purchase plugin now supports subscriptions for iOS and Android apps. Today, subscriptions are the best way to monetize your app, offering recurring revenue from your users. Also Apple and Google only take a 15% share on subscriptions after 1 year, compared to the 30% share for regular in-app purchases, so that is another plus!
If you want to use subscriptions or the built-in virtual economy system, we recommend using the Felgo in-app purchase plugin instead of the default Qt Purchasing module.
Note: With this update, you need to add additional files for iOS, if you use the in-app purchase plugin. Please check out the integration guide to see where you can find those files.
libSoomlaiOSStore.a
libKeeva.a
libcrypto.a
libssl.a
AppleIncRootCertificate.cer
import Felgo 3.0 import QtQuick 2.0 App { NavigationStack { Page { id: page title: qsTr("Choose Photos") // right bar item to accept selection rightBarItem: TextButtonBarItem { text: "Next" enabled: imagePicker.selectedCount > 0 // your app will probably pop the photo selection page from the stack to move on // this example only logs the selected photos onClicked: console.debug("SELECTED:", JSON.stringify(imagePicker.selection)) } // image picker view for photo selection ImagePicker { id: imagePicker anchors.fill: parent } } } }
You can also build your own UI for picking photos. Call NativeUtils::fetchGalleryPhotos() to load a list of all device photos, which your view can then access with the NativeUtils::galleryPhotos property. To further work with individual images, use NativeUtils::getCachedAssetPath().
The update to Qt 5.12.3 adds several more new features. You can now use the TableView as another type of Item View in Qt Quick. It is similar to a ListView but with multiple columns. Unlike the previous implementation of QtQuick Controls 1, it does not do any styling. The TableView provides the optimal solution for instantiating, pooling and reusing delegates on demand as you scroll the table. A TableModel for the view can be created with a custom C++ QAbstractTableModel implementation.
Also, various controls in Qt Quick Controls 2 gained new methods or new functionalities.
The Pointer Handlers of Qt 5.11 are now renamed to Input Handlers and are fully supported as a first-class feature in Qt Quick. The Input Handlers simplify the creation of complex touch interactions, that used to be difficult to do with MouseArea and TouchArea alone. They can detect events even in cases of deep nesting.
This also applies for the TapHandler, which can detect taps and touch gestures. Unlike MouseArea, it can handle events in multiple nested Items at the same time:
import QtQuick 2.12 import Felgo 3.0 App { NavigationStack { Page { title: "Nested Touch Example" // Outer Rectangle Rectangle { anchors.centerIn: parent id: outerRect width: dp(200) height: dp(200) color: tapHandler.pressed ? "lightyellow" : "lightgreen" TapHandler { id: tapHandler } // Inner Rectangle Rectangle { id: innerRect anchors.centerIn: parent width: dp(75) height: dp(75) color: tapHandler2.pressed ? "lightblue" : "orange" TapHandler { id: tapHandler2 } } } } } }
It is also easy to make an Item draggable with the DragHandler.
import QtQuick 2.12 import Felgo 3.0 App { NavigationStack { Page { title: "Drag Example" // Draggable Rectangle Rectangle { // initial position x: (parent.width - width) / 2 y: (parent.height - height) / 2 width: dp(200) height: dp(100) color: dragHandler.active ? "lightyellow" : "lightgreen" AppText { id: text text: "Drag Me!" anchors.centerIn: parent } DragHandler { id: dragHandler } } } } }
HoverHandler was added as a new type of handler for detecting mouse hover. As touchscreens generally do not offer hover events, in practice it detects a hovering mouse or tablet stylus.
As a new tech preview, you can have a look at the DelegateChooser type. It allows to use different delegates in item views like AppListView. Depending on role values from the model or the index, you can choose between multiple delegates:
import QtQuick 2.12 import Felgo 3.0 import Qt.labs.qmlmodels 1.0 // tech preview import App { NavigationStack { Page { title: "Multiple Delegates" AppListView { anchors.fill: parent model: [ { text: "Apple", detailText: "A delicious fruit with round shape", type: "fruit" }, { text: "Beer", type: "drink" }, { text: "Orange", detailText: "Another fruit with round shape", type: "fruit" }, { text: "Wine", type: "drink" } ] delegate: DelegateChooser { role: "type" DelegateChoice { roleValue: "fruit" // Delegate for "fruit" type SimpleRow { onSelected: text = "Clicked" } } DelegateChoice { roleValue: "drink" // Delegate for "drink" type Rectangle { width: parent.width height: dp(50) color: Theme.tintColor AppText { x: dp(16) anchors.verticalCenter: parent.verticalCenter text: modelData.text color: "white" } } } } } } } }
There are many more additions you get with Qt 5.12.3, for example:
Also note that the following modules are part of the Qt 5.12 release, but are deprecated and considered for removal in subsequent releases of Qt:
You can also have a look at the official Qt 5.12 blog post or see the full list of changes here.
Highlights Blog Post: Release 3.1.0: New Felgo Plugins Version, Unified App Configuration and FlickablePage
Felgo 3.1.0 introduces a new base version for Felgo Plugins and simplifies maintenance with a unified app configuration for Desktop, iOS and Android.
Felgo 3.1.0 comes as a free update for all Felgo developers.
To match the new Felgo SDK version 3, the version for Felgo Plugins now also increased to 3. This version change is relevant when building your project for the Android platform. You will notice that the configured plugin
dependencies in the android/build.gradle
of your project are no longer supported.
To correctly integrate the latest Felgo Plugins in your project, please update the build.gradle
configuration to use version 3 of the plugins. For example: To use the AdMob
Plugin on Android add
implementation 'net.vplay.plugins:plugin-admob:3.+'
instead of
implementation 'net.vplay.plugins:plugin-admob:2.+'
to the dependencies block of your build.gradle
. Note that the version setting at the end of the line changed to 3.+
. The same pattern applies to all other plugin integrations. You can also see
the updated integration guide in the Felgo Plugins Documentation.
With this change the Android configuration of your app is correctly set up to use the latest version of Felgo Plugins.
The PRODUCT_IDENTIFIER
, PRODUCT_VERSION_CODE
and PRODUCT_VERSION_NAME
project settings are now fully supported on iOS, Android and Desktop.
The app identifier and version of your app usually requires to be specified at many different places. For example at the qml/config.json
on Desktop, or the AndroidManifest.xml
or
Project-Info.plist
for mobile platforms.
With this release, you can specify the relevant values with a single configuration for all platforms. The Felgo project configuration now supports the PRODUCT_IDENTIFIER
, PRODUCT_VERSION_CODE
and PRODUCT_VERSION_NAME
settings:
CONFIG += felgo # configure the identifier and version information PRODUCT_IDENTIFIER = net.felgo.demos.FelgoProject PRODUCT_VERSION_NAME = 1.0.0 PRODUCT_VERSION_CODE = 1
New projects created with the Qt Creator wizards use this setup by default. If you want to update your existing projects to this system, also add the relevant placeholders to your Project-Info.plist
:
<key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleShortVersionString</key> <string>${PRODUCT_VERSION_NAME}</string> <key>CFBundleVersion</key> <string>${PRODUCT_VERSION_CODE}</string>
Otherwise, the project variables are not used on iOS. For Android, you can modify your build.gradle
configuration to also use the specified project settings:
android { defaultConfig { applicationId = productIdentifier versionCode = productVersionCode.toInteger() versionName = productVersionName } }
For Desktop platforms no additional steps are required. Each time you run qmake for your project, the values are updated with the latest configuration on all platforms.
Many app pages with custom content require an AppFlickable to make the content scrollable. To reduce boilerplate code, you can now use the new FlickablePage, which already contains a pre-configured AppFlickable and ScrollIndicator:
import Felgo 3.0 import QtQuick 2.0 App { NavigationStack { FlickablePage { title: "Flickable Page" // set contentHeight of flickable to allow scrolling if the content is bigger than the page height flickable.contentHeight: column.height // set false to hide the scroll indicator, it is visible by default scrollIndicator.visible: true // page content Column { id: column width: parent.width // fill column with 100 AppText items using Repeater Repeater { model: 100 delegate: Rectangle { width: parent.width height: dp(50) AppText { anchors.centerIn: parent text: qsTr("Item") + " " + index } } } } // Column } // FlickablePage } }
All content items of your FlickablePage get reparented to the internal AppFlickable automatically and are thus scrollable.
It is now easier distinguish the Felgo Live Server and Felgo Live Client on macOS and Linux. The different applications now use different app icons on these systems as well:
VPLAY_PLUGINS
project setting. You can now use the setting to link plugin frameworks on iOS again.Highlights Blog Post: Release 3.0.0: V-Play is Now Felgo - New Release & Roadmap
Felgo 3.0.0 combines all app, game and plugin types into Felgo and unifies component naming conventions.
Felgo 3.0.0 comes as a free update for all Felgo developers.
You no longer have to use different import statements when working with Felgo. The components of the V-Play Apps, V-Play Games and V-Play Plugins modules are all available with a single import Felgo 3.0
statement:
import Felgo 3.0 import QtQuick 2.0 App { // Storage, required import VPlay 2.0 before Storage { id: felgoStorage } // NavigationStack, required import VPlayApps 1.0 before NavigationStack { id: appNavStack initialPage: Page { title: "AdMob Page" // AdMob Plugin, required import VPlayPlugins 1.0 before AdMobBanner { adUnitId: "ca-app-pub-3940256099942544/6300978111" // banner test ad by AdMob testDeviceIds: [ "<a testdevice id>" ] banner: AdMobBanner.Smart anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top } } } }
With many recent additions, the line between the Apps and Games SDK got less clear. For example, the Storage type is also relevant for apps but was part of the V-Play Games module. The SocialView, which is based on app components, replaced the VPlayGameNetworkView also for games, and so on.
You can combine both app and game components in your Felgo app. The unified import for all components now further simplifies this. Felgo is still compatible with the old V-Play imports. Your existing V-Play projects still work as they used to.
But we suggest to update your projects for Felgo as soon as you can. The V-Play modules are now deprecated and not maintained further. You can thus only get the latest features and components of future Felgo updates with the new module import.
In case you run into troubles or face an issue after upgrading to Felgo, don’t hesitate to contact us.
Especially for the V-Play Games module, many components used to have a ‘VPlay’ suffix, which is now removed. This helps to keep component names short and the code is easier to read:
import QtQuick 2.0 import Felgo 3.0 GameWindow { activeScene: scene Scene { id: scene // previously: SpriteSequenceVPlay SpriteSequence { id: spriteseq defaultSource: "spritesheet.png" // previously: SpriteVPlay Sprite { name: "walk" frameWidth: 32 frameHeight: 32 frameCount: 4 startFrameColumn: 1 frameRate: 20 to: {"jump":0, "walk": 1} } // previously: SpriteVPlay Sprite { name: "jump" frameWidth: 32 frameHeight: 32 frameCount: 4 startFrameColumn: 5 frameRate: 10 to: {"walk":1} } } // SpriteSequence Row { spacing: dp(4) anchors.centerIn: parent AppButton { text: "walk" onClicked: spriteseq.jumpTo("walk") } AppButton { text: "jump" onClicked: spriteseq.jumpTo("jump") } } } // Scene } // GameWindow
Note: Some of the renamed components in the V-Play SDK have colliding names with Qt components. For Example, the Qt Quick module also holds a SpriteSequence or Sprite type. Qt Creator auto-resolves the types with the imported modules in the QML file. At the moment, the most recent import gets precedence to earlier ones. The above example thus uses the Felgo SpriteSequence and Sprite types, because we import Felgo after Qt Quick.
To avoid issues and mix-ups due to this auto-resolve, you can make sure to always use a specific module by setting a custom module identifier for the import. This is how you could use the Qt Quick types in the above example, without changing the order of imported modules:
import QtQuick 2.0 as QtQuick import Felgo 3.0 GameWindow { activeScene: scene Scene { id: scene QtQuick.SpriteSequence { // ... QtQuick.Sprite { // ... } } // SpriteSequence } // Scene } // GameWindow
This is the full list of components that previously used ‘VPlay’ suffix in their name: Scene3D, Camera, AnimatedSprite, Sprite, SpriteSequence, TexturePackerAnimatedSprite, TexturePackerSprite, TexturePackerSpriteSequence, SoundEffect and Particle.
When you update your project to the new Felgo 3.0 import, please also make sure to use the new names for these components. The name changes only apply for the Felgo module import. Your existing project with V-Play imports is not affected and can still use the old names.
With the rename of V-Play to Felgo, the game network and multiplayer components got renamed as well. The VPlayGameNetwork
type is now FelgoGameNetwork, and
VPlayMultiplayer
turned into FelgoMultiplayer.
As the VPlayGameNetworkView
and VPlayMultiplayerView
are in the process of getting deprecated, they do not get the Felgo name. These types have ‘VPlay’ removed and are available as
GameNetworkView and MultiplayerView. Only the SocialView will see updates and fixes in the future. It
is the new default UI for social services and the preferred component to use:
import Felgo 3.0 App { FelgoGameNetwork { id: gameNetwork gameId: 285 secret: "AmazinglySecureGameSecret" multiplayerItem: multiplayer } FelgoMultiplayer { id: multiplayer appKey: "dd7f1761-038c-4722-9f94-812d798cecfb" pushKey: "a4780578-5aad-4590-acbe-057c232913b5" gameNetworkItem: gameNetwork } SocialView { id: socialView gameNetworkItem: gameNetwork multiplayerItem: multiplayer } }
To integrate the Felgo SDK in your project, set CONFIG += felgo
in your *.pro
configuration:
# allows to add DEPLOYMENTFOLDERS and links to the Felgo library and QtCreator auto-completion CONFIG += felgo # previously CONFIG += vplay # uncomment this line to add the Live Client Module and use live reloading with your custom C++ code # for the remaining steps to build a custom Live Code Reload app see here: https://felgo.com/custom-code-reload-app/ # CONFIG += felgo-live # previously CONFIG += vplay-live
The previous CONFIG += vplay
setting is still supported. For live reloading with custom C++ code, the CONFIG += vplay-live
setting changed to CONFIG += felgo-live
as well. If you
use Felgo Plugins in your project, link the iOS Plugin Frameworks with the FELGO_PLUGINS
configuration:
ios { QMAKE_INFO_PLIST = ios/Project-Info.plist OTHER_FILES += $$QMAKE_INFO_PLIST } FELGO_PLUGINS += admob # previously: VPLAY_PLUGINS += admob
In your main.cpp
, the Felgo application and Live Client class names also got renamed:
#include <QApplication> #include <QQmlApplicationEngine> #include <FelgoApplication> // previously: #include <VPlayApplication> // uncomment this line to add the Live Client Module and use live reloading with your custom C++ code //#include <FelgoLiveClient> // previously: #include <VPLiveClient> int main(int argc, char *argv[]) { QApplication app(argc, argv); FelgoApplication felgo; // previously: VPApplication vplay; // ... // to start your project as Live Client, comment (remove) the lines "felgo.setMainQmlFileName ..." & "engine.load ...", and uncomment the line below //FelgoLiveClient client (&engine); // previously: VPLiveClient client (&engine); return app.exec(); }
Similar to other changes of this update, the previous class names and includes are still supported as well.
With the power of Felgo Apps at hand, there’s no need to use outdated controls that were part of the Games module. You can take advantage of Felgo Apps Controls and Qt Quick Controls 2 for your games as well.
To make the difference clear and match the name pattern of Felgo app controls like AppButton, those game controls now prepend ‘Game’. In case a ‘VPlay’ suffix was used, it is removed:
Those types are also marked deprecated and won’t receive updates anymore. We advise to not use these types in future projects.
Highlights Blog Post: Release 2.18.3: QML JSON ListModel
Felgo 2.18.3 adds the JsonListModel as a performant and feature-rich QML ListModel enhancement. It helps you transform your JSON data to a model and enables you to detect changes to individual items in your model. You can then only update the changed items in your UI instead of updating the full list. This update also adds several improvements and fixes.
Felgo 2.18.3 comes as a free update for all Felgo developers.
The JsonListModel type implements the full QML ListModel API and fires individual events for all changes in the data. The list view can thus only update relevant entries or apply transition animations. This is super useful, as you can e.g. fetch new data and simply replace the old JSON. The JsonListModel will detect all changes, and the ListView updates its items accordingly - without a full redraw.
You thus get much better performance and scrolling stays smooth when the list is updated:
|
|
Json Model: List jumps to the top after an update. |
JsonListModel: The list keeps its scroll position.
(the GIF only jumps to the top when it restarts) |
With the JsonListModel you do not require to implement a custom model in C++ anymore. The JsonListModel itself is your C++ model, which is fully usable from QML and can work with JSON list items of any format.
Apart from list views, the model also supports the GridView and Repeater types to display model data.
The following example shows how to use JsonListModel together with AppListView. When adding a new item to the JSON, the JsonListModel detects the change. The AppListView can thus use a transition animation when adding the entry. It is not required to fully redraw the list and existing items in the view are not affected.
import Felgo 3.0 import QtQuick 2.0 App { NavigationStack { Page { id: page title: "JSONListModel" // property with json data property var jsonData: [ { "id": 1, "title": "Entry 1" }, { "id": 2, "title": "Entry 2" }, { "id": 3, "title": "Entry 3" } ] // list model for json data JsonListModel { id: jsonModel source: page.jsonData keyField: "id" } // list view AppListView { anchors.fill: parent model: jsonModel delegate: SimpleRow { text: model.title } // transition animation for adding items add: Transition { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 1000 easing.type: Easing.OutQuad; } } } // Button to add a new entry AppButton { anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom text: "Add Entry" onClicked: { var newItem = { "id": jsonModel.count + 1, "title": "Entry "+(jsonModel.count + 1) } page.jsonData.push(newItem) // manually emit signal that jsonData property changed // JsonListModel thus synchronizes the list with the new jsonData page.jsonDataChanged() } } } // Page } }
Please see the documentation of JsonListModel for more information and examples. The JsonListModel is now also used for all JSON models of the Felgo SDK app demos.
You can find the MVC Architecture Demo App along with other app demos in the Felgo SDK and as a project wizard in Qt Creator. The basic app is the best starting point for new applications and combines many features that used to be part of individual wizards before. It is also available for you on GitHub.
It uses list transition animations and shows how to integrate PullToRefreshHandler, VisibilityRefreshHandler or SortFilterProxyModel. The demo supports fetching of todos, creation and storing of drafts, offline caching, paging, sorting and filtering.
Use PRODUCT_VERSION_CODE
and PRODUCT_VERSION_NAME
variables in your *.pro file to update version information for all platforms. The benefit of this new solution is, that you now need update the
version data just at one place instead at multiple places. Version information is then automatically set in your iOS Info.plist file and Android AndroidManifest.xml file every time you run qmake for
your project.
To make use of this new Felgo feature you need to modify existing projects. Totally modify three files to make use of the new variables:
Note: After installing the update, no modification is required for new created projects (wizard).
In the *.pro project configuration add two new properties:
PRODUCT_VERSION_CODE
: Number of the build, a positive integer. Must be higher than the last code used. (e.g. 1,2,3,4)PRODUCT_VERSION_NAME
: Public version number shown to users. (e.g. 1.5, 1.6, 2.0.1)In the build.gradle
file in your projects android folder replace your applicationId
assignment. You can keep the existing defaultConfig
block, but remove the
applicationId
line above and add:
defaultConfig { applicationId = productIdentifier versionCode = productVersionCode.toInteger() versionName = productVersionName }
In the Project-Info.plist
file in your projects ios folder replace the value in the line below the following keys:
CFBundleShortVersionString
-> ${PRODUCT_VERSION_NAME}
CFBundleVersion
-> ${PRODUCT_VERSION_CODE}
Next time you want to update the version data, just change the PRODUCT_VERSION_
properties in your project configuration file and build the app.
You can also specify a custom transition using StackViewDelegate:
import Felgo 3.0 import QtQuick 2.0 import QtQuick.Controls 1.4 App { // NavigationStack NavigationStack { // custom transition delegate transitionDelegate: StackViewDelegate { pushTransition: StackViewTransition { NumberAnimation { target: enterItem property: "opacity" from: 0 to: 1 duration: 1000 } } popTransition: StackViewTransition { NumberAnimation { target: exitItem property: "opacity" from: 1 to: 0 duration: 1000 } } } initialPage: pageComponent } // Component for pages Component { id: pageComponent Page { id: page title: "Page 1" Rectangle { anchors.centerIn: parent color: Qt.rgba(Math.random(255), Math.random(255), Math.random(255)) width: parent.width / 2 height: parent.height / 2 } AppButton { anchors.horizontalCenter: parent.horizontalCenter text: "Push" onClicked: { var properties = { title: "Page " + (page.navigationStack.depth + 1) } page.navigationStack.push(pageComponent, properties) } } } // Page } // Component }
id: textEdit
.
Highlights Blog Post: Release 2.18.2: MVC, MVVM, Flux with QML
Felgo 2.18.2 adds the latest Qt Creator 4.7, as well as many improvements and fixes. A new comprehensive guide helps you to structure your code, and separate logic from UI (MVC, MVVM, Flux).
Felgo 2.18.2 comes as a free update for all Felgo developers.
Update Note: For using the Qt Quick Compiler, which is the default for building in Release Mode with Qt Creator 4.7, it is required to list each qml
file with an own entry in your resources.qrc
. Otherwise, the compiler does not find the QML source files.
To deactivate the QML compiler, you can use the CONFIG -= qtquickcompiler
setting in your *.pro
configuration. This only protects the QML resources and bundles them as assets within your binary.
You can also skip a specific .qrc
configuration with e.g. QTQUICK_COMPILER_SKIPPED_RESOURCES += bundle_only.qrc
.
The guide offers a best-practice solution how to separate model, view and logic components in your Felgo apps:
A clean component architecture and data-flow helps to keep create readable code, avoids bugs and makes maintenance or refactoring easy.
You can find the full example of the guide on GitHub:
It is available as a project wizard template in Qt Creator as well:
All Felgo Apps Examples and Demos now also use this best-practice solution.
This example hides the effect for a single button:
import Felgo 3.0 App { AppButton { text: "No Ripple Effect" onClicked: console.log("clicked") rippleEffect: false } }
You can also use Theme.appButton.rippleEffect to change your app's default setting:
import Felgo 3.0 App { onInitTheme: { Theme.appButton.rippleEffect = false } AppButton { text: "No Ripple Effect" onClicked: console.log("clicked") } }
You can use more than one FirebaseConfig instance by assigning a different unique name to each instance. These names are used for persistence and should be the same between app starts.
Highlights Blog Post: Release 2.18.1: JavaScript Promises for REST Services, Tinder Swipe Material Cards, QML QSortFilterProxyModel, QML YouTube Player
Felgo 2.18.1 introduces new components for embedding YouTube videos, for creating material cards and Tinder-like swipe cards. It also simplifies connecting to REST services, with the new HttpRequest component. Felgo 2.18.1 also adds several other fixes and improvements.
Felgo 2.18.1 comes as a free update for all Felgo developers.
The component uses a WebView internally and is based on the YouTube Iframe-Player API. To show how you can use the player in your app, you can have a look at the YouTube Video Player App. It uses the YouTube Data API to browse playlists and videos of a configured channel.
This is how you can use the player in QML:
import Felgo 3.0 App { NavigationStack { Page { title: "YouTube Player" YouTubeWebPlayer { videoId: "KQgqTYCfJjM" autoplay: true } } } }
New Features
section below and in the documentation.
import Felgo 3.0 App { NavigationStack { Page { title: "Page" // this code and manual checks of isCurrentStackPage are no longer required onIsCurrentStackPageChanged: { if(isCurrentStackPage) console.log("Page appeared") else console.log("Page disappeared") } // instead, you can use the new signals onAppeared: console.log("Page appeared") onDisappeared: console.log("Page disappeared") } } }
This example shows how all the Page lifecycle events trigger when working with NavigationStack:
Use this snippet to test the signals yourself:
import Felgo 3.0 import QtQuick 2.0 App { // navigation stack for pages NavigationStack { initialPage: pageComponent } // page component Component { id: pageComponent Page { id: page title: "Page 1" // allow to push and pop pages dynamically Column { anchors.centerIn: parent // push additional page AppButton { text: "Push" onClicked: page.navigationStack.push(pageComponent, { title: "Page "+(navigationStack.depth + 1) }) } // pop current page AppButton { text: "Pop" onClicked: page.navigationStack.pop() } } // handle lifecycle signals onAppeared: console.log(title+" appeared") onDisappeared: console.log(title+ " disappared") onPushed: console.log(title+ " pushed") onPopped: console.log(title+ " popped") } } }
It is available as a singleton item for all components that use import Felgo 3.0
:
import Felgo 3.0 import QtQuick 2.0 App { Component.onCompleted: { HttpRequest .get("http://httpbin.org/get") .timeout(5000) .then(function(res) { console.log(res.status); console.log(JSON.stringify(res.header, null, 4)); console.log(JSON.stringify(res.body, null, 4)); }) .catch(function(err) { console.log(err.message) console.log(err.response) }); } }
Similar to HttpRequest, which matches the DuperAgent Request
type, other DuperAgent features are also available in Felgo with the Http
prefix:
attach
function.
The HttpRequest type also supports response caching of your requests out-of-the-box. To change cache behavior, you can use the HttRequest::config() method. It is also possible to change cache settings for individual requests:
import Felgo 3.0 import QtQuick 2.0 App { Component.onCompleted: { HttpRequest .get("http://httpbin.org/get") .cacheSave(true) // cache the result of this request, regardless of global cache setting .cacheLoad(HttpCacheControl.PreferNetwork) // use network if possible, otherwise load from cache .then(function(res) { console.log(JSON.stringify(res.body)) }) .catch(function(err) { console.log(err.message) }); } }
Http
prefix:
import Felgo 3.0 import QtQuick 2.0 App { Component.onCompleted: { var p1 = Promise.resolve(3); var p2 = 1337; var p3 = HttpRequest .get("http://httpbin.org/get") .then(function(resp) { return resp.body; }); var p4 = Promise.all([p1, p2, p3]); p4.then(function(values) { console.log(values[0]); // 3 console.log(values[1]); // 1337 console.log(values[2]); // resp.body }); } }
Promises are a convenient and flexible way to handle asynchronous aspects of your application.
The following example shows the configured entries of the ListModel in a ListPage, and allows to sort the list
using the name
property:
import Felgo 3.0 import QtQuick 2.0 App { // data model ListModel { id: fruitModel ListElement { name: "Banana" cost: 1.95 } ListElement { name: "Apple" cost: 2.45 } ListElement { name: "Orange" cost: 3.25 } } // sorted model for list view SortFilterProxyModel { id: filteredTodoModel sourceModel: fruitModel // configure sorters sorters: [ StringSorter { id: nameSorter roleName: "name" }] } // list page NavigationStack { ListPage { id: listPage title: "SortFilterProxyModel" model: filteredTodoModel delegate: SimpleRow { text: name detailText: "cost: "+cost style.showDisclosure: false } // add checkbox to activate sorter as list header listView.header: AppCheckBox { text: "Sort by name" checked: nameSorter.enabled updateChecked: false onClicked: nameSorter.enabled = !nameSorter.enabled anchors.horizontalCenter: parent.horizontalCenter height: dp(48) } } // ListPage } // NavigationStack } // App
Please see the documentation of SortFilterProxyModel for more details and relevant types.
true
only after a short delay. This is required, as otherwise the network adapter might not be
ready yet, which can cause immediate network requests to fail.
Highlights Blog Post: Release 2.18.0: Update to Qt 5.11.1 with QML Compiler and Massive Performance Improvements
Felgo 2.18.0 updates to Qt 5.11.1 and adds several improvements and fixes.
Felgo 2.18.0 comes as a free update for all Felgo developers.
CONFIG += qtquickcompiler
Highlights Blog Post: Release 2.17.1: Use 3D with Live Reloading and Test Plugin Code Examples from Browser
Felgo 2.17.1 adds several improvements and fixes for Felgo components. It also includes a new app example, how to create custom listview delegates.
Felgo 2.17.1 comes as a free update for all Felgo developers.
|
|
Here is an example how to display an ad banner with the AdMob plugin:
import Felgo 3.0 App { NavigationStack { Page { title: "AdMob Banner" AdMobBanner { adUnitId: "ca-app-pub-3940256099942544/6300978111" // banner test ad by AdMob banner: AdMobBanner.Smart } } } }
The following example displays a floating action button above the keyboard, that also adapts to size changes of the keyboard:
import Felgo 3.0 import QtQuick 2.7 App { id: app // We unset the focus from the AppTextField after the keyboard was dismissed from the screen onKeyboardVisibleChanged: if(!keyboardVisible) textField.focus = false NavigationStack { Page { id: page title: qsTr("Keyboard Height") AppTextField { id: textField width: parent.width font.pixelSize: sp(25) } FloatingActionButton { // Add the keyboard height as bottom margin, so the button floats above the keyboard anchors.bottomMargin: app.keyboardHeight + dp(15) // We only show the button if the AppTextField has focus and the keyboard is expanded visible: textField.focus && app.keyboardHeight != 0 icon: IconType.check backgroundColor: Theme.tintColor iconColor: "white" onClicked: textField.focus = false } } } }
.txt
or .json
anymore. This allows working with shaders in
the Felgo Live Client without any custom C++ code from QML.
itemId
as parameter that triggered the
signal.
The new phoneNumber property now works with Android run-time permissions.
Note: The methods getContacts() and getPhoneNumber() are deprecated as of Felgo 2.17.1. Use the new properties instead.
startAt
and endAt
on iOS.
Highlights Blog Post: Release 2.17.0: Firebase Storage, Downloadable Resources at Runtime and Native File Access on All Platforms
Felgo 2.17.0 adds two new demos that show how to integrate C++ code with QML and add the new DownloadableResource and FileUtils items.
Felgo 2.17.0 comes as a free update for all Felgo developers.
With the new FirebaseStorage item, you can upload files to the Firebase Cloud Storage. It uploads local files to the cloud file system and provides a public download URL.
You can upload files like the following:
In addition, the text and icon of tabs for TabControl or AppTabButton may now use a different color while being pressed. To take advantage of this feature in your app's navigation drawer entries and tabs, the Theme provides the following new settings:
true
.
import Felgo 3.0 import QtQuick 2.0 App { onInitTheme: { Theme.colors.tintColor = "red" // drawer + item bg Theme.navigationAppDrawer.backgroundColor = "lightgrey" Theme.navigationAppDrawer.itemBackgroundColor = Theme.tintColor Theme.navigationAppDrawer.itemSelectedBackgroundColor = "orange" Theme.navigationAppDrawer.itemActiveBackgroundColor = "white" // item text Theme.navigationAppDrawer.textColor = "white" Theme.navigationAppDrawer.selectedTextColor = "black" Theme.navigationAppDrawer.activeTextColor = Theme.tintColor // tab text Theme.tabBar.titleColor = Theme.tintColor Theme.tabBar.titlePressedColor = "orange" } Navigation { navigationMode: navigationModeTabsAndDrawer NavigationItem { title: "Home" icon: IconType.home NavigationStack { Page { title: "Home" } } } NavigationItem { title: "Favorites" icon: IconType.star NavigationStack { Page { title: "Favorites" } } } NavigationItem { title: "Help" icon: IconType.question NavigationStack { Page { title: "Help" } } } } }
false
. If you hide the button or use a customized profile, you can still provide this feature with the FelgoGameNetwork::deleteUser() function.
true
and running is also set to true
). The overall performance
also increased, as frames are no longer re-drawn if the animation is not running or paused.
You can do this either by assigning currentFrame or by calling advance().
file://
URLs on Android & iOS.
Please note that if your targetSdkVersion
in AndroidManifest.xml
is 24 or higher and you want to open file://
URLs with another application on Android devices, you need to enable
the paths you intend to use in the android/res/xml/file_paths.xml
file.
Highlights Blog Post: Release 2.16.1: Live Code Reloading with Custom C++ and Native Code for Qt
Felgo 2.16.1 features live code reloading with custom C++ and native code for Felgo and Qt projects.
Starting with Felgo 2.16.1, the app's bundle identifier for iOS is set using the PRODUCT_IDENTIFIER
setting in your *.pro
project configuration. To adapt to the new setting perform the following
steps:
1. Open your *.pro
project file and add the following block:
# configure the product's bundle identifier # this identifier is used for the app on iOS PRODUCT_IDENTIFIER = com.your.company.YourApp
where com.your.company.YourApp
matches the CFBundleIdentifier
setting of your existing Project-Info.plist
configuration.
2. Open your Project-Info.plist
in the ios
subfolder and replace the value of CFBundleIdentifier
with $(PRODUCT_BUNDLE_IDENTIFIER)
, so that it looks like the following:
<key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
3. After running qmake, your iOS build uses the new setting.
Note: Make sure to transition your project to this new format, as otherwise app store build uploads from Xcode 9 might fail.
All Felgo Project Wizards already use the new project setting.
Felgo version 2.16.1 introduces the Live Client Module. You can use it to add QML live reloading features to your own application. This allows you to use custom C++ and native code together with live code reloading for QML and JavaScript. You can find a quick integration guide in the update blog post.
You can style the badge globally with the Theme::listItem properties or specifically for a row instance with the SimpleRow::style property:
You can style the badge with the Theme::navigationAppDrawer properties:
Highlights Blog Post: Release 2.16.0: iPhone X Support and Runtime Screen Orientation Changes
Felgo 2.16.0 brings iPhone X support and runtime screen orientation changes.
The iPhone X comes with new UI challenges, as the screen is now bigger and includes reserved areas that hold native buttons or overlays. The Felgo Navigation components automatically adjust their style to match these new requirements. In addition, the Page::useSafeArea setting takes care of keeping your UI elements within the safe area of the screen.
Alternatively, you can also disable the setting and manually align your content to the Page::safeArea item. The exact pixel insets of the screen are available with the NativeUtils::safeAreaInsets property.
To support existing games on devices with reserved screen areas, the Scene::useSafeArea setting keeps your scene content within the safe area. The Scene::gameWindowAnchorItem reflects this safe area of the screen.
To provide the best look and experience, you can take advantage of the new Scene::fullWindowAnchorItem. You can then e.g. let your background fill the whole screen, without affecting other parts of the game.
The exact pixel insets of the screen are available with the NativeUtils::safeAreaInsets property. If used within a Scene, keep in mind that these insets do not take scene-scaling into consideration.
To speed up development, you can test your UI for iPhone X on Desktop without having to build and deploy for the iPhone Simulator.
The Desktop simulation for iPhone X also covers the native safe area. You can quickly switch between different devices to see how your app looks like with and without safe area insets.
To specify the global orientation you can use the new property NativeUtils::preferredScreenOrientation. E.g. to lock and unlock your app or game to portrait orientation, you can use the following lines of code:
import Felgo 3.0 import QtQuick 2.5 App { NavigationStack { Page { title: "Orientation Lock" Column { AppButton { text: "Lock to portrait" onClicked: nativeUtils.preferredScreenOrientation = NativeUtils.ScreenOrientationPortrait } AppButton { text: "Reset default orientation" // Resets to the orientation defined in AndroidManifest.xml / Project-Info.plist onClicked: nativeUtils.preferredScreenOrientation = NativeUtils.ScreenOrientationDefault } } } } }
You can also specify the orientation per page in apps, using Page::preferredScreenOrientation. Use this example code to show a page fixed to portrait mode:
import Felgo 3.0 import QtQuick 2.0 App { id: app NavigationStack { id: stack Page { id: page title: "Screen orientation test" AppButton { text: "Push portrait page" onClicked: stack.push(portraitPage) } } } Component { id: portraitPage Page { id: page title: "Portrait page" preferredScreenOrientation: NativeUtils.ScreenOrientationPortrait } } }
These properties only have an effect on iOS and Android and override the default screen orientation defined in your project's Project-Info.plist
and AndroidManifest.xml
.
false
for phablets and phones with bigger screens like the iPhone X or Samsung Galaxy S8+.
import Felgo 3.0
only. for NativeUtils anymore if you are only using app
components).
false
.
false
.
targetSdkVersion >= 24
in AndroidManifest.xml
, it needs to use a content provider so the camera app can save the image to the app.
For new projects created in Qt Creator, everything is already configured properly.
If you have an existing project and are updating targetSdkVersion
to 23 or greater, you need to add the following code to android/AndroidManifest.xml
inside the <application>
tag:
<!-- file provider needed for letting external apps (like camera) write to a file of the app --> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider>
Additionally you need to create a file android/res/xml/file_paths.xml
with the following contents:
<?xml version="1.0" encoding="utf-8"?> <paths> <external-files-path name="images" path="Pictures"/> </paths>
Finally, add the following dependencies to android/build.gradle
:
dependencies { ... implementation 'com.android.support:support-core-utils:27.1.0' implementation 'com.android.support:appcompat-v7:27.1.0' }
getPrice()F
method in log output when using Soomla Plugin.
Highlights Blog Post: Release 2.15.1: Upgrade to Qt 5.10.1 & Qt Creator 4.5.1 | Firebase Improvements and New Live Code Reloading Apps
Felgo 2.15.1 updates to Qt 5.10.1 & Qt Creator 4.5.1 and adds new APIs for the Firebase Plugin.
Highlights Blog Post: Release 2.15.0: Upgrade to Qt 5.10 & Qt Creator 4.5 | Firebase Data Structures and Queries & Many Improvements
Felgo 2.15.0 updates to Qt 5.10
Example:
FirebaseDatabase { id: firebaseDb Component.onCompleted: getValue("public/path/to/my/object") onReadCompleted: { if(success) { //signal parameter "value" can be a nested object/array as read from your database console.debug("Read value " + value.subarray[3].subproperty.text) } } }
queryProperties
to the functions FirebaseDatabase::getValue() and FirebaseDatabase::getUserValue().
Example:
//use query parameter: firebaseDb.getValue("public/bigqueryobject", { orderByKey: true, //order by key before limiting startAt: "c", //return only keys alphabetically after "c" endAt: "m", //return only keys alphabetically before "m" limitToFirst: 5, //return only first 5 sub-keys })
See more details about the available query parameters at the documentation of FirebaseDatabase::getValue().
source
property for NavigationItem.
List of older releases: Felgo Updates (Older Releases)