Qt — Обновление в функции, вызываемой QSignalMapper

У меня есть QTreeWidget, в котором каждый из его элементов имеет QComboBox в столбце. Я подключил его к слоту с помощью QSignalMapper и успешно извлекаю как элемент, так и индекс в выпадающем списке, когда он запускается. Я сделал это так:

foreach(Workplace *wp, allWorkplaces){
QTreeWidgetItem *workplaceItem = new QTreeWidgetItem;

workplaceItem->setText(0, wp->workplaceName());
workplaceItem->setText(1, wp->workplaceDescription());

myWorkplaceUi->treeWidget->addTopLevelItem(workplaceItem);

QComboBox *combo = new QComboBox();

combo->addItems(allShiftModels);

combo->setAutoFillBackground(true);

ShiftModel *shiftModel = qobject_cast<ShiftModel *>(wp->usedShiftModel);

myWorkplaceUi->treeWidget->setItemWidget(workplaceItem,2, combo);

if(shiftModel && !shiftModel->shiftModelName().isEmpty()){
qDebug()<<"after the cast: "<< shiftModel->shiftModelName();
combo->setCurrentIndex(combo->findText(shiftModel->shiftModelName(), Qt::MatchExactly));
}else{
combo->setCurrentIndex(combo->findText("None", Qt::MatchExactly));
}

connect(combo, SIGNAL(currentIndexChanged(int)), signalMapper, SLOT(map()));
signalMapper->setMapping(combo, QString("%1").arg(wp->workplaceName()));
}

connect(signalMapper, SIGNAL(mapped(const QString &)),this, SLOT(changed(const QString &)));

Моя цель, после получения обоих Workplace и ShiftModel, чтобы обновить их в экземплярах моих уже созданных рабочих мест. Поэтому, в основном, я пытаюсь найти выбранное Workplace и ShiftModel, потому что в зависимости от выбранного ShiftModel я изменю указатель на ShiftModel в классе Workplace:

class Workplace : public QObject
{
Q_OBJECT

public:
(...)
ShiftModel *usedShiftModel;
(...)
}

И changed слот:

void workplacesdialog::changed(QString position){

QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
QList<ShiftModel*> allShiftModels = this->myProject->myFactory->listShiftModels();

foreach(Workplace* workplace, allWorkplaces){
foreach(ShiftModel *shiftmodel, allShiftModels){
qDebug() <<"workplace:"<< workplace->workplaceName();
qDebug() <<"shiftmodel:"<< shiftmodel->shiftModelName();

QString wp = position;
QTreeWidgetItem* item=(QTreeWidgetItem*)myWorkplaceUi->treeWidget->findItems(wp,Qt::MatchExactly,0).at(0);
QComboBox *combo = (QComboBox*)myWorkplaceUi->treeWidget->itemWidget(item,2);
if(combo && item){
QString sm = combo->currentText();

qDebug() << "selected shiftmodel "<< sm << " on workplace "<< wp;

if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
workplace->usedShiftModel = shiftmodel;
break;
}
else{
workplace->usedShiftModel = 0;
return;
}

}else{
qDebug() << "cast failed!";
return;
}
}
}
}

Итак, моя проблема с этим заключается в том, что, когда я щелкаю один из выпадающих списков, успешно извлекаю как выбранный элемент, так и индекс, но затем, когда я пытаюсь обойти их двумя foreach петли в слоте, это не работает, как я ожидал. Я надеялся, что каждый раз, когда я нажимаю на индекс в одном из списков, это будет называться, и это так. Хотя, по какой-то причине, метод, который я использую, чтобы сопоставить то, что пользователь выбрал с тем, что уже было заявлено, не работает.

Кроме того, похоже, что он поражает только 1-й workplace на allWorkplaces список, а также 1-й shiftmodel на ShiftModels список, и это моя проблема.

Если кто-нибудь знает, как это исправить или у вас есть идеи, чтобы поделиться, пожалуйста, дайте мне знать. Спасибо.

1

Решение

Проблема заключается в следующем:

if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
workplace->usedShiftModel = shiftmodel;
break;
}
else{
workplace->usedShiftModel = 0;
return;
}

Если либо имя рабочего места не совпадает, либо имя модели смены не совпадает, связь между рабочим местом и его связанной в настоящее время моделью смены удаляется, и ваша функция возвращается.

Я мог бы реструктурировать два цикла for для вас, но есть более простой и менее подверженный ошибкам способ:

Примечание: я пометил некоторые пути кода «TODO», который пропустил из-за нехватки времени. Вы должны быть в состоянии понять их самостоятельно, хотя.

// Set up hashes for quick lookup
QHash< QString, Workplace* > workplaceHash;

QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
foreach( Workplace* workplace, allWorkplaces )
{
workplaceHash.insert( workplace, workplace->workplaceName() );
}

// TODO: Do a similar thing for the shift models here

// Find the selected workplace
if( !workplaceHash.contains( position ) )
{
// TODO: Error handling (An unknown/No workplace was selected)
return;
}
// else: A valid workplace was selected

Workplace* selectedWorkplace = workplaceHash.value( position );

// TODO: Retrieve the name of the shift model (stored in variable sm)

// Find the selected shiftmodel
if( !shiftplaceHash.contains( sm ) )
{
// No shift model was selected
selectedWorkplace->usedShiftModel= 0;
return;
}
// Else: Both work place and shift model were selected

Shiftplace* selectedShiftModel = shiftplaceHash.value( sm );

selectedWorkplace->usedShiftModel = selectedShiftModel;

Несколько идей для рефакторинга:

  • Вы можете создать хэши вне этого метода и сохранить их в переменных-членах. Просто убедитесь, что хэш всегда обновляется при добавлении или удалении рабочего места.
  • Вы можете упростить обнаружение ошибок, выделив части кода в отдельные методы, например, QString getSelectedShiftModelName() и т.п.
1

Другие решения

Итак, в конце я понял, что мои петли действительно испорчены … Теперь это работает:

void workplacesdialog::changed(QString position){

QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
QList<ShiftModel*> allShiftModels = this->myProject->myFactory->listShiftModels();

qDebug() << allWorkplaces.size() << " workplaces";
qDebug() << allShiftModels.size() << " ShiftModels";

QString wp = position;
QString sm;
QTreeWidgetItem* item=(QTreeWidgetItem*)myWorkplaceUi->treeWidget->findItems(wp,Qt::MatchExactly,0).at(0);
QComboBox *combo = (QComboBox*)myWorkplaceUi->treeWidget->itemWidget(item,2);
if(combo && item){
sm = combo->currentText();
qDebug() << "selected shiftmodel "<< sm << " on workplace "<< wp;

}else{
qDebug() << "cast failed!";
return;
}

foreach(Workplace* workplace, allWorkplaces){
foreach(ShiftModel *shiftmodel, allShiftModels){
qDebug() <<"workplace:"<< workplace->workplaceName();
qDebug() <<"shiftmodel:"<< shiftmodel->shiftModelName();
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
qDebug() << "found match!: "<< wp << " >>>>> " << sm;
workplace->usedShiftModel = shiftmodel;
return;
}else if(workplace->workplaceName()==wp && sm=="None"){
qDebug() << "clear match: "<< wp << " >>>>> " << sm;
workplace->usedShiftModel = 0;
return;
}
}
}
}
1

По вопросам рекламы [email protected]