From 79af684323abfa10abfc31003ab47fd89a03d625 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Tue, 27 May 2014 16:14:46 +0200 Subject: Tweaked the forms look and feal a bit and changed the way models are created. --- form.hpp | 198 ++++++++++++++++++++++++++++++++++++++++++++------- fusion_model.hpp | 12 ++-- fusion_outputter.hpp | 4 +- main.cpp | 31 +++++--- main_window.cpp | 1 + 5 files changed, 207 insertions(+), 39 deletions(-) diff --git a/form.hpp b/form.hpp index 15605a1..e90a3da 100644 --- a/form.hpp +++ b/form.hpp @@ -3,12 +3,15 @@ #include "fusion_static_dispatch.hpp" #include "gui_item_delegate.hpp" #include "boost_any_qvariant_convert.hpp" +#include "fusion_model.hpp" #include +#include #include #include #include #include +#include #include #include @@ -88,12 +91,30 @@ struct StringToBoostAny { std::stringstream ss(str); value_type x; - ss >> x; + ss >> std::boolalpha >> x; return boost::any(x); } }; +template +struct BoostAnyToString { + + typedef std::string return_type; + + template + static return_type call(boost::any any) + { + typedef typename friendly_fusion::utils::DecayedTypeOfAtIndex::type value_type; + + std::stringstream ss; + ss << std::boolalpha << boost::any_cast(any); + + return ss.str(); + } + +}; + class FormUpdateHandler : public QObject { @@ -107,8 +128,10 @@ public: : edit(edit) , cb(cb) { - connect(edit, SIGNAL(textEdited(QString const&)), - this, SLOT(edited(QString const&))); + connect( + edit, SIGNAL(textEdited(QString const&)), + this, SLOT(edited(QString const&)) + ); } private slots: @@ -119,54 +142,173 @@ private slots: }; +//This base is required because an QObject may not be templated and Form is a class template. +//Slots can be virtual however. +class QtFormBase : public QObject +{ + + Q_OBJECT + +protected slots: + virtual void prev_clicked() = 0; + virtual void jump() = 0; + virtual void next_clicked() = 0; +}; + template -struct Form : public QFormLayout{ +struct Form : public QtFormBase, public FusionModelObserver { std::shared_ptr model; QMdiArea* area; + QVBoxLayout* layout; + QFormLayout* form_layout; + QHBoxLayout* button_layout; + QPushButton* prev; + QLineEdit* jump_edit; + QPushButton* next; std::vector> updatehandlers; - std::map> line_edits; - GuiItemDelegate delegate; + std::map line_edits; + + int current_index; Form(std::shared_ptr model) : model(model) , area(new QMdiArea()) + , layout(new QVBoxLayout()) + , form_layout(new QFormLayout()) + , button_layout(new QHBoxLayout()) + , prev(new QPushButton("&Previous")) + , jump_edit(new QLineEdit()) + , next(new QPushButton("&Next")) , updatehandlers() , line_edits() - , delegate() + , current_index(0) { - area->setLayout(this); + layout->setAlignment(Qt::AlignTop); + + prev->setMaximumWidth(150); + + jump_edit->setValidator(new QIntValidator()); + jump_edit->setMaximumWidth(100); + + next->setMaximumWidth(150); + + layout->addLayout(form_layout); + layout->addLayout(button_layout); + + button_layout->addWidget(prev); + button_layout->addWidget(jump_edit); + button_layout->addWidget(next); + button_layout->setAlignment(Qt::AlignHCenter); + + area->setLayout(layout); + setup_gui(); fill_data(); + + area->updateGeometry(); + + set_button_state(); + connect( + prev, SIGNAL(clicked()), + this, SLOT(prev_clicked()) + ); + + connect( + jump_edit, SIGNAL(editingFinished()), + this, SLOT(jump()) + ); + + connect( + next, SIGNAL(clicked()), + this, SLOT(next_clicked()) + ); + + set_current_index(0); } 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 - ); - } + for(int j = 0; j < model->column_count(); j++) { + QLineEdit* edit = apply_functor_to_member(j); + updatehandlers.push_back(std::make_shared(edit, [j, this](std::string str){update_nth_in_model(j, str);})); + line_edits[j] = edit; + form_layout->addRow( + new QLabel(QString::fromStdString(model->field_name(j))), + edit + ); } } + void update_pos(int i, int j) + { + line_edits[j]->setText(QString::fromStdString(apply_functor_to_member(j, model->get_cell(i, j)))); + } + 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))); - } + for(int j = 0; j < model->column_count(); j++) { + update_pos(current_index, j); } } - void update_nth(int row, int column, std::string str) + void set_button_state() + { + prev->setEnabled(current_index != 0); + next->setEnabled(current_index != model->row_count() - 1); + } + + void update_nth_in_model(int entry, std::string str) + { + model->set_cell(current_index, entry, apply_functor_to_member(entry, str)); + } + + void set_current_index(int i) { - model->set_cell(row, column, apply_functor_to_member(column, str)); + current_index = i; + fill_data(); + set_button_state(); + jump_edit->setText(QString::number(i + 1)); + } + + int clamp_index(int i) + { + if(i < 0) { + i = 0; + } + + if(i > model->row_count() - 1) { + i = model->row_count() - 1; + } + + return i; + } + + //Observer interface + virtual void cell_changed(int form_id, int entry) override final + { + update_pos(form_id, entry); + } + + //Gui interface. + virtual void prev_clicked() override final + { + int i = clamp_index(current_index - 1); + set_current_index(i); + } + + virtual void jump() override final + { + int jump_to = jump_edit->text().toInt() - 1; + int i = clamp_index(jump_to); + + set_current_index(i); + } + + virtual void next_clicked() override final + { + int i = clamp_index(current_index + 1); + set_current_index(i); } QWidget* get_widget() @@ -174,3 +316,11 @@ struct Form : public QFormLayout{ return area; } }; + +template +std::shared_ptr> make_form(std::shared_ptr model) +{ + auto ret = std::make_shared>(model); + model->add_observer(ret); + return ret; +} diff --git a/fusion_model.hpp b/fusion_model.hpp index 3d84c87..d2fe950 100644 --- a/fusion_model.hpp +++ b/fusion_model.hpp @@ -94,9 +94,11 @@ struct FusionModel> : public FusionModelInterface typedef std::vector data_type; typedef T row_type; - std::vector data; + std::vector& data; - FusionModel() = default; + FusionModel(std::vector& data) + : data(data) + {} virtual size_t row_count() const override final { @@ -133,9 +135,11 @@ struct FusionModel> : public FusionModelInterface data_type; typedef T row_type; - std::map data; + std::map& data; - FusionModel() = default; + FusionModel(std::map& data) + : data(data) + {} virtual size_t row_count() const override final { diff --git a/fusion_outputter.hpp b/fusion_outputter.hpp index 3c3d5c4..a1a6927 100644 --- a/fusion_outputter.hpp +++ b/fusion_outputter.hpp @@ -39,8 +39,6 @@ struct Outputter { return os; } - - }; template @@ -48,7 +46,7 @@ std::ostream& operator<<(std::ostream& os, std::map map) { os << "{" << std::endl; for (auto&& x : map) { - os << "\t{" << x.first << ", " << x.second << "}" << std::endl; + os << "\t{" << x.first << ", " << "{" << x.second << "}}" << std::endl; } os << "}" << std::endl; return os; diff --git a/main.cpp b/main.cpp index 43f8513..b631722 100644 --- a/main.cpp +++ b/main.cpp @@ -12,6 +12,7 @@ struct Data { const std::string name; + std::string gender; uint32_t number; const double ratio1; double ratio2; @@ -21,6 +22,7 @@ struct Data { BOOST_FUSION_ADAPT_STRUCT( Data, (const std::string, name) + (std::string, gender) (uint32_t, number) (const double, ratio1) (double,ratio2) @@ -28,13 +30,26 @@ BOOST_FUSION_ADAPT_STRUCT( ) struct DataModel : public FusionModel> { + + std::vector model; + + DataModel() + : FusionModel(model) + {} + void add_data(Data d) { - data.push_back(d); + model.push_back(d); } - }; -struct DataMapping :public FusionModel> { +struct DataMapping : public FusionModel> { + + std::map model; + + DataMapping() + : FusionModel(model) + {} + void add_data(std::string key, Data value) { call_on_observers(&FusionModelObserver::append_row_begin); @@ -52,9 +67,9 @@ struct CustomDataModelWidget : public WidgetType::type int main() { - Data d1{"Pietje", 2, 3.333, 0.333, true}; - Data d2{"Jantje", 3, 1.5, 0.5, false}; - Data d3{"Sjaakje", 1, 0.1337, 0.0337, false}; + Data d1{"Jan", "Male", 1, 3.333, 0.333, true}; + Data d2{"Piet", "Male",2, 1.5, 0.5, false}; + Data d3{"Klaas", "Confused", 3, 0.1337, 0.0337, false}; auto model = std::make_shared(); @@ -74,9 +89,9 @@ int main() auto widget2 = make_qt_widget(model); auto widget3 = make_qt_widget(mapping); - Form form(model); + auto form = make_form(model); - w.add_widget(form.get_widget()); + w.add_widget(form->get_widget()); w.add_widget(widget1.get()); w.add_widget(widget2.get()); w.add_widget(widget3.get()); diff --git a/main_window.cpp b/main_window.cpp index 65daf3e..2affa7f 100644 --- a/main_window.cpp +++ b/main_window.cpp @@ -7,6 +7,7 @@ MainWindow::MainWindow() , area(new QMdiArea()) , layout(new QVBoxLayout()) { + layout->setAlignment(Qt::AlignTop); area->setLayout(layout); w.setCentralWidget(area); -- cgit v1.2.3-70-g09d2