diff --git a/src/main/java/org/jabref/gui/AbstractViewModel.java b/src/main/java/org/jabref/gui/AbstractViewModel.java index f04b77cd7a8..ff9f1fca633 100644 --- a/src/main/java/org/jabref/gui/AbstractViewModel.java +++ b/src/main/java/org/jabref/gui/AbstractViewModel.java @@ -1,5 +1,5 @@ package org.jabref.gui; public class AbstractViewModel { - + //empty } diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index c83ec818dff..b6b506375e2 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -11,7 +11,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -110,7 +109,6 @@ import org.jabref.model.database.shared.DatabaseLocation; import org.jabref.model.database.shared.DatabaseSynchronizer; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.EntryType; import org.jabref.model.entry.FieldName; import org.jabref.model.entry.InternalBibtexFields; import org.jabref.model.entry.LinkedFile; @@ -761,58 +759,6 @@ public void registerUndoableChanges(SaveSession session) { } } - /** - * This method is called from JabRefFrame when the user wants to create a new entry. If the argument is null, the - * user is prompted for an entry type. - * - * @param type The type of the entry to create. - * @return The newly created BibEntry or null the operation was canceled by the user. - */ - public BibEntry newEntry(EntryType type) { - EntryType actualType = type; - if (actualType == null) { - // Find out what type is wanted. - final EntryTypeDialog etd = new EntryTypeDialog(frame); - // We want to center the dialog, to make it look nicer. - etd.setVisible(true); - actualType = etd.getChoice(); - } - if (actualType != null) { // Only if the dialog was not canceled. - final BibEntry be = new BibEntry(actualType.getName()); - try { - bibDatabaseContext.getDatabase().insertEntry(be); - // Set owner/timestamp if options are enabled: - List list = new ArrayList<>(); - list.add(be); - UpdateField.setAutomaticFields(list, true, true, Globals.prefs.getUpdateFieldPreferences()); - - // Create an UndoableInsertEntry object. - getUndoManager().addEdit(new UndoableInsertEntry(bibDatabaseContext.getDatabase(), be)); - output(Localization.lang("Added new '%0' entry.", actualType.getName().toLowerCase(Locale.ROOT))); - - // We are going to select the new entry. Before that, make sure that we are in - // show-entry mode. If we aren't already in that mode, enter the WILL_SHOW_EDITOR - // mode which makes sure the selection will trigger display of the entry editor - // and adjustment of the splitter. - if (mode != BasePanelMode.SHOWING_EDITOR) { - mode = BasePanelMode.WILL_SHOW_EDITOR; - } - - clearAndSelect(be); - - // The database just changed. - markBaseChanged(); - - this.showAndEdit(be); - - return be; - } catch (KeyCollisionException ex) { - LOGGER.info(ex.getMessage(), ex); - } - } - return null; - } - /** * This method is called from JabRefFrame when the user wants to create a new entry. * @@ -822,10 +768,10 @@ public void insertEntry(final BibEntry bibEntry) { if (bibEntry != null) { try { bibDatabaseContext.getDatabase().insertEntry(bibEntry); - if (Globals.prefs.getBoolean(JabRefPreferences.USE_OWNER)) { - // Set owner field to default value - UpdateField.setAutomaticFields(bibEntry, true, true, Globals.prefs.getUpdateFieldPreferences()); - } + + // Set owner and timestamp + UpdateField.setAutomaticFields(bibEntry, true, true, Globals.prefs.getUpdateFieldPreferences()); + // Create an UndoableInsertEntry object. getUndoManager().addEdit(new UndoableInsertEntry(bibDatabaseContext.getDatabase(), bibEntry)); output(Localization.lang("Added new '%0' entry.", bibEntry.getType())); diff --git a/src/main/java/org/jabref/gui/EntryType.fxml b/src/main/java/org/jabref/gui/EntryType.fxml new file mode 100644 index 00000000000..e08551310df --- /dev/null +++ b/src/main/java/org/jabref/gui/EntryType.fxml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/EntryTypeDialog.java b/src/main/java/org/jabref/gui/EntryTypeDialog.java deleted file mode 100644 index 93cc5a73a3d..00000000000 --- a/src/main/java/org/jabref/gui/EntryTypeDialog.java +++ /dev/null @@ -1,366 +0,0 @@ -package org.jabref.gui; - -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutionException; - -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; - -import org.jabref.Globals; -import org.jabref.gui.importer.ImportInspectionDialog; -import org.jabref.gui.keyboard.KeyBinding; -import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.logic.bibtex.DuplicateCheck; -import org.jabref.logic.bibtexkeypattern.BibtexKeyGenerator; -import org.jabref.logic.importer.FetcherException; -import org.jabref.logic.importer.IdBasedFetcher; -import org.jabref.logic.importer.WebFetchers; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.EntryTypes; -import org.jabref.model.database.BibDatabaseMode; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.BiblatexEntryTypes; -import org.jabref.model.entry.BibtexEntryTypes; -import org.jabref.model.entry.EntryType; -import org.jabref.model.entry.IEEETranEntryTypes; -import org.jabref.preferences.JabRefPreferences; - -import com.jgoodies.forms.builder.ButtonBarBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Dialog that prompts the user to choose a type for an entry. - * Returns null if canceled. - */ -public class EntryTypeDialog extends JabRefDialog implements ActionListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(EntryTypeDialog.class); - private static final int COLUMN = 3; - private final JabRefFrame frame; - private final CancelAction cancelAction = new CancelAction(); - private EntryType type; - private SwingWorker, Void> fetcherWorker = new FetcherWorker(); - private JButton generateButton; - private JTextField idTextField; - private JComboBox comboBox; - - public EntryTypeDialog(JabRefFrame frame) { - // modal dialog - super(true, EntryTypeDialog.class); - - this.frame = frame; - - setTitle(Localization.lang("Select entry type")); - - addWindowListener(new WindowAdapter() { - - @Override - public void windowClosing(WindowEvent e) { - cancelAction.actionPerformed(null); - } - }); - - getContentPane().setLayout(new BorderLayout()); - getContentPane().add(createCancelButtonBarPanel(), BorderLayout.SOUTH); - getContentPane().add(createEntryGroupsPanel(), BorderLayout.CENTER); - - pack(); - setResizable(false); - } - - private JPanel createEntryGroupsPanel() { - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - - if (frame.getCurrentBasePanel().getBibDatabaseContext().isBiblatexMode()) { - panel.add(createEntryGroupPanel("biblatex", BiblatexEntryTypes.ALL)); - - List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBLATEX); - if (!customTypes.isEmpty()) { - panel.add(createEntryGroupPanel(Localization.lang("Custom"), customTypes)); - } - } else { - panel.add(createEntryGroupPanel("BibTeX", BibtexEntryTypes.ALL)); - panel.add(createEntryGroupPanel("IEEETran", IEEETranEntryTypes.ALL)); - - List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBTEX); - if (!customTypes.isEmpty()) { - panel.add(createEntryGroupPanel(Localization.lang("Custom"), customTypes)); - } - } - panel.add(createIdFetcherPanel()); - - return panel; - } - - private JPanel createCancelButtonBarPanel() { - JButton cancel = new JButton(Localization.lang("Cancel")); - cancel.addActionListener(this); - - // Make ESC close dialog, equivalent to clicking Cancel. - cancel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(Globals.getKeyPrefs().getKey(KeyBinding.CLOSE), "close"); - cancel.getActionMap().put("close", cancelAction); - - JPanel buttons = new JPanel(); - ButtonBarBuilder bb = new ButtonBarBuilder(buttons); - bb.addGlue(); - bb.addButton(cancel); - bb.addGlue(); - return buttons; - } - - private JPanel createEntryGroupPanel(String groupTitle, Collection entries) { - JPanel panel = new JPanel(); - GridBagLayout bagLayout = new GridBagLayout(); - panel.setLayout(bagLayout); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.WEST; - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.insets = new Insets(4, 4, 4, 4); - // column count - int col = 0; - - for (EntryType entryType : entries) { - TypeButton entryButton = new TypeButton(entryType.getName(), entryType); - entryButton.addActionListener(this); - // Check if we should finish the row. - col++; - if (col == EntryTypeDialog.COLUMN) { - col = 0; - constraints.gridwidth = GridBagConstraints.REMAINDER; - } else { - constraints.gridwidth = 1; - } - bagLayout.setConstraints(entryButton, constraints); - panel.add(entryButton); - } - panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), groupTitle)); - - return panel; - } - - private JPanel createIdFetcherPanel() { - JLabel fetcherLabel = new JLabel(Localization.lang("ID type")); - JLabel idLabel = new JLabel(Localization.lang("ID")); - generateButton = new JButton(Localization.lang("Generate")); - idTextField = new JTextField(""); - comboBox = new JComboBox<>(); - - WebFetchers.getIdBasedFetchers(Globals.prefs.getImportFormatPreferences()).forEach(fetcher -> comboBox.addItem(fetcher.getName())); - - comboBox.setSelectedItem(Globals.prefs.get(JabRefPreferences.ID_ENTRY_GENERATOR)); - - generateButton.addActionListener(action -> { - fetcherWorker.execute(); - }); - - comboBox.addActionListener(e -> { - idTextField.requestFocus(); - idTextField.selectAll(); - }); - - idTextField.addActionListener(event -> fetcherWorker.execute()); - - JPanel jPanel = new JPanel(); - - GridBagConstraints constraints = new GridBagConstraints(); - constraints.insets = new Insets(4, 4, 4, 4); - - GridBagLayout layout = new GridBagLayout(); - jPanel.setLayout(layout); - - constraints.fill = GridBagConstraints.HORIZONTAL; - - constraints.gridx = 0; - constraints.gridy = 0; - constraints.weightx = 1; - jPanel.add(fetcherLabel, constraints); - - constraints.gridx = 1; - constraints.gridy = 0; - constraints.weightx = 2; - jPanel.add(comboBox, constraints); - - constraints.gridx = 0; - constraints.gridy = 1; - constraints.weightx = 1; - jPanel.add(idLabel, constraints); - - constraints.gridx = 1; - constraints.gridy = 1; - constraints.weightx = 2; - jPanel.add(idTextField, constraints); - - constraints.gridy = 2; - constraints.gridx = 0; - constraints.gridwidth = 2; - constraints.fill = GridBagConstraints.NONE; - jPanel.add(generateButton, constraints); - - jPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), Localization.lang("ID-based entry generator"))); - - SwingUtilities.invokeLater(() -> idTextField.requestFocus()); - - return jPanel; - } - - private void stopFetching() { - if (fetcherWorker.getState() == SwingWorker.StateValue.STARTED) { - fetcherWorker.cancel(true); - } - } - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource() instanceof TypeButton) { - type = ((TypeButton) e.getSource()).getType(); - } - stopFetching(); - dispose(); - } - - public EntryType getChoice() { - return type; - } - - static class TypeButton extends JButton implements Comparable { - - private final EntryType type; - - TypeButton(String label, EntryType type) { - super(label); - this.type = type; - } - - @Override - public int compareTo(TypeButton o) { - return type.getName().compareTo(o.type.getName()); - } - - public EntryType getType() { - return type; - } - } - - class CancelAction extends AbstractAction { - - public CancelAction() { - super("Cancel"); - } - - @Override - public void actionPerformed(ActionEvent e) { - stopFetching(); - dispose(); - } - } - - private class FetcherWorker extends SwingWorker, Void> { - - private boolean fetcherException = false; - private String fetcherExceptionMessage = ""; - private IdBasedFetcher fetcher = null; - private String searchID = ""; - - @Override - protected Optional doInBackground() throws Exception { - Optional bibEntry = Optional.empty(); - SwingUtilities.invokeLater(() -> { - generateButton.setEnabled(false); - generateButton.setText(Localization.lang("Searching...")); - }); - - Globals.prefs.put(JabRefPreferences.ID_ENTRY_GENERATOR, String.valueOf(comboBox.getSelectedItem())); - fetcher = WebFetchers.getIdBasedFetchers(Globals.prefs.getImportFormatPreferences()).get(comboBox.getSelectedIndex()); - searchID = idTextField.getText(); - if (!searchID.isEmpty()) { - try { - bibEntry = fetcher.performSearchById(searchID); - } catch (FetcherException e) { - LOGGER.error(e.getMessage(), e); - fetcherException = true; - fetcherExceptionMessage = e.getMessage(); - } - } - return bibEntry; - } - - @Override - protected void done() { - try { - Optional result = get(); - if (result.isPresent()) { - final BibEntry bibEntry = result.get(); - if ((DuplicateCheck.containsDuplicate(frame.getCurrentBasePanel().getDatabase(), bibEntry, frame.getCurrentBasePanel().getBibDatabaseContext().getMode()).isPresent())) { - //If there are duplicates starts ImportInspectionDialog - final BasePanel panel = frame.getCurrentBasePanel(); - - ImportInspectionDialog diag = new ImportInspectionDialog(frame, panel, Localization.lang("Import"), false); - diag.addEntries(Collections.singletonList(bibEntry)); - diag.entryListComplete(); - diag.setVisible(true); - diag.toFront(); - } else { - // Regenerate CiteKey of imported BibEntry - new BibtexKeyGenerator(frame.getCurrentBasePanel().getBibDatabaseContext(), Globals.prefs.getBibtexKeyPatternPreferences()).generateAndSetKey(bibEntry); - // Update Timestamps - if (Globals.prefs.getTimestampPreferences().includeCreatedTimestamp()) { - bibEntry.setField(Globals.prefs.getTimestampPreferences().getTimestampField(), Globals.prefs.getTimestampPreferences().now()); - } - DefaultTaskExecutor.runInJavaFXThread(() -> frame.getCurrentBasePanel().insertEntry(bibEntry)); - } - - dispose(); - } else if (searchID.trim().isEmpty()) { - DefaultTaskExecutor.runInJavaFXThread(() -> { - frame.getDialogService().showWarningDialogAndWait( - Localization.lang("Empty search ID"), - Localization.lang("The given search ID was empty.")); - }); - } else if (!fetcherException) { - DefaultTaskExecutor.runInJavaFXThread(() -> { - frame.getDialogService().showErrorDialogAndWait( - Localization.lang("No files found."), - Localization.lang("Fetcher '%0' did not find an entry for id '%1'.", fetcher.getName(), searchID) + "\n" + fetcherExceptionMessage); - }); - } else { - DefaultTaskExecutor.runInJavaFXThread(() -> { - frame.getDialogService().showErrorDialogAndWait( - Localization.lang("Error"), - Localization.lang("Error while fetching from %0", fetcher.getName()) + "." + "\n" + fetcherExceptionMessage); - }); - } - fetcherWorker = new FetcherWorker(); - SwingUtilities.invokeLater(() -> { - idTextField.requestFocus(); - idTextField.selectAll(); - generateButton.setText(Localization.lang("Generate")); - generateButton.setEnabled(true); - }); - } catch (ExecutionException | InterruptedException e) { - LOGGER.error(String.format("Exception during fetching when using fetcher '%s' with entry id '%s'.", searchID, fetcher.getName()), e); - } - } - } -} diff --git a/src/main/java/org/jabref/gui/EntryTypeView.java b/src/main/java/org/jabref/gui/EntryTypeView.java new file mode 100644 index 00000000000..7eeb35a218c --- /dev/null +++ b/src/main/java/org/jabref/gui/EntryTypeView.java @@ -0,0 +1,161 @@ +package org.jabref.gui; + +import java.util.Collection; +import java.util.List; + +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.ComboBox; +import javafx.scene.control.TextField; +import javafx.scene.control.TitledPane; +import javafx.scene.layout.FlowPane; + +import org.jabref.gui.util.BaseDialog; +import org.jabref.gui.util.ControlHelper; +import org.jabref.gui.util.ViewModelListCellFactory; +import org.jabref.logic.importer.IdBasedFetcher; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.EntryTypes; +import org.jabref.model.database.BibDatabaseMode; +import org.jabref.model.entry.BiblatexEntryTypes; +import org.jabref.model.entry.BibtexEntryTypes; +import org.jabref.model.entry.EntryType; +import org.jabref.model.entry.IEEETranEntryTypes; +import org.jabref.preferences.JabRefPreferences; + +import com.airhacks.afterburner.views.ViewLoader; +import org.fxmisc.easybind.EasyBind; + +/** + * Dialog that prompts the user to choose a type for an entry. + * Returns null if canceled. + */ +public class EntryTypeView extends BaseDialog { + + @FXML private ButtonType generateButton; + @FXML private TextField idTextField; + @FXML private ComboBox idBasedFetchers; + @FXML private FlowPane biblatexPane; + @FXML private FlowPane bibTexPane; + @FXML private FlowPane ieeetranPane; + @FXML private FlowPane customPane; + @FXML private TitledPane biblatexTitlePane; + @FXML private TitledPane bibTexTitlePane; + @FXML private TitledPane ieeeTranTitlePane; + @FXML private TitledPane customTitlePane; + + private final BasePanel basePanel; + private final DialogService dialogService; + private final JabRefPreferences prefs; + + private EntryType type; + private EntryTypeViewModel viewModel; + + public EntryTypeView(BasePanel basePanel, DialogService dialogService, JabRefPreferences preferences) { + this.basePanel = basePanel; + this.dialogService = dialogService; + this.prefs = preferences; + + this.setTitle(Localization.lang("Select entry type")); + ViewLoader.view(this) + .load() + .setAsDialogPane(this); + + ControlHelper.setAction(generateButton, this.getDialogPane(), event -> viewModel.runFetcherWorker()); + + setResultConverter(button -> { + //The buttonType will always be cancel, even if we pressed one of the entry type buttons + return type; + }); + + Button btnGenerate = (Button) this.getDialogPane().lookupButton(generateButton); + + btnGenerate.textProperty().bind(EasyBind.map(viewModel.searchingProperty(), searching -> (searching) ? Localization.lang("Searching...") : Localization.lang("Generate"))); + btnGenerate.disableProperty().bind(viewModel.searchingProperty()); + } + + private void addEntriesToPane(FlowPane pane, Collection entries) { + + for (EntryType entryType : entries) { + Button entryButton = new Button(entryType.getName()); + entryButton.setUserData(entryType); + entryButton.setOnAction(event -> setEntryTypeForReturnAndClose(entryType)); + pane.getChildren().add(entryButton); + } + } + + @FXML + public void initialize() { + viewModel = new EntryTypeViewModel(prefs, basePanel, dialogService); + + idBasedFetchers.itemsProperty().bind(viewModel.fetcherItemsProperty()); + idTextField.textProperty().bindBidirectional(viewModel.idTextProperty()); + idBasedFetchers.valueProperty().bindBidirectional(viewModel.selectedItemProperty()); + + EasyBind.subscribe(viewModel.getFocusAndSelectAllProperty(), evt -> { + if (evt) { + idTextField.requestFocus(); + idTextField.selectAll(); + } + }); + + new ViewModelListCellFactory().withText(item -> item.getName()).install(idBasedFetchers); + + //we set the managed property so that they will only be rendered when they are visble so that the Nodes only take the space when visible + //avoids removing and adding from the scence graph + bibTexTitlePane.managedProperty().bind(bibTexTitlePane.visibleProperty()); + ieeeTranTitlePane.managedProperty().bind(ieeeTranTitlePane.visibleProperty()); + biblatexTitlePane.managedProperty().bind(biblatexTitlePane.visibleProperty()); + customTitlePane.managedProperty().bind(customTitlePane.visibleProperty()); + + if (basePanel.getBibDatabaseContext().isBiblatexMode()) { + addEntriesToPane(biblatexPane, BiblatexEntryTypes.ALL); + + bibTexTitlePane.setVisible(false); + ieeeTranTitlePane.setVisible(false); + + List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBLATEX); + if (customTypes.isEmpty()) { + customTitlePane.setVisible(false); + } else { + addEntriesToPane(customPane, customTypes); + } + + } else { + biblatexTitlePane.setVisible(false); + addEntriesToPane(bibTexPane, BibtexEntryTypes.ALL); + addEntriesToPane(ieeetranPane, IEEETranEntryTypes.ALL); + + List customTypes = EntryTypes.getAllCustomTypes(BibDatabaseMode.BIBTEX); + if (customTypes.isEmpty()) { + customTitlePane.setVisible(false); + } else { + addEntriesToPane(customPane, customTypes); + } + } + + } + + public EntryType getChoice() { + return type; + } + + @FXML + private void runFetcherWorker(Event event) { + viewModel.runFetcherWorker(); + } + + @FXML + private void focusTextField(Event event) { + idTextField.requestFocus(); + idTextField.selectAll(); + } + + private void setEntryTypeForReturnAndClose(EntryType entryType) { + type = entryType; + viewModel.stopFetching(); + this.close(); + } +} diff --git a/src/main/java/org/jabref/gui/EntryTypeViewModel.java b/src/main/java/org/jabref/gui/EntryTypeViewModel.java new file mode 100644 index 00000000000..bc0464a309d --- /dev/null +++ b/src/main/java/org/jabref/gui/EntryTypeViewModel.java @@ -0,0 +1,158 @@ +package org.jabref.gui; + +import java.util.Arrays; +import java.util.Optional; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.concurrent.Task; +import javafx.concurrent.Worker; + +import org.jabref.gui.importer.ImportInspectionDialog; +import org.jabref.logic.bibtex.DuplicateCheck; +import org.jabref.logic.bibtexkeypattern.BibtexKeyGenerator; +import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.importer.IdBasedFetcher; +import org.jabref.logic.importer.WebFetchers; +import org.jabref.logic.importer.fetcher.DoiFetcher; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.strings.StringUtil; +import org.jabref.preferences.JabRefPreferences; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EntryTypeViewModel { + + private static final Logger LOGGER = LoggerFactory.getLogger(EntryTypeViewModel.class); + + private final JabRefPreferences prefs; + private final BooleanProperty searchingProperty = new SimpleBooleanProperty(); + private final ObjectProperty selectedItemProperty = new SimpleObjectProperty<>(); + private final ListProperty fetchers = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final StringProperty idText = new SimpleStringProperty(); + private final BooleanProperty focusAndSelectAllProperty = new SimpleBooleanProperty(); + private Task> fetcherWorker = new FetcherWorker(); + private final BasePanel basePanel; + private final DialogService dialogService; + + public EntryTypeViewModel(JabRefPreferences preferences, BasePanel basePanel, DialogService dialogService) { + this.basePanel = basePanel; + this.prefs = preferences; + this.dialogService = dialogService; + fetchers.addAll(WebFetchers.getIdBasedFetchers(preferences.getImportFormatPreferences())); + selectedItemProperty.setValue(getLastSelectedFetcher()); + + } + + public BooleanProperty searchingProperty() { + return searchingProperty; + } + + public ObjectProperty selectedItemProperty() { + return selectedItemProperty; + } + + public StringProperty idTextProperty() { + return idText; + } + + public BooleanProperty getFocusAndSelectAllProperty() { + return focusAndSelectAllProperty; + } + + public void storeSelectedFetcher() { + prefs.setIdBasedFetcherForEntryGenerator(selectedItemProperty.getValue().getName()); + } + + private IdBasedFetcher getLastSelectedFetcher() { + return fetchers.stream().filter(fetcher -> fetcher.getName().equals(prefs.getIdBasedFetcherForEntryGenerator())) + .findFirst().orElse(new DoiFetcher(prefs.getImportFormatPreferences())); + } + + public ListProperty fetcherItemsProperty() { + return fetchers; + } + + public void stopFetching() { + if (fetcherWorker.getState() == Worker.State.RUNNING) { + fetcherWorker.cancel(true); + } + } + + private class FetcherWorker extends Task> { + + private IdBasedFetcher fetcher = null; + private String searchID = ""; + + @Override + protected Optional call() throws InterruptedException, FetcherException { + Optional bibEntry = Optional.empty(); + + searchingProperty().setValue(true); + storeSelectedFetcher(); + fetcher = selectedItemProperty().getValue(); + searchID = idText.getValue(); + if (!searchID.isEmpty()) { + bibEntry = fetcher.performSearchById(searchID); + } + return bibEntry; + } + + } + + public void runFetcherWorker() { + fetcherWorker.run(); + fetcherWorker.setOnFailed(event -> { + Throwable exception = fetcherWorker.getException(); + String fetcherExceptionMessage = exception.getMessage(); + String fetcher = selectedItemProperty().getValue().getName(); + String searchId = idText.getValue(); + if (exception instanceof FetcherException) { + dialogService.showErrorDialogAndWait(Localization.lang("Error"), Localization.lang("Error while fetching from %0", fetcher + "." + "\n" + fetcherExceptionMessage)); + } else { + dialogService.showErrorDialogAndWait(Localization.lang("No files found.", Localization.lang("Fetcher '%0' did not find an entry for id '%1'.", fetcher, searchId) + "\n" + fetcherExceptionMessage)); + } + LOGGER.error(String.format("Exception during fetching when using fetcher '%s' with entry id '%s'.", searchId, fetcher), exception); + + searchingProperty.set(false); + fetcherWorker = new FetcherWorker(); + }); + + fetcherWorker.setOnSucceeded(evt -> { + Optional result = fetcherWorker.getValue(); + if (result.isPresent()) { + final BibEntry bibEntry = result.get(); + if ((DuplicateCheck.containsDuplicate(basePanel.getDatabase(), bibEntry, basePanel.getBibDatabaseContext().getMode()).isPresent())) { + //If there are duplicates starts ImportInspectionDialog + ImportInspectionDialog diag = new ImportInspectionDialog(basePanel.frame(), basePanel, Localization.lang("Import"), false); + diag.addEntries(Arrays.asList(bibEntry)); + diag.entryListComplete(); + diag.setVisible(true); + diag.toFront(); + } else { + // Regenerate CiteKey of imported BibEntry + new BibtexKeyGenerator(basePanel.getBibDatabaseContext(), prefs.getBibtexKeyPatternPreferences()).generateAndSetKey(bibEntry); + basePanel.insertEntry(bibEntry); + } + + // close(); + } else if (StringUtil.isBlank(idText.getValue())) { + dialogService.showWarningDialogAndWait(Localization.lang("Empty search ID"), Localization.lang("The given search ID was empty.")); + } + fetcherWorker = new FetcherWorker(); + + focusAndSelectAllProperty.set(true); + searchingProperty().setValue(false); + + }); + } +} diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index b894a5e3f05..d440752b7a2 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -621,7 +621,7 @@ private Node createToolbar() { PushToApplicationButton pushToExternal = new PushToApplicationButton(this, pushApplications.getApplications()); HBox rightSide = new HBox( - factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(this, BiblatexEntryTypes.ARTICLE)), + factory.createIconButton(StandardActions.NEW_ENTRY, new NewEntryAction(this, BiblatexEntryTypes.ARTICLE, dialogService, Globals.prefs)), factory.createIconButton(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, Globals.stateManager)), factory.createIconButton(StandardActions.UNDO, new OldDatabaseCommandWrapper(Actions.UNDO, this, Globals.stateManager)), @@ -838,9 +838,9 @@ private MenuBar createMenu() { ); library.getItems().addAll( - factory.createMenuItem(StandardActions.NEW_ARTICLE, new NewEntryAction(this, BibtexEntryTypes.ARTICLE)), - factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(this)), - factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAINTEX, new NewEntryFromPlainTextAction(this, Globals.prefs.getUpdateFieldPreferences())), + factory.createMenuItem(StandardActions.NEW_ARTICLE, new NewEntryAction(this, BibtexEntryTypes.ARTICLE, dialogService, Globals.prefs)), + factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(this, dialogService, Globals.prefs)), + factory.createMenuItem(StandardActions.NEW_ENTRY_FROM_PLAINTEX, new NewEntryFromPlainTextAction(this, Globals.prefs.getUpdateFieldPreferences(), dialogService, Globals.prefs)), new SeparatorMenuItem(), diff --git a/src/main/java/org/jabref/gui/actions/NewEntryAction.java b/src/main/java/org/jabref/gui/actions/NewEntryAction.java index dd8c0add054..a5b483a4d67 100644 --- a/src/main/java/org/jabref/gui/actions/NewEntryAction.java +++ b/src/main/java/org/jabref/gui/actions/NewEntryAction.java @@ -4,17 +4,19 @@ import java.util.Map; import java.util.Optional; -import javax.swing.SwingUtilities; - import org.jabref.Globals; -import org.jabref.gui.EntryTypeDialog; +import org.jabref.gui.DialogService; +import org.jabref.gui.EntryTypeView; import org.jabref.gui.JabRefFrame; +import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.EntryType; +import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class NewEntryAction extends SimpleCommand { + private static final Logger LOGGER = LoggerFactory.getLogger(NewEntryAction.class); private final JabRefFrame jabRefFrame; @@ -22,16 +24,21 @@ public class NewEntryAction extends SimpleCommand { * The type of the entry to create. */ private final Optional type; + private final DialogService dialogService; + private final JabRefPreferences preferences; - - public NewEntryAction(JabRefFrame jabRefFrame) { + public NewEntryAction(JabRefFrame jabRefFrame, DialogService dialogService, JabRefPreferences preferences) { this.jabRefFrame = jabRefFrame; this.type = Optional.empty(); + this.dialogService = dialogService; + this.preferences = preferences; } - public NewEntryAction(JabRefFrame jabRefFrame, EntryType type) { + public NewEntryAction(JabRefFrame jabRefFrame, EntryType type, DialogService dialogService, JabRefPreferences preferences) { this.jabRefFrame = jabRefFrame; this.type = Optional.of(type); + this.dialogService = dialogService; + this.preferences = preferences; } @Override @@ -42,27 +49,23 @@ public void execute() { } if (type.isPresent()) { - jabRefFrame.getCurrentBasePanel().newEntry(type.get()); + jabRefFrame.getCurrentBasePanel().insertEntry(new BibEntry(type.get())); } else { - SwingUtilities.invokeLater(() -> { - EntryTypeDialog typeChoiceDialog = new EntryTypeDialog(jabRefFrame); - typeChoiceDialog.setVisible(true); - EntryType selectedType = typeChoiceDialog.getChoice(); - if (selectedType == null) { - return; - } + EntryTypeView typeChoiceDialog = new EntryTypeView(jabRefFrame.getCurrentBasePanel(), dialogService, preferences); + EntryType selectedType = typeChoiceDialog.showAndWait().orElse(null); + if (selectedType == null) { + return; + } - trackNewEntry(selectedType); - jabRefFrame.getCurrentBasePanel().newEntry(selectedType); - }); + trackNewEntry(selectedType); + jabRefFrame.getCurrentBasePanel().insertEntry(new BibEntry(selectedType)); } } private void trackNewEntry(EntryType type) { Map properties = new HashMap<>(); properties.put("EntryType", type.getName()); - Map measurements = new HashMap<>(); - Globals.getTelemetryClient().ifPresent(client -> client.trackEvent("NewEntry", properties, measurements)); + Globals.getTelemetryClient().ifPresent(client -> client.trackEvent("NewEntry", properties, new HashMap<>())); } } diff --git a/src/main/java/org/jabref/gui/actions/NewEntryFromPlainTextAction.java b/src/main/java/org/jabref/gui/actions/NewEntryFromPlainTextAction.java index 0c048ea7ed8..b4c3faa9a2b 100644 --- a/src/main/java/org/jabref/gui/actions/NewEntryFromPlainTextAction.java +++ b/src/main/java/org/jabref/gui/actions/NewEntryFromPlainTextAction.java @@ -1,12 +1,14 @@ package org.jabref.gui.actions; -import org.jabref.gui.EntryTypeDialog; +import org.jabref.gui.DialogService; +import org.jabref.gui.EntryTypeView; import org.jabref.gui.JabRefFrame; import org.jabref.gui.plaintextimport.TextInputDialog; import org.jabref.logic.util.UpdateField; import org.jabref.logic.util.UpdateFieldPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.EntryType; +import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,10 +19,14 @@ public class NewEntryFromPlainTextAction extends SimpleCommand { private final UpdateFieldPreferences prefs; private final JabRefFrame jabRefFrame; + private final DialogService dialogService; + private final JabRefPreferences preferences; - public NewEntryFromPlainTextAction(JabRefFrame jabRefFrame, UpdateFieldPreferences prefs) { + public NewEntryFromPlainTextAction(JabRefFrame jabRefFrame, UpdateFieldPreferences prefs, DialogService dialogService, JabRefPreferences preferences) { this.jabRefFrame = jabRefFrame; this.prefs = prefs; + this.dialogService = dialogService; + this.preferences = preferences; } @@ -31,13 +37,12 @@ public void execute() { return; } - EntryTypeDialog typeChoiceDialog = new EntryTypeDialog(jabRefFrame); - typeChoiceDialog.setVisible(true); - EntryType selectedType = typeChoiceDialog.getChoice(); + EntryTypeView typeChoiceDialog = new EntryTypeView(jabRefFrame.getCurrentBasePanel(), dialogService, preferences); + EntryType selectedType = typeChoiceDialog.showAndWait().orElse(null); if (selectedType == null) { return; } - BibEntry bibEntry = new BibEntry(selectedType.getName()); + BibEntry bibEntry = new BibEntry(selectedType); TextInputDialog tidialog = new TextInputDialog(jabRefFrame, bibEntry); tidialog.setVisible(true); diff --git a/src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java b/src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java index 01b54ce0103..2d260b3f074 100644 --- a/src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java +++ b/src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java @@ -117,10 +117,10 @@ private static boolean haveDifferentEditions(final BibEntry one, final BibEntry } private static boolean haveDifferentChaptersOrPagesOfTheSameBook(final BibEntry one, final BibEntry two) { - return compareSingleField(AUTHOR, one, two) == EQUAL && - compareSingleField(TITLE, one, two) == EQUAL && - (compareSingleField(CHAPTER, one, two) == NOT_EQUAL || - compareSingleField(PAGES, one, two) == NOT_EQUAL); + return (compareSingleField(AUTHOR, one, two) == EQUAL) && + (compareSingleField(TITLE, one, two) == EQUAL) && + ((compareSingleField(CHAPTER, one, two) == NOT_EQUAL) || + (compareSingleField(PAGES, one, two) == NOT_EQUAL)); } @@ -289,12 +289,9 @@ public static double compareEntriesStrictly(BibEntry one, BibEntry two) { public static Optional containsDuplicate(final BibDatabase database, final BibEntry entry, final BibDatabaseMode bibDatabaseMode) { - for (final BibEntry other : database.getEntries()) { - if (DuplicateCheck.isDuplicate(entry, other, bibDatabaseMode)) { - return Optional.of(other); // Duplicate found. - } - } - return Optional.empty(); // No duplicate found. + + return database.getEntries().stream().filter(other -> DuplicateCheck.isDuplicate(entry, other, bibDatabaseMode)).findFirst(); + } /** @@ -342,7 +339,7 @@ private static double similarity(final String first, final String second) { return 1.0; } final double distanceIgnoredCase = new StringSimilarity().editDistanceIgnoreCase(longer, shorter); - final double similarity = (longerLength - distanceIgnoredCase) / (double) longerLength; + final double similarity = (longerLength - distanceIgnoredCase) / longerLength; LOGGER.debug("Longer string: " + longer + " Shorter string: " + shorter + " Similarity: " + similarity); return similarity; } diff --git a/src/main/java/org/jabref/pdfimport/PdfImporter.java b/src/main/java/org/jabref/pdfimport/PdfImporter.java index 78428efab3e..7f1298cfc44 100644 --- a/src/main/java/org/jabref/pdfimport/PdfImporter.java +++ b/src/main/java/org/jabref/pdfimport/PdfImporter.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.Optional; import javax.swing.JOptionPane; @@ -13,21 +12,17 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; -import org.jabref.gui.BasePanelMode; -import org.jabref.gui.EntryTypeDialog; +import org.jabref.gui.EntryTypeView; import org.jabref.gui.JabRefFrame; import org.jabref.gui.externalfiles.DroppedFileHandler; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.filelist.FileListEntry; import org.jabref.gui.filelist.FileListTableModel; import org.jabref.gui.maintable.MainTable; -import org.jabref.gui.undo.UndoableInsertEntry; import org.jabref.logic.bibtexkeypattern.BibtexKeyGenerator; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.fileformat.PdfContentImporter; import org.jabref.logic.importer.fileformat.PdfXmpImporter; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.UpdateField; import org.jabref.logic.util.io.FileUtil; import org.jabref.logic.xmp.XmpUtilShared; import org.jabref.model.database.KeyCollisionException; @@ -117,26 +112,26 @@ private List importPdfFilesInternal(List fileNames) { if (neverShow || (importDialog.getResult() == JOptionPane.OK_OPTION)) { int choice = neverShow ? globalChoice : importDialog.getChoice(); switch (choice) { - case ImportDialog.XMP: - doXMPImport(fileName, res); - break; - - case ImportDialog.CONTENT: - doContentImport(fileName, res); - break; - case ImportDialog.NOMETA: - createNewBlankEntry(fileName).ifPresent(res::add); - break; - case ImportDialog.ONLYATTACH: - DroppedFileHandler dfh = new DroppedFileHandler(frame, panel); - if (dropRow >= 0) { - dfh.linkPdfToEntry(fileName, entryTable, dropRow); - } else { - entryTable.getSelectedEntries().forEach(entry -> dfh.linkPdfToEntry(fileName, entry)); - } - break; - default: - break; + case ImportDialog.XMP: + doXMPImport(fileName, res); + break; + + case ImportDialog.CONTENT: + doContentImport(fileName, res); + break; + case ImportDialog.NOMETA: + createNewBlankEntry(fileName).ifPresent(res::add); + break; + case ImportDialog.ONLYATTACH: + DroppedFileHandler dfh = new DroppedFileHandler(frame, panel); + if (dropRow >= 0) { + dfh.linkPdfToEntry(fileName, entryTable, dropRow); + } else { + entryTable.getSelectedEntries().forEach(entry -> dfh.linkPdfToEntry(fileName, entry)); + } + break; + default: + break; } } @@ -169,10 +164,10 @@ private void doXMPImport(String fileName, List res) { Path toLink = Paths.get(fileName); // Get a list of file directories: List dirsS = panel.getBibDatabaseContext() - .getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences()); + .getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences()); tm.addEntry(0, new FileListEntry("", FileUtil.shortenFileName(toLink, dirsS).toString(), - ExternalFileTypes.getInstance().getExternalFileTypeByName("PDF"))); + ExternalFileTypes.getInstance().getExternalFileTypeByName("PDF"))); entry.setField(FieldName.FILE, tm.getStringRepresentation()); res.add(entry); } @@ -190,7 +185,7 @@ private Optional createNewBlankEntry(String fileName) { private void doContentImport(String fileName, List res) { PdfContentImporter contentImporter = new PdfContentImporter( - Globals.prefs.getImportFormatPreferences()); + Globals.prefs.getImportFormatPreferences()); Path filePath = Paths.get(fileName); ParserResult result = contentImporter.importDatabase(filePath, Globals.prefs.getDefaultEncoding()); if (result.hasWarnings()) { @@ -210,7 +205,7 @@ private void doContentImport(String fileName, List res) { panel.getDatabase().insertEntry(entry); panel.markBaseChanged(); new BibtexKeyGenerator(panel.getBibDatabaseContext(), Globals.prefs.getBibtexKeyPatternPreferences()) - .generateAndSetKey(entry); + .generateAndSetKey(entry); DroppedFileHandler dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entry); @@ -224,37 +219,13 @@ private void doContentImport(String fileName, List res) { private Optional createNewEntry() { // Find out what type is desired - EntryTypeDialog etd = new EntryTypeDialog(frame); - etd.setVisible(true); - EntryType type = etd.getChoice(); + EntryTypeView entryTypeDialog = new EntryTypeView(frame.getCurrentBasePanel(), frame.getDialogService(), Globals.prefs); + EntryType type = entryTypeDialog.showAndWait().orElse(null); if (type != null) { // Only if the dialog was not canceled. - final BibEntry bibEntry = new BibEntry(type.getName()); + final BibEntry bibEntry = new BibEntry(type); try { - panel.getDatabase().insertEntry(bibEntry); - - // Set owner/timestamp if options are enabled: - List list = new ArrayList<>(); - list.add(bibEntry); - UpdateField.setAutomaticFields(list, true, true, Globals.prefs.getUpdateFieldPreferences()); - - // Create an UndoableInsertEntry object. - panel.getUndoManager().addEdit(new UndoableInsertEntry(panel.getDatabase(), bibEntry)); - panel.output(Localization.lang("Added new") + " '" + type.getName().toLowerCase(Locale.ROOT) + "' " - + Localization.lang("entry") + "."); - - // We are going to select the new entry. Before that, make sure that we are in - // show-entry mode. If we aren't already in that mode, enter the WILL_SHOW_EDITOR - // mode which makes sure the selection will trigger display of the entry editor - // and adjustment of the splitter. - if (panel.getMode() != BasePanelMode.SHOWING_EDITOR) { - panel.setMode(BasePanelMode.WILL_SHOW_EDITOR); - } - - SwingUtilities.invokeLater(() -> panel.showAndEdit(bibEntry)); - - // The database just changed. - panel.markBaseChanged(); + panel.insertEntry(bibEntry); return Optional.of(bibEntry); } catch (KeyCollisionException ex) { diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 1be4e2a6052..d398ff19978 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -901,14 +901,14 @@ private static void insertDefaultCleanupPreset(Map storage) { public EntryEditorPreferences getEntryEditorPreferences() { return new EntryEditorPreferences(getEntryEditorTabList(), - getLatexFieldFormatterPreferences(), - getImportFormatPreferences(), - getCustomTabFieldNames(), - getBoolean(SHOW_RECOMMENDATIONS), - getBoolean(DEFAULT_SHOW_SOURCE), - getBibtexKeyPatternPreferences(), - Globals.getKeyPrefs(), - getBoolean(AVOID_OVERWRITING_KEY)); + getLatexFieldFormatterPreferences(), + getImportFormatPreferences(), + getCustomTabFieldNames(), + getBoolean(SHOW_RECOMMENDATIONS), + getBoolean(DEFAULT_SHOW_SOURCE), + getBibtexKeyPatternPreferences(), + Globals.getKeyPrefs(), + getBoolean(AVOID_OVERWRITING_KEY)); } public Map getSidePanePreferredPositions() { @@ -1354,7 +1354,7 @@ public void importPreferences(Path file) throws JabRefException { Preferences.importPreferences(is); } catch (InvalidPreferencesFormatException | IOException ex) { throw new JabRefException("Could not import preferences", Localization.lang("Could not import preferences"), - ex); + ex); } } @@ -1424,7 +1424,7 @@ public boolean isKeywordSyncEnabled() { public ImportFormatPreferences getImportFormatPreferences() { return new ImportFormatPreferences(customImports, getDefaultEncoding(), getKeywordDelimiter(), getBibtexKeyPatternPreferences(), getFieldContentParserPreferences(), getXMPPreferences(), - isKeywordSyncEnabled()); + isKeywordSyncEnabled()); } public SavePreferences loadForExportFromPreferences() { @@ -1472,13 +1472,13 @@ public ExporterFactory getExporterFactory(JournalAbbreviationLoader abbreviation public BibtexKeyPatternPreferences getBibtexKeyPatternPreferences() { return new BibtexKeyPatternPreferences( - get(KEY_PATTERN_REGEX), - get(KEY_PATTERN_REPLACEMENT), - getBoolean(KEY_GEN_ALWAYS_ADD_LETTER), - getBoolean(KEY_GEN_FIRST_LETTER_A), - getBoolean(ENFORCE_LEGAL_BIBTEX_KEY), - getKeyPattern(), - getKeywordDelimiter()); + get(KEY_PATTERN_REGEX), + get(KEY_PATTERN_REPLACEMENT), + getBoolean(KEY_GEN_ALWAYS_ADD_LETTER), + getBoolean(KEY_GEN_FIRST_LETTER_A), + getBoolean(ENFORCE_LEGAL_BIBTEX_KEY), + getKeyPattern(), + getKeywordDelimiter()); } public TimestampPreferences getTimestampPreferences() { @@ -1947,4 +1947,12 @@ public void setLanguage(Language language) { setLanguageDependentDefaultValues(); } } + + public void setIdBasedFetcherForEntryGenerator(String fetcherName) { + put(ID_ENTRY_GENERATOR, fetcherName); + } + + public String getIdBasedFetcherForEntryGenerator() { + return get(ID_ENTRY_GENERATOR); + } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index f356031221a..58fe003e16b 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -39,6 +39,8 @@ What\ is\ Mr.\ DLib?=What is Mr. DLib? Add=Add +Add\ new=Add new + Add\ a\ (compiled)\ custom\ Importer\ class\ from\ a\ class\ path.=Add a (compiled) custom Importer class from a class path. The\ path\ need\ not\ be\ on\ the\ classpath\ of\ JabRef.=The path need not be on the classpath of JabRef. @@ -53,16 +55,12 @@ Add\ from\ folder=Add from folder Add\ from\ JAR=Add from JAR -Add\ new=Add new - Add\ subgroup=Add subgroup Add\ to\ group=Add to group Added\ group\ "%0".=Added group "%0". -Added\ new=Added new - Added\ string=Added string Additionally,\ entries\ whose\ %0\ field\ does\ not\ contain\ %1\ can\ be\ assigned\ manually\ to\ this\ group\ by\ selecting\ them\ then\ using\ either\ drag\ and\ drop\ or\ the\ context\ menu.\ This\ process\ adds\ the\ term\ %1\ to\ each\ entry's\ %0\ field.\ Entries\ can\ be\ removed\ manually\ from\ this\ group\ by\ selecting\ them\ then\ using\ the\ context\ menu.\ This\ process\ removes\ the\ term\ %1\ from\ each\ entry's\ %0\ field.=Additionally, entries whose %0 field does not contain %1 can be assigned manually to this group by selecting them then using either drag and drop or the context menu. This process adds the term %1 to each entry's %0 field. Entries can be removed manually from this group by selecting them then using the context menu. This process removes the term %1 from each entry's %0 field. @@ -2038,7 +2036,6 @@ Existing\ file=Existing file ID=ID ID\ type=ID type -ID-based\ entry\ generator=ID-based entry generator Fetcher\ '%0'\ did\ not\ find\ an\ entry\ for\ id\ '%1'.=Fetcher '%0' did not find an entry for id '%1'. Select\ first\ entry=Select first entry diff --git a/src/test/java/org/jabref/gui/GUITest.java b/src/test/java/org/jabref/gui/GUITest.java deleted file mode 100644 index 92f93eaca61..00000000000 --- a/src/test/java/org/jabref/gui/GUITest.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.jabref.gui; - -import java.io.IOException; - -import javax.swing.JButton; - -import org.jabref.gui.dbproperties.DatabasePropertiesDialog; - -import org.assertj.swing.core.GenericTypeMatcher; -import org.assertj.swing.dependency.jsr305.Nonnull; -import org.assertj.swing.fixture.DialogFixture; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -import static org.assertj.swing.finder.WindowFinder.findDialog; - -@Tag("GUITest") -public class GUITest extends AbstractUITest { - - @Test - public void testExit() { - exitJabRef(); - } - - @Test - public void testNewFile() { - newDatabase(); - closeDatabase(); - exitJabRef(); - } - - @Test - public void testCreateBibtexEntry() throws IOException { - newDatabase(); - - mainFrame.menuItemWithPath("BibTeX", "New entry...").click(); - findDialog(EntryTypeDialog.class).withTimeout(10_000).using(robot()) - .button(new GenericTypeMatcher(JButton.class) { - @Override - protected boolean isMatching(@Nonnull JButton jButton) { - return "Book".equals(jButton.getText()); - } - }).click(); - takeScreenshot(mainFrame, "MainWindowWithOneDatabase"); - } - - /** - * tests different buttons - * sometimes this test clicks some buttons twice to reverse their effect and leaves JabRef as it was before - */ - @Test - public void testViewChanges() { - newDatabase(); - - mainFrame.menuItemWithPath("View", "Increase table font size").click(); - mainFrame.menuItemWithPath("View", "Decrease table font size").click(); - - mainFrame.menuItemWithPath("View", "Web search").click(); - mainFrame.menuItemWithPath("View", "Web search").click(); - - mainFrame.menuItemWithPath("View", "Toggle groups interface").click(); - mainFrame.menuItemWithPath("View", "Toggle groups interface").click(); - - mainFrame.menuItemWithPath("View", "Toggle entry preview").click(); - mainFrame.menuItemWithPath("View", "Toggle entry preview").click(); - - mainFrame.menuItemWithPath("View", "Next preview layout").click(); - mainFrame.menuItemWithPath("View", "Previous preview layout").click(); - - mainFrame.menuItemWithPath("View", "Hide/show toolbar").click(); - mainFrame.menuItemWithPath("View", "Hide/show toolbar").click(); - - mainFrame.menuItemWithPath("View", "Focus entry table").click(); - - closeDatabase(); - exitJabRef(); - } - - @Test - public void testDatabasePropertiesDialog() throws IOException { - newDatabase(); - - mainFrame.menuItemWithPath("File", "Library properties").click(); - - robot().waitForIdle(); - - DialogFixture databasePropertiesDialog = findDialog(DatabasePropertiesDialog.class).withTimeout(10_000).using(robot()); - takeScreenshot(databasePropertiesDialog, "DatabasePropertiesDialog"); - databasePropertiesDialog.button(new GenericTypeMatcher(JButton.class) { - @Override - protected boolean isMatching(@Nonnull JButton jButton) { - return "OK".equals(jButton.getText()); - } - }).click(); - - closeDatabase(); - exitJabRef(); - } -} diff --git a/src/test/java/org/jabref/gui/UndoTest.java b/src/test/java/org/jabref/gui/UndoTest.java deleted file mode 100644 index b8b2fb3eb18..00000000000 --- a/src/test/java/org/jabref/gui/UndoTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.jabref.gui; - -import javax.swing.JButton; - -import org.assertj.swing.core.GenericTypeMatcher; -import org.assertj.swing.dependency.jsr305.Nonnull; -import org.assertj.swing.fixture.JTableFixture; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -import static org.assertj.swing.finder.WindowFinder.findDialog; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@Tag("GUITest") -public class UndoTest extends AbstractUITest { - - @Test - public void undoCutOfMultipleEntries() { - importBibIntoNewDatabase(getAbsolutePath("testbib/testjabref.bib")); - - JTableFixture entryTable = mainFrame.table(); - - assertTrue(entryTable.rowCount() >= 2, "The database must have at least 2 entries for the test to begin!"); - entryTable.selectRows(0, 1); - entryTable.requireSelectedRows(0, 1); - - int oldRowCount = entryTable.rowCount(); - mainFrame.menuItemWithPath("Edit", "Cut").click(); - mainFrame.menuItemWithPath("Edit", "Undo").click(); - entryTable.requireRowCount(oldRowCount); - - closeDatabase(); - exitJabRef(); - } - - @Test - public void undoRedoUpdatedCorrectly() { - newDatabase(); - assertFalse(mainFrame.menuItemWithPath("Edit", "Undo").isEnabled()); - assertFalse(mainFrame.menuItemWithPath("Edit", "Redo").isEnabled()); - JTableFixture entryTable = mainFrame.table(); - mainFrame.menuItemWithPath("BibTeX", "New entry...").click(); - findDialog(EntryTypeDialog.class).withTimeout(10_000).using(robot()) - .button(new GenericTypeMatcher(JButton.class) { - - @Override - protected boolean isMatching(@Nonnull JButton jButton) { - return "Book".equals(jButton.getText()); - } - }).click(); - - assertTrue(mainFrame.menuItemWithPath("Edit", "Undo").isEnabled()); - assertFalse(mainFrame.menuItemWithPath("Edit", "Redo").isEnabled()); - entryTable.requireRowCount(1); - - mainFrame.menuItemWithPath("Edit", "Undo").click(); - assertFalse(mainFrame.menuItemWithPath("Edit", "Undo").isEnabled()); - assertTrue(mainFrame.menuItemWithPath("Edit", "Redo").isEnabled()); - entryTable.requireRowCount(0); - - closeDatabase(); - exitJabRef(); - } - -}