Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select Library to import into #9402

Merged
merged 8 commits into from
Dec 19, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We added support for the Ukrainian and Arabic languages. [#9236](https://github.com/JabRef/jabref/pull/9236), [#9243](https://github.com/JabRef/jabref/pull/9243)
- The default file directory of a library is used as default directory for [unlinked file lookup](https://docs.jabref.org/collect/findunlinkedfiles#link-the-pdfs-to-your-bib-library). [koppor#546](https://github.com/koppor/jabref/issues/546)
- We added support for the field `fjournal` (in `@article`) for abbreviation and unabbreviation functionalities. [#321](https://github.com/JabRef/jabref/pull/321)
- We added a dropdown menu to let users change the library they want to import into during import.[#6177](https://github.com/JabRef/jabref/issues/6177)

### Changed

Expand Down
12 changes: 1 addition & 11 deletions src/main/java/org/jabref/gui/LibraryTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ public void updateTabTitle(boolean isChanged) {
}

// Unique path fragment
Optional<String> uniquePathPart = FileUtil.getUniquePathFragment(collectAllDatabasePaths(), databasePath);
Optional<String> uniquePathPart = FileUtil.getUniquePathDirectory(stateManager.collectAllDatabasePaths(), databasePath);
uniquePathPart.ifPresent(part -> tabTitle.append(" \u2013 ").append(part));
} else {
if (databaseLocation == DatabaseLocation.LOCAL) {
Expand Down Expand Up @@ -379,16 +379,6 @@ public void updateTabTitle(boolean isChanged) {
}
}

private List<String> collectAllDatabasePaths() {
List<String> list = new ArrayList<>();
stateManager.getOpenDatabases().stream()
.map(BibDatabaseContext::getDatabasePath)
.forEachOrdered(pathOptional -> pathOptional.ifPresentOrElse(
path -> list.add(path.toAbsolutePath().toString()),
() -> list.add("")));
return list;
}

@Subscribe
public void listen(BibDatabaseContextChangedEvent event) {
this.changedProperty.setValue(true);
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/jabref/gui/StateManager.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jabref.gui;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -201,4 +202,14 @@ public LastAutomaticFieldEditorEdit getLastAutomaticFieldEditorEdit() {
public void setLastAutomaticFieldEditorEdit(LastAutomaticFieldEditorEdit automaticFieldEditorEdit) {
lastAutomaticFieldEditorEditProperty().set(automaticFieldEditorEdit);
}

public List<String> collectAllDatabasePaths() {
List<String> list = new ArrayList<>();
getOpenDatabases().stream()
.map(BibDatabaseContext::getDatabasePath)
.forEachOrdered(pathOptional -> pathOptional.ifPresentOrElse(
path -> list.add(path.toAbsolutePath().toString()),
() -> list.add("")));
return list;
}
}
17 changes: 14 additions & 3 deletions src/main/java/org/jabref/gui/importer/ImportEntriesDialog.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonType?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
Expand All @@ -11,16 +12,25 @@
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import org.controlsfx.control.CheckListView?>
<?import javafx.scene.control.ComboBox?>
<DialogPane prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.2-internal"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.importer.ImportEntriesDialog">
<content>
<VBox spacing="10.0">
<Label text="%Select the entries to be imported:"/>
<CheckListView fx:id="entriesListView" VBox.vgrow="ALWAYS"/>
<HBox spacing="4">
<Button onAction="#selectAllNewEntries" styleClass="text-button" text="%Select all new entries"/>
<Button onAction="#selectAllEntries" styleClass="text-button" text="%Select all entries"/>
<Button onAction="#unselectAll" styleClass="text-button" text="%Unselect all"/>
<VBox spacing="10">
<HBox spacing="4">
<Button onAction="#selectAllNewEntries" text="%Select all new entries"/>
<Button onAction="#selectAllEntries" text="%Select all entries"/>
<Button onAction="#unselectAll" text="%Unselect all"/>
</HBox>
<HBox spacing="4" alignment="CENTER_LEFT">
<Label text="%Library to import into"/>
<ComboBox fx:id="libraryListView" layoutX="16.0" layoutY="52.0"/>
</HBox>
</VBox>
<HBox HBox.hgrow="ALWAYS"/>
<GridPane hgap="4.0" vgap="4.0">
<columnConstraints>
Expand All @@ -30,6 +40,7 @@
<rowConstraints>
<RowConstraints minHeight="10.0"/>
<RowConstraints minHeight="10.0"/>
<RowConstraints minHeight="10.0"/>
</rowConstraints>
<Label styleClass="info-section" text="%Total items found:"/>
<Label fx:id="totalItems" GridPane.columnIndex="1"/>
Expand Down
30 changes: 28 additions & 2 deletions src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jabref.gui.importer;

import java.util.EnumSet;
import java.util.Optional;

import javax.swing.undo.UndoManager;

Expand All @@ -12,6 +13,7 @@
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
Expand All @@ -21,7 +23,6 @@
import javafx.scene.text.Text;

import org.jabref.gui.DialogService;
import org.jabref.gui.Globals;
import org.jabref.gui.StateManager;
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.util.BackgroundTask;
Expand All @@ -32,6 +33,7 @@
import org.jabref.gui.util.ViewModelListCellFactory;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.io.FileUtil;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.BibEntryTypesManager;
Expand All @@ -49,6 +51,7 @@
public class ImportEntriesDialog extends BaseDialog<Boolean> {

public CheckListView<BibEntry> entriesListView;
public ComboBox<BibDatabaseContext> libraryListView;
public ButtonType importButton;
public Label totalItems;
public Label selectedItems;
Expand Down Expand Up @@ -102,6 +105,29 @@ private void initialize() {
entriesListView.setPlaceholder(placeholder);
entriesListView.setItems(viewModel.getEntries());

libraryListView.setEditable(false);
libraryListView.getItems().addAll(stateManager.getOpenDatabases());
new ViewModelListCellFactory<BibDatabaseContext>()
.withText(database -> {
Optional<String> dbOpt = Optional.empty();
if (database.getDatabasePath().isPresent()) {
dbOpt = FileUtil.getUniquePathFragment(stateManager.collectAllDatabasePaths(), database.getDatabasePath().get());
}

if (dbOpt.isEmpty()) {
return "Untitled";
}

return dbOpt.get();
})
.install(libraryListView);
viewModel.selectedDbProperty().bind(libraryListView.getSelectionModel().selectedItemProperty());

// FixMe: getActiveDatabase result object is different from the ones in getOpenDatabases.
Siedlerchr marked this conversation as resolved.
Show resolved Hide resolved
// Solution: Debug JabRef to find out, why there is a new object for the stateManager constructed (Must be done sooner or later)
// Easy Workaround: Check the open databases for their path and select the matching one from getOpenDatabases
stateManager.getActiveDatabase().ifPresent(database -> libraryListView.getSelectionModel().select(database));

PseudoClass entrySelected = PseudoClass.getPseudoClass("entry-selected");
new ViewModelListCellFactory<BibEntry>()
.withGraphic(entry -> {
Expand Down Expand Up @@ -129,7 +155,7 @@ private void initialize() {
duplicateButton.setOnAction(event -> viewModel.resolveDuplicate(entry));
container.getChildren().add(1, duplicateButton);
}
}).executeWith(Globals.TASK_EXECUTOR);
}).executeWith(taskExecutor);

/*
inserted the if-statement here, since a Platform.runLater() call did not work.
Expand Down
19 changes: 15 additions & 4 deletions src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import javax.swing.undo.UndoManager;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
Expand All @@ -13,7 +15,6 @@
import org.jabref.gui.AbstractViewModel;
import org.jabref.gui.DialogService;
import org.jabref.gui.Globals;
import org.jabref.gui.JabRefGUI;
import org.jabref.gui.StateManager;
import org.jabref.gui.duplicationFinder.DuplicateResolverDialog;
import org.jabref.gui.externalfiles.ImportHandler;
Expand Down Expand Up @@ -49,6 +50,7 @@ public class ImportEntriesViewModel extends AbstractViewModel {
private final ObservableList<BibEntry> entries;
private final PreferencesService preferences;
private final BibEntryTypesManager entryTypesManager;
private final ObjectProperty<BibDatabaseContext> selectedDb;

/**
* @param databaseContext the database to import into
Expand All @@ -74,6 +76,7 @@ public ImportEntriesViewModel(BackgroundTask<ParserResult> task,
this.entries = FXCollections.observableArrayList();
this.message = new SimpleStringProperty();
this.message.bind(task.messageProperty());
this.selectedDb = new SimpleObjectProperty<>();

task.onSuccess(parserResult -> {
// store the complete parser result (to import groups, ... later on)
Expand All @@ -97,14 +100,22 @@ public StringProperty messageProperty() {
return message;
}

public ObjectProperty<BibDatabaseContext> selectedDbProperty() {
return selectedDb;
}

public BibDatabaseContext getSelectedDb() {
return selectedDb.get();
}

public ObservableList<BibEntry> getEntries() {
return entries;
}

public boolean hasDuplicate(BibEntry entry) {
return findInternalDuplicate(entry).isPresent() ||
new DuplicateCheck(entryTypesManager)
.containsDuplicate(databaseContext.getDatabase(), entry, databaseContext.getMode()).isPresent();
.containsDuplicate(selectedDb.getValue().getDatabase(), entry, selectedDb.getValue().getMode()).isPresent();
}

/**
Expand Down Expand Up @@ -161,12 +172,12 @@ public void importEntries(List<BibEntry> entriesToImport, boolean shouldDownload
parserResult.getPath().map(path -> path.getFileName().toString()).orElse("unknown"),
parserResult.getDatabase().getEntries());

JabRefGUI.getMainFrame().getCurrentLibraryTab().markBaseChanged();
// JabRefGUI.getMainFrame().getCurrentLibraryTab().markBaseChanged();
}

private void buildImportHandlerThenImportEntries(List<BibEntry> entriesToImport) {
ImportHandler importHandler = new ImportHandler(
databaseContext,
selectedDb.getValue(),
preferences,
fileUpdateMonitor,
undoManager,
Expand Down
26 changes: 22 additions & 4 deletions src/main/java/org/jabref/logic/util/io/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,35 @@ public static Path addExtension(Path path, String extension) {
return path.resolveSibling(path.getFileName() + extension);
}

public static Optional<String> getUniquePathFragment(List<String> paths, Path databasePath) {
String fileName = databasePath.getFileName().toString();
/**
* Looks for the unique directory, if any, different to the provided paths
*
* @param paths List of paths as Strings
* @param comparePath The to be tested path
*/
public static Optional<String> getUniquePathDirectory(List<String> paths, Path comparePath) {
String fileName = comparePath.getFileName().toString();

List<String> uniquePathParts = uniquePathSubstrings(paths);
return uniquePathParts.stream()
.filter(part -> databasePath.toString().contains(part)
.filter(part -> comparePath.toString().contains(part)
&& !part.equals(fileName) && part.contains(File.separator))
.findFirst()
.map(part -> part.substring(0, part.lastIndexOf(File.separator)));
}

/**
* Looks for the shortest unique path of the in a list of paths
*
* @param paths List of paths as Strings
* @param comparePath The to be shortened path
*/
public static Optional<String> getUniquePathFragment(List<String> paths, Path comparePath) {
return uniquePathSubstrings(paths).stream()
.filter(part -> comparePath.toString().contains(part))
.findFirst();
}

/**
* Creates the minimal unique path substring for each file among multiple file paths.
*
Expand All @@ -148,7 +166,7 @@ public static List<String> uniquePathSubstrings(List<String> paths) {

List<String> pathSubstrings = new ArrayList<>(Collections.nCopies(paths.size(), ""));

// compute shortest folder substrings
// compute the shortest folder substrings
while (!stackList.stream().allMatch(Vector::isEmpty)) {
for (int i = 0; i < stackList.size(); i++) {
String tempString = pathSubstrings.get(i);
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2516,3 +2516,5 @@ Do\ you\ want\ to\ recover\ the\ library\ from\ the\ backup\ file?=Do you want t
This\ could\ indicate\ that\ JabRef\ did\ not\ shut\ down\ cleanly\ last\ time\ the\ file\ was\ used.=This could indicate that JabRef did not shut down cleanly last time the file was used.

Use\ the\ field\ FJournal\ to\ store\ the\ full\ journal\ name\ for\ (un)abbreviations\ in\ the\ entry=Use the field FJournal to store the full journal name for (un)abbreviations in the entry

Library\ to\ import\ into=Library to import into
Siedlerchr marked this conversation as resolved.
Show resolved Hide resolved