Skip to content

Commit 0a63038

Browse files
Akanksha928Siedlerchrcalixtus
authored
Automatic field editor: Add Clear content tab + viewmodel (#13824)
* Automatic field editor: Add Clear content tab + viewmodel * Removing comments * PR comment changes * Bot suggested changes * Bot suggested changes * reformat * fix fxml * Added tests, reformats and visual modifications. Fixed number of affected files * Fixed tab number * CHANGELOG.md --------- Co-authored-by: Siedlerchr <[email protected]> Co-authored-by: Carl Christian Snethlage <[email protected]>
1 parent dc61614 commit 0a63038

File tree

12 files changed

+274
-61
lines changed

12 files changed

+274
-61
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
7070
- We added support for import of a Refer/BibIX file format. [#13069](https://github.com/JabRef/jabref/issues/13069)
7171
- We added markdown rendering and copy capabilities to AI chat responses. [#12234](https://github.com/JabRef/jabref/issues/12234)
7272
- We added a new `jabkit` command `pseudonymize` to pseudonymize the library. [#13109](https://github.com/JabRef/jabref/issues/13109)
73+
- We moved the clear fields mechanic in the Automatic Field Editor from the edit content tab to a separate tab. [#13780](https://github.com/JabRef/jabref/issues/13780)
7374
- We added functionality to focus running instance when trying to start a second instance. [#13129](https://github.com/JabRef/jabref/issues/13129)
7475
- We added a "Copy Field Content" submenu to the entry context menu, allowing users to quickly copy specific field contents including Author, Journal, Date, Keywords, and Abstract fields from selected entries. [#13280](https://github.com/JabRef/jabref/pull/13280)
7576
- We added a highlighted diff regarding changes to the Group Tree Structure of a bib file, made outside JabRef. [#11221](https://github.com/JabRef/jabref/issues/11221)

jabgui/src/main/java/org/jabref/gui/edit/automaticfiededitor/AutomaticFieldEditorViewModel.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import org.jabref.gui.AbstractViewModel;
99
import org.jabref.gui.StateManager;
10+
import org.jabref.gui.edit.automaticfiededitor.clearcontent.ClearContentTabView;
1011
import org.jabref.gui.edit.automaticfiededitor.copyormovecontent.CopyOrMoveFieldContentTabView;
1112
import org.jabref.gui.edit.automaticfiededitor.editfieldcontent.EditFieldContentTabView;
1213
import org.jabref.gui.edit.automaticfiededitor.renamefield.RenameFieldTabView;
@@ -25,6 +26,7 @@ public AutomaticFieldEditorViewModel(BibDatabase database, UndoManager undoManag
2526
fieldEditorTabs.addAll(
2627
new EditFieldContentTabView(database, stateManager),
2728
new CopyOrMoveFieldContentTabView(database, stateManager),
29+
new ClearContentTabView(stateManager),
2830
new RenameFieldTabView(database, stateManager)
2931
);
3032
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.jabref.gui.edit.automaticfiededitor.clearcontent;
2+
3+
import java.util.Set;
4+
5+
import javafx.application.Platform;
6+
import javafx.fxml.FXML;
7+
import javafx.scene.control.Button;
8+
import javafx.scene.control.CheckBox;
9+
import javafx.scene.control.ComboBox;
10+
11+
import org.jabref.gui.StateManager;
12+
import org.jabref.gui.edit.automaticfiededitor.AbstractAutomaticFieldEditorTabView;
13+
import org.jabref.gui.edit.automaticfiededitor.AutomaticFieldEditorTab;
14+
import org.jabref.logic.l10n.Localization;
15+
import org.jabref.model.entry.field.Field;
16+
17+
import com.airhacks.afterburner.views.ViewLoader;
18+
import com.tobiasdiez.easybind.EasyBind;
19+
20+
import static org.jabref.gui.util.FieldsUtil.FIELD_STRING_CONVERTER;
21+
22+
public class ClearContentTabView extends AbstractAutomaticFieldEditorTabView implements AutomaticFieldEditorTab {
23+
24+
@FXML private ComboBox<Field> fieldComboBox;
25+
@FXML private CheckBox showOnlySetFieldsCheckBox;
26+
@FXML private Button clearButton;
27+
private final StateManager stateManager;
28+
private ClearContentViewModel viewModel;
29+
30+
public ClearContentTabView(StateManager stateManager) {
31+
this.stateManager = stateManager;
32+
ViewLoader.view(this)
33+
.root(this)
34+
.load();
35+
}
36+
37+
@FXML
38+
public void initialize() {
39+
viewModel = new ClearContentViewModel(stateManager);
40+
41+
fieldComboBox.setConverter(FIELD_STRING_CONVERTER);
42+
fieldComboBox.getItems().setAll(viewModel.getAllFields());
43+
if (!fieldComboBox.getItems().isEmpty()) {
44+
fieldComboBox.getSelectionModel().selectFirst();
45+
}
46+
47+
EasyBind.subscribe(showOnlySetFieldsCheckBox.selectedProperty(), selected -> {
48+
Set<Field> items = selected ? viewModel.getSetFieldsOnly()
49+
: viewModel.getAllFields();
50+
fieldComboBox.getItems().setAll(items);
51+
if (!items.isEmpty()) {
52+
fieldComboBox.getSelectionModel().selectFirst();
53+
}
54+
});
55+
56+
clearButton.disableProperty().bind(fieldComboBox.valueProperty().isNull());
57+
58+
Platform.runLater(fieldComboBox::requestFocus);
59+
}
60+
61+
@FXML
62+
private void onClear() {
63+
Field chosen = fieldComboBox.getValue();
64+
if (chosen != null) {
65+
viewModel.clearField(chosen);
66+
}
67+
}
68+
69+
@Override
70+
public String getTabName() {
71+
return Localization.lang("Clear content");
72+
}
73+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.jabref.gui.edit.automaticfiededitor.clearcontent;
2+
3+
import java.util.LinkedHashSet;
4+
import java.util.List;
5+
import java.util.Optional;
6+
import java.util.Set;
7+
import java.util.stream.Collectors;
8+
9+
import org.jabref.gui.StateManager;
10+
import org.jabref.gui.edit.automaticfiededitor.LastAutomaticFieldEditorEdit;
11+
import org.jabref.gui.undo.NamedCompoundEdit;
12+
import org.jabref.gui.undo.UndoableFieldChange;
13+
import org.jabref.model.entry.BibEntry;
14+
import org.jabref.model.entry.field.Field;
15+
import org.jabref.model.entry.field.FieldFactory;
16+
17+
public class ClearContentViewModel {
18+
public static final int TAB_INDEX = 2;
19+
private final StateManager stateManager;
20+
21+
public ClearContentViewModel(StateManager stateManager) {
22+
this.stateManager = stateManager;
23+
}
24+
25+
public Set<Field> getAllFields() {
26+
return FieldFactory.getAllFieldsWithOutInternal();
27+
}
28+
29+
public Set<Field> getSetFieldsOnly() {
30+
return stateManager.getSelectedEntries().stream()
31+
.flatMap(entry -> entry.getFields().stream()
32+
.filter(f -> entry.getField(f).isPresent() && !entry.getField(f).get().isBlank()))
33+
.collect(Collectors.toCollection(LinkedHashSet::new));
34+
}
35+
36+
public void clearField(Field field) {
37+
NamedCompoundEdit edits = new NamedCompoundEdit("CLEAR_SELECTED_FIELD");
38+
List<BibEntry> selected = stateManager.getSelectedEntries();
39+
int affectedEntriesCount = 0;
40+
for (BibEntry entry : selected) {
41+
Optional<String> oldFieldValue = entry.getField(field);
42+
if (oldFieldValue.isPresent()) {
43+
entry.clearField(field)
44+
.ifPresent(change -> edits.addEdit(new UndoableFieldChange(change)));
45+
affectedEntriesCount++;
46+
}
47+
}
48+
49+
if (edits.hasEdits()) {
50+
edits.end();
51+
}
52+
stateManager.setLastAutomaticFieldEditorEdit(
53+
new LastAutomaticFieldEditorEdit(
54+
affectedEntriesCount,
55+
TAB_INDEX,
56+
edits)
57+
);
58+
}
59+
}

jabgui/src/main/java/org/jabref/gui/edit/automaticfiededitor/editfieldcontent/EditFieldContentTabView.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424

2525
public class EditFieldContentTabView extends AbstractAutomaticFieldEditorTabView {
2626
public Button appendValueButton;
27-
public Button clearFieldButton;
2827
public Button setValueButton;
28+
2929
@FXML
3030
private ComboBox<Field> fieldComboBox;
3131

@@ -64,15 +64,14 @@ public void initialize() {
6464
fieldComboBox.getSelectionModel().selectFirst();
6565

6666
fieldComboBox.valueProperty().bindBidirectional(viewModel.selectedFieldProperty());
67-
EasyBind.listen(fieldComboBox.getEditor().textProperty(), observable -> fieldComboBox.commitValue());
67+
EasyBind.listen(fieldComboBox.getEditor().textProperty(), _ -> fieldComboBox.commitValue());
6868

6969
fieldValueTextField.textProperty().bindBidirectional(viewModel.fieldValueProperty());
7070

7171
overwriteFieldContentCheckBox.selectedProperty().bindBidirectional(viewModel.overwriteFieldContentProperty());
7272

7373
appendValueButton.disableProperty().bind(viewModel.canAppendProperty().not());
7474
setValueButton.disableProperty().bind(viewModel.fieldValidationStatus().validProperty().not());
75-
clearFieldButton.disableProperty().bind(viewModel.fieldValidationStatus().validProperty().not());
7675
overwriteFieldContentCheckBox.disableProperty().bind(viewModel.fieldValidationStatus().validProperty().not());
7776

7877
Platform.runLater(() -> visualizer.initVisualization(viewModel.fieldValidationStatus(), fieldComboBox, true));
@@ -88,11 +87,6 @@ void appendToFieldValue() {
8887
viewModel.appendToFieldValue();
8988
}
9089

91-
@FXML
92-
void clearField() {
93-
viewModel.clearSelectedField();
94-
}
95-
9690
@FXML
9791
void setFieldValue() {
9892
viewModel.setFieldValue();

jabgui/src/main/java/org/jabref/gui/edit/automaticfiededitor/editfieldcontent/EditFieldContentViewModel.java

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,6 @@ public BooleanBinding canAppendProperty() {
6767
return canAppend;
6868
}
6969

70-
public void clearSelectedField() {
71-
NamedCompoundEdit clearFieldEdit = new NamedCompoundEdit("CLEAR_SELECTED_FIELD");
72-
int affectedEntriesCount = 0;
73-
for (BibEntry entry : selectedEntries) {
74-
Optional<String> oldFieldValue = entry.getField(selectedField.get());
75-
if (oldFieldValue.isPresent()) {
76-
entry.clearField(selectedField.get())
77-
.ifPresent(fieldChange -> clearFieldEdit.addEdit(new UndoableFieldChange(fieldChange)));
78-
affectedEntriesCount++;
79-
}
80-
}
81-
82-
if (clearFieldEdit.hasEdits()) {
83-
clearFieldEdit.end();
84-
}
85-
stateManager.setLastAutomaticFieldEditorEdit(new LastAutomaticFieldEditorEdit(
86-
affectedEntriesCount,
87-
TAB_INDEX,
88-
clearFieldEdit
89-
));
90-
}
91-
9270
public void setFieldValue() {
9371
NamedCompoundEdit setFieldEdit = new NamedCompoundEdit("CHANGE_SELECTED_FIELD");
9472
String toSetFieldValue = fieldValue.getValue();
@@ -150,10 +128,6 @@ public Field getSelectedField() {
150128
return selectedFieldProperty().get();
151129
}
152130

153-
public String getFieldValue() {
154-
return fieldValue.get();
155-
}
156-
157131
public StringProperty fieldValueProperty() {
158132
return fieldValue;
159133
}

jabgui/src/main/java/org/jabref/gui/edit/automaticfiededitor/renamefield/RenameFieldTabView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void initialize() {
5656
fieldComboBox.setConverter(FIELD_STRING_CONVERTER);
5757

5858
fieldComboBox.valueProperty().bindBidirectional(viewModel.selectedFieldProperty());
59-
EasyBind.listen(fieldComboBox.getEditor().textProperty(), observable -> fieldComboBox.commitValue());
59+
EasyBind.listen(fieldComboBox.getEditor().textProperty(), _ -> fieldComboBox.commitValue());
6060

6161
renameButton.disableProperty().bind(viewModel.canRenameProperty().not());
6262

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import javafx.geometry.Insets?>
4+
<?import javafx.scene.control.Button?>
5+
<?import javafx.scene.control.CheckBox?>
6+
<?import javafx.scene.control.ComboBox?>
7+
<?import javafx.scene.control.Label?>
8+
<?import javafx.scene.layout.ColumnConstraints?>
9+
<?import javafx.scene.layout.GridPane?>
10+
<?import javafx.scene.layout.HBox?>
11+
<?import javafx.scene.layout.RowConstraints?>
12+
<?import javafx.scene.layout.VBox?>
13+
<?import org.jabref.gui.icon.JabRefIconView?>
14+
<fx:root prefHeight="400.0" prefWidth="600.0" type="VBox" styleClass="edit-field-content-pane"
15+
xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
16+
fx:controller="org.jabref.gui.edit.automaticfiededitor.clearcontent.ClearContentTabView">
17+
<GridPane hgap="8.0" prefWidth="568.0" vgap="8.0">
18+
<columnConstraints>
19+
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
20+
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
21+
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
22+
</columnConstraints>
23+
<rowConstraints>
24+
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
25+
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
26+
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
27+
</rowConstraints>
28+
<HBox alignment="BOTTOM_LEFT"
29+
maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
30+
minHeight="-Infinity" minWidth="-Infinity"
31+
GridPane.hgrow="ALWAYS" GridPane.rowSpan="2" GridPane.vgrow="ALWAYS">
32+
<Label styleClass="sectionHeader"
33+
text="%Clear field content for selected entries">
34+
<HBox.margin>
35+
<Insets bottom="10.0"/>
36+
</HBox.margin>
37+
</Label>
38+
</HBox>
39+
<HBox spacing="8.0" GridPane.rowIndex="2" GridPane.columnSpan="3" GridPane.hgrow="ALWAYS">
40+
<ComboBox fx:id="fieldComboBox" prefHeight="36.0" editable="true" HBox.hgrow="ALWAYS" />
41+
<CheckBox fx:id="showOnlySetFieldsCheckBox" text="%Show only set fields"/>
42+
</HBox>
43+
<HBox spacing="8.0" GridPane.rowIndex="3" GridPane.columnSpan="3">
44+
<Button fx:id="clearButton" text="%Clear field content" onAction="#onClear">
45+
<graphic>
46+
<JabRefIconView glyph="DELETE_ENTRY"/>
47+
</graphic>
48+
</Button>
49+
</HBox>
50+
</GridPane>
51+
</fx:root>

jabgui/src/main/resources/org/jabref/gui/edit/automaticfiededitor/editfieldcontent/EditFieldContentTab.fxml

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
<?import javafx.scene.control.TextField?>
99
<?import javafx.scene.layout.HBox?>
1010
<?import javafx.scene.layout.VBox?>
11-
<?import org.jabref.gui.icon.JabRefIconView?>
12-
<fx:root type="VBox" styleClass="edit-field-content-pane" xmlns="http://javafx.com/javafx/17"
13-
xmlns:fx="http://javafx.com/fxml/1"
11+
<fx:root type="VBox" styleClass="edit-field-content-pane"
12+
xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
1413
fx:controller="org.jabref.gui.edit.automaticfiededitor.editfieldcontent.EditFieldContentTabView">
1514
<Label styleClass="sectionHeader" text="%Edit field content for selected entries"/>
1615
<HBox styleClass="actions">
@@ -23,11 +22,5 @@
2322
<Button fx:id="appendValueButton" mnemonicParsing="false" onAction="#appendToFieldValue"
2423
text="%Append"/>
2524
<Separator orientation="VERTICAL"/>
26-
<Button fx:id="clearFieldButton" mnemonicParsing="false" onAction="#clearField"
27-
text="%Clear field content">
28-
<graphic>
29-
<JabRefIconView glyph="DELETE_ENTRY"/>
30-
</graphic>
31-
</Button>
3225
</HBox>
3326
</fx:root>

jabgui/src/test/java/org/jabref/gui/edit/EditFieldContentTabViewModelTest.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,6 @@ void setup() {
3939
editFieldContentViewModel = new EditFieldContentViewModel(bibDatabase, List.of(entryA, entryB), stateManager);
4040
}
4141

42-
@Test
43-
void clearSelectedFieldShouldClearFieldContentEvenWhenOverwriteFieldContentIsNotEnabled() {
44-
editFieldContentViewModel.selectedFieldProperty().set(StandardField.YEAR);
45-
editFieldContentViewModel.overwriteFieldContentProperty().set(false);
46-
editFieldContentViewModel.clearSelectedField();
47-
48-
assertEquals(Optional.empty(), entryA.getField(StandardField.YEAR));
49-
}
50-
51-
@Test
52-
void clearSelectedFieldShouldDoNothingWhenFieldDoesntExistOrIsEmpty() {
53-
editFieldContentViewModel.selectedFieldProperty().set(StandardField.FILE);
54-
editFieldContentViewModel.clearSelectedField();
55-
56-
assertEquals(Optional.empty(), entryA.getField(StandardField.FILE));
57-
}
58-
5942
@Test
6043
void setFieldValueShouldNotDoAnythingIfOverwriteFieldContentIsNotEnabled() {
6144
editFieldContentViewModel.overwriteFieldContentProperty().set(false);

0 commit comments

Comments
 (0)