summaryrefslogtreecommitdiff
path: root/rapid
diff options
context:
space:
mode:
authorJulien Valroff <julien@kirya.net>2011-04-29 18:38:33 +0200
committerJulien Valroff <julien@kirya.net>2011-04-29 18:38:33 +0200
commit6f8a860aa541b16c84a86cce86c02dd503a3c5c0 (patch)
tree7ff5d93036ef405738d82ffde5a765d20d197d4b /rapid
parent47f84e1a3d14ea9cab37d495b699d60ceed398f4 (diff)
Imported Upstream version 0.4.0upstream/0.4.0
Diffstat (limited to 'rapid')
-rw-r--r--rapid/ChangeLog23
-rw-r--r--rapid/config.py2
-rw-r--r--rapid/downloadtracker.py30
-rw-r--r--rapid/errorlog.py1
-rw-r--r--rapid/glade3/rapid.ui8
-rw-r--r--rapid/preferencesdialog.py1
-rwxr-xr-xrapid/rapid.py48
7 files changed, 96 insertions, 17 deletions
diff --git a/rapid/ChangeLog b/rapid/ChangeLog
index 944119d..8fce376 100644
--- a/rapid/ChangeLog
+++ b/rapid/ChangeLog
@@ -1,3 +1,22 @@
+Version 0.4.0
+-------------
+
+2011-04-28
+
+Features added since Release Candiate 1:
+
+* Allow multiple selection of files to check or uncheck for downloading.
+* Automation feature to delete downloaded files from a device.
+
+Bug fix: translation fixes.
+
+Bug fix: don't crash when completing download with backups enabled and no backup
+devices detected.
+
+Updated Dutch, French, German, Polish, Russian, Serbian and Spanish
+translations.
+
+
Version 0.4.0 RC 1
------------------
@@ -16,8 +35,8 @@ will rendered during the download itself.
Added preferences option to disable thumbnail generation. When auto start is
enabled, this can speed-up transfers when downloading from high-speed devices.
-Access to the preferences window is now disable while a download is occurring,
-as changing preferences when files are being download can cause prolems.
+Access to the preferences window is now disabled while a download is occurring,
+as changing preferences when files are being download can cause problems.
Bug fix: don't crash when downloading some files after having previously
downloaded some others in the same session.
diff --git a/rapid/config.py b/rapid/config.py
index 6019d6a..86a268a 100644
--- a/rapid/config.py
+++ b/rapid/config.py
@@ -15,7 +15,7 @@
### along with this program; if not, write to the Free Software
### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-version = '0.4.0~rc1'
+version = '0.4.0'
GCONF_KEY="/apps/rapid-photo-downloader"
diff --git a/rapid/downloadtracker.py b/rapid/downloadtracker.py
index 75c9c9d..824a812 100644
--- a/rapid/downloadtracker.py
+++ b/rapid/downloadtracker.py
@@ -18,6 +18,11 @@
### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import time
+
+import multiprocessing
+import logging
+logger = multiprocessing.get_logger()
+
from rpdfile import FILE_TYPE_PHOTO, FILE_TYPE_VIDEO
from config import STATUS_DOWNLOAD_FAILED, STATUS_DOWNLOADED_WITH_WARNING, \
STATUS_DOWNLOAD_AND_BACKUP_FAILED, STATUS_BACKUP_PROBLEM
@@ -59,6 +64,7 @@ class DownloadTracker:
self.total_warnings = 0
self.total_bytes_to_download = 0
self.backups_performed_by_unique_id = dict()
+ self.auto_delete = dict()
def set_no_backup_devices(self, no_backup_devices):
self.no_backup_devices = no_backup_devices
@@ -95,14 +101,31 @@ class DownloadTracker:
def get_no_warnings(self, scan_pid):
return self.warnings.get(scan_pid, 0)
+
+ def add_to_auto_delete(self, rpd_file):
+ if rpd_file.scan_pid in self.auto_delete:
+ self.auto_delete[rpd_file.scan_pid].append(rpd_file.full_file_name)
+ else:
+ self.auto_delete[rpd_file.scan_pid] = [rpd_file.full_file_name,]
+
+ def get_files_to_auto_delete(self, scan_pid):
+ return self.auto_delete[scan_pid]
+
+ def clear_auto_delete(self, scan_pid):
+ if scan_pid in self.auto_delete:
+ del self.auto_delete[scan_pid]
def file_backed_up(self, unique_id):
self.backups_performed_by_unique_id[unique_id] = \
self.backups_performed_by_unique_id.get(unique_id, 0) + 1
def all_files_backed_up(self, unique_id):
- v = self.backups_performed_by_unique_id[unique_id] == self.no_backup_devices
- return v
+ if unique_id in self.backups_performed_by_unique_id:
+ return self.backups_performed_by_unique_id[unique_id] == self.no_backup_devices
+ else:
+ logger.critical("Unexpected unique_id in self.backups_performed_by_unique_id")
+ return True
+
def file_downloaded_increment(self, scan_pid, file_type, status):
self.files_downloaded[scan_pid] += 1
@@ -125,8 +148,7 @@ class DownloadTracker:
else:
self.video_failures[scan_pid] += 1
self.total_video_failures += 1
-
-
+
def get_percent_complete(self, scan_pid):
"""
Returns a float representing how much of the download
diff --git a/rapid/errorlog.py b/rapid/errorlog.py
index 0334465..9b35a52 100644
--- a/rapid/errorlog.py
+++ b/rapid/errorlog.py
@@ -34,6 +34,7 @@ class ErrorLog():
"""
self.builder = gtk.Builder()
+ self.builder.set_translation_domain(config.APP_NAME)
self.builder.add_from_file(paths.share_dir("glade3/errorlog.ui"))
self.builder.connect_signals(self)
self.widget = self.builder.get_object("errorlog")
diff --git a/rapid/glade3/rapid.ui b/rapid/glade3/rapid.ui
index bd9638e..1e49e4e 100644
--- a/rapid/glade3/rapid.ui
+++ b/rapid/glade3/rapid.ui
@@ -24,7 +24,7 @@
<signal name="activate" handler="on_donate_action_activate" swapped="no"/>
</object>
<object class="GtkAction" id="download_action">
- <property name="label">Download</property>
+ <property name="label" translatable="yes">Download</property>
<property name="icon_name">system-run</property>
<property name="sensitive">False</property>
<signal name="activate" handler="on_download_action_activate" swapped="no"/>
@@ -35,7 +35,7 @@
<signal name="activate" handler="on_get_help_action_activate" swapped="no"/>
</object>
<object class="GtkAction" id="help_action">
- <property name="label">Help</property>
+ <property name="label" translatable="yes">Help</property>
<signal name="activate" handler="on_help_action_activate" swapped="no"/>
</object>
<object class="GtkAction" id="next_image_action">
@@ -46,7 +46,7 @@
<signal name="activate" handler="on_next_image_action_activate" swapped="no"/>
</object>
<object class="GtkAction" id="preferences_action">
- <property name="label">Preferences</property>
+ <property name="label" translatable="yes">Preferences</property>
<signal name="activate" handler="on_preferences_action_activate" swapped="no"/>
</object>
<object class="GtkAction" id="prev_image_action">
@@ -253,8 +253,8 @@
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
- <accelerator key="plus" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="equal" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="plus" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
diff --git a/rapid/preferencesdialog.py b/rapid/preferencesdialog.py
index 368b064..7289d0e 100644
--- a/rapid/preferencesdialog.py
+++ b/rapid/preferencesdialog.py
@@ -800,6 +800,7 @@ class PreferencesDialog():
def __init__(self, rapidapp):
self.builder = gtk.Builder()
+ self.builder.set_translation_domain(config.APP_NAME)
self.builder.add_from_file(paths.share_dir("glade3/prefs.ui"))
self.builder.connect_signals(self)
diff --git a/rapid/rapid.py b/rapid/rapid.py
index 335db34..17d8335 100755
--- a/rapid/rapid.py
+++ b/rapid/rapid.py
@@ -83,7 +83,7 @@ import gettext
gettext.bindtextdomain(config.APP_NAME)
gettext.textdomain(config.APP_NAME)
-from gettext import gettext as _
+_ = gettext.gettext
from utilities import format_size_for_user
@@ -454,7 +454,11 @@ class ThumbnailDisplay(gtk.IconView):
self.set_spacing(0)
self.set_row_spacing(5)
self.set_margin(25)
-
+
+ self.set_selection_mode(gtk.SELECTION_MULTIPLE)
+ self.connect('selection-changed', self.on_selection_changed)
+ self._selected_items = []
+
self.rapid_app = parent_app
self.batch_size = 10
@@ -591,12 +595,25 @@ class ThumbnailDisplay(gtk.IconView):
def sort_by_timestamp(self):
self.liststore.set_sort_column_id(self.TIMESTAMP_COL, gtk.SORT_ASCENDING)
+
+ def on_selection_changed(self, iconview):
+ self._selected_items = self.get_selected_items()
def on_checkbutton_toggled(self, cellrenderertoggle, path):
- iter = self.liststore.get_iter(path)
- self.liststore.set_value(iter, self.SELECTED_COL, not cellrenderertoggle.get_active())
+ paths = [p[0] for p in self._selected_items]
+ if int(path) not in paths:
+ self._selected_items = [path,]
+
+ for path in self._selected_items:
+ iter = self.liststore.get_iter(path)
+ status = self.liststore.get_value(iter, self.DOWNLOAD_STATUS_COL)
+ if status == STATUS_NOT_DOWNLOADED:
+ self.liststore.set_value(iter, self.SELECTED_COL, not cellrenderertoggle.get_active())
+ self.select_path(path)
+
self.rapid_app.set_download_action_sensitivity()
+
def set_selected(self, unique_id, value):
iter = self.get_iter_from_unique_id(unique_id)
self.liststore.set_value(iter, self.SELECTED_COL, value)
@@ -2294,6 +2311,10 @@ class RapidApp(dbus.service.Object):
if not succeeded:
self.log_error(config.SERIOUS_ERROR, rpd_file.error_title,
rpd_file.error_msg, rpd_file.error_extra_detail)
+ elif self.prefs.auto_delete:
+ # record which files to automatically delete when download
+ # completes
+ self.download_tracker.add_to_auto_delete(rpd_file)
self.thumbnails.update_status_post_download(rpd_file)
self.download_tracker.file_downloaded_increment(scan_pid,
@@ -2309,6 +2330,10 @@ class RapidApp(dbus.service.Object):
# Last file for this scan pid has been downloaded, so clean temp directory
logger.debug("Purging temp directories")
self._clean_temp_dirs_for_scan_pid(scan_pid)
+ if self.prefs.auto_delete:
+ logger.debug("Auto deleting files")
+ self.auto_delete(scan_pid)
+ self.download_tracker.clear_auto_delete(scan_pid)
self.download_active_by_scan_pid.remove(scan_pid)
self.time_remaining.remove(scan_pid)
self.notify_downloaded_from_device(scan_pid)
@@ -2371,6 +2396,16 @@ class RapidApp(dbus.service.Object):
self.rapid_statusbar.pop(self.statusbar_context_id)
self.rapid_statusbar.push(self.statusbar_context_id, message)
+ def auto_delete(self, scan_pid):
+ """Delete files from download device at completion of download"""
+ for file in self.download_tracker.get_files_to_auto_delete(scan_pid):
+ f = gio.File(file)
+ try:
+ f.delete(cancellable=None)
+ except gio.Error, inst:
+ logger.error("Failure deleting file %s", file)
+ logger.error(inst)
+
def file_types_by_number(self, no_photos, no_videos):
"""
returns a string to be displayed to the user that can be used
@@ -2497,7 +2532,7 @@ class RapidApp(dbus.service.Object):
files_to_download = self.download_tracker.get_no_files_in_download(scan_pid)
file_types = self.download_tracker.get_file_types_present(scan_pid)
completed = files_downloaded == files_to_download
- if completed and self.prefs.backup_images:
+ if completed and (self.prefs.backup_images and len(self.backup_devices)):
completed = self.download_tracker.all_files_backed_up(unique_id)
if completed:
@@ -2730,6 +2765,7 @@ class RapidApp(dbus.service.Object):
Initialize widgets in the main window, and variables that point to them
"""
builder = gtk.Builder()
+ builder.set_translation_domain(config.APP_NAME)
self.builder = builder
builder.add_from_file(paths.share_dir("glade3/rapid.ui"))
self.rapidapp = builder.get_object("rapidapp")
@@ -2952,7 +2988,7 @@ class RapidApp(dbus.service.Object):
#Used to differentiate between two different file systems
#e.g. Free space: 21.3GB (photos); 14.7GB (videos).
msg += _("; ")
- else:
+ elif not self.prefs.backup_images:
#Inserted at the end of the statusbar message concerning the amount of freespace
#Used to differentiate between two different file systems
#e.g. Free space: 21.3GB (photos); 14.7GB (videos).