Commit ac508832 authored by Tinja Paavoseppä's avatar Tinja Paavoseppä
Browse files

Add GUI for configuring build. Still largely WIP.

Wizard UI for configuring the build.
TODO: icons for checkbox, create data containers for stuff like component
dependencies, error handling...
parent 3315517e
......@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.16)
project(UnixsocketPlayground2 VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
......@@ -11,15 +12,20 @@ qt_add_executable(appUnixsocketPlayground2
main.cpp
qunixsockettotcpserver.h qunixsockettotcpserver.cpp
qunixsockettotcpbridge.h qunixsockettotcpbridge.cpp
qhttprequest.h qhttprequest.cpp
qhttprequest.h qhttprequest.cpp buildparams.h buildparams.cpp
qml.qrc
)
qt_add_qml_module(appUnixsocketPlayground2
URI UnixsocketPlayground2
VERSION 1.0
QML_FILES main.qml
QML_FILES main.qml DirSelectionItem.qml
PageStart.qml PageModules.qml Header.qml
PageBuilding.qml Footer.qml PageSummary.qml
)
set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/imports CACHE STRING "" FORCE)
set_target_properties(appUnixsocketPlayground2 PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
......
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
RowLayout {
id: root
property alias text: label.text
property alias input: textField.text
signal buttonClicked()
spacing: 8
Label {
id: label
Layout.fillWidth: true
}
TextField {
id: textField
}
Button {
id: button
text: qsTr("Browse")
onClicked: root.buttonClicked()
}
}
import QtQuick
import QtQuick.Controls
import Theme
Item {
id: root
property int currentIndex
property int pageCount
signal back()
signal next()
signal quit()
signal build()
Rectangle {
id: bottomDivider
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
color: Theme.colorLight
height: 1
}
Row {
id: rowButtons
anchors.right: parent.right
anchors.bottom: parent.bottom
padding: 12
spacing: 8
Button {
id: buttonBack
text: qsTr("Back")
enabled: currentIndex > 0 && currentIndex < pageCount - 1
onClicked: back()
}
Button {
id: buttonNext
focus: true
enabled: currentIndex < pageCount - 1
onClicked: {
if (currentIndex === pageCount - 2) {
build()
buttonQuit.focus = true
}
next()
}
states: [
State {
when: currentIndex < pageCount - 2
PropertyChanges {
target: buttonNext
text: qsTr("Next")
}
},
State {
when: currentIndex >= pageCount - 2
PropertyChanges {
target: buttonNext
text: qsTr("Build")
}
}
]
}
Button {
id: buttonQuit
text: qsTr("Quit")
onClicked: quit()
}
}
}
import QtQuick
import QtQuick.Controls
Item {
id: header
height: qtIcon.height + 24
Label {
text: "Let's build Qt!"
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 12
}
Image {
id: qtIcon
source: "qrc:/icons/qt_logo_green_64x64px.png"
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 12
}
Rectangle {
id: divider
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
color: "#f3f3f4"
height: 1
}
}
import QtQuick
import QtQuick.Controls
Item {
id: pageBuilding
Label {
id: title
text: "Building..."
}
Label {
// TODO show details, errors etc
id: details
text: "Everything going great!"
anchors.top: title.bottom
anchors.topMargin: 24
}
ProgressBar {
id: progressBar
indeterminate: true
width: 500
anchors.top: details.bottom
anchors.left: parent.left
anchors.topMargin: 24
}
}
import QtQuick
import QtQuick.Controls
import UnixsocketPlayground2
Item {
id: root
property var moduleNames: ["qtbase", "qtdeclarative", "qtremoteobjects", "qt5compat", "qttools",
"qtimageformats", "qtquicktimeline", "qtshadertools", "qtmultimedia"]
property var requiredModules: [] // TODO add required submodules to component
property BuildParams buildParams: null
onBuildParamsChanged: {
if (buildParams)
setModules()
}
Label {
id: label
text: qsTr("Choose what modules you would like to include.")
+ qsTr(" Some modules may be selected due to being required by add-ons selected in the previous page")
width: parent.width
}
ScrollView {
id: scrollView
anchors.left: parent.left
anchors.top: label.bottom
anchors.topMargin: 28
anchors.right: parent.horizontalCenter
height: 400
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
Column {
id: moduleCheckBoxes
spacing: 8
Repeater {
id: repeater
CheckBox {
text: modelData
enabled: !isModuleRequired(modelData)
checked: !enabled
}
}
}
}
Label {
id: labelBranch
text: qsTr("Choose the branch to checkout:")
anchors.left: scrollView.right
anchors.leftMargin: 12
anchors.top: label.bottom
anchors.topMargin: 28
}
TextField {
id: fieldBranch
anchors.left: scrollView.right
anchors.leftMargin: 12
anchors.top: labelBranch.bottom
anchors.topMargin: 8
anchors.right: parent.right
text: "dev"
}
CheckBox {
id: chbSubmodulesUseSameBranch
anchors.left: scrollView.right
anchors.leftMargin: 12
anchors.top: fieldBranch.bottom
anchors.topMargin: 24
text: "Use the same branch for submodules"
}
function isModuleRequired(moduleName) {
for (var i = 0; i < requiredModules.length; i++) {
if (requiredModules[i] === moduleName) {
return true
}
}
return false
}
function setModules() {
repeater.model = []
requiredModules = []
requiredModules.push("qtbase")
if (buildParams.isComponentSelected("Qt Android Automotive")) {
for (var i = 1; i < moduleNames.length - 1; i++) {
requiredModules.push(moduleNames[i])
}
}
repeater.model = moduleNames
}
}
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt.labs.platform
import UnixsocketPlayground2
Item {
id: root
property url qtDir: qtDirSelection.input
property url sdkDir: sdkSelection.input
property url ndkDir: ndkSelection.input
property BuildParams buildParams: null
onBuildParamsChanged: console.log("boo " + buildParams)
Label {
id: label
text: qsTr("Choose what to build and where to install.")
anchors.left: parent.left
anchors.right: parent.right
}
DirSelectionItem {
id: qtDirSelection
text: qsTr("Qt installation folder:")
anchors.left: parent.left
anchors.top: label.bottom
anchors.right: parent.right
anchors.topMargin: 28
onButtonClicked: {
folderDialog.currentItem = this
folderDialog.open()
}
}
Column {
id: qtVariantsCheckboxes
anchors.left: parent.left
anchors.top: qtDirSelection.bottom
anchors.topMargin: 28
anchors.right: parent.horizontalCenter
anchors.rightMargin: 12
height: 8 * 32
spacing: 8
Label {
text: qsTr("Choose which components you would like to build and install.")
width: parent.width
}
ButtonGroup {
id: childGroup
exclusive: false
checkState: chbAndroid.checkState
}
CheckBox {
text: "GCC 64"
onCheckedChanged: componenSelectedChanged(text, checked)
}
CheckBox {
id: chbAndroid
text: "Android"
checkState: childGroup.checkState
}
CheckBox {
text: "arm64 v8a"
leftPadding: 8
visible: chbAndroid.checkState === Qt.Checked
|| chbAndroid.checkState === Qt.PartiallyChecked
ButtonGroup.group: childGroup
onCheckedChanged: componenSelectedChanged(text, checked)
}
CheckBox {
text: "arm7"
leftPadding: 8
visible: chbAndroid.checkState === Qt.Checked
|| chbAndroid.checkState === Qt.PartiallyChecked
ButtonGroup.group: childGroup
onCheckedChanged: componenSelectedChanged(text, checked)
}
CheckBox {
text: "x86"
leftPadding: 8
visible: chbAndroid.checkState === Qt.Checked
|| chbAndroid.checkState === Qt.PartiallyChecked
ButtonGroup.group: childGroup
onCheckedChanged: componenSelectedChanged(text, checked)
}
CheckBox {
text: "x86 64"
leftPadding: 8
visible: chbAndroid.checkState === Qt.Checked
|| chbAndroid.checkState === Qt.PartiallyChecked
ButtonGroup.group: childGroup
onCheckedChanged: componenSelectedChanged(text, checked)
}
CheckBox {
text: "Qt Android Automotive"
enabled: chbAndroid.checkState === Qt.Checked
|| chbAndroid.checkState === Qt.PartiallyChecked
onCheckedChanged: componenSelectedChanged(text, checked)
}
}
Label {
id: labelAndroidDirs
anchors.top: qtVariantsCheckboxes.bottom
anchors.topMargin: 32
text: qsTr("Choose the location of Android SDK and NDK root folders.")
enabled: chbAndroid.checkState !== Qt.Unchecked
}
DirSelectionItem {
id: sdkSelection
text: qsTr("Android SDK root folder:")
anchors.left: parent.left
anchors.top: labelAndroidDirs.bottom
anchors.right: parent.right
anchors.topMargin: 24
enabled: chbAndroid.checkState !== Qt.Unchecked
onButtonClicked: {
folderDialog.currentItem = this
folderDialog.open()
}
}
DirSelectionItem {
id: ndkSelection
text: qsTr("Android NDK root folder:")
anchors.left: parent.left
anchors.top: sdkSelection.bottom
anchors.right: parent.right
anchors.topMargin: 18
enabled: chbAndroid.checkState !== Qt.Unchecked
onButtonClicked: {
folderDialog.currentItem = this
folderDialog.open()
}
}
function componenSelectedChanged(componentName, selected) {
if (selected)
buildParams.addComponent(componentName)
else
buildParams.removeComponent(componentName)
}
FolderDialog {
id: folderDialog
property DirSelectionItem currentItem
onAccepted: {
currentItem.input = folder
}
}
}
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import Theme
import UnixsocketPlayground2
Item {
id: pageSummary
property var variantsToBuild: ["Qt GCC", "Qt for Android", "Qt Android Automotive"]
property var modulesToBuild: ["my bow", "my sword", "and my axe!"]
property BuildParams buildParams: null
onBuildParamsChanged: {
if (buildParams) {
if (buildParams.isComponentSelected("Qt Android Automotive")) {
gitCredentials.enabled = true
}
}
}
Item {
id: gitCredentials
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 160
enabled: true // TODO if contains QTAA
visible: enabled // TODO a Loader
Label {
id: labelGitCredentials
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
text: qsTr("You have chosen to build some components that have restricted access. ") +
qsTr("Please enter your credentials for checking out the repositories. ") +
qsTr("Make sure you have set up your account according to these instructions: ") +
qsTr("<a href=\"https://wiki.qt.io/Setting_up_Gerrit\">Setting up Gerrit</a>")
linkColor: Theme.colorHighlight
onLinkActivated: (link)=> Qt.openUrlExternally(link)
}
RowLayout {
id: rowUsername
anchors.left: parent.left
anchors.top: labelGitCredentials.bottom
anchors.topMargin: 24
anchors.right: parent.right
anchors.rightMargin: 104
Label {
id: labelUsername
text: "Gerrit username:"
Layout.fillWidth: true
}
TextField {
id: username
}
}
DirSelectionItem {
id: gitKey
anchors.left: parent.left
anchors.top: rowUsername.bottom
anchors.topMargin: 18
anchors.right: parent.right
text: qsTr("Git private key location:")
onButtonClicked: {
fileDialog.open()
}
}
}
Label {
id: label
anchors.left: parent.left
anchors.top: gitCredentials.bottom
anchors.topMargin: 28
anchors.right: parent.horizontalCenter
text: "You will be building the following Qt components:"
}
Column {
anchors.left: parent.left
anchors.top: label.bottom
anchors.topMargin: 12
anchors.right: parent.horizontalCenter
anchors.bottom: parent.bottom
Repeater {
model: buildParams ? buildParams.selectedComponents : []
Label {
text: modelData
}
}
}
Label {
id: labelModules
anchors.left: parent.horizontalCenter
anchors.leftMargin: 24
anchors.top: gitCredentials.bottom
anchors.topMargin: 28
anchors.right: parent.right
text: "Submodules:"
}
ListView {
anchors.left: parent.horizontalCenter
anchors.leftMargin: 24
anchors.top: label.bottom
anchors.topMargin: 12
anchors.right: parent.right
anchors.bottom: parent.bottom
model: modulesToBuild
delegate: Label {
text: modelData
}
}
FileDialog {
id: fileDialog
onAccepted: gitKey.input = selectedFile
}
}
#include "buildparams.h"
BuildParams::BuildParams(QObject *parent)
: QObject{parent}
{
}
void BuildParams::addComponent(const QString &component)
{
if (!m_selectedComponents.contains(component)) {
m_selectedComponents.append(component);
emit selectedComponentsChanged();
}
}
void BuildParams::addSubmodule(const QString &submodule)
{
if (!m_selectedSubmodules.contains(submodule)) {
m_selectedSubmodules.append(submodule);
emit selectedSubmodulesChanged();
}
}
void BuildParams::removeComponent(const QString &component)
{
if (m_selectedComponents.removeOne(component))
emit selectedComponentsChanged();