Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to link from ComboBox to another ComboBox

I try to make a converter app depending on two ComboBoxes using Controls 2. For example:

// First combobox is input unit:
ComboBox {
            id: res_combo1
            width: res_comborect1.width
            currentIndex: 0
            model: ListModel {
                id: model1
                ListItem { text: qsTr("meter") }
                ListItem { text: qsTr("mile") }
                ListItem { text: qsTr("km") }
            }
        }
    }
// Second combobox is output unit:
ComboBox {
            id: res_combo2
            width: res_comborect1.width
            currentIndex: 0
            model: ListModel {
                id: model2
                ListItem { text: qsTr("meter") }
                ListItem { text: qsTr("mile") }
                ListItem { text: qsTr("km") }
            }
        }
    }

When current index is selected from first combobox, second combobox should remove the current index. When another index is selected from first, second should restore previous index and it should remove current index dynamically. For example if meter is selected, second combobox should be {"mile", "km"} I only know a very long way that can be performed with combination of a few index, but my combobox data includes 20 item so I cannot apply this way. Long way:

   function visible1(){
        if(res_combo1.currentIndex==0){
            return true
        }
        else{
            return false
        }
    }
    function visible2(){
        if(res_combo1.currentIndex==1){
            return true
        }
        else{
            return false
        }
    }
    function visible3(){
        if(res_combo1.currentIndex==2){
            return true
        }
        else{
            return false
        }
    }
// if meter is selected from first combobox, second combobox:
RowLayout{
       visible: parent.visible1()
    ComboBox {   
        id: outcombo1
        currentIndex: 0
        model: ListModel {
            id: model_o1
            ListElement { text: qsTr("mile") }
            ListElement { text: qsTr("km") }
        }
    }
   }
// if mile is selected from first combobox:
RowLayout{
       visible: parent.visible2()
    ComboBox {   
        id: outcombo1
        currentIndex: 0
        model: ListModel {
            id: model_o2
            ListElement { text: qsTr("meter") }
            ListElement { text: qsTr("km") }
        }
    }
   }
// if km is selected from first combobox:
RowLayout{
       visible: parent.visible3()
    ComboBox {   
        id: outcombo1
        currentIndex: 0
        model: ListModel {
            id: model_o3
            ListElement { text: qsTr("meter") }
            ListElement { text: qsTr("mile") }
        }
    }
   }

I think we cannot change ListItem dynamically, so JavaScript with JSON list model is required by finding the current index via:

function find(model, criteria) {
  for(var i = 0; i < model.count; ++i) if (criteria(model.get(i))) return i
  return null
}

But I couldn't do this in QML. Is there any solution? Thanks

like image 645
Edip Ahmet Avatar asked Nov 24 '25 18:11

Edip Ahmet


1 Answers

You cannot change a ListItem, but you CAN change the ListModel itself.

ListModel {
    id: fromModel
    ListElement {text: "m" }
    ListElement {text: "mile" }
    ListElement {text: "km" }
}

ListModel {
    id: toModel

    function updateModel()
    {
        // Update model Here
    }
}

RowLayout
{
    anchors.centerIn: parent
    ComboBox
    {
        id: fromCombobox
        model: fromModel
        onCurrentIndexChanged: toModel.updateModel()
    }
    ComboBox
    {
        id: toComboBox
        model: toModel
    }
}

This way, every time the first combo changes, the second combo's model will be updated.

Before you update the model 2, check if the previously selected item in combo 2 will still be available after the update, in order to restore it once the model2 is rebuilt.

    function updateModel()
    {
        // Save old selection
        var selectedFrom = fromModel.get(fromCombobox.currentIndex).text
        if(toComboBox.currentText != selectedFrom)
            var valueToRestore = toComboBox.currentText
        else
            valueToRestore = ""

        // Update model
        clear()
        for(var i=0; i<fromModel.count; i++)
        {
            if(i == fromCombobox.currentIndex)
                continue
            append(fromModel.get(i))
        }

        //Restore selection
        for(var i=0; i<toModel.count; i++)
        {
            // If no value to restore, select first available
            if(valueToRestore == "")
            {
                if(toModel.get(i).text != selectedFrom)
                {
                    toComboBox.currentIndex = i
                    break
                }
            }

            // Else, restore previously selected item
            else
            {
                if(toModel.get(i).text == valueToRestore)
                {
                    toComboBox.currentIndex = i
                    break
                }
            }

        }
    }
like image 59
Yoann Quenach de Quivillic Avatar answered Nov 26 '25 18:11

Yoann Quenach de Quivillic