Thu, 17 Apr 2008 17:42:31 +0200 <thp@perli.net>

Clean up preferences dialog + Move download settings to downloads tab

	* data/gpodder.glade: UI-related changes to the preferences dialog
	clean-up and the moving of the download settings to the downloads tab;
	thanks to Paul Rudking for the download settings to downloads tab
	patch
	* src/gpodder/download.py: Better rate limiting, implemented by Paul
	Rudkin
	* src/gpodder/gui.py: UI-related changes to the preferences dialog
	clean-up; the download settings changes are by Paul Rudkin
	* src/gpodder/services.py: Improve the waiting/locking for the maximum
	number of simultaneous downloads using a threading.Event
	(Closes: http://bugs.gpodder.org/show_bug.cgi?id=69)
	(Closes: http://bugs.gpodder.org/show_bug.cgi?id=83)



git-svn-id: svn://svn.berlios.de/gpodder/trunk@673 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
Thomas Perl 2008-04-17 15:45:29 +00:00
parent d2a731e476
commit d3d7adf099
5 changed files with 760 additions and 878 deletions

View File

@ -1,3 +1,19 @@
Thu, 17 Apr 2008 17:42:31 +0200 <thp@perli.net>
Clean up preferences dialog + Move download settings to downloads tab
* data/gpodder.glade: UI-related changes to the preferences dialog
clean-up and the moving of the download settings to the downloads tab;
thanks to Paul Rudking for the download settings to downloads tab
patch
* src/gpodder/download.py: Better rate limiting, implemented by Paul
Rudkin
* src/gpodder/gui.py: UI-related changes to the preferences dialog
clean-up; the download settings changes are by Paul Rudkin
* src/gpodder/services.py: Improve the waiting/locking for the maximum
number of simultaneous downloads using a threading.Event
(Closes: http://bugs.gpodder.org/show_bug.cgi?id=69)
(Closes: http://bugs.gpodder.org/show_bug.cgi?id=83)
Tue, 15 Apr 2008 21:01:19 +0200 <thp@perli.net>
Updated French translation by Jérôme Chabod

File diff suppressed because it is too large Load Diff

View File

@ -82,9 +82,6 @@ class DownloadThread(threading.Thread):
self.filename = self.episode.local_filename()
self.tempname = os.path.join( os.path.dirname( self.filename), '.tmp-' + os.path.basename( self.filename))
self.limit_rate = gl.config.limit_rate
self.limit_rate_value = gl.config.limit_rate_value
self.cancelled = False
self.start_time = 0.0
self.speed = _('Queued')
@ -92,6 +89,11 @@ class DownloadThread(threading.Thread):
self.downloader = DownloadURLOpener( self.channel)
self.last_update = 0.0
# Keep a copy of these global variables for comparison later
self.limit_rate_value = gl.config.limit_rate_value
self.limit_rate = gl.config.limit_rate
self.start_blocks = 0
def cancel( self):
self.cancelled = True
@ -114,21 +116,38 @@ class DownloadThread(threading.Thread):
if count % 5 == 0:
now = time.time()
if self.start_time > 0:
# Has rate limiting been enabled or disabled?
if self.limit_rate != gl.config.limit_rate:
# If it has been enabled then reset base time and block count
if gl.config.limit_rate:
self.start_time = now
self.start_blocks = count
self.limit_rate = gl.config.limit_rate
# Has the rate been changed and are we currently limiting?
if self.limit_rate_value != gl.config.limit_rate_value and self.limit_rate:
self.start_time = now
self.start_blocks = count
self.limit_rate_value = gl.config.limit_rate_value
passed = now - self.start_time
if passed > 0:
speed = (count*blockSize)/passed
speed = ((count-self.start_blocks)*blockSize)/passed
else:
speed = 0
else:
self.start_time = now
self.start_blocks = count
passed = now - self.start_time
speed = count*blockSize
self.speed = '%s/s' % gl.format_filesize(speed)
if self.limit_rate and speed > self.limit_rate_value:
if gl.config.limit_rate and speed > gl.config.limit_rate_value:
# calculate the time that should have passed to reach
# the desired download rate and wait if necessary
should_have_passed = float(count*blockSize)/(self.limit_rate_value*1024.0)
should_have_passed = float((count-self.start_blocks)*blockSize)/(gl.config.limit_rate_value*1024.0)
if should_have_passed > passed:
# sleep a maximum of 10 seconds to not cause time-outs
delay = min( 10.0, float(should_have_passed-passed))

View File

@ -278,6 +278,16 @@ class gPodder(GladeWidget):
gl.config.connect_gtk_window( self.gPodder)
gl.config.connect_gtk_paned( 'paned_position', self.channelPaned)
gl.config.connect_gtk_spinbutton('max_downloads', self.spinMaxDownloads)
gl.config.connect_gtk_togglebutton('max_downloads_enabled', self.cbMaxDownloads)
gl.config.connect_gtk_spinbutton('limit_rate_value', self.spinLimitDownloads)
gl.config.connect_gtk_togglebutton('limit_rate', self.cbLimitDownloads)
# Make sure we free/close the download queue when we
# update the "max downloads" spin button
changed_cb = lambda spinbutton: services.download_status_manager.update_max_downloads()
self.spinMaxDownloads.connect('value-changed', changed_cb)
while gtk.events_pending():
gtk.main_iteration( False)
@ -816,6 +826,12 @@ class gPodder(GladeWidget):
self.updateComboBox()
def on_cbMaxDownloads_toggled(self, widget, *args):
self.spinMaxDownloads.set_sensitive(self.cbMaxDownloads.get_active())
def on_cbLimitDownloads_toggled(self, widget, *args):
self.spinLimitDownloads.set_sensitive(self.cbLimitDownloads.get_active())
def updateComboBox( self):
( model, iter ) = self.treeChannels.get_selection().get_selected()
@ -1934,19 +1950,12 @@ class gPodderProperties(GladeWidget):
self.table13.hide_all() # bluetooth
self.table5.hide_all() # player
self.table6.hide_all() # bittorrent
# start from web importer
self.hseparator3.hide_all()
self.label87.hide_all()
self.image2423.hide_all()
self.opmlURL.hide_all()
# end from web importer
self.gPodderProperties.fullscreen()
gl.config.connect_gtk_editable( 'http_proxy', self.httpProxy)
gl.config.connect_gtk_editable( 'ftp_proxy', self.ftpProxy)
gl.config.connect_gtk_editable( 'player', self.openApp)
gl.config.connect_gtk_editable('videoplayer', self.openVideoApp)
gl.config.connect_gtk_editable( 'opml_url', self.opmlURL)
gl.config.connect_gtk_editable( 'custom_sync_name', self.entryCustomSyncName)
gl.config.connect_gtk_togglebutton( 'custom_sync_name_enabled', self.cbCustomSyncName)
gl.config.connect_gtk_togglebutton( 'auto_download_when_minimized', self.downloadnew)
@ -1956,10 +1965,6 @@ class gPodderProperties(GladeWidget):
gl.config.connect_gtk_togglebutton( 'fssync_channel_subfolders', self.cbChannelSubfolder)
gl.config.connect_gtk_togglebutton( 'on_sync_mark_played', self.on_sync_mark_played)
gl.config.connect_gtk_togglebutton( 'on_sync_delete', self.on_sync_delete)
gl.config.connect_gtk_spinbutton( 'max_downloads', self.spinMaxDownloads)
gl.config.connect_gtk_togglebutton( 'max_downloads_enabled', self.cbMaxDownloads)
gl.config.connect_gtk_spinbutton( 'limit_rate_value', self.spinLimitDownloads)
gl.config.connect_gtk_togglebutton( 'limit_rate', self.cbLimitDownloads)
gl.config.connect_gtk_togglebutton( 'proxy_use_environment', self.cbEnvironmentVariables)
gl.config.connect_gtk_filechooser( 'bittorrent_dir', self.chooserBitTorrentTo)
gl.config.connect_gtk_spinbutton('episode_old_age', self.episode_old_age)
@ -1970,7 +1975,6 @@ class gPodderProperties(GladeWidget):
gl.config.connect_gtk_togglebutton('minimize_to_tray', self.minimize_to_tray)
gl.config.connect_gtk_togglebutton('enable_notifications', self.enable_notifications)
gl.config.connect_gtk_togglebutton('start_iconified', self.start_iconified)
gl.config.connect_gtk_togglebutton('on_quit_ask', self.on_quit_ask)
gl.config.connect_gtk_togglebutton('bluetooth_enabled', self.bluetooth_enabled)
gl.config.connect_gtk_togglebutton('bluetooth_ask_always', self.bluetooth_ask_always)
gl.config.connect_gtk_togglebutton('bluetooth_ask_never', self.bluetooth_ask_never)
@ -2158,18 +2162,12 @@ class gPodderProperties(GladeWidget):
if command == '':
self.openVideoApp.set_sensitive(True)
self.openVideoApp.show()
self.labelCustomCommand.show()
self.label115.show()
else:
self.openVideoApp.set_text(command)
self.openVideoApp.set_sensitive(False)
self.openVideoApp.hide()
self.labelCustomCommand.hide()
def on_cbMaxDownloads_toggled(self, widget, *args):
self.spinMaxDownloads.set_sensitive( self.cbMaxDownloads.get_active())
def on_cbLimitDownloads_toggled(self, widget, *args):
self.spinLimitDownloads.set_sensitive( self.cbLimitDownloads.get_active())
self.label115.hide()
def on_cbEnvironmentVariables_toggled(self, widget, *args):
sens = not self.cbEnvironmentVariables.get_active()

View File

@ -85,6 +85,11 @@ class DownloadStatusManager(ObservableService):
self.tree_model = gtk.ListStore( *self.COLUMN_TYPES)
self.tree_model_lock = threading.Lock()
# Used to notify all threads that they should
# re-check if they can acquire the lock
self.notification_event = threading.Event()
self.notification_event_waiters = 0
signal_names = ['list-changed', 'progress-changed', 'progress-detail', 'download-complete']
ObservableService.__init__(self, signal_names)
@ -99,18 +104,41 @@ class DownloadStatusManager(ObservableService):
def s_acquire( self):
if not gl.config.max_downloads_enabled:
return False
# Release queue slots if user has enabled more slots
while self.max_downloads < gl.config.max_downloads:
self.semaphore.release()
self.max_downloads += 1
# Acquire queue slots if user has decreased the slots
while self.max_downloads > gl.config.max_downloads:
self.semaphore.acquire()
self.max_downloads -= 1
return self.semaphore.acquire()
# Make sure we update the maximum number of downloads
self.update_max_downloads()
while self.semaphore.acquire(False) == False:
self.notification_event_waiters += 1
self.notification_event.wait(2.)
self.notification_event_waiters -= 1
# If we are the last thread that woke up from
# the notification_event, clear the flag here
if self.notification_event_waiters == 0:
self.notification_event.clear()
# If the user has change the config option since the
# last time we checked, return false and start download
if not gl.config.max_downloads_enabled:
return False
# If we land here, we've acquired exactly the one we need
return True
def update_max_downloads(self):
# Release queue slots if user has enabled more slots
while self.max_downloads < gl.config.max_downloads:
self.semaphore.release()
self.max_downloads += 1
# Notify all threads that the limit might have been changed
self.notification_event.set()
def s_release( self, acquired = True):
if acquired: