diff options
| -rw-r--r-- | fusion_model.hpp | 71 | ||||
| -rw-r--r-- | fusion_static_dispatch.hpp | 2 | ||||
| -rw-r--r-- | main.cpp | 75 | ||||
| -rw-r--r-- | qt_adapter.hpp | 62 |
4 files changed, 164 insertions, 46 deletions
diff --git a/fusion_model.hpp b/fusion_model.hpp index ace8f51..f40ac33 100644 --- a/fusion_model.hpp +++ b/fusion_model.hpp @@ -9,44 +9,95 @@ #include <vector> #include <map> +#include <iostream> template <typename T> struct fusion_model { - +private: + fusion_model(T); +}; + +struct FusionModelInterface { + virtual size_t row_count() const {throw std::runtime_error("\"row_count()\" not implemented for this model");} + virtual size_t column_count() const {throw std::runtime_error("\"column_count()\" not implemented for this model");} + virtual std::string field_name(size_t section) const {throw std::runtime_error("\"field_name(size_t)\" not implemented for this model");} + virtual std::string key(size_t section) const {throw std::runtime_error("\"key(size_t)\" not implemented for this model");} + virtual boost::any get_cell(size_t row, size_t column) const {throw std::runtime_error("\"get_cell(size_t, size_t)\" not implemented for this model");} }; template <typename T> -struct fusion_model<std::vector<T>> +struct fusion_model<std::vector<T>> : public FusionModelInterface { - static_assert(boost::fusion::traits::is_sequence<T>::type::value, "T is not a boost fusion sequence"); + static_assert(friendly_fusion::traits::is_sequence<T>::type::value, "T is not a boost fusion sequence"); typedef std::vector<T> data_type; + typedef T row_type; + + static constexpr bool has_header_h = true; + static constexpr bool has_header_v = false; std::vector<T> data; - size_t row_count() const + virtual size_t row_count() const override final { return data.size(); } - size_t column_count() const + virtual size_t column_count() const override final { return boost::fusion::result_of::size<T>::type::value; } - std::string horizontal_header_data(size_t section) const + virtual std::string field_name(size_t section) const override final { return get_nth_name<T>(section); } - boost::any get_cell(size_t row, size_t column) const + virtual boost::any get_cell(size_t row, size_t column) const override final { return get_nth(data[row], column); } }; -template <typename T, typename U> -struct fusion_model<std::map<T, U>> +template <typename T> +struct fusion_model<std::map<std::string, T>> : public FusionModelInterface { - std::map<T, U> data; + static_assert(boost::fusion::traits::is_sequence<T>::type::value, "T is not a boost fusion sequence"); + + typedef std::map<std::string, T> data_type; + typedef T row_type; + + static constexpr bool has_header_h = true; + static constexpr bool has_header_v = true; + + std::map<std::string, T> data; + + virtual size_t row_count() const override final + { + return data.size(); + } + + virtual size_t column_count() const override final + { + return boost::fusion::result_of::size<T>::type::value; + } + + virtual std::string field_name(size_t section) const override final + { + return get_nth_name<T>(section); + } + + virtual std::string key(size_t section) const override final + { + auto cit = data.cbegin(); + std::advance(cit, section); + return cit->first; + } + + virtual boost::any get_cell(size_t row, size_t column) const override final + { + auto cit = data.cbegin(); + std::advance(cit, row); + return get_nth(cit->second, column); + } };
\ No newline at end of file diff --git a/fusion_static_dispatch.hpp b/fusion_static_dispatch.hpp index 17b6ff4..8b68ba0 100644 --- a/fusion_static_dispatch.hpp +++ b/fusion_static_dispatch.hpp @@ -5,6 +5,8 @@ #include <boost/any.hpp> +#include <functional> + template <typename T, int index> struct TypeAt { typedef friendly_fusion::result_of::begin<T> begin; @@ -2,19 +2,23 @@ #include "fusion_model.hpp" #include "qt_adapter.hpp" #include "gui_item_delegate.hpp" +#include "meta_types.hpp" #include <boost/fusion/adapted.hpp> #include <iostream> #include <QMainWindow> +#include <QHeaderView> +#include <QVBoxLayout> #include <QApplication> +#include <QMdiArea> struct Data { std::string name; uint32_t number; float ratio; - bool lolwut; + bool boolean; }; BOOST_FUSION_ADAPT_STRUCT( @@ -22,7 +26,7 @@ BOOST_FUSION_ADAPT_STRUCT( (std::string, name) (uint32_t, number) (float, ratio) - (bool, lolwut) + (bool, boolean) ) struct DataModel : public fusion_model<std::vector<Data>> { @@ -32,49 +36,62 @@ struct DataModel : public fusion_model<std::vector<Data>> { } }; +struct DataMapping :public fusion_model<std::map<std::string, Data>> { + void add_data(std::string key, Data value) + { + data.emplace(key, value); + } +}; + int main() { + Data d1{"Pietje", 2, 3.333f, true}; + Data d2{"Jantje", 3, 1.5f, false}; + Data d3{"Sjaakje", 1, 0.1337f, false}; + DataModel model; - model.add_data({"Pietje", 2, 3.333f, true}); - model.add_data({"Jantje", 3, 1.5f, false}); - model.add_data({"Sjaakje", 1, 0.1337f, false}); + model.add_data(d1); + model.add_data(d2); + model.add_data(d3); auto adapter = make_qt_adapter(model); + DataMapping mapping; + + mapping.add_data("nummer1", d1); + mapping.add_data("nummer2", d2); + mapping.add_data("nummer3", d3); + + auto&& adapter2 = make_qt_adapter(mapping); + int argc = 0; QApplication qapp(argc, nullptr); QMainWindow w; - - decltype(adapter)::element_type::view view; - view.setModel(adapter.get()); + widget_type<decltype(adapter)>::type widget; + widget.setFixedSize(640, 480); + widget.setModel(adapter.get()); + //widget.show(); - GuiItemDelegate delegate; - view.setItemDelegate(&delegate); + widget_type<decltype(adapter)>::type widget2; + widget2.setFixedSize(640, 480); + widget2.verticalHeader()->setEnabled(true); + widget2.setModel(adapter2.get()); + //widget2.show(); - view.show(); + QMdiArea area; - qapp.exec(); + QVBoxLayout layout; + + layout.addWidget(&widget); + layout.addWidget(&widget2); - for(int column = 0; column < model.column_count(); ++column) - { - std::cout << model.horizontal_header_data(column) << "\t"; - } - std::cout << std::endl; + area.setLayout(&layout); - for(int row = 0; row < model.row_count(); ++row) - { - for(int column = 0; column < model.column_count(); ++column) { - if(column == 0) { - std::cout << boost::any_cast<std::string>(model.get_cell(row, column)) << "\t"; - } else { - std::cout << boost::any_cast<uint32_t>(model.get_cell(row, column)) << "\t"; - } - } - std::cout << std::endl; - } + w.setCentralWidget(&area); + w.show(); - return 0; + return qapp.exec(); } diff --git a/qt_adapter.hpp b/qt_adapter.hpp index 2843667..6e0de17 100644 --- a/qt_adapter.hpp +++ b/qt_adapter.hpp @@ -3,14 +3,16 @@ #include "fusion_model.hpp" #include "boost_any_to_qvariant.hpp" #include "meta_types.hpp" +#include "gui_item_delegate.hpp" #include <QAbstractTableModel> #include <QTableView> +#include <QVariant> #include <QMetaType> #include <memory> - - +#include <string> +#include <iostream> template <typename T> struct QtModelType @@ -24,6 +26,34 @@ struct QtModelType<std::vector<V>> typedef QAbstractTableModel type; }; +template <typename V> +struct QtModelType<std::map<std::string, V>> +{ + typedef QAbstractTableModel type; +}; + +template <typename T> +struct widget_type { + typedef void type; +}; + +template <typename T> +struct widget_type<std::unique_ptr<T>> { + typedef typename T::widget type; +}; + +template <typename T> +struct QtWidget : public T { + + GuiItemDelegate delegate; + + QtWidget(QWidget* parent = nullptr) + : T(parent) + { + T::setItemDelegate(&delegate); + } +}; + template <typename T, typename Q> struct QtAdapter : public Q { @@ -37,6 +67,7 @@ template <typename T> struct QtAdapter<T, QAbstractTableModel> : public QAbstractTableModel { typedef QTableView view; + typedef QtWidget<view> widget; T model; @@ -54,16 +85,33 @@ struct QtAdapter<T, QAbstractTableModel> : public QAbstractTableModel return model.column_count(); } - virtual QVariant data(QModelIndex const& index, int role) const + virtual QVariant data(QModelIndex const& index, int role) const override { if(role != Qt::DisplayRole) return QVariant(); - return to_qvariant<typename T::data_type::value_type>(model.get_cell(index.row(), index.column()), index.column()); + return to_qvariant<typename T::row_type>(model.get_cell(index.row(), index.column()), index.column()); + } + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override + { + if(role != Qt::DisplayRole) { + return QVariant(); + } + + if(orientation == Qt::Horizontal && T::has_header_h) { + return QVariant(QString::fromStdString(model.field_name(section))); + } + + if(orientation == Qt::Vertical && T::has_header_v) { + return QVariant(QString::fromStdString(model.key(section))); + } + + return QVariant(); } }; - template <typename T> -std::shared_ptr<QtAdapter<T, typename QtModelType<typename T::data_type>::type>> make_qt_adapter(T value) { - return std::make_shared<QtAdapter<T, typename QtModelType<typename T::data_type>::type>>(value); +std::unique_ptr<QtAdapter<T, typename QtModelType<typename T::data_type>::type>> make_qt_adapter(T value) { + typedef QtAdapter<T, typename QtModelType<typename T::data_type>::type> type; + return std::unique_ptr<type>(new type(value)); } |
