Skip to content

Commit 96a4f4a

Browse files
committed
Merge branch 'main' into fix-pdf-url-paste
2 parents 9387443 + 2bd1c42 commit 96a4f4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+640
-123
lines changed

.github/workflows/on-pr-closed.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,13 @@ jobs:
8383
default-column: "Free to take"
8484
issue-number: ${{ steps.get_issue_number.outputs.ticketNumber }}
8585
skip-if-not-in-project: true
86-
close_issue_on_pr_merge:
87-
runs-on: ubuntu-latest
88-
steps:
89-
- name: Closes issues related to a merged pull request.
90-
uses: ldez/[email protected]
91-
env:
92-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
86+
- name: Comment on issue
87+
uses: thollander/actions-comment-pull-request@v3
88+
with:
89+
pr-number: ${{ steps.get_issue_number.outputs.ticketNumber }}
90+
message: |
91+
Closed by ${{ github.event.pull_request.html_url }}
92+
93+
Please head to <https://builds.jabref.org/main> to try it out.
94+
95+
For any feedback, add a comment to the pull request at ${{ github.event.pull_request.html_url }}.

.github/workflows/unassign-issues.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
permissions:
1313
issues: write
1414
outputs:
15-
unassigned_issues: ${{ steps.unassign.outputs.unassigned_issues }}
15+
unassigned_issues: ${{ steps.unassign.outputs.unassigned_issues || '[]' }}
1616
steps:
1717
- name: Unassign stale assignments
1818
id: unassign

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
2626
- We added a feature for enabling drag-and-drop of files into groups [#12540](https://github.com/JabRef/jabref/issues/12540)
2727
- We added support for reordering keywords via drag and drop, automatic alphabetical ordering, and improved pasting and editing functionalities in the keyword editor. [#10984](https://github.com/JabRef/jabref/issues/10984)
2828
- We added a new functionality where author names having multiple spaces in-between will be considered as separate user block as it does for " and ". [#12701](https://github.com/JabRef/jabref/issues/12701)
29+
- We added an option to choose whether to open the file explorer in the files directory or in the last opened directory when attaching files. [#12554](https://github.com/JabRef/jabref/issues/12554)
2930
- We enhanced support for parsing XMP metadata from PDF files. [#12829](https://github.com/JabRef/jabref/issues/12829)
3031
- We added a "Preview" header in the JStyles tab in the "Select style" dialog, to make it consistent with the CSL styles tab. [#12838](https://github.com/JabRef/jabref/pull/12838)
3132
- We added automatic PubMed URL insertion when importing from PubMed if no URL is present. [#12832](https://github.com/JabRef/jabref/issues/12832/)
@@ -104,6 +105,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
104105
- We fixed an issue where the tooltip only displayed the first linked file when hovering. [#12470](https://github.com/JabRef/jabref/issues/12470)
105106
- We fixed an issue where some texts in the "Citation Information" tab and the "Preferences" dialog could not be translated. [#12883](https://github.com/JabRef/jabref/pull/12883)
106107
- We fixed an issue where pasting a PDF URL into the main table caused an import error instead of creating a new entry. [#12911](https://github.com/JabRef/jabref/pull/12911)
108+
- We fixed an issue where libraries would sometimes be hidden when closing tabs with the Welcome tab open. [#12894](https://github.com/JabRef/jabref/issues/12894)
107109

108110
### Removed
109111

docs/Gemfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ gem 'jekyll-figure'
77

88
gem "just-the-docs", "0.10.0"
99

10+
# "required" by just-the-docs
11+
gem 'jekyll-seo-tag'
12+
gem 'jekyll-github-metadata'
13+
gem 'jekyll-include-cache'
14+
gem 'jekyll-sitemap'
15+
1016
gem "jekyll-remote-theme"
1117

1218
# Added, because defualt layout with path "**/*.md" does not work at Jekyll
@@ -20,3 +26,4 @@ gem 'jekyll-titles-from-headings'
2026

2127
# Homepage: https://github.com/benbalter/jekyll-relative-links
2228
gem 'jekyll-relative-links'
29+

docs/_config.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repository: JabRef/jabref
22
title: "Developer Documentation"
3-
remote_theme: just-the-docs/just-the-docs@v0.5.0
3+
remote_theme: just-the-docs/just-the-docs@v0.10.0
44
color_scheme: light
55

66
exclude: [_config.yml, .dockerignore, .gitignore, CNAME, Dockerfile, Gemfile, Gemfile.lock, README.md, mkdocs-custom.css]
@@ -38,6 +38,12 @@ baseurl: ""
3838
url: ""
3939

4040
plugins:
41+
# from https://github.com/just-the-docs/just-the-docs/blob/main/_config.yml
42+
- jekyll-seo-tag
43+
- jekyll-github-metadata
44+
- jekyll-include-cache
45+
- jekyll-sitemap
46+
# custom additions
4147
- jekyll-default-layout
4248
- jekyll-figure
4349
- jekyll-remote-theme

src/main/java/org/jabref/gui/actions/StandardActions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public enum StandardActions implements Action {
163163
MOVE_FILE_TO_FOLDER_AND_RENAME(Localization.lang("Move file to file directory and rename file")),
164164
COPY_FILE_TO_FOLDER(Localization.lang("Copy linked file to folder..."), IconTheme.JabRefIcons.COPY_TO_FOLDER, KeyBinding.COPY),
165165
REMOVE_LINK(Localization.lang("Remove link"), IconTheme.JabRefIcons.REMOVE_LINK),
166+
REMOVE_LINKS(Localization.lang("Remove links"), IconTheme.JabRefIcons.REMOVE_LINK),
166167
DELETE_FILE(Localization.lang("Permanently delete local file"), IconTheme.JabRefIcons.DELETE_FILE, KeyBinding.DELETE_ENTRY),
167168

168169
HELP(Localization.lang("Online help"), IconTheme.JabRefIcons.HELP, KeyBinding.HELP),

src/main/java/org/jabref/gui/consistency/ConsistencyCheckDialog.java

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import java.util.stream.Collectors;
99

1010
import javafx.beans.property.ReadOnlyStringWrapper;
11-
import javafx.collections.ListChangeListener;
1211
import javafx.collections.transformation.FilteredList;
1312
import javafx.fxml.FXML;
1413
import javafx.scene.control.ComboBox;
@@ -25,6 +24,8 @@
2524
import org.jabref.logic.quality.consistency.BibliographyConsistencyCheck;
2625
import org.jabref.logic.quality.consistency.ConsistencyMessage;
2726
import org.jabref.model.entry.BibEntryTypesManager;
27+
import org.jabref.model.entry.field.Field;
28+
import org.jabref.model.entry.field.FieldFactory;
2829
import org.jabref.model.entry.field.SpecialField;
2930

3031
import com.airhacks.afterburner.views.ViewLoader;
@@ -62,13 +63,6 @@ public ConsistencyCheckDialog(LibraryTab libraryTab,
6263
.setAsDialogPane(this);
6364
}
6465

65-
private void onSelectionChanged(ListChangeListener.Change<? extends ConsistencyMessage> change) {
66-
if (change.next()) {
67-
change.getAddedSubList().stream().findFirst().ifPresent(message ->
68-
libraryTab.showAndEdit(message.bibEntry()));
69-
}
70-
}
71-
7266
public ConsistencyCheckDialogViewModel getViewModel() {
7367
return viewModel;
7468
}
@@ -77,8 +71,6 @@ public ConsistencyCheckDialogViewModel getViewModel() {
7771
public void initialize() {
7872
viewModel = new ConsistencyCheckDialogViewModel(dialogService, preferences, entryTypesManager, result);
7973

80-
tableView.getSelectionModel().getSelectedItems().addListener(this::onSelectionChanged);
81-
8274
entryTypeCombo.getItems().addAll(viewModel.getEntryTypes());
8375
entryTypeCombo.valueProperty().bindBidirectional(viewModel.selectedEntryTypeProperty());
8476
EasyBind.listen(entryTypeCombo.getEditor().textProperty(), observable -> entryTypeCombo.commitValue());
@@ -129,6 +121,25 @@ protected void updateItem(String item, boolean empty) {
129121
setText(item);
130122
}
131123
);
124+
125+
this.setOnMouseClicked(event -> {
126+
if (!isEmpty()) {
127+
TableColumn<ConsistencyMessage, String> clickedColumn = getTableColumn();
128+
129+
ConsistencyMessage message = getTableRow().getItem();
130+
String cellValue = getTableColumn().getCellObservableValue(getIndex()).getValue();
131+
Field field = FieldFactory.parseField(clickedColumn.getText());
132+
boolean isUnsetField = cellValue.equals(ConsistencySymbol.UNSET_FIELD_AT_ENTRY_TYPE_CELL_ENTRY.getText());
133+
134+
if (field.isStandardField()) {
135+
libraryTab.editEntryAndFocusField(message.bibEntry(), field);
136+
} else if (!message.bibEntry().hasField(field) && isUnsetField) {
137+
libraryTab.showAndEdit(message.bibEntry());
138+
} else {
139+
libraryTab.editEntryAndFocusField(message.bibEntry(), field);
140+
}
141+
}
142+
});
132143
}
133144
});
134145

src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java

Lines changed: 39 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import javafx.scene.control.ProgressBar;
2020
import javafx.scene.control.ProgressIndicator;
2121
import javafx.scene.control.SelectionMode;
22-
import javafx.scene.control.SeparatorMenuItem;
2322
import javafx.scene.control.Tooltip;
2423
import javafx.scene.input.ClipboardContent;
2524
import javafx.scene.input.DragEvent;
@@ -34,25 +33,24 @@
3433

3534
import org.jabref.gui.DialogService;
3635
import org.jabref.gui.DragAndDropDataFormats;
37-
import org.jabref.gui.actions.ActionFactory;
38-
import org.jabref.gui.actions.SimpleCommand;
39-
import org.jabref.gui.actions.StandardActions;
4036
import org.jabref.gui.autocompleter.SuggestionProvider;
41-
import org.jabref.gui.copyfiles.CopySingleFileAction;
37+
import org.jabref.gui.fieldeditors.contextmenu.ContextAction;
38+
import org.jabref.gui.fieldeditors.contextmenu.ContextMenuFactory;
39+
import org.jabref.gui.fieldeditors.contextmenu.ContextMenuFactory.MultiContextCommandFactory;
40+
import org.jabref.gui.fieldeditors.contextmenu.ContextMenuFactory.SingleContextCommandFactory;
41+
import org.jabref.gui.fieldeditors.contextmenu.MultiContextAction;
4242
import org.jabref.gui.icon.IconTheme;
4343
import org.jabref.gui.icon.JabRefIconView;
4444
import org.jabref.gui.importer.GrobidUseDialogHelper;
4545
import org.jabref.gui.keyboard.KeyBinding;
4646
import org.jabref.gui.linkedfile.DeleteFileAction;
4747
import org.jabref.gui.linkedfile.LinkedFileEditDialog;
4848
import org.jabref.gui.preferences.GuiPreferences;
49-
import org.jabref.gui.util.BindingsHelper;
5049
import org.jabref.gui.util.ViewModelListCellFactory;
5150
import org.jabref.gui.util.uithreadaware.UiThreadObservableList;
5251
import org.jabref.logic.integrity.FieldCheckers;
5352
import org.jabref.logic.journals.JournalAbbreviationRepository;
5453
import org.jabref.logic.l10n.Localization;
55-
import org.jabref.logic.preferences.CliPreferences;
5654
import org.jabref.logic.util.TaskExecutor;
5755
import org.jabref.model.database.BibDatabaseContext;
5856
import org.jabref.model.entry.BibEntry;
@@ -88,6 +86,9 @@ public class LinkedFilesEditor extends HBox implements FieldEditorFX {
8886
private ObservableOptionalValue<BibEntry> bibEntry = EasyBind.wrapNullable(new SimpleObjectProperty<>());
8987
private final UiThreadObservableList<LinkedFileViewModel> decoratedModelList;
9088

89+
private ContextMenu activeContextMenu = null;
90+
private ContextMenuFactory contextMenuFactory;
91+
9192
public LinkedFilesEditor(Field field,
9293
BibDatabaseContext databaseContext,
9394
SuggestionProvider<?> suggestionProvider,
@@ -98,8 +99,8 @@ public LinkedFilesEditor(Field field,
9899
this.fieldCheckers = fieldCheckers;
99100

100101
ViewLoader.view(this)
101-
.root(this)
102-
.load();
102+
.root(this)
103+
.load();
103104

104105
decoratedModelList = new UiThreadObservableList<>(viewModel.filesProperty());
105106
Bindings.bindContentBidirectional(listView.itemsProperty().get(), decoratedModelList);
@@ -120,7 +121,6 @@ private void initialize() {
120121
new ViewModelListCellFactory<LinkedFileViewModel>()
121122
.withStringTooltip(LinkedFileViewModel::getDescriptionAndLink)
122123
.withGraphic(this::createFileDisplay)
123-
.withContextMenu(this::createContextMenuForFile)
124124
.withOnMouseClickedEvent(this::handleItemMouseClick)
125125
.setOnDragDetected(this::handleOnDragDetected)
126126
.setOnDragDropped(this::handleOnDragDropped)
@@ -302,90 +302,40 @@ private void addFromURL() {
302302

303303
private void handleItemMouseClick(LinkedFileViewModel linkedFile, MouseEvent event) {
304304
if (event.getButton() == MouseButton.PRIMARY && (event.getClickCount() == 2)) {
305-
// Double click -> open
306-
linkedFile.open();
305+
linkedFile.open(); // Double-click: open file
306+
} else if (activeContextMenu != null && event.getButton() == MouseButton.PRIMARY) {
307+
activeContextMenu.hide(); // Hide context menu if left-click
308+
activeContextMenu = null;
309+
} else if (event.getButton() == MouseButton.SECONDARY) {
310+
if (activeContextMenu != null) {
311+
activeContextMenu.hide(); // Hide any existing context menu
312+
activeContextMenu = null;
313+
}
314+
315+
SingleContextCommandFactory contextCommandFactory = (action, file) ->
316+
new ContextAction(action, file, databaseContext, bibEntry, preferences, viewModel);
317+
318+
MultiContextCommandFactory multiContextCommandFactory = (action, files) ->
319+
new MultiContextAction(action, files, databaseContext, bibEntry, preferences, viewModel);
320+
321+
contextMenuFactory = new ContextMenuFactory(
322+
dialogService,
323+
preferences,
324+
databaseContext,
325+
bibEntry,
326+
viewModel,
327+
contextCommandFactory,
328+
multiContextCommandFactory
329+
);
330+
331+
ContextMenu contextMenu = contextMenuFactory.createForSelection(listView.getSelectionModel().getSelectedItems());
332+
contextMenu.show(listView, event.getScreenX(), event.getScreenY());
333+
activeContextMenu = contextMenu;
307334
}
308335
}
309336

310337
@Override
311338
public double getWeight() {
312339
return 3;
313340
}
314-
315-
private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) {
316-
ContextMenu menu = new ContextMenu();
317-
ActionFactory factory = new ActionFactory();
318-
319-
menu.getItems().addAll(
320-
factory.createMenuItem(StandardActions.EDIT_FILE_LINK, new ContextAction(StandardActions.EDIT_FILE_LINK, linkedFile, preferences)),
321-
new SeparatorMenuItem(),
322-
factory.createMenuItem(StandardActions.OPEN_FILE, new ContextAction(StandardActions.OPEN_FILE, linkedFile, preferences)),
323-
factory.createMenuItem(StandardActions.OPEN_FOLDER, new ContextAction(StandardActions.OPEN_FOLDER, linkedFile, preferences)),
324-
new SeparatorMenuItem(),
325-
factory.createMenuItem(StandardActions.DOWNLOAD_FILE, new ContextAction(StandardActions.DOWNLOAD_FILE, linkedFile, preferences)),
326-
factory.createMenuItem(StandardActions.RENAME_FILE_TO_PATTERN, new ContextAction(StandardActions.RENAME_FILE_TO_PATTERN, linkedFile, preferences)),
327-
factory.createMenuItem(StandardActions.RENAME_FILE_TO_NAME, new ContextAction(StandardActions.RENAME_FILE_TO_NAME, linkedFile, preferences)),
328-
factory.createMenuItem(StandardActions.MOVE_FILE_TO_FOLDER, new ContextAction(StandardActions.MOVE_FILE_TO_FOLDER, linkedFile, preferences)),
329-
factory.createMenuItem(StandardActions.MOVE_FILE_TO_FOLDER_AND_RENAME, new ContextAction(StandardActions.MOVE_FILE_TO_FOLDER_AND_RENAME, linkedFile, preferences)),
330-
factory.createMenuItem(StandardActions.COPY_FILE_TO_FOLDER, new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext, preferences.getFilePreferences())),
331-
factory.createMenuItem(StandardActions.REDOWNLOAD_FILE, new ContextAction(StandardActions.REDOWNLOAD_FILE, linkedFile, preferences)),
332-
factory.createMenuItem(StandardActions.REMOVE_LINK, new ContextAction(StandardActions.REMOVE_LINK, linkedFile, preferences)),
333-
factory.createMenuItem(StandardActions.DELETE_FILE, new ContextAction(StandardActions.DELETE_FILE, linkedFile, preferences))
334-
);
335-
336-
return menu;
337-
}
338-
339-
private class ContextAction extends SimpleCommand {
340-
341-
private final StandardActions command;
342-
private final LinkedFileViewModel linkedFile;
343-
344-
public ContextAction(StandardActions command, LinkedFileViewModel linkedFile, CliPreferences preferences) {
345-
this.command = command;
346-
this.linkedFile = linkedFile;
347-
348-
this.executable.bind(
349-
switch (command) {
350-
case RENAME_FILE_TO_PATTERN -> Bindings.createBooleanBinding(
351-
() -> !linkedFile.getFile().isOnlineLink()
352-
&& linkedFile.getFile().findIn(databaseContext, preferences.getFilePreferences()).isPresent()
353-
&& !linkedFile.isGeneratedNameSameAsOriginal(),
354-
linkedFile.getFile().linkProperty(), bibEntry.getValue().map(BibEntry::getFieldsObservable).orElse(null));
355-
case MOVE_FILE_TO_FOLDER, MOVE_FILE_TO_FOLDER_AND_RENAME -> Bindings.createBooleanBinding(
356-
() -> !linkedFile.getFile().isOnlineLink()
357-
&& linkedFile.getFile().findIn(databaseContext, preferences.getFilePreferences()).isPresent()
358-
&& !linkedFile.isGeneratedPathSameAsOriginal(),
359-
linkedFile.getFile().linkProperty(), bibEntry.getValue().map(BibEntry::getFieldsObservable).orElse(null));
360-
case DOWNLOAD_FILE -> Bindings.createBooleanBinding(
361-
() -> linkedFile.getFile().isOnlineLink(),
362-
linkedFile.getFile().linkProperty(), bibEntry.getValue().map(BibEntry::getFieldsObservable).orElse(null));
363-
case REDOWNLOAD_FILE -> Bindings.createBooleanBinding(
364-
() -> !linkedFile.getFile().getSourceUrl().isEmpty(),
365-
linkedFile.getFile().sourceUrlProperty(), bibEntry.getValue().map(BibEntry::getFieldsObservable).orElse(null));
366-
case OPEN_FILE, OPEN_FOLDER, RENAME_FILE_TO_NAME, DELETE_FILE -> Bindings.createBooleanBinding(
367-
() -> !linkedFile.getFile().isOnlineLink()
368-
&& linkedFile.getFile().findIn(databaseContext, preferences.getFilePreferences()).isPresent(),
369-
linkedFile.getFile().linkProperty(), bibEntry.getValue().map(BibEntry::getFieldsObservable).orElse(null));
370-
default -> BindingsHelper.constantOf(true);
371-
});
372-
}
373-
374-
@Override
375-
public void execute() {
376-
switch (command) {
377-
case EDIT_FILE_LINK -> linkedFile.edit();
378-
case OPEN_FILE -> linkedFile.open();
379-
case OPEN_FOLDER -> linkedFile.openFolder();
380-
case DOWNLOAD_FILE -> linkedFile.download(true);
381-
case REDOWNLOAD_FILE -> linkedFile.redownload();
382-
case RENAME_FILE_TO_PATTERN -> linkedFile.renameToSuggestion();
383-
case RENAME_FILE_TO_NAME -> linkedFile.askForNameAndRename();
384-
case MOVE_FILE_TO_FOLDER -> linkedFile.moveToDefaultDirectory();
385-
case MOVE_FILE_TO_FOLDER_AND_RENAME -> linkedFile.moveToDefaultDirectoryAndRename();
386-
case DELETE_FILE -> viewModel.deleteFile(linkedFile);
387-
case REMOVE_LINK -> viewModel.removeFileLink(linkedFile);
388-
}
389-
}
390-
}
391341
}

0 commit comments

Comments
 (0)