OSDN Git Service

Board treeview is sortable.
[fukui-no-namari/dialektos.git] / src / thread_list_model.hxx
1 /*
2  * Copyright (C) 2009 by Aiwota Programmer
3  * aiwotaprog@tetteke.tk
4  *
5  * This file is part of Dialektos.
6  *
7  * Dialektos is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Dialektos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Dialektos.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #ifndef THREAD_LIST_MODEL_HXX
22 #define THREAD_LIST_MODEL_HXX
23
24 #include <glibmm/object.h>
25 #include <gtkmm/treemodel.h>
26 #include <boost/unordered_map.hpp>
27 #include <boost/mpl/vector.hpp>
28 #include <boost/mpl/find.hpp>
29 #include <boost/mpl/size.hpp>
30 #include <boost/mpl/inherit.hpp>
31 #include <boost/mpl/inherit_linearly.hpp>
32 #include <boost/array.hpp>
33 #include <boost/integer_traits.hpp>
34 #include <boost/function.hpp>
35 #include <string>
36 #include <vector>
37
38
39 namespace dialektos {
40
41 namespace model_column {
42
43 template <typename T, int ID = 0>
44 struct TypeHolder {
45   typedef T type;
46   enum { Identifyer = ID };
47 };
48
49 template <typename TypeHolderT>
50 struct FieldHolder {
51   FieldHolder() : data_() {}
52   typedef typename TypeHolderT::type ValueType;
53   ValueType data_;
54 };
55
56 template <typename TypeHolderT>
57 inline typename TypeHolderT::type& field(FieldHolder<TypeHolderT>& t) {
58   return t.data_;
59 }
60 template <typename TypeHolderT>
61 inline const typename TypeHolderT::type& field(const FieldHolder<TypeHolderT>& t) {
62   return t.data_;
63 }
64
65 typedef TypeHolder<int> Number;
66 typedef TypeHolder<int, 1> ResNum;
67 typedef TypeHolder<int, 2> LineCount;
68 typedef TypeHolder<double> Average;
69 typedef TypeHolder<std::string> Title;
70 typedef TypeHolder<std::string, 1> ID;
71 typedef boost::mpl::vector<ID, Number, Title, ResNum, LineCount, Average> List;
72
73 } // namespace model_column
74
75
76 struct ModelColumns : public boost::mpl::inherit_linearly<
77   model_column::List,
78   boost::mpl::inherit<boost::mpl::_1, model_column::FieldHolder<boost::mpl::_2> >
79   >::type {
80   typedef model_column::List type;
81 };
82
83 namespace {
84 template <typename TypeHolderT, typename ValueType> struct DoCompare;
85 template <typename TypeHolderT, typename ValueType> struct DoCompareReverse;
86
87 template <typename TypeHolderT>
88 struct DoCompare<TypeHolderT, std::string> :
89   public std::binary_function<ModelColumns, ModelColumns, bool> {
90   bool operator()(const ModelColumns& lhs, const ModelColumns& rhs) const {
91     typedef typename TypeHolderT::type ValueType;
92     const ValueType& left = model_column::field<TypeHolderT>(lhs);
93     const ValueType& right = model_column::field<TypeHolderT>(rhs);
94
95     if (left.empty() && right.empty()) return false;
96     if (left.empty()) return false;
97     if (right.empty()) return true;
98
99     return left < right;
100   }
101 };
102
103 template <typename TypeHolderT>
104 struct DoCompareReverse<TypeHolderT, std::string> :
105   public std::binary_function<ModelColumns, ModelColumns, bool> {
106   bool operator()(const ModelColumns& lhs, const ModelColumns& rhs) const {
107     typedef typename TypeHolderT::type ValueType;
108     const ValueType& left = model_column::field<TypeHolderT>(lhs);
109     const ValueType& right = model_column::field<TypeHolderT>(rhs);
110
111     if (left.empty() && right.empty()) return false;
112     if (left.empty()) return false;
113     if (right.empty()) return true;
114
115     return left > right;
116   }
117 };
118
119 template <typename ColumnType>
120 struct DoCompare<ColumnType, int> {
121   bool operator()(const ModelColumns& lhs, const ModelColumns& rhs) const {
122     int left_num = model_column::field<ColumnType>(lhs);
123     int right_num = model_column::field<ColumnType>(rhs);
124
125     if (left_num == 0) left_num = boost::integer_traits<int>::const_max;
126     if (right_num == 0) right_num = boost::integer_traits<int>::const_max;
127
128     return left_num < right_num;
129   }
130 };
131 template <typename ColumnType>
132 struct DoCompareReverse<ColumnType, int> {
133   bool operator()(const ModelColumns& lhs, const ModelColumns& rhs) const {
134     int left_num = model_column::field<ColumnType>(lhs);
135     int right_num = model_column::field<ColumnType>(rhs);
136
137     if (left_num == 0) left_num = boost::integer_traits<int>::const_min;
138     if (right_num == 0) right_num = boost::integer_traits<int>::const_min;
139
140     return left_num > right_num;
141   }
142 };
143
144 template <typename ColumnType>
145 struct DoCompare<ColumnType, double> {
146   bool operator()(const ModelColumns& lhs, const ModelColumns& rhs) const {
147     double left_num = model_column::field<ColumnType>(lhs);
148     double right_num = model_column::field<ColumnType>(rhs);
149
150     if (left_num == 0) left_num = boost::integer_traits<int>::const_max;
151     if (right_num == 0) right_num = boost::integer_traits<int>::const_max;
152
153     return left_num < right_num;
154   }
155 };
156 template <typename ColumnType>
157 struct DoCompareReverse<ColumnType, double> {
158   bool operator()(const ModelColumns& lhs, const ModelColumns& rhs) const {
159     double left_num = model_column::field<ColumnType>(lhs);
160     double right_num = model_column::field<ColumnType>(rhs);
161
162     if (left_num == 0) left_num = boost::integer_traits<int>::const_min;
163     if (right_num == 0) right_num = boost::integer_traits<int>::const_min;
164
165     return left_num > right_num;
166   }
167 };
168
169 template <typename TypeHolderT>
170 struct Compare : public DoCompare<TypeHolderT, typename TypeHolderT::type> {};
171
172 template <typename TypeHolderT>
173 struct CompareReverse :
174   public DoCompareReverse<TypeHolderT, typename TypeHolderT::type> {};
175
176 }
177
178
179 class ThreadListModel : public Glib::Object, public Gtk::TreeModel {
180 public:
181   typedef Gtk::TreeModel::iterator iterator;
182
183   static Glib::RefPtr<ThreadListModel> create();
184
185   virtual ~ThreadListModel();
186   void append(const ModelColumns& record);
187   void set_buffer(const boost::unordered_map<model_column::ID::type, ModelColumns>& buffer);
188   void get_buffer(boost::unordered_map<model_column::ID::type, ModelColumns>& buffer) const;
189   const ModelColumns& get_model_columns(size_t row_index) const;
190   void update_row(const ModelColumns& record);
191   template <typename TypeHolderT> void set_sort_function(bool ascendant);
192   void sort();
193 protected:
194   ThreadListModel();
195
196   virtual GType get_column_type_vfunc(int index) const;
197   virtual Gtk::TreeModelFlags get_flags_vfunc() const;
198   virtual int get_n_columns_vfunc() const;
199   virtual bool get_iter_vfunc(const Gtk::TreeModel::Path& path, iterator& iter) const;
200   virtual Gtk::TreeModel::Path get_path_vfunc(const iterator& iter) const;
201   virtual void get_value_vfunc(const iterator& iter, int column,
202       Glib::ValueBase& value) const;
203
204   virtual bool iter_children_vfunc(const iterator& parent, iterator& iter) const;
205   virtual bool iter_has_child_vfunc(const iterator& iter) const;
206   virtual bool iter_is_valid(const iterator& iter) const;
207   virtual int iter_n_children_vfunc(const iterator& iter) const;
208   virtual int iter_n_root_children_vfunc() const;
209   virtual bool iter_next_vfunc(const iterator& iter, iterator& iter_next) const;
210   virtual bool iter_nth_child_vfunc(const iterator& parent, int n,
211       iterator& iter) const;
212   virtual bool iter_nth_root_child_vfunc(int n, iterator& iter) const;
213   virtual bool iter_parent_vfunc(const iterator& child, iterator& iter) const;
214
215 private:
216   void do_after_sort();
217
218   typedef std::vector<ModelColumns> StoreType;
219   typedef boost::unordered_map<model_column::ID::type, size_t> OrderType;
220
221   StoreType list_;
222   OrderType order_;
223
224   boost::function<bool (const ModelColumns&, const ModelColumns&)>
225     sort_function_;
226 };
227
228 template <typename TypeHolderT>
229 void ThreadListModel::set_sort_function(bool ascendant) {
230   if (ascendant) sort_function_ = Compare<TypeHolderT>();
231   else sort_function_ = CompareReverse<TypeHolderT>();
232 }
233
234
235 } // namespace dialektos
236
237 #endif