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 #include "thread_list_model.hxx"
23 #include <gtkmm/treemodel.h>
24 #include <gtkmm/treepath.h>
25 #include <boost/mpl/size.hpp>
26 #include <boost/mpl/for_each.hpp>
27 #include <boost/mpl/find.hpp>
28 #include <boost/mpl/pop_front.hpp>
29 #include <boost/foreach.hpp>
30 #include <boost/integer_traits.hpp>
35 namespace model_column {
37 struct GetColumnData {
39 const ModelColumns& model_columns,
41 Glib::ValueBase& data)
42 : index_(index), model_columns_(model_columns), data_(data) {
43 assert(index < unsigned(boost::mpl::size<ModelColumns::type>::value));
46 template <typename TypeHolderT>
47 void operator()(const TypeHolderT& /*t*/) {
48 using namespace boost::mpl;
49 if (index_ == unsigned(find<ModelColumns::type, TypeHolderT>::type::pos::value)) {
50 Glib::Value<typename TypeHolderT::type> value;
51 value.init(Glib::Value<typename TypeHolderT::type>::value_type());
53 value.set(field<TypeHolderT>(model_columns_));
54 data_.init(Glib::Value<typename TypeHolderT::type>::value_type());
60 const dialektos::ModelColumns& model_columns_;
61 Glib::ValueBase& data_;
64 struct GetColumnGType {
65 GetColumnGType(size_t index, GType& data) : index_(index), data_(data) {
66 assert(index < unsigned(boost::mpl::size<ModelColumns::type>::value));
69 template <typename TypeHolderT>
70 void operator()(const TypeHolderT& /*t*/) {
71 using namespace boost::mpl;
72 if (index_ == unsigned(find<ModelColumns::type, TypeHolderT>::type::pos::value)) {
73 data_ = Glib::Value<typename TypeHolderT::type>::value_type();
81 } // namespace model_column
84 struct CompareNumber {
85 CompareNumber(boost::unordered_map<std::string, ModelColumns>& cols) :
88 bool operator()(const std::string& lhs, const std::string& rhs) const {
89 boost::unordered_map<std::string, ModelColumns>::const_iterator it = cols_.find(lhs);
90 assert(it != cols_.end());
91 const ModelColumns& left_cols = it->second;
94 assert(it != cols_.end());
95 const ModelColumns& right_cols = it->second;
97 int left_num = model_column::field<model_column::Number>(left_cols);
98 int right_num = model_column::field<model_column::Number>(right_cols);
100 if (left_num == 0) left_num = boost::integer_traits<int>::const_max;
101 if (right_num == 0) right_num = boost::integer_traits<int>::const_max;
103 return left_num < right_num;
105 boost::unordered_map<std::string, ModelColumns>& cols_;
110 Glib::RefPtr<ThreadListModel> ThreadListModel::create() {
111 return Glib::RefPtr<ThreadListModel>(new ThreadListModel());
114 ThreadListModel::ThreadListModel():
115 Glib::ObjectBase(typeid(ThreadListModel)),
120 ThreadListModel::~ThreadListModel() {}
122 void ThreadListModel::append(const ModelColumns& record) {
123 const model_column::ID::type& id = model_column::field<model_column::ID>(record);
124 StoreType::iterator it = list_.find(id);
125 if (it != list_.end()) {
129 order_.push_back(model_column::field<model_column::ID>(record));
131 const size_t index = list_.size() -1;
133 iter.gobj()->stamp = 1;
134 iter.gobj()->user_data = GINT_TO_POINTER(index);
135 iter.gobj()->user_data2 = 0;
136 iter.gobj()->user_data3 = 0;
138 Gtk::TreeModel::Path path;
139 path.append_index(index);
140 row_inserted(path, iter);
144 void ThreadListModel::set_buffer(
145 const boost::unordered_map<model_column::ID::type, ModelColumns>& buffer) {
148 for(size_t i = 0; i != list_.size(); i++) {
149 Gtk::TreeModel::Path path;
150 path.append_index(0);
155 order_ = OrderType();
157 typedef std::pair<model_column::ID::type, ModelColumns> PairType;
158 BOOST_FOREACH(const PairType& pair, buffer) {
159 const ModelColumns& cols = pair.second;
163 boost::unordered_map<std::string, int> old_order;
164 for (size_t i = 0; i != order_.size(); ++i) old_order[order_[i]] = i;
166 std::sort(order_.begin(), order_.end(), CompareNumber(list_));
168 std::vector<int> new_order;
169 new_order.reserve(order_.size());
171 BOOST_FOREACH(const std::string& id, order_) {
172 new_order.push_back(old_order[id]);
175 if (!new_order.empty())
176 rows_reordered(Gtk::TreeModel::Path(), &(new_order[0]));
179 void ThreadListModel::get_buffer(
180 boost::unordered_map<model_column::ID::type, ModelColumns>& buffer) const {
184 const ModelColumns& ThreadListModel::get_model_columns(const size_t row_index) const {
185 assert(row_index < list_.size());
187 const std::string& id = order_[row_index];
188 StoreType::const_iterator it = list_.find(id);
190 assert(it != list_.end());
195 GType ThreadListModel::get_column_type_vfunc(const int index) const {
196 assert(index >= 0 && index < boost::mpl::size<ModelColumns::type>::value);
199 model_column::GetColumnGType functor(index, value);
200 boost::mpl::for_each<ModelColumns::type>(functor);
204 Gtk::TreeModelFlags ThreadListModel::get_flags_vfunc() const {
205 return Gtk::TREE_MODEL_LIST_ONLY;
208 int ThreadListModel::get_n_columns_vfunc() const {
209 return boost::mpl::size<ModelColumns::type>::value;
212 bool ThreadListModel::get_iter_vfunc(const Gtk::TreeModel::Path& path, iterator& iter) const {
213 assert(path.get_depth() == 1); // no children.
217 if (path.empty()) return false;
219 const size_t index = path.front();
221 if (index >= list_.size()) return false;
224 iter.gobj()->user_data = GINT_TO_POINTER(index);
229 Gtk::TreeModel::Path ThreadListModel::get_path_vfunc(const iterator& iter) const {
230 const GtkTreeIter* gtktreeiter = iter.gobj();
231 const size_t index = GPOINTER_TO_INT(gtktreeiter->user_data);
233 Gtk::TreeModel::Path path;
234 path.append_index(index);
238 void ThreadListModel::get_value_vfunc(const iterator& iter, const int column,
239 Glib::ValueBase& value) const {
241 if (iter.get_stamp() != 1) return;
242 if (column >= boost::mpl::size<model_column::List>::value) return;
244 const size_t index = GPOINTER_TO_INT(iter.gobj()->user_data);
245 if (index >= order_.size()) return;
247 const std::string& id = order_[index];
249 StoreType::const_iterator it = list_.find(id);
250 assert(it != list_.end());
252 const ModelColumns& record = it->second;
253 model_column::GetColumnData functor(record, column, value);
254 boost::mpl::for_each<model_column::List>(functor);
257 bool ThreadListModel::iter_children_vfunc(const iterator& parent,
258 iterator& iter) const {
259 return iter_nth_child_vfunc(parent, 0, iter);
262 bool ThreadListModel::iter_has_child_vfunc(const iterator& iter) const {
266 bool ThreadListModel::iter_is_valid(const iterator& iter) const {
267 return iter.gobj()->stamp == 1 && Gtk::TreeModel::iter_is_valid(iter);
270 int ThreadListModel::iter_n_children_vfunc(const iterator& iter) const {
274 int ThreadListModel::iter_n_root_children_vfunc() const {
278 bool ThreadListModel::iter_next_vfunc(const iterator& iter, iterator& iter_next) const {
279 iter_next = iterator();
281 if (iter.get_stamp() != 1) return false;
283 size_t index = GPOINTER_TO_INT(iter.gobj()->user_data);
286 if (index >= list_.size()) return false;
288 iter_next.gobj()->stamp = 1;
289 iter_next.gobj()->user_data = GINT_TO_POINTER(index);
294 bool ThreadListModel::iter_nth_child_vfunc(const iterator& parent, int n,
295 iterator& iter) const {
300 bool ThreadListModel::iter_nth_root_child_vfunc(int n, iterator& iter) const {
301 if (unsigned(n) >= list_.size()) return false;
303 const unsigned int row_index = n;
306 iter.gobj()->user_data = GINT_TO_POINTER(row_index);
310 bool ThreadListModel::iter_parent_vfunc(const iterator& child, iterator& iter) const {
316 } // namespace dialektos