gui: Begin a tab redesign

I'm creating as many "static tabs" as I can using GtkBuilder, and
splitting their code out of tabs.cpp.  This should help to contain the
growth of this file and make all the code easier to work with.

This patch begins the redesign and adds beginning code for a new
collection tab.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2014-02-17 15:32:47 -05:00 committed by Anna Schumaker
parent 1434618381
commit 97511f82a9
5 changed files with 615 additions and 15 deletions

98
gui/collection.cpp Normal file
View File

@ -0,0 +1,98 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <deck.h>
#include <ocarina.h>
static Glib::RefPtr<PlayqueueModel> model;
/*
* Basic helper functions
*/
static inline Playqueue *library_pq()
{
return deck::get_library_pq();
}
static Gtk::ToggleButton *get_random_button()
{
return get_widget<Gtk::ToggleButton>("o_collection_random");
}
static void set_queue_size()
{
Gtk::Label *label = get_widget<Gtk::Label>("o_collection_size");
label->set_text(itoa(library_pq()->size()));
}
/*
* Gtk signal functions
*/
static void on_random_toggled()
{
if (get_random_button()->get_active())
library_pq()->set_flag(PQ_RANDOM);
else
library_pq()->unset_flag(PQ_RANDOM);
}
/*
* Functions exposed through a TabFuncs structure
*/
static void collection_init_late()
{
set_queue_size();
get_random_button()->set_active(library_pq()->get_flags() & PQ_RANDOM);
}
static void collection_cleanup() {}
static bool collection_has_queue(Playqueue *pq)
{
return pq == library_pq();
}
static void collection_track_added(Playqueue *pq, unsigned int row)
{
model->on_row_inserted(row);
set_queue_size();
}
static void collection_track_deleted(Playqueue *pq, unsigned int row)
{
model->on_row_deleted(row);
set_queue_size();
}
static struct TabFuncs collection_funcs = {
.init_late = collection_init_late,
.cleanup = collection_cleanup,
.has_queue = collection_has_queue,
.track_added = collection_track_added,
.track_deleted = collection_track_deleted,
};
/*
* Basic tab setup
*/
struct TabFuncs *init_collection_tab()
{
model = Glib::RefPtr<PlayqueueModel>(new PlayqueueModel(library_pq()));
get_widget<Gtk::TreeView>("o_collection_pq_treeview")->set_model(model);
get_random_button()->signal_toggled().connect(sigc::ptr_fun(on_random_toggled));
return &collection_funcs;
}

View File

@ -163,6 +163,435 @@
<property name="tab_pos">left</property>
<property name="scrollable">True</property>
<property name="enable_popup">True</property>
<child>
<object class="GtkBox" id="box15">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">1</property>
<property name="margin_right">1</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="box23">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="spacing">5</property>
<child>
<object class="GtkSearchEntry" id="searchentry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="o_collection_random">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
<object class="GtkImage" id="image17">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">media-playlist-shuffle</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">2</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_bottom">5</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="o_collection_pq_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
<property name="rubber_banding">True</property>
<property name="tooltip_column">9</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection2">
<property name="mode">multiple</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn4">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">20</property>
<property name="title" translatable="yes">#</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext3"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn5">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">300</property>
<property name="title" translatable="yes">Title</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext4"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn6">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">60</property>
<property name="title" translatable="yes">Length</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext5"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn7">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">100</property>
<property name="title" translatable="yes">Artist</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext6"/>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn8">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">100</property>
<property name="title" translatable="yes">Album</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext7"/>
<attributes>
<attribute name="text">4</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn9">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">45</property>
<property name="title" translatable="yes">Year</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext8"/>
<attributes>
<attribute name="text">5</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn10">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">100</property>
<property name="title" translatable="yes">Genre</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext9"/>
<attributes>
<attribute name="text">6</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn11">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">60</property>
<property name="title" translatable="yes">Count</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext10"/>
<attributes>
<attribute name="text">7</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn12">
<property name="resizable">True</property>
<property name="sizing">fixed</property>
<property name="fixed_width">1</property>
<property name="title" translatable="yes">Played</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext11"/>
<attributes>
<attribute name="text">8</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="tab">
<object class="GtkBox" id="box18">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">5</property>
<child>
<object class="GtkImage" id="image14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="icon_name">media-optical</property>
<property name="icon_size">1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box19">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">1</property>
<property name="label" translatable="yes">&lt;big&gt;Collection&lt;/big&gt;</property>
<property name="use_markup">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="o_collection_size">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box16">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<object class="GtkBox" id="box20">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">5</property>
<child>
<object class="GtkImage" id="image15">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="icon_name">document-open-recent</property>
<property name="icon_size">1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box21">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">1</property>
<property name="label" translatable="yes">&lt;big&gt;History&lt;/big&gt;</property>
<property name="use_markup">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">0</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box17">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child type="tab">
<object class="GtkBox" id="box22">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">5</property>
<child>
<object class="GtkImage" id="image16">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="icon_name">emblem-documents</property>
<property name="icon_size">1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">1</property>
<property name="label" translatable="yes">Playlist
Manager</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box8">
<property name="visible">True</property>
@ -408,6 +837,9 @@
</packing>
</child>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child type="tab">
<object class="GtkBox" id="box1">
@ -418,6 +850,7 @@
<object class="GtkImage" id="image8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="icon_name">system-file-manager</property>
<property name="icon_size">1</property>
</object>
@ -431,18 +864,20 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">1</property>
<property name="label" translatable="yes">Collection
Manager</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">3</property>
<property name="tab_fill">False</property>
</packing>
</child>
@ -485,7 +920,7 @@ Manager</property>
<child>
<object class="GtkScale" id="o_position_scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="adjustment">o_progress</property>
<property name="round_digits">1</property>
<property name="draw_value">False</property>
@ -524,7 +959,7 @@ Manager</property>
<child>
<object class="GtkButton" id="o_play">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -543,7 +978,7 @@ Manager</property>
</child>
<child>
<object class="GtkButton" id="o_pause">
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -563,7 +998,7 @@ Manager</property>
<child>
<object class="GtkButton" id="o_stop">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -583,7 +1018,7 @@ Manager</property>
<child>
<object class="GtkButton" id="o_prev">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -603,7 +1038,7 @@ Manager</property>
<child>
<object class="GtkButton" id="o_next">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -634,7 +1069,7 @@ Manager</property>
<child>
<object class="GtkToggleButton" id="o_favorite">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -654,7 +1089,7 @@ Manager</property>
<child>
<object class="GtkToggleButton" id="o_ban">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">True</property>
<property name="focus_on_click">False</property>
<child>
@ -686,7 +1121,7 @@ Manager</property>
<object class="GtkCheckButton" id="o_pause_enabled">
<property name="label" translatable="yes">Pause after </property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="focus_on_click">False</property>
<property name="xalign">0</property>
@ -702,6 +1137,7 @@ Manager</property>
<object class="GtkSpinButton" id="o_pause_count">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="caps_lock_warning">False</property>
<property name="adjustment">adjustment1</property>
<property name="numeric">True</property>
</object>

View File

@ -9,6 +9,7 @@
#include <playlist.h>
#include <playqueue.h>
#include <list>
#include <map>
#include <set>
#include <sstream>
@ -16,6 +17,7 @@
class OcarinaPage;
static std::map<Playqueue *, OcarinaPage *> tab_map;
static std::list<TabFuncs *> tab_types;
static unsigned int sort_timeout_count = 0;
static class SidebarColumns : public Gtk::TreeModelColumnRecord {
@ -761,12 +763,28 @@ void OcarinaPage::on_focus_search()
/*
* Do stuff with tabs
*/
static TabFuncs *find_tab_funcs(Playqueue *pq)
{
std::list<TabFuncs *>::iterator tab_it;
for (tab_it = tab_types.begin(); tab_it != tab_types.end(); tab_it++) {
if ((*tab_it)->has_queue(pq))
return *tab_it;
}
return NULL;
}
static void on_track_added(Playqueue *pq, unsigned int row)
{
std::map<Playqueue *, OcarinaPage *>::iterator it;
it = tab_map.find(pq);
if (it != tab_map.end())
it->second->on_row_inserted(row);
struct TabFuncs *tab;
tab = find_tab_funcs(pq);
if (tab)
tab->track_added(pq, row);
}
static void on_track_deleted(Playqueue *pq, unsigned int row)
@ -775,6 +793,11 @@ static void on_track_deleted(Playqueue *pq, unsigned int row)
it = tab_map.find(pq);
if (it != tab_map.end())
it->second->on_row_deleted(row);
struct TabFuncs *tab;
tab = find_tab_funcs(pq);
if (tab)
tab->track_deleted(pq, row);
}
static void on_track_changed(Playqueue *pq, unsigned int row)
@ -794,7 +817,7 @@ static void on_switch_page(Gtk::Widget *page, int num)
get_builder()->get_widget("o_queue_time", label);
get_builder()->get_widget("o_notebook", notebook);
if (num >= notebook->get_n_pages() - 1)
if (num >= notebook->get_n_pages() - 4)
label->hide();
else {
tab->on_runtime_changed();
@ -856,7 +879,7 @@ void queue_selected(bool random)
}
}
static void on_new_queue()
/*static void on_new_queue()
{
queue_selected(false);
}
@ -877,7 +900,7 @@ static void init_menu_item(const std::string &name, unsigned int num)
Glib::RefPtr<Gtk::MenuItem>menu = Glib::RefPtr<Gtk::MenuItem>::cast_static(get_builder()->get_object(name));
menu->signal_activate().connect(sigc::bind<unsigned int> (
sigc::ptr_fun(on_add_to_queue), num));
}
}*/
void focus_tab_search()
{
@ -906,7 +929,7 @@ void init_tabs()
get_callbacks()->on_queue_track_changed = on_track_changed;
Glib::RefPtr<Gtk::MenuItem> new_pq = Glib::RefPtr<Gtk::MenuItem>::cast_static(get_builder()->get_object("o_new_pq"));
/*Glib::RefPtr<Gtk::MenuItem> new_pq = Glib::RefPtr<Gtk::MenuItem>::cast_static(get_builder()->get_object("o_new_pq"));
new_pq->signal_activate().connect(sigc::ptr_fun(on_new_queue));
init_menu_item("o_pq_0", 0);
@ -918,7 +941,9 @@ void init_tabs()
init_menu_item("o_pq_6", 6);
init_menu_item("o_pq_7", 7);
init_menu_item("o_pq_8", 8);
init_menu_item("o_pq_9", 9);
init_menu_item("o_pq_9", 9);*/
tab_types.push_back(init_collection_tab());
notebook->signal_switch_page().connect(sigc::ptr_fun(on_switch_page));
notebook->signal_page_reordered().connect(sigc::ptr_fun(on_page_reordered));
@ -930,10 +955,18 @@ void init_tabs2()
std::map<Playqueue *, OcarinaPage *>::iterator it;
for (it = tab_map.begin(); it != tab_map.end(); it++)
it->second->check_pq_flags();
std::list<TabFuncs *>::iterator tab_it;
for (tab_it = tab_types.begin(); tab_it != tab_types.end(); tab_it++)
(*tab_it)->init_late();
}
void cleanup_tabs()
{
while (tab_map.size() > 0)
delete tab_map.begin()->second;
std::list<TabFuncs *>::iterator it;
for (it = tab_types.begin(); it != tab_types.end(); it++)
(*it)->cleanup();
}

View File

@ -5,14 +5,20 @@
#define OCARINA_H
#include <playqueue.h>
#include <tabs.h>
#include <gtkmm.h>
/* collection.cpp */
struct TabFuncs *init_collection_tab();
/* collection_mgr.cpp */
void collection_mgr_init();
/* main.cpp */
Gtk::Window *ocarina_init(int *, char ***);
/* model.cpp */
class PlayqueueModel : public Gtk::TreeModel, public Glib::Object {
private:
@ -51,6 +57,7 @@ public:
unsigned int path_to_id(const Gtk::TreePath &);
};
/* tabs.cpp */
void queue_selected(bool);
void focus_tab_search();
@ -58,6 +65,7 @@ void init_tabs();
void init_tabs2();
void cleanup_tabs();
/* wires.cpp */
void enable_idle();
void connect_button(const std::string &, void (*func)());

25
include/tabs.h Normal file
View File

@ -0,0 +1,25 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#ifndef OCARINA_TABS_H
#define OCARINA_TABS_H
#include <sstream>
struct TabFuncs {
void (*init_late)();
void (*cleanup)();
bool (*has_queue)(Playqueue *);
void (*track_added)(Playqueue *, unsigned int);
void (*track_deleted)(Playqueue *, unsigned int);
};
static inline std::string itoa(unsigned int i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
#endif /* OCARINA_TABS_H */