19 package org.sleuthkit.autopsy.texttranslation.ui;
21 import com.google.common.collect.Lists;
22 import com.google.common.util.concurrent.ThreadFactoryBuilder;
23 import java.awt.Component;
24 import java.awt.ComponentOrientation;
26 import java.awt.event.ActionEvent;
27 import java.awt.event.ActionListener;
28 import java.io.IOException;
29 import java.io.Reader;
30 import java.util.Arrays;
31 import java.util.concurrent.ExecutorService;
32 import java.util.concurrent.Executors;
33 import java.util.concurrent.ThreadFactory;
34 import org.openide.nodes.Node;
35 import org.openide.util.lookup.ServiceProvider;
38 import org.openide.util.Lookup;
39 import org.openide.util.NbBundle;
40 import org.openide.util.lookup.Lookups;
46 import java.util.List;
47 import java.util.logging.Level;
48 import javax.swing.SwingUtilities;
58 @ServiceProvider(service =
TextViewer.class, position = 4)
63 private static final int MAX_EXTRACT_SIZE_BYTES = 25600;
67 private volatile Node
node;
69 private final ThreadFactory translationThreadFactory
70 =
new ThreadFactoryBuilder().setNameFormat(
"translation-content-viewer-%d").build();
71 private final ExecutorService executorService = Executors.newSingleThreadExecutor(translationThreadFactory);
74 "TranslatedTextViewer.maxPayloadSize=Up to the first %dKB of text will be translated"
80 panel.addDisplayTextActionListener(displayDropDownListener);
83 panel.addLanguagePackNames(INSTALLED_LANGUAGE_PACKS);
88 panel.setWarningLabelMsg(String.format(Bundle.TranslatedTextViewer_maxPayloadSize(), payloadMaxInKB));
94 @NbBundle.Messages({
"TranslatedTextViewer.title=Translation"})
97 return Bundle.TranslatedTextViewer_title();
100 @NbBundle.Messages({
"TranslatedTextViewer.toolTip=Displays translated file text."})
103 return Bundle.TranslatedTextViewer_toolTip();
120 if (backgroundTask != null) {
121 backgroundTask.cancel(
true);
123 backgroundTask = null;
136 AbstractFile file = node.getLookup().lookup(AbstractFile.class);
152 private final AbstractFile
file;
155 super(translateText, String.format(
"%s (objId=%d)", file.getName(), file.getId()));
167 "TranslatedContentViewer.extractingText=Extracting text, please wait...",
168 "# {0} - exception message",
"TranslatedContentViewer.errorExtractingText=An error occurred while extracting the text ({0}).",
170 protected String
retrieveText()
throws IOException, InterruptedException, IllegalStateException {
171 SwingUtilities.invokeLater(() -> {
172 onProgressDisplay(Bundle.TranslatedContentViewer_extractingText(), ComponentOrientation.LEFT_TO_RIGHT, Font.ITALIC);
176 return getFileText(file);
178 logger.log(Level.WARNING, String.format(
"Error extracting text for file %s (objId=%d)", file.getName(), file.getId()), ex);
180 throw new IllegalStateException(Bundle.TranslatedContentViewer_errorExtractingText(ex.getMessage()), ex);
198 "TranslatedContentViewer.ocrNotEnabled=OCR is not enabled. To change, go to Tools->Options->Machine Translation",
201 final boolean isImage = file.getMIMEType().toLowerCase().startsWith(
"image/");
203 return Bundle.TranslatedContentViewer_ocrNotEnabled();
209 byte[] resultInUTF8Bytes = result.getBytes(
"UTF8");
210 byte[] trimToArraySize = Arrays.copyOfRange(resultInUTF8Bytes, 0,
211 Math.min(resultInUTF8Bytes.length, MAX_EXTRACT_SIZE_BYTES));
212 return new String(trimToArraySize,
"UTF-8");
229 Reader textExtractor = getTextExtractor(source, ocrEnabled);
231 char[] cbuf =
new char[8096];
232 StringBuilder textBuilder =
new StringBuilder();
239 while ((read = textExtractor.read(cbuf)) != -1) {
240 if (this.isCancelled()) {
241 throw new InterruptedException();
246 int bytesLeft = MAX_EXTRACT_SIZE_BYTES - bytesRead;
248 if (bytesLeft < read) {
249 textBuilder.append(cbuf, 0, bytesLeft);
250 return textBuilder.toString();
253 textBuilder.append(cbuf, 0, read);
257 return textBuilder.toString();
275 Lookup context = null;
281 String ocrSelection = panel.getSelectedOcrLanguagePack();
282 if (!ocrSelection.isEmpty()) {
289 context = Lookups.fixed(imageConfig, terminator);
302 protected void onTextDisplay(String text, ComponentOrientation orientation,
int font) {
303 panel.
display(text, orientation, font);
316 abstract String getSelection();
320 String selection = getSelection();
321 if (!selection.equals(currentSelection)) {
322 currentSelection = selection;
324 if (backgroundTask != null && !backgroundTask.isDone()) {
325 backgroundTask.cancel(
true);
328 AbstractFile file = node.getLookup().lookup(AbstractFile.class);
329 String textDisplaySelection = panel.getDisplayDropDownSelection();
330 boolean translateText = !textDisplaySelection.equals(DisplayDropdownOptions.ORIGINAL_TEXT.toString());
335 executorService.execute(backgroundTask);
346 String getSelection() {
347 return panel.getDisplayDropDownSelection();
357 String getSelection() {
358 return panel.getSelectedOcrLanguagePack();
void setNode(final Node node)
volatile ExtractAndTranslateTextTask backgroundTask
synchronized int getMaxTextChars()
static boolean getUseOcrInTranslation()
void onTextDisplay(String text, ComponentOrientation orientation, int font)
String extractText(AbstractFile source, boolean ocrEnabled)
String getFileText(AbstractFile file)
void display(String text, ComponentOrientation direction, int font)
ExtractAndTranslateTextTask(AbstractFile file, boolean translateText)
Reader getTextExtractor(AbstractFile file, boolean ocrEnabled)
boolean isSupported(Node node)
final void actionPerformed(ActionEvent e)
static TextTranslationService getInstance()
synchronized boolean hasProvider()
synchronized static Logger getLogger(String name)
TextViewer createInstance()
int isPreferred(Node node)