chore(CPP): base for the window and layouting system
Demo controls migrations to Qt6 POC for an application layout with isolated components Closes: #5902
This commit is contained in:
parent
36a079aea8
commit
cecfd7f8e8
|
@ -32,3 +32,4 @@ add_subdirectory(app)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
# TODO: temporary not to duplicate resources until we switch to c++ app then it can be refactored
|
# TODO: temporary not to duplicate resources until we switch to c++ app then it can be refactored
|
||||||
add_subdirectory(ui/imports/assets)
|
add_subdirectory(ui/imports/assets)
|
||||||
|
add_subdirectory(ui/fonts)
|
||||||
|
|
|
@ -12,17 +12,26 @@ qt6_add_executable(${PROJECT_NAME} "")
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Application
|
URI Status.Application
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
QML_FILES
|
QML_FILES
|
||||||
qml/main.qml
|
qml/main.qml
|
||||||
qml/Status/Application/StatusWindow.qml
|
qml/Status/Application/Decorators/SplashScreen.qml
|
||||||
qml/Status/Application/StatusContentView.qml
|
|
||||||
qml/Status/Application/MainShortcuts.qml
|
|
||||||
|
|
||||||
qml/Status/Application/MainView/MainView.qml
|
qml/Status/Application/MainView/MainView.qml
|
||||||
|
qml/Status/Application/MainView/StatusApplicationSections.qml
|
||||||
|
|
||||||
|
qml/Status/Application/MainView/StatusApplicationSections/Wallet/WalletNavBarSection.qml
|
||||||
|
|
||||||
|
qml/Status/Application/Settings/ApplicationSettings.qml
|
||||||
|
|
||||||
qml/Status/Application/System/StatusTrayIcon.qml
|
qml/Status/Application/System/StatusTrayIcon.qml
|
||||||
|
|
||||||
qml/Status/Application/Decorators/SplashScreen.qml
|
qml/Status/Application/Workflows/CloseApplicationHandler.qml
|
||||||
|
|
||||||
|
qml/Status/Application/StatusContentView.qml
|
||||||
|
qml/Status/Application/MainShortcuts.qml
|
||||||
|
qml/Status/Application/StatusWindow.qml
|
||||||
|
|
||||||
OUTPUT_DIRECTORY
|
OUTPUT_DIRECTORY
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Application
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Application
|
||||||
)
|
)
|
||||||
|
@ -37,6 +46,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE BUILD_BINARY_DIR=${CMAKE_BINA
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE BUILD_SOURCE_DIR=${CMAKE_SOURCE_DIR})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE BUILD_SOURCE_DIR=${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
add_subdirectory(qml)
|
add_subdirectory(qml)
|
||||||
|
add_subdirectory(qml/Status/Application/Navigation)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(res)
|
add_subdirectory(res)
|
||||||
|
|
||||||
|
@ -53,11 +63,14 @@ target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Qt6::Quick
|
Qt6::Quick
|
||||||
|
|
||||||
|
StatusQ_Application_Navigation
|
||||||
|
|
||||||
# TODO: Use Status:: namespace
|
# TODO: Use Status:: namespace
|
||||||
#Core
|
#Core
|
||||||
Helpers
|
Helpers
|
||||||
Onboarding
|
Onboarding
|
||||||
Assets
|
Assets
|
||||||
|
StatusQ
|
||||||
)
|
)
|
||||||
|
|
||||||
# QtCreator needs this
|
# QtCreator needs this
|
||||||
|
|
|
@ -2,11 +2,20 @@ import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
import Status.Application
|
||||||
|
|
||||||
|
import Status.Containers
|
||||||
|
import Status.Controls
|
||||||
|
|
||||||
|
import Status.Application.Navigation
|
||||||
|
|
||||||
/// Responsible for setup of user workflows after onboarding
|
/// Responsible for setup of user workflows after onboarding
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
/// Emited when everything is loaded and UX ready
|
required property ApplicationController appController
|
||||||
|
|
||||||
|
/// Emitted when everything is loaded and UX ready
|
||||||
signal ready()
|
signal ready()
|
||||||
|
|
||||||
Component.onCompleted: root.ready()
|
Component.onCompleted: root.ready()
|
||||||
|
@ -14,22 +23,40 @@ Item {
|
||||||
implicitWidth: mainLayout.implicitWidth
|
implicitWidth: mainLayout.implicitWidth
|
||||||
implicitHeight: mainLayout.implicitHeight
|
implicitHeight: mainLayout.implicitHeight
|
||||||
|
|
||||||
ColumnLayout {
|
RowLayout {
|
||||||
id: mainLayout
|
id: mainLayout
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
RowLayout {}
|
StatusNavigationBar {
|
||||||
Label {
|
id: navBar
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
text: "TODO MainView"
|
Layout.fillHeight: true
|
||||||
}
|
|
||||||
Button {
|
sections: appSections.sectionsList
|
||||||
text: "Quit"
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
onClicked: Qt.quit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {}
|
ColumnLayout {
|
||||||
|
// Not visible all the time
|
||||||
|
StatusBanner {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
//statusText: // TODO: appController.bannerController.text
|
||||||
|
//type: // TODO: appController.bannerController.type
|
||||||
|
visible: false // TODO: appController.bannerController.visible
|
||||||
|
}
|
||||||
|
Loader {
|
||||||
|
id: mainLoader
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusApplicationSections {
|
||||||
|
id: appSections
|
||||||
|
// Chat ...
|
||||||
|
// Wallet ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import QtQml
|
||||||
|
|
||||||
|
import Status.Controls.Navigation
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
readonly property var sectionsList: [wallet, settings]
|
||||||
|
readonly property ApplicationSection wallet: ApplicationSection {
|
||||||
|
navButton: WalletButtonComponent
|
||||||
|
content: WalletContentComponent
|
||||||
|
|
||||||
|
component WalletButtonComponent: NavigationBarButton {
|
||||||
|
}
|
||||||
|
component WalletContentComponent: ApplicationContentView {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property ApplicationSection settings: ApplicationSection {
|
||||||
|
navButton: SettingsButtonComponent
|
||||||
|
content: SettingsContentComponent
|
||||||
|
|
||||||
|
component SettingsButtonComponent: NavigationBarButton {
|
||||||
|
}
|
||||||
|
component SettingsContentComponent: ApplicationContentView {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
import Status.Application.Navigation
|
||||||
|
import Status.Controls.Navigation
|
||||||
|
|
||||||
|
NavigationBarSection {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
implicitHeight: walletButton.implicitHeight
|
||||||
|
|
||||||
|
StatusNavigationButton {
|
||||||
|
id: walletButton
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// TODO: icon, tooltip ...
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Controls specialized on user workflows
|
||||||
|
project(StatusQ_Application_Navigation)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
set_source_files_properties(Style.qml PROPERTIES
|
||||||
|
QT_QML_SINGLETON_TYPE TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.Application.Navigation
|
||||||
|
VERSION 1.0
|
||||||
|
|
||||||
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
|
QML_FILES
|
||||||
|
StatusNavigationBar.qml
|
||||||
|
StatusNavigationButton.qml
|
||||||
|
|
||||||
|
# Required to suppress "qmllint may not work" warning
|
||||||
|
OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Application/Navigation
|
||||||
|
)
|
|
@ -0,0 +1,29 @@
|
||||||
|
import QtQml
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import Status.Controls.Navigation
|
||||||
|
|
||||||
|
NavigationBar {
|
||||||
|
implicitHeight: mainLayout.implicitHeight
|
||||||
|
|
||||||
|
required property var sections
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: mainLayout
|
||||||
|
|
||||||
|
MacTrafficLights {
|
||||||
|
Layout.margins: 13
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: sections
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
sourceComponent: modelData.navButton
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import QtQml
|
||||||
|
|
||||||
|
import Status.Controls.Navigation
|
||||||
|
|
||||||
|
NavigationBarButton {
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import QtQml
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import Qt.labs.settings
|
||||||
|
|
||||||
|
Settings {
|
||||||
|
property bool quitOnClose: false
|
||||||
|
}
|
|
@ -5,10 +5,16 @@ import QtQuick.Controls
|
||||||
import Status.Application
|
import Status.Application
|
||||||
import Status.Onboarding
|
import Status.Onboarding
|
||||||
|
|
||||||
/// Has entry responsibility for the main workflows
|
import Status.Controls.Navigation
|
||||||
|
|
||||||
|
/*! Has entry responsibility for the main workflows
|
||||||
|
*/
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
required property ApplicationState appState
|
||||||
|
required property ApplicationController appController
|
||||||
|
|
||||||
implicitWidth: d.isViewLoaded ? d.loadedView.implicitWidth : 800
|
implicitWidth: d.isViewLoaded ? d.loadedView.implicitWidth : 800
|
||||||
implicitHeight: d.isViewLoaded ? d.loadedView.implicitHeight : 600
|
implicitHeight: d.isViewLoaded ? d.loadedView.implicitHeight : 600
|
||||||
|
|
||||||
|
@ -35,6 +41,7 @@ Item {
|
||||||
|
|
||||||
MainView {
|
MainView {
|
||||||
onReady: splashScreenPopup.close()
|
onReady: splashScreenPopup.close()
|
||||||
|
appController: root.appController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,12 @@ import Qt.labs.settings
|
||||||
|
|
||||||
import Status.Application
|
import Status.Application
|
||||||
|
|
||||||
/** Administrative scope
|
import Status.Controls.Navigation
|
||||||
|
import Status.Core.Theme
|
||||||
|
|
||||||
|
import "Workflows"
|
||||||
|
|
||||||
|
/*! Administrative scope
|
||||||
*/
|
*/
|
||||||
Window {
|
Window {
|
||||||
id: root
|
id: root
|
||||||
|
@ -14,35 +19,73 @@ Window {
|
||||||
minimumHeight: 600
|
minimumHeight: 600
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
width: mainLayout.implicitWidth
|
width: contentView.implicitWidth
|
||||||
height: mainLayout.implicitHeight
|
height: contentView.implicitHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: true
|
visible: true
|
||||||
title: qsTr(Qt.application.name)
|
title: qsTr(Qt.application.name)
|
||||||
|
|
||||||
flags: Qt.FramelessWindowHint
|
flags: Qt.FramelessWindowHint
|
||||||
|
color: "transparent"
|
||||||
ColumnLayout {
|
|
||||||
id: mainLayout
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
// TODO: nav-bar?
|
|
||||||
// StatusAppNavBar {
|
|
||||||
// }
|
|
||||||
|
|
||||||
StatusContentView {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationController {
|
ApplicationController {
|
||||||
id: appController
|
id: appController
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings {
|
Rectangle {
|
||||||
|
id: windowBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Style.geometry.appCornersRadius
|
||||||
|
color: Theme.palette.appBackgroundColor
|
||||||
|
|
||||||
|
StatusContentView {
|
||||||
|
id: contentView
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
appState: appState
|
||||||
|
appController: appController
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Title gestures handler
|
||||||
|
MouseArea {
|
||||||
|
id: dragArea
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: Style.geometry.titleBarHeight
|
||||||
|
// lower than contentView to not steal events from user controls
|
||||||
|
z: contentView.z - 1
|
||||||
|
|
||||||
|
onDoubleClicked: root.visibility === Window.Maximized ? Window.window.showNormal() : Window.window.showMaximized()
|
||||||
|
|
||||||
|
property point prevMousePoint
|
||||||
|
onPressed: (mouse) => prevMousePoint = Qt.point(mouse.x, mouse.y)
|
||||||
|
onMouseXChanged: root.x += mouseX - prevMousePoint.x
|
||||||
|
onMouseYChanged: root.y += mouseY - prevMousePoint.y
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationState {
|
||||||
|
id: appState
|
||||||
|
}
|
||||||
|
|
||||||
|
onClosing: function(close) {
|
||||||
|
close.accepted = closeHandler.canApplicationClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseApplicationHandler {
|
||||||
|
id: closeHandler
|
||||||
|
|
||||||
|
quitOnClose: appSettings.quitOnClose
|
||||||
|
|
||||||
|
onHideApplication: root.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationSettings {
|
||||||
|
id: appSettings
|
||||||
|
|
||||||
property alias x: root.x
|
property alias x: root.x
|
||||||
property alias y: root.y
|
property alias y: root.y
|
||||||
property alias width: root.width
|
property alias width: root.width
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQml
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property bool quitOnClose
|
||||||
|
|
||||||
|
signal hideApplication()
|
||||||
|
|
||||||
|
function canApplicationClose() {
|
||||||
|
if(root.quitOnClose) {
|
||||||
|
root.hideApplication()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,9 +19,11 @@ set_source_files_properties(qml/Status/Assets/Resources.qml PROPERTIES
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Assets
|
URI Status.Assets
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
QML_FILES
|
QML_FILES
|
||||||
qml/Status/Assets/Resources.qml
|
qml/Status/Assets/Resources.qml
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Assets/
|
OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Assets/
|
||||||
)
|
)
|
||||||
|
@ -31,6 +33,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||||
Qt6::Qml
|
Qt6::Qml
|
||||||
|
|
||||||
# TODO: refactor when moved to C++ code
|
# TODO: refactor when moved to C++ code
|
||||||
|
FontAssets
|
||||||
UiAssets
|
UiAssets
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,7 @@ QtObject {
|
||||||
function gif(name) {
|
function gif(name) {
|
||||||
return assetPath + "/gif/" + name + ".gif";
|
return assetPath + "/gif/" + name + ".gif";
|
||||||
}
|
}
|
||||||
|
function png(name) {
|
||||||
|
return assetPath + "/png/" + name + ".png";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,11 @@ qt6_standard_project_setup()
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Core
|
URI Status.Core
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
QML_FILES
|
QML_FILES
|
||||||
qml/Status/Core/DevTest.qml
|
qml/Status/Core/DevTest.qml
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
OUTPUT_DIRECTORY
|
OUTPUT_DIRECTORY
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Core
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Core
|
||||||
|
|
|
@ -14,9 +14,11 @@ qt6_standard_project_setup()
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Onboarding
|
URI Status.Onboarding
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
QML_FILES
|
QML_FILES
|
||||||
qml/Status/Onboarding/OnboardingView.qml
|
qml/Status/Onboarding/OnboardingView.qml
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Onboarding/
|
OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Onboarding/
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,6 +2,9 @@ import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
import Status.Containers
|
||||||
|
import Status.Controls.Navigation
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
@ -15,7 +18,11 @@ Item {
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
RowLayout {}
|
MacTrafficLights {
|
||||||
|
Layout.margins: 13
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutSpacer {}
|
||||||
Label {
|
Label {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "TODO OnboardingWorkflow"
|
text: "TODO OnboardingWorkflow"
|
||||||
|
@ -25,6 +32,6 @@ Item {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
onClicked: root.userLoggedIn()
|
onClicked: root.userLoggedIn()
|
||||||
}
|
}
|
||||||
RowLayout {}
|
LayoutSpacer {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,31 @@ qt6_standard_project_setup()
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status
|
URI Status
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
QML_FILES
|
QML_FILES
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
OUTPUT_DIRECTORY
|
OUTPUT_DIRECTORY
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(qml/Status/Core/Theme)
|
add_subdirectory(qml/Status/Containers)
|
||||||
|
add_subdirectory(qml/Status/Controls)
|
||||||
|
add_subdirectory(qml/Status/Core)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
PRIVATE
|
||||||
|
Qt6::Quick
|
||||||
|
Qt6::Qml
|
||||||
|
|
||||||
|
Assets
|
||||||
|
StatusQ_Containers
|
||||||
|
StatusQ_Controls
|
||||||
|
StatusQ_Core
|
||||||
|
)
|
||||||
|
|
||||||
# QtCreator needs this
|
# QtCreator needs this
|
||||||
set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml;${QML_IMPORT_PATH} CACHE STRING "For QtCreator" FORCE)
|
set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml;${QML_IMPORT_PATH} CACHE STRING "For QtCreator" FORCE)
|
||||||
list(REMOVE_DUPLICATES QML_IMPORT_PATH)
|
list(REMOVE_DUPLICATES QML_IMPORT_PATH)
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Custom container and layouts
|
||||||
|
project(StatusQ_Containers)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.Containers
|
||||||
|
VERSION 1.0
|
||||||
|
|
||||||
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
|
QML_FILES
|
||||||
|
LayoutSpacer.qml
|
||||||
|
|
||||||
|
# Required to suppress "qmllint may not work" warning
|
||||||
|
OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Containers
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
PRIVATE
|
||||||
|
Qt6::Quick
|
||||||
|
Qt6::Qml
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Custom controls
|
||||||
|
project(StatusQ_Controls)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.Controls
|
||||||
|
VERSION 1.0
|
||||||
|
|
||||||
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
|
QML_FILES
|
||||||
|
StatusBanner.qml
|
||||||
|
|
||||||
|
# Required to suppress "qmllint may not work" warning
|
||||||
|
OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Controls
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(Navigation)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
PRIVATE
|
||||||
|
Qt6::Quick
|
||||||
|
Qt6::Qml
|
||||||
|
|
||||||
|
StatusQ_Controls_Navigation
|
||||||
|
)
|
|
@ -0,0 +1,7 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Template for application section content
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import QtQml
|
||||||
|
|
||||||
|
/*!
|
||||||
|
An application section with button and content view
|
||||||
|
*/
|
||||||
|
QtObject {
|
||||||
|
required property NavigationBarButtonComponent navButton
|
||||||
|
required property ApplicationContentView content
|
||||||
|
|
||||||
|
component NavigationBarButtonComponent: NavigationBarButton {}
|
||||||
|
component ApplicationContentViewComponent: ApplicationContentView {}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import QtQml
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Keep general application related stated used by custom controls
|
||||||
|
*/
|
||||||
|
QtObject {
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Controls specialized on user workflows
|
||||||
|
project(StatusQ_Controls_Navigation)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
set_source_files_properties(Style.qml PROPERTIES
|
||||||
|
QT_QML_SINGLETON_TYPE TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.Controls.Navigation
|
||||||
|
VERSION 1.0
|
||||||
|
|
||||||
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
|
QML_FILES
|
||||||
|
ApplicationContentView.qml
|
||||||
|
ApplicationSection.qml
|
||||||
|
ApplicationState.qml
|
||||||
|
MacTrafficLights.qml
|
||||||
|
NavigationBar.qml
|
||||||
|
NavigationBarButton.qml
|
||||||
|
|
||||||
|
# Required to suppress "qmllint may not work" warning
|
||||||
|
OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Controls/Navigation
|
||||||
|
)
|
|
@ -0,0 +1,125 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
import Status.Core.Theme
|
||||||
|
import Status.Assets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property color inactiveColor: Style.isLightTheme ? "#10000000" : "#10FFFFFF"
|
||||||
|
property color inactiveBorderColor: inactiveColor
|
||||||
|
property bool showActive: true
|
||||||
|
|
||||||
|
width: layout.implicitWidth
|
||||||
|
height: layout.implicitHeight
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: layout
|
||||||
|
spacing: 8
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
TrafficLightButton {
|
||||||
|
colors: ButtonColors{
|
||||||
|
pressed: "#B24F47"
|
||||||
|
active: Qt.lighter("#E9685C", 1.07)
|
||||||
|
inactive: root.inactiveColor
|
||||||
|
}
|
||||||
|
borderColors: ButtonColors {
|
||||||
|
pressed: "#943229"
|
||||||
|
active: "#D14C40"
|
||||||
|
inactive: root.inactiveBorderColor
|
||||||
|
}
|
||||||
|
imagePrefix: "close"
|
||||||
|
|
||||||
|
onClicked: Window.window.close()
|
||||||
|
}
|
||||||
|
TrafficLightButton {
|
||||||
|
colors: ButtonColors{
|
||||||
|
pressed: "#878E3B"
|
||||||
|
active: Qt.lighter("#EDB84C", 1.07)
|
||||||
|
inactive: root.inactiveColor
|
||||||
|
}
|
||||||
|
borderColors: ButtonColors {
|
||||||
|
pressed: "#986E29"
|
||||||
|
active: "#D79F3D"
|
||||||
|
inactive: root.inactiveBorderColor
|
||||||
|
}
|
||||||
|
imagePrefix: "minimise"
|
||||||
|
imageScale: 0.64
|
||||||
|
imageVCenterOffset: 0.5
|
||||||
|
|
||||||
|
onClicked: Window.window.showMinimized()
|
||||||
|
}
|
||||||
|
TrafficLightButton {
|
||||||
|
colors: ButtonColors{
|
||||||
|
pressed: "#48943f"
|
||||||
|
active: Qt.lighter("#62C454", 1.06)
|
||||||
|
inactive: root.inactiveColor
|
||||||
|
}
|
||||||
|
borderColors: ButtonColors {
|
||||||
|
pressed: "#357225"
|
||||||
|
active: "#53A73E"
|
||||||
|
inactive: root.inactiveBorderColor
|
||||||
|
}
|
||||||
|
imagePrefix: "maximize"
|
||||||
|
|
||||||
|
onClicked: Window.visibility === Window.FullScreen ? Window.window.showNormal() : Window.window.showFullScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
component ButtonColors: QtObject {
|
||||||
|
required property color pressed
|
||||||
|
required property color active
|
||||||
|
required property color inactive
|
||||||
|
}
|
||||||
|
|
||||||
|
component TrafficLightButton: AbstractButton {
|
||||||
|
id: button
|
||||||
|
|
||||||
|
required property ButtonColors colors
|
||||||
|
required property ButtonColors borderColors
|
||||||
|
required property string imagePrefix
|
||||||
|
property real imageScale: 0.52
|
||||||
|
property real imageVCenterOffset: 0
|
||||||
|
|
||||||
|
implicitWidth: 12
|
||||||
|
implicitHeight: 12
|
||||||
|
hoverEnabled: true
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
contentItem: Image {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: allMouseArea.containsMouse
|
||||||
|
source: Resources.png(`traffic_lights/${imagePrefix}${button.pressed ? "_pressed" : ""}`)
|
||||||
|
anchors.verticalCenterOffset: button.imageVCenterOffset
|
||||||
|
scale: button.imageScale
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
antialiasing: true
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
radius: width / 2
|
||||||
|
opacity: enabled ? 1 : 0.3
|
||||||
|
|
||||||
|
color: button.down ? colors.pressed
|
||||||
|
: Window.active ? colors.active
|
||||||
|
: colors.inactive
|
||||||
|
border.color: button.down ? borderColors.pressed
|
||||||
|
: Window.active ? borderColors.active
|
||||||
|
: borderColors.inactive
|
||||||
|
border.width: Style.isLightTheme ? 0.5 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
z: allMouseArea.z + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: allMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Template for side NavigationBar
|
||||||
|
|
||||||
|
The width is given, the rest of the controls have to adapt to the width
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
implicitWidth: 78
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Template for a NavigationBar square button
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
height: width
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Template for a Navigation Bar section
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import Status.Core
|
||||||
|
import Status.Core.Theme
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmltype StatusBanner
|
||||||
|
\inherits Column
|
||||||
|
\inqmlmodule StatusQ.Controls
|
||||||
|
\since StatusQ.Controls 0.1
|
||||||
|
\brief It displays a banner with a custom text, size and type. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-column.html}{Column}.
|
||||||
|
|
||||||
|
The \c StatusBanner displays a banner with a custom text, size and type (Info, Danger, Success or Warning).
|
||||||
|
|
||||||
|
Example of how the control looks like:
|
||||||
|
\image status_banner.png
|
||||||
|
|
||||||
|
Example of how to use it:
|
||||||
|
|
||||||
|
\qml
|
||||||
|
StatusBanner {
|
||||||
|
width: parent.width
|
||||||
|
visible: popup.userIsBlocked
|
||||||
|
type: StatusBanner.Type.Danger
|
||||||
|
statusText: qsTr("Blocked")
|
||||||
|
}
|
||||||
|
\endqml
|
||||||
|
|
||||||
|
For a list of components available see StatusQ.
|
||||||
|
*/
|
||||||
|
Column {
|
||||||
|
id: statusBanner
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmlproperty string StatusBanner::statusText
|
||||||
|
This property holds the text the banner will display.
|
||||||
|
*/
|
||||||
|
property string statusText
|
||||||
|
/*!
|
||||||
|
\qmlproperty string StatusBanner::type
|
||||||
|
This property holds type of banner. Possible values are:
|
||||||
|
\qml
|
||||||
|
enum Type {
|
||||||
|
Info, // 0
|
||||||
|
Danger, // 1
|
||||||
|
Success, // 2
|
||||||
|
Warning // 3
|
||||||
|
}
|
||||||
|
\endqml
|
||||||
|
*/
|
||||||
|
property int type: StatusBanner.Type.Info
|
||||||
|
/*!
|
||||||
|
\qmlproperty string StatusBanner::textPixels
|
||||||
|
This property holds the pixels size of the text inside the banner.
|
||||||
|
*/
|
||||||
|
property int textPixels: 15
|
||||||
|
/*!
|
||||||
|
\qmlproperty string StatusBanner::statusBannerHeight
|
||||||
|
This property holds the height of the banner rectangle.
|
||||||
|
*/
|
||||||
|
property int statusBannerHeight: 38
|
||||||
|
|
||||||
|
// "private" properties
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property color backgroundColor
|
||||||
|
property color bordersColor
|
||||||
|
property color fontColor
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move it to C++
|
||||||
|
enum Type {
|
||||||
|
Info, // 0
|
||||||
|
Danger, // 1
|
||||||
|
Success, // 2
|
||||||
|
Warning // 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Component definition
|
||||||
|
Rectangle {
|
||||||
|
id: topDiv
|
||||||
|
color: d.bordersColor
|
||||||
|
height: 1
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: box
|
||||||
|
width: parent.width
|
||||||
|
height: statusBanner.statusBannerHeight
|
||||||
|
color: d.backgroundColor
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: statusTxt
|
||||||
|
anchors.fill: parent
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font.pixelSize: statusBanner.textPixels
|
||||||
|
text: statusBanner.statusText
|
||||||
|
color: d.fontColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bottomDiv
|
||||||
|
color: d.bordersColor
|
||||||
|
height: 1
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Behavior
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
when: statusBanner.type === StatusBanner.Type.Info
|
||||||
|
PropertyChanges { target: d; backgroundColor: Theme.palette.primaryColor3}
|
||||||
|
PropertyChanges { target: d; bordersColor: Theme.palette.primaryColor2}
|
||||||
|
PropertyChanges { target: d; fontColor: Theme.palette.primaryColor1}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
when: statusBanner.type === StatusBanner.Type.Danger
|
||||||
|
PropertyChanges { target: d; backgroundColor: Theme.palette.dangerColor3}
|
||||||
|
PropertyChanges { target: d; bordersColor: Theme.palette.dangerColor2}
|
||||||
|
PropertyChanges { target: d; fontColor: Theme.palette.dangerColor1}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
when: statusBanner.type === StatusBanner.Type.Success
|
||||||
|
PropertyChanges { target: d; backgroundColor: Theme.palette.successColor2}
|
||||||
|
PropertyChanges { target: d; bordersColor: Theme.palette.successColor2}
|
||||||
|
PropertyChanges { target: d; fontColor: Theme.palette.successColor1}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
when: statusBanner.type === StatusBanner.Type.Warning
|
||||||
|
PropertyChanges { target: d; backgroundColor: Theme.palette.pinColor3}
|
||||||
|
PropertyChanges { target: d; bordersColor: Theme.palette.pinColor2}
|
||||||
|
PropertyChanges { target: d; fontColor: Theme.palette.pinColor1}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
# QML generic elements used by the other components
|
||||||
|
project(StatusQ_Core)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.Core
|
||||||
|
VERSION 1.0
|
||||||
|
|
||||||
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
|
QML_FILES
|
||||||
|
StatusBaseText.qml
|
||||||
|
|
||||||
|
# Required to suppress "qmllint may not work" warning
|
||||||
|
OUTPUT_DIRECTORY
|
||||||
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Core
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(Theme)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
PRIVATE
|
||||||
|
Qt6::Quick
|
||||||
|
Qt6::Qml
|
||||||
|
|
||||||
|
StatusQ_Core_Theme
|
||||||
|
)
|
|
@ -0,0 +1,31 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import Status.Core.Theme
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmltype StatusBaseText
|
||||||
|
\inherits Text
|
||||||
|
\inqmlmodule StatusQ.Core
|
||||||
|
\since StatusQ.Core
|
||||||
|
\brief Displays multiple lines of text. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-text.html}{Text}.
|
||||||
|
|
||||||
|
The \c StatusBaseText item displays text.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
\qml
|
||||||
|
StatusBaseText {
|
||||||
|
width: 240
|
||||||
|
text: qsTr("Hello World!")
|
||||||
|
font.pixelSize: 24
|
||||||
|
color: Theme.pallete.directColor1
|
||||||
|
}
|
||||||
|
\endqml
|
||||||
|
|
||||||
|
\image status_base_text.png
|
||||||
|
|
||||||
|
For a list of components available see StatusQ.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Text {
|
||||||
|
font.family: Theme.baseFont.name
|
||||||
|
}
|
|
@ -6,22 +6,34 @@ set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
qt6_standard_project_setup()
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
set_source_files_properties(Style.qml PROPERTIES
|
set_source_files_properties(
|
||||||
QT_QML_SINGLETON_TYPE TRUE
|
StatusColors.qml
|
||||||
|
Style.qml
|
||||||
|
Theme.qml
|
||||||
|
Utils.qml
|
||||||
|
|
||||||
|
PROPERTIES
|
||||||
|
QT_QML_SINGLETON_TYPE TRUE
|
||||||
)
|
)
|
||||||
|
|
||||||
qt6_add_qml_module(${PROJECT_NAME}
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
URI Status.Core.Theme
|
URI Status.Core.Theme
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
|
|
||||||
# TODO: temporary until we make qt_target_qml_sources work
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
QML_FILES
|
QML_FILES
|
||||||
|
StatusColors.qml
|
||||||
StatusDarkPalette.qml
|
StatusDarkPalette.qml
|
||||||
StatusDarkTheme.qml
|
StatusDarkTheme.qml
|
||||||
|
StatusLayouting.qml
|
||||||
StatusLightPalette.qml
|
StatusLightPalette.qml
|
||||||
StatusLightTheme.qml
|
StatusLightTheme.qml
|
||||||
StatusPalette.qml
|
StatusPalette.qml
|
||||||
StatusTheme.qml
|
StatusTheme.qml
|
||||||
Style.qml
|
Style.qml
|
||||||
|
Theme.qml
|
||||||
|
Utils.qml
|
||||||
|
|
||||||
# Required to suppress "qmllint may not work" warning
|
# Required to suppress "qmllint may not work" warning
|
||||||
OUTPUT_DIRECTORY
|
OUTPUT_DIRECTORY
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Core/Theme
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Status/Core/Theme
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQml
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Define the base color values
|
||||||
|
*/
|
||||||
|
QtObject {
|
||||||
|
readonly property color black: '#000000'
|
||||||
|
readonly property color white: '#FFFFFF'
|
||||||
|
|
||||||
|
readonly property color blue: '#4360DF'
|
||||||
|
readonly property color blue2: '#2946C4'
|
||||||
|
readonly property color blue3: '#88B0FF'
|
||||||
|
readonly property color blue4: '#869EFF'
|
||||||
|
readonly property color blue5: '#AAC6FF'
|
||||||
|
readonly property color blue6: '#ECEFFC'
|
||||||
|
|
||||||
|
readonly property color brown: '#8B3131'
|
||||||
|
readonly property color brown2: '#9B832F'
|
||||||
|
readonly property color brown3: '#AD4343'
|
||||||
|
|
||||||
|
readonly property color cyan: '#51D0F0'
|
||||||
|
|
||||||
|
readonly property color graphite: '#212121'
|
||||||
|
readonly property color graphite2: '#252525'
|
||||||
|
readonly property color graphite3: '#2C2C2C'
|
||||||
|
readonly property color graphite4: '#373737'
|
||||||
|
readonly property color graphite5: '#909090'
|
||||||
|
|
||||||
|
readonly property color green: '#4EBC60'
|
||||||
|
readonly property color green2: '#7CDA00'
|
||||||
|
readonly property color green3: '#60C370'
|
||||||
|
readonly property color green4: '#93DB33'
|
||||||
|
readonly property color green5: '#9EA85D'
|
||||||
|
readonly property color green6: '#AFB551'
|
||||||
|
|
||||||
|
readonly property color grey: '#F0F2F5'
|
||||||
|
readonly property color grey2: '#F6F8FA'
|
||||||
|
readonly property color grey3: '#E9EDF1'
|
||||||
|
readonly property color grey4: '#EEF2F5'
|
||||||
|
readonly property color grey5: '#939BA1'
|
||||||
|
|
||||||
|
readonly property color moss: '#26A69A'
|
||||||
|
readonly property color moss2: '#10A88E'
|
||||||
|
|
||||||
|
readonly property color orange: '#FE8F59'
|
||||||
|
readonly property color orange2: '#FF9F0F'
|
||||||
|
readonly property color orange3: '#FFA67B'
|
||||||
|
readonly property color orange4: '#FE8F59'
|
||||||
|
|
||||||
|
readonly property color purple: '#887AF9'
|
||||||
|
|
||||||
|
readonly property color red: '#FF2D55'
|
||||||
|
readonly property color red2: '#FA6565'
|
||||||
|
readonly property color red3: '#FF5C7B'
|
||||||
|
|
||||||
|
readonly property color turquoise: '#0DA4C9'
|
||||||
|
readonly property color turquoise2: '#07BCE9'
|
||||||
|
readonly property color turquoise3: '#7BE5FF'
|
||||||
|
readonly property color turquoise4: '#0DA4C9'
|
||||||
|
|
||||||
|
readonly property color violet: '#D37EF4'
|
||||||
|
|
||||||
|
readonly property color yellow: '#FFCA0F'
|
||||||
|
readonly property color yellow2: '#EAD27B'
|
||||||
|
}
|
|
@ -1,5 +1,23 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
StatusPalette {
|
StatusPalette {
|
||||||
|
baseColor3: StatusColors.graphite3
|
||||||
|
|
||||||
|
appBackgroundColor: baseColor3
|
||||||
|
|
||||||
|
dangerColor1: StatusColors.red3
|
||||||
|
dangerColor2: Utils.addAlphaTo(StatusColors.red3, 0.3)
|
||||||
|
dangerColor3: Utils.addAlphaTo(StatusColors.red3, 0.2)
|
||||||
|
|
||||||
|
successColor1: StatusColors.green3
|
||||||
|
successColor2: Utils.addAlphaTo(StatusColors.green3, 0.2)
|
||||||
|
|
||||||
|
mentionColor1: StatusColors.turquoise3
|
||||||
|
mentionColor2: Utils.addAlphaTo(StatusColors.turquoise4, 0.3)
|
||||||
|
mentionColor3: Utils.addAlphaTo(StatusColors.turquoise4, 0.2)
|
||||||
|
mentionColor4: Utils.addAlphaTo(StatusColors.turquoise4, 0.1)
|
||||||
|
|
||||||
|
pinColor1: StatusColors.orange3
|
||||||
|
pinColor2: Utils.addAlphaTo(StatusColors.orange4, 0.2)
|
||||||
|
pinColor3: Utils.addAlphaTo(StatusColors.orange4, 0.1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
StatusTheme {
|
StatusTheme {
|
||||||
readonly property string name: "dark"
|
name: "dark"
|
||||||
readonly property StatusPalette palette: StatusDarkPalette {}
|
palette: StatusDarkPalette {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import QtQml
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
readonly property int titleBarHeight: 25
|
||||||
|
readonly property real appCornersRadius: 5
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,27 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
StatusPalette {
|
StatusPalette {
|
||||||
|
baseColor3: StatusColors.grey3
|
||||||
|
|
||||||
|
appBackgroundColor: "white"
|
||||||
|
|
||||||
|
primaryColor1: StatusColors.blue
|
||||||
|
primaryColor2: Utils.addAlphaTo(StatusColors.blue, 0.2)
|
||||||
|
primaryColor3: Utils.addAlphaTo(StatusColors.blue, 0.1)
|
||||||
|
|
||||||
|
dangerColor1: StatusColors.red
|
||||||
|
dangerColor2: Utils.addAlphaTo(StatusColors.red, 0.2)
|
||||||
|
dangerColor3: Utils.addAlphaTo(StatusColors.red, 0.1)
|
||||||
|
|
||||||
|
successColor1: StatusColors.green
|
||||||
|
successColor2: Utils.addAlphaTo(StatusColors.green, 0.1)
|
||||||
|
|
||||||
|
mentionColor1: StatusColors.turquoise
|
||||||
|
mentionColor2: Utils.addAlphaTo(StatusColors.turquoise2, 0.3)
|
||||||
|
mentionColor3: Utils.addAlphaTo(StatusColors.turquoise2, 0.2)
|
||||||
|
mentionColor4: Utils.addAlphaTo(StatusColors.turquoise2, 0.1)
|
||||||
|
|
||||||
|
pinColor1: StatusColors.orange
|
||||||
|
pinColor2: Utils.addAlphaTo(StatusColors.orange2, 0.2)
|
||||||
|
pinColor3: Utils.addAlphaTo(StatusColors.orange2, 0.1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
StatusTheme {
|
StatusTheme {
|
||||||
readonly property string name: "light"
|
name: "light"
|
||||||
readonly property StatusPalette palette: StatusLightPalette {}
|
|
||||||
|
palette: StatusLightPalette {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,32 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Base interface for the palette requirements of presentation layer
|
||||||
|
*/
|
||||||
QtObject {
|
QtObject {
|
||||||
}
|
// Generic colors defined by the design style
|
||||||
|
required property color baseColor3
|
||||||
|
|
||||||
|
// Application base colors
|
||||||
|
required property color appBackgroundColor
|
||||||
|
|
||||||
|
required property color primaryColor1
|
||||||
|
required property color primaryColor2
|
||||||
|
required property color primaryColor3
|
||||||
|
|
||||||
|
required property color dangerColor1
|
||||||
|
required property color dangerColor2
|
||||||
|
required property color dangerColor3
|
||||||
|
|
||||||
|
required property color successColor1
|
||||||
|
required property color successColor2
|
||||||
|
|
||||||
|
required property color mentionColor1
|
||||||
|
required property color mentionColor2
|
||||||
|
required property color mentionColor3
|
||||||
|
required property color mentionColor4
|
||||||
|
|
||||||
|
required property color pinColor1
|
||||||
|
required property color pinColor2
|
||||||
|
required property color pinColor3
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Base interface for the look and feel requirements of the presentation layer
|
||||||
|
*/
|
||||||
Item {
|
Item {
|
||||||
required property string name
|
required property string name
|
||||||
required property StatusPalette palette
|
required property StatusPalette palette
|
||||||
|
|
|
@ -1,27 +1,17 @@
|
||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
//import QtQuick.Controls.Universal
|
|
||||||
|
|
||||||
QtObject {
|
/*!
|
||||||
property StatusTheme theme: lightTheme
|
The main entry point into presentation layer customization
|
||||||
property StatusPalette palette: theme.palette
|
*/
|
||||||
readonly property StatusTheme lightTheme: StatusLightTheme {}
|
Item {
|
||||||
readonly property StatusTheme darkTheme: StatusDarkTheme {}
|
readonly property StatusPalette palette: Theme.palette
|
||||||
|
readonly property StatusTheme theme: Theme.current
|
||||||
|
|
||||||
property var changeTheme: function (palette, isCurrentSystemThemeDark) {
|
readonly property alias geometry: geometryObject
|
||||||
switch (theme) {
|
|
||||||
case Universal.Light:
|
StatusLayouting {
|
||||||
theme = lightTheme;
|
id: geometryObject
|
||||||
break;
|
|
||||||
case Universal.Dark:
|
|
||||||
theme = darkTheme;
|
|
||||||
break;
|
|
||||||
case Universal.System:
|
|
||||||
current = isCurrentSystemThemeDark? darkTheme : lightTheme;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.warning('Unknown theme. Valid themes are "light" and "dark"')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import QtQuick.Controls.Universal 2.12
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Convenience type for easy access to StatusTheme
|
||||||
|
*/
|
||||||
|
QtObject {
|
||||||
|
property StatusTheme current: lightTheme
|
||||||
|
property bool isLightTheme: current === lightTheme
|
||||||
|
readonly property StatusTheme lightTheme: StatusLightTheme {}
|
||||||
|
readonly property StatusTheme darkTheme: StatusDarkTheme {}
|
||||||
|
|
||||||
|
property QtObject baseFont: FontLoader {
|
||||||
|
source: "qrc:/Status/FontsAssets/Inter/Inter-Regular.otf"
|
||||||
|
}
|
||||||
|
|
||||||
|
property StatusPalette palette: current.palette
|
||||||
|
|
||||||
|
property var changeTheme: function (universalTheme, isCurrentSystemThemeDark) {
|
||||||
|
switch (universalTheme) {
|
||||||
|
case Universal.Light:
|
||||||
|
current = lightTheme;
|
||||||
|
break;
|
||||||
|
case Universal.Dark:
|
||||||
|
current = darkTheme;
|
||||||
|
break;
|
||||||
|
case Universal.System:
|
||||||
|
current = isCurrentSystemThemeDark? darkTheme : lightTheme;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warning('Unknown theme. Valid themes are "light" and "dark"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Helper functions for colors and sizes transformations
|
||||||
|
|
||||||
|
\note Consider moving some heavy used functions to C++ for type optimizations.
|
||||||
|
\note Consider that Qt6 transpile QML files in C++ which are then optimized by compiler;
|
||||||
|
however, types like \c QVariant is providing limited options compared to native types
|
||||||
|
*/
|
||||||
|
QtObject {
|
||||||
|
function addAlphaTo(baseColor, alpha) {
|
||||||
|
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, alpha)
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,10 +35,12 @@ target_include_directories(${PROJECT_NAME}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(TestHelpers)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
Qt6::QuickTest
|
Qt6::QuickTest
|
||||||
Qt6::Qml
|
Qt6::Qml
|
||||||
Qt6::Quick
|
Qt6::Quick
|
||||||
|
|
||||||
|
Status::TestHelpers
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Base library. Expect most of the module libraries to depend on it
|
||||||
|
#
|
||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
|
||||||
|
project(TestHelpers
|
||||||
|
VERSION 0.1.0
|
||||||
|
LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(GTest REQUIRED)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Quick Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.TestHelpers
|
||||||
|
VERSION 1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/IOTestHelpers.h
|
||||||
|
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/IOTestHelpers.cpp
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
Qt6::Quick
|
||||||
|
Qt6::Qml
|
||||||
|
|
||||||
|
PRIVATE
|
||||||
|
GTest::gtest_main
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(Status::TestHelpers ALIAS TestHelpers)
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "IOTestHelpers.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace Status::Testing {
|
||||||
|
|
||||||
|
fs::path createTestFolder(const std::string& testName)
|
||||||
|
{
|
||||||
|
auto t = std::time(nullptr);
|
||||||
|
auto tm = *std::localtime(&t);
|
||||||
|
std::ostringstream timeOss;
|
||||||
|
timeOss << std::put_time(&tm, "%d-%m-%Y_%H-%M-%S");
|
||||||
|
auto tmpPath = fs::path(testing::TempDir())/(testName + "-" + timeOss.str());
|
||||||
|
fs::create_directories(tmpPath);
|
||||||
|
return tmpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoCleanTempTestDir::AutoCleanTempTestDir(const std::string &testName)
|
||||||
|
: m_testFolder(createTestFolder(testName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoCleanTempTestDir::~AutoCleanTempTestDir()
|
||||||
|
{
|
||||||
|
fs::remove_all(m_testFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::filesystem::path& AutoCleanTempTestDir::testFolder()
|
||||||
|
{
|
||||||
|
return m_testFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Status::Testing {
|
||||||
|
|
||||||
|
class AutoCleanTempTestDir {
|
||||||
|
public:
|
||||||
|
/// Creates a temporary folder to be used in tests. The folder content's will
|
||||||
|
/// be removed when out of scope
|
||||||
|
explicit AutoCleanTempTestDir(const std::string& testName);
|
||||||
|
~AutoCleanTempTestDir();
|
||||||
|
|
||||||
|
const std::filesystem::path& testFolder();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::filesystem::path m_testFolder;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace Status::Testing {
|
||||||
|
|
||||||
std::weak_ptr<QString> MonitorQtOutput::m_qtMessageOutputForSharing;
|
std::weak_ptr<QString> MonitorQtOutput::m_qtMessageOutputForSharing;
|
||||||
std::mutex MonitorQtOutput::m_mutex;
|
std::mutex MonitorQtOutput::m_mutex;
|
||||||
QtMessageHandler MonitorQtOutput::m_previousHandler = nullptr;
|
QtMessageHandler MonitorQtOutput::m_previousHandler = nullptr;
|
||||||
|
@ -66,3 +68,5 @@ MonitorQtOutput::restartCapturing()
|
||||||
m_previousHandler = prev;
|
m_previousHandler = prev;
|
||||||
m_start = m_thisMessageOutput->length();
|
m_start = m_thisMessageOutput->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace Status::Testing {
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Monitor output for tests and declaratively control message handler availability
|
/// \brief Monitor output for tests and declaratively control message handler availability
|
||||||
///
|
///
|
||||||
|
@ -41,3 +43,5 @@ private:
|
||||||
std::shared_ptr<QString> m_thisMessageOutput;
|
std::shared_ptr<QString> m_thisMessageOutput;
|
||||||
int m_start = 0;
|
int m_start = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
target_include_directories(${PROJECT_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(TestHelpers)
|
|
|
@ -1,8 +0,0 @@
|
||||||
target_sources(${PROJECT_NAME}
|
|
||||||
PRIVATE
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.h
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.cpp
|
|
||||||
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Temporary library not to duplicate resources
|
||||||
|
# TODO: refactor it when switching to C++ code into Assets resource library linked or embed with the app
|
||||||
|
#
|
||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
|
||||||
|
project(FontAssets
|
||||||
|
VERSION 0.1.0
|
||||||
|
LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS true)
|
||||||
|
|
||||||
|
find_package(Qt6 ${STATUS_QT_VERSION} COMPONENTS Qml REQUIRED)
|
||||||
|
qt6_standard_project_setup()
|
||||||
|
|
||||||
|
qt6_add_qml_module(${PROJECT_NAME}
|
||||||
|
URI Status.FontsAssets
|
||||||
|
VERSION 1.0
|
||||||
|
# TODO: temporary until we make qt_target_qml_sources work
|
||||||
|
RESOURCES
|
||||||
|
Inter/Inter-Regular.otf
|
||||||
|
|
||||||
|
RESOURCE_PREFIX ""
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
PRIVATE
|
||||||
|
Qt6::Qml
|
||||||
|
)
|
Loading…
Reference in New Issue