diff options
author | Julien Valroff <julien@kirya.net> | 2014-03-08 09:07:11 +0100 |
---|---|---|
committer | Julien Valroff <julien@kirya.net> | 2014-03-08 09:07:11 +0100 |
commit | 88da93d2f69f0a3dbf5b5f9bdaa11b3cb90ddb53 (patch) | |
tree | b2d1a530df46001fb15cf7b9f07b9ac544838102 /rapid/preferencesdialog.py | |
parent | fe8148d00d6503bdc3d4b7856a1535131bee73b6 (diff) | |
parent | e57608218ea2d7fa960b20f2aedf78094eeb79a5 (diff) |
Merge tag 'upstream/0.4.10'
Upstream version 0.4.10
Diffstat (limited to 'rapid/preferencesdialog.py')
-rw-r--r-- | rapid/preferencesdialog.py | 705 |
1 files changed, 355 insertions, 350 deletions
diff --git a/rapid/preferencesdialog.py b/rapid/preferencesdialog.py index 295b6e7..a0767af 100644 --- a/rapid/preferencesdialog.py +++ b/rapid/preferencesdialog.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: latin1 -*- -### Copyright (C) 2007-2012 Damon Lynch <damonlynch@gmail.com> +### Copyright (C) 2007-2014 Damon Lynch <damonlynch@gmail.com> ### This program is free software; you can redistribute it and/or modify ### it under the terms of the GNU General Public License as published by @@ -58,16 +58,16 @@ class PrefError(Exception): """ Make the preferences presentable to the user """ - + s = '' for i in l: if i <> ORDER_KEY: s += "'" + i + "', " return s[:-2] - def __str__(self): + def __str__(self): return self.msg - + class PrefKeyError(PrefError): def __init__(self, error): value = error[0] @@ -80,13 +80,13 @@ class PrefValueInvalidError(PrefKeyError): def __init__(self, error): value = error[0] self.msg = "Preference value '%(value)s' is invalid" % {'value': value} - + class PrefLengthError(PrefError): def __init__(self, error): self.msg = "These preferences are not well formed:" + "\n %s" % self.unpackList(error) - + class PrefValueKeyComboError(PrefError): - def __init__(self, error): + def __init__(self, error): self.msg = error @@ -107,7 +107,7 @@ def check_pref_valid(pref_defn, prefs, modulo=3): else: for i in range(0, len(prefs), modulo): _check_pref_valid(pref_defn, prefs[i:i+modulo]) - + return True def _check_pref_valid(pref_defn, prefs): @@ -117,16 +117,16 @@ def _check_pref_valid(pref_defn, prefs): if pref_defn.has_key(key): - + next_pref_defn = pref_defn[key] - + if value == None: # value should never be None, at any time raise PrefValueInvalidError((None, next_pref_defn)) if next_pref_defn and not value: raise gn.PrefValueInvalidError((value, next_pref_defn)) - + if type(next_pref_defn) == type({}): return _check_pref_valid(next_pref_defn, prefs[1:]) else: @@ -174,13 +174,13 @@ def filter_subfolder_prefs(pref_list): # must exit loop and try again pref_list = pref_list[:i] + pref_list[i+3:] break - + return (prefs_changed, pref_list) class Comboi18n(gtk.ComboBox): - """ very simple i18n version of the venerable combo box + """ very simple i18n version of the venerable combo box with one column displayed to the user. - + This combo box has two columns: 1. the first contains the actual value and is invisible 2. the second contains the translation of the first column, and this is what @@ -193,35 +193,35 @@ class Comboi18n(gtk.ComboBox): self.pack_start(cell, True) self.add_attribute(cell, 'text', 1) # must name the combo box on pygtk used in Ubuntu 11.04, Fedora 15, etc. - self.set_name('GtkComboBox') - + self.set_name('GtkComboBox') + def append_text(self, text): model = self.get_model() model.append((text, _(text))) - + def get_active_text(self): model = self.get_model() active = self.get_active() if active < 0: return None - return model[active][0] - + return model[active][0] + class PreferenceWidgets: - + def __init__(self, default_row, default_prefs, pref_defn_L0, pref_list): self.default_row = default_row self.default_prefs = default_prefs self.pref_defn_L0 = pref_defn_L0 self.pref_list = pref_list - + def _create_combo(self, choices): combobox = Comboi18n() for text in choices: combobox.append_text(text) return combobox - + def get_default_row(self): - """ + """ returns a list of default widgets """ return self.get_widgets_based_on_user_selection(self.default_row) @@ -229,11 +229,11 @@ class PreferenceWidgets: def _get_pref_widgets(self, pref_definition, prefs, widgets): key = prefs[0] value = prefs[1] - + # supply a default value if the user has not yet chosen a value! if not key: key = pref_definition[ORDER_KEY][0] - + if not key in pref_definition: raise gn.PrefKeyError((key, pref_definition.keys())) @@ -243,13 +243,13 @@ class PreferenceWidgets: # the first widget will always be a combo box widget0 = self._create_combo(list0) widget0.set_active(list0.index(key)) - + widgets.append(widget0) - + if key == TEXT: widget1 = gtk.Entry() widget1.set_text(value) - + widgets.append(widget1) widgets.append(None) return @@ -260,8 +260,8 @@ class PreferenceWidgets: else: next_pref_definition = pref_definition[key] if type(next_pref_definition) == type({}): - return self._get_pref_widgets(next_pref_definition, - prefs[1:], + return self._get_pref_widgets(next_pref_definition, + prefs[1:], widgets) else: if type(next_pref_definition) == type([]): @@ -272,56 +272,56 @@ class PreferenceWidgets: widget1.set_active(next_pref_definition.index(value)) except: raise gn.PrefValueInvalidError((value, next_pref_definition)) - + widgets.append(widget1) else: widgets.append(None) - + def _get_values_from_list(self): for i in range(0, len(self.pref_list), 3): - yield (self.pref_list[i], self.pref_list[i+1], self.pref_list[i+2]) - + yield (self.pref_list[i], self.pref_list[i+1], self.pref_list[i+2]) + def get_widgets_based_on_prefs(self): - """ + """ Yields a list of widgets and their callbacks based on the users preferences. - - This list is equivalent to one row of preferences when presented to the + + This list is equivalent to one row of preferences when presented to the user in the Plus Minus Table. """ - + for L0, L1, L2 in self._get_values_from_list(): prefs = [L0, L1, L2] widgets = [] self._get_pref_widgets(self.pref_defn_L0, prefs, widgets) yield widgets - + def get_widgets_based_on_user_selection(self, selection): """ Returns a list of widgets and their callbacks based on what the user has selected. - + Selection is the values the user has chosen thus far in comboboxes. It determines the contents of the widgets returned. It should be a list of three values, with None for values not chosen. For values which are None, the first value in the preferences definition is chosen. - + """ widgets = [] - + self._get_pref_widgets(self.pref_defn_L0, selection, widgets) return widgets - + def check_prefs_for_validity(self): """ Checks preferences validity """ - - return check_pref_valid(self.pref_defn_L0, self.pref_list) + + return check_pref_valid(self.pref_defn_L0, self.pref_list) class PhotoNamePrefs(PreferenceWidgets): def __init__(self, pref_list): - PreferenceWidgets.__init__(self, + PreferenceWidgets.__init__(self, default_row = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], default_prefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], pref_defn_L0 = DICT_IMAGE_RENAME_L0, @@ -334,11 +334,11 @@ class VideoNamePrefs(PreferenceWidgets): default_prefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], pref_defn_L0 = DICT_VIDEO_RENAME_L0, pref_list = pref_list) - + class PhotoSubfolderPrefs(PreferenceWidgets): def __init__(self, pref_list): - + PreferenceWidgets.__init__(self, default_row = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]], default_prefs = DEFAULT_SUBFOLDER_PREFS, @@ -349,13 +349,13 @@ class PhotoSubfolderPrefs(PreferenceWidgets): filtered, pref_list = filter_subfolder_prefs(self.pref_list) if filtered: self.pref_list = pref_list - + def check_prefs_for_validity(self): """ Checks subfolder preferences validity above and beyond image name checks. - + See parent method for full description. - + Subfolders have additional requirments to that of file names. """ v = PreferenceWidgets.check_prefs_for_validity(self) @@ -364,7 +364,7 @@ class PhotoSubfolderPrefs(PreferenceWidgets): # 1. do not start with a separator # 2. do not end with a separator # 3. do not have two separators in a row - # these three rules will ensure something else other than a + # these three rules will ensure something else other than a # separator is specified L1s = [] for i in range(0, len(self.pref_list), 3): @@ -382,47 +382,47 @@ class PhotoSubfolderPrefs(PreferenceWidgets): class VideoSubfolderPrefs(PhotoSubfolderPrefs): def __init__(self, pref_list): - PreferenceWidgets.__init__(self, + PreferenceWidgets.__init__(self, default_row = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[0]], default_prefs = DEFAULT_VIDEO_SUBFOLDER_PREFS, pref_defn_L0 = DICT_VIDEO_SUBFOLDER_L0, pref_list = pref_list) class QuestionDialog(gtk.Dialog): - def __init__(self, parent_window, title, question, use_markup=False, + def __init__(self, parent_window, title, question, use_markup=False, default_to_yes=True, post_choice_callback=None): gtk.Dialog.__init__(self, title, None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, + (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, gtk.STOCK_YES, gtk.RESPONSE_OK)) - - self.post_choice_callback = post_choice_callback + + self.post_choice_callback = post_choice_callback self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) - + prompt_hbox = gtk.HBox() - + icontheme = gtk.icon_theme_get_default() - icon = icontheme.load_icon('dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) + icon = icontheme.load_icon('dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) if icon: image = gtk.Image() image.set_from_pixbuf(icon) prompt_hbox.pack_start(image, False, False, padding = 6) - + prompt_label = gtk.Label(question) prompt_label.set_use_markup(use_markup) prompt_label.set_line_wrap(True) prompt_hbox.pack_start(prompt_label, False, False, padding=6) - + self.vbox.pack_start(prompt_hbox, padding=6) self.set_border_width(6) - self.set_has_separator(False) - - if default_to_yes: + self.set_has_separator(False) + + if default_to_yes: self.set_default_response(gtk.RESPONSE_OK) else: self.set_default_response(gtk.RESPONSE_CANCEL) - + self.set_transient_for(parent_window) self.show_all() @@ -439,31 +439,31 @@ class RemoveAllJobCodeDialog(QuestionDialog): _('Remove all Job Codes?'), _('Should all Job Codes be removed?'), post_choice_callback=post_choice_callback) - + class RemoveAllRemeberedDevicesDialog(QuestionDialog): def __init__(self, parent_window, post_choice_callback): QuestionDialog.__init__(self, parent_window, _('Remove all Remembered Paths?'), _('Should all remembered paths be removed?'), post_choice_callback=post_choice_callback) - + class RemoveAllIgnoredPathsDialog(QuestionDialog): def __init__(self, parent_window, post_choice_callback): QuestionDialog.__init__(self, parent_window, _('Remove all Ignored Paths?'), _('Should all ignored paths be removed?'), post_choice_callback=post_choice_callback) - + class PhotoRenameTable(tpm.TablePlusMinus): def __init__(self, preferencesdialog, adjust_scroll_window): - + tpm.TablePlusMinus.__init__(self, 1, 3) self.preferencesdialog = preferencesdialog self.adjust_scroll_window = adjust_scroll_window if not hasattr(self, "error_title"): self.error_title = _("Error in Photo Rename preferences") - + self.table_type = self.error_title[len("Error in "):] self.i = 0 @@ -481,17 +481,17 @@ class PhotoRenameTable(tpm.TablePlusMinus): self.get_preferencesdialog_prefs() self.setup_prefs_factory() - + try: self.prefs_factory.check_prefs_for_validity() - - except (PrefValueInvalidError, PrefLengthError, + + except (PrefValueInvalidError, PrefLengthError, PrefValueKeyComboError, PrefKeyError), e: logger.error(self.error_title) logger.error("Sorry, these preferences contain an error:") logger.error(format_pref_list_for_pretty_print(self.prefs_factory.pref_list)) - + # the preferences were invalid # reset them to their default @@ -502,18 +502,18 @@ class PhotoRenameTable(tpm.TablePlusMinus): msg = "%s.\n" % e msg += "Resetting to default values." logger.error(msg) - - - misc.run_dialog(self.error_title, msg, + + + misc.run_dialog(self.error_title, msg, preferencesdialog, gtk.MESSAGE_ERROR) - + for row in self.prefs_factory.get_widgets_based_on_prefs(): self.append(row) - + def update_preferences(self): pref_list = [] - for row in self.pm_rows: + for row in self.pm_rows: for col in range(self.pm_no_columns): widget = row[col] if widget: @@ -533,24 +533,24 @@ class PhotoRenameTable(tpm.TablePlusMinus): self.update_parentapp_prefs() self.prefs_factory.pref_list = pref_list self.update_example() - - + + def scrollbar_visibility_change(self, widget, event): if event.state == gtk.gdk.VISIBILITY_UNOBSCURED: self.have_vertical_scrollbar = True self.adjust_scroll_window.set_size_request(self.adjust_scroll_window.allocation.width + self.bump, -1) - + def size_adjustment(self, widget, arg2): """ Adjust scrolledwindow width in preferences dialog to reflect width of image rename table - + The algorithm is complicated by the need to take into account the presence of a vertical scrollbar, which might be added as the user adds more rows - + The pygtk code behaves inconsistently depending on the pygtk version """ - + if self.adjust_scroll_window: self.have_vertical_scrollbar = self.scroll_bar.allocation.width > 1 or self.have_vertical_scrollbar if not self.have_vertical_scrollbar: @@ -560,31 +560,31 @@ class PhotoRenameTable(tpm.TablePlusMinus): if self.allocation.width > self.adjust_scroll_window.allocation.width - self.bump: self.adjust_scroll_window.set_size_request(self.allocation.width + self.bump, -1) self.bump = 0 - + def get_preferencesdialog_prefs(self): self.pref_list = self.preferencesdialog.prefs.image_rename - - + + def setup_prefs_factory(self): self.prefs_factory = PhotoNamePrefs(self.pref_list) - + def update_parentapp_prefs(self): self.preferencesdialog.prefs.image_rename = self.pref_list - + def update_example_job_code(self): job_code = self.preferencesdialog.prefs.get_sample_job_code() if not job_code: job_code = _('Job code') #~ self.prefs_factory.setJobCode(job_code) - + def update_example(self): self.preferencesdialog.update_photo_rename_example() - + def get_default_row(self): return self.prefs_factory.get_default_row() - + def on_combobox_changed(self, widget, row_position): - + for col in range(self.pm_no_columns): if self.pm_rows[row_position][col] == widget: break @@ -597,13 +597,13 @@ class PhotoRenameTable(tpm.TablePlusMinus): selection.append(w.get_active_text()) else: selection.append(w.get_text()) - + for i in range(col + 1, self.pm_no_columns): selection.append('') - + if col <> (self.pm_no_columns - 1): widgets = self.prefs_factory.get_widgets_based_on_user_selection(selection) - + for i in range(col + 1, self.pm_no_columns): old_widget = self.pm_rows[row_position][i] if old_widget: @@ -618,7 +618,7 @@ class PhotoRenameTable(tpm.TablePlusMinus): new_widget.show() self.update_preferences() - + def on_entry_changed(self, widget, row_position): self.update_preferences() @@ -627,30 +627,30 @@ class PhotoRenameTable(tpm.TablePlusMinus): Update preferences, as a row has been added """ self.update_preferences() - + # if this was the last row or 2nd to last row, and another has just been added, move vertical scrollbar down if row_position in range(self.pm_no_rows - 3, self.pm_no_rows - 2): adjustment = self.preferencesdialog.rename_scrolledwindow.get_vadjustment() adjustment.set_value(adjustment.upper) - + def on_row_deleted(self, row_position): """ Update preferences, as a row has been deleted """ - self.update_preferences() + self.update_preferences() class VideoRenameTable(PhotoRenameTable): - def __init__(self, preferencesdialog, adjust_scroll_window): + def __init__(self, preferencesdialog, adjust_scroll_window): self.error_title = _("Error in Video Rename preferences") PhotoRenameTable.__init__(self, preferencesdialog, adjust_scroll_window) def get_preferencesdialog_prefs(self): self.pref_list = self.preferencesdialog.prefs.video_rename - + def setup_prefs_factory(self): self.prefs_factory = VideoNamePrefs(self.pref_list) - + def update_parentapp_prefs(self): self.preferencesdialog.prefs.video_rename = self.pref_list @@ -662,103 +662,103 @@ class SubfolderTable(PhotoRenameTable): Table to display photo download subfolder preferences as part of preferences dialog window. """ - def __init__(self, preferencesdialog, adjust_scroll_window): + def __init__(self, preferencesdialog, adjust_scroll_window): self.error_title = _("Error in Photo Download Subfolders preferences") PhotoRenameTable.__init__(self, preferencesdialog, adjust_scroll_window) def get_preferencesdialog_prefs(self): self.pref_list = self.preferencesdialog.prefs.subfolder - + def setup_prefs_factory(self): self.prefs_factory = PhotoSubfolderPrefs(self.pref_list) - + def update_parentapp_prefs(self): self.preferencesdialog.prefs.subfolder = self.pref_list def update_example(self): self.preferencesdialog.update_photo_download_folder_example() - + class VideoSubfolderTable(PhotoRenameTable): - def __init__(self, preferencesdialog, adjust_scroll_window): + def __init__(self, preferencesdialog, adjust_scroll_window): self.error_title = _("Error in Video Download Subfolders preferences") PhotoRenameTable.__init__(self, preferencesdialog, adjust_scroll_window) def get_preferencesdialog_prefs(self): self.pref_list = self.preferencesdialog.prefs.video_subfolder - + def setup_prefs_factory(self): self.prefs_factory = VideoSubfolderPrefs(self.pref_list) - + def update_parentapp_prefs(self): self.preferencesdialog.prefs.video_subfolder = self.pref_list def update_example(self): - self.preferencesdialog.update_video_download_folder_example() + self.preferencesdialog.update_video_download_folder_example() class RemoveAllJobCodeDialog(gtk.Dialog): def __init__(self, parent_window, post_choice_callback): gtk.Dialog.__init__(self, _('Remove all Job Codes?'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, + (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, gtk.STOCK_YES, gtk.RESPONSE_OK)) - - self.post_choice_callback = post_choice_callback + + self.post_choice_callback = post_choice_callback self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) - + prompt_hbox = gtk.HBox() - + icontheme = gtk.icon_theme_get_default() - icon = icontheme.load_icon('dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) + icon = icontheme.load_icon('dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) if icon: image = gtk.Image() image.set_from_pixbuf(icon) prompt_hbox.pack_start(image, False, False, padding = 6) - + prompt_label = gtk.Label(_('Should all Job Codes be removed?')) prompt_label.set_line_wrap(True) prompt_hbox.pack_start(prompt_label, False, False, padding=6) - + self.vbox.pack_start(prompt_hbox, padding=6) self.set_border_width(6) - self.set_has_separator(False) - + self.set_has_separator(False) + self.set_default_response(gtk.RESPONSE_OK) - + self.set_transient_for(parent_window) self.show_all() self.connect('response', self.on_response) - + def on_response(self, device_dialog, response): user_selected = response == gtk.RESPONSE_OK self.post_choice_callback(self, user_selected) class JobCodeDialog(gtk.Dialog): """ Dialog prompting for a job code""" - + def __init__(self, parent_window, job_codes, default_job_code, post_job_code_entry_callback, entry_only): # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode gtk.Dialog.__init__(self, _('Enter a Job Code'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) - + self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) self.post_job_code_entry_callback = post_job_code_entry_callback - + self.combobox = gtk.combo_box_entry_new_text() for text in job_codes: self.combobox.append_text(text) - + self.job_code_hbox = gtk.HBox(homogeneous = False) - + if len(job_codes) and not entry_only: # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode task_label = gtk.Label(_('Enter a new Job Code, or select a previous one')) else: # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode - task_label = gtk.Label(_('Enter a new Job Code')) + task_label = gtk.Label(_('Enter a new Job Code')) task_label.set_line_wrap(True) task_hbox = gtk.HBox() task_hbox.pack_start(task_label, False, False, padding=6) @@ -766,13 +766,13 @@ class JobCodeDialog(gtk.Dialog): label = gtk.Label(_('Job Code:')) self.job_code_hbox.pack_start(label, False, False, padding=6) self.job_code_hbox.pack_start(self.combobox, True, True, padding=6) - + self.set_border_width(6) self.set_has_separator(False) # make entry box have entry completion self.entry = self.combobox.child - + completion = gtk.EntryCompletion() completion.set_match_func(self.match_func) completion.connect("match-selected", @@ -780,32 +780,32 @@ class JobCodeDialog(gtk.Dialog): completion.set_model(self.combobox.get_model()) completion.set_text_column(0) self.entry.set_completion(completion) - + # when user hits enter, close the dialog window self.set_default_response(gtk.RESPONSE_OK) self.entry.set_activates_default(True) if default_job_code: self.entry.set_text(default_job_code) - + self.vbox.pack_start(task_hbox, False, False, padding = 6) self.vbox.pack_start(self.job_code_hbox, False, False, padding=12) - + self.set_transient_for(parent_window) self.show_all() self.connect('response', self.on_job_code_resp) - + def match_func(self, completion, key, iter): model = completion.get_model() return model[iter][0].lower().startswith(self.entry.get_text().lower()) - + def on_completion_match(self, completion, model, iter): self.entry.set_text(model[iter][0]) self.entry.set_position(-1) def get_job_code(self): return self.combobox.child.get_text() - + def on_job_code_resp(self, jc_dialog, response): user_chose_code = False if response == gtk.RESPONSE_OK: @@ -814,24 +814,24 @@ class JobCodeDialog(gtk.Dialog): else: logger.debug("Job Code not entered") self.post_job_code_entry_callback(self, user_chose_code, self.get_job_code()) - + class IgnorePathDialog(gtk.Dialog): """ Dialog prompting for a path to ignore when scanning devices""" - + def __init__(self, parent_window, post_entry_callback): gtk.Dialog.__init__(self, _('Enter a Path to Ignore'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) - + self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) self.post_entry_callback = post_entry_callback - + self.path_entry = gtk.Entry(max=0) - + self.ignored_path_hbox = gtk.HBox(homogeneous = False) - - task_label = gtk.Label(_('Specify a path that will never be scanned for photos or videos')) + + task_label = gtk.Label(_('Specify a path that will never be scanned for photos or videos')) task_label.set_line_wrap(True) task_hbox = gtk.HBox() task_hbox.pack_start(task_label, False, False, padding=6) @@ -839,17 +839,17 @@ class IgnorePathDialog(gtk.Dialog): label = gtk.Label(_('Path:')) self.ignored_path_hbox.pack_start(label, False, False, padding=6) self.ignored_path_hbox.pack_start(self.path_entry, True, True, padding=6) - + self.set_border_width(6) self.set_has_separator(False) - + # when user hits enter, close the dialog window self.set_default_response(gtk.RESPONSE_OK) self.path_entry.set_activates_default(True) self.vbox.pack_start(task_hbox, False, False, padding = 6) self.vbox.pack_start(self.ignored_path_hbox, False, False, padding=12) - + self.set_transient_for(parent_window) self.show_all() self.connect('response', self.on_ignored_path_resp) @@ -867,55 +867,55 @@ class IgnorePathDialog(gtk.Dialog): class PreferencesDialog(): """ Dialog window to show Rapid Photo Downloader preferences. - + Is tightly integrated into main Rapid Photo Downloader window, i.e. directly access members in class RapidApp. """ - + 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) - + self.dialog = self.preferencesdialog self.widget = self.dialog self.dialog.set_transient_for(rapidapp.rapidapp) self.prefs = rapidapp.prefs - + rapidapp.preferences_dialog_displayed = True - + self.pref_dialog_startup = True - + self.rapidapp = rapidapp self._setup_tab_selector() - + self._setup_control_spacing() - + self.file_types = metadatavideo.file_types_to_download() self._setup_sample_names() - + # setup tabs self._setup_photo_download_folder_tab() self._setup_image_rename_tab() self._setup_video_download_folder_tab() - self._setup_video_rename_tab() + self._setup_video_rename_tab() self._setup_rename_options_tab() self._setup_job_code_tab() self._setup_device_tab() - self._setup_device_options_tab() + self._setup_device_options_tab() self._setup_backup_tab() self._setup_miscellaneous_tab() self._setup_error_tab() - + if not metadatavideo.DOWNLOAD_VIDEO: self.disable_video_controls() self.dialog.realize() - + #set the width of the left column for selecting values #note: this must be called after self.dialog.realize(), or else the width calculation will fail width_of_widest_sel_row = self.treeview.get_background_area(1, self.treeview_column)[2] @@ -929,7 +929,7 @@ class PreferencesDialog(): self.rename_scrolledwindow.set_size_request(self.rename_table.allocation.width + extra, -1) self.dialog.show() - + self.pref_dialog_startup = False def __getattr__(self, key): @@ -940,11 +940,11 @@ class PreferencesDialog(): setattr(self, key, widget) return widget raise AttributeError(key) - + def on_preferencesdialog_destroy(self, widget): """ Delete variables from memory that cause a file descriptor to be created on a mounted media""" logger.debug("Preference window closing") - + def _setup_tab_selector(self): self.notebook.set_show_tabs(0) self.model = gtk.ListStore(type("")) @@ -959,44 +959,44 @@ class PreferencesDialog(): label = self.notebook.get_tab_label(c).get_text() if not label.startswith("_"): self.model.append( (label,) ) - + # select the first value in the list store self.treeview.set_cursor(0,column) - + def on_download_folder_filechooser_button_selection_changed(self, widget): path = misc.get_folder_selection(widget) if path: self.prefs.download_folder = path self.update_photo_download_folder_example() - + def on_video_download_folder_filechooser_button_selection_changed(self, widget): path = misc.get_folder_selection(widget) if path: self.prefs.video_download_folder = path self.update_video_download_folder_example() - + def on_backup_folder_filechooser_button_selection_changed(self, widget): path = misc.get_folder_selection(widget) - if path: + if path: self.prefs.backup_location = path self.update_backup_example() - + def on_backup_video_folder_filechooser_button_selection_changed(self, widget): path = misc.get_folder_selection(widget) if path: self.prefs.backup_video_location = path self.update_backup_example() - + def on_device_location_filechooser_button_selection_changed(self, widget): path = misc.get_folder_selection(widget) - if path: + if path: self.prefs.device_location = path - + def on_add_ignored_path_button_clicked(self, widget): - i = IgnorePathDialog(parent_window = self.dialog, + i = IgnorePathDialog(parent_window = self.dialog, post_entry_callback = self.add_ignored_path) - + def add_ignored_path(self, dialog, user_chose_path, path): dialog.destroy() if user_chose_path: @@ -1009,29 +1009,29 @@ class PreferencesDialog(): #scroll to the top adjustment = self.ignored_paths_scrolledwindow.get_vadjustment() adjustment.set_value(adjustment.lower) - + def on_ignored_paths_use_re_checkbutton_toggled(self, checkbutton): self.prefs.use_re_ignored_paths = checkbutton.get_active() if self.prefs.use_re_ignored_paths and not self.pref_dialog_startup: # check for invalid regular expressions self.update_ignored_paths() - + def on_remove_ignored_path_button_clicked(self, button): self._remove_from_treeview(self.ignored_paths_treeview) self.update_ignored_paths() - + def on_remove_all_ignored_paths_button_clicked(self, button): i = RemoveAllIgnoredPathsDialog(self.dialog, self.remove_all_ignored_paths) - + def remove_all_ignored_paths(self, dialog, user_selected): dialog.destroy() if user_selected: self.ignored_paths_liststore.clear() - self.update_ignored_paths() - + self.update_ignored_paths() + def on_remove_remembered_device_button_clicked(self, button): """ - uses remembered devices treeview to delete any removed items from the + uses remembered devices treeview to delete any removed items from the device_whitelist and device_blacklist prefs """ blacklist = [i for i in self.prefs.device_blacklist if i] @@ -1046,7 +1046,7 @@ class PreferencesDialog(): for i in range(0, no): iter = iters[i] if i == no - 1: - path = model.get_path(iter) + path = model.get_path(iter) v = self.remembered_devices_liststore.get_value(iter, 0) if v in blacklist: blacklist.remove(v) @@ -1055,33 +1055,33 @@ class PreferencesDialog(): else: logger.debug("Unknown remembered device %s", v) model.remove(iter) - - # now that we removed the selection, play nice with + + # now that we removed the selection, play nice with # the user and select the next item selection.select_path(path) - + # if there was no selection that meant the user - # removed the last entry, so we try to select the + # removed the last entry, so we try to select the # last item if not selection.path_is_selected(path): row = path[0]-1 # test case for empty lists if row >= 0: - selection.select_path((row,)) - + selection.select_path((row,)) + self.prefs.device_blacklist = blacklist self.prefs.device_whitelist = whitelist - + def on_remove_all_remembered_device_button_clicked(self, button): r = RemoveAllRemeberedDevicesDialog(self.dialog, self.remove_all_remembered_devices) - + def remove_all_remembered_devices(self, dialog, user_selected): dialog.destroy() if user_selected: self.remembered_devices_liststore.clear() self.prefs.device_blacklist = [] self.prefs.device_whitelist = [] - + def _setup_sample_names(self, use_dummy_data = False): """ If use_dummy_data is True, then samples will not attempt to get @@ -1094,9 +1094,9 @@ class PreferencesDialog(): day_start = self.prefs.day_start, downloads_today = self.prefs.downloads_today[1], downloads_today_date = self.prefs.downloads_today[0]) - self.sequences = gn.Sequences(self.downloads_today_tracker, + self.sequences = gn.Sequences(self.downloads_today_tracker, self.prefs.stored_sequence_no) - + # get example photo and video data if use_dummy_data: self.sample_photo = None @@ -1110,12 +1110,12 @@ class PreferencesDialog(): else: self.sample_photo.sequences = self.sequences self.sample_photo.download_start_time = datetime.datetime.now() - + if self.sample_photo is None: self.sample_photo = rpdfile.SamplePhoto(sequences=self.sequences) - + self.sample_photo.job_code = job_code - + self.sample_video = None if metadatavideo.DOWNLOAD_VIDEO: if not use_dummy_data: @@ -1123,38 +1123,38 @@ class PreferencesDialog(): if self.sample_video is not None: self.sample_video.load_metadata() self.sample_video.sequences = self.sequences - self.sample_video.download_start_time = datetime.datetime.now() + self.sample_video.download_start_time = datetime.datetime.now() if self.sample_video is None: self.sample_video = rpdfile.SampleVideo(sequences=self.sequences) self.sample_video.job_code = job_code - + def _setup_control_spacing(self): """ set spacing of some but not all controls """ - - self._setup_table_spacing(self.download_folder_table) - self._setup_table_spacing(self.video_download_folder_table) - self.download_folder_table.set_row_spacing(2, + + self._setup_table_spacing(self.download_folder_table) + self._setup_table_spacing(self.video_download_folder_table) + self.download_folder_table.set_row_spacing(2, hd.VERTICAL_CONTROL_SPACE) - self.video_download_folder_table.set_row_spacing(2, + self.video_download_folder_table.set_row_spacing(2, hd.VERTICAL_CONTROL_SPACE) self._setup_table_spacing(self.rename_example_table) self._setup_table_spacing(self.video_rename_example_table) self.devices_table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) self.automation_table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) - + self._setup_table_spacing(self.backup_table) self.backup_table.set_col_spacing(1, hd.NESTED_CONTROLS_SPACE) self.backup_table.set_col_spacing(2, hd.CONTROL_LABEL_SPACE) self._setup_table_spacing(self.compatibility_table) - self.compatibility_table.set_row_spacing(0, - hd.VERTICAL_CONTROL_LABEL_SPACE) + self.compatibility_table.set_row_spacing(0, + hd.VERTICAL_CONTROL_LABEL_SPACE) self._setup_table_spacing(self.error_table) - - + + def _setup_table_spacing(self, table): table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) table.set_col_spacing(1, hd.CONTROL_LABEL_SPACE) @@ -1163,7 +1163,7 @@ class PreferencesDialog(): self.subfolder_table = SubfolderTable(self, None) self.subfolder_vbox.pack_start(self.subfolder_table) self.subfolder_table.show_all() - + def _setup_video_subfolder_table(self): self.video_subfolder_table = VideoSubfolderTable(self, None) self.video_subfolder_vbox.pack_start(self.video_subfolder_table) @@ -1176,17 +1176,17 @@ class PreferencesDialog(): self.prefs.download_folder) self.download_folder_filechooser_button.set_action( gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - self.download_folder_filechooser_button.connect("selection-changed", + self.download_folder_filechooser_button.connect("selection-changed", self.on_download_folder_filechooser_button_selection_changed) - + self.download_folder_table.attach( - self.download_folder_filechooser_button, + self.download_folder_filechooser_button, 2, 3, 2, 3, yoptions = gtk.SHRINK) - self.download_folder_filechooser_button.show() + self.download_folder_filechooser_button.show() self._setup_subfolder_table() self.update_photo_download_folder_example() - + def _setup_video_download_folder_tab(self): self.video_download_folder_filechooser_button = gtk.FileChooserButton( _("Select a folder to download videos to")) @@ -1194,16 +1194,16 @@ class PreferencesDialog(): self.prefs.video_download_folder) self.video_download_folder_filechooser_button.set_action( gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - self.video_download_folder_filechooser_button.connect("selection-changed", + self.video_download_folder_filechooser_button.connect("selection-changed", self.on_video_download_folder_filechooser_button_selection_changed) - + self.video_download_folder_table.attach( - self.video_download_folder_filechooser_button, + self.video_download_folder_filechooser_button, 2, 3, 2, 3, yoptions = gtk.SHRINK) - self.video_download_folder_filechooser_button.show() + self.video_download_folder_filechooser_button.show() self._setup_video_subfolder_table() - self.update_video_download_folder_example() - + self.update_video_download_folder_example() + def _setup_image_rename_tab(self): self.rename_table = PhotoRenameTable(self, self.rename_scrolledwindow) @@ -1214,7 +1214,7 @@ class PreferencesDialog(): def _setup_photo_original_name(self): self.original_name_label.set_markup("<i>%s</i>" % self.sample_photo.display_name) - + def _setup_video_rename_tab(self): self.video_rename_table = VideoRenameTable(self, self.video_rename_scrolledwindow) @@ -1222,15 +1222,15 @@ class PreferencesDialog(): self.video_rename_table.show_all() self._setup_video_original_name() self.update_video_rename_example() - + def _setup_video_original_name(self): if self.sample_video is not None: self.video_original_name_label.set_markup("<i>%s</i>" % self.sample_video.display_name) else: - self.video_original_name_label.set_markup("") - + self.video_original_name_label.set_markup("") + def _setup_rename_options_tab(self): - + # sequence numbers self.downloads_today_entry = ValidatedEntry.ValidatedEntry(ValidatedEntry.bounded(ValidatedEntry.v_int, int, 0)) self.stored_number_entry = ValidatedEntry.ValidatedEntry(ValidatedEntry.bounded(ValidatedEntry.v_int, int, 1)) @@ -1251,11 +1251,11 @@ class PreferencesDialog(): self.synchronize_raw_jpg_checkbutton.set_active( self.prefs.synchronize_raw_jpg) - + #compatibility self.strip_characters_checkbutton.set_active( self.prefs.strip_characters) - + def _setup_job_code_tab(self): self.job_code_liststore = gtk.ListStore(str) column = gtk.TreeViewColumn() @@ -1270,13 +1270,13 @@ class PreferencesDialog(): self.job_code_treeview.props.model = self.job_code_liststore for code in self.prefs.job_codes: self.job_code_liststore.append((code, )) - + # set multiple selections self.job_code_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) - + self.remove_all_job_code_button.set_image(gtk.image_new_from_stock( gtk.STOCK_CLEAR, - gtk.ICON_SIZE_BUTTON)) + gtk.ICON_SIZE_BUTTON)) def _setup_device_options_tab(self): """ Setup ignored paths and remembered devices tab in prefs dialog @@ -1284,7 +1284,7 @@ class PreferencesDialog(): self.ignored_paths_use_re_checkbutton.set_active( self.prefs.use_re_ignored_paths) - + self.ignored_paths_liststore = gtk.ListStore(str) column = gtk.TreeViewColumn() rentext = gtk.CellRendererText() @@ -1298,17 +1298,17 @@ class PreferencesDialog(): self.ignored_paths_treeview.props.model = self.ignored_paths_liststore for path in self.prefs.ignored_paths: self.ignored_paths_liststore.append((path, )) - + self.ignored_paths_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.remove_all_ignored_paths_button.set_image(gtk.image_new_from_stock( gtk.STOCK_CLEAR, gtk.ICON_SIZE_BUTTON)) - + # Remembered devices are a little different in that they cannot be - # edited, and they can only added when the user is prompted by the + # edited, and they can only added when the user is prompted by the # program. Moreover, the list the user sees is a combination of two # lists: device_whitelist and device_blacklist - + self.remembered_devices_liststore = gtk.ListStore(str) column = gtk.TreeViewColumn() rentext = gtk.CellRendererText() @@ -1325,12 +1325,12 @@ class PreferencesDialog(): for device in self.prefs.device_blacklist: if device: self.remembered_devices_liststore.append((device, )) - + self.remembered_devices_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.remove_all_remembered_device_button.set_image(gtk.image_new_from_stock( gtk.STOCK_CLEAR, gtk.ICON_SIZE_BUTTON)) - + def _setup_device_tab(self): self.device_location_filechooser_button = gtk.FileChooserButton( @@ -1339,8 +1339,8 @@ class PreferencesDialog(): self.prefs.device_location) self.device_location_filechooser_button.set_action( gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - - self.device_location_filechooser_button.connect("selection-changed", + + self.device_location_filechooser_button.connect("selection-changed", self.on_device_location_filechooser_button_selection_changed) self.devices2_table.attach(self.device_location_filechooser_button, @@ -1350,13 +1350,13 @@ class PreferencesDialog(): self.prefs.device_autodetection) self.autodetect_psd_checkbutton.set_active( self.prefs.device_autodetection_psd) - + self.update_device_controls() - + def _setup_backup_tab(self): """ - Setup and configure backup tab + Setup and configure backup tab """ #Manual backup location for photos file chooser self.backup_folder_filechooser_button = gtk.FileChooserButton( @@ -1365,12 +1365,12 @@ class PreferencesDialog(): self.prefs.backup_location) self.backup_folder_filechooser_button.set_action( gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - self.backup_folder_filechooser_button.connect("selection-changed", + self.backup_folder_filechooser_button.connect("selection-changed", self.on_backup_folder_filechooser_button_selection_changed) self.backup_table.attach(self.backup_folder_filechooser_button, 3, 4, 8, 9, yoptions = gtk.SHRINK) self.backup_folder_filechooser_button.show() - + #Manual backup location for videos file chooser self.backup_video_folder_filechooser_button = gtk.FileChooserButton( _("Select a folder in which to backup videos")) @@ -1378,7 +1378,7 @@ class PreferencesDialog(): self.prefs.backup_video_location) self.backup_video_folder_filechooser_button.set_action( gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - self.backup_video_folder_filechooser_button.connect("selection-changed", + self.backup_video_folder_filechooser_button.connect("selection-changed", self.on_backup_video_folder_filechooser_button_selection_changed) self.backup_table.attach(self.backup_video_folder_filechooser_button, 3, 4, 9, 10, yoptions = gtk.SHRINK) @@ -1386,7 +1386,7 @@ class PreferencesDialog(): self.backup_identifier_entry.set_text(self.prefs.backup_identifier) self.video_backup_identifier_entry.set_text(self.prefs.video_backup_identifier) - + #setup controls for manipulating sensitivity self._backup_controls0 = [self.auto_detect_backup_checkbutton] self._backup_controls1 = [self.backup_identifier_explanation_label, @@ -1397,30 +1397,30 @@ class PreferencesDialog(): self._backup_controls2 = [self.backup_location_label, self.backup_folder_filechooser_button, self.backup_location_explanation_label] - + if metadatavideo.DOWNLOAD_VIDEO: self._backup_controls2 += [self.backup_video_folder_filechooser_button, self.backup_video_location_label] else: self.backup_video_folder_filechooser_button.set_sensitive(False) self.backup_video_location_label.set_sensitive(False) - + self._backup_controls = self._backup_controls0 + self._backup_controls1 + \ self._backup_controls2 - + self._backup_video_controls = [self.video_backup_identifier_label, self.video_backup_identifier_entry] - + #assign values to checkbuttons only when other controls #have been setup, because their toggle signal is activated #when a value is assigned - + self.backup_checkbutton.set_active(self.prefs.backup_images) self.auto_detect_backup_checkbutton.set_active( self.prefs.backup_device_autodetection) self.update_backup_controls() self.update_backup_example() - + def _setup_miscellaneous_tab(self): self.auto_startup_checkbutton.set_active( self.prefs.auto_download_at_startup) @@ -1436,52 +1436,54 @@ class PreferencesDialog(): self.prefs.generate_thumbnails) self.auto_rotate_checkbutton.set_active( self.prefs.auto_rotate_jpeg) - + self.verify_file_checkbutton.set_active( + self.prefs.verify_file) + self.update_misc_controls() - + def _setup_error_tab(self): if self.prefs.download_conflict_resolution == config.SKIP_DOWNLOAD: self.skip_download_radiobutton.set_active(True) else: self.add_identifier_radiobutton.set_active(True) - + if self.prefs.backup_duplicate_overwrite: self.backup_duplicate_overwrite_radiobutton.set_active(True) else: self.backup_duplicate_skip_radiobutton.set_active(True) - + def update_example_file_name(self, display_table, rename_table, sample_rpd_file, generator, example_label): if hasattr(self, display_table) and sample_rpd_file is not None: sample_rpd_file.download_folder = self.prefs.get_download_folder_for_file_type(sample_rpd_file.file_type) sample_rpd_file.strip_characters = self.prefs.strip_characters - sample_rpd_file.initialize_problem() + sample_rpd_file.initialize_problem() name = generator.generate_name(sample_rpd_file) else: name = '' - + # since this is markup, escape it text = "<i>%s</i>" % utilities.escape(name) - + if sample_rpd_file is not None: if sample_rpd_file.has_problem(): text += "\n" # Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees text += _("<i><b>Warning:</b> There is insufficient metadata to fully generate the name. Please use other renaming options.</i>") - example_label.set_markup(text) - + example_label.set_markup(text) + def update_photo_rename_example(self): - """ - Displays example image name to the user + """ + Displays example image name to the user """ generator = gn.PhotoName(self.prefs.image_rename) - self.update_example_file_name('rename_table', self.rename_table, - self.sample_photo, generator, + self.update_example_file_name('rename_table', self.rename_table, + self.sample_photo, generator, self.new_name_label) - + def update_video_rename_example(self): """ Displays example video name to the user @@ -1490,20 +1492,20 @@ class PreferencesDialog(): generator = gn.VideoName(self.prefs.video_rename) else: generator = None - self.update_example_file_name('video_rename_table', - self.video_rename_table, - self.sample_video, generator, + self.update_example_file_name('video_rename_table', + self.video_rename_table, + self.sample_video, generator, self.video_new_name_label) - - def update_download_folder_example(self, display_table, subfolder_table, - download_folder, sample_rpd_file, + + def update_download_folder_example(self, display_table, subfolder_table, + download_folder, sample_rpd_file, generator, - example_download_path_label, + example_download_path_label, subfolder_warning_label): - """ - Displays example subfolder name(s) to the user """ - + Displays example subfolder name(s) to the user + """ + if hasattr(self, display_table) and sample_rpd_file is not None: #~ subfolder_table.update_example_job_code() sample_rpd_file.strip_characters = self.prefs.strip_characters @@ -1511,7 +1513,7 @@ class PreferencesDialog(): path = generator.generate_name(sample_rpd_file) else: path = '' - + text = os.path.join(download_folder, path) # since this is markup, escape it path = utilities.escape(text) @@ -1524,35 +1526,35 @@ class PreferencesDialog(): # Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see example_download_path_label.set_markup(_("<i>Example: %s</i>") % text) subfolder_warning_label.set_markup(warning) - + def update_photo_download_folder_example(self): if hasattr(self, 'subfolder_table'): generator = gn.PhotoSubfolder(self.prefs.subfolder) - self.update_download_folder_example('subfolder_table', + self.update_download_folder_example('subfolder_table', self.subfolder_table, self.prefs.download_folder, - self.sample_photo, generator, - self.example_photo_download_path_label, + self.sample_photo, generator, + self.example_photo_download_path_label, self.photo_subfolder_warning_label) - + def update_video_download_folder_example(self): if hasattr(self, 'video_subfolder_table'): if self.sample_video is not None: generator = gn.VideoSubfolder(self.prefs.video_subfolder) else: generator = None - self.update_download_folder_example('video_subfolder_table', + self.update_download_folder_example('video_subfolder_table', self.video_subfolder_table, self.prefs.video_download_folder, - self.sample_video, generator, - self.example_video_download_path_label, + self.sample_video, generator, + self.example_video_download_path_label, self.video_subfolder_warning_label) - + def on_hour_spinbutton_value_changed(self, spinbutton): hour = spinbutton.get_value_as_int() minute = self.minute_spinbutton.get_value_as_int() self.rapidapp.downloads_today_tracker.set_day_start(hour, minute) self.on_downloads_today_entry_changed(self.downloads_today_entry) - + def on_minute_spinbutton_value_changed(self, spinbutton): hour = self.hour_spinbutton.get_value_as_int() minute = spinbutton.get_value_as_int() @@ -1563,7 +1565,7 @@ class PreferencesDialog(): # do not update value if a download is occurring - it will mess it up! if self.rapidapp.download_is_occurring(): logger.info("Downloads today value not updated, as a download is currently occurring") - else: + else: v = entry.get_text() try: v = int(v) @@ -1574,9 +1576,9 @@ class PreferencesDialog(): self.rapidapp.downloads_today_tracker.reset_downloads_today(v) self.rapidapp.refresh_downloads_today = True self.update_photo_rename_example() - + def on_stored_number_entry_changed(self, entry): - # do not update value if a download is occurring - it will mess it up! + # do not update value if a download is occurring - it will mess it up! if self.rapidapp.download_is_occurring(): logger.info("Stored number value not updated, as a download is currently occurring") else: @@ -1597,13 +1599,13 @@ class PreferencesDialog(): def _update_video_subfolder_pref_on_error(self, new_pref_list): self.prefs.video_subfolder = new_pref_list - - + + def check_subfolder_values_valid_on_exit(self, users_pref_list, update_pref_function, filetype, default_pref_list): """ Checks that the user has not entered in any inappropriate values - - If they have, filters out bad values and warns the user + + If they have, filters out bad values and warns the user """ filtered, pref_list = filter_subfolder_prefs(users_pref_list) if filtered: @@ -1616,7 +1618,7 @@ class PreferencesDialog(): sys.stderr.write(msg + "\n") misc.run_dialog(PROGRAM_NAME, msg) update_pref_function(self.prefs.get_default(default_pref_list)) - + def on_preferencesdialog_response(self, dialog, arg): if arg == gtk.RESPONSE_HELP: webbrowser.open("http://www.damonlynch.net/rapid/documentation") @@ -1624,22 +1626,22 @@ class PreferencesDialog(): # arg==gtk.RESPONSE_CLOSE, or the user hit the 'x' to close the window self.prefs.backup_identifier = self.backup_identifier_entry.get_property("text") self.prefs.video_backup_identifier = self.video_backup_identifier_entry.get_property("text") - + #check subfolder preferences for bad values self.check_subfolder_values_valid_on_exit(self.prefs.subfolder, self._update_subfolder_pref_on_error, _("photo"), "subfolder") self.check_subfolder_values_valid_on_exit(self.prefs.video_subfolder, self._update_video_subfolder_pref_on_error, _("video"), "video_subfolder") - + self.dialog.destroy() self.rapidapp.preferences_dialog_displayed = False self.rapidapp.post_preference_change() - + def on_add_job_code_button_clicked(self, button): j = JobCodeDialog(parent_window = self.dialog, job_codes = self.prefs.job_codes, - default_job_code = None, + default_job_code = None, post_job_code_entry_callback=self.add_job_code, entry_only = True) @@ -1670,36 +1672,36 @@ class PreferencesDialog(): for i in range(0, no): iter = iters[i] if i == no - 1: - path = model.get_path(iter) + path = model.get_path(iter) model.remove(iter) - - # now that we removed the selection, play nice with + + # now that we removed the selection, play nice with # the user and select the next item selection.select_path(path) - + # if there was no selection that meant the user - # removed the last entry, so we try to select the + # removed the last entry, so we try to select the # last item if not selection.path_is_selected(path): row = path[0]-1 # test case for empty lists if row >= 0: selection.select_path((row,)) - - + + def on_remove_job_code_button_clicked(self, button): """ remove selected job codes (can be multiple selection)""" - + self._remove_from_treeview(self.job_code_treeview) self.update_job_codes() self.update_photo_rename_example() self.update_video_rename_example() self.update_photo_download_folder_example() self.update_video_download_folder_example() - + def on_remove_all_job_code_button_clicked(self, button): j = RemoveAllJobCodeDialog(self.dialog, self.remove_all_job_code) - + def remove_all_job_code(self, dialog, user_selected): dialog.destroy() if user_selected: @@ -1709,7 +1711,7 @@ class PreferencesDialog(): self.update_video_rename_example() self.update_photo_download_folder_example() self.update_video_download_folder_example() - + 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) @@ -1723,20 +1725,20 @@ class PreferencesDialog(): replacement_list = [] for row in liststore: replacement_list.append(row[0]) - return replacement_list - + return replacement_list + def update_job_codes(self): """ update preferences with list of job codes""" self.prefs.job_codes = self._update_prefs_list(self.job_code_liststore) - + def on_ignored_path_edited(self, widget, path, new_text): iter = self.ignored_paths_liststore.get_iter(path) self.ignored_paths_liststore.set_value(iter, 0, new_text) - self.update_ignored_paths() - + self.update_ignored_paths() + def update_ignored_paths(self): ignored_paths = self._update_prefs_list(self.ignored_paths_liststore) - + # remove any trailing slashes ignored_paths = [path.rstrip('/') for path in ignored_paths if path] # remove any blank values from ignored_paths @@ -1761,21 +1763,24 @@ class PreferencesDialog(): else: msg = _("This regular expression is invalid, and will be removed unless you correct it:\n %s") % bad_paths misc.run_dialog(_("Invalid regular expression"), msg, self) - + self.prefs.ignored_paths = ignored_paths - + def on_auto_startup_checkbutton_toggled(self, checkbutton): self.prefs.auto_download_at_startup = checkbutton.get_active() - + def on_auto_insertion_checkbutton_toggled(self, checkbutton): self.prefs.auto_download_upon_device_insertion = checkbutton.get_active() - + def on_auto_unmount_checkbutton_toggled(self, checkbutton): self.prefs.auto_unmount = checkbutton.get_active() - + def on_auto_rotate_checkbutton_toggled(self, checkbutton): self.prefs.auto_rotate_jpeg = checkbutton.get_active() + def on_verify_file_checkbutton_toggled(self, checkbutton): + self.prefs.verify_file = checkbutton.get_active() + def on_auto_exit_checkbutton_toggled(self, checkbutton): active = checkbutton.get_active() self.prefs.auto_exit = active @@ -1783,45 +1788,45 @@ class PreferencesDialog(): self.prefs.auto_exit_force = False self.auto_exit_force_checkbutton.set_active(False) self.update_misc_controls() - + def on_auto_exit_force_checkbutton_toggled(self, checkbutton): self.prefs.auto_exit_force = checkbutton.get_active() - + def on_autodetect_device_checkbutton_toggled(self, checkbutton): self.prefs.device_autodetection = checkbutton.get_active() self.update_device_controls() def on_autodetect_psd_checkbutton_toggled(self, checkbutton): self.prefs.device_autodetection_psd = checkbutton.get_active() - + def on_generate_thumbnails_checkbutton_toggled(self, checkbutton): self.prefs.generate_thumbnails = checkbutton.get_active() - + def on_backup_duplicate_overwrite_radiobutton_toggled(self, widget): self.prefs.backup_duplicate_overwrite = widget.get_active() - + def on_backup_duplicate_skip_radiobutton_toggled(self, widget): self.prefs.backup_duplicate_overwrite = not widget.get_active() - + def on_treeview_cursor_changed(self, tree): path, column = tree.get_cursor() self.notebook.set_current_page(path[0]) def on_synchronize_raw_jpg_checkbutton_toggled(self, check_button): self.prefs.synchronize_raw_jpg = check_button.get_active() - + def on_strip_characters_checkbutton_toggled(self, check_button): self.prefs.strip_characters = check_button.get_active() self.update_photo_rename_example() self.update_photo_download_folder_example() self.update_video_download_folder_example() - + def on_add_identifier_radiobutton_toggled(self, widget): if widget.get_active(): self.prefs.download_conflict_resolution = config.ADD_UNIQUE_IDENTIFIER else: self.prefs.download_conflict_resolution = config.SKIP_DOWNLOAD - + def update_device_controls(self): """ @@ -1842,7 +1847,7 @@ class PreferencesDialog(): c.set_sensitive(True) self.autodetect_psd_checkbutton.set_sensitive(False) self.autodetect_image_devices_label.set_sensitive(False) - + if not self.pref_dialog_startup: logger.debug("Resetting sample file photo and video files") self._setup_sample_names(use_dummy_data = True) @@ -1852,20 +1857,20 @@ class PreferencesDialog(): self.update_video_download_folder_example() self._setup_video_original_name() self.update_video_rename_example() - + def update_misc_controls(self): """ Sets sensitivity of miscillaneous controls """ - + self.auto_exit_force_checkbutton.set_sensitive(self.prefs.auto_exit) - - + + def update_backup_controls(self): """ Sets sensitivity of backup related widgets """ - + if not self.backup_checkbutton.get_active(): for c in self._backup_controls + self._backup_video_controls: c.set_sensitive(False) @@ -1897,15 +1902,15 @@ class PreferencesDialog(): c.set_sensitive(True) if metadatavideo.DOWNLOAD_VIDEO: for c in self._backup_video_controls: - c.set_sensitive(False) - + c.set_sensitive(False) + def disable_video_controls(self): """ Disables video preferences if video downloading is disabled (probably because the appropriate libraries to enable video metadata extraction are not installed) - """ - controls = [self.example_video_filename_label, + """ + controls = [self.example_video_filename_label, self.original_video_filename_label, self.new_video_filename_label, self.video_new_name_label, @@ -1917,27 +1922,27 @@ class PreferencesDialog(): ] for c in controls: c.set_sensitive(False) - + self.videos_cannot_be_downloaded_label.show() self.folder_videos_cannot_be_downloaded_label.show() self.folder_videos_cannot_be_downloaded_hbox.show() - + def on_auto_detect_backup_checkbutton_toggled(self, widget): self.prefs.backup_device_autodetection = widget.get_active() self.update_backup_controls_auto() - + def on_backup_checkbutton_toggled(self, widget): self.prefs.backup_images = self.backup_checkbutton.get_active() self.update_backup_controls() def on_backup_identifier_entry_changed(self, widget): self.update_backup_example() - + def on_video_backup_identifier_entry_changed(self, widget): self.update_backup_example() def on_backup_scan_folder_on_entry_changed(self, widget): - self.update_backup_example() + self.update_backup_example() def update_backup_example(self): # Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. |