diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED index 5cd40a900d..3efcade0f5 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED @@ -39,7 +39,7 @@ MediaFileViewer.title=Media MediaFileViewer.toolTip=Displays supported multimedia files (images, videos, audio) MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory. MediaViewImagePanel.errorLabel.text=Could not load file into Media View. -MediaViewImagePanel.externalViewerButton.text=Open in External Viewer +MediaViewImagePanel.externalViewerButton.text=Open in External Viewer Ctrl+E MediaViewVideoPanel.pauseButton.text=\u25ba MediaViewVideoPanel.progressLabel.text=00:00 MediaViewVideoPanel.infoLabel.text=info diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java index b98c350d68..b96e61e462 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java @@ -60,7 +60,7 @@ import org.sleuthkit.datamodel.AbstractFile; * Image viewer part of the Media View layered pane. Uses JavaFX to display the * image. */ -@NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer", +@NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer Ctrl+E", "MediaViewImagePanel.errorLabel.text=Could not load file into Media View.", "MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory."}) @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java index 29e289d67e..250b76cac7 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,6 +38,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction; /** * A DataResultTopComponent object is a NetBeans top component that provides @@ -100,7 +101,7 @@ public final class DataResultTopComponent extends TopComponent implements DataRe DataResultTopComponent resultViewTopComponent = new DataResultTopComponent(false, title, null, Collections.emptyList(), DataContentTopComponent.findInstance()); initInstance(description, node, childNodeCount, resultViewTopComponent); return resultViewTopComponent; - } + } /** * Creates a result view top component that provides multiple views of the @@ -147,7 +148,7 @@ public final class DataResultTopComponent extends TopComponent implements DataRe DataResultTopComponent resultViewTopComponent = new DataResultTopComponent(false, title, null, Collections.emptyList(), DataContentTopComponent.findInstance()); return resultViewTopComponent; } - + /** * Initializes a partially initialized result view top component. * @@ -248,6 +249,9 @@ public final class DataResultTopComponent extends TopComponent implements DataRe setName(title); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS getActionMap().put("addBookmarkTag", new AddBookmarkTagAction()); //NON-NLS + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ExternalViewerShortcutAction.EXTERNAL_VIEWER_SHORTCUT, "useExternalViewer"); //NON-NLS + + getActionMap().put("useExternalViewer", new ExternalViewerShortcutAction()); //NON-NLS putClientProperty(TopComponent.PROP_CLOSING_DISABLED, isMain); putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, true); putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, true); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java index 5af1d5c085..69e3787e99 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java @@ -22,6 +22,8 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.EnumSet; import java.util.List; import java.util.Objects; @@ -31,7 +33,6 @@ import org.openide.nodes.Node; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CasePreferences; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; @@ -87,6 +88,16 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable dataSources = tskCase.getDataSources(); + + Collections.sort(dataSources, new Comparator() { + @Override + public int compare(DataSource dataS1, DataSource dataS2) { + String dataS1Name = dataS1.getName().toLowerCase(); + String dataS2Name = dataS2.getName().toLowerCase(); + return dataS1Name.compareTo(dataS2Name); + } + }); + List keys = new ArrayList<>(); dataSources.forEach((datasource) -> { keys.add(new DataSourceGrouping(datasource)); @@ -140,4 +151,4 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable(Arrays.asList(content)); } + + Collections.sort(currentKeys, new Comparator() { + @Override + public int compare(Content content1, Content content2) { + String content1Name = content1.getName().toLowerCase(); + String content2Name = content2.getName().toLowerCase(); + return content1Name.compareTo(content2Name); + } + + }); + setKeys(currentKeys); } catch (TskCoreException | NoCurrentCaseException | TskDataException ex) { logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS @@ -165,4 +177,4 @@ public class DataSourcesNode extends DisplayableItemNode { NAME)); return sheet; } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java index 13e7ef34a5..81f69cfbbf 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java @@ -148,7 +148,7 @@ public class FileNode extends AbstractFsContentNode { @NbBundle.Messages({ "FileNode.getActions.viewFileInDir.text=View File in Directory", "FileNode.getActions.viewInNewWin.text=View in New Window", - "FileNode.getActions.openInExtViewer.text=Open in External Viewer", + "FileNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E", "FileNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash"}) public Action[] getActions(boolean context) { List actionsList = new ArrayList<>(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 0bdb1b5d9c..32c9acd3c1 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -52,7 +52,7 @@ ChangeViewAction.menuItem.view.string=String DataResultFilterNode.action.viewFileInDir.text=View File in Directory DataResultFilterNode.action.viewSrcFileInDir.text=View Source File in Directory DataResultFilterNode.action.viewInNewWin.text=View in New Window -DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer +DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer Ctrl+E DataResultFilterNode.action.searchFilesSameMd5.text=Search for files with the same MD5 hash DataResultFilterNode.action.viewInDir.text=View in Directory DirectoryTreeFilterNode.action.collapseAll.text=Collapse All diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED index 0a0e8a7be2..f12028c542 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties-MERGED @@ -11,6 +11,7 @@ ExternalViewerAction.actionPerformed.failure.open.url=Cannot open URL ExternalViewerAction.actionPerformed.failure.permission.message=Permission to open the file was denied. ExternalViewerAction.actionPerformed.failure.support.message=This platform (operating system) does not support opening a file in an editor this way. ExternalViewerAction.actionPerformed.failure.title=Open File Failure +ExternalViewerShortcutAction.title.text=Open in External Viewer Ctrl+E ExtractAction.noOpenCase.errMsg=No open case available. ExtractUnallocAction.imageError=Error extracting unallocated space from image ExtractUnallocAction.noFiles=No unallocated files found on volume @@ -80,7 +81,7 @@ ChangeViewAction.menuItem.view.string=String DataResultFilterNode.action.viewFileInDir.text=View File in Directory DataResultFilterNode.action.viewSrcFileInDir.text=View Source File in Directory DataResultFilterNode.action.viewInNewWin.text=View in New Window -DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer +DataResultFilterNode.action.openInExtViewer.text=Open in External Viewer Ctrl+E DataResultFilterNode.action.searchFilesSameMd5.text=Search for files with the same MD5 hash DataResultFilterNode.action.viewInDir.text=View in Directory DirectoryTreeFilterNode.action.collapseAll.text=Collapse All diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java index 3451b073a3..cecd709b1a 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerAction.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -35,6 +35,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.SlackFileNode; +import org.sleuthkit.datamodel.AbstractFile; /** * Extracts a File object to a temporary file in the case directory, and then @@ -44,18 +45,13 @@ import org.sleuthkit.autopsy.datamodel.SlackFileNode; public class ExternalViewerAction extends AbstractAction { private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName()); - private final org.sleuthkit.datamodel.AbstractFile fileObject; + private final AbstractFile fileObject; private String fileObjectExt; final static String[] EXECUTABLE_EXT = {".exe", ".dll", ".com", ".bat", ".msi", ".reg", ".scr", ".cmd"}; //NON-NLS - /** - * - * @param title Name of the action - * @param fileNode File to display - */ - public ExternalViewerAction(String title, Node fileNode) { + ExternalViewerAction(String title, AbstractFile file, boolean isSlackFile) { super(title); - this.fileObject = fileNode.getLookup().lookup(org.sleuthkit.datamodel.AbstractFile.class); + this.fileObject = file; long size = fileObject.getSize(); String fileName = fileObject.getName(); @@ -79,11 +75,20 @@ public class ExternalViewerAction extends AbstractAction { // find an application for files without an extension // or if file is executable (for security reasons) // Also skip slack files since their extension is the original extension + "-slack" - if (!(size > 0) || extPos == -1 || isExecutable || (fileNode instanceof SlackFileNode)) { + if (!(size > 0) || extPos == -1 || isExecutable || isSlackFile) { this.setEnabled(false); } } + /** + * + * @param title Name of the action + * @param fileNode File to display + */ + public ExternalViewerAction(String title, Node fileNode) { + this(title, fileNode.getLookup().lookup(org.sleuthkit.datamodel.AbstractFile.class), fileNode instanceof SlackFileNode); + } + @Override public void actionPerformed(ActionEvent e) { // Get the temp folder path of the case @@ -152,8 +157,8 @@ public class ExternalViewerAction extends AbstractAction { try { String localpath = file.getPath(); if (localpath.toLowerCase().contains("http")) { - String url_path = file.getPath().replaceAll("\\\\","/"); - Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/","//"))); + String url_path = file.getPath().replaceAll("\\\\", "/"); + Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/", "//"))); } else { Desktop.getDesktop().open(file); } @@ -183,24 +188,24 @@ public class ExternalViewerAction extends AbstractAction { Bundle.ExternalViewerAction_actionPerformed_failure_title(), JOptionPane.ERROR_MESSAGE); } catch (URISyntaxException ex) { - logger.log(Level.WARNING, "Could not open URL provided: " + file.getPath(), ex); - JOptionPane.showMessageDialog(null, - Bundle.ExternalViewerAction_actionPerformed_failure_open_url(), - Bundle.ExternalViewerAction_actionPerformed_failure_title(), - JOptionPane.ERROR_MESSAGE); + logger.log(Level.WARNING, "Could not open URL provided: " + file.getPath(), ex); + JOptionPane.showMessageDialog(null, + Bundle.ExternalViewerAction_actionPerformed_failure_open_url(), + Bundle.ExternalViewerAction_actionPerformed_failure_title(), + JOptionPane.ERROR_MESSAGE); } } } /** * Opens a URL using the default desktop browser - * - * @param path URL to open + * + * @param path URL to open */ public static void openURL(String path) { - String url_path = path.replaceAll("\\\\","/"); + String url_path = path.replaceAll("\\\\", "/"); try { - Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/","//"))); + Desktop.getDesktop().browse(new URI(url_path.replaceFirst("/", "//"))); } catch (IOException ex) { logger.log(Level.WARNING, "Could not find a viewer for the given URL: " + url_path, ex); //NON-NLS JOptionPane.showMessageDialog(null, @@ -226,11 +231,11 @@ public class ExternalViewerAction extends AbstractAction { Bundle.ExternalViewerAction_actionPerformed_failure_title(), JOptionPane.ERROR_MESSAGE); } catch (URISyntaxException ex) { - logger.log(Level.WARNING, "Could not open URL provided: " + url_path, ex); - JOptionPane.showMessageDialog(null, - Bundle.ExternalViewerAction_actionPerformed_failure_open_url(), - Bundle.ExternalViewerAction_actionPerformed_failure_title(), - JOptionPane.ERROR_MESSAGE); + logger.log(Level.WARNING, "Could not open URL provided: " + url_path, ex); + JOptionPane.showMessageDialog(null, + Bundle.ExternalViewerAction_actionPerformed_failure_open_url(), + Bundle.ExternalViewerAction_actionPerformed_failure_title(), + JOptionPane.ERROR_MESSAGE); } } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerShortcutAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerShortcutAction.java new file mode 100644 index 0000000000..8d50ceb046 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExternalViewerShortcutAction.java @@ -0,0 +1,57 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.directorytree; + +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Collection; +import java.util.HashSet; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.openide.util.NbBundle.Messages; +import org.openide.util.Utilities; +import org.sleuthkit.datamodel.AbstractFile; + +/** + * Extracts a File object to a temporary file in the case directory, and then + * tries to open it in the user's system with the default or user specified + * associated application. + */ +@Messages({"ExternalViewerShortcutAction.title.text=Open in External Viewer Ctrl+E"}) +public class ExternalViewerShortcutAction extends AbstractAction { + public static final KeyStroke EXTERNAL_VIEWER_SHORTCUT = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK); + + public ExternalViewerShortcutAction() { + super(Bundle.ExternalViewerShortcutAction_title_text()); + } + + @Override + public void actionPerformed(ActionEvent e) { + final Collection selectedFiles = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if (!selectedFiles.isEmpty()) { + for (AbstractFile file : selectedFiles){ + ExternalViewerAction action = new ExternalViewerAction(Bundle.ExternalViewerShortcutAction_title_text(), file, false); + if(action.isEnabled()){ + action.actionPerformed(e); + } + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index 2f6c6ed559..747152ee59 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -65,6 +65,7 @@ import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction; import org.sleuthkit.autopsy.timeline.actions.Back; import org.sleuthkit.autopsy.timeline.actions.Forward; import org.sleuthkit.autopsy.timeline.explorernodes.EventNode; @@ -261,7 +262,8 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS getActionMap().put("addBookmarkTag", new AddBookmarkTagAction()); //NON-NLS - + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ExternalViewerShortcutAction.EXTERNAL_VIEWER_SHORTCUT, "useExternalViewer"); //NON-NLS + getActionMap().put("useExternalViewer", new ExternalViewerShortcutAction()); //NON-NLS this.controller = controller; //create linked result and content views diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java index d5e4440ee6..159936ba4a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2018 Basis Technology Corp. + * Copyright 2013-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,6 +50,7 @@ import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Modality; import javax.annotation.concurrent.GuardedBy; +import javax.swing.JComponent; import javax.swing.SwingUtilities; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.apache.commons.lang3.ObjectUtils.notEqual; @@ -64,6 +65,7 @@ import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager; import org.sleuthkit.autopsy.imagegallery.gui.DataSourceCell; @@ -238,6 +240,8 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl public ImageGalleryTopComponent() { setName(Bundle.CTL_ImageGalleryTopComponent()); initComponents(); + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ExternalViewerShortcutAction.EXTERNAL_VIEWER_SHORTCUT, "useExternalViewer"); //NON-NLS + getActionMap().put("useExternalViewer", new ExternalViewerShortcutAction()); //NON-NLS } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenExternalViewerAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenExternalViewerAction.java index a698c22191..6e3543dc00 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenExternalViewerAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenExternalViewerAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,9 @@ package org.sleuthkit.autopsy.imagegallery.actions; import java.awt.event.ActionEvent; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyCodeCombination; +import javafx.scene.input.KeyCombination; import javax.swing.SwingUtilities; import org.controlsfx.control.action.Action; import org.openide.util.NbBundle; @@ -33,10 +36,11 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; * appropriate text and graphic */ @NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer", - "OpenExternalViewerAction.displayName=External Viewer"}) + "OpenExternalViewerAction.displayName=External Viewer"}) public class OpenExternalViewerAction extends Action { private static final Image EXTERNAL = new Image(OpenExternalViewerAction.class.getResource("/org/sleuthkit/autopsy/imagegallery/images/external.png").toExternalForm()); //NON-NLS + private static final KeyCombination EXTERNAL_VIEWER_SHORTCUT = new KeyCodeCombination(KeyCode.E, KeyCombination.CONTROL_DOWN); private static final ActionEvent ACTION_EVENT = new ActionEvent(OpenExternalViewerAction.class, ActionEvent.ACTION_PERFORMED, ""); //Swing ActionEvent //NOI18N public OpenExternalViewerAction(DrawableFile file) { @@ -49,9 +53,12 @@ public class OpenExternalViewerAction extends Action { ExternalViewerAction externalViewerAction = new ExternalViewerAction(Bundle.MediaViewImagePanel_externalViewerButton_text(), new FileNode(file.getAbstractFile())); setLongText(Bundle.MediaViewImagePanel_externalViewerButton_text()); - setEventHandler(actionEvent -> //fx ActionEvent + setEventHandler(actionEvent + -> //fx ActionEvent SwingUtilities.invokeLater(() -> externalViewerAction.actionPerformed(ACTION_EVENT)) ); setGraphic(new ImageView(EXTERNAL)); + setAccelerator(EXTERNAL_VIEWER_SHORTCUT); } + } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 67e6496584..11651a5db3 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -87,7 +87,7 @@ KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg=Keyword KeywordSearchEditListPanel.kwColName=Keyword KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list: KeywordSearchEditListPanel.addKeyword.title=New Keyword -KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer +KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer Ctrl+E KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the same MD5 hash KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list. diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 034e4355d3..f64794953f 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -122,7 +122,7 @@ KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg=Keyword KeywordSearchEditListPanel.kwColName=Keyword KeywordSearchEditListPanel.addKeyword.message=Add a new word to the keyword search list: KeywordSearchEditListPanel.addKeyword.title=New Keyword -KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer +KeywordSearchFilterNode.getFileActions.openExternViewActLbl=Open in External Viewer Ctrl+E KeywordSearchFilterNode.getFileActions.searchSameMd5=Search for files with the same MD5 hash KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=View in New Window KeywordSearchIngestModule.init.noKwInLstMsg=No keywords in keyword list.