#pragma once #include "fusion_static_dispatch.hpp" #include "gui_item_delegate.hpp" #include "boost_any_qvariant_convert.hpp" #include #include #include #include #include #include #include template struct QValidator_impl { static constexpr bool needed = false; typedef void type; }; template <> struct QValidator_impl { static constexpr bool needed = true; typedef QIntValidator type; }; template <> struct QValidator_impl { static constexpr bool needed = true; typedef QDoubleValidator type; }; template struct QValidatorFor { static constexpr bool needed = QValidator_impl::value, std::is_floating_point::value>::needed; typedef typename QValidator_impl::value, std::is_floating_point::value>::type type; }; template struct CreateWidget { typedef QLineEdit* return_type; template static typename std::enable_if::type set_validator_if_needed(QLineEdit* edit) { edit->setValidator(new V()); } template static typename std::enable_if::type set_validator_if_needed(QLineEdit*) { return; } template static return_type call() { QLineEdit* edit = new QLineEdit(); typedef typename friendly_fusion::utils::DecayedTypeOfAtIndex::type value_type; typedef QValidatorFor QValiGen; set_validator_if_needed(edit); edit->setReadOnly(is_const(I)); return edit; } }; template struct StringToBoostAny { typedef boost::any return_type; template static return_type call(std::string str) { typedef typename friendly_fusion::utils::DecayedTypeOfAtIndex::type value_type; std::stringstream ss(str); value_type x; ss >> x; return boost::any(x); } }; class FormUpdateHandler : public QObject { Q_OBJECT public: QLineEdit* edit; std::function cb; FormUpdateHandler(QLineEdit* edit, std::function cb) : edit(edit) , cb(cb) { connect(edit, SIGNAL(textEdited(QString const&)), this, SLOT(edited(QString const&))); } private slots: void edited(QString const& str) { cb(str.toStdString()); } }; template struct Form : public QFormLayout{ std::shared_ptr model; QMdiArea* area; std::vector> updatehandlers; std::map> line_edits; GuiItemDelegate delegate; Form(std::shared_ptr model) : model(model) , area(new QMdiArea()) , updatehandlers() , line_edits() , delegate() { area->setLayout(this); setup_gui(); fill_data(); } void setup_gui() { for(int i = 0; i < model->row_count(); ++i) { for(int j = 0; j < model->column_count(); j++) { QLineEdit* edit = apply_functor_to_member(j); updatehandlers.push_back(std::make_shared(edit, [i, j, this](std::string str){update_nth(i, j, str);})); line_edits[i][j] = edit; this->addRow( new QLabel(QString::fromStdString(model->field_name(j))), edit ); } } } void fill_data() { for(int i = 0; i < model->row_count(); ++i) { for(int j = 0; j < model->column_count(); j++) { line_edits[i][j]->setText(delegate.displayText(to_qvariant(model->get_cell(i, j), j))); } } } void update_nth(int row, int column, std::string str) { model->set_cell(row, column, apply_functor_to_member(column, str)); } QWidget* get_widget() { return area; } };