diff --git a/CHANGELOG.md b/CHANGELOG.md index 861471f2d69..93f5d1ec768 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added +- We added automatic date-based groups that create year/month/day subgroups from an entry’s date fields. [#10822](https://github.com/JabRef/jabref/issues/10822) + ### Changed ### Fixed diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogView.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogView.java index 536d4b29265..6f0501d6aaf 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogView.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogView.java @@ -43,7 +43,10 @@ import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.groups.AbstractGroup; +import org.jabref.model.groups.DateGranularity; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.search.SearchFlags; @@ -101,6 +104,11 @@ public class GroupDialogView extends BaseDialog { @FXML private TextField texGroupFilePath; + @FXML private RadioButton dateRadioButton; + @FXML private ComboBox dateGroupFieldCombo; + @FXML private ComboBox dateGroupOptionCombo; + @FXML private CheckBox dateGroupIncludeEmpty; + private final EnumMap hierarchyText = new EnumMap<>(GroupHierarchyType.class); private final EnumMap hierarchyToolTip = new EnumMap<>(GroupHierarchyType.class); @@ -222,6 +230,16 @@ public void initialize() { texGroupFilePath.textProperty().bindBidirectional(viewModel.texGroupFilePathProperty()); + // Date Group bindings + dateRadioButton.selectedProperty().bindBidirectional(viewModel.dateRadioButtonSelectedProperty()); + dateGroupFieldCombo.valueProperty().bindBidirectional(viewModel.dateGroupFieldProperty()); + dateGroupOptionCombo.valueProperty().bindBidirectional(viewModel.dateGroupOptionProperty()); + dateGroupIncludeEmpty.selectedProperty().bindBidirectional(viewModel.dateGroupIncludeEmptyProperty()); + + // Initialize Date Group ComboBoxes + dateGroupFieldCombo.setItems(FXCollections.observableArrayList(FieldFactory.getDateFields())); + dateGroupOptionCombo.setItems(FXCollections.observableArrayList(DateGranularity.values())); + validationVisualizer.setDecoration(new IconValidationDecorator()); Platform.runLater(() -> { validationVisualizer.initVisualization(viewModel.nameValidationStatus(), nameField); diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java index 4b9f66dfe3b..30eb4c07b39 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java @@ -39,11 +39,15 @@ import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.Keyword; +import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; +import org.jabref.model.entry.field.StandardField; import org.jabref.model.groups.AbstractGroup; +import org.jabref.model.groups.AutomaticDateGroup; import org.jabref.model.groups.AutomaticGroup; import org.jabref.model.groups.AutomaticKeywordGroup; import org.jabref.model.groups.AutomaticPersonsGroup; +import org.jabref.model.groups.DateGranularity; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.GroupTreeNode; @@ -98,6 +102,12 @@ public class GroupDialogViewModel { private final StringProperty texGroupFilePathProperty = new SimpleStringProperty(""); + // Date Group Properties + private final BooleanProperty dateRadioButtonSelectedProperty = new SimpleBooleanProperty(); + private final ObjectProperty dateGroupFieldProperty = new SimpleObjectProperty<>(); + private final ObjectProperty dateGroupOptionProperty = new SimpleObjectProperty<>(); + private final BooleanProperty dateGroupIncludeEmptyProperty = new SimpleBooleanProperty(); + private Validator nameValidator; private Validator nameContainsDelimiterValidator; private Validator sameNameValidator; @@ -376,6 +386,13 @@ public AbstractGroup resultConverter(ButtonType button) { currentDatabase.getMetaData(), preferences.getFilePreferences().getUserAndHost() ); + } else if (Boolean.TRUE.equals(dateRadioButtonSelectedProperty.getValue())) { + resultingGroup = new AutomaticDateGroup( + groupName, + groupHierarchySelectedProperty.getValue(), + dateGroupFieldProperty.getValue(), + dateGroupOptionProperty.getValue() + ); } if (resultingGroup != null) { @@ -413,6 +430,11 @@ public void setValues() { typeExplicitProperty.setValue(true); groupHierarchySelectedProperty.setValue(preferences.getGroupsPreferences().getDefaultHierarchicalContext()); autoGroupKeywordsOptionProperty.setValue(Boolean.TRUE); + + // Initialize Date Group defaults + dateGroupFieldProperty.setValue(StandardField.DATE); + dateGroupOptionProperty.setValue(DateGranularity.YEAR); + dateGroupIncludeEmptyProperty.setValue(false); } else { nameProperty.setValue(editedGroup.getName()); colorUseProperty.setValue(editedGroup.getColor().isPresent()); @@ -458,6 +480,12 @@ public void setValues() { AutomaticPersonsGroup group = (AutomaticPersonsGroup) editedGroup; autoGroupPersonsOptionProperty.setValue(Boolean.TRUE); autoGroupPersonsFieldProperty.setValue(group.getField().getName()); + } else if (editedGroup.getClass() == AutomaticDateGroup.class) { + AutomaticDateGroup group = (AutomaticDateGroup) editedGroup; + dateRadioButtonSelectedProperty.setValue(Boolean.TRUE); + dateGroupFieldProperty.setValue(group.getField()); + dateGroupOptionProperty.setValue(group.getGranularity()); + dateGroupIncludeEmptyProperty.setValue(false); } } else if (editedGroup.getClass() == TexGroup.class) { typeTexProperty.setValue(true); @@ -651,6 +679,23 @@ public StringProperty texGroupFilePathProperty() { return texGroupFilePathProperty; } + // Date Group Property Getters + public BooleanProperty dateRadioButtonSelectedProperty() { + return dateRadioButtonSelectedProperty; + } + + public ObjectProperty dateGroupFieldProperty() { + return dateGroupFieldProperty; + } + + public ObjectProperty dateGroupOptionProperty() { + return dateGroupOptionProperty; + } + + public BooleanProperty dateGroupIncludeEmptyProperty() { + return dateGroupIncludeEmptyProperty; + } + private boolean groupOrSubgroupIsSearchGroup(GroupTreeNode groupTreeNode) { if (groupTreeNode.getGroup() instanceof SearchGroup) { return true; diff --git a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index 7193dc00465..3210e763d3c 100644 --- a/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -36,6 +36,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.groups.AllEntriesGroup; +import org.jabref.model.groups.AutomaticDateGroup; import org.jabref.model.groups.AutomaticGroup; import org.jabref.model.groups.AutomaticKeywordGroup; import org.jabref.model.groups.AutomaticPersonsGroup; @@ -461,6 +462,8 @@ public boolean canAddEntriesIn() { return false; } else if (group instanceof TexGroup) { return false; + } else if (group instanceof AutomaticDateGroup) { + return false; } else { throw new UnsupportedOperationException("canAddEntriesIn method not yet implemented in group: " + group.getClass().getName()); } @@ -476,6 +479,7 @@ public boolean canBeDragged() { SearchGroup _, AutomaticKeywordGroup _, AutomaticPersonsGroup _, + AutomaticDateGroup _, TexGroup _ -> true; case KeywordGroup _ -> @@ -503,6 +507,7 @@ public boolean canAddGroupsIn() { true; case AutomaticKeywordGroup _, AutomaticPersonsGroup _, + AutomaticDateGroup _, SmartGroup _ -> false; case KeywordGroup _ -> @@ -528,6 +533,7 @@ public boolean canRemove() { SearchGroup _, AutomaticKeywordGroup _, AutomaticPersonsGroup _, + AutomaticDateGroup _, TexGroup _ -> true; case KeywordGroup _ -> @@ -553,6 +559,7 @@ public boolean isEditable() { SearchGroup _, AutomaticKeywordGroup _, AutomaticPersonsGroup _, + AutomaticDateGroup _, TexGroup _ -> true; case KeywordGroup _ -> diff --git a/jabgui/src/main/resources/org/jabref/gui/groups/GroupDialog.fxml b/jabgui/src/main/resources/org/jabref/gui/groups/GroupDialog.fxml index 324ed9ca48a..ea905b0cbc1 100644 --- a/jabgui/src/main/resources/org/jabref/gui/groups/GroupDialog.fxml +++ b/jabgui/src/main/resources/org/jabref/gui/groups/GroupDialog.fxml @@ -99,6 +99,12 @@ + + + + + @@ -183,6 +189,18 @@