Archive / / / / / / PlaySourceTreeModel.cc
2008-10-21 13:54:12 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 "PlaySourceTreeModel.h" #include "../../PlaybackManager.h" #include <cassert> #include <iostream> #include <memory> using namespace std; PlaySourceTreeModel::PlaySourceTreeModel(PlaySourceRef source) : Glib::ObjectBase( typeid(PlaySourceTreeModel) ), //register a custom GType. Glib::Object(), //The custom GType is actually registered here. m_source(source), m_stamp(1) { m_source->signal_track_removed().connect( sigc::mem_fun(*this, &PlaySourceTreeModel::on_source_row_deleted)); m_source->signal_track_inserted().connect( sigc::mem_fun(*this, &PlaySourceTreeModel::on_source_row_inserted)); m_source->signal_track_changed().connect( sigc::mem_fun(*this, &PlaySourceTreeModel::on_source_row_changed)); PlaybackManager::signal_track_started().connect( sigc::mem_fun(*this, &PlaySourceTreeModel::on_track_started)); PlaybackManager::signal_track_stopped().connect( sigc::mem_fun(*this, &PlaySourceTreeModel::on_track_stopped)); } Glib::RefPtr<PlaySourceTreeModel> PlaySourceTreeModel::create(PlaySourceRef source) { return Glib::RefPtr<PlaySourceTreeModel>(new PlaySourceTreeModel(source)); } void PlaySourceTreeModel::on_source_row_deleted(int index) { m_stamp++; Gtk::TreePath path; path.append_index(index); row_deleted(path); } void PlaySourceTreeModel::on_source_row_inserted(int index) { m_stamp++; Gtk::TreePath path; path.append_index(index); Gtk::TreeIter iter; iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)index; row_inserted(path, iter); } void PlaySourceTreeModel::on_source_row_changed(int index) { Gtk::TreePath path; path.append_index(index); Gtk::TreeIter iter; iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)index; row_changed(path, iter); } void PlaySourceTreeModel::on_track_started( PlaySourceRef playlist, int index, bool was_paused) { // Update to show the "currently playing" icon next to the track if (playlist == m_source) on_source_row_changed(index); } void PlaySourceTreeModel::on_track_stopped( PlaySourceRef playlist, int index, bool is_paused) { if (playlist == m_source) on_source_row_changed(index); } GType PlaySourceTreeModel::get_column_type_vfunc(int index) const { assert(index >= 0); assert(index < (int)m_column_records.size()); switch (index) { case 0: return m_column_records.title.type(); case 1: return m_column_records.artist.type(); case 2: return m_column_records.album.type(); case 3: return m_column_records.track_number.type(); default: return m_column_records.is_playing.type(); } } bool PlaySourceTreeModel::get_iter_vfunc(const Gtk::TreePath& path, Gtk::TreeIter& iter) const { assert(path[0] >= 0); if (path.size() != 1 || path[0] >= m_source->get_num_tracks()) { return false; } iter = Gtk::TreeIter(); iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)path[0]; return true; } Gtk::TreePath PlaySourceTreeModel::get_path_vfunc(const Gtk::TreeIter& iter) const { assert(iter.get_stamp() == m_stamp); int index = (int)(iter.gobj()->user_data); //cout << "get_path for " << index << endl; assert(index >= 0); assert(index < m_source->get_num_tracks()); Gtk::TreePath path; path.append_index((int)iter.gobj()->user_data); return path; } void PlaySourceTreeModel::get_value_vfunc(const Gtk::TreeIter& iter, int column, Glib::ValueBase& value) const { assert(iter.get_stamp() == m_stamp); int index = (int)(iter.gobj()->user_data); //if (column == 0) // cout << "get_value for " << index << endl; assert(index >= 0); assert(index < m_source->get_num_tracks()); Glib::Value<Glib::ustring> value_ustring; value_ustring.init(Glib::Value<Glib::ustring>::value_type()); Glib::Value<int> value_int; value_int.init(Glib::Value<int>::value_type()); Glib::Value<bool> value_bool; value_bool.init(Glib::Value<bool>::value_type()); assert(column >= 0); assert(column < (int)m_column_records.size()); switch (column) { case 0: // title value.init(Glib::Value<Glib::ustring>::value_type()); value_ustring.set(m_source->get_track(index)->get_title()); value = value_ustring; break; case 1: // artist value.init(Glib::Value<Glib::ustring>::value_type()); value_ustring.set(m_source->get_track(index)->get_artist()); value = value_ustring; break; case 2: // album value.init(Glib::Value<Glib::ustring>::value_type()); value_ustring.set(m_source->get_track(index)->get_album()); value = value_ustring; break; case 3: // track number value.init(Glib::Value<int>::value_type()); value_int.set(m_source->get_track(index)->get_track_number()); value = value_int; break; case 4: // is currently playing value.init(Glib::Value<bool>::value_type()); value_bool.set( PlaybackManager::get_playing_source() == m_source && PlaybackManager::get_playing_index() == index); value = value_bool; break; } } bool PlaySourceTreeModel::iter_next_vfunc(const Gtk::TreeIter& iter, Gtk::TreeIter& iter_next) const { assert(iter.get_stamp() == m_stamp); int index = (int)(iter.gobj()->user_data); //cout << "iter_next for " << index << " -> " << (index+1) << endl; assert(index >= 0); assert(index < m_source->get_num_tracks()); index++; if (index >= m_source->get_num_tracks()) { return false; } iter_next = Gtk::TreeIter(); iter_next.set_stamp(m_stamp); iter_next.gobj()->user_data = (void*)index; return true; } bool PlaySourceTreeModel::iter_nth_root_child_vfunc (int n, Gtk::TreeIter& iter) const { assert(n >= 0); //cout << "iter_nth_root_child for " << n << endl; if (n >= m_source->get_num_tracks()) { return false; } iter = Gtk::TreeIter(); iter.set_stamp(m_stamp); iter.gobj()->user_data = (void*)n; return true; } // Drag/drop functions bool PlaySourceTreeModel::row_draggable_vfunc (const Gtk::TreePath& path) const { assert(path.size() == 1); assert(path[0] >= 0); assert(path[0] < m_source->get_num_tracks()); return true; } bool PlaySourceTreeModel::drag_data_get_vfunc (const Gtk::TreePath& path, Gtk::SelectionData& selection_data) const { assert(path.size() == 1); assert(path[0] >= 0); assert(path[0] < m_source->get_num_tracks()); if (selection_data.get_target() == "PLAYLIST_ITEM") { DragData drag_data(m_source, path[0]); selection_data.set(selection_data.get_target(), 0, (guint8*)&drag_data, sizeof(drag_data)); return true; } return false; } bool PlaySourceTreeModel::drag_data_delete_vfunc (const Gtk::TreePath& path) { return false; } bool PlaySourceTreeModel::row_drop_possible_vfunc (const Gtk::TreePath& dest, const Gtk::SelectionData& selection_data) const { if (dest.size() != 1) { return false; } assert(dest[0] >= 0); return true; } bool PlaySourceTreeModel::drag_data_received_vfunc (const Gtk::TreePath& dest, const Gtk::SelectionData& selection_data) { assert(dest.size() == 1); assert(dest[0] >= 0); ModPlaySourceRef mod_source = boost::dynamic_pointer_cast<ModPlaySource>(m_source); assert(mod_source); // Make sure the source is a modifiable source int index = dest[0]; if (index >= m_source->get_num_tracks()) index = m_source->get_num_tracks(); if (selection_data.get_data_type() == "PLAYLIST_ITEM") { DragData* drag_data = (DragData*)selection_data.get_data(); if (drag_data->playlist == m_source) mod_source->move_track(drag_data->index, index); else { mod_source->insert_track(index, drag_data->playlist->get_track(drag_data->index)); // TODO should we move or copy tracks when dragged from another tab? //drag_data->playlist->remove_track(drag_data->index); } return true; } if (selection_data.get_data_type() == "text/uri-list") { mod_source->insert_from_uris(index, selection_data.get_uris()); return true; } return false; }