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());
}