[Zinf-commits] zinf/ui/musicbrowsermm/src gtkmain.cpp,NONE,1.1 gtkplaylistmodel.cpp,1.1,1.2 musicbro
Brought to you by:
kgk,
mayhemchaos
From: <tur...@us...> - 2005-02-07 23:31:16
|
Update of /cvsroot/zinf/zinf/ui/musicbrowsermm/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24219/ui/musicbrowsermm/src Modified Files: gtkplaylistmodel.cpp musicbrowsermm.cpp playlistcontrol.cpp gtkplaylist.cpp Added Files: gtkmain.cpp Log Message: Revision: zin...@so.../zinf--cvstrunk--1--patch-3 Update BrowserMM Patches applied: * da...@th...--2004/zinf--browsermm--0.5--patch-46 Add Custom Layout... Dialog * da...@th...--2004/zinf--browsermm--0.5--patch-47 Make threading simpler by running all code from within GTK Main Loop * da...@th...--2004/zinf--browsermm--0.5--patch-48 Simplify the dialog blocking code as no longer nned to run outside of gtk main loop * da...@th...--2004/zinf--browsermm--0.5--patch-49 Reduce Locking When Looking Up Metadata In Playlist * da...@th...--2004/zinf--browsermm--0.5--patch-50 Parse out Playlist names from URL better * da...@th...--2004/zinf--browsermm--0.5--patch-51 Start of better documentation * da...@th...--2004/zinf--browsermm--0.5--patch-52 Read metadata when visible rows doesn't change but visible URLs does * da...@th...--2004/zinf--browsermm--0.5--patch-53 Use Glib::Dispatcher for much better performance when using main_thread_call * da...@th...--2004/zinf--browsermm--0.5--patch-54 Make it possible to use MusicBrowserMM as primary UI * da...@th...--2004/zinf--browsermm--0.5--patch-55 Make sure browser only shows error message when running as primary UI * da...@th...--2004/zinf--browsermm--0.5--patch-56 Get rid of Glade dependency * da...@th...--2004/zinf--browsermm--0.5--patch-57 Get rid of old glade directory * da...@th...--2004/zinf--browsermm--0.5--patch-58 Don't use autosize columns in the playlist --- NEW FILE: gtkmain.cpp --- #include <glibmm/main.h> #include <glibmm/thread.h> #include <glibmm/dispatcher.h> #include <gdk/gdk.h> #include <gtkmm/main.h> #include "gtkmain.h" namespace MusicBrowserMM { ///Pointer to single GtkUtil instance GtkUtil* GtkUtil::m_instance = NULL; GtkUtil* GtkUtil::instance() { if(!m_instance) { //Need to to create the single instance m_instance = new GtkUtil(); } return m_instance; } GtkUtil::GtkUtil() { //Init variables m_main_thread = NULL; m_dispatcher = NULL; m_function_queue_lock = NULL; } GtkUtil::~GtkUtil() { //Delete variables if(m_main_thread) destroy(); delete m_dispatcher; delete m_function_queue_lock; } void GtkUtil::init(FAContext *context) { //Acquire GTK+ Setup Lock context->gtkLock.Acquire(); //Init GTK+/GTKMM Gtk::Main main(context->argc, context->argv); //Check if we need to create main thread if(!context->gtkInitialized) { //Make sure thread stuff works Glib::thread_init(); //Create thread - Use condition to wait for notification thread has started Glib::Mutex start_lock; Glib::Cond start_condition; start_lock.lock(); m_main_thread = Glib::Thread::create(sigc::bind(sigc::mem_fun(*this, &GtkUtil::gtk_main_loop), &start_lock, &start_condition), true); //Wait for thread to signal its started start_condition.wait(start_lock); start_lock.unlock(); //Flag as inited & running context->gtkInitialized = true; context->gtkRunning = true; } //Release GTK+ Setup Lock context->gtkLock.Release(); //Create dispatcher m_dispatcher = new Glib::Dispatcher(); m_function_queue_lock = new Glib::Mutex(); //Attach call_function to dispatcher signal m_dispatcher->connect(sigc::mem_fun(*this, &GtkUtil::call_function)); } void GtkUtil::gtk_main_loop(Glib::Mutex *start_lock, Glib::Cond *start_cond) { //Signal that we've started start_lock->lock(); start_cond->signal(); start_lock->unlock(); //Run Main Loop Gtk::Main::instance()->run(); } void GtkUtil::destroy() { //If we started main loop if(m_main_thread) { //Quit main loop gdk_threads_enter(); Gtk::Main::instance()->quit(); gdk_threads_leave(); //Wait for it to exit, and destroy it m_main_thread->join(); m_main_thread = NULL; } } void GtkUtil::call(const sigc::slot<void>& function, bool wait) { if(!wait) { //Simply add to queue m_function_queue_lock->lock(); m_function_queue.push(function); m_function_queue_lock->unlock(); //Dispatch signal m_dispatcher->emit(); } else { //We need to wait, use mutex/cond for signalling Glib::Mutex wait_mutex; Glib::Cond wait_cond; //Queue wrapped function m_function_queue_lock->lock(); m_function_queue.push(sigc::bind(sigc::mem_fun(*this, &GtkUtil::function_wait_wrapper), function, &wait_mutex, &wait_cond)); m_function_queue_lock->unlock(); //Dispatch signal, and wait for completed signal wait_mutex.lock(); m_dispatcher->emit(); wait_cond.wait(wait_mutex); wait_mutex.unlock(); } } void GtkUtil::call_function() { //Read Function Off Queue sigc::slot<void> function; { Glib::Mutex::Lock locked(*m_function_queue_lock); function = m_function_queue.front(); m_function_queue.pop(); } //Call function from in gdk_thread_lock gdk_threads_enter(); function(); gdk_threads_leave(); } /** * Wrapper function, that locks wait_mutex, and signals wait_cond when function completed. * Function is called from within gdk thread lock. */ void GtkUtil::function_wait_wrapper(const sigc::slot<void>& function, Glib::Mutex *wait_mutex, Glib::Cond *wait_cond) { //Lock wait mutex till locked goes out of scope Glib::Mutex::Lock locked(*wait_mutex); //Call wrapped function function(); //Signal completion, and indicate timeout no longer needed wait_cond->signal(); } } // arch-tag: 1d79a27d-ea62-4fe4-9734-a9f30c85fc25 Index: gtkplaylistmodel.cpp =================================================================== RCS file: /cvsroot/zinf/zinf/ui/musicbrowsermm/src/gtkplaylistmodel.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** gtkplaylistmodel.cpp 29 Nov 2004 01:46:36 -0000 1.1 --- gtkplaylistmodel.cpp 7 Feb 2005 23:30:26 -0000 1.2 *************** *** 11,14 **** --- 11,15 ---- #include "gtkplaylistmodel.h" #include "eventdata.h" + #include "gtkmain.h" namespace MusicBrowserMM { *************** *** 61,65 **** //Create metadata read thread ! metadata_rows_lock = new Glib::Mutex(); metadata_cache_lock = new Glib::Mutex(); metadata_cond = new Glib::Cond(); --- 62,66 ---- //Create metadata read thread ! metadata_urls_lock = new Glib::Mutex(); metadata_cache_lock = new Glib::Mutex(); metadata_cond = new Glib::Cond(); *************** *** 75,79 **** metadata_thread->join(); delete metadata_cond; ! delete metadata_rows_lock; delete metadata_cache_lock; } --- 76,80 ---- metadata_thread->join(); delete metadata_cond; ! delete metadata_urls_lock; delete metadata_cache_lock; } *************** *** 120,136 **** void GTKPlaylistModel::cache_rows(const std::vector<uint32_t>& rows) { //Calculate set difference, to get new rows only ! std::vector<uint32_t> set_diff; ! std::insert_iterator< std::vector<uint32_t> > to_insert(set_diff, set_diff.begin()); ! set_difference(rows.begin(), rows.end(), m_current_rows.begin(), m_current_rows.end(), to_insert); ! //Loop through rows, add to read stack ! //Top row wants to be first read, so should be added last ! std::vector<uint32_t>::reverse_iterator row; ! metadata_rows_lock->lock(); ! for(row = set_diff.rbegin(); row != set_diff.rend(); row++) { ! m_rows_to_read.push(*row); } ! metadata_rows_lock->unlock(); //Signal read thread --- 121,147 ---- void GTKPlaylistModel::cache_rows(const std::vector<uint32_t>& rows) { + //Get the urls these rows represent + std::vector< std::pair<uint32_t, std::string> > urls; + std::vector<uint32_t>::const_iterator row; + for(row = rows.begin(); row != rows.end(); row++) { + PlaylistItem *item_at; + if(item_at = m_plm->ItemAt(*row)) { + urls.push_back(std::pair<uint32_t, std::string>(*row, item_at->URL())); + } + } + //Calculate set difference, to get new rows only ! std::vector< std::pair<uint32_t, std::string> > set_diff; ! std::insert_iterator< std::vector< std::pair<uint32_t, std::string> > > to_insert(set_diff, set_diff.begin()); ! set_difference(urls.begin(), urls.end(), m_current_urls.begin(), m_current_urls.end(), to_insert); ! //Loop through urls, add to read stack ! //Top url wants to be first read, so should be added last ! std::vector< std::pair<uint32_t, std::string> >::reverse_iterator url; ! metadata_urls_lock->lock(); ! for(url = set_diff.rbegin(); url != set_diff.rend(); url++) { ! m_urls_to_read.push(*url); } ! metadata_urls_lock->unlock(); //Signal read thread *************** *** 138,142 **** //Update current rows ! m_current_rows = rows; } --- 149,153 ---- //Update current rows ! m_current_urls = urls; } *************** *** 151,178 **** while(!exit_read_thread) { //Wait for some rows, if needed ! metadata_rows_lock->lock(); ! while(!exit_read_thread && m_rows_to_read.empty()) ! metadata_cond->wait(*metadata_rows_lock); if(exit_read_thread) { //Did we just wake up to exit? ! metadata_rows_lock->unlock(); break; } ! //Get the next row to read ! uint32_t row = m_rows_to_read.top(); ! m_rows_to_read.pop(); ! metadata_rows_lock->unlock(); //Keep locking to minimum //Actually read/cache the metadata ! PlaylistItem* item_at = m_plm->ItemAt(row); ! if(item_at) { ! if(cache_url(item_at->URL())) { ! gdk_threads_enter(); ! send_updated_signal(row); //Only update if actually changed ! gdk_threads_leave(); ! } } } } void GTKPlaylistModel::refresh_row(uint32_t row) { --- 162,187 ---- while(!exit_read_thread) { //Wait for some rows, if needed ! metadata_urls_lock->lock(); ! while(!exit_read_thread && m_urls_to_read.empty()) ! metadata_cond->wait(*metadata_urls_lock); if(exit_read_thread) { //Did we just wake up to exit? ! metadata_urls_lock->unlock(); break; } ! //Get the next url to read ! std::pair<uint32_t, std::string> url = m_urls_to_read.top(); ! m_urls_to_read.pop(); ! metadata_urls_lock->unlock(); //Keep locking to minimum //Actually read/cache the metadata ! if(cache_url(url.second)) { //Only Update if actually changed ! //Call send_updated_signal - From Within GTK Main Loop ! //send_updated_signal(row); ! GtkUtil::instance()->call(sigc::bind(sigc::mem_fun(*this, >KPlaylistModel::send_updated_signal), url.first)); } } } + void GTKPlaylistModel::refresh_row(uint32_t row) { Index: musicbrowsermm.cpp =================================================================== RCS file: /cvsroot/zinf/zinf/ui/musicbrowsermm/src/musicbrowsermm.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** musicbrowsermm.cpp 29 Nov 2004 01:46:36 -0000 1.1 --- musicbrowsermm.cpp 7 Feb 2005 23:30:26 -0000 1.2 *************** *** 29,32 **** --- 29,33 ---- #include <gtkmm/stockid.h> #include <gdkmm/pixbuf.h> + #include <gtkmm/messagedialog.h> using namespace std; *************** *** 35,38 **** --- 36,40 ---- #include "player.h" + #include "gtkmain.h" #include "musicbrowsermm.h" #include "gtkplaylist.h" *************** *** 65,77 **** m_startupType = 0; m_master_browser = NULL; - m_gtk_main = NULL; } Error MusicBrowserMM_UI::Init(int32_t startup_level) { ! if ((m_startupType = startup_level) != SECONDARY_UI_STARTUP) { cout << _("The musicbrowser cannot run as the primary ui\n"); return kError_InitFailedSafely; ! } if (!getenv("DISPLAY")) --- 67,83 ---- m_startupType = 0; m_master_browser = NULL; } + /** + * Inits GTKMM and makes a call to init_main which is executed in the + * GTK Main Thread + */ Error MusicBrowserMM_UI::Init(int32_t startup_level) { ! m_startupType = startup_level; ! /*if ((m_startupType = startup_level) != SECONDARY_UI_STARTUP) { cout << _("The musicbrowser cannot run as the primary ui\n"); return kError_InitFailedSafely; ! }*/ if (!getenv("DISPLAY")) *************** *** 79,84 **** //Init GTKMM ! m_gtk_main = new Gtk::Main(m_context->argc, m_context->argv); //Init Playlist Controller PlaylistController::Init(); --- 85,102 ---- //Init GTKMM ! GtkUtil::instance()->init(m_context); ! ! //Initalise All GTKMM Stuff - From Within Main Loop ! GtkUtil::instance()->call(sigc::mem_fun(*this, &MusicBrowserMM_UI::init_main), false); + return kError_NoErr; + } + + /** + * Inits PlaylistController, creates stock icons + * and reads preferences + */ + void MusicBrowserMM_UI::init_main() + { //Init Playlist Controller PlaylistController::Init(); *************** *** 92,134 **** //Read Prefs read_prefs(); ! ! return kError_NoErr; } Error MusicBrowserMM_UI::AcceptEvent(Event *event) { switch (event->Type()) { case CMD_Cleanup: { - gdk_threads_enter(); m_master_browser->hide(); ! std::vector<PlaylistContainer *>::iterator browser; ! for(browser = m_containers.begin(); browser != m_containers.end(); browser++) { ! //It Will Clean Up Its Own Resources By Calling container_closed ! ((GTKBrowser *)(*browser))->hide(); ! } ! gdk_threads_leave(); m_context->target->AcceptEvent(new Event(INFO_ReadyToDieUI)); break; } case CMD_ToggleMusicBrowserUI: { - gdk_threads_enter(); if (m_master_browser->is_visible()) m_master_browser->hide(); else m_master_browser->show(); - gdk_threads_leave(); break; } case INFO_FileNotFound: { MissingFileEvent *mfe = (MissingFileEvent *)event; - - gdk_threads_enter(); - MissingFileDialog *file_dialog = new MissingFileDialog(m_context, mfe->Item()); file_dialog->run(); - delete file_dialog; ! gdk_threads_leave(); break; } --- 110,183 ---- //Read Prefs read_prefs(); ! ! //If primary ui, show master browser ! if(m_startupType == PRIMARY_UI) { ! m_master_browser->show(); ! //Listen for when master browser is shut, so we can quit ! m_master_browser->signal_hide().connect(sigc::mem_fun(*this, &MusicBrowserMM_UI::exit_zinf)); ! } } + void MusicBrowserMM_UI::exit_zinf() + { + //Send quit event + m_context->target->AcceptEvent(new Event(CMD_QuitPlayer)); + } + + /** + * Accepts events from Zinf. Events are processed in the GTK Main Thread + * via AcceptEventGTK. Waits for other thread to process the event before + * returning, otherwise Event object might get deleted early. + */ Error MusicBrowserMM_UI::AcceptEvent(Event *event) { + //Process Event In GTK Main Loop + GtkUtil::instance()->call(sigc::bind(sigc::mem_fun(*this, &MusicBrowserMM_UI::AcceptEventGTK), event), true); + + return kError_NoErr; + } + + /** + * Process event from Zinf. Executes inside the GTK Main Thread + */ + void MusicBrowserMM_UI::AcceptEventGTK(Event *event) + { switch (event->Type()) { case CMD_Cleanup: { m_master_browser->hide(); ! std::vector<PlaylistContainer *>::iterator browser; ! for(browser = m_containers.begin(); browser != m_containers.end(); browser++) { ! //It Will Clean Up Its Own Resources By Calling container_closed ! ((GTKBrowser *)(*browser))->hide(); ! } m_context->target->AcceptEvent(new Event(INFO_ReadyToDieUI)); break; } case CMD_ToggleMusicBrowserUI: { if (m_master_browser->is_visible()) m_master_browser->hide(); else m_master_browser->show(); break; } case INFO_FileNotFound: { + //Show missing file dialog MissingFileEvent *mfe = (MissingFileEvent *)event; MissingFileDialog *file_dialog = new MissingFileDialog(m_context, mfe->Item()); + file_dialog->run(); ! delete file_dialog; ! break; ! } ! case INFO_ErrorMessage: { ! if(m_startupType == PRIMARY_UI) { ! //Create message dialog ! ErrorMessageEvent *e = (ErrorMessageEvent *)event; ! Gtk::MessageDialog dialog(e->GetErrorMessage(), false, Gtk::MESSAGE_ERROR); + //Show it + dialog.run(); + } break; } *************** *** 137,140 **** --- 186,190 ---- // Fall Through default: { + //Send message to all browsers std::vector<PlaylistContainer *>::iterator browser; for (browser = m_containers.begin(); browser != m_containers.end(); browser++) *************** *** 143,154 **** } } - return kError_NoErr; - } - - void MusicBrowserMM_UI::read_prefs() - { - gdk_threads_enter(); - PlaylistController::read_prefs(); - gdk_threads_leave(); } --- 193,196 ---- *************** *** 180,183 **** --- 222,226 ---- }*/ + /**Creates a new GTKBrowser object*/ PlaylistContainer* MusicBrowserMM_UI::create_container() { *************** *** 185,188 **** --- 228,232 ---- } + /**Calls GTKBrowser.hide() function*/ void MusicBrowserMM_UI::close_container(PlaylistContainer *container) { Index: playlistcontrol.cpp =================================================================== RCS file: /cvsroot/zinf/zinf/ui/musicbrowsermm/src/playlistcontrol.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** playlistcontrol.cpp 29 Nov 2004 01:46:36 -0000 1.1 --- playlistcontrol.cpp 7 Feb 2005 23:30:26 -0000 1.2 *************** *** 26,29 **** --- 26,33 ---- } + /** + * Resets active playlist to the master playlist owned by Zinf, allowing Zinf to delete m_context->plm itself. + * Deletes all other created resources (containers and playlists) + */ PlaylistController::~PlaylistController() { *************** *** 42,45 **** --- 46,54 ---- } + /** + * Wraps the master playlists in a GTKPlaylist and creates a container + * to show it in. If master playlist/active playlist were saved, will load them + * from disk, and restore the correct position in the playlist. + */ void PlaylistController::Init() { *************** *** 92,95 **** --- 101,109 ---- } + /** + * Reads the Show Tabs, Save Playlist, Remember Active Playlist preferences. If tabs are not displayed + * this moves all playlists (apart from the master playlist) into their own new containers. If tabs are shown + * this moves all playlists in their own containers into the master container and disposes of the other containers. + */ void PlaylistController::read_prefs() { *************** *** 136,139 **** --- 150,156 ---- } + /** + * \brief Creates a new container and shows the given playlist in it. + */ void PlaylistController::new_container(GTKPlaylist *playlist) { *************** *** 149,152 **** --- 166,172 ---- } + /** + * \brief Removes all playlists from the container and closes them + */ void PlaylistController::delete_playlists(PlaylistContainer *container) { *************** *** 165,168 **** --- 185,192 ---- } + /** + * Creates a new empty playlist, sets it's name to be "New Playlist #n" + * and shows the playlist. + */ GTKPlaylist* PlaylistController::new_playlist() { *************** *** 183,186 **** --- 207,214 ---- } + /** + * Creates a new empty playlist, and tells it to read it's contents + * from the given url. The playlist is then shown + */ GTKPlaylist* PlaylistController::open_playlist(const std::string& url) { *************** *** 198,201 **** --- 226,233 ---- } + /** + * Shows the given playlist, either in a new container or + * by adding it to the master container. + */ void PlaylistController::add_playlist(GTKPlaylist *playlist) { *************** *** 209,212 **** --- 241,252 ---- } + /** + * Called after a container is closed. If the container holds the master it + * is saved to disk. If it holds the active playlist, the url of the active playlist + * is saved to preferences. If the active playlist has never been saved, so it doesn't have a url, + * it is saved to disk as ZinfDir() + activelist.m3u. + * + * The playlists and the container are then destroyed. + */ void PlaylistController::container_closed(PlaylistContainer *old_container) { *************** *** 270,273 **** --- 310,318 ---- } + /** + * Called after a container closes a playlist. If it was the active + * playlist, changes active playlist to master playlist. Deletes + * GTKPlaylist object. + */ void PlaylistController::playlist_closed(GTKPlaylist *old_playlist) { *************** *** 286,304 **** } ! void PlaylistController::show_master_playlist() ! { ! //Find GTKPlaylist That Represents Master Playlist ! std::vector<GTKPlaylist *>::iterator playlist; ! playlist = m_playlists.begin(); ! while( (playlist != m_playlists.end()) && ((*playlist)->get_plm() != m_context->plm) ) { ! playlist++; ! } ! ! //Master Playlist Should Be In Master Browser ! if(playlist != m_playlists.end()) { ! m_master_container->show_playlist(*playlist); ! } ! } ! void PlaylistController::set_active_playlist(GTKPlaylist *active_playlist) { --- 331,338 ---- } ! /** ! * Switches the playlist currently being played by Zinf. ! * Sends an INFO_ActivePlaylistChanged Event once the playlist has changed. ! */ void PlaylistController::set_active_playlist(GTKPlaylist *active_playlist) { *************** *** 336,339 **** --- 370,377 ---- } + /** + * Changes the current index of the given playlist. If the playlist is + * the active playlist, it will restart playback at new position. + */ void PlaylistController::start_playback(GTKPlaylist *playlist, uint32_t index) { *************** *** 357,360 **** --- 395,401 ---- ******************************/ + /** + * Adds the given playlist to m_playlists + */ void PlaylistContainer::manage_playlist(GTKPlaylist *playlist) { *************** *** 362,365 **** --- 403,409 ---- } + /** + * Removes the given playlists from m_playlists + */ void PlaylistContainer::unmanage_playlist(GTKPlaylist *playlist) { *************** *** 371,374 **** --- 415,421 ---- } + /** + * Copies m_playlists into playlists + */ void PlaylistContainer::get_managed_playlists(std::vector<GTKPlaylist *>& playlists) { Index: gtkplaylist.cpp =================================================================== RCS file: /cvsroot/zinf/zinf/ui/musicbrowsermm/src/gtkplaylist.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** gtkplaylist.cpp 29 Nov 2004 01:46:36 -0000 1.1 --- gtkplaylist.cpp 7 Feb 2005 23:30:27 -0000 1.2 *************** *** 4,7 **** --- 4,8 ---- #include <iostream> #include <iomanip> + #include <cstdlib> #include <time.h> #include <gtkmm/treerowreference.h> *************** *** 93,96 **** --- 94,106 ---- if(m_own_plm) delete m_plm; + + //Store column widths + std::ostringstream pref; + Glib::ListHandle<Gtk::TreeViewColumn*> cols = m_listMusic.get_columns(); + Glib::ListHandle<Gtk::TreeViewColumn*>::const_iterator col = cols.begin(); + for(; col != cols.end(); col++) { + pref << (*col)->get_width() << ','; + } + m_context->prefs->SetPrefString(kMusicBrowserHeaderWidthsPref, pref.str()); } *************** *** 98,110 **** { std::string cols; ! Gtk::TreeView::Column* addedCol; //Reset Columns m_listMusic.remove_all_columns(); ! m_listMusic.append_column("#", m_PlaylistCols.playlistposition); ! addedCol = m_listMusic.get_column(0); ! addedCol->add_attribute(*(addedCol->get_first_cell_renderer()), "weight", (int) m_PlaylistCols.fontweight.index()); ! //addedCol->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED); ! //((Gtk::CellRendererText*)(addedCol->get_first_cell_renderer()))->set_fixed_height_from_font(1); m_context->prefs->GetPrefString(kPlaylistHeaderColumnsPref, cols); --- 108,123 ---- { std::string cols; ! Gtk::TreeView::Column* new_column; //Reset Columns m_listMusic.remove_all_columns(); ! ! //Create playlist position column ! new_column = Gtk::manage( new Gtk::TreeViewColumn("#", m_PlaylistCols.playlistposition) ); ! new_column->add_attribute(*(new_column->get_first_cell_renderer()), "weight", (int) m_PlaylistCols.fontweight.index()); ! new_column->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED); ! new_column->set_resizable(); ! new_column->set_min_width(15); ! m_listMusic.append_column(*new_column); m_context->prefs->GetPrefString(kPlaylistHeaderColumnsPref, cols); *************** *** 118,122 **** std::string column_title; std::string column_field; - int new_col_index; //Get Title:field string --- 131,134 ---- *************** *** 139,155 **** } ! //Add Next Column m_PlaylistCols.add_metadata(column_field); ! new_col_index = m_listMusic.append_column(column_title, m_PlaylistCols[column_field]) - 1; //Set column attributes ! addedCol = m_listMusic.get_column(new_col_index); ! addedCol->add_attribute(*(addedCol->get_first_cell_renderer()), "weight", (int) m_PlaylistCols.fontweight.index()); ! addedCol->set_resizable(); ! //addedCol->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED); ! //((Gtk::CellRendererText*)(addedCol->get_first_cell_renderer()))->set_fixed_height_from_font(1); start_pos = end_pos + 1; } //Create Model m_modelMusic = Glib::RefPtr<GTKPlaylistModel>( new GTKPlaylistModel(m_plm, m_PlaylistCols, m_context->collection) ); --- 151,197 ---- } ! //Create Column m_PlaylistCols.add_metadata(column_field); ! new_column = Gtk::manage( new Gtk::TreeViewColumn(column_title, m_PlaylistCols[column_field]) ); //Set column attributes ! new_column->add_attribute(*(new_column->get_first_cell_renderer()), "weight", (int) m_PlaylistCols.fontweight.index()); ! new_column->set_resizable(); ! new_column->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED); ! new_column->set_fixed_width(15); ! ! //Add column ! m_listMusic.append_column(*new_column); ! ! //Move to next column start_pos = end_pos + 1; } + //Get column sizes + m_context->prefs->GetPrefString(kMusicBrowserHeaderWidthsPref, cols); + + //Loop through pref string + int column = 0; + start_pos = 0; + while(start_pos < cols.length()) { + int col_size; + + //Find end of number + end_pos = cols.find(",", start_pos); + if(end_pos == std::string::npos) + end_pos = cols.length(); + + //Get col_size + col_size = atoi(cols.substr(start_pos, end_pos - start_pos).c_str()); + + //Set column size + if(col_size > 0) + m_listMusic.get_column(column)->set_fixed_width(col_size); + + //Loop + start_pos = end_pos + 1; + column++; + } + //Create Model m_modelMusic = Glib::RefPtr<GTKPlaylistModel>( new GTKPlaylistModel(m_plm, m_PlaylistCols, m_context->collection) ); *************** *** 202,208 **** { //If we don't have a name, return the filename ! if(m_name == "") ! return Glib::path_get_basename(m_url); ! else return m_name; } --- 244,257 ---- { //If we don't have a name, return the filename ! if(m_name == "") { ! //Decode URL, and strip path and extension ! std::string name; ! URLToFilePath(m_url, name); ! name = Glib::path_get_basename(name); ! if(name.find('.') != std::string::npos) { ! name = name.substr(0, name.find('.')); ! } ! return name; ! } else return m_name; } |