1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
29 from gpodder
import util
31 from gpodder
.gtkui
.interface
.common
import BuilderWidget
32 from gpodder
.gtkui
.interface
.configeditor
import gPodderConfigEditor
34 from gpodder
.gtkui
.desktopfile
import PlayerListModel
36 class NewEpisodeActionList(gtk
.ListStore
):
37 C_CAPTION
, C_AUTO_DOWNLOAD
, C_HIDE_DIALOG
= range(3)
39 ACTION_NONE
, ACTION_ASK
, ACTION_MINIMIZED
, ACTION_ALWAYS
= range(4)
41 def __init__(self
, config
):
42 gtk
.ListStore
.__init
__(self
, str, str, bool)
44 self
.append((_('Do nothing'), 'never', True))
45 self
.append((_('Show episode list'), 'never', False))
46 self
.append((_('Add to download list'), 'queue', False))
47 self
.append((_('Download if minimized'), 'minimized', False))
48 self
.append((_('Download immediately'), 'always', False))
51 if self
._config
.do_not_show_new_episodes_dialog
:
54 for index
, row
in enumerate(self
):
55 if row
[self
.C_HIDE_DIALOG
]:
58 if self
._config
.auto_download
== \
59 row
[self
.C_AUTO_DOWNLOAD
]:
62 return 1 # Some sane default
64 def set_index(self
, index
):
65 self
._config
.do_not_show_new_episodes_dialog
= self
[index
][self
.C_HIDE_DIALOG
]
66 self
._config
.auto_download
= self
[index
][self
.C_AUTO_DOWNLOAD
]
69 class gPodderPreferences(BuilderWidget
):
71 if not hasattr(self
, 'callback_finished'):
72 self
.callback_finished
= None
74 for cb
in (self
.combo_audio_player_app
, self
.combo_video_player_app
):
75 cellrenderer
= gtk
.CellRendererPixbuf()
76 cb
.pack_start(cellrenderer
, False)
77 cb
.add_attribute(cellrenderer
, 'pixbuf', PlayerListModel
.C_ICON
)
78 cellrenderer
= gtk
.CellRendererText()
79 cellrenderer
.set_property('ellipsize', pango
.ELLIPSIZE_END
)
80 cb
.pack_start(cellrenderer
, True)
81 cb
.add_attribute(cellrenderer
, 'markup', PlayerListModel
.C_NAME
)
82 cb
.set_row_separator_func(PlayerListModel
.is_separator
)
84 self
.audio_player_model
= self
.user_apps_reader
.get_model('audio')
85 self
.combo_audio_player_app
.set_model(self
.audio_player_model
)
86 index
= self
.audio_player_model
.get_index(self
._config
.player
)
87 self
.combo_audio_player_app
.set_active(index
)
89 self
.video_player_model
= self
.user_apps_reader
.get_model('video')
90 self
.combo_video_player_app
.set_model(self
.video_player_model
)
91 index
= self
.video_player_model
.get_index(self
._config
.videoplayer
)
92 self
.combo_video_player_app
.set_active(index
)
94 self
._config
.connect_gtk_togglebutton('enable_notifications', self
.checkbutton_enable_notifications
)
95 self
._config
.connect_gtk_togglebutton('display_tray_icon', self
.checkbutton_show_tray_icon
)
97 self
.update_interval_presets
= [0, 10, 30, 60, 2*60, 6*60, 12*60]
98 adjustment_update_interval
= self
.hscale_update_interval
.get_adjustment()
99 adjustment_update_interval
.set_upper(len(self
.update_interval_presets
)-1)
100 if self
._config
.auto_update_frequency
in self
.update_interval_presets
:
101 index
= self
.update_interval_presets
.index(self
._config
.auto_update_frequency
)
102 self
.hscale_update_interval
.set_value(index
)
104 # Patch in the current "custom" value into the mix
105 self
.update_interval_presets
.append(self
._config
.auto_update_frequency
)
106 self
.update_interval_presets
.sort()
108 adjustment_update_interval
.set_upper(len(self
.update_interval_presets
)-1)
109 index
= self
.update_interval_presets
.index(self
._config
.auto_update_frequency
)
110 self
.hscale_update_interval
.set_value(index
)
112 self
._config
.connect_gtk_togglebutton('update_on_startup', self
.checkbutton_update_on_startup
)
113 self
._config
.connect_gtk_spinbutton('max_episodes_per_feed', self
.spinbutton_episode_limit
)
115 self
.auto_download_model
= NewEpisodeActionList(self
._config
)
116 self
.combo_auto_download
.set_model(self
.auto_download_model
)
117 cellrenderer
= gtk
.CellRendererText()
118 self
.combo_auto_download
.pack_start(cellrenderer
, True)
119 self
.combo_auto_download
.add_attribute(cellrenderer
, 'text', NewEpisodeActionList
.C_CAPTION
)
120 self
.combo_auto_download
.set_active(self
.auto_download_model
.get_index())
122 if self
._config
.auto_remove_played_episodes
:
123 adjustment_expiration
= self
.hscale_expiration
.get_adjustment()
124 if self
._config
.episode_old_age
> adjustment_expiration
.get_upper():
125 # Patch the adjustment to include the higher current value
126 adjustment_expiration
.set_upper(self
._config
.episode_old_age
)
128 self
.hscale_expiration
.set_value(self
._config
.episode_old_age
)
130 self
.hscale_expiration
.set_value(0)
132 self
._config
.connect_gtk_togglebutton('auto_remove_unplayed_episodes', self
.checkbutton_expiration_unplayed
)
133 self
._config
.connect_gtk_togglebutton('auto_cleanup_downloads', self
.checkbutton_auto_cleanup_downloads
)
135 # Initialize the UI state with configuration settings
136 self
.checkbutton_enable
.set_active(self
._config
.mygpo_enabled
)
137 self
.entry_username
.set_text(self
._config
.mygpo_username
)
138 self
.entry_password
.set_text(self
._config
.mygpo_password
)
139 self
.entry_caption
.set_text(self
._config
.mygpo_device_caption
)
141 # Disable mygpo sync while the dialog is open
142 self
._enable
_mygpo
= self
._config
.mygpo_enabled
143 self
._config
.mygpo_enabled
= False
145 def on_dialog_destroy(self
, widget
):
146 # Re-enable mygpo sync if the user has selected it
147 self
._config
.mygpo_enabled
= self
._enable
_mygpo
148 # Make sure the device is successfully created/updated
149 self
.mygpo_client
.create_device()
150 # Flush settings for mygpo client now
151 self
.mygpo_client
.flush(now
=True)
153 if self
.callback_finished
:
154 self
.callback_finished()
156 def on_button_close_clicked(self
, widget
):
157 self
.main_window
.destroy()
159 def on_button_advanced_clicked(self
, widget
):
160 self
.main_window
.destroy()
161 gPodderConfigEditor(self
.parent_window
, _config
=self
._config
)
163 def on_combo_audio_player_app_changed(self
, widget
):
164 index
= self
.combo_audio_player_app
.get_active()
165 self
._config
.player
= self
.audio_player_model
.get_command(index
)
167 def on_combo_video_player_app_changed(self
, widget
):
168 index
= self
.combo_video_player_app
.get_active()
169 self
._config
.videoplayer
= self
.video_player_model
.get_command(index
)
171 def on_button_audio_player_clicked(self
, widget
):
172 result
= self
.show_text_edit_dialog(_('Configure audio player'), \
177 self
._config
.player
= result
178 index
= self
.audio_player_model
.get_index(self
._config
.player
)
179 self
.combo_audio_player_app
.set_active(index
)
181 def on_button_video_player_clicked(self
, widget
):
182 result
= self
.show_text_edit_dialog(_('Configure video player'), \
184 self
._config
.videoplayer
)
187 self
._config
.videoplayer
= result
188 index
= self
.video_player_model
.get_index(self
._config
.videoplayer
)
189 self
.combo_video_player_app
.set_active(index
)
191 def format_update_interval_value(self
, scale
, value
):
194 return _('manual only')
196 return util
.format_seconds_to_hour_min_sec(self
.update_interval_presets
[int(value
)]*60)
198 def on_update_interval_value_changed(self
, range):
199 value
= int(range.get_value())
200 self
._config
.auto_update_feeds
= (value
> 0)
201 self
._config
.auto_update_frequency
= self
.update_interval_presets
[value
]
203 def on_combo_auto_download_changed(self
, widget
):
204 index
= self
.combo_auto_download
.get_active()
205 self
.auto_download_model
.set_index(index
)
207 def format_expiration_value(self
, scale
, value
):
212 return N_('after %d day', 'after %d days', value
) % value
214 def on_expiration_value_changed(self
, range):
215 value
= int(range.get_value())
218 self
.checkbutton_expiration_unplayed
.set_active(False)
219 self
._config
.auto_remove_played_episodes
= False
220 self
._config
.auto_remove_unplayed_episodes
= False
222 self
._config
.auto_remove_played_episodes
= True
223 self
._config
.episode_old_age
= value
225 self
.checkbutton_expiration_unplayed
.set_sensitive(value
> 0)
227 def on_enabled_toggled(self
, widget
):
228 # Only update indirectly (see on_dialog_destroy)
229 self
._enable
_mygpo
= widget
.get_active()
231 def on_username_changed(self
, widget
):
232 self
._config
.mygpo_username
= widget
.get_text()
234 def on_password_changed(self
, widget
):
235 self
._config
.mygpo_password
= widget
.get_text()
237 def on_device_caption_changed(self
, widget
):
238 self
._config
.mygpo_device_caption
= widget
.get_text()
240 def on_button_overwrite_clicked(self
, button
):
241 title
= _('Replace subscription list on server')
242 message
= _('Remote podcasts that have not been added locally will be removed on the server. Continue?')
243 if self
.show_confirmation(message
, title
):
245 self
._config
.mygpo_enabled
= True
246 self
.on_send_full_subscriptions()
247 self
._config
.mygpo_enabled
= False
248 threading
.Thread(target
=thread_proc
).start()