Archive / / / / / / FileBrowserModel.cc
2008-10-06 11:18:27 UTC
previous next
/* Echo Media Player * Copyright (C) 2008 Shane O'Connell * * [ The original file includes a copyright header in this location describing * the file as being released under the terms of the GNU General Public * License. It has been removed in order to display the file as part of the * archive. ] */ #include <cassert> #include <iostream> #include <algorithm> #include "FileBrowserModel.h" FileBrowserModel::FileBrowserModel(const std::string& uri) : Glib::ObjectBase(typeid(FileBrowserModel)), Glib::Object(), m_stamp(1) { m_root_node = new Node(NULL, 0, "", uri, true, Glib::RefPtr<Gio::Icon>()); } GType FileBrowserModel::get_column_type_vfunc(int index) const { assert(index >= 0); assert(index < (int)get_columns().size()); return get_columns().types()[index]; } void FileBrowserModel::get_value_vfunc(const Gtk::TreeIter& iter, int column, Glib::ValueBase& value) const { assert(iter.get_stamp() == m_stamp); assert(iter.gobj()->user_data != NULL); assert(column >= 0); assert(column < (int)get_columns().size()); Node* node = (Node*)(iter.gobj()->user_data); Glib::Value<Glib::ustring> value_ustring; value_ustring.init(Glib::Value<Glib::ustring>::value_type()); Glib::Value<Glib::RefPtr<Gio::Icon> > value_icon; value_icon.init(Glib::Value<Glib::RefPtr<Gio::Icon> >::value_type()); value.init(get_column_type_vfunc(column)); switch (column) { case 0: // filename value_ustring.set(node->get_display_name()); value = value_ustring; break; case 1: // icon value_icon.set(node->get_icon()); value = value_icon; break; } } bool FileBrowserModel::get_iter_vfunc(const Gtk::TreePath& path, Gtk::TreeIter& iter) const { assert(path.size() > 0); Node* node = m_root_node; for (int i = 0; i < (int)path.size(); i++) { node = node->get_child(path[i]); if (!node) return false; } iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)node; return true; } Gtk::TreePath FileBrowserModel::get_path_vfunc(const Gtk::TreeIter& iter) const { assert(iter.get_stamp() == m_stamp); assert(iter.gobj()->user_data != NULL); Gtk::TreePath path; Node* node = (Node*)(iter.gobj()->user_data); while (node) { path.push_front(node->get_index()); node = node->get_parent(); } return path; } bool FileBrowserModel::iter_next_vfunc(const Gtk::TreeIter& iter, Gtk::TreeIter& iter_next) const { assert(iter.get_stamp() == m_stamp); assert(iter.gobj()->user_data != NULL); Node* node = (Node*)(iter.gobj()->user_data); node = node->get_parent()->get_child(node->get_index()+1); if (node) { iter_next.set_stamp(m_stamp); iter_next.gobj()->user_data = (void*)node; return true; } else { return false; } } int FileBrowserModel::iter_n_children_vfunc(const Gtk::TreeIter& iter) const { assert(iter.get_stamp() == m_stamp); assert(iter.gobj()->user_data != NULL); Node* node = (Node*)(iter.gobj()->user_data); return node->get_num_children(); } bool FileBrowserModel::iter_nth_child_vfunc(const Gtk::TreeIter& parent, int n, Gtk::TreeIter& iter) const { assert(parent.get_stamp() == m_stamp); assert(parent.gobj()->user_data != NULL); assert(n >= 0); Node* node = (Node*)(parent.gobj()->user_data); node = node->get_child(n); if (node) { iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)node; return true; } else { return false; } } bool FileBrowserModel::iter_nth_root_child_vfunc (int n, Gtk::TreeIter& iter) const { assert(n >= 0); if (m_root_node->get_child(n)) { iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)(m_root_node->get_child(n)); return true; } else { return false; } } bool FileBrowserModel::iter_parent_vfunc(const Gtk::TreeIter& child, Gtk::TreeIter& iter) const { assert(child.get_stamp() == m_stamp); assert(child.gobj()->user_data != NULL); Node* node = (Node*)(child.gobj()->user_data); node = node->get_parent(); if (node && node->get_parent()) { iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)node; return true; } else { return false; } } int FileBrowserModel::Node::get_num_children() { if (!m_children_known) add_children(); return m_children.size(); } FileBrowserModel::Node* FileBrowserModel::Node::get_child(int index) { assert(index >= 0); if (!m_children_known) add_children(); if (index >= (int)m_children.size()) { return NULL; } else { return &m_children[index]; } } void FileBrowserModel::Node::add_children() { if (m_children_known) return; Glib::RefPtr<Gio::File> parent = Gio::File::create_for_uri(m_uri); Glib::RefPtr<Gio::FileEnumerator> children; try { children = parent->enumerate_children("standard::type,standard::name,standard::display-name,standard::fast-content-type,standard::icon"); } catch (Glib::Error& e) { // TODO Handle error (file may have been deleted) // Maybe somehow send a signal to make the TreeModel update? m_children_known = true; return; } Glib::RefPtr<Gio::FileInfo> child; while(child = children->next_file()) { if (child->get_name().at(0) == '.') continue; if (child->get_file_type() != Gio::FILE_TYPE_DIRECTORY && child->get_attribute_string("standard::fast-content-type") != "audio/mpeg") continue; // TODO get a list of supported media content types from somewhere (gstreamer?) std::string uri = parent->get_child(child->get_name())->get_uri(); m_children.push_back(Node(this, 0, child->get_display_name(), uri, child->get_file_type() == Gio::FILE_TYPE_DIRECTORY, child->get_icon())); } sort(m_children.begin(), m_children.end()); for (int i = 0; i < (int)m_children.size(); i++) { m_children[i].m_index = i; } m_children_known = true; } bool FileBrowserModel::Node::operator<(const Node& other_node) const { if (is_directory() && !other_node.is_directory()) return true; if (!is_directory() && other_node.is_directory()) return false; return (m_display_name.casefold() < other_node.m_display_name.casefold()); }