qml: styling updates qt6.10

This commit is contained in:
Sander van Grieken
2026-02-20 13:36:08 +01:00
parent 42472a1e94
commit cdb5c0b86d
40 changed files with 209 additions and 175 deletions
@@ -109,6 +109,7 @@ Pane {
verticalPadding: 0
horizontalPadding: 0
bottomPadding: 1
background: PaneInsetBackground {}
ElListView {
@@ -249,6 +250,8 @@ Pane {
ButtonContainer {
Layout.fillWidth: true
headerComponent: null
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
@@ -37,6 +37,7 @@ ElDialog {
InfoTextArea {
Layout.fillWidth: true
Layout.margins: constants.paddingMedium
backgroundColor: constants.darkerDialogBackground
text: bip39RecoveryListModel.state == Bip39RecoveryListModel.Scanning
? qsTr('Scanning for accounts...')
@@ -65,7 +66,9 @@ ElDialog {
verticalPadding: 0
horizontalPadding: 0
background: PaneInsetBackground {}
background: PaneInsetBackground {
baseColor: constants.darkerDialogBackground
}
ColumnLayout {
spacing: 0
+2 -3
View File
@@ -63,9 +63,6 @@ Pane {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: constants.paddingLarge
Layout.bottomMargin: constants.paddingLarge
Layout.leftMargin: constants.paddingMedium
Layout.rightMargin: constants.paddingMedium
verticalPadding: 0
horizontalPadding: 0
@@ -121,6 +118,8 @@ Pane {
ButtonContainer {
Layout.fillWidth: true
headerComponent: null
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
+2 -1
View File
@@ -29,9 +29,10 @@ Item {
property color mutedForeground: 'gray' //Qt.lighter(Material.background, 2)
property color darkerBackground: Qt.darker(Material.background, 1.20)
property color lighterBackground: Qt.lighter(Material.background, 1.10)
property color darkerDialogBackground: Qt.darker(Material.dialogColor, 1.20)
property color highlightBackground: Qt.lighter(Material.background, 1.30)
property color dialogColor: Material.dialogColor
property color seedTextAreaBackground: Qt.darker(darkerDialogBackground, 1.20)
property color notificationBackground: Qt.lighter(Material.background, 1.5)
property color colorCredit: "#ff80ff80"
@@ -76,7 +76,7 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
id: buttons
Layout.fillWidth: true
@@ -88,7 +88,7 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
FlatButton {
@@ -458,7 +458,7 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
FlatButton {
@@ -46,8 +46,13 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
function beforeLayout() {
if (!dialog.text) {
headerComponent = null
}
}
FlatButton {
Layout.fillWidth: true
@@ -50,6 +50,7 @@ ElDialog {
Layout.fillHeight: true
Layout.leftMargin: constants.paddingLarge
Layout.rightMargin: constants.paddingLarge
Layout.bottomMargin: constants.paddingLarge
TextHighlightPane {
Layout.fillWidth: true
@@ -65,6 +66,7 @@ ElDialog {
RowLayout {
Layout.fillWidth: true
Layout.topMargin: constants.paddingLarge
ElTextArea {
id: relays_ta
Layout.fillWidth: true
@@ -96,14 +98,18 @@ ElDialog {
}
}
FlatButton {
DialogButtonContainer {
Layout.fillWidth: true
text: qsTr('Ok')
enabled: valid
icon.source: '../../icons/confirmed.png'
onClicked: {
Config.nostrRelays = clean_array(relays_ta.text).join(",")
rootItem.close()
FlatButton {
Layout.fillWidth: true
text: qsTr('Ok')
enabled: valid
icon.source: '../../icons/confirmed.png'
onClicked: {
Config.nostrRelays = clean_array(relays_ta.text).join(",")
rootItem.close()
}
}
}
}
@@ -41,23 +41,20 @@ ElDialog {
InfoTextArea {
id: notice
Layout.fillWidth: true
Layout.bottomMargin: constants.paddingSmall
text: Daemon.singlePasswordEnabled || isStartup
? qsTr('Please enter password')
: qsTr('Wallet <b>%1</b> requires password to unlock').arg(name)
iconStyle: InfoTextArea.IconStyle.Warn
Layout.fillWidth: true
}
Label {
text: qsTr('Password')
Layout.fillWidth: true
color: Material.accentColor
compact: true
iconStyle: InfoTextArea.IconStyle.Info
backgroundColor: constants.darkerDialogBackground
}
PasswordField {
id: password
Layout.fillWidth: true
Layout.leftMargin: constants.paddingXLarge
placeholderText: qsTr('Password')
onTextChanged: {
unlockButton.enabled = true
@@ -77,16 +74,19 @@ ElDialog {
}
}
FlatButton {
id: unlockButton
DialogButtonContainer {
Layout.fillWidth: true
icon.source: '../../icons/unlock.png'
text: qsTr("Unlock")
onClicked: {
unlock()
FlatButton {
id: unlockButton
Layout.fillWidth: true
icon.source: '../../icons/unlock.png'
text: qsTr("Unlock")
onClicked: {
unlock()
}
}
}
}
function unlock() {
@@ -32,13 +32,17 @@ ElDialog {
Item { Layout.fillHeight: true; Layout.preferredWidth: 1 }
FlatButton {
DialogButtonContainer {
Layout.fillWidth: true
text: qsTr('Ok')
icon.source: '../../icons/confirmed.png'
onClicked: {
Network.proxy = proxyconfig.toProxyDict()
rootItem.close()
FlatButton {
Layout.fillWidth: true
text: qsTr('Ok')
icon.source: '../../icons/confirmed.png'
onClicked: {
Network.proxy = proxyconfig.toProxyDict()
rootItem.close()
}
}
}
}
@@ -95,7 +95,7 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
FlatButton {
@@ -143,7 +143,7 @@ ElDialog {
}
ButtonContainer {
DialogButtonContainer {
id: buttons
Layout.fillWidth: true
+1 -1
View File
@@ -66,7 +66,7 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
FlatButton {
@@ -26,27 +26,31 @@ ElDialog {
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: constants.paddingLarge
Layout.rightMargin: constants.paddingLarge
ServerConfig {
id: serverconfig
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: constants.paddingLarge
Layout.rightMargin: constants.paddingLarge
}
}
FlatButton {
DialogButtonContainer {
Layout.fillWidth: true
text: qsTr('Ok')
enabled: serverconfig.addressValid
icon.source: '../../icons/confirmed.png'
onClicked: {
let auto_connect = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Autoconnect
let server = serverconfig.address
let one_server = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Single
Network.setServerParameters(server, auto_connect, one_server)
rootItem.close()
FlatButton {
Layout.fillWidth: true
text: qsTr('Ok')
enabled: serverconfig.addressValid
icon.source: '../../icons/confirmed.png'
onClicked: {
let auto_connect = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Autoconnect
let server = serverconfig.address
let one_server = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Single
Network.setServerParameters(server, auto_connect, one_server)
rootItem.close()
}
}
}
}
@@ -179,8 +179,9 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
+1 -1
View File
@@ -282,7 +282,7 @@ ElDialog {
Item { Layout.fillHeight: true; Layout.preferredWidth: 1 }
ButtonContainer {
DialogButtonContainer {
Layout.columnSpan: 2
Layout.fillWidth: true
FlatButton {
+17 -10
View File
@@ -60,6 +60,8 @@ ElDialog {
Layout.fillWidth: true
TextHighlightPane {
Layout.fillWidth: true
backgroundColor: constants.darkerDialogBackground
Label {
text: qsTr('Enter the list of private keys to sweep into this wallet')
width: parent.width
@@ -133,24 +135,29 @@ ElDialog {
iconStyle: InfoTextArea.IconStyle.Warn
Layout.fillWidth: true
Layout.margins: constants.paddingMedium
backgroundColor: constants.darkerDialogBackground
visible: text
}
}
}
FlatButton {
DialogButtonContainer {
Layout.fillWidth: true
Layout.preferredWidth: 1
enabled: valid
icon.source: '../../icons/tab_send.png'
text: qsTr('Sweep...')
onClicked: {
console.log('sweeping')
root.privateKeys = sweepkeys.text
root.accept()
headerComponent: null
FlatButton {
Layout.fillWidth: true
Layout.preferredWidth: 1
enabled: valid
icon.source: '../../icons/tab_send.png'
text: qsTr('Sweep...')
onClicked: {
console.log('sweeping')
root.privateKeys = sweepkeys.text
root.accept()
}
}
}
}
Bitcoin {
-1
View File
@@ -32,7 +32,6 @@ Pane {
ColumnLayout {
Layout.fillWidth: true
Layout.margins: constants.paddingLarge
Heading {
text: qsTr('Wallets')
@@ -7,11 +7,26 @@ Container {
id: root
property bool showSeparator: true
property color separatorColor: constants.darkerBackground
property Component headerComponent: Component {
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 2
Layout.leftMargin: constants.paddingSmall
Layout.rightMargin: constants.paddingSmall
color: root.separatorColor
}
}
property var _contentRootItem
property var _headerItem
property Item _layout
function fillContentItem() {
var contentRoot = containerLayout.createObject(root)
var outerLayout = rootLayout.createObject(root)
if (headerComponent != null)
_headerItem = headerComponent.createObject(outerLayout)
var contentRoot = containerLayout.createObject(outerLayout)
contentRoot.children.length = 0 // empty array
let total = contentChildren.length
@@ -32,7 +47,8 @@ Container {
contentRoot.children.push(button)
}
contentItem = contentRoot
contentItem = outerLayout //contentRoot
_contentRootItem = contentRoot
}
// override this function to dynamically add buttons.
@@ -43,6 +59,13 @@ Container {
fillContentItem()
}
Component {
id: rootLayout
ColumnLayout {
spacing: 0
}
}
Component {
id: containerLayout
RowLayout {
@@ -59,7 +82,7 @@ Container {
Layout.preferredWidth: showSeparator ? 2 : 0
Layout.preferredHeight: pheight
Layout.alignment: Qt.AlignVCenter
color: constants.darkerBackground
color: root.separatorColor
Component.onCompleted: {
// create binding here, we need to be able to have stable ref master_idx
visible = Qt.binding(function() {
@@ -0,0 +1,3 @@
ButtonContainer {
separatorColor: constants.darkerDialogBackground
}
@@ -106,10 +106,10 @@ Dialog {
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: constants.paddingXXSmall
Layout.rightMargin: constants.paddingXXSmall
height: 1
color: Qt.rgba(0,0,0,0.5)
Layout.leftMargin: constants.paddingSmall
Layout.rightMargin: constants.paddingSmall
Layout.preferredHeight: 2
color: constants.darkerDialogBackground
}
}
@@ -35,7 +35,7 @@ ElDialog {
implicitHeight: rootLayout.height + topPadding + bottomPadding
padding: constants.paddingLarge
background: Rectangle {
color: constants.lighterBackground
color: constants.highlightBackground
}
ColumnLayout {
id: rootLayout
@@ -7,6 +7,7 @@ RowLayout {
property alias text: password_tf.text
property alias tf: password_tf
property alias echoMode: password_tf.echoMode
property alias placeholderText: password_tf.placeholderText
property bool showReveal: true
signal accepted
@@ -19,6 +19,10 @@ Pane {
kbd.keyEvent(keycode, key)
}
background: Rectangle {
color: constants.darkerDialogBackground
}
FlatButton {
anchors.fill: parent
@@ -35,10 +35,11 @@ Pane {
TextArea {
id: seedtextarea
Layout.fillWidth: true
Layout.minimumHeight: fontMetrics.height * 3 + topPadding + bottomPadding
Layout.minimumHeight: fontMetrics.lineSpacing * 3 + topPadding + bottomPadding
rightPadding: constants.paddingLarge
leftPadding: constants.paddingLarge
bottomPadding: constants.paddingXLarge
wrapMode: TextInput.WordWrap
font.bold: true
@@ -47,8 +48,9 @@ Pane {
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhLowercaseOnly | Qt.ImhNoPredictiveText
readOnly: AppController.isAndroid()
background: Rectangle {
color: constants.darkerBackground
Component.onCompleted: {
background.filled = true
background.fillColor = constants.seedTextAreaBackground
}
onTextChanged: {
@@ -66,16 +68,19 @@ Pane {
Rectangle {
anchors.fill: contentText
color: root.indicatorValid ? 'green' : 'red'
border.color: Material.accentColor
radius: 2
radius: 3
}
Label {
id: contentText
text: root.indicatorText
anchors.right: parent.right
anchors.bottom: parent.bottom
leftPadding: root.indicatorText != '' ? constants.paddingLarge : 0
rightPadding: root.indicatorText != '' ? constants.paddingLarge : 0
anchors.rightMargin: constants.paddingXXSmall
anchors.bottomMargin: constants.paddingXXSmall
leftPadding: root.indicatorText != '' ? constants.paddingMedium : 0
rightPadding: root.indicatorText != '' ? constants.paddingMedium : 0
topPadding: root.indicatorText != '' ? constants.paddingXXSmall/2 : 0
bottomPadding: root.indicatorText != '' ? constants.paddingXXSmall/2 : 0
font.bold: false
font.pixelSize: constants.fontSizeSmall
}
@@ -99,7 +104,7 @@ Pane {
Layout.margins: constants.paddingXXSmall
width: suggestionLabel.width
height: suggestionLabel.height
color: constants.lighterBackground
color: constants.darkerDialogBackground
radius: constants.paddingXXSmall
Label {
id: suggestionLabel
@@ -127,7 +132,7 @@ Pane {
Layout.fillWidth: true
Layout.preferredHeight: kbd.width / 1.75
visible: !root.readOnly
onKeyEvent: {
onKeyEvent: (keycode, text) => {
if (keycode == Qt.Key_Backspace) {
if (seedtextarea.text.length > 0)
seedtextarea.text = seedtextarea.text.substring(0, seedtextarea.text.length-1)
@@ -43,7 +43,7 @@ Item {
HelpButton {
Layout.alignment: Qt.AlignRight
heading: qsTr('Connection mode')+':'
heading: qsTr('Connection mode') + ':'
helptext: Config.getTranslatedMessage('MSG_CONNECTMODE_SERVER_HELP') + '<br/><br/>' +
Config.getTranslatedMessage('MSG_CONNECTMODE_NODES_HELP') + '<ul>' +
'<li><b>' + Config.getTranslatedMessage('MSG_CONNECTMODE_AUTOCONNECT') +
@@ -56,39 +56,32 @@ Item {
}
}
Label {
text: qsTr("Server")
enabled: address_tf.enabled
}
TextHighlightPane {
TextField {
id: address_tf
Layout.fillWidth: true
TextField {
id: address_tf
enabled: server_connect_mode_cb.currentValue != ServerConnectModeComboBox.Mode.Autoconnect
width: parent.width
inputMethodHints: Qt.ImhNoPredictiveText
enabled: server_connect_mode_cb.currentValue != ServerConnectModeComboBox.Mode.Autoconnect
inputMethodHints: Qt.ImhNoPredictiveText
placeholderText: qsTr('Server')
property bool valid: true
property bool valid: true
function validate() {
if (!enabled) {
valid = true
return
}
valid = Network.isValidServerAddress(address_tf.text)
function validate() {
if (!enabled) {
valid = true
return
}
valid = Network.isValidServerAddress(address_tf.text)
}
onTextChanged: validate()
onEnabledChanged: validate()
onTextChanged: validate()
onEnabledChanged: validate()
Rectangle {
anchors.fill: parent
color: "red"
opacity: 0.2
visible: !parent.valid
}
Rectangle {
anchors.fill: parent
color: "red"
opacity: 0.2
visible: !parent.valid
}
}
@@ -6,7 +6,7 @@ import QtQuick.Controls.Material
Pane {
padding: constants.paddingSmall
property color backgroundColor: Qt.lighter(Material.background, 1.15)
property color backgroundColor: constants.highlightBackground
property color borderColor: 'transparent'
background: Rectangle {
@@ -30,6 +30,7 @@ WizardComponent {
InfoTextArea {
Layout.fillWidth: true
Layout.bottomMargin: constants.paddingLarge
backgroundColor: constants.darkerDialogBackground
text: qsTr('Your seed is important!') + ' ' +
qsTr('If you lose your seed, your money will be permanently lost.') + ' ' +
qsTr('To make sure that you have properly saved your seed, please retype it here.')
@@ -43,6 +43,7 @@ WizardComponent {
Layout.fillWidth: true
visible: cosigner
backgroundColor: constants.darkerDialogBackground
RowLayout {
width: parent.width
@@ -47,6 +47,7 @@ WizardComponent {
InfoTextArea {
id: warningtext
Layout.fillWidth: true
backgroundColor: constants.darkerDialogBackground
iconStyle: InfoTextArea.IconStyle.Warn
}
@@ -61,6 +61,7 @@ WizardComponent {
id: validationtext
Layout.fillWidth: true
Layout.columnSpan: 2
backgroundColor: constants.darkerDialogBackground
visible: text
iconStyle: InfoTextArea.IconStyle.Error
}
@@ -75,6 +75,7 @@ WizardComponent {
Layout.fillWidth: true
visible: cosigner
backgroundColor: constants.darkerDialogBackground
RowLayout {
width: parent.width
@@ -122,6 +122,7 @@ WizardComponent {
Layout.fillWidth: true
visible: cosigner
backgroundColor: constants.darkerDialogBackground
RowLayout {
width: parent.width
@@ -169,6 +170,7 @@ WizardComponent {
ComboBox {
id: seed_variant_cb
visible: !is2fa
textRole: 'text'
@@ -188,13 +190,16 @@ WizardComponent {
id: infotext
Layout.fillWidth: true
Layout.columnSpan: 2
Layout.bottomMargin: constants.paddingLarge
Layout.topMargin: constants.paddingLarge
compact: true
backgroundColor: constants.darkerDialogBackground
}
SeedTextArea {
id: seedtext
Layout.fillWidth: true
Layout.columnSpan: 2
Layout.topMargin: constants.paddingLarge
placeholderText: cosigner ? qsTr('Enter cosigner seed') : qsTr('Enter your seed')
@@ -27,8 +27,10 @@ WizardComponent {
ColumnLayout {
width: parent.width
height: parent.height
InfoTextArea {
Layout.preferredWidth: parent.width
backgroundColor: constants.darkerDialogBackground
text: qsTr('Enter a list of Bitcoin addresses (this will create a watching-only wallet), or a list of private keys.')
}
@@ -41,6 +41,7 @@ WizardComponent {
InfoTextArea {
Layout.preferredWidth: parent.width
backgroundColor: constants.darkerDialogBackground
text: qsTr('Choose the number of participants, and the number of signatures needed to unlock funds in your wallet.')
}
@@ -161,19 +161,19 @@ WizardComponent {
InfoTextArea {
Layout.fillWidth: true
Layout.topMargin: constants.paddingMedium
Layout.bottomMargin: constants.paddingMedium
compact: true
backgroundColor: constants.darkerDialogBackground
text: qsTr('You can override the suggested derivation path.') + ' ' +
qsTr('If you are not sure what this is, leave this field unchanged.')
}
Label {
text: qsTr('Derivation path')
}
TextField {
id: derivationpathtext
Layout.fillWidth: true
Layout.leftMargin: constants.paddingMedium
inputMethodHints: Qt.ImhNoPredictiveText
placeholderText: qsTr('Derivation path')
onTextChanged: validate()
}
@@ -181,6 +181,7 @@ WizardComponent {
InfoTextArea {
id: validationtext
Layout.fillWidth: true
backgroundColor: constants.darkerDialogBackground
visible: text
iconStyle: InfoTextArea.IconStyle.Error
}
@@ -1,49 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.electrum 1.0
import "../controls"
WizardComponent {
valid: true
property string masterPubkey: wizard_data['multisig_master_pubkey']
ColumnLayout {
width: parent.width
Label {
text: qsTr('Here is your master public key. Please share it with your cosigners')
Layout.fillWidth: true
wrapMode: Text.Wrap
}
TextHighlightPane {
Layout.fillWidth: true
RowLayout {
width: parent.width
Label {
Layout.fillWidth: true
text: masterPubkey
font.pixelSize: constants.fontSizeMedium
font.family: FixedFont
wrapMode: Text.Wrap
}
ToolButton {
icon.source: '../../../icons/share.png'
icon.color: 'transparent'
onClicked: {
var dialog = app.genericShareDialog.createObject(app,
{ title: qsTr('Master public key'), text: masterPubkey }
)
dialog.open()
}
}
}
}
}
}
@@ -45,12 +45,14 @@ WizardComponent {
Label {
Layout.fillWidth: true
text: !enforceExistingPassword ? qsTr('Enter password') : qsTr('Enter existing password')
Layout.bottomMargin: constants.paddingSmall
text: !enforceExistingPassword ? qsTr('Enter a password to secure access to your wallet') : qsTr('Enter your existing wallet password')
wrapMode: Text.Wrap
}
PasswordField {
id: password1
placeholderText: qsTr('Enter password')
onTextChanged: {
if (enforceExistingPassword) {
root.passwordMatchesAnyExisting = false
@@ -59,16 +61,12 @@ WizardComponent {
}
}
Label {
text: qsTr('Enter password (again)')
visible: !enforceExistingPassword
}
PasswordField {
id: password2
showReveal: false
echoMode: password1.echoMode
visible: !enforceExistingPassword
placeholderText: qsTr('Enter password (again)')
}
RowLayout {
@@ -100,12 +98,14 @@ WizardComponent {
text: qsTr('Passwords don\'t match')
visible: (password1.text != password2.text) && !enforceExistingPassword
iconStyle: InfoTextArea.IconStyle.Warn
backgroundColor: constants.darkerDialogBackground
}
InfoTextArea {
Layout.alignment: Qt.AlignCenter
text: qsTr('Password too short')
visible: (password1.text == password2.text) && !valid && !enforceExistingPassword
visible: (password1.text == password2.text) && password1.text != '' && !valid && !enforceExistingPassword
iconStyle: InfoTextArea.IconStyle.Warn
backgroundColor: constants.darkerDialogBackground
}
InfoTextArea {
Layout.alignment: Qt.AlignCenter
@@ -116,6 +116,7 @@ WizardComponent {
qsTr("Creating new wallets with different passwords is not supported.")
].join("\n")
iconStyle: InfoTextArea.IconStyle.Info
backgroundColor: constants.darkerDialogBackground
}
InfoTextArea {
Layout.alignment: Qt.AlignCenter
@@ -123,6 +124,13 @@ WizardComponent {
visible: password1.text != "" && !valid && enforceExistingPassword
text: qsTr('Password does not match any existing wallets password.')
iconStyle: InfoTextArea.IconStyle.Warn
backgroundColor: constants.darkerDialogBackground
}
Item {
Layout.preferredWidth: 1
Layout.fillHeight: true
}
}
}
@@ -107,7 +107,7 @@ ElDialog {
spacing: 0
// root Item in Wizard, capture back button here and delegate to main
Keys.onReleased: {
Keys.onReleased: (event) => {
if (event.key == Qt.Key_Back) {
console.log("Back button within wizard")
app.close() // this handles unwind of dialogs/stack
@@ -159,7 +159,7 @@ ElDialog {
}
}
ButtonContainer {
DialogButtonContainer {
Layout.fillWidth: true
FlatButton {