Skip to content

Commit aaea73a

Browse files
committed
PICARD-2496: Replace overwrite option with conflict handling strategy (skip/rename/overwrite)
1 parent 52a0f00 commit aaea73a

File tree

4 files changed

+53
-15
lines changed

4 files changed

+53
-15
lines changed

picard/file.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,16 @@ def _rename(self, old_filename, metadata, settings):
676676
new_dirname = os.path.dirname(new_filename)
677677
if not os.path.isdir(new_dirname):
678678
os.makedirs(new_dirname)
679-
if not settings['move_overwrite_existing_files']:
680-
new_filename = get_available_filename(new_filename, old_filename)
679+
config = get_config()
680+
strategy = config.setting.get('move_conflict_strategy', 'rename')
681+
if os.path.exists(new_filename):
682+
if strategy == "skip":
683+
log.warning("Destination exists, skipping move of %r", old_filename)
684+
return old_filename
685+
elif strategy == "rename":
686+
new_filename = get_available_filename(new_filename, old_filename)
687+
elif strategy == "overwrite":
688+
pass
681689
log.debug("Moving file %r => %r", old_filename, new_filename)
682690
move_ensure_casing(old_filename, new_filename)
683691
return new_filename
@@ -697,7 +705,6 @@ def _save_images(self, dirname, metadata):
697705
images = metadata.images
698706
for image in images:
699707
image.save(dirname, metadata, counters)
700-
701708
def _move_additional_files(self, old_filename, new_filename, config):
702709
"""Move extra files, like images, playlists…"""
703710
if config.setting['move_files'] and config.setting['move_additional_files']:
@@ -708,7 +715,7 @@ def _move_additional_files(self, old_filename, new_filename, config):
708715
patterns = self._compile_move_additional_files_pattern(patterns_string)
709716
try:
710717
moves = self._get_additional_files_moves(old_path, new_path, patterns)
711-
self._apply_additional_files_moves(moves, config.setting['move_overwrite_existing_files'])
718+
self._apply_additional_files_moves(moves)
712719
except OSError as why:
713720
log.error("Failed to scan %r: %s", old_path, why)
714721

@@ -732,15 +739,22 @@ def _get_additional_files_moves(self, old_path, new_path, patterns):
732739
yield (entry.path, new_file_path)
733740
break # we are done with this file
734741

735-
def _apply_additional_files_moves(self, moves, overwrite_existing_files=False):
742+
def _apply_additional_files_moves(self, moves):
743+
config = get_config()
744+
strategy = config.setting.get('move_conflict_strategy', 'rename')
736745
for old_file_path, new_file_path in moves:
737746
# FIXME we shouldn't do this from a thread!
738747
if self.tagger.files.get(decode_filename(old_file_path)):
739748
log.debug("File loaded in the tagger, not moving %r", old_file_path)
740749
continue
741-
if not overwrite_existing_files and os.path.exists(new_file_path):
742-
log.warning("File %r already exists, not moving %r", new_file_path, old_file_path)
743-
continue
750+
if os.path.exists(new_file_path):
751+
if strategy == "skip":
752+
log.warning("File %r exists, skipping %r", new_file_path, old_file_path)
753+
continue
754+
elif strategy == "rename":
755+
new_file_path = get_available_filename(new_file_path)
756+
elif strategy == "overwrite":
757+
pass
744758
log.debug("Moving %r to %r", old_file_path, new_file_path)
745759
try:
746760
shutil.move(old_file_path, new_file_path)

picard/options.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,6 @@ def make_default_toolbar_layout():
427427
TextOption('setting', 'move_additional_files_pattern', "*.jpg *.png", title=N_("Additional file patterns"))
428428
BoolOption('setting', 'move_files', False, title=N_("Move files"))
429429
TextOption('setting', 'move_files_to', DEFAULT_MUSIC_DIR, title=N_("Destination directory"))
430-
BoolOption('setting', 'move_overwrite_existing_files', False, title=N_("Overwrite existing files"))
431430
BoolOption('setting', 'rename_files', False, title=N_("Rename files"))
432431

433432
# picard/ui/options/renaming_compat.py
@@ -540,6 +539,7 @@ def make_default_toolbar_layout():
540539
'',
541540
title=N_("Sessions directory"),
542541
)
542+
TextOption('setting', 'move_conflict_strategy', 'rename', title=N_("File conflict handling strategy"))
543543

544544
# picard/ui/searchdialog/album.py
545545
#

picard/ui/options/renaming.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ class RenamingOptionsPage(OptionsPage):
7575
OPTIONS = (
7676
('move_files', ['move_files']),
7777
('move_files_to', ['move_files_to']),
78-
('move_overwrite_existing_files', ['move_overwrite_existing_files']),
7978
('move_additional_files', ['move_additional_files']),
8079
('move_additional_files_pattern', ['move_additional_files_pattern']),
80+
('move_conflict_strategy', ['move_conflict_strategy']),
8181
('delete_empty_dirs', ['delete_empty_dirs']),
8282
('rename_files', ['rename_files']),
8383
('selected_file_naming_script_id', ['naming_script_selector']),
@@ -250,8 +250,11 @@ def load(self):
250250
self.ui.move_files_to.setCursorPosition(0)
251251
self.ui.move_additional_files.setChecked(config.setting['move_additional_files'])
252252
self.ui.move_additional_files_pattern.setText(config.setting['move_additional_files_pattern'])
253+
strategy = config.setting['move_conflict_strategy']
254+
self.ui.move_conflict_skip.setChecked(strategy == "skip")
255+
self.ui.move_conflict_rename.setChecked(strategy == "rename")
256+
self.ui.move_conflict_overwrite.setChecked(strategy == "overwrite")
253257
self.ui.delete_empty_dirs.setChecked(config.setting['delete_empty_dirs'])
254-
self.ui.move_overwrite_existing_files.setChecked(config.setting['move_overwrite_existing_files'])
255258
self.naming_scripts = config.setting['file_renaming_scripts']
256259
self.selected_naming_script_id = config.setting['selected_file_naming_script_id']
257260
if self.script_editor_dialog:
@@ -285,9 +288,14 @@ def save(self):
285288
config.setting['move_files'] = self.ui.move_files.isChecked()
286289
config.setting['move_files_to'] = os.path.normpath(self.ui.move_files_to.text())
287290
config.setting['move_additional_files'] = self.ui.move_additional_files.isChecked()
291+
if self.ui.move_conflict_skip.isChecked():
292+
config.setting['move_conflict_strategy'] = "skip"
293+
elif self.ui.move_conflict_rename.isChecked():
294+
config.setting['move_conflict_strategy'] = "rename"
295+
elif self.ui.move_conflict_overwrite.isChecked():
296+
config.setting['move_conflict_strategy'] = "overwrite"
288297
config.setting['move_additional_files_pattern'] = self.ui.move_additional_files_pattern.text()
289298
config.setting['delete_empty_dirs'] = self.ui.delete_empty_dirs.isChecked()
290-
config.setting['move_overwrite_existing_files'] = self.ui.move_overwrite_existing_files.isChecked()
291299
config.setting['selected_file_naming_script_id'] = self.selected_naming_script_id
292300

293301
def display_error(self, error):

ui/options_renaming.ui

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,23 @@
8080
</widget>
8181
</item>
8282
<item>
83-
<widget class="QCheckBox" name="move_overwrite_existing_files">
83+
<widget class="QRadioButton" name="move_conflict_skip">
8484
<property name="text">
85-
<string>Overwrite existing files</string>
85+
<string>Do not move duplicate files</string>
86+
</property>
87+
</widget>
88+
</item>
89+
<item>
90+
<widget class="QRadioButton" name="move_conflict_rename">
91+
<property name="text">
92+
<string>Move and rename file with numeric suffix</string>
93+
</property>
94+
</widget>
95+
</item>
96+
<item>
97+
<widget class="QRadioButton" name="move_conflict_overwrite">
98+
<property name="text">
99+
<string>Move and overwrite existing files</string>
86100
</property>
87101
</widget>
88102
</item>
@@ -298,7 +312,9 @@
298312
<tabstop>move_additional_files</tabstop>
299313
<tabstop>move_additional_files_pattern</tabstop>
300314
<tabstop>delete_empty_dirs</tabstop>
301-
<tabstop>move_overwrite_existing_files</tabstop>
315+
<tabstop>move_conflict_skip</tabstop>
316+
<tabstop>move_conflict_rename</tabstop>
317+
<tabstop>move_conflict_overwrite</tabstop>
302318
<tabstop>rename_files</tabstop>
303319
<tabstop>naming_script_selector</tabstop>
304320
<tabstop>open_script_editor</tabstop>

0 commit comments

Comments
 (0)