-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix for issue 10042 #12854
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
Fix for issue 10042 #12854
Changes from all commits
3a4d580
4a53ed2
7482baa
de21816
218d840
9bb6863
35d272d
411c380
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
import java.util.Optional; | ||
import java.util.Random; | ||
import java.util.function.Supplier; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
|
||
import javax.swing.undo.UndoManager; | ||
|
@@ -93,6 +94,7 @@ | |
import org.jabref.model.entry.event.FieldChangedEvent; | ||
import org.jabref.model.entry.field.Field; | ||
import org.jabref.model.entry.field.FieldFactory; | ||
import org.jabref.model.entry.field.StandardField; | ||
import org.jabref.model.groups.GroupTreeNode; | ||
import org.jabref.model.search.query.SearchQuery; | ||
import org.jabref.model.util.DirectoryMonitor; | ||
|
@@ -937,7 +939,56 @@ public void pasteEntry() { | |
return; | ||
} | ||
|
||
importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); | ||
boolean checkCopyPreferences = preferences.getFilePreferences().copyLinkedFiles(); | ||
|
||
if (checkCopyPreferences && (bibDatabaseContext.getLocation() == DatabaseLocation.SHARED)) { | ||
List<BibEntry> linkedFileEntry = copyLinkedFiles(entriesToAdd); | ||
importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, linkedFileEntry); | ||
} else { | ||
importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); | ||
} | ||
} | ||
|
||
private List<BibEntry> copyLinkedFiles(List<BibEntry> entriesToAdd) { | ||
String storagepath = ""; | ||
Optional<String> generalFileDirectory = bibDatabaseContext.getMetaData().getLibrarySpecificFileDirectory(); | ||
if (generalFileDirectory.isPresent()) { | ||
storagepath += generalFileDirectory.get(); | ||
} else { | ||
storagepath += preferences.getFilePreferences().getLinkedFileDirectory(); | ||
} | ||
Comment on lines
+955
to
+959
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code should follow the fail-fast principle by handling invalid states early and avoiding else branches. This can be refactored for better readability. |
||
|
||
Pattern pattern = Pattern.compile("/"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The pattern is compiled inside the method and used multiple times. It should be a static final field to avoid recompilation and improve performance. |
||
for (BibEntry entry : entriesToAdd) { | ||
int i = 0; | ||
String desired = ""; | ||
|
||
List<LinkedFile> entryLinkedFiles = entry.getFiles(); | ||
|
||
for (LinkedFile file : entryLinkedFiles) { | ||
String[] parts = pattern.split(file.getLink()); | ||
String filename = parts[parts.length - 1]; | ||
Path destinationFilePath = Path.of(storagepath).resolve(filename); | ||
Path orignalFilePath = Path.of(file.getLink()); | ||
|
||
FileUtil.copyFile(orignalFilePath, destinationFilePath, true); | ||
|
||
filename = destinationFilePath.toString(); | ||
|
||
desired += file.getDescription() + ":" + filename + ":" + file.getFileType(); | ||
|
||
if (!file.getSourceUrl().isEmpty()) { | ||
desired += ":" + file.getSourceUrl(); | ||
} | ||
if (i < entryLinkedFiles.size() - 1) { | ||
desired += ";"; | ||
} else { | ||
entry.setField(StandardField.FILE, desired); | ||
} | ||
i++; | ||
} | ||
} | ||
return entriesToAdd; | ||
} | ||
|
||
private List<BibEntry> handleNonBibTeXStringData(String data) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,9 +37,14 @@ public class LinkedFilesTab extends AbstractPreferenceTabView<LinkedFilesTabView | |
|
||
@FXML private ComboBox<String> fileNamePattern; | ||
@FXML private TextField fileDirectoryPattern; | ||
|
||
@FXML private CheckBox confirmLinkedFileDelete; | ||
@FXML private CheckBox moveToTrash; | ||
|
||
@FXML private CheckBox copyLinkedFiles; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The addition of the 'copyLinkedFiles' checkbox should be accompanied by a preference migration to handle any changes in default settings. |
||
@FXML private TextField linkedFileDirectory; | ||
|
||
|
||
private final ControlsFxVisualizer validationVisualizer = new ControlsFxVisualizer(); | ||
|
||
public LinkedFilesTab() { | ||
|
@@ -65,6 +70,9 @@ public void initialize() { | |
moveToTrash.selectedProperty().bindBidirectional(viewModel.moveToTrashProperty()); | ||
moveToTrash.setDisable(!NativeDesktop.get().moveToTrashSupported()); | ||
|
||
copyLinkedFiles.selectedProperty().bindBidirectional(viewModel.copyLinkedFilesProperty()); | ||
linkedFileDirectory.textProperty().bindBidirectional(viewModel.linkedFileDirectoryProperty()); | ||
|
||
autolinkFileStartsBibtex.selectedProperty().bindBidirectional(viewModel.autolinkFileStartsBibtexProperty()); | ||
autolinkFileExactBibtex.selectedProperty().bindBidirectional(viewModel.autolinkFileExactBibtexProperty()); | ||
autolinkUseRegex.selectedProperty().bindBidirectional(viewModel.autolinkUseRegexProperty()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,8 @@ public class LinkedFilesTabViewModel implements PreferenceTabViewModel { | |
private final StringProperty fileDirectoryPatternProperty = new SimpleStringProperty(); | ||
private final BooleanProperty confirmLinkedFileDeleteProperty = new SimpleBooleanProperty(); | ||
private final BooleanProperty moveToTrashProperty = new SimpleBooleanProperty(); | ||
private final BooleanProperty copyLinkedFilesProperty = new SimpleBooleanProperty(); | ||
private final StringProperty linkedFileDirectoryProperty = new SimpleStringProperty(); | ||
|
||
private final Validator mainFileDirValidator; | ||
|
||
|
@@ -84,6 +86,8 @@ public void setValues() { | |
fileDirectoryPatternProperty.setValue(filePreferences.getFileDirectoryPattern()); | ||
confirmLinkedFileDeleteProperty.setValue(filePreferences.confirmDeleteLinkedFile()); | ||
moveToTrashProperty.setValue(filePreferences.moveToTrash()); | ||
copyLinkedFilesProperty.setValue(filePreferences.copyLinkedFiles()); | ||
linkedFileDirectoryProperty.setValue(filePreferences.getLinkedFileDirectory()); | ||
|
||
// Autolink preferences | ||
switch (autoLinkPreferences.getCitationKeyDependency()) { | ||
|
@@ -116,6 +120,8 @@ public void storeSettings() { | |
autoLinkPreferences.setRegularExpression(autolinkRegexKeyProperty.getValue()); | ||
filePreferences.confirmDeleteLinkedFile(confirmLinkedFileDeleteProperty.getValue()); | ||
filePreferences.moveToTrash(moveToTrashProperty.getValue()); | ||
filePreferences.copyLinkedFiles(copyLinkedFilesProperty.getValue()); | ||
filePreferences.setLinkedFileDirectory(linkedFileDirectoryProperty.getValue()); | ||
} | ||
|
||
ValidationStatus mainFileDirValidationStatus() { | ||
|
@@ -192,5 +198,13 @@ public BooleanProperty confirmLinkedFileDeleteProperty() { | |
public BooleanProperty moveToTrashProperty() { | ||
return this.moveToTrashProperty; | ||
} | ||
|
||
public BooleanProperty copyLinkedFilesProperty() { | ||
return this.copyLinkedFilesProperty; | ||
} | ||
Comment on lines
+202
to
+204
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method 'copyLinkedFilesProperty' should return an Optional instead of potentially returning null, adhering to modern Java practices. |
||
|
||
public StringProperty linkedFileDirectoryProperty() { | ||
return linkedFileDirectoryProperty; | ||
} | ||
Comment on lines
+206
to
+208
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method 'linkedFileDirectoryProperty' should return an Optional instead of potentially returning null, following modern Java practices. |
||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,8 @@ public class FilePreferences { | |
private final BooleanProperty confirmDeleteLinkedFile = new SimpleBooleanProperty(); | ||
private final BooleanProperty moveToTrash = new SimpleBooleanProperty(); | ||
private final BooleanProperty shouldKeepDownloadUrl = new SimpleBooleanProperty(); | ||
private final BooleanProperty copyLinkedFiles = new SimpleBooleanProperty(); | ||
private final StringProperty linkedFileDirectory = new SimpleStringProperty(); | ||
|
||
public FilePreferences(String userAndHost, | ||
String mainFileDirectory, | ||
|
@@ -45,7 +47,9 @@ public FilePreferences(String userAndHost, | |
Path backupDirectory, | ||
boolean confirmDeleteLinkedFile, | ||
boolean moveToTrash, | ||
boolean shouldKeepDownloadUrl) { | ||
boolean shouldKeepDownloadUrl, | ||
boolean copyLinkedFiles, | ||
String linkedFileDirectory) { | ||
this.userAndHost.setValue(userAndHost); | ||
this.mainFileDirectory.setValue(mainFileDirectory); | ||
this.storeFilesRelativeToBibFile.setValue(storeFilesRelativeToBibFile); | ||
|
@@ -59,6 +63,8 @@ public FilePreferences(String userAndHost, | |
this.confirmDeleteLinkedFile.setValue(confirmDeleteLinkedFile); | ||
this.moveToTrash.setValue(moveToTrash); | ||
this.shouldKeepDownloadUrl.setValue(shouldKeepDownloadUrl); | ||
this.copyLinkedFiles.setValue(copyLinkedFiles); | ||
this.linkedFileDirectory.setValue(linkedFileDirectory); | ||
} | ||
|
||
public String getUserAndHost() { | ||
|
@@ -216,4 +222,28 @@ public BooleanProperty shouldKeepDownloadUrlProperty() { | |
public void setKeepDownloadUrl(boolean shouldKeepDownloadUrl) { | ||
this.shouldKeepDownloadUrl.set(shouldKeepDownloadUrl); | ||
} | ||
|
||
public boolean copyLinkedFiles() { | ||
return copyLinkedFiles.get(); | ||
} | ||
|
||
public BooleanProperty copyLinkedFilesProperty() { | ||
return copyLinkedFiles; | ||
} | ||
|
||
public void copyLinkedFiles(boolean copyLinkedFiles) { | ||
this.copyLinkedFiles.set(copyLinkedFiles); | ||
} | ||
|
||
public String getLinkedFileDirectory() { | ||
return linkedFileDirectory.get(); | ||
} | ||
Comment on lines
+238
to
+240
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method 'getLinkedFileDirectory' should return an Optional to avoid returning null and handle absent values safely. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JabRef works with ...Property; not with the data directly. Please refer to other methods and class variables in that class. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is correct. See other Preferences e.g.
|
||
|
||
public StringProperty linkedFileDirectoryProperty() { | ||
return linkedFileDirectory; | ||
} | ||
|
||
public void setLinkedFileDirectory(String linkedFileDirectory) { | ||
this.linkedFileDirectory.set(linkedFileDirectory); | ||
} | ||
Siedlerchr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition should follow the fail-fast principle by handling invalid states early and returning, instead of nesting logic inside else branches.