> searchFlagsProperty() {
return searchFlagsProperty;
}
+ public void setSearchFlag(SearchFlags searchFlag, boolean value) {
+ if (value) {
+ searchFlagsProperty.getValue().add(searchFlag);
+ } else {
+ searchFlagsProperty.getValue().remove(searchFlag);
+ }
+ }
+
public BooleanProperty autoGroupKeywordsOptionProperty() {
return autoGroupKeywordsOptionProperty;
}
diff --git a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java
index cc64665235f..812674cdd65 100644
--- a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java
+++ b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java
@@ -101,13 +101,10 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state
if (groupNode.getGroup() instanceof TexGroup) {
databaseContext.getMetaData().groupsBinding().addListener(new WeakInvalidationListener(onInvalidatedGroup));
} else if (groupNode.getGroup() instanceof SearchGroup searchGroup) {
- stateManager.getLuceneManager(databaseContext).ifPresent(luceneManager -> {
- BackgroundTask.wrap(() -> {
- searchGroup.setMatchedEntries(luceneManager.search(searchGroup.getQuery()).getMatchedEntries());
- }).onSuccess(success -> {
- refreshGroup();
- databaseContext.getMetaData().groupsBinding().invalidate();
- }).executeWith(taskExecutor);
+ stateManager.getIndexManager(databaseContext).ifPresent(indexManager -> {
+ searchGroup.setMatchedEntries(indexManager.search(searchGroup.getSearchQuery()).getMatchedEntries());
+ refreshGroup();
+ databaseContext.getMetaData().groupsBinding().invalidate();
});
}
@@ -127,7 +124,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state
// 'all' returns 'true' for empty streams, so this has to be checked explicitly
allSelectedEntriesMatched = selectedEntriesMatchStatus.isEmptyBinding().not().and(selectedEntriesMatchStatus.allMatch(matched -> matched));
- this.databaseContext.getDatabase().registerListener(new LuceneIndexListener());
+ this.databaseContext.getDatabase().registerListener(new SearchIndexListener());
}
public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager stateManager, TaskExecutor taskExecutor, AbstractGroup group, CustomLocalDragboard localDragboard, GuiPreferences preferences) {
@@ -251,7 +248,7 @@ public GroupTreeNode getGroupNode() {
/**
* Gets invoked if an entry in the current database changes.
*
- * @implNote Search groups are updated in {@link LuceneIndexListener}.
+ * @implNote Search groups are updated in {@link SearchIndexListener}.
*/
private void onDatabaseChanged(ListChangeListener.Change extends BibEntry> change) {
if (groupNode.getGroup() instanceof SearchGroup) {
@@ -536,17 +533,14 @@ public boolean isEditable() {
}
}
- class LuceneIndexListener {
+ class SearchIndexListener {
@Subscribe
public void listen(IndexStartedEvent event) {
if (groupNode.getGroup() instanceof SearchGroup searchGroup) {
- stateManager.getLuceneManager(databaseContext).ifPresent(luceneManager -> {
- BackgroundTask.wrap(() -> {
- searchGroup.setMatchedEntries(luceneManager.search(searchGroup.getQuery()).getMatchedEntries());
- }).onSuccess(success -> {
- refreshGroup();
- databaseContext.getMetaData().groupsBinding().invalidate();
- }).executeWith(taskExecutor);
+ stateManager.getIndexManager(databaseContext).ifPresent(indexManager -> {
+ searchGroup.setMatchedEntries(indexManager.search(searchGroup.getSearchQuery()).getMatchedEntries());
+ refreshGroup();
+ databaseContext.getMetaData().groupsBinding().invalidate();
});
}
}
@@ -554,10 +548,10 @@ public void listen(IndexStartedEvent event) {
@Subscribe
public void listen(IndexAddedOrUpdatedEvent event) {
if (groupNode.getGroup() instanceof SearchGroup searchGroup) {
- stateManager.getLuceneManager(databaseContext).ifPresent(luceneManager -> {
+ stateManager.getIndexManager(databaseContext).ifPresent(indexManager -> {
BackgroundTask.wrap(() -> {
for (BibEntry entry : event.entries()) {
- searchGroup.updateMatches(entry, luceneManager.isEntryMatched(entry, searchGroup.getQuery()));
+ searchGroup.updateMatches(entry, indexManager.isEntryMatched(entry, searchGroup.getSearchQuery()));
}
}).onFinished(() -> {
for (BibEntry entry : event.entries()) {
diff --git a/src/main/java/org/jabref/gui/icon/IconTheme.java b/src/main/java/org/jabref/gui/icon/IconTheme.java
index 0cd33366896..aa6cff98462 100644
--- a/src/main/java/org/jabref/gui/icon/IconTheme.java
+++ b/src/main/java/org/jabref/gui/icon/IconTheme.java
@@ -169,6 +169,7 @@ public enum JabRefIcons implements JabRefIcon {
ADD_NOBOX(MaterialDesignP.PLUS),
ADD_ARTICLE(MaterialDesignP.PLUS),
ADD_ENTRY(MaterialDesignP.PLAYLIST_PLUS),
+ CASE_SENSITIVE(MaterialDesignA.ALPHABETICAL),
EDIT_ENTRY(MaterialDesignT.TOOLTIP_EDIT),
EDIT_STRINGS(MaterialDesignT.TOOLTIP_TEXT),
FOLDER(MaterialDesignF.FOLDER_OUTLINE),
diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java
index 68b086f4ba8..e63af24ab95 100644
--- a/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java
+++ b/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java
@@ -21,7 +21,7 @@
public class CheckForNewEntryTypesAction implements GUIPostOpenAction {
@Override
- public boolean isActionNecessary(ParserResult parserResult, CliPreferences preferences) {
+ public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) {
return !getListOfUnknownAndUnequalCustomizations(parserResult, preferences.getLibraryPreferences()).isEmpty();
}
diff --git a/src/main/java/org/jabref/gui/importer/actions/GUIPostOpenAction.java b/src/main/java/org/jabref/gui/importer/actions/GUIPostOpenAction.java
index 2551845ea61..f4eec73e339 100644
--- a/src/main/java/org/jabref/gui/importer/actions/GUIPostOpenAction.java
+++ b/src/main/java/org/jabref/gui/importer/actions/GUIPostOpenAction.java
@@ -9,7 +9,7 @@
* opening a BIB file into JabRef. This can for instance be file upgrade actions
* that should be offered due to new features in JabRef, and may depend on e.g.
* which JabRef version the file was last written by.
- *
+ *
* This interface is introduced in an attempt to add such functionality in a
* flexible manner.
*/
@@ -22,12 +22,12 @@ public interface GUIPostOpenAction {
* @param pr The result of the BIB parse operation.
* @return true if the action should be called, false otherwise.
*/
- boolean isActionNecessary(ParserResult pr, CliPreferences preferences);
+ boolean isActionNecessary(ParserResult pr, DialogService dialogService, CliPreferences preferences);
/**
* This method is called after the new database has been added to the GUI, if
* the isActionNecessary() method returned true.
- *
+ *
* Note: if several such methods need to be called sequentially, it is
* important that all implementations of this method do not return
* until the operation is finished.
diff --git a/src/main/java/org/jabref/gui/importer/actions/MergeReviewIntoCommentAction.java b/src/main/java/org/jabref/gui/importer/actions/MergeReviewIntoCommentAction.java
index 9ccec061d23..3d69e620558 100644
--- a/src/main/java/org/jabref/gui/importer/actions/MergeReviewIntoCommentAction.java
+++ b/src/main/java/org/jabref/gui/importer/actions/MergeReviewIntoCommentAction.java
@@ -11,7 +11,7 @@
public class MergeReviewIntoCommentAction implements GUIPostOpenAction {
@Override
- public boolean isActionNecessary(ParserResult parserResult, CliPreferences preferences) {
+ public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) {
return MergeReviewIntoCommentMigration.needsMigration(parserResult);
}
diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
index 605e389e76a..748c78db227 100644
--- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
+++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
@@ -34,12 +34,14 @@
import org.jabref.logic.shared.exception.InvalidDBMSConnectionPropertiesException;
import org.jabref.logic.shared.exception.NotASharedDatabaseException;
import org.jabref.logic.util.BackgroundTask;
+import org.jabref.logic.util.Directories;
import org.jabref.logic.util.StandardFileType;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.logic.util.io.FileHistory;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.util.FileUpdateMonitor;
+import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,7 +58,7 @@ public class OpenDatabaseAction extends SimpleCommand {
new MergeReviewIntoCommentAction(),
// Check for new custom entry types loaded from the BIB file:
new CheckForNewEntryTypesAction(),
- // Migrate search groups from Search.g4 to Lucene syntax
+ // Migrate search groups fielded terms to use the new operators (RegEx, case sensitive)
new SearchGroupsMigrationAction());
private final LibraryTabContainer tabContainer;
@@ -94,7 +96,7 @@ public OpenDatabaseAction(LibraryTabContainer tabContainer,
public static void performPostOpenActions(ParserResult result, DialogService dialogService, CliPreferences preferences) {
for (GUIPostOpenAction action : OpenDatabaseAction.POST_OPEN_ACTIONS) {
- if (action.isActionNecessary(result, preferences)) {
+ if (action.isActionNecessary(result, dialogService, preferences)) {
action.performAction(result, dialogService, preferences);
}
}
@@ -102,20 +104,47 @@ public static void performPostOpenActions(ParserResult result, DialogService dia
@Override
public void execute() {
- FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder()
+ List filesToOpen = getFilesToOpen();
+ openFiles(new ArrayList<>(filesToOpen));
+ }
+
+ @VisibleForTesting
+ List getFilesToOpen() {
+ List filesToOpen;
+
+ try {
+ FileDialogConfiguration initialDirectoryConfig = getFileDialogConfiguration(getInitialDirectory());
+ filesToOpen = dialogService.showFileOpenDialogAndGetMultipleFiles(initialDirectoryConfig);
+ } catch (IllegalArgumentException e) {
+ // See https://github.com/JabRef/jabref/issues/10548 for details
+ // Rebuild a new config with the home directory
+ FileDialogConfiguration homeDirectoryConfig = getFileDialogConfiguration(Directories.getUserDirectory());
+ filesToOpen = dialogService.showFileOpenDialogAndGetMultipleFiles(homeDirectoryConfig);
+ }
+
+ return filesToOpen;
+ }
+
+ /**
+ * Builds a new FileDialogConfiguration using the given path as the initial directory for use in
+ * dialogService.showFileOpenDialogAndGetMultipleFiles().
+ *
+ * @param initialDirectory Path to use as the initial directory
+ * @return new FileDialogConfig with given initial directory
+ */
+ public FileDialogConfiguration getFileDialogConfiguration(Path initialDirectory) {
+ return new FileDialogConfiguration.Builder()
.addExtensionFilter(StandardFileType.BIBTEX_DB)
.withDefaultExtension(StandardFileType.BIBTEX_DB)
- .withInitialDirectory(getInitialDirectory())
+ .withInitialDirectory(initialDirectory)
.build();
-
- List filesToOpen = dialogService.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration);
- openFiles(new ArrayList<>(filesToOpen));
}
/**
* @return Path of current panel database directory or the working directory
*/
- private Path getInitialDirectory() {
+ @VisibleForTesting
+ Path getInitialDirectory() {
if (tabContainer.getLibraryTabs().isEmpty()) {
return preferences.getFilePreferences().getWorkingDirectory();
} else {
diff --git a/src/main/java/org/jabref/gui/importer/actions/SearchGroupsMigrationAction.java b/src/main/java/org/jabref/gui/importer/actions/SearchGroupsMigrationAction.java
index 9e2ca086ab6..c7f85f5bd54 100644
--- a/src/main/java/org/jabref/gui/importer/actions/SearchGroupsMigrationAction.java
+++ b/src/main/java/org/jabref/gui/importer/actions/SearchGroupsMigrationAction.java
@@ -7,11 +7,10 @@
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.preferences.CliPreferences;
+import org.jabref.logic.search.query.SearchQueryConversion;
import org.jabref.logic.util.Version;
-import org.jabref.migrations.SearchToLuceneMigration;
import org.jabref.model.groups.GroupTreeNode;
import org.jabref.model.groups.SearchGroup;
-import org.jabref.model.search.SearchFlags;
import org.antlr.v4.runtime.misc.ParseCancellationException;
@@ -24,11 +23,17 @@ public class SearchGroupsMigrationAction implements GUIPostOpenAction {
// We cannot have this constant in `Version.java` because of recursion errors
// Thus, we keep it here, because it is (currently) used only in the context of groups migration.
public static final Version VERSION_6_0_ALPHA = Version.parse("6.0-alpha");
+ public static final Version VERSION_6_0_ALPHA_1 = Version.parse("6.0-alpha_1");
@Override
- public boolean isActionNecessary(ParserResult parserResult, CliPreferences preferences) {
- if (parserResult.getMetaData().getGroupSearchSyntaxVersion().isPresent()) {
- // Currently the presence of any version is enough to know that no migration is necessary
+ public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) {
+ Optional currentVersion = parserResult.getMetaData().getGroupSearchSyntaxVersion();
+ if (currentVersion.isPresent()) {
+ if (currentVersion.get().equals(VERSION_6_0_ALPHA)) {
+ // TODO: This text will only be shown after releasing 6.0-alpha and then removed
+ dialogService.showErrorDialogAndWait("Search groups migration of " + parserResult.getPath().map(Path::toString).orElse(""),
+ "The search groups syntax has been reverted to the old one. Please use the backup you made before using 6.0-alpha.");
+ }
return false;
}
@@ -57,21 +62,22 @@ public void performAction(ParserResult parserResult, DialogService dialogService
}
parserResult.getMetaData().getGroups().ifPresent(groupTreeNode -> migrateGroups(groupTreeNode, dialogService));
- parserResult.getMetaData().setGroupSearchSyntaxVersion(VERSION_6_0_ALPHA);
+ parserResult.getMetaData().setGroupSearchSyntaxVersion(VERSION_6_0_ALPHA_1);
parserResult.setChangedOnMigration(true);
}
private void migrateGroups(GroupTreeNode node, DialogService dialogService) {
if (node.getGroup() instanceof SearchGroup searchGroup) {
try {
- String luceneSearchExpression = SearchToLuceneMigration.migrateToLuceneSyntax(searchGroup.getSearchExpression(), searchGroup.getSearchFlags().contains(SearchFlags.REGULAR_EXPRESSION));
- searchGroup.setSearchExpression(luceneSearchExpression);
+ String newSearchExpression = SearchQueryConversion.flagsToSearchExpression(searchGroup.getSearchQuery());
+ searchGroup.setSearchExpression(newSearchExpression);
} catch (ParseCancellationException e) {
- Optional luceneSearchExpression = dialogService.showInputDialogWithDefaultAndWait(
+ Optional newSearchExpression = dialogService.showInputDialogWithDefaultAndWait(
Localization.lang("Search group migration failed"),
- Localization.lang("The search group '%0' could not be migrated. Please enter the new search expression.", searchGroup.getName()),
+ Localization.lang("The search group '%0' could not be migrated. Please enter the new search expression.",
+ searchGroup.getName()),
searchGroup.getSearchExpression());
- luceneSearchExpression.ifPresent(searchGroup::setSearchExpression);
+ newSearchExpression.ifPresent(searchGroup::setSearchExpression);
}
}
for (GroupTreeNode child : node.getChildren()) {
diff --git a/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java b/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java
index 953020e6c61..0b73e3bccab 100644
--- a/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java
+++ b/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java
@@ -85,7 +85,7 @@ private String lookupIdentifiers(List bibEntries) {
LOGGER.error("Could not fetch {}", fetcher.getIdentifierName(), e);
}
if (identifier.isPresent() && !bibEntry.hasField(identifier.get().getDefaultField())) {
- Optional fieldChange = bibEntry.setField(identifier.get().getDefaultField(), identifier.get().getNormalized());
+ Optional fieldChange = bibEntry.setField(identifier.get().getDefaultField(), identifier.get().asString());
if (fieldChange.isPresent()) {
namedCompound.addEdit(new UndoableFieldChange(fieldChange.get()));
foundCount++;
diff --git a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java
index aa8fdc38ec3..613a102d9df 100644
--- a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java
+++ b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java
@@ -14,11 +14,9 @@
import javafx.beans.binding.Binding;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
-import javafx.beans.property.FloatProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleBooleanProperty;
-import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
@@ -50,7 +48,6 @@ public class BibEntryTableViewModel {
private final EasyBinding