[ontv] Improved channel reordering
- From: Olof Kindgren <olki src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ontv] Improved channel reordering
- Date: Sat, 23 Oct 2010 13:09:04 +0000 (UTC)
commit c0b2f1a0e4d7cec20f9c8f3c25a80ea4c76d716a
Author: Olof Kindgren <olki src gnome org>
Date: Sat Oct 23 14:57:51 2010 +0200
Improved channel reordering
The preferences dialog for reordering channels has been improved to
use two treeview to distinguish between selected and unselected
channels. Except for DnD, this fixes bgo#534973
data/preferences_dialog.ui | 185 +++++++++++++++++++++++++++++++++++---------
ontv/dialogs.py | 160 +++++++++++++++++++++++++++++++++-----
ontv/gui.py | 6 +-
3 files changed, 289 insertions(+), 62 deletions(-)
---
diff --git a/data/preferences_dialog.ui b/data/preferences_dialog.ui
index 3c8b633..3d2f919 100644
--- a/data/preferences_dialog.ui
+++ b/data/preferences_dialog.ui
@@ -1,14 +1,22 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkTreeModelFilter" id="treemodelfilter1"/>
<object class="GtkListStore" id="channels_model">
<columns>
<!-- column-name col_obj -->
<column type="PyObject"/>
</columns>
</object>
+ <object class="GtkListStore" id="channels_selected_model">
+ <columns>
+ <!-- column-name col_channel_name -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeModelFilter" id="channels_unselected_filter">
+ <property name="child_model">channels_model</property>
+ </object>
<object class="GtkDialog" id="preferences_dialog">
<property name="width_request">530</property>
<property name="height_request">520</property>
@@ -16,7 +24,6 @@
<property name="title" translatable="yes">Preferences for OnTV</property>
<property name="window_position">center-always</property>
<property name="type_hint">dialog</property>
- <property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
@@ -80,7 +87,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="invisible_char">●</property>
+ <property name="invisible_char">â??</property>
<signal name="changed" handler="on_output_file_entry_changed"/>
<signal name="activate" handler="on_output_file_entry_activate"/>
</object>
@@ -109,7 +116,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="invisible_char">●</property>
+ <property name="invisible_char">â??</property>
<signal name="changed" handler="on_grabber_command_entry_changed"/>
<signal name="activate" handler="on_grabber_command_entry_activate"/>
</object>
@@ -246,7 +253,6 @@
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
- <property name="group">upcoming_programs_below_radiobutton</property>
</object>
<packing>
<property name="position">1</property>
@@ -322,56 +328,93 @@
</packing>
</child>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow5">
+ <object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">etched-in</property>
<child>
- <object class="GtkTreeView" id="channels_treeview">
+ <object class="GtkScrolledWindow" id="scrolledwindow5">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="model">channels_model</property>
- <property name="headers_visible">False</property>
- <property name="rules_hint">True</property>
- <property name="search_column">2</property>
- <signal name="row_activated" handler="on_channels_treeview_row_activated"/>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">etched-in</property>
<child>
- <object class="GtkTreeViewColumn" id="col_ch_selected">
- <property name="title">Selected</property>
+ <object class="GtkTreeView" id="channels_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">channels_unselected_filter</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="rules_hint">True</property>
+ <property name="search_column">2</property>
+ <signal name="row_activated" handler="on_channels_treeview_row_activated"/>
<child>
- <object class="GtkCellRendererToggle" id="cr_toggle">
- <property name="xpad">6</property>
- <property name="ypad">3</property>
- <signal name="toggled" handler="on_channels_treeview_toggled" object="channels_model"/>
+ <object class="GtkTreeViewColumn" id="col_ch_logo">
+ <property name="title">Logo</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cr_logo">
+ <property name="xpad">3</property>
+ <property name="ypad">3</property>
+ </object>
+ </child>
</object>
</child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn" id="col_ch_logo">
- <property name="title">Logo</property>
<child>
- <object class="GtkCellRendererPixbuf" id="cr_logo">
- <property name="xpad">3</property>
- <property name="ypad">3</property>
+ <object class="GtkTreeViewColumn" id="col_ch_name">
+ <property name="title">Channel</property>
+ <child>
+ <object class="GtkCellRendererText" id="cr_name">
+ <property name="xpad">3</property>
+ <property name="ypad">3</property>
+ </object>
+ </child>
</object>
</child>
</object>
</child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
<child>
- <object class="GtkTreeViewColumn" id="col_ch_name">
- <property name="title">Channel</property>
+ <object class="GtkTreeView" id="selected_channels_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">channels_selected_model</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="rules_hint">True</property>
<child>
- <object class="GtkCellRendererText" id="cr_name">
- <property name="xpad">3</property>
- <property name="ypad">3</property>
+ <object class="GtkTreeViewColumn" id="col_ch_sel_logo">
+ <property name="title">Logo</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cr_ch_sel_logo">
+ <property name="xpad">3</property>
+ <property name="ypad">3</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="col_ch_sel_name">
+ <property name="title">Channel</property>
+ <child>
+ <object class="GtkCellRendererText" id="cr_ch_sel_name"/>
+ </child>
</object>
</child>
</object>
</child>
</object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
@@ -385,6 +428,7 @@
<object class="GtkButton" id="channel_properties_button">
<property name="label">gtk-properties</property>
<property name="visible">True</property>
+ <property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
@@ -396,7 +440,74 @@
</packing>
</child>
<child>
- <placeholder/>
+ <object class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkButton" id="button_remove_channel">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_button_remove_channel_clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_add_channel">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_button_add_channel_clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_move_channel_down">
+ <property name="label">gtk-go-down</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_button_move_channel_down_clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_move_channel_up">
+ <property name="label">gtk-go-up</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_button_move_channel_up_clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
diff --git a/ontv/dialogs.py b/ontv/dialogs.py
index 8b4fd61..0227c82 100644
--- a/ontv/dialogs.py
+++ b/ontv/dialogs.py
@@ -147,7 +147,6 @@ class PreferencesDialog:
self.__get_widgets()
- self.__make_channels_treeview()
self.__make_reminders_treeview()
#self.sd.create_search_treeview_menu(self.reminders_treeview.get_model())
self.pw.set_reminders_model(self.reminders_treeview.get_model())
@@ -194,16 +193,26 @@ class PreferencesDialog:
# Channels tab
self.channels_treeview = builder.get_object("channels_treeview")
+ self.selected_channels_treeview = builder.get_object("selected_channels_treeview")
self.channels_model = builder.get_object("channels_model")
-
- builder.get_object("col_ch_selected").set_cell_data_func(builder.get_object("cr_toggle"),
- self.__crtoggle_cell_data_func)
+ self.unselected_channels_filter = builder.get_object("channels_unselected_filter")
+ self.selected_channels_filter = builder.get_object("channels_selected_filter")
builder.get_object("col_ch_logo").set_cell_data_func(builder.get_object("cr_logo"),
self.__crpixbuf_cell_data_func)
builder.get_object("col_ch_name").set_cell_data_func(builder.get_object("cr_name"),
self.__crtext_cell_data_func)
-
+ builder.get_object("col_ch_sel_logo").set_cell_data_func(builder.get_object("cr_ch_sel_logo"),
+ self.__crpixbuf_cell_sel_data_func)
+ builder.get_object("col_ch_sel_name").set_cell_data_func(builder.get_object("cr_ch_sel_name"),
+ self.__crtext_cell_sel_data_func)
+ self.unselected_channels_filter.set_visible_func(self.filter)
+ self.selected_channels_model = builder.get_object("channels_selected_model")
self.channel_properties_button = builder.get_object("channel_properties_button")
+ self.button_add_channel = builder.get_object("button_add_channel")
+ self.button_remove_channel = builder.get_object("button_remove_channel")
+ self.button_move_channel_up = builder.get_object("button_move_channel_up")
+ self.button_move_channel_down = builder.get_object("button_move_channel_down")
+
# Reminders tab
self.reminders_treeview = builder.get_object("reminders_treeview")
self.program_entry = builder.get_object("program_entry")
@@ -213,12 +222,6 @@ class PreferencesDialog:
self.update_reminder_button = builder.get_object("update_reminder_button")
self.remove_reminder_button = builder.get_object("remove_reminder_button")
-
- def __make_channels_treeview(self):
- self.channels_model.set_sort_func(0, self.__channels_model_sort_func)
- self.channels_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
- self.channels_treeview.set_search_equal_func(self.__channels_treeview_search_equal)
-
def __channels_model_sort_func(self, model, iter1, iter2, object=True):
channel = model.get_value(iter1, 0)
other_channel = model.get_value(iter2, 0)
@@ -226,6 +229,12 @@ class PreferencesDialog:
return utils.natcmp(channel.name.lower(), other_channel.name.lower())
return utils.natcmp(channel.lower(), other_channel.lower())
+ def filter(self, model, iter):
+ if iter:
+ channel = model.get_value(iter, 0)
+ if channel:
+ return not channel.selected
+
def on_channels_treeview_toggled(self, model, path):
channel = model[path][0]
channel.selected = not channel.selected
@@ -243,10 +252,6 @@ class PreferencesDialog:
channel = model.get_value(iter, 0)
return key.lower() not in channel.name.lower()
- def __crtoggle_cell_data_func(self, column, cell, model, iter):
- channel = model.get_value(iter, 0)
- cell.props.active = channel.selected
-
def __crpixbuf_cell_data_func(self, column, cell, model, iter):
channel = model.get_value(iter, 0)
cell.props.pixbuf = channel.logo
@@ -256,6 +261,17 @@ class PreferencesDialog:
markup = "<b>%s</b>"
cell.props.markup = markup % channel.markup_escaped_name
+ def __crpixbuf_cell_sel_data_func(self, column, cell, model, iter):
+ channel_name = model.get_value(iter, 0)
+ channel = self.listings.channels[channel_name]
+ cell.props.pixbuf = channel.logo
+
+ def __crtext_cell_sel_data_func(self, column, cell, model, iter):
+ channel_name = model.get_value(iter, 0)
+ channel = self.listings.channels[channel_name]
+ markup = "<b>%s</b>"
+ cell.props.markup = markup % channel.markup_escaped_name
+
def __make_reminders_treeview(self):
reminders_model = gtk.ListStore(object)
self.reminders_treeview.set_model(reminders_model)
@@ -307,6 +323,9 @@ class PreferencesDialog:
selection = self.channels_treeview.get_selection()
selection.connect("changed", self.__channels_treeview_selection_changed)
+ selection = self.selected_channels_treeview.get_selection()
+ selection.connect("changed", self.__selected_channels_treeview_selection_changed)
+
# Reminders tab
self.reminders_treeview.connect("key-press-event", self.__reminders_treeview_key_press_event)
selection = self.reminders_treeview.get_selection()
@@ -332,12 +351,56 @@ class PreferencesDialog:
def __dialog_delete(self, dialog, event):
return True
+ def __selected_channels_treeview_selection_changed(self, selection):
+ (model, iter) = selection.get_selected()
+ if iter:
+ self.channels_treeview.get_selection().unselect_all()
+ self.update_buttons(selection, True)
+ else:
+ self.update_buttons(None, True)
+
def __channels_treeview_selection_changed(self, selection):
- (search_model, search_iter) = selection.get_selected()
- if search_iter:
+ (model, iter) = selection.get_selected()
+ if iter:
+ self.selected_channels_treeview.get_selection().unselect_all()
+ self.update_buttons(selection, False)
+ else:
+ self.update_buttons(None, False)
+
+ def update_buttons(self, selection, selected):
+ if selection:
self.channel_properties_button.set_sensitive(True)
+ (model, iter) = selection.get_selected()
+
+ self.button_remove_channel.set_sensitive(selected)
+ self.button_add_channel.set_sensitive(not selected)
+
+ if selected:
+ channel_name = model.get_value(iter, 0)
+ self.selected_channel = self.listings.channels[channel_name]
+
+ row, = model.get_path(iter)
+ if row == 0:
+ self.button_move_channel_up.set_sensitive(False)
+ else:
+ self.button_move_channel_up.set_sensitive(True)
+ if row == len(self.selected_channels_model)-:
+ self.button_move_channel_down.set_sensitive(False)
+ else:
+ self.button_move_channel_down.set_sensitive(True)
+
+ else:
+ filter = model
+ model = filter.get_model()
+ self.selected_channel = model.get_value(filter.convert_iter_to_child_iter(iter), 0)
+ self.button_move_channel_up.set_sensitive(False)
+ self.button_move_channel_down.set_sensitive(False)
else:
self.channel_properties_button.set_sensitive(False)
+ self.button_remove_channel.set_sensitive(False)
+ self.button_add_channel.set_sensitive(False)
+ self.button_move_channel_up.set_sensitive(False)
+ self.button_move_channel_down.set_sensitive(False)
def on_grabber_command_entry_changed(self, entry):
self.config.grabber_command = entry.get_text()
@@ -385,12 +448,64 @@ class PreferencesDialog:
menu.popup(None, None, None, event.button, event.time)
def on_channel_properties_button_clicked(self, button):
+ cd = ChannelDialog(self.selected_channel, self)
+ cd.dialog.show()
+
+ def on_button_remove_channel_clicked(self, button):
+ selection = self.selected_channels_treeview.get_selection()
+ (model, iter) = selection.get_selected()
+ if iter:
+ channel_name = model.get_value(iter, 0)
+
+ channel = self.listings.channels[channel_name]
+ channel.selected = False
+ self.unselected_channels_filter.refilter()
+ self.listings.selected_channels.remove(channel_name)
+ self.selected_channels_model.remove(iter)
+ self.pw.update()
+ self.listings.save()
+
+ def on_button_add_channel_clicked(self, button):
selection = self.channels_treeview.get_selection()
+ (filter, iter) = selection.get_selected()
+ if iter:
+ model = filter.get_model()
+ channel = model.get_value(filter.convert_iter_to_child_iter(iter), 0)
+
+ channel.selected = True
+ self.listings.selected_channels.append(channel.name)
+ self.selected_channels_model.append([channel.name])
+ self.unselected_channels_filter.refilter()
+ self.pw.update()
+ self.listings.save()
+
+ def on_button_move_channel_down_clicked(self, button):
+ selection = self.selected_channels_treeview.get_selection()
+ (model, iter) = selection.get_selected()
+ if iter:
+ row, = model.get_path(iter)
+ self.listings.selected_channels[row], self.listings.selected_channels[row+1] = \
+ self.listings.selected_channels[row+1], self.listings.selected_channels[row]
+ iter_next = model.get_iter(row+1)
+
+ model.swap(iter,iter_next)
+ self.selected_channels_treeview.get_selection().emit("changed")
+ self.pw.update()
+ self.listings.save()
+
+ def on_button_move_channel_up_clicked(self, button):
+ selection = self.selected_channels_treeview.get_selection()
(model, iter) = selection.get_selected()
- channel = model.get_value(iter,0)
- if channel:
- cd = ChannelDialog(channel, self)
- cd.dialog.show()
+ if iter:
+ row, = model.get_path(iter)
+ self.listings.selected_channels[row], self.listings.selected_channels[row-1] = \
+ self.listings.selected_channels[row-1], self.listings.selected_channels[row]
+ iter_prev = model.get_iter(row-1)
+
+ model.swap(iter,iter_prev)
+ self.selected_channels_treeview.get_selection().emit("changed")
+ self.pw.update()
+ self.listings.save()
def __reminders_treeview_selection_changed(self, selection):
(reminders_model, reminders_iter) = selection.get_selected()
@@ -553,6 +668,9 @@ class PreferencesDialog:
self.listings = listings
self.channels_combobox_model.append([_("All")])
self.sd.set_all_as_combo_active(self.sd.channels_combobox)
+ self.selected_channels_model.clear()
+ for channel_name in self.listings.selected_channels:
+ self.selected_channels_model.append([channel_name])
def __xmltvfile_loaded_channel(self, xmltvfile, channel):
self.channels_model.append([channel])
diff --git a/ontv/gui.py b/ontv/gui.py
index 30885f2..7170571 100644
--- a/ontv/gui.py
+++ b/ontv/gui.py
@@ -35,7 +35,6 @@ search_dialog_ui_file = os.path.join(DATA_DIR, "search_dialog.ui")
preferences_dialog_ui_file = os.path.join(DATA_DIR, "preferences_dialog.ui")
icon_theme = gtk.icon_theme_get_default()
-COL_PROG = 2
def get_icon_list(sizes):
icon_list = []
for size in sizes:
@@ -73,12 +72,11 @@ def has_selection(treeview):
return True
return False
-def get_selected_value(treeview):
+def get_selected_value(treeview, col=0):
selection = treeview.get_selection()
(model, iter) = selection.get_selected()
if iter:
- value = model.get_value(iter, COL_PROG)
- return value
+ return model.get_value(iter, col)
return None
def queue_resize(treeview):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]