mike mike - 3 months ago 11
C++ Question

How to force multiple views to show the same model row

I have multiple QComboboxes sharing the same model. Usually they can independently select items in that model.
In some circumstances I wish to force those comboboxes to show the same model row, i.e. when one changes a selection, that should be reflected across the other combos.

This can be done via (a potential mess of) signals and slots, but I wonder if there is a way to do it more cleanly from the model end. I.e. force all views to show the same row.

A comment below points to sharing the selectionModel amongst the combos. I have done this by gathering my combos into a list and setting a model on them:

QList<QComboBox*> my_combos;
// .. then populate my_combos .. then
QComboBox *combo;
foreach(combo, my_combos)
combo->setModel(&_my_model);


then

QItemSelectionModel *selectionmodel = my_combos.at(0)->view()->selectionModel();
foreach(combo, my_combos)
{
if (combo == my_combos.at(0))
continue;
combo->view()->setSelectionModel(selectionmodel);
}


Am I missing a step here?

Answer

The selection is a red herring. QComboBox does not allow multiple item selection. What you're referring to as "selection" is the current index. It's easy to share it among combo boxes by connecting the currentIndexChanged signal to setCurrentIndex:

// https://github.com/KubaO/stackoverflown/tree/master/questions/combo-shared-select-39247471
#include <QtWidgets>
#include <array>

int main(int argc, char ** argv) {
    QApplication app{argc, argv};
    QStringListModel model;
    model.setStringList({ "foo", "bar", "baz "});

    QWidget ui;
    QHBoxLayout layout{&ui};
    std::array<QComboBox, 3> combos;
    // setIndices could be a method in a class
    auto setIndices = [&combos](int index) {
        for (auto & combo : combos)
            combo.setCurrentIndex(index);
    };
    for (auto & combo : combos) {
        using namespace std::placeholders;
        layout.addWidget(&combo);
        combo.setModel(&model);
        QObject::connect(&combo,
                         static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
                         setIndices);
    }
    ui.show();

    return app.exec();
}

Side note: You can hold the widgets by value. If their number is fixed at compile time, use std::array. Otherwise, you can use std::list with emplace_back. Signed, byValueGuy.

Comments