#ifndef AUTOFORM_H #define AUTOFORM_H #include #include #include #include #include #include #include #include #include #include #include "../qdecimal/src/QDecDouble.hh" #include "iform.h" #include "service.h" #include "ivalidator.h" #include "iservice.h" #include "iplugin.h" #include "combodata.h" template class AutoForm : public IForm { public: explicit AutoForm(QWidget *parent = 0) : IForm(parent) { m_serviceConnected = false; m_saved = false; } virtual ~AutoForm() { foreach (IValidator *val, m_validators) { delete val; } m_validators.clear(); } void setEntity(QSharedPointer entity) { m_entity = entity; bindToUi(); } QSharedPointer entity() { return m_entity; } void setNewRec(bool isNew) { m_newRec = isNew; } void registerBinding(QWidget *widget) { if (!m_bindWidgets.contains(widget)) { m_bindWidgets.append(widget); } } void registerBinding(QComboBox *combo, const QList &values) { m_bindCombos[combo] = values; } void registerValidator(IValidator *validator) { m_validators.append(validator); } protected: virtual void bindOtherToUi() {} virtual bool bindOtherToData() { return true; } virtual void registerCombos() {} private: QSharedPointer m_entity; QList m_bindWidgets; QList m_validators; QHash > m_bindCombos; void bindToUi() { registerCombos(); foreach (QWidget *widget, m_bindWidgets) { const char* prop = widget->metaObject()->userProperty().name(); QVariant value = ((QObject*)m_entity.data())->property(widget->objectName().toStdString().c_str()); if (value.canConvert()) { widget->setProperty(prop, value.value().toString()); } else { widget->setProperty(prop, value); } } foreach (QComboBox *combo, m_bindCombos.keys()) { int idx = 0; QVariant field = ((QObject*)m_entity.data())->property(combo->objectName().toStdString().c_str()); combo->clear(); for (int i = 0; i < m_bindCombos[combo].size(); i++) { ComboData data = m_bindCombos[combo][i]; combo->addItem(data.label(), data.index()); if (data.index().canConvert()) { ComboItem* ci = qobject_cast(data.index().value()); ComboItem* ciField = qobject_cast(field.value()); if (ci->eq(ciField)) { idx = i; } } else if (field == data.index()) { idx = i; } } combo->setCurrentIndex(idx); } bindOtherToUi(); } bool bindToData() { foreach (IValidator *val, m_validators) { if (!val->validate()) { emit validationError(val->errMessage()); return false; } } foreach (QWidget *widget, m_bindWidgets) { const char* prop = widget->metaObject()->userProperty().name(); QVariant val = widget->property(prop); if (((QObject*)m_entity.data())->property(widget->objectName().toStdString().c_str()).canConvert()) { QDecDouble dec(val.toDouble()); val = QVariant::fromValue(dec); } ((QObject*)m_entity.data())->setProperty(widget->objectName().toStdString().c_str(), val); } foreach (QComboBox *combo, m_bindCombos.keys()) { ((QObject*)m_entity.data())->setProperty(combo->objectName().toStdString().c_str(), combo->currentData()); } return bindOtherToData(); } public slots: bool saveRecord() { if (!bindToData()) { return false; } if (!m_serviceConnected) { connect(service(), &IService::dbError, [this](QString msg) { QMessageBox::critical(this, tr("Database error"), tr(msg.toStdString().c_str())); m_saved = false; }); connect(service(), &IService::dataChanged, [this]() { m_saved = true; }); m_serviceConnected = true; } if (m_newRec) { service()->save(entity()); if (m_saved) { emit recordAdded(); } } else { service()->update(entity()); if (m_saved) { emit recordUpdated(); } } return m_saved; } private: Service *service() { IPlugin *plugin = Context::instance().plugin(pluginId()); if (plugin == NULL) { Q_ASSERT(false); return NULL; } Service *service = plugin->service(); if (service == NULL) { Q_ASSERT(false); return NULL; } return service; } bool m_serviceConnected; bool m_saved; }; #endif // AUTOFORM_H