2 * Copyright (C) 2009 by Aiwota Programmer
3 * aiwotaprog@tetteke.tk
5 * This file is part of Dialektos.
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.
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.
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/>.
21 #ifndef THREAD_LIST_MODEL_HXX
22 #define THREAD_LIST_MODEL_HXX
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>
41 namespace model_column {
43 template <typename T, int ID = 0>
46 enum { Identifyer = ID };
49 template <typename TypeHolderT>
51 FieldHolder() : data_() {}
52 typedef typename TypeHolderT::type ValueType;
56 template <typename TypeHolderT>
57 inline typename TypeHolderT::type& field(FieldHolder<TypeHolderT>& t) {
60 template <typename TypeHolderT>
61 inline const typename TypeHolderT::type& field(const FieldHolder<TypeHolderT>& t) {
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;
73 } // namespace model_column
76 struct ModelColumns : public boost::mpl::inherit_linearly<
78 boost::mpl::inherit<boost::mpl::_1, model_column::FieldHolder<boost::mpl::_2> >
80 typedef model_column::List type;
84 template <typename TypeHolderT, typename ValueType> struct DoCompare;
85 template <typename TypeHolderT, typename ValueType> struct DoCompareReverse;
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);
95 if (left.empty() && right.empty()) return false;
96 if (left.empty()) return false;
97 if (right.empty()) return true;
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);
111 if (left.empty() && right.empty()) return false;
112 if (left.empty()) return false;
113 if (right.empty()) return true;
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);
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;
128 return left_num < right_num;
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);
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;
140 return left_num > right_num;
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);
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;
153 return left_num < right_num;
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);
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;
165 return left_num > right_num;
169 template <typename TypeHolderT>
170 struct Compare : public DoCompare<TypeHolderT, typename TypeHolderT::type> {};
172 template <typename TypeHolderT>
173 struct CompareReverse :
174 public DoCompareReverse<TypeHolderT, typename TypeHolderT::type> {};
179 class ThreadListModel : public Glib::Object, public Gtk::TreeModel {
181 typedef Gtk::TreeModel::iterator iterator;
183 static Glib::RefPtr<ThreadListModel> create();
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);
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;
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;
216 void do_after_sort();
218 typedef std::vector<ModelColumns> StoreType;
219 typedef boost::unordered_map<model_column::ID::type, size_t> OrderType;
224 boost::function<bool (const ModelColumns&, const ModelColumns&)>
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>();
235 } // namespace dialektos