QtAseman is a set of tools, design patterns and architectures that we have developed over the years in various projects for wide range of uses. Now, with it's proven stability, we have decided to release this collection with the name QtAseman as an Open Source and Free tool under the LGPLv3 license.
Currently binary packages only available on the ubuntu (launchpad) repositories. To install it on the ubuntu 20.04 LTS:
sudo add-apt-repository ppa:aseman/qt-modules
sudo apt install qt5aseman
and to install development files install qt5aseman-dev
package.
QtAseman uses standard Qt module mechanisms and it only depends on Qt libraries. Therefor it's quite easy to build on all platforms. Just clone it and build it easily:
git clone https://github.com/Aseman-Land/QtAseman.git
cd QtAseman
mkdir build && cd build
qmake -r ..
make -j2
make install
The easiest way to build is to open it using QtCreator and click on the build icon :)
Afterwards just run make install
command to install it in the Qt location.
One of the main assets of QtAseman is that you can add it to your project without any extra change to the standard structure of the default QML app.
So To create an application using QtAseman, Just create a new QML project in your QtCreator and add AsemanQML module to the project. Now you can use all QtAseman components:
import AsemanQml.Controls 2.0
import QtQuick.Controls 2.12
AsemanWindow {
visible: true
width: 480
height: 720
title: qsTr("QtAseman Example")
Label {
anchors.centerIn: parent
text: "Hello World! :)"
}
}
If you wish to change any application attribute like applicationName or applicationOrganization you can create an AsemanApp
object in the parent of AsemanWindow
. Although it's completely optional and you can ignore it.
import AsemanQml.Controls 2.0
AsemanApplication {
id: app
applicationAbout: "QtAseman Application"
applicationDisplayName: "QtAseman"
applicationId: "be2a1f0c-34aa-44ed-8e65-4b1720e560b8"
organizationDomain: "aseman.io"
AsemanWindow {
visible: true
width: 480
height: 720
}
}
We suggest you to also create an AsemanApplication object, because QtAseman handles config file paths better while this attributes is set.
Note: In order to make all modules work correctly on android devices you must replace io.aseman.android.AsemanApplication
and io.aseman.android.AsemanActivity
with Qt's values in the android manifest file.
There are many modules and components in QtAseman that will help you create applications without use of any extra C++ code. Also QtAseman offers a great software architecture for each module that makes development much more easier and faster.
AsemanQml.Base module provides many base and core modules for your application. For example modules like Device infos, Desktop functions tools, data type converters, lists, hashes and etc. are placed in Base module.
here is one of the main uses of Base module:
import AsemanQml.Controls 2.0
import AsemanQml.Base 2.0
AsemanWindow {
visible: true
width: 480
height: 720
title: qsTr("QtAseman Example")
Rectangle {
height: Devices.statusBarHeight
width: parent.width
color: "blue"
}
}
QtAseman makes mobile status bars transparent by default and Devices.statusBarHeight
returns the status bar height of the device. The above example makes the status bar color blue. If there is no status bar on the device (like desktop operation systems) it returns zero as the result.
You can get other useful values like screen density, suggested font density, main OS folder locations, platform details, device type and etc. using Devices
component.
Also there is Tools
component that provides some extra tools for applications, like methods to read or write to/from files or methods to convert json to variant map or convert url to local path and etc.
For example below codes create sha256 hash:
var sha = Tools.hash("12345", Tools.Sha256);
Or below codes read text from file:
var text = Tools.readText("/home/bardia/file.txt");
There is also a Process
component that runs processes or a great back handler component named BackHandler
.
BackHandler
component provides back mechanism for your application. It's simple and easy to work with, plus all components of QtAseman support it by default, therefore it handles back actions automatically without the direct interference of developer.
Below example shows you how to use BackHandler
component in your code:
Button {
anchors.centerIn: parent
text: "Show"
onClicked: subRect.visible = true
}
Rectangle {
id: subRect
anchors.fill: parent
visible: false
onVisibleChanged: {
if (visible)
BackHandler.pushHandler(subRect, function(){ subRect.visible = false })
else
BackHandler.removeHandler(subRect)
}
Button {
anchors.centerIn: parent
text: "Hide"
onClicked: BackHandler.back()
}
}
Beside clicking on the hide button to trigger back function, you can press Esc button or the physical back button of device. On mobile devices if there is no back function in the BackHandler stack and back() method is called, application will try to quit.
Note: You must use AsemanWindow object to make Esc or Physical back button work.
AsemanListModel provides a model component for advanced usage of QML. Below example shows how to use AsemanListModel in your code:
AsemanListModel {
id: model
data: [
{
"name": "bardia",
"age": 30 + 2 // It supports js values too.
},
{
"name": "amir",
"age": 31
}
]
// cachePath store model data to the file and restore it everytime
// Application load again
cachePath: AsemanApp.homePath + "/ages.model"
}
Note: AsemanApp.homePath
returns standard path to store config files.
And You can manage your model using below methods:
var value = model.get(idx, "propertyName");
var allValues = model.get(idx); // allValues.propertyName is equal to value
model.clear();
model.append({"name", "bardia", "age": 30});
var data = model.data; // Get all data of the model as list
var json = Tools.variantToJson(data); // Convert data to json string
Creates a settings file in a specific path and stores settings values there:
Settings {
id: settings
category: "General"
source: AsemanApp.homePath + "/ui-settings.ini"
property bool languageInited: false
property int nightMode: 0
property int colorTheme: 0
property int darkColorTheme: 3
}
Every change in setting's property is saved and can be restored within the next load of application.
Translations
and TranslationManager
provide functions and tools to manage translation in your application:
TranslationManager {
id: translationManager
// Finds all lang-*.qm files in the sourceDirectory using three below lines
sourceDirectory: "../translations"
delimiters: "-"
fileName: "lang"
localeName: "fa"
}
Button {
// Everytime translation changed to other language, Every refresher texts
// will refreshed and translated to the new language
text: qsTr("Dismiss") + Translations.refresher
}
It renders every included child item as rounded. For example below code shows an image with rounded corners:
RoundedItem {
width: 100
height: 100
radius: 10
Image {
anchors.fill: parent
source: "image.png"
}
}
DelegateSwitch
provides a component to switch between two or more children components on the fly. For example:
ListView {
model: 20
delegate: DelegateSwitch {
current: model.index % 2
Component {
Rectangle {
width: 100; height: 40
color: "red"
}
}
Component {
Rectangle {
width: 40; height: 40
color: "blue"
}
}
}
}
This example shows red rectangles on even indexes and blue squeres on odd indexes.
To read more about Base module, please read this document.
Controls module provides any control module like QtQuick.Controls. For example It provides AsemanApplication
, AsemanWindow
, SideMenu
, Header
and many other components.
Below example shows a simple usage of the Controls
component.
import QtQuick 2.9
import AsemanQml.Base 2.0
import AsemanQml.Controls 2.0
AsemanWindow {
visible: true
width: 480
height: 720
title: qsTr("Hello World")
Header {
width: parent.width
text: "Hello"
color: "#18f"
}
Drawer {
id: menu
anchors.fill: parent
delegate: Rectangle {
anchors.fill: parent
color: "#333"
}
}
HeaderMenuButton {
id: btn
/*
* If BackHandler stack is not empty, It shows back
* button instead of hamburger btn.
*/
ratio: BackHandler.count? 1 : menu.percent
onClicked: BackHandler.count? BackHandler.back() : menu.show()
}
}
Viewport module provides a new design architecture for applications.
There is a Viewport
component that provides a manage mechanism for your page, popup, dialogs and etc.
Below example shows you the usage of the Viewport
component.
import AsemanQml.Viewport 2.0
/*
* Viewport component manage pages and Way of the they opened.
* Like popups, pages, dialogs or ...
* It also supports BackHandler by default like other QtAseman components
*/
Viewport {
id: viewPort
anchors.fill: parent
mainItem: Page {
// Main/Default Viewport item
anchors.fill: parent
Button {
text: "Open"
anchors.centerIn: parent
// append hiComponent to the viewPort stack and open it as page
// append() returns a refrence to the created ui object.
// Types are: page, activity, popup, dialog and drawer
onClicked: viewPort.append(hiComponent, undefined, "page")
}
}
}
Component {
id: hiComponent
Page {
id: page
anchors.fill: parent
property int cnt
Button {
id: btn
text: "Open " + (page.cnt+1)
anchors.centerIn: parent
// append method could also pass properties to the dest object
onClicked: viewPort.append(hiComponent, {"counter": page.cnt+1}, "popup")
}
}
}
There is also an attached property, you can use to call append function in the Viewport's childeren components:
Viewport.viewport.append(...)
Using ViewportController
components you won't need to create a complicated architecture. It helps you to make your architecture quite easy and dynamic.
Below example shows you how to create UI and open them easily in the apps.
Using this design architecture, you create separated UI files, link them to their specific path and just call them using controllers anywhere in the App.
ViewportController
opens them automatically in the Viewport
.
Viewport {
id: viewPort
anchors.fill: parent
mainItem: Page {
anchors.fill: parent
Button {
text: "Open"
anchors.centerIn: parent
// Trigger the path and open UI item that linked to the path.
// trigger() returns a refrence to the created ui object.
onClicked: controller.trigger("main://test/bardia")
}
}
}
ViewportController {
id: controller
viewport: viewPort
// Define all your UI routes that connect paths to UI components.
ViewportControllerRoute {
route: /main:\/\/test\/.*/
sourceComponent: hiComponent
viewportType: "popup"
}
ViewportControllerRoute {
route: /about:\/\/aseman\/.*/
// You can also use `source` property and pass component's url to it.
sourceComponent: aboutComponent
viewportType: "page"
}
}
Component {
id: hiComponent
Page {
anchors.fill: parent
Button {
text: "About"
anchors.centerIn: parent
/*
* You can also pass properties to object using js map
* or using html query way (about://aseman/test?text=about&color=blue)
*/
onClicked: controller.trigger("about://aseman/test", {"text": "about"})
}
}
}
Component {
id: aboutComponent
Label {
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
// If you specify a url property, triggered url will put to this property
property string url
}
}
There is also an attached property, you can use to call trigger function in the Viewport's childeren components:
MouseArea {
onClicked: Viewport.controller.trigger("about://aseman/test", {"text": "about"})
}
Viewport.controller
method returns first controller of the parent Viewport. If you wish to get all controllers as array, use Viewport.allController
method instead.
Network module provides components to send network requests. For Example NetworkRequestManager
and NetworkRequest
could send http requests like post, get, put and etc.
Below example shows you a simple usage of network module.
import AsemanQml.Network 2.0
Button {
text: "Signup"
onClicked: networkManager.post(signInRequest) // get, post, put or ...
}
BusyIndicator { running: signInRequest.refreshing }
NetworkRequestManager { id: networkManager }
NetworkRequest {
id: signInRequest
contentType: NetworkRequest.TypeJson
url: "https://example.com/auth/signIn"
headers: {
"Authorization": "Bearer ...",
}
// Properties will post as json file map
property string username: "test"
property string password: "pass1234"
onServerError: ; // server error codes
onClientError: ; // client error codes
onSuccessfull: {
// Response contains response map if it's json
// or if not response text
console.debug(response.token)
}
}
You can create many simple request files in your project and every time you need them, just send them to the server using NetworkRequestManager and get your response.
These two modules provide access to the MaterialIcons and FontAwesome font icons. The usage is easy:
import AsemanQml.MaterialIcons 2.0
import AsemanQml.Awesome 2.0
Label {
font.family: Awesome.family
text: Awesome.fa_github
}
Label {
font.family: MaterialIcons.family
text: MaterialIcons.mdi_github
}
If you need to access advanced options or create components inherited from QtAseman or even have further use using C++ simply add below line to your .pro
file and use components there:
QT += asemancore asemangui asemanqml asemannetwork asemanwidgets asemangeo
We have started to document all modules and their essential details using Doxygen standards we will put them in documents folder, but the full documentation process is under developing and not completed yet.