/* * Copyright 2014 (c) Anna Schumaker. * * See the example at: * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/others/treemodelcustom */ #include #include #include QueueModel::QueueModel(Queue *q) : Glib::ObjectBase( typeid(QueueModel) ), Glib::Object(), _stamp(1), _queue(q) { } void QueueModel::increment_stamp() { if (++_stamp == 0) ++_stamp; } bool QueueModel::check_iter_validity(const Gtk::TreeIter &iter) const { return _stamp == iter.get_stamp(); } void QueueModel::on_row_inserted(unsigned int row) { increment_stamp(); row_inserted(Gtk::TreePath(1, row), Gtk::TreeIter()); } void QueueModel::on_row_deleted(unsigned int row) { increment_stamp(); row_deleted(Gtk::TreePath(1, row)); } void QueueModel::on_row_changed(unsigned int row) { increment_stamp(); row_changed(Gtk::TreePath(1, row), Gtk::TreeIter()); } void QueueModel::on_path_selected(const Gtk::TreePath &path) { audio :: load_track(tags :: get_track(path_to_id(path))); _queue->track_selected(path[0]); audio :: play(); } unsigned int QueueModel :: iter_to_id(const Gtk::TreeIter &iter) const { return GPOINTER_TO_UINT(iter.gobj()->user_data); } unsigned int QueueModel::path_to_id(const Gtk::TreePath &path) const { return _queue->operator[](path[0])->index(); } 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 { if (index > 9) return 0; if (index == 0 || index == 5 || index == 7) return G_TYPE_UINT; return G_TYPE_STRING; } template static void set_val(const T &t, Glib::ValueBase &value) { Glib::Value specific; specific.init(Glib::Value::value_type()); specific.set(t); value.init(specific.gobj()); } void QueueModel::get_value_vfunc(const Gtk::TreeIter &iter, int column, Glib::ValueBase &value) const { Track *track; if (!check_iter_validity(iter) || column > get_n_columns_vfunc()) return; track = _queue->operator[](iter_to_id(iter)); switch (column) { case 0: return set_val(track->track(), value); case 1: return set_val(track->name(), value); case 2: return set_val(track->length_str(), value); case 3: return set_val(track->artist()->name(), value); case 4: return set_val(track->album()->name(), value); case 5: return set_val(track->album()->year(), value); case 6: return set_val(track->genre()->name(), value); case 7: return set_val(track->count(), value); case 8: return set_val(track->date(), value); case 9: return set_val(Glib::Markup::escape_text(track->path()), value); } } bool QueueModel::iter_next_vfunc(const Gtk::TreeIter &iter, Gtk::TreeIter &next) const { next = Gtk::TreeIter(); if (check_iter_validity(iter)) return iter_nth_root_child_vfunc(iter_to_id(iter) + 1, next); return false; } int QueueModel::iter_n_root_children_vfunc() const { return _queue->size(); } 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; } Gtk::TreeModel::Path QueueModel::get_path_vfunc(const Gtk::TreeIter &iter) const { Gtk::TreeModel::Path path; if (check_iter_validity(iter)) path.push_back(iter_to_id(iter)); return path; } bool QueueModel::get_iter_vfunc(const Gtk::TreePath &path, Gtk::TreeIter &iter) const { iter = Gtk::TreeIter(); if (path.size() == 1) return iter_nth_root_child_vfunc(path[0], iter); return false; }