summaryrefslogtreecommitdiff
path: root/form.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'form.hpp')
-rw-r--r--form.hpp198
1 files changed, 174 insertions, 24 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 <QMdiArea>
+#include <QVBoxLayout>
#include <QFormLayout>
#include <QLineEdit>
#include <QLabel>
#include <QValidator>
+#include <QPushButton>
#include <memory>
#include <sstream>
@@ -88,12 +91,30 @@ struct StringToBoostAny {
std::stringstream ss(str);
value_type x;
- ss >> x;
+ ss >> std::boolalpha >> x;
return boost::any(x);
}
};
+template <typename T>
+struct BoostAnyToString {
+
+ typedef std::string return_type;
+
+ template <int I>
+ static return_type call(boost::any any)
+ {
+ typedef typename friendly_fusion::utils::DecayedTypeOfAtIndex<T, I>::type value_type;
+
+ std::stringstream ss;
+ ss << std::boolalpha << boost::any_cast<value_type>(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 <typename T>
-struct Form : public QFormLayout{
+struct Form : public QtFormBase, public FusionModelObserver {
std::shared_ptr<T> model;
QMdiArea* area;
+ QVBoxLayout* layout;
+ QFormLayout* form_layout;
+ QHBoxLayout* button_layout;
+ QPushButton* prev;
+ QLineEdit* jump_edit;
+ QPushButton* next;
std::vector<std::shared_ptr<FormUpdateHandler>> updatehandlers;
- std::map<int, std::map<int, QLineEdit*>> line_edits;
- GuiItemDelegate delegate;
+ std::map<int, QLineEdit*> line_edits;
+
+ int current_index;
Form(std::shared_ptr<T> 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<typename T::row_type, CreateWidget>(j);
- updatehandlers.push_back(std::make_shared<FormUpdateHandler>(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<typename T::row_type, CreateWidget>(j);
+ updatehandlers.push_back(std::make_shared<FormUpdateHandler>(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<typename T::row_type, BoostAnyToString>(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<typename T::row_type>(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<typename T::row_type, StringToBoostAny>(entry, str));
+ }
+
+ void set_current_index(int i)
{
- model->set_cell(row, column, apply_functor_to_member<typename T::row_type, StringToBoostAny>(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 <typename Model>
+std::shared_ptr<Form<Model>> make_form(std::shared_ptr<Model> model)
+{
+ auto ret = std::make_shared<Form<Model>>(model);
+ model->add_observer(ret);
+ return ret;
+}