From 1de9270ded0db955e309a21b8abc8981237fbc52 Mon Sep 17 00:00:00 2001 From: Julien Valroff Date: Sat, 3 Jul 2010 16:56:43 +0200 Subject: Imported Upstream version 0.2.3 --- rapid/ChangeLog | 44 +++++++++++++++++++++++++++++++++++++ rapid/INSTALL | 15 ++++++++----- rapid/config.py | 2 +- rapid/glade3/rapid.glade | 2 ++ rapid/media.py | 5 +++-- rapid/metadata.py | 30 +++++++++++++++----------- rapid/rapid.py | 56 ++++++++++++++++++++++++++++++++---------------- 7 files changed, 115 insertions(+), 39 deletions(-) (limited to 'rapid') diff --git a/rapid/ChangeLog b/rapid/ChangeLog index 325b386..96f3d4f 100644 --- a/rapid/ChangeLog +++ b/rapid/ChangeLog @@ -1,3 +1,47 @@ +Version 0.2.3 +------------- + +2010-06-23 + +Updated Hungarian, Russian, Swedish and Ukrainian translations. + +Fixed bug #590725: don't crash if the theme does not associate an icon with +the detected device. + +Bug fix: update example filenames and folders when Job codes are manually +modified in the preferences window. + +This is the final release before 0.3.0, which will be a major update. + + +Version 0.2.2 +------------- + +2010-06-06 + +Added Ukrainian translation by Sergiy Gavrylov. + +Bug fix: in systems where exiv2 is not installed, don't crash on startup. + + +Version 0.2.1 +------------- + +2010-06-05 + +Bug fix: display sample photo and video names in preferences dialog using +first photo and video found on download device, where possible. This used to +work but was inadvertently disabled in a recent release. + +Bug fix: prompt for Job code when only video names or video subfolder names +use a job code. + +Bug fix: filter out Null bytes from Exif string values. These can occur when +the Exif data is corrupted. + +Updated Spanish, Russian and Finnish translations. + + Version 0.2.0 ------------- diff --git a/rapid/INSTALL b/rapid/INSTALL index 359b265..144568d 100644 --- a/rapid/INSTALL +++ b/rapid/INSTALL @@ -10,23 +10,28 @@ Rapid Photo Downloader depends on the following software: - libexiv2 0.15 or higher - pyexiv2 0.1.1 or higher +To run Rapid Photo Downloader you will need all the software mentioned above. -To run Rapid Photo Downloader you will need all the software mentioned above. If -you want to download videos, you can install: +A recommended package is exiv2 (not just the library libexiv2), so Rapid Photo +Downloader can determine if it can download additional types of RAW files +(some early versions of exiv2 and pyexiv2 segfault on certain RAW file types). + +If you want to download videos, you can install: - python-kaa-metadata - ffmpegthumbnailer kaa metadata is required to download videos. ffmpegthumbnailer is used only to -display thumbnail images as the download occurs. +display thumbnail images as the download occurs. This is a useful feature, and +if you can install it, it is recommended. kaa metadata and ffmpegthumbnailer are optional. The program will run without them. To start from a fairly basic system, I suggest the following: -1. Install the required gnome packages from your linux distribution's package - repositories. On a recent linux distribution, expect all to be available for +1. Install the required gnome packages from your Linux distribution's package + repositories. On a recent Linux distribution, expect all to be available for easy download and installation. If you already use gnome, most of the packages will already be installed. Do confirm that python-gconf, python-glade2, and gnome-python are installed, because they diff --git a/rapid/config.py b/rapid/config.py index 1ece2b0..cafcc16 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.2.0' +version = '0.2.3' GCONF_KEY="/apps/rapid-photo-downloader" GLADE_FILE = "glade3/rapid.glade" diff --git a/rapid/glade3/rapid.glade b/rapid/glade3/rapid.glade index 48a32a8..539ac9c 100644 --- a/rapid/glade3/rapid.glade +++ b/rapid/glade3/rapid.glade @@ -2951,8 +2951,10 @@ Miloš Popović <gpopac@gmail.com> Michal Predotka <mpredotka@googlemail.com> Luca Reverberi <thereve@gmail.com> Mikko Ruohola <polarfox@polarfox.net> +Sergiy Gavrylov <sergiovana@bigmir.net> Sergei Sedov <sedov@webmail.perm.ru> Marco Solari <marcosolari@gmail.com> +Toni Lähdekorpi <toni@lygon.net> Ulf Urdén <ulf.urden@purplescout.com> Julien Valroff <julien@kirya.net> rapid-photo-downloader-about.png diff --git a/rapid/media.py b/rapid/media.py index 4ed5380..d00855a 100755 --- a/rapid/media.py +++ b/rapid/media.py @@ -159,10 +159,11 @@ class CardMedia(Media): else: return self.fileSizeSum - def _firstFile(self, isCorrectFile): + def _firstFile(self, function_to_check): + if self.imagesAndVideos: for i in range(len(self.imagesAndVideos)): - if isCorrectFile(self.imagesAndVideos[i]): + if function_to_check(self.imagesAndVideos[i][0]): return self.imagesAndVideos[i] else: return None diff --git a/rapid/metadata.py b/rapid/metadata.py index f8886d7..c116072 100755 --- a/rapid/metadata.py +++ b/rapid/metadata.py @@ -98,17 +98,18 @@ RAW_FILE_EXTENSIONS = ['arw', 'dcr', 'cr2', 'crw', 'dng', 'mos', 'mrw', #RW2 files, so we should not read those! exiv2 0.17 & pyexiv2 segfaults #with MEF files. -if exiv2_version[0] > 0: - RAW_FILE_EXTENSIONS += ['rw2', 'mef'] -else: - if exiv2_version[1] > 17: - RAW_FILE_EXTENSIONS += ['mef'] - if exiv2_version[1] > 18: - RAW_FILE_EXTENSIONS += ['rw2'] +if exiv2_version is not None: + if exiv2_version[0] > 0: + RAW_FILE_EXTENSIONS += ['rw2', 'mef'] else: - if len(exiv2_version) > 2: - if exiv2_version[2] >= 1: - RAW_FILE_EXTENSIONS += ['rw2'] + if exiv2_version[1] > 17: + RAW_FILE_EXTENSIONS += ['mef'] + if exiv2_version[1] > 18: + RAW_FILE_EXTENSIONS += ['rw2'] + else: + if len(exiv2_version) > 2: + if exiv2_version[2] >= 1: + RAW_FILE_EXTENSIONS += ['rw2'] RAW_FILE_EXTENSIONS.sort() @@ -455,10 +456,13 @@ class MetaData(baseclass): def __getitem__(self, key): if self.__version01__: - return pyexiv2.Image.__getitem__(self, key) + v = pyexiv2.Image.__getitem__(self, key) else: - return pyexiv2.metadata.ImageMetadata.__getitem__(self, key).raw_value - + v = pyexiv2.metadata.ImageMetadata.__getitem__(self, key).raw_value + # strip out null bytes from strings + if isinstance(v, types.StringType): + v = v.replace('\x00', '') + return v class DummyMetaData(MetaData): diff --git a/rapid/rapid.py b/rapid/rapid.py index f5f221e..ddd0b95 100755 --- a/rapid/rapid.py +++ b/rapid/rapid.py @@ -751,20 +751,23 @@ class PreferencesDialog(gnomeglade.Component): w = workers.firstWorkerReadyToDownload() root, self.sampleImageName = w.firstImage() image = os.path.join(root, self.sampleImageName) + self.sampleImage = metadata.MetaData(image) - self.sampleImage.readMetadata() + self.sampleImage.read() except: self.sampleImage = metadata.DummyMetaData() self.sampleImageName = 'IMG_0524.CR2' try: - root, self.sampleVideoName = w.firstVideo() + root, self.sampleVideoName, modificationTime = w.firstVideo() video = os.path.join(root, self.sampleVideoName) - self.sampleVideo = videometadata.MetaData(video) + self.sampleVideo = videometadata.VideoMetaData(video) + self.videoFallBackDate = modificationTime except: self.sampleVideo = videometadata.DummyMetaData() self.sampleVideoName = 'MVI_1379.MOV' + self.videoFallBackDate = datetime.datetime.now() # setup tabs @@ -1077,12 +1080,12 @@ class PreferencesDialog(gnomeglade.Component): self.backup_duplicate_skip_radiobutton.set_active(True) - def updateExampleFileName(self, display_table, rename_table, sample, sampleName, example_label): + def updateExampleFileName(self, display_table, rename_table, sample, sampleName, example_label, fallback_date = None): if hasattr(self, display_table): rename_table.updateExampleJobCode() name, problem = rename_table.prefsFactory.generateNameUsingPreferences( sample, sampleName, - self.prefs.strip_characters, sequencesPreliminary=False) + self.prefs.strip_characters, sequencesPreliminary=False, fallback_date=fallback_date) else: name = problem = '' @@ -1107,9 +1110,9 @@ class PreferencesDialog(gnomeglade.Component): """ Displays example video name to the user """ - self.updateExampleFileName('video_rename_table', self.video_rename_table, self.sampleVideo, self.sampleVideoName, self.video_new_name_label) + self.updateExampleFileName('video_rename_table', self.video_rename_table, self.sampleVideo, self.sampleVideoName, self.video_new_name_label, self.videoFallBackDate) - def updateDownloadFolderExample(self, display_table, subfolder_table, download_folder, sample, sampleName, example_download_path_label, subfolder_warning_label): + def updateDownloadFolderExample(self, display_table, subfolder_table, download_folder, sample, sampleName, example_download_path_label, subfolder_warning_label, fallback_date = None): """ Displays example subfolder name(s) to the user """ @@ -1118,7 +1121,7 @@ class PreferencesDialog(gnomeglade.Component): subfolder_table.updateExampleJobCode() path, problem = subfolder_table.prefsFactory.generateNameUsingPreferences( sample, sampleName, - self.prefs.strip_characters) + self.prefs.strip_characters, fallback_date = fallback_date) else: path = problem = '' @@ -1139,7 +1142,7 @@ class PreferencesDialog(gnomeglade.Component): def updateVideoDownloadFolderExample(self): if hasattr(self, 'video_subfolder_table'): - self.updateDownloadFolderExample('video_subfolder_table', self.video_subfolder_table, self.prefs.video_download_folder, self.sampleVideo, self.sampleVideoName, self.example_video_download_path_label, self.video_subfolder_warning_label) + self.updateDownloadFolderExample('video_subfolder_table', self.video_subfolder_table, self.prefs.video_download_folder, self.sampleVideo, self.sampleVideoName, self.example_video_download_path_label, self.video_subfolder_warning_label, self.videoFallBackDate) def on_hour_spinbutton_value_changed(self, spinbutton): hour = spinbutton.get_value_as_int() @@ -1278,7 +1281,9 @@ class PreferencesDialog(gnomeglade.Component): self.update_job_codes() self.updateImageRenameExample() - self.updateDownloadFolderExample() + self.updateVideoRenameExample() + self.updatePhotoDownloadFolderExample() + self.updateVideoDownloadFolderExample() def on_remove_all_job_code_button_clicked(self, button): j = RemoveAllJobCodeDialog(self.widget, self.remove_all_job_code) @@ -1289,14 +1294,18 @@ class PreferencesDialog(gnomeglade.Component): self.job_code_liststore.clear() self.update_job_codes() self.updateImageRenameExample() - self.updateDownloadFolderExample() + self.updateVideoRenameExample() + self.updatePhotoDownloadFolderExample() + self.updateVideoDownloadFolderExample() def on_job_code_edited(self, widget, path, new_text): iter = self.job_code_liststore.get_iter(path) self.job_code_liststore.set_value(iter, 0, new_text) self.update_job_codes() self.updateImageRenameExample() - self.updateDownloadFolderExample() + self.updateVideoRenameExample() + self.updatePhotoDownloadFolderExample() + self.updateVideoDownloadFolderExample() def update_job_codes(self): """ update preferences with list of job codes""" @@ -1560,9 +1569,20 @@ class CopyPhotos(Thread): """ returns name, path and size of the first image """ + name, root, size, modificationTime = self.cardMedia.firstImage() + return root, name + def firstVideo(self): + """ + returns name, path and size of the first image + """ + + name, root, size, modificationTime = self.cardMedia.firstVideo() + + return root, name, modificationTime + def handlePreferencesError(self, e, prefsFactory): sys.stderr.write(_("Sorry,these preferences contain an error:\n")) sys.stderr.write(prefsFactory.formatPreferencesForPrettyPrint() + "\n") @@ -2022,8 +2042,7 @@ class CopyPhotos(Thread): nameUniqueBeforeCopy = True downloadNonUniqueFile = True - - + # do a preliminary check to see if a file with the same name already exists if os.path.exists(newFile): nameUniqueBeforeCopy = False @@ -3385,7 +3404,7 @@ class RapidApp(gnomeglade.GnomeApp, dbus.service.Object): return prefsOk def needJobCode(self): - return rn.usesJobCode(self.prefs.image_rename) or rn.usesJobCode(self.prefs.subfolder) + return rn.usesJobCode(self.prefs.image_rename) or rn.usesJobCode(self.prefs.subfolder) or rn.usesJobCode(self.prefs.video_rename) or rn.usesJobCode(self.prefs.video_subfolder) def assignJobCode(self, code): """ assign job code (which may be empty) to global variable and update user preferences @@ -4195,7 +4214,7 @@ class RapidApp(gnomeglade.GnomeApp, dbus.service.Object): if not self.preferencesDialogDisplayed: self.postPreferenceChange() - elif key in ['subfolder', 'image_rename']: + elif key in ['subfolder', 'image_rename', 'video_subfolder', 'video_rename']: global need_job_code need_job_code = self.needJobCode() @@ -4283,9 +4302,10 @@ class Volume: gicon = self.volume.get_icon() f = None if isinstance(gicon, gio.ThemedIcon): - iconinfo = icontheme.choose_icon(gicon.get_names(), size, gtk.ICON_LOOKUP_USE_BUILTIN) - f = iconinfo.get_filename() try: + # on some user's systems, themes do not have icons associated with them + iconinfo = icontheme.choose_icon(gicon.get_names(), size, gtk.ICON_LOOKUP_USE_BUILTIN) + f = iconinfo.get_filename() v = gtk.gdk.pixbuf_new_from_file_at_size(f, size, size) except: f = None -- cgit v1.2.3