QML reset dialog with tabview - qt

I was trying to implement a tabbed Dialog in QML with the means to reset it to the intial values.
Since tabs are dynamically instantiated, none of the straight forward methods seem to work. The parent Dialog can not reference the inner Combobox and the Combobox can not reference the outer Dialog. How can this be achieved?
import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
Dialog {
id: dlg
title: "Settings"
visible: true
standardButtons: StandardButton.Apply | StandardButton.Reset
property string val: ""
onApply: console.log(val)
onReset: {
// RESET COMBOBOX TO DEFAULT
}
TabView {
id: tabView
anchors.fill: parent
Tab {
title: "ValueTab"
id: tabVal
GridLayout {
id: gridVal
anchors.fill: parent
GroupBox {
title: qsTr("Choose value")
id: gb
Layout.fillWidth: true
ColumnLayout {
anchors.fill: parent
id: cl
ComboBox {
id: valueChooser
editable: false
model: ListModel {
id: listModel
ListElement { text: "One" }
ListElement { text: "Two" }
ListElement { text: "Three" }
}
Layout.fillWidth: true
onCurrentTextChanged : val = currentText
}
}
}
}
}
}
}

I am quite unsure, if I got your question right as you say, you can not reference the Dialog from within the Combobox. I can not see the reason why.
Assuming the example of yours contains indeed your problem and all you want to do is to reset the values (and you know the original values) once the reset button is pressed, this is how I would solve it.
Using the Connections-type to connect to the Dialog's reset() from within the Combobox
import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
Dialog {
id: dlg
title: "Settings"
visible: true
standardButtons: StandardButton.Apply | StandardButton.Reset
property string val: ""
onApply: console.log(val)
onReset: {
// **DONT** RESET COMBOBOX TO DEFAULT **HERE**
}
TabView {
id: tabView
anchors.fill: parent
Tab {
title: "ValueTab"
id: tabVal
GridLayout {
id: gridVal
anchors.fill: parent
GroupBox {
title: qsTr("Choose value")
id: gb
Layout.fillWidth: true
ColumnLayout {
anchors.fill: parent
id: cl
ComboBox {
id: valueChooser
editable: false
model: ListModel {
id: listModel
ListElement { text: "One" }
ListElement { text: "Two" }
ListElement { text: "Three" }
}
Layout.fillWidth: true
onCurrentTextChanged : val = currentText
/// *** INTERESTING PART HERE! ***
Connections {
target: dlg
onReset: {
// RESET COMBOBOX TO DEFAULT **HERE** INSTEAD
valueChooser.currentIndex = 0
}
}
}
}
}
}
}
}
}

Related

Can't bind on current item in QML view/model

I have a simple task: need to output some information about current item of ListView separately. For example, in outside Label, but I can't succeed.
I figured out that problem related to where model was defined. If it is separate object with id this behavior happened. But when I define it inlined inside the view, all works fine. This behaviour is very weird and looks like a bug.
To make this code work, just switch to commented model definition. Anybody encounter this problem or may be know something?
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.calendar 1.0
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
CalendarModel {
id: myModel
from: new Date(2018, 0, 1)
to: new Date(2018, 11, 31)
}
ColumnLayout {
anchors.fill: parent
Label {
id: myLabel
text: "myLabel1"
}
Label {
text: myModel.monthAt(myView.currentIndex)
}
ListView {
id: myView
Layout.fillWidth: true
Layout.fillHeight: true
snapMode: ListView.SnapOneItem
orientation: ListView.Horizontal
highlightRangeMode: ListView.StrictlyEnforceRange
boundsBehavior: Flickable.StopAtBounds
model: myModel
// model: CalendarModel {
// id: myModel
// from: new Date(2018, 0, 1)
// to: new Date(2018, 11, 31)
// }
delegate: Rectangle {
color: "green"
width: myView.width
height: 200
Text {
anchors.centerIn: parent
text: model.month
}
}
onCurrentIndexChanged: {
console.log(currentIndex)
myLabel.text = String(currentIndex)
}
ScrollIndicator.horizontal: ScrollIndicator {}
}
}
}

Make effective property alias, using Connections, Binding or Qt.binding

Is it possible to make mutual connection (without loop issue), using Connections, Binding or Qt.binding()?
It is possible to connect, say, SwipeView.currentIndex to TabBar.currentIndex and vise versa. When I page through SwipeView, then current tab of TabBar is also changed and vice versa. There is no binding loop of properties.
How to achieve this in Repeater? When some item created by Repeater became selected (in some sense), then I want to rebind its properties to another standalone item, which operates like editor of the selected item. The state of elements in selected item should depend on the state of items into the editor. But on selection changing I need to initialize items in editor using values from newly selected item.
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
ApplicationWindow {
id: root
property var currentDayOfWeek: { "enabled": false, "time": "08:00" }
visible: true
SystemPalette {
id: palette
}
RowLayout {
anchors.centerIn: parent
Column {
ButtonGroup { id: weekButtonGroup }
Repeater {
model: 7
RowLayout {
Settings {
id: dayOfWeekSettings
category: Qt.locale("C").standaloneDayName(index, Locale.LongFormat)
property bool enabled: false
property string time: "08:00"
}
Label {
text: dayOfWeekSettings.time
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
background: Rectangle {
color: dayOfWeekSettings.enabled ? palette.highlight : palette.base
}
Layout.fillHeight: true
}
RadioButton {
text: Qt.locale().standaloneDayName(index, Locale.LongFormat)
onCheckedChanged: {
if (checked) {
root.currentDayOfWeek = dayOfWeekSettings
timeField.text = Qt.binding(function() { return dayOfWeekSettings.time }) // ???
enabledCheckBox.checked = Qt.binding(function() { return dayOfWeekSettings.enabled }) // ???
}
}
ButtonGroup.group: weekButtonGroup
Layout.fillHeight: true
}
}
}
Layout.fillHeight: true
}
Column {
// Editor
TextField {
id: timeField
text: currentDayOfWeek.time // ???
inputMask: "00:00;_"
inputMethodHints: Qt.ImhDigitsOnly
}
CheckBox {
id: enabledCheckBox
checked: currentDayOfWeek.enabled // ???
}
Layout.fillHeight: true
}
}
}
How to achieve this? Is there canonical way to do this? Above example is not the solution.
The following code works as I want:
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
ApplicationWindow {
id: root
//property var currentDayOfWeek: { "enabled": false, "time": "08:00" }
visible: true
SystemPalette {
id: palette
}
RowLayout {
anchors.centerIn: parent
Column {
ButtonGroup { id: weekButtonGroup }
Repeater {
model: 7
RowLayout {
Settings {
id: dayOfWeekSettings
category: Qt.locale("C").standaloneDayName(index, Locale.LongFormat)
property bool enabled: false
property string time: "08:00"
Binding on enabled {
when: dayOfWeekSettingsCheckBox.checked
value: enabledCheckBox.checked
}
Binding on time {
when: dayOfWeekSettingsCheckBox.checked
value: timeField.text
}
}
Label {
text: dayOfWeekSettings.time
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
background: Rectangle {
color: dayOfWeekSettings.enabled ? palette.highlight : palette.base
}
Layout.fillHeight: true
}
RadioButton {
id: dayOfWeekSettingsCheckBox
text: Qt.locale().standaloneDayName(index, Locale.LongFormat)
onCheckedChanged: {
if (checked) {
//root.currentDayOfWeek = dayOfWeekSettings
timeField.text = dayOfWeekSettings.time
enabledCheckBox.checked = dayOfWeekSettings.enabled
}
}
ButtonGroup.group: weekButtonGroup
Layout.fillHeight: true
}
}
}
Layout.fillHeight: true
}
Column {
id: editor
TextField {
id: timeField
//text: currentDayOfWeek.time
inputMask: "00:00;_"
inputMethodHints: Qt.ImhDigitsOnly
}
CheckBox {
id: enabledCheckBox
//checked: currentDayOfWeek.enabled
}
Layout.fillHeight: true
}
}
}
but there is an issue: editor filled with values in onCheckedChanged when checked became true. But what if when: in Bindings shoot first? Is it possible? Should I use delayed?
If I comment out:
timeField.text = dayOfWeekSettings.time
enabledCheckBox.checked = dayOfWeekSettings.enabled
and uncomment all the commented in above solution, then also all works fine. But the suspicion still persist.

ComboBox disable an item at a particular index

I have a combobox in qml in a as a TableViewColummn and I define it as follows:
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
ListModel {
id: comboModel
ListElement {
text: ""
Index: -1
Dims: -1
}
}
TableViewColumn {
id: imageTypeList
role: "ImageType"
title: "Image Type"
width: 100
delegate: Rectangle {
ComboBox {
anchors.verticalCenter: parent.verticalCenter
anchors.margins: 2
model: comboModel
onActivated : {
console.log(comboModel.get(index).Index)
}
}
}
}
My question is that if it is possible to disable a combobox menu item given a index to the item in the ComboBox. So, I would not like to change the underlying model but actually simply disable the item and not allow the user to select it.
Is it possible to disable a ComboBox menu item ... and not allow the user to select it?
Sure, it is possible.
To do it using Quick Controls 2 you need to create ComboBox delegate this way:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
Window {
visible: true
width: 640
height: 200
title: qsTr("Let's disable some items in ComboBox")
ComboBox {
id: control
currentIndex: 0
anchors.centerIn: parent
model: [
{ text: "Enabled item.", enabled: true },
{ text: "Supposed to be disabled. Can't click on it.", enabled: false},
{ text: "Last, but enabled item.", enabled: true}
]
width: 500
textRole: "text"
delegate: ItemDelegate {
width: control.width
text: modelData.text
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
highlighted: ListView.isCurrentItem
enabled: modelData.enabled
}
}
}
If you are using Quick Controls 1, you should provide your own implementation of ComboBox component.

QT 5.7 QML How to control which Control gets the focus within a TabView

I'd like to arrange for a specific control to get the focus within a TabView Tab. Its seems that the first one gets the focus regardless of what I do. I have tried setting focus:false everywhere else but it doesn't work.
Consider the following code. I have a simple column containing two RadioButtons and a TextField. I'd like to arrange for the TextField to always get focus when the tab is selected, but it always goes to the first RadioButton
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
ApplicationWindow
{
visible: true
width: 800
height: 400
TabView
{
anchors.fill: parent
Tab { title: "tab1"; sourceComponent: foo }
Tab { title: "tab2"; sourceComponent: foo }
}
Component
{
id: foo
ColumnLayout
{
spacing: 32
ExclusiveGroup { id: optionGroup }
RadioButton
{
// i always get the focus!!
exclusiveGroup: optionGroup
text: "Click me"
activeFocusOnPress: true
focus: false
}
RadioButton
{
exclusiveGroup: optionGroup
text: "No, click me!"
activeFocusOnPress: true
focus: false
}
TextField
{
// but i want the focus
placeholderText: "type here"
focus: true
}
}
}
}
Press "tab2" to see this,
I tried forcing within TabView by adding,
onCurrentIndexChanged: getTab(currentIndex).item.forceActiveFocus()
But it makes no difference.
I've read the explanation of focus but it hasn't helped in this case.
Thanks for any suggestion or help,
Probably a bug. Try Qt Quick Controls 2.0 instead:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 800
height: 400
header: TabBar {
id: bar
width: parent.width
TabButton {
text: qsTr("tab1")
}
TabButton {
text: qsTr("tab2")
}
}
StackLayout {
anchors.fill: parent
currentIndex: bar.currentIndex
ColumnLayout {
id: columnLayout
spacing: 32
ButtonGroup {
id: optionGroup
buttons: columnLayout.children
}
RadioButton {
text: "Click me"
}
RadioButton {
text: "No, click me!"
}
TextField {
placeholderText: "type here"
focus: true
}
}
}
}

QtQuick TableView delete row doesn't work

I am using QtQuick TableView to show data from a database through QSqlTableModel and QSortFilterProxyModel.
The remove row operation doesn't work as it should. I have implemented a method in a class derived from QSortFilterProxyModel to call removeRows methods of QSortFilterProxyModel.
Everything works correctly as long as I have a filter setted in QSortFilterProxyModel ( i set it through a text box ). But when the filter is empty, the TableView rowCount property doesn't decrement and, after each delete, the currentRow property is set to rowCount-2. Why? To me it looks like a bug. Why it works when the filter is not empty?
Q_INVOKABLE void eliminaCliente(int row) {
removeRows(row,1);
}
import QtQuick 2.6
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import Material 0.2
import Material.ListItems 0.1
ApplicationWindow {
id: root
visible: true
width: 1024
height: 640
title: qsTr("assiBase")
Page {
id: pLayout
anchors.fill: parent
ColumnLayout {
anchors.fill: parent
Toolbar {
id: aBar
Layout.fillWidth: true
page: pLayout
backgroundColor: "#eeeeee"
RowLayout {
anchors.fill: parent
ActionButton {
id: addButton
Layout.leftMargin: 10
iconName: "content/add_circle"
backgroundColor: "#4CAF50"
onClicked: modalDialog.show()
isMiniSize: true
}
ActionButton {
id: editButton
iconName: "content/create"
isMiniSize: true
}
ActionButton {
id: deleteButton
iconName: "action/delete"
isMiniSize: true
backgroundColor: "#FF0000"
onClicked: {
if (dataView.currentRow != -1) {
var r = dataView.currentRow
console.log(dataView.currentRow)
sqlSortedData.eliminaCliente(dataView.currentRow)
console.log(dataView.rowCount)
//dataView.currentRow = r
}
}
}
RowLayout {
Layout.alignment: Qt.AlignRight
Icon {
name: "action/search"
Layout.alignment: Qt.AlignBottom
}
TextField {
id: searchBox
Layout.rightMargin: 20
Layout.minimumWidth: 400
Layout.preferredWidth: 500
placeholderText: qsTr("cerca...")
onTextChanged: sqlSortedData.setFilterWildcard(searchBox.text)
font.capitalization: Font.MixedCase
}
}
}
}
TableView {
anchors.top: aBar.bottom
anchors.topMargin: 3
sortIndicatorVisible: true
frameVisible: false
Layout.fillWidth: true
Layout.fillHeight: true
onSortIndicatorColumnChanged: model.sort(sortIndicatorColumn, sortIndicatorOrder)
onSortIndicatorOrderChanged: model.sort(sortIndicatorColumn, sortIndicatorOrder)
id: dataView
TableViewColumn {
role: "ID"
visible: false
}
TableViewColumn {
role: "Nome"
title: "Nome"
width: 200
}
TableViewColumn {
role: "Residenza"
title: "Residenza"
width: 200
}
TableViewColumn {
role: "Assicurazione"
title: "Assicurazione"
width: 200
}
TableViewColumn {
width: 128
resizable: false
delegate: RowLayout {
anchors.fill: parent
clip: true
IconButton {
iconName: "content/create"
onClicked: console.log(styleData.row)
}
IconButton {
iconName: "action/delete"
onClicked: {
console.log(styleData.row)
sqlSortedData.eliminaCliente(styleData.row)
console.log(dataView.rowCount)
}
}
}
}
model: sqlSortedData
}
}
}
Take a look at here. There is an workaround suggestion.
It seems like QSortFilterProxyModel needs some love for a long time.

Resources