diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | boost_any_qvariant_convert.hpp | 121 | ||||
| -rw-r--r-- | boost_any_to_qvariant.hpp | 67 | ||||
| -rw-r--r-- | fusion_model.hpp | 13 | ||||
| -rw-r--r-- | fusion_static_dispatch.hpp | 47 | ||||
| -rw-r--r-- | gui_item_delegate.cpp | 29 | ||||
| -rw-r--r-- | gui_item_delegate.hpp | 2 | ||||
| -rw-r--r-- | main.cpp | 2 | ||||
| -rw-r--r-- | qt_adapter.hpp | 19 |
9 files changed, 223 insertions, 79 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0427ed1..5a880f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ add_executable(msc-scriptie friendly_fusion.hpp fusion_static_dispatch.hpp meta_types.hpp - boost_any_to_qvariant.hpp + boost_any_qvariant_convert.hpp gui_item_delegate.hpp gui_item_delegate.cpp main_window.hpp main_window.cpp ${qt_sources} diff --git a/boost_any_qvariant_convert.hpp b/boost_any_qvariant_convert.hpp new file mode 100644 index 0000000..859623b --- /dev/null +++ b/boost_any_qvariant_convert.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include "friendly_fusion.hpp" +#include "index_list.hpp" + +#include <QVariant> + +#include <boost/any.hpp> + +#include <string> + +template<typename value_type> +QVariant to_qvariant(boost::any const& x) +{ + return QVariant::fromValue<value_type>(boost::any_cast<value_type>(x)); +} + +template <typename T, int n> +QVariant to_qvariant(boost::any const& x) +{ + typedef friendly_fusion::result_of::begin<T> begin; + typedef friendly_fusion::result_of::advance_c<typename begin::type, n> adv_it; + typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; + typedef typename std::decay<typename deref::type>::type value_type; + return to_qvariant<value_type>(x); +} + +#if defined( __GNUC__ ) && !defined( __clang__ ) +template <typename T, int index> +std::function<QVariant(boost::any const&)> to_qvariant_lambda() +{ + return [](boost::any const& any) + { + return convert<T, index>(any); + }; +} + +#endif //defined( __GNUC__ ) && !defined( __clang__ ) + +template<typename T, int... Indices> +QVariant to_qvariant(boost::any const& any, int index, indices<Indices...>) +{ + typedef std::function<QVariant(boost::any const&)> element_type; + static element_type table[] = + { +#if defined( __GNUC__ ) && !defined( __clang__ ) + //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 + to_qvariant_lambda<T, Indices>() + ... +#else + [](boost::any const& any){return to_qvariant<T, Indices>(any);} + ... +#endif //defined( __GNUC__ ) && !defined( __clang__ ) + }; + + return table[index](any); +} + +template <typename T> +QVariant to_qvariant(boost::any const& x, int index) +{ + typedef typename friendly_fusion::result_of::size<T>::type seq_size; + typedef typename build_indices<seq_size::value>::type indices_type; + + return to_qvariant<T>(x, index, indices_type{}); +} + +template<typename value_type> +boost::any to_boost_any(QVariant const& x) +{ + return boost::any(x.value<value_type>()); +} + +template <typename T, int n> +boost::any to_boost_any(QVariant const& x) +{ + typedef friendly_fusion::result_of::begin<T> begin; + typedef friendly_fusion::result_of::advance_c<typename begin::type, n> adv_it; + typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; + typedef typename std::decay<typename deref::type>::type value_type; + return to_boost_any<value_type>(x); +} + +#if defined( __GNUC__ ) && !defined( __clang__ ) +template <typename T, int index> +std::function<boost::any(QVariant const&)> to_qvariant_lambda() +{ + return [](QVariant const& value) + { + return to_boost_any<T, index>(value); + }; +} +#endif //defined( __GNUC__ ) && !defined( __clang__ ) + +template<typename T, int... Indices> +boost::any to_boost_any(QVariant const& value, int index, indices<Indices...>) +{ + typedef std::function<boost::any(QVariant const&)> element_type; + static element_type table[] = + { +#if defined( __GNUC__ ) && !defined( __clang__ ) + //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 + to_boost_any_lambda<T, Indices>() + ... +#else + [](QVariant const& value){return to_boost_any<T, Indices>(value);} + ... +#endif //defined( __GNUC__ ) && !defined( __clang__ ) + }; + + return table[index](value); +} + +template <typename T> +boost::any to_boost_any(QVariant const& x, int index) +{ + typedef typename friendly_fusion::result_of::size<T>::type seq_size; + typedef typename build_indices<seq_size::value>::type indices_type; + + return to_boost_any<T>(x, index, indices_type{}); +}
\ No newline at end of file diff --git a/boost_any_to_qvariant.hpp b/boost_any_to_qvariant.hpp deleted file mode 100644 index 6172c09..0000000 --- a/boost_any_to_qvariant.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "friendly_fusion.hpp" -#include "index_list.hpp" - -#include <QVariant> - -#include <boost/any.hpp> - -#include <string> - -template<typename value_type> -QVariant convert(boost::any const& x) -{ - return QVariant::fromValue<value_type>(boost::any_cast<value_type>(x)); -} - -template <typename T, int n> -QVariant convert(boost::any const& x) -{ - typedef friendly_fusion::result_of::begin<T> begin; - typedef friendly_fusion::result_of::advance_c<typename begin::type, n> adv_it; - typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; - typedef typename std::decay<typename deref::type>::type value_type; - return convert<value_type>(x); -} - -#if defined( __GNUC__ ) && !defined( __clang__ ) -template <typename T, int index> -std::function<QVariant(boost::any const&)> convert_lambda() -{ - return [](boost::any const& any) - { - return convert<T, index>(any); - }; -} - -#endif //defined( __GNUC__ ) && !defined( __clang__ ) - -template<typename T, int... Indices> -QVariant to_qvariant(boost::any const& any, int index, indices<Indices...>) -{ - typedef std::function<QVariant(boost::any const&)> element_type; - static element_type table[] = - { -#if defined( __GNUC__ ) && !defined( __clang__ ) - //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 - convert_lambda<T, Indices>() - ... -#else - [](boost::any const& any){return convert<T, Indices>(any);} - ... -#endif //defined( __GNUC__ ) && !defined( __clang__ ) - }; - - return table[index](any); -} - - -template <typename T> -QVariant to_qvariant(boost::any const& x, int index) -{ - typedef typename friendly_fusion::result_of::size<T>::type seq_size; - typedef typename build_indices<seq_size::value>::type indices_type; - - return to_qvariant<T>(x, index, indices_type{}); -}
\ No newline at end of file diff --git a/fusion_model.hpp b/fusion_model.hpp index f40ac33..4ccaa5b 100644 --- a/fusion_model.hpp +++ b/fusion_model.hpp @@ -23,6 +23,7 @@ struct FusionModelInterface { 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");} + virtual void set_cell(size_t row, size_t column, boost::any const& value) {throw std::runtime_error("\"set_cell(size_t, size_t, boost::any const&)\" not implemented for this model");} }; template <typename T> @@ -57,6 +58,11 @@ struct fusion_model<std::vector<T>> : public FusionModelInterface { return get_nth(data[row], column); } + + virtual void set_cell(size_t row, size_t column, boost::any const& value) override final + { + set_nth<row_type>(data[row], column, value); + } }; template <typename T> @@ -100,4 +106,11 @@ struct fusion_model<std::map<std::string, T>> : public FusionModelInterface std::advance(cit, row); return get_nth(cit->second, column); } + + virtual void set_cell(size_t row, size_t column, boost::any const& value) override final + { + auto it = data.begin(); + std::advance(it, row); + set_nth<row_type>(it->second, column, value); + } };
\ No newline at end of file diff --git a/fusion_static_dispatch.hpp b/fusion_static_dispatch.hpp index 8b68ba0..b0037a6 100644 --- a/fusion_static_dispatch.hpp +++ b/fusion_static_dispatch.hpp @@ -7,14 +7,6 @@ #include <functional> -template <typename T, int index> -struct TypeAt { - typedef friendly_fusion::result_of::begin<T> begin; - typedef friendly_fusion::result_of::advance_c<typename begin::type, index> adv_it; - typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; - typedef typename std::decay<typename deref::type>::type value_type; -}; - #if defined( __GNUC__ ) && !defined( __clang__ ) template<int index, typename T> std::function<boost::any(T)> make_at_c_lambda(T seq) @@ -62,6 +54,45 @@ boost::any get_nth(T x, int index) return get_nth_functor<T>()(x, index); } +template <typename T, int... Indices> +void set_nth_impl(T& seq, int index, boost::any const& value, indices<Indices...>) +{ + typedef std::function<void(T&, boost::any const&)> element_type; + static element_type table[] = + { + [](T& seq, boost::any const& value) + { + typedef friendly_fusion::result_of::begin<T> begin; + typedef friendly_fusion::result_of::advance_c<typename begin::type, Indices> adv_it; + typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; + typedef typename std::decay<typename deref::type>::type value_type; + + friendly_fusion::deref(friendly_fusion::advance_c<Indices>(friendly_fusion::begin(seq))) = boost::any_cast<value_type>(value); + } + ... + }; + + table[index](seq, value); +} + +template<typename T> +struct set_nth_functor +{ + void operator()(T& seq, int index, boost::any const& value) + { + typedef typename friendly_fusion::result_of::size<T>::type seq_size; + typedef typename build_indices<seq_size::value>::type indices_type; + + set_nth_impl(seq, index, value, indices_type{}); + } +}; + +template <typename T> +void set_nth(T& x, int index, boost::any const& value) +{ + set_nth_functor<T>()(x, index, value); +} + #if defined( __GNUC__ ) && !defined( __clang__ ) template<int index, typename T> std::function<std::string()> make_struct_member_name_lambda() diff --git a/gui_item_delegate.cpp b/gui_item_delegate.cpp index aba0727..7527020 100644 --- a/gui_item_delegate.cpp +++ b/gui_item_delegate.cpp @@ -2,11 +2,40 @@ #include "gui_item_delegate.hpp" +#include <QMetaProperty> +#include <iostream> + GuiItemDelegate::GuiItemDelegate(QObject *parent) : QStyledItemDelegate(parent) { } +void GuiItemDelegate::setModelData(QWidget* widget, QAbstractItemModel* model, const QModelIndex& index) const +{ + static int string_id = qMetaTypeId<std::string>(); + QByteArray n = widget->metaObject()->userProperty().name(); + QVariant variant = widget->property(n); + + if(variant.type() == QVariant::String) { + model->setData(index, QVariant::fromValue(variant.toString().toStdString()), Qt::EditRole); + } else { + QStyledItemDelegate::setModelData(widget, model, index); + } +} + +void GuiItemDelegate::setEditorData(QWidget* widget, const QModelIndex& index) const +{ + static int string_id = qMetaTypeId<std::string>(); + QVariant variant = index.data(Qt::EditRole); + QByteArray n = widget->metaObject()->userProperty().name(); + + if(string_id == variant.userType()) { + widget->setProperty(n, QVariant(QString::fromStdString(variant.value<std::string>()))); + } else { + QStyledItemDelegate::setEditorData(widget, index); + } +} + QString GuiItemDelegate::displayText(const QVariant &value, const QLocale &locale) const { QString ret; diff --git a/gui_item_delegate.hpp b/gui_item_delegate.hpp index d715dc2..b0f52a7 100644 --- a/gui_item_delegate.hpp +++ b/gui_item_delegate.hpp @@ -9,6 +9,8 @@ public: explicit GuiItemDelegate(QObject *parent = 0); virtual ~GuiItemDelegate() = default; + virtual void setModelData(QWidget* widget, QAbstractItemModel* model, QModelIndex const& index) const override final; + virtual void setEditorData(QWidget* widget, QModelIndex const& index) const override final; virtual QString displayText(const QVariant &value, const QLocale &locale) const override final; signals: @@ -68,5 +68,5 @@ int main() w.add_widget(&widget); w.add_widget(&widget2); - w.show_and_run(); + return w.show_and_run(); } diff --git a/qt_adapter.hpp b/qt_adapter.hpp index d19a35c..8af44d7 100644 --- a/qt_adapter.hpp +++ b/qt_adapter.hpp @@ -1,7 +1,7 @@ #pragma once #include "fusion_model.hpp" -#include "boost_any_to_qvariant.hpp" +#include "boost_any_qvariant_convert.hpp" #include "meta_types.hpp" #include "gui_item_delegate.hpp" @@ -67,6 +67,7 @@ struct QtWidget : public T { { T::setModel(this->model.get()); T::setItemDelegate(&delegate); + T::setEditTriggers(QAbstractItemView::DoubleClicked); } }; @@ -101,9 +102,23 @@ struct QtAdapter<T, QAbstractTableModel> : public QAbstractTableModel return model.column_count(); } + bool setData(QModelIndex const& index, QVariant const& value, int role) override final + { + if(role != Qt::EditRole) return false; + + model.set_cell(index.row(), index.column(), to_boost_any<typename T::row_type>(value, index.column())); + + return true; + } + + virtual Qt::ItemFlags flags(const QModelIndex &index) const + { + return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; + } + virtual QVariant data(QModelIndex const& index, int role) const override { - if(role != Qt::DisplayRole) return QVariant(); + if(role != Qt::DisplayRole && role != Qt::EditRole) return QVariant(); return to_qvariant<typename T::row_type>(model.get_cell(index.row(), index.column()), index.column()); } |
