/* * Copyright 2014 (c) Anna Schumaker. * * See the example at: * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/others/treemodelcustom */ #include #include #include #include QueueModel::QueueModel(Queue *q) : Glib::ObjectBase( typeid(QueueModel) ), Glib::Object(), queue(q) { do { stamp = rand(); } while (stamp == 0); } void QueueModel::increment_stamp() { do { stamp++; } while (stamp == 0); } void QueueModel::on_row_inserted(unsigned int row) { Gtk::TreePath path; Gtk::TreeIter iter; path.push_back(row); increment_stamp(); row_inserted(path, iter); } void QueueModel::on_row_deleted(unsigned int row) { Gtk::TreePath path; path.push_back(row); increment_stamp(); row_deleted(path); } void QueueModel::on_row_changed(unsigned int row) { Gtk::TreePath path; Gtk::TreeIter iter; path.push_back(row); increment_stamp(); row_changed(path, iter); } void QueueModel::on_path_selected(const Gtk::TreePath &path) { audio :: load_track(tagdb :: lookup(path_to_id(path))); queue->track_selected(path[0]); audio :: play(); } unsigned int QueueModel :: iter_to_id(const Gtk::TreeIter &iter) { return GPOINTER_TO_UINT(iter.gobj()->user_data); } unsigned int QueueModel::path_to_id(const Gtk::TreePath &path) { return queue->operator[](path[0])->id; } /* * * Function overrides begin here * */ Gtk::TreeModelFlags QueueModel::get_flags_vfunc() const { return Gtk::TREE_MODEL_LIST_ONLY; } int QueueModel::get_n_columns_vfunc() const { return 10; } GType QueueModel::get_column_type_vfunc(int index) const { switch (index) { case 0: case 5: case 7: return G_TYPE_UINT; case 1: case 2: case 3: case 4: case 6: case 8: case 9: return G_TYPE_STRING; default: return 0; } } void QueueModel::get_value_uint(Track *track, int column, Glib::ValueBase &value) const { Glib::Value specific; specific.init(Glib::Value::value_type()); switch (column) { case 0: specific.set(track->track); break; case 5: specific.set(track->album->year); break; case 7: specific.set(track->play_count); } value.init(Glib::Value::value_type()); value = specific; } void QueueModel::get_value_str(Track *track, int column, Glib::ValueBase &value) const { std::stringstream ss; Glib::Value specific; specific.init(Glib::Value::value_type()); switch (column) { case 1: specific.set(track->title); break; case 2: specific.set(track->length_str); break; case 3: specific.set(track->artist->name); break; case 4: specific.set(track->album->name); break; case 6: specific.set(track->genre->name); break; case 8: if (track->play_count == 0) specific.set("Never"); else { ss << track->last_month << " / "; ss << track->last_day << " / "; ss << track->last_year; specific.set(ss.str()); } break; case 9: specific.set(Glib::Markup::escape_text(track->path())); } value.init(Glib::Value::value_type()); value = specific; } void QueueModel::get_value_vfunc(const Gtk::TreeIter &iter, int column, Glib::ValueBase &value) const { unsigned int row; Track *track; if (!check_iter_validity(iter)) return; if (column > get_n_columns_vfunc()) return; row = GPOINTER_TO_UINT(iter.gobj()->user_data); track = queue->operator[](row); switch (column) { case 0: case 5: case 7: get_value_uint(track, column, value); break; default: get_value_str(track, column, value); } } bool QueueModel::iter_next_vfunc(const Gtk::TreeIter &iter, Gtk::TreeIter &iter_next) const { unsigned int index; if (!check_iter_validity(iter)) { iter_next = Gtk::TreeIter(); return false; } index = GPOINTER_TO_UINT(iter.gobj()->user_data); return iter_nth_root_child_vfunc(++index, iter_next); } bool QueueModel::iter_children_vfunc(const Gtk::TreeIter &parent, Gtk::TreeIter &iter) const { return iter_nth_child_vfunc(parent, 0, iter); } bool QueueModel::iter_has_child_vfunc(const Gtk::TreeIter &iter) const { return (iter_n_children_vfunc(iter) > 0); } int QueueModel::iter_n_children_vfunc(const Gtk::TreeIter &iter) const { return 0; } int QueueModel::iter_n_root_children_vfunc() const { return queue->size(); } bool QueueModel::iter_nth_child_vfunc(const Gtk::TreeIter &parent, int n, Gtk::TreeIter &iter) const { iter = Gtk::TreeIter(); return false; } bool QueueModel::iter_nth_root_child_vfunc(int n, Gtk::TreeIter &iter) const { iter = Gtk::TreeIter(); if (n >= (int)queue->size()) return false; iter.set_stamp(stamp); iter.gobj()->user_data = GUINT_TO_POINTER(n); return true; } bool QueueModel::iter_parent_vfunc(const Gtk::TreeIter &child, Gtk::TreeIter &iter) const { iter = Gtk::TreeIter(); return false; } Gtk::TreeModel::Path QueueModel::get_path_vfunc(const Gtk::TreeIter &iter) const { Gtk::TreeModel::Path path; if (check_iter_validity(iter)) path.push_back(GPOINTER_TO_UINT(iter.gobj()->user_data)); return path; } bool QueueModel::get_iter_vfunc(const Gtk::TreePath &path, Gtk::TreeIter &iter) const { if (path.size() != 1) { iter = Gtk::TreeIter(); return false; } return iter_nth_root_child_vfunc(path[0], iter); } bool QueueModel::check_iter_validity(const Gtk::TreeIter &iter) const { return stamp == iter.get_stamp(); }