Add gpodder.net settings to preferences (Desktop UI)

This commit is contained in:
Thomas Perl 2010-05-03 21:16:13 +02:00
parent cd609dc318
commit 42cc4eddc5
8 changed files with 195 additions and 239 deletions

View File

@ -370,7 +370,7 @@
<child>
<object class="GtkAction" id="homepage">
<property name="name">homepage</property>
<property name="label" translatable="yes">Go to gpodder.org</property>
<property name="label" translatable="yes">Website</property>
<signal handler="on_homepage_activate" name="activate"/>
</object>
</child>
@ -422,9 +422,6 @@
<menuitem action="itemExportChannels"/>
<separator/>
<menuitem action="itemMassUnsubscribe"/>
<separator/>
<menuitem action="item_mygpo_settings"/>
<menuitem action="item_goto_mygpo"/>
</menu>
<menu action="menuChannels">
<menuitem action="itemPlaySelected"/>
@ -461,6 +458,7 @@
</menu>
<menu action="menuHelp">
<menuitem action="wiki"/>
<menuitem action="item_goto_mygpo"/>
<separator/>
<menuitem action="homepage"/>
<menuitem action="bug_tracker"/>

View File

@ -175,6 +175,119 @@
<property name="tab-label" translatable="yes">General</property>
</packing>
</child>
<child>
<object class="GtkTable" id="mygpo_config">
<property name="border_width">6</property>
<property name="column_spacing">6</property>
<property name="n_columns">3</property>
<property name="n_rows">7</property>
<property name="row_spacing">6</property>
<property name="visible">True</property>
<child>
<object class="GtkCheckButton" id="checkbutton_enable">
<property name="label" translatable="yes">Synchronize subscriptions and episode actions</property>
<property name="visible">True</property>
<signal handler="on_enabled_toggled" name="toggled"/>
</object>
<packing>
<property name="bottom_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_username">
<property name="label" translatable="yes">Username:</property>
<property name="visible">True</property>
<property name="xalign">1.0</property>
</object>
<packing>
<property name="bottom_attach">3</property>
<property name="top_attach">2</property>
<property name="x_options">fill</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_password">
<property name="label" translatable="yes">Password:</property>
<property name="visible">True</property>
<property name="xalign">1.0</property>
</object>
<packing>
<property name="bottom_attach">4</property>
<property name="top_attach">3</property>
<property name="x_options">fill</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button_overwrite">
<property name="label" translatable="yes">Replace list on server with local subscriptions</property>
<property name="visible">True</property>
<signal handler="on_button_overwrite_clicked" name="clicked"/>
</object>
<packing>
<property name="bottom_attach">6</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_caption">
<property name="label" translatable="yes">Device name:</property>
<property name="visible">True</property>
<property name="xalign">1.0</property>
</object>
<packing>
<property name="bottom_attach">5</property>
<property name="top_attach">4</property>
<property name="x_options">fill</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_username">
<property name="visible">True</property>
<signal handler="on_username_changed" name="changed"/>
</object>
<packing>
<property name="bottom_attach">3</property>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_password">
<property name="visibility">False</property>
<property name="is_focus">True</property>
<property name="visible">True</property>
<signal handler="on_password_changed" name="changed"/>
</object>
<packing>
<property name="bottom_attach">4</property>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_caption">
<property name="visible">True</property>
<signal handler="on_device_caption_changed" name="changed"/>
</object>
<packing>
<property name="bottom_attach">5</property>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
</object>
<packing>
<property name="tab-label" translatable="yes">gpodder.net</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox_updating">
<property name="border_width">12</property>
@ -305,7 +418,7 @@
</object>
<packing>
<property name="tab-label" translatable="yes">Updating</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
@ -379,7 +492,7 @@
</object>
<packing>
<property name="tab-label" translatable="yes">Clean-up</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child>
@ -392,7 +505,7 @@ See &lt;a href="http://gpodder.org/bug/955"&gt;http://gpodder.org/bug/955&lt;/a&
</object>
<packing>
<property name="tab-label" translatable="yes">Devices</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
</object>

View File

@ -339,7 +339,7 @@
<child>
<object class="GtkAction" id="homepage">
<property name="name">homepage</property>
<property name="label" translatable="yes">Go to gpodder.org</property>
<property name="label" translatable="yes">Website</property>
<signal handler="on_homepage_activate" name="activate"/>
</object>
</child>
@ -387,7 +387,6 @@
<menuitem action="itemExportChannels"/>
<separator/>
<menuitem action="item_mygpo_settings"/>
<menuitem action="item_goto_mygpo"/>
</menu>
<menu action="menuChannels">
<menuitem action="itemPlaySelected"/>
@ -414,6 +413,7 @@
</menu>
<menu action="menuHelp">
<menuitem action="wiki"/>
<menuitem action="item_goto_mygpo"/>
<separator/>
<menuitem action="homepage"/>
<menuitem action="bug_tracker"/>

View File

@ -2,11 +2,11 @@
<!--*- mode: xml -*-->
<interface>
<object class="GtkDialog" id="MygPodderSettings">
<property name="default_height">260</property>
<property name="default_width">320</property>
<property name="title" translatable="yes">gpodder.net settings</property>
<property name="title" translatable="yes">My gpodder.net account</property>
<property name="type_hint">dialog</property>
<property name="visible">True</property>
<property name="modal">True</property>
<signal handler="on_delete_event" name="delete-event"/>
<child internal-child="vbox">
<object class="GtkVBox" id="vbox">
@ -14,15 +14,15 @@
<property name="visible">True</property>
<child>
<object class="GtkTable" id="table">
<property name="border_width">12</property>
<property name="border_width">6</property>
<property name="column_spacing">6</property>
<property name="n_columns">3</property>
<property name="n_rows">9</property>
<property name="n_rows">7</property>
<property name="row_spacing">6</property>
<property name="visible">True</property>
<child>
<object class="GtkCheckButton" id="checkbutton_enable">
<property name="label" translatable="yes">Enable synchronization of subscription list</property>
<property name="label" translatable="yes">Synchronize subscriptions and episode actions</property>
<property name="visible">True</property>
<signal handler="on_enabled_toggled" name="toggled"/>
</object>
@ -62,59 +62,21 @@
<property name="visible">True</property>
<signal handler="on_button_overwrite_clicked" name="clicked"/>
</object>
<packing>
<property name="bottom_attach">5</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_device">
<property name="label" translatable="yes">&lt;b&gt;Device configuration&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="visible">True</property>
<property name="xalign">0.0</property>
</object>
<packing>
<property name="bottom_attach">6</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_uid">
<property name="label" translatable="yes">Device ID:</property>
<property name="visible">True</property>
<property name="xalign">1.0</property>
</object>
<packing>
<property name="bottom_attach">7</property>
<property name="top_attach">6</property>
<property name="x_options">fill</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_caption">
<property name="label" translatable="yes">Device Name:</property>
<property name="label" translatable="yes">Device name:</property>
<property name="visible">True</property>
<property name="xalign">1.0</property>
</object>
<packing>
<property name="bottom_attach">8</property>
<property name="top_attach">7</property>
<property name="x_options">fill</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_type">
<property name="label" translatable="yes">Type:</property>
<property name="visible">True</property>
<property name="xalign">1.0</property>
</object>
<packing>
<property name="bottom_attach">9</property>
<property name="top_attach">8</property>
<property name="bottom_attach">5</property>
<property name="top_attach">4</property>
<property name="x_options">fill</property>
</packing>
</child>
@ -144,56 +106,16 @@
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_uid_value">
<property name="visible">True</property>
<property name="xalign">0.0</property>
</object>
<packing>
<property name="bottom_attach">7</property>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry_caption">
<property name="visible">True</property>
<signal handler="on_device_caption_changed" name="changed"/>
</object>
<packing>
<property name="bottom_attach">8</property>
<property name="bottom_attach">5</property>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="combo_type">
<property name="visible">True</property>
<signal handler="on_device_type_changed" name="changed"/>
</object>
<packing>
<property name="bottom_attach">9</property>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">8</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkButton" id="button_list_uids">
<property name="label" translatable="yes">Select device</property>
<property name="visible">True</property>
<signal handler="on_button_list_uids_clicked" name="clicked"/>
</object>
<packing>
<property name="bottom_attach">7</property>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">6</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
<property name="top_attach">4</property>
</packing>
</child>
</object>

View File

@ -19,6 +19,7 @@
import gtk
import pango
import threading
import gpodder
@ -131,7 +132,24 @@ class gPodderPreferences(BuilderWidget):
self._config.connect_gtk_togglebutton('auto_remove_unplayed_episodes', self.checkbutton_expiration_unplayed)
self._config.connect_gtk_togglebutton('auto_cleanup_downloads', self.checkbutton_auto_cleanup_downloads)
# Initialize the UI state with configuration settings
self.checkbutton_enable.set_active(self._config.mygpo_enabled)
self.entry_username.set_text(self._config.mygpo_username)
self.entry_password.set_text(self._config.mygpo_password)
self.entry_caption.set_text(self._config.mygpo_device_caption)
# Disable mygpo sync while the dialog is open
self._enable_mygpo = self._config.mygpo_enabled
self._config.mygpo_enabled = False
def on_dialog_destroy(self, widget):
# Re-enable mygpo sync if the user has selected it
self._config.mygpo_enabled = self._enable_mygpo
# Make sure the device is successfully created/updated
self.mygpo_client.create_device()
# Flush settings for mygpo client now
self.mygpo_client.flush(now=True)
if self.callback_finished:
self.callback_finished()
@ -206,3 +224,26 @@ class gPodderPreferences(BuilderWidget):
self.checkbutton_expiration_unplayed.set_sensitive(value > 0)
def on_enabled_toggled(self, widget):
# Only update indirectly (see on_dialog_destroy)
self._enable_mygpo = widget.get_active()
def on_username_changed(self, widget):
self._config.mygpo_username = widget.get_text()
def on_password_changed(self, widget):
self._config.mygpo_password = widget.get_text()
def on_device_caption_changed(self, widget):
self._config.mygpo_device_caption = widget.get_text()
def on_button_overwrite_clicked(self, button):
title = _('Replace subscription list on server')
message = _('Remote podcasts that have not been added locally will be removed on the server. Continue?')
if self.show_confirmation(message, title):
def thread_proc():
self._config.mygpo_enabled = True
self.on_send_full_subscriptions()
self._config.mygpo_enabled = False
threading.Thread(target=thread_proc).start()

View File

@ -33,76 +33,7 @@ from gpodder.gtkui.interface.progress import ProgressIndicator
from gpodder.gtkui.interface.common import BuilderWidget
class DeviceList(gtk.ListStore):
C_UID, C_CAPTION, C_DEVICE_TYPE, C_ICON_NAME = range(4)
def __init__(self, devices):
gtk.ListStore.__init__(self, str, str, str, str)
for uid, caption, device_type in devices:
if device_type == 'desktop':
icon_name = 'computer'
elif device_type == 'mobile':
icon_name = 'phone'
elif device_type == 'server':
icon_name = 'server'
elif device_type == 'laptop':
icon_name = 'stock_notebook'
else:
icon_name = 'audio-x-generic'
self.append((uid, caption, device_type, icon_name))
class DeviceBrowser(gtk.Dialog):
def __init__(self, model, parent=None):
gtk.Dialog.__init__(self, _('Select a device'), parent)
self._model = model
hbox = gtk.HBox()
hbox.set_border_width(6)
hbox.set_spacing(6)
self.vbox.add(hbox)
hbox.pack_start(gtk.Label(_('Device:')), expand=False)
combobox = gtk.ComboBox()
hbox.add(combobox)
cell = gtk.CellRendererPixbuf()
combobox.pack_start(cell, expand=False)
combobox.add_attribute(cell, 'icon-name', DeviceList.C_ICON_NAME)
cell = gtk.CellRendererText()
combobox.pack_start(cell)
combobox.add_attribute(cell, 'text', DeviceList.C_CAPTION)
combobox.set_model(self._model)
combobox.set_active(0)
self._combobox = combobox
self.add_button(_('Cancel'), gtk.RESPONSE_CANCEL)
self.add_button(_('Use device'), gtk.RESPONSE_OK)
def get_selected(self):
result = None
self.show_all()
if self.run() == gtk.RESPONSE_OK:
active = self._combobox.get_active()
result = (self._model[active][DeviceList.C_UID],
self._model[active][DeviceList.C_CAPTION],
self._model[active][DeviceList.C_DEVICE_TYPE])
self.destroy()
return result
class MygPodderSettings(BuilderWidget):
# Valid types defined in mygpoclient.api.PodcastDevice
VALID_TYPES = (
('desktop', _('Desktop')),
('laptop', _('Laptop')),
('mobile', _('Mobile phone')),
('server', _('Server')),
('other', _('Other')),
)
# Columns IDs for the combo box model
C_ID, C_CAPTION = range(2)
@ -111,30 +42,18 @@ class MygPodderSettings(BuilderWidget):
assert getattr(self, 'mygpo_client', None) is not None
active_index = 0
self._model = gtk.ListStore(str, str)
for index, data in enumerate(self.VALID_TYPES):
id, caption = data
if id == self.config.mygpo_device_type:
active_index = index
self._model.append(data)
self.combo_type.set_model(self._model)
cell = gtk.CellRendererText()
self.combo_type.pack_start(cell, True)
self.combo_type.add_attribute(cell, 'text', 1)
# Initialize the UI state with configuration settings
self.checkbutton_enable.set_active(self.config.mygpo_enabled)
self.entry_username.set_text(self.config.mygpo_username)
self.entry_password.set_text(self.config.mygpo_password)
self.label_uid_value.set_label(self.config.mygpo_device_uid)
#self.label_uid_value.set_label(self.config.mygpo_device_uid)
self.entry_caption.set_text(self.config.mygpo_device_caption)
self.combo_type.set_active(active_index)
if gpodder.ui.fremantle:
self.checkbutton_enable.set_name('HildonButton-finger')
self.button_overwrite.set_name('HildonButton-finger')
self.button_list_uids.set_name('HildonButton-finger')
#self.button_list_uids.set_name('HildonButton-finger')
# Disable mygpo sync while the dialog is open
self._enable_mygpo = self.config.mygpo_enabled
@ -153,12 +72,6 @@ class MygPodderSettings(BuilderWidget):
def on_device_caption_changed(self, widget):
self.config.mygpo_device_caption = widget.get_text()
def on_device_type_changed(self, widget):
model = widget.get_model()
it = widget.get_active_iter()
device_type = model.get_value(it, self.C_ID)
self.config.mygpo_device_type = device_type
def on_button_overwrite_clicked(self, button):
title = _('Replace subscription list on server')
message = _('Remote podcasts that have not been added locally will be removed on the server. Continue?')
@ -169,53 +82,11 @@ class MygPodderSettings(BuilderWidget):
self.config.mygpo_enabled = False
threading.Thread(target=thread_proc).start()
def on_button_list_uids_clicked(self, button):
indicator = ProgressIndicator(_('Downloading device list'),
_('Getting the list of devices from your account.'),
False, self.main_window)
def thread_proc():
try:
devices = self.mygpo_client.get_devices()
except Exception, e:
indicator.on_finished()
def show_error(e):
if str(e):
message = str(e)
else:
message = e.__class__.__name__
self.show_message(message,
_('Error getting list'),
important=True)
util.idle_add(show_error, e)
return
indicator.on_finished()
def ui_callback(devices):
model = DeviceList(devices)
dialog = DeviceBrowser(model, self.main_window)
result = dialog.get_selected()
if result is not None:
uid, caption, device_type = result
# Update config and label with new UID
self.config.mygpo_device_uid = uid
self.label_uid_value.set_label(uid)
self.entry_caption.set_text(caption)
for index, data in enumerate(self.VALID_TYPES):
d_type, d_name = data
if device_type == d_type:
self.combo_type.set_active(index)
break
util.idle_add(ui_callback, devices)
threading.Thread(target=thread_proc).start()
def on_delete_event(self, widget, event):
# Re-enable mygpo sync if the user has selected it
self.config.mygpo_enabled = self._enable_mygpo
# Make sure the device is successfully created/updated
self.mygpo_client.create_device()
# Flush settings for mygpo client now
self.mygpo_client.flush(now=True)

View File

@ -3148,7 +3148,9 @@ class gPodder(BuilderWidget, dbus.service.Object):
callback_finished=self.properties_closed, \
user_apps_reader=self.user_apps_reader, \
mygpo_login=self.on_mygpo_settings_activate, \
parent_window=self.main_window)
parent_window=self.main_window, \
mygpo_client=self.mygpo_client, \
on_send_full_subscriptions=self.on_send_full_subscriptions)
# Initial message to relayout window (in case it's opened in portrait mode
self.preferences_dialog.on_window_orientation_changed(self._last_orientation)

View File

@ -183,6 +183,21 @@ class MygPoClient(object):
self._worker_thread = None
atexit.register(self._at_exit)
def create_device(self):
"""Uploads the device changes to the server
This should be called when device settings change
or when the mygpo client functionality is enabled.
"""
# Remove all previous device update actions
self._store.remove(self._store.load(UpdateDeviceAction))
# Insert our new update action
action = UpdateDeviceAction(self.device_id, \
self._config.mygpo_device_caption, \
self._config.mygpo_device_type)
self._store.save(action)
def get_rewritten_urls(self):
"""Returns a list of rewritten URLs for uploads
@ -379,14 +394,8 @@ class MygPoClient(object):
self._config.mygpo_password, self._config.mygpo_server)
log('Reloading settings.', sender=self)
elif name.startswith('mygpo_device_'):
# Remove all previous device update actions
self._store.remove(self._store.load(UpdateDeviceAction))
# Insert our new update action
action = UpdateDeviceAction(self.device_id, \
self._config.mygpo_device_caption, \
self._config.mygpo_device_type)
self._store.save(action)
# Update or create the device
self.create_device()
def synchronize_episodes(self, actions):
log('Starting episode status sync.', sender=self)