I want to write a program, working like a little navigation system uisng the Qt framework, but i still am very new to it.
I created a dialog with two Comboboxes. Each combobox contains all "citynames". At the initialization the content of both boxes is sorted alphabetically.
If a name in the first box is selected, it should not be displayed in the second one and the other way too.
I successfully removed the item and added it again, if another item is selected, but know i cannot sort them anymore
This is what i tried so far for updating:
for(std::vector<City>::iterator iter = citylist.begin(); iter != citylist.end(); iter++){
if(ui->combo2->currentText() != (*iter).getName()
and ui->combo1->findText((*iter).getName()) == -1){
ui->combo1->addItem((*iter).getName(),QComboBox::InsertAlphabetically);
}
}
but it does not insert the items alphabetically...
so i tried to sort it afterwards:
QSortFilterProxyModel* proxy = new QSortFilterProxyModel(ui->combo1);
proxy->setSourceModel(ui->combo1->model());
// combo's current model must be reparented,
// otherwise QComboBox::setModel() will delete it
ui->combo1->model()->setParent(proxy);
ui->combo1->setModel(proxy);
// sort
ui->combo1->model()->sort(0);
But if i try to call this function an error occurs and the application terminates.
So is anyone out there, who is able to help me?
You're trying to use QComboBox
's internal model as source model for proxy
. This is not going to work because QComboBox
owns its internal model and when you call QComboBox::setModel
, previous model is deleted (despite you reset its parent). You need to create a separate source model. Conveniently, you can use one source model for both comboboxes if cities list is the same.
Using QSortFilterProxyModel
for sorting is easy, but it's surprisingly hard to exclude one specific string with it. You can subclass QSortFilterProxyModel::filterAcceptsRow
and implement the behavior you want. I decided to use a bit of black magic instead (see this answer).
Private class fields:
private:
QSortFilterProxyModel *proxy1, *proxy2;
Source:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QStandardItemModel* model = new QStandardItemModel(this);
foreach(QString name, QStringList()
<< "Paris"<< "London"<< "Moscow" << "Tokyo" << "Berlin" << "Amsterdam") {
model->appendRow(new QStandardItem(name));
}
proxy1 = new QSortFilterProxyModel();
proxy1->setSourceModel(model);
proxy1->sort(0);
ui->comboBox1->setModel(proxy1);
proxy2 = new QSortFilterProxyModel();
proxy2->setSourceModel(model);
proxy2->sort(0);
ui->comboBox2->setModel(proxy2);
connect(ui->comboBox1, &QComboBox::currentTextChanged,
this, &MainWindow::something_changed);
connect(ui->comboBox2, &QComboBox::currentTextChanged,
this, &MainWindow::something_changed);
something_changed();
}
void MainWindow::something_changed() {
ui->comboBox1->blockSignals(true); //prevent recursion
ui->comboBox2->blockSignals(true);
proxy2->setFilterRegExp(QString("^(?!(%1)$)").arg(
QRegExp::escape(ui->comboBox1->currentText())));
proxy1->setFilterRegExp(QString("^(?!(%1)$)").arg(
QRegExp::escape(ui->comboBox2->currentText())));
ui->comboBox1->blockSignals(false);
ui->comboBox2->blockSignals(false);
}
Tested in Qt 5.3.