Как отправить переменную из делегата в другой класс?

294
23 декабря 2016, 14:27

В ComboBoxDelegate.cpp получаю переменную key:

void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
     QComboBox *combo = static_cast<QComboBox*>(editor);
     model->setData(index, combo->currentText());
     int comboRow = combo->currentIndex();
     QModelIndex comboIndex = combo->model()->index(comboRow, 2);
     QVariant value = combo->model()->data(comboIndex);
     QString key = value.toString();
     qDebug()<<key;
}

Далее хочу отправить её в pekarnya.cpp, где буду выполнять с ней следующее:

QSqlQuery query;
query.prepare("UPDATE sklad SET sklad.weight = :weight WHERE sklad.key = :key;");
query.bindValue(":weight", result);
query.bindValue(":key", key);
query.exec();

Каким способом можно отправить key и оптимально ли это делать?

Связанный вопрос.

Answer 1

Можно оздать собственный произвольный сигнал в делегате, передающий значение ключа, по которому произошли изменения в исходной модели. Достаточно в классе делегата объявить произвольный сигнал и отправлять его из соответствующего метода:

class ComboBoxDelegate : public QStyledItemDelegate {
    Q_OBJECT
    signals:
        void keyChanged(const QString &key);
    ...
};
void ComboBoxDelegate::setModelData(QWidget *editor
    , QAbstractItemModel *model, const QModelIndex &index) const {
     // Так делать не надо!
     // QComboBox *combo = static_cast<QComboBox*>(editor);
     // Если речь идёт об указателе, связанном с QObject или QWidget,
     // используйте именно qobject_cast<T>().
     QComboBox *combo = qobject_cast<QComboBox>(editor);
     if(combo == Q_NULLPTR) return;
     model->setData(index, combo->currentText());
     int comboRow = combo->currentIndex();
     QModelIndex comboIndex = combo->model()->index(comboRow, 2);
     QVariant value = combo->model()->data(comboIndex);
     emit keyChanged(value.toString());
}

На приёмной стороне или, проще говоря, слоте, который будет предварительно подключен к данному сигналу, останется лишь выполнить соответствующую обработку:

void Pekarnya::onSkladKeyChanged(const QString &key) {
    QSqlQuery query;
    query.prepare(
        "UPDATE sklad SET sklad.weight = :weight" \
        " WHERE sklad.key = :key;");
    query.bindValue(":weight", result); // "result" берётся извне.
    query.bindValue(":key", key);
    query.exec();
}

От себя я бы всё-таки порекомендовал отойти от такой практики синхронизации взаимосвязей между таблицами на уровне кода в приложении и по возможности переключить ответственность за отслеживанием изменений непосредственно на саму базу данных. Это могут быть триггеры или даже процедуры. Также, в отдельных простых случаях помогает упростить задачу использование связки уже готовых классов QSqlRelation....

Замечание

Поскольку метод ComboBoxDelegate::setModelData() const является константным, соответственно, чтобы отправить из него сигнал ComboBoxDelegate::keyChanged() потребуется или объявить и сам сигнал константным:

signals:
    void keyChanged(const QString &key) const;

Или произвести приведение типа указателя this к неконстантному типу:

ComboBoxDelegate *delegate = const_cast<ComboBoxDelegate*>(this);
emit delegate->keyChanged(value.toString());
READ ALSO
Как управлять камерой Onvif?

Как управлять камерой Onvif?

Прошу сразу не кидаться тапками ибо не знаю, подходит ли данный вопрос по тематике этого сайтаЕсли вопрос не подходит

274
sizeof для символа кириллицы

sizeof для символа кириллицы

Я провел несколько экспериментов, но объяснить почему это так работает я не смог

433
Ошибка компиляции LNK 2005

Ошибка компиляции LNK 2005

Список ошибок:

282
Qt | Работа с layout&#39;ами

Qt | Работа с layout'ами

Есть QTabWidgetВ его вкладку нужно добавить виджет, например QLabel

402