summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2014-05-03 16:14:48 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2014-05-03 22:38:33 +0200
commit13cfd05f9b2bb3c8d7d1bf47fcef037a745bacf8 (patch)
tree98a325d0e547d5da0b0fd4b0b9ce2054306e87d0
parent5bf919190e90b017ff00ab074bce68e90958fa3c (diff)
downloadgeneric-gui-13cfd05f9b2bb3c8d7d1bf47fcef037a745bacf8.tar.gz
generic-gui-13cfd05f9b2bb3c8d7d1bf47fcef037a745bacf8.tar.bz2
generic-gui-13cfd05f9b2bb3c8d7d1bf47fcef037a745bacf8.zip
Adds editing functionality to the models.
no longer able to store QStrings in the model though, But when creating generic guis you should not use any Gui related types anyway.
-rw-r--r--CMakeLists.txt2
-rw-r--r--boost_any_qvariant_convert.hpp121
-rw-r--r--boost_any_to_qvariant.hpp67
-rw-r--r--fusion_model.hpp13
-rw-r--r--fusion_static_dispatch.hpp47
-rw-r--r--gui_item_delegate.cpp29
-rw-r--r--gui_item_delegate.hpp2
-rw-r--r--main.cpp2
-rw-r--r--qt_adapter.hpp19
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:
diff --git a/main.cpp b/main.cpp
index 380a3a9..6af725f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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());
}