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

Follow-up #12035 and #12068: Show an informative progress indicator when dragging and dropping PDF files to JabRef #12072

Merged
merged 6 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -40,6 +40,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076)
- We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686)
- By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955)
- When dragging and dropping several PDF files into the main table, the menu icon for background tasks becomes a progress indicator visualising the import's progress. [#12072](https://github.com/JabRef/jabref/pull/12072)
BaronMac08 marked this conversation as resolved.
Show resolved Hide resolved

### Changed

Expand Down
19 changes: 13 additions & 6 deletions src/main/java/org/jabref/gui/externalfiles/ImportHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.groups.GroupEntryChanger;
import org.jabref.model.groups.GroupTreeNode;
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.FileUpdateMonitor;
import org.jabref.model.util.OptionalUtil;

Expand Down Expand Up @@ -102,6 +103,7 @@ public BackgroundTask<List<ImportFilesResultItemViewModel>> importFilesInBackgro
return new BackgroundTask<>() {
private int counter;
private final List<ImportFilesResultItemViewModel> results = new ArrayList<>();
private final List<BibEntry> allEntriesToAdd = new ArrayList<>();

@Override
public List<ImportFilesResultItemViewModel> call() {
Expand All @@ -115,8 +117,13 @@ public List<ImportFilesResultItemViewModel> call() {
}

UiTaskExecutor.runInJavaFXThread(() -> {
updateMessage(Localization.lang("Processing file %0", file.getFileName()));
updateProgress(counter, files.size() - 1d);
setTitle(Localization.lang("Processing %0 file(s) for %1 | %2 of %0 file(s) processed.",
files.size(),
bibDatabaseContext.getDatabasePath().map(path -> path.getFileName().toString()).orElse(Localization.lang("untitled")),
counter));
updateMessage(Localization.lang("Processing %0", StringUtil.shortenFileName(file.getFileName().toString(), 68)));
updateProgress(counter, files.size());
showToUser(true);
});

try {
Expand Down Expand Up @@ -168,10 +175,7 @@ public List<ImportFilesResultItemViewModel> call() {

UiTaskExecutor.runInJavaFXThread(() -> updateMessage(Localization.lang("Error")));
}

// We need to run the actual import on the FX Thread, otherwise we will get some deadlocks with the UIThreadList
// That method does a clone() on each entry
UiTaskExecutor.runInJavaFXThread(() -> importEntries(entriesToAdd));
allEntriesToAdd.addAll(entriesToAdd);

ce.addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entriesToAdd));
ce.end();
Expand All @@ -180,6 +184,9 @@ public List<ImportFilesResultItemViewModel> call() {

counter++;
}
// We need to run the actual import on the FX Thread, otherwise we will get some deadlocks with the UIThreadList
// That method does a clone() on each entry
UiTaskExecutor.runInJavaFXThread(() -> importEntries(allEntriesToAdd));
return results;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.LinkedFile;
import org.jabref.model.search.LinkedFilesConstants;
import org.jabref.model.strings.StringUtil;

import org.apache.commons.io.FileUtils;
import org.apache.lucene.document.Document;
Expand Down Expand Up @@ -133,8 +134,6 @@ private void addToIndex(Map<String, Pair<Long, Path>> linkedFiles, BackgroundTas
return;
}

task.setTitle(Localization.lang("Indexing PDF files for %0", libraryName));
task.showToUser(true);
LOGGER.debug("Adding {} files to index", linkedFiles.size());
int i = 1;
for (Map.Entry<String, Pair<Long, Path>> entry : linkedFiles.entrySet()) {
Expand All @@ -143,8 +142,10 @@ private void addToIndex(Map<String, Pair<Long, Path>> linkedFiles, BackgroundTas
return;
}
addToIndex(entry.getKey(), entry.getValue().getKey(), entry.getValue().getValue());
task.setTitle(Localization.lang("Indexing PDF %0 file(s) for %1 | %2 of %0 file(s) indexed.", linkedFiles.size(), libraryName, i));
task.updateProgress(i, linkedFiles.size());
task.updateMessage(Localization.lang("Indexing %0. %1 of %2 files added to the index.", entry.getValue().getValue().getFileName(), i, linkedFiles.size()));
task.updateMessage(Localization.lang("Indexing %0", StringUtil.shortenFileName(entry.getValue().getValue().getFileName().toString(), 68)));
task.showToUser(true);
i++;
}
LOGGER.debug("Added {} files to index", linkedFiles.size());
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/org/jabref/model/strings/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import org.jabref.architecture.AllowedToUseApacheCommonsLang3;
import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.logic.util.io.FileUtil;

import com.google.common.base.CharMatcher;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -26,6 +27,8 @@ public class StringUtil {
private static final Pattern LINE_BREAKS = Pattern.compile("\\r\\n|\\r|\\n");
private static final Pattern BRACED_TITLE_CAPITAL_PATTERN = Pattern.compile("\\{[A-Z]+\\}");
private static final UnicodeToReadableCharMap UNICODE_CHAR_MAP = new UnicodeToReadableCharMap();
private static final String ELLIPSIS = "...";
private static final int ELLIPSIS_LENGTH = ELLIPSIS.length();

public static String booleanToBinaryString(boolean expression) {
return expression ? "1" : "0";
Expand Down Expand Up @@ -167,6 +170,66 @@ public static String getCorrectFileName(String orgName, String defaultExtension)
return orgName;
}

/**
* Shorten a given file name in the middle of the name using ellipsis. Example: verylongfilenameisthis.pdf
* with maxLength = 20 is shortened into verylo...isthis.pdf
*
* @param fileName the given file name to be shortened
* @param maxLength the maximum number of characters in the string after shortening (including the extension)
* @return the original fileName if fileName.length() <= maxLength. Otherwise, a shortened fileName
*/
public static String shortenFileName(String fileName, int maxLength) {
if (fileName == null || maxLength < ELLIPSIS_LENGTH) {
return "";
}

if (fileName.length() <= maxLength) {
return fileName;
}

String name;
String extension;

extension = FileUtil.getFileExtension(fileName).map(fileExtension -> '.' + fileExtension).orElse("");
if (extension.isEmpty()) {
name = fileName;
} else {
name = fileName.substring(0, fileName.length() - extension.length());
}

int totalNeededLength = ELLIPSIS_LENGTH + extension.length();
if (maxLength <= totalNeededLength) {
return ELLIPSIS;
}

int charsForName = maxLength - totalNeededLength;
if (charsForName <= 0) {
return ELLIPSIS + extension;
}

int numCharsBeforeEllipsis;
int numCharsAfterEllipsis;
if (charsForName == 1) {
numCharsBeforeEllipsis = 1;
numCharsAfterEllipsis = 0;
} else {
// Allow the front part to have the extra in odd cases
numCharsBeforeEllipsis = (charsForName + 1) / 2;
numCharsAfterEllipsis = charsForName / 2;
}

numCharsBeforeEllipsis = Math.min(numCharsBeforeEllipsis, name.length());
numCharsAfterEllipsis = Math.min(numCharsAfterEllipsis, name.length() - numCharsBeforeEllipsis);

StringBuilder result = new StringBuilder();
result.append(name, 0, numCharsBeforeEllipsis)
.append(ELLIPSIS)
.append(name.substring(name.length() - numCharsAfterEllipsis))
.append(extension);

return result.toString();
}

BaronMac08 marked this conversation as resolved.
Show resolved Hide resolved
/**
* Formats field contents for output. Must be "symmetric" with the parse method above, so stored and reloaded fields
* are not mangled.
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ Extract\ References\ (online)=Extract References (online)
Processing...=Processing...
Processing\ "%0"...=Processing "%0"...
Processing\ PDF(s)=Processing PDF(s)
Processing\ file\ %0=Processing file %0
Processing\ %0=Processing %0
Processing\ %0\ file(s)\ for\ %1\ |\ %2\ of\ %0\ file(s)\ processed.=Processing %0 file(s) for %1 | %2 of %0 file(s) processed.
Processing\ a\ large\ number\ of\ files=Processing a large number of files

You\ are\ about\ to\ process\ %0\ files.\ Continue?=You are about to process %0 files. Continue?
Expand Down Expand Up @@ -490,10 +491,10 @@ Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Indepe
I\ Agree=I Agree

Indexing\ bib\ fields\ for\ %0=Indexing bib fields for %0
Indexing\ PDF\ files\ for\ %0=Indexing PDF files for %0
Indexing\ %0=Indexing %0
Indexing\ PDF\ %0\ file(s)\ for\ %1\ |\ %2\ of\ %0\ file(s)\ indexed.=Indexing PDF %0 file(s) for %1 | %2 of %0 file(s) indexed.
%0\ of\ %1\ entries\ added\ to\ the\ index.=%0 of %1 entries added to the index.
%0\ of\ %1\ entries\ removed\ from\ the\ index.=%0 of %1 entries removed from the index.
Indexing\ %0.\ %1\ of\ %2\ files\ added\ to\ the\ index.=Indexing %0. %1 of %2 files added to the index.
Removing\ entries\ from\ index\ for\ %0=Removing entries from index for %0
Invalid\ URL=Invalid URL

Expand Down
23 changes: 23 additions & 0 deletions src/test/java/org/jabref/model/strings/StringUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
Expand Down Expand Up @@ -367,6 +368,28 @@ void capitalizeFirst() {
assertEquals("Aa", StringUtil.capitalizeFirst("AA"));
}

@ParameterizedTest
@CsvSource({
"'' , , -5",
"'' , , 0",
"'' , , 3",
"'' , , 5",
"'' , , 10",
"'' , thisisatestfile.pdf , -5",
"'' , thisisatestfile.pdf , 0",
"... , thisisatestfile.pdf , 3",
"... , thisisatestfile.pdf , 5",
"th...e.pdf , thisisatestfile.pdf , 10",
"thisisatestfile.pdf , thisisatestfile.pdf , 20",
"... , longfilename.extremelylongextension , 5",
"... , longfilename.extremelylongextension , 10",
"... , longfilename.extremelylongextension , 20",
"lo...me.extremelylongextension , longfilename.extremelylongextension , 30",
})
void shortenFileName(String expected, String fileName, int maxLength) {
assertEquals(expected, StringUtil.shortenFileName(fileName, maxLength));
}

BaronMac08 marked this conversation as resolved.
Show resolved Hide resolved
private static Stream<Arguments> getQuoteStringIfSpaceIsContainedData() {
return Stream.of(
Arguments.of("", ""),
Expand Down
Loading