Skip to content

Commit f2744d4

Browse files
ethanwharrislenhard
authored andcommitted
Fix for issue #2721 append to a field (#3395)
* Add append button (no functionality) to the user interface under Quality -> set/clear/rename fields * Add functionality to append button under Quality -> Set/clear/append/rename fields * Update Localization for set/clear/append/rename fields dialog * Update CHANGELOG.md * Rename variables (ce -> compoundEdit, oldVal -> oldValue, text -> textToAppend / Set etc.) for review and rename some variables from old code to match. * Prevent re-assignment of parameter in massAppend method * Rename TextField variables for clarity * Revert localisation for set/clear/appen/rename_fields to original from set/clear/rename_fields
1 parent efdf91a commit f2744d4

38 files changed

+161
-78
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
3030
- Late initialization of the context menus in the entry editor. This improves performance and memory footprint further [#3340](https://github.com/JabRef/jabref/pull/3340)
3131
- Integrity check "Abbreviation Detection" detects abbreviated names for journals and booktitles based on the internal list instead of only looking for "." signs. Fixes [#3144](https://github.com/JabRef/jabref/issues/3144).
3232
- We added a dialog to show that JabRef is working on checking integrity. [#3358](https://github.com/JabRef/jabref/issues/3358)
33+
- We added an option to mass append to fields via the Quality -> set/clear/append/rename fields dialog. [#2721](https://github.com/JabRef/jabref/issues/2721)
3334

3435
### Fixed
3536
- We fixed the translation of \textendash in the entry preview [#3307](https://github.com/JabRef/jabref/issues/3307)

src/main/java/org/jabref/gui/actions/MassSetFieldAction.java

Lines changed: 88 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -53,28 +53,32 @@ public class MassSetFieldAction extends MnemonicAwareAction {
5353
private JRadioButton selected;
5454
private JRadioButton clear;
5555
private JRadioButton set;
56+
private JRadioButton append;
5657
private JRadioButton rename;
5758
private JComboBox<String> field;
58-
private JTextField text;
59-
private JTextField renameTo;
59+
private JTextField textFieldSet;
60+
private JTextField textFieldAppend;
61+
private JTextField textFieldRename;
6062
private boolean canceled = true;
6163
private JCheckBox overwrite;
6264

6365

6466
public MassSetFieldAction(JabRefFrame frame) {
65-
putValue(Action.NAME, Localization.menuTitle("Set/clear/rename fields") + "...");
67+
putValue(Action.NAME, Localization.menuTitle("Set/clear/append/rename fields") + "...");
6668
this.frame = frame;
6769
}
6870

6971
private void createDialog() {
70-
diag = new JDialog(frame, Localization.lang("Set/clear/rename fields"), true);
72+
diag = new JDialog(frame, Localization.lang("Set/clear/append/rename fields"), true);
7173

7274
field = new JComboBox<>();
7375
field.setEditable(true);
74-
text = new JTextField();
75-
text.setEnabled(false);
76-
renameTo = new JTextField();
77-
renameTo.setEnabled(false);
76+
textFieldSet = new JTextField();
77+
textFieldSet.setEnabled(false);
78+
textFieldAppend = new JTextField();
79+
textFieldAppend.setEnabled(false);
80+
textFieldRename = new JTextField();
81+
textFieldRename.setEnabled(false);
7882

7983
JButton ok = new JButton(Localization.lang("OK"));
8084
JButton cancel = new JButton(Localization.lang("Cancel"));
@@ -83,6 +87,7 @@ private void createDialog() {
8387
selected = new JRadioButton(Localization.lang("Selected entries"));
8488
clear = new JRadioButton(Localization.lang("Clear fields"));
8589
set = new JRadioButton(Localization.lang("Set fields"));
90+
append = new JRadioButton(Localization.lang("Append to fields"));
8691
rename = new JRadioButton(Localization.lang("Rename field to") + ":");
8792
rename.setToolTipText(Localization.lang("Move contents of a field into a field with a different name"));
8893

@@ -93,16 +98,23 @@ private void createDialog() {
9398
}
9499

95100
set.addChangeListener(e ->
96-
// Entering a text is only relevant if we are setting, not clearing:
97-
text.setEnabled(set.isSelected()));
101+
// Entering a setText is only relevant if we are setting, not clearing:
102+
textFieldSet.setEnabled(set.isSelected()));
103+
104+
append.addChangeListener(e -> {
105+
// Text to append is only required if we are appending:
106+
textFieldAppend.setEnabled(append.isSelected());
107+
// Overwrite protection makes no sense if we are appending to a field:
108+
overwrite.setEnabled(!clear.isSelected() && !append.isSelected());
109+
});
98110

99111
clear.addChangeListener(e ->
100-
// Overwrite protection makes no sense if we are clearing the field:
101-
overwrite.setEnabled(!clear.isSelected()));
112+
// Overwrite protection makes no sense if we are clearing the field:
113+
overwrite.setEnabled(!clear.isSelected() && !append.isSelected()));
102114

103115
rename.addChangeListener(e ->
104-
// Entering a text is only relevant if we are renaming
105-
renameTo.setEnabled(rename.isSelected()));
116+
// Entering a setText is only relevant if we are renaming
117+
textFieldRename.setEnabled(rename.isSelected()));
106118

107119
overwrite = new JCheckBox(Localization.lang("Overwrite existing field values"), true);
108120
ButtonGroup bg = new ButtonGroup();
@@ -111,9 +123,10 @@ private void createDialog() {
111123
bg = new ButtonGroup();
112124
bg.add(clear);
113125
bg.add(set);
126+
bg.add(append);
114127
bg.add(rename);
115128
FormBuilder builder = FormBuilder.create().layout(new FormLayout(
116-
"left:pref, 4dlu, fill:100dlu:grow", "pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref"));
129+
"left:pref, 4dlu, fill:100dlu:grow", "pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref"));
117130
builder.addSeparator(Localization.lang("Field name")).xyw(1, 1, 3);
118131
builder.add(Localization.lang("Field name")).xy(1, 3);
119132
builder.add(field).xy(3, 3);
@@ -122,11 +135,13 @@ private void createDialog() {
122135
builder.add(selected).xyw(1, 9, 3);
123136
builder.addSeparator(Localization.lang("New field value")).xyw(1, 11, 3);
124137
builder.add(set).xy(1, 13);
125-
builder.add(text).xy(3, 13);
138+
builder.add(textFieldSet).xy(3, 13);
126139
builder.add(clear).xyw(1, 15, 3);
127-
builder.add(rename).xy(1, 17);
128-
builder.add(renameTo).xy(3, 17);
129-
builder.add(overwrite).xyw(1, 19, 3);
140+
builder.add(append).xy(1, 17);
141+
builder.add(textFieldAppend).xy(3, 17);
142+
builder.add(rename).xy(1, 19);
143+
builder.add(textFieldRename).xy(3, 19);
144+
builder.add(overwrite).xyw(1, 21, 3);
130145

131146
ButtonBarBuilder bb = new ButtonBarBuilder();
132147
bb.addGlue();
@@ -219,31 +234,36 @@ public void actionPerformed(ActionEvent e) {
219234
} else {
220235
entryList = entries;
221236
}
222-
String toSet = text.getText();
237+
238+
String toSet = textFieldSet.getText();
223239
if (toSet.isEmpty()) {
224240
toSet = null;
225241
}
226242

227243
String[] fields = getFieldNames(((String) field.getSelectedItem()).trim().toLowerCase(Locale.ROOT));
228-
NamedCompound ce = new NamedCompound(Localization.lang("Set field"));
244+
NamedCompound compoundEdit = new NamedCompound(Localization.lang("Set field"));
229245
if (rename.isSelected()) {
230246
if (fields.length > 1) {
231247
JOptionPane.showMessageDialog(diag, Localization.lang("You can only rename one field at a time"), "",
232248
JOptionPane.ERROR_MESSAGE);
233249
return; // Do not close the dialog.
234250
} else {
235-
ce.addEdit(MassSetFieldAction.massRenameField(entryList, fields[0], renameTo.getText(),
251+
compoundEdit.addEdit(MassSetFieldAction.massRenameField(entryList, fields[0], textFieldRename.getText(),
236252
overwrite.isSelected()));
237253
}
254+
} else if (append.isSelected()) {
255+
for (String field : fields) {
256+
compoundEdit.addEdit(MassSetFieldAction.massAppendField(entryList, field, textFieldAppend.getText()));
257+
}
238258
} else {
239-
for (String field1 : fields) {
240-
ce.addEdit(MassSetFieldAction.massSetField(entryList, field1,
259+
for (String field : fields) {
260+
compoundEdit.addEdit(MassSetFieldAction.massSetField(entryList, field,
241261
set.isSelected() ? toSet : null,
242262
overwrite.isSelected()));
243263
}
244264
}
245-
ce.end();
246-
bp.getUndoManager().addEdit(ce);
265+
compoundEdit.end();
266+
bp.getUndoManager().addEdit(compoundEdit);
247267
bp.markBaseChanged();
248268
}
249269

@@ -253,31 +273,58 @@ public void actionPerformed(ActionEvent e) {
253273
*
254274
* @param entries The entries to set the field for.
255275
* @param field The name of the field to set.
256-
* @param text The value to set. This value can be null, indicating that the field should be cleared.
276+
* @param textToSet The value to set. This value can be null, indicating that the field should be cleared.
257277
* @param overwriteValues Indicate whether the value should be set even if an entry already has the field set.
258278
* @return A CompoundEdit for the entire operation.
259279
*/
260-
private static UndoableEdit massSetField(Collection<BibEntry> entries, String field, String text,
280+
private static UndoableEdit massSetField(Collection<BibEntry> entries, String field, String textToSet,
261281
boolean overwriteValues) {
262282

263-
NamedCompound ce = new NamedCompound(Localization.lang("Set field"));
283+
NamedCompound compoundEdit = new NamedCompound(Localization.lang("Set field"));
264284
for (BibEntry entry : entries) {
265-
Optional<String> oldVal = entry.getField(field);
285+
Optional<String> oldValue = entry.getField(field);
266286
// If we are not allowed to overwrite values, check if there is a
267287
// nonempty
268288
// value already for this entry:
269-
if (!overwriteValues && (oldVal.isPresent()) && !oldVal.get().isEmpty()) {
289+
if (!overwriteValues && (oldValue.isPresent()) && !oldValue.get().isEmpty()) {
270290
continue;
271291
}
272-
if (text == null) {
292+
if (textToSet == null) {
273293
entry.clearField(field);
274294
} else {
275-
entry.setField(field, text);
295+
entry.setField(field, textToSet);
276296
}
277-
ce.addEdit(new UndoableFieldChange(entry, field, oldVal.orElse(null), text));
297+
compoundEdit.addEdit(new UndoableFieldChange(entry, field, oldValue.orElse(null), textToSet));
298+
}
299+
compoundEdit.end();
300+
return compoundEdit;
301+
}
302+
303+
/**
304+
* Append a given value to a given field for all entries in a Collection. This method DOES NOT update any UndoManager,
305+
* but returns a relevant CompoundEdit that should be registered by the caller.
306+
*
307+
* @param entries The entries to process the operation for.
308+
* @param field The name of the field to append to.
309+
* @param textToAppend The value to set. A null in this case will simply preserve the current field state.
310+
* @return A CompoundEdit for the entire operation.
311+
*/
312+
private static UndoableEdit massAppendField(Collection<BibEntry> entries, String field, String textToAppend) {
313+
314+
String newValue = "";
315+
316+
if (textToAppend != null) {
317+
newValue = textToAppend;
318+
}
319+
320+
NamedCompound compoundEdit = new NamedCompound(Localization.lang("Append field"));
321+
for (BibEntry entry : entries) {
322+
Optional<String> oldValue = entry.getField(field);
323+
entry.setField(field, oldValue.orElse("") + newValue);
324+
compoundEdit.addEdit(new UndoableFieldChange(entry, field, oldValue.orElse(null), newValue));
278325
}
279-
ce.end();
280-
return ce;
326+
compoundEdit.end();
327+
return compoundEdit;
281328
}
282329

283330
/**
@@ -292,7 +339,7 @@ private static UndoableEdit massSetField(Collection<BibEntry> entries, String fi
292339
*/
293340
private static UndoableEdit massRenameField(Collection<BibEntry> entries, String field, String newField,
294341
boolean overwriteValues) {
295-
NamedCompound ce = new NamedCompound(Localization.lang("Rename field"));
342+
NamedCompound compoundEdit = new NamedCompound(Localization.lang("Rename field"));
296343
for (BibEntry entry : entries) {
297344
Optional<String> valToMove = entry.getField(field);
298345
// If there is no value, do nothing:
@@ -307,12 +354,12 @@ private static UndoableEdit massRenameField(Collection<BibEntry> entries, String
307354
}
308355

309356
entry.setField(newField, valToMove.get());
310-
ce.addEdit(new UndoableFieldChange(entry, newField, valInNewField.orElse(null), valToMove.get()));
357+
compoundEdit.addEdit(new UndoableFieldChange(entry, newField, valInNewField.orElse(null), valToMove.get()));
311358
entry.clearField(field);
312-
ce.addEdit(new UndoableFieldChange(entry, field, valToMove.get(), null));
359+
compoundEdit.addEdit(new UndoableFieldChange(entry, field, valToMove.get(), null));
313360
}
314-
ce.end();
315-
return ce;
361+
compoundEdit.end();
362+
return compoundEdit;
316363
}
317364

318365
private static String[] getFieldNames(String s) {

src/main/resources/l10n/JabRef_da.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=Download_af_fuldtekst-dokument_mislykkedes
13751375
Update_to_current_column_order=Brug_nuværende_kolonnerækkefølge
13761376
Download_from_URL=
13771377
Rename_field=Omdøb_felt
1378-
Set/clear/rename_fields=Sæt/ryd/omdøb_felter
1378+
Set/clear/append/rename_fields=Sæt/ryd/omdøb_felter
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=Omdøb_felt_til
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=Flyt_indhold_af_et_felt_til_et_felt_med_et_andet_navn
13811383
You_can_only_rename_one_field_at_a_time=Du_kan_kun_omdøbe_et_felt_ad_gangen

src/main/resources/l10n/JabRef_de.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=Herunterladen_des_Volltext-Beitrags_fehlgesch
13751375
Update_to_current_column_order=Aktuelle_Spaltenanordnung_verwenden
13761376
Download_from_URL=Download_von_URL
13771377
Rename_field=Feld_umbenennen
1378-
Set/clear/rename_fields=Felder_setzen/löschen/umbenennen
1378+
Set/clear/append/rename_fields=Felder_setzen/löschen/umbenennen
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=Feld_umbenennen
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=Inhalt_eines_Felds_in_ein_Feld_mit_anderem_Namen_verschieben
13811383
You_can_only_rename_one_field_at_a_time=Sie_können_nur_eine_Datei_auf_einmal_umbenennen

src/main/resources/l10n/JabRef_el.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=
13751375
Update_to_current_column_order=
13761376
Download_from_URL=
13771377
Rename_field=
1378-
Set/clear/rename_fields=
1378+
Set/clear/append/rename_fields=Ρύθμιση/καθαρισμός/μετονομασία_πεδίων
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=
13811383
You_can_only_rename_one_field_at_a_time=

src/main/resources/l10n/JabRef_en.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=Full_text_document_download_failed
13751375
Update_to_current_column_order=Update_to_current_column_order
13761376
Download_from_URL=Download_from_URL
13771377
Rename_field=Rename_field
1378-
Set/clear/rename_fields=Set/clear/rename_fields
1378+
Set/clear/append/rename_fields=Set/clear/append/rename_fields
1379+
Append_field=Append_field
1380+
Append_to_fields=Append_to_fields
13791381
Rename_field_to=Rename_field_to
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=Move_contents_of_a_field_into_a_field_with_a_different_name
13811383
You_can_only_rename_one_field_at_a_time=You_can_only_rename_one_field_at_a_time

src/main/resources/l10n/JabRef_es.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=Falló_la_descarga_del_texto_completo_del_art
13751375
Update_to_current_column_order=Actualizar_al_orden_de_columnas_actual
13761376
Download_from_URL=Descargar_desde_URL
13771377
Rename_field=Renombrar_campo
1378-
Set/clear/rename_fields=Establecer/limpiar/renombrar_campos
1378+
Set/clear/append/rename_fields=Establecer/limpiar/renombrar_campos
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=Renombrar_campo_a
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=Mover_contenidos_de_un_campo_en_un_campo_con_nombre_diferente
13811383
You_can_only_rename_one_field_at_a_time=Sólo_puede_renombrar_un_campo_a_la_vez

src/main/resources/l10n/JabRef_fa.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=
13751375
Update_to_current_column_order=
13761376
Download_from_URL=
13771377
Rename_field=
1378-
Set/clear/rename_fields=
1378+
Set/clear/append/rename_fields=تنظیم/حذف/تغییرنام_حوزه‌ها
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=
13811383
You_can_only_rename_one_field_at_a_time=

src/main/resources/l10n/JabRef_fr.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=Echec_du_téléchargement_du_document_cité
13751375
Update_to_current_column_order=Enregistrer_l'ordre_actuel_des_colonnes
13761376
Download_from_URL=Télécharger_depuis_l'URL
13771377
Rename_field=Renommer_le_champ
1378-
Set/clear/rename_fields=Définir/vider/renommer_les_champs
1378+
Set/clear/append/rename_fields=Définir/vider/renommer_les_champs
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=Renommer_le_champ_en
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=Déplacer_le_contenu_d'un_champ_vers_un_champ_d'un_nom_différent
13811383
You_can_only_rename_one_field_at_a_time=Vou_pouvez_supprimer_uniquement_un_champ_à_la_fois
@@ -2341,7 +2343,6 @@ Copying_file_%0_of_entry_%1=
23412343
Finished_copying=
23422344
Could_not_copy_file=
23432345
Copied_%0_files_of_%1_sucessfully_to_%2==
2344-
23452346
Rename_failed=Échec_du_renommage
23462347
JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_ne_peut_pas_accéder_au_fichier_parce_qu'il_est_utilisé_par_un_autre_processus.
23472348
Show_console_output_(only_necessary_when_the_launcher_is_used)=Afficher_la_sortie_de_la_console_(uniquement_nécessaire_quand_le_lanceur_est_utilisé)

src/main/resources/l10n/JabRef_in.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,9 @@ Full_text_document_download_failed=Gagal_muaturun_artikel_teks_lengkap
13751375
Update_to_current_column_order=Perbarui_sebuai_urutan_kolom_sekarang
13761376
Download_from_URL=
13771377
Rename_field=Ganti_nama_bidang
1378-
Set/clear/rename_fields=Pilih/hapus/namai_ulang_bidang
1378+
Set/clear/append/rename_fields=Pilih/hapus/namai_ulang_bidang
1379+
Append_field=
1380+
Append_to_fields=
13791381
Rename_field_to=Ganti_nama_bidang_menjadi
13801382
Move_contents_of_a_field_into_a_field_with_a_different_name=Pindah_isi_dari_bidang_ke_bidang_lain_dengan_nama_lain
13811383
You_can_only_rename_one_field_at_a_time=Anda_bisa_mengganti_nama_satu_bidang_dalam_satu_waktu

0 commit comments

Comments
 (0)