1
# Miro - an RSS based video player application
2
# Copyright (C) 2005-2010 Participatory Culture Foundation
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
# In addition, as a special exception, the copyright holders give
19
# permission to link the code of portions of this program with the OpenSSL
22
# You must obey the GNU General Public License in all respects for all of
23
# the code used other than OpenSSL. If you modify file(s) with this
24
# exception, you may extend this exception to your version of the file(s),
25
# but you are not obligated to do so. If you do not wish to do so, delete
26
# this exception statement from your version. If you delete this exception
27
# statement from all source files in the program, then also delete it here.
29
"""Manages the tab lists from a high level perspective."""
32
from miro import config
33
from miro import prefs
35
from miro.frontends.widgets import tablist
36
from miro.plat.frontends.widgets import widgetset
38
class TabListManager(object):
40
self.static_tab_list = tablist.StaticTabList()
41
self.library_tab_list = tablist.LibraryTabList()
42
self.site_list = tablist.SiteList()
43
self.feed_list = tablist.FeedList()
44
self.audio_feed_list = tablist.AudioFeedList()
45
self.playlist_list = tablist.PlaylistList()
46
self.widget_to_tablist = {}
47
for tab_list in self.all_tab_lists():
48
self.widget_to_tablist[tab_list.view] = tab_list
49
self.__table_view = None
51
def populate_tab_list(self):
52
self.static_tab_list.build_tabs()
53
self.library_tab_list.build_tabs()
54
self.select_startup_default()
55
for tab_list in self.all_tab_lists():
56
tab_list.view.connect('selection-changed',
57
self.on_selection_changed)
59
def _select_from_tab_list(self, tab_list, iter):
61
previous_selection = view.get_selection()
62
for previously_selected in previous_selection:
63
if (view.model[previously_selected][0] == view.model[iter][0]):
64
return # The tab is already selected
66
for previously_selected in previous_selection:
67
# We unselect *after* having made the new selection because if we
68
# unselect first and the selection is empty, the on_selection_changed
69
# callback forces the guide to be selected.
70
view.unselect(previously_selected)
71
self.selected_tab_list = tab_list
72
self.selected_tabs = [view.model[iter][0]]
73
self.handle_new_selection()
75
def handle_startup_selection(self):
76
self.handle_new_selection()
78
def handle_new_selection(self):
79
app.display_manager.select_display_for_tabs(self.selected_tab_list,
82
def which_tablist_has_id(self, feed_id):
84
Find out whether the video feed list or the audio feed list has this id
86
for tablist in self.feed_list, self.audio_feed_list:
87
if tablist.has_info(feed_id):
89
raise ValueError("Unknown feed id. %s" % feed_id)
91
def all_tab_lists(self):
93
self.static_tab_list, self.library_tab_list, self.site_list,
94
self.feed_list, self.audio_feed_list, self.playlist_list)
96
def select_guide(self):
97
self.select_static_tab(0)
99
def select_search(self):
100
self.select_static_tab(1)
103
def select_startup_default(self):
104
if config.get(prefs.OPEN_CHANNEL_ON_STARTUP) is not None:
105
# try regular feeds first, followed by audio feeds
106
for tab_list in self.feed_list, self.audio_feed_list:
107
info = tab_list.find_feed_with_url(
108
config.get(prefs.OPEN_CHANNEL_ON_STARTUP))
110
self._select_from_tab_list(
112
tab_list.iter_map[info.id])
115
if config.get(prefs.OPEN_FOLDER_ON_STARTUP) is not None:
116
for tab_list in self.feed_list, self.audio_feed_list:
117
for iter in tab_list.iter_map.values():
118
info = tab_list.view.model[iter][0]
119
if info.is_folder and info.name == config.get(
120
prefs.OPEN_FOLDER_ON_STARTUP):
121
self._select_from_tab_list(tab_list, iter)
123
# if we get here, the fallback default is the Guide
126
def select_static_tab(self, index):
127
iter = self.static_tab_list.view.model.nth_iter(index)
128
self._select_from_tab_list(self.static_tab_list, iter)
130
def handle_tablist_change(self, new_tablist):
131
self.selected_tab_list = new_tablist
132
for tab_list in self.all_tab_lists():
133
if tab_list is not new_tablist:
134
tab_list.view.unselect_all()
136
def update_selected_tabs(self):
137
table_view = self.selected_tab_list.view
138
self.__table_view = table_view
139
self.selected_tabs = [table_view.model[i][0] for i in
140
table_view.get_selection()]
142
def on_selection_changed(self, table_view):
143
if (table_view is not self.selected_tab_list.view and
144
table_view.num_rows_selected() == 0):
145
# This is the result of us calling unselect_all() in
146
# handle_tablist_change
149
tab_list = self.widget_to_tablist[table_view]
150
if tab_list.doing_change:
152
if tab_list is not self.selected_tab_list:
153
self.handle_tablist_change(tab_list)
154
if table_view.num_rows_selected() > 0:
155
self.update_selected_tabs()
157
self.handle_no_tabs_selected()
158
self.handle_new_selection()
160
def recalc_selection(self):
161
self.on_selection_changed(self.selected_tab_list.view)
163
def handle_no_tabs_selected(self):
164
model = self.selected_tab_list.view.model
165
iter = model.first_iter()
167
# We deleted all the feeds/playlists, select the guide instead
170
self.selected_tab_list.view.select(iter)
171
self.selected_tabs = [model[iter][0]]
173
def get_selection(self):
174
if self.__table_view is not None:
175
return self.selected_tab_list.type, self.selected_tabs
179
def get_selection_and_children(self):
180
"""This returns the selection and, in the case of parent rows, returns
181
all children, too. This is particularly useful for getting selections
182
that include children of folders.
184
This returns a list generated from a set--so there are no repeated
187
table_view = self.__table_view
188
if table_view is not None:
189
selected_tabs = set()
190
for mem in table_view.get_selection():
191
row = table_view.model[mem]
192
# sort children before parents
193
selected_tabs.add((1, row[0]))
194
for children in row.iterchildren():
195
selected_tabs.add((0, children[0]))
196
return self.selected_tab_list.type, [obj for index, obj in
197
sorted(selected_tabs)]