mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-16 17:57:43 +00:00
fix bugs, validate ammount spinner,a dd View in Timeine action to a few more palces
This commit is contained in:
parent
9350a0fac7
commit
fe7daed3fc
@ -130,7 +130,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
try {
|
||||
AbstractFile c = findLinked(artifact);
|
||||
if (c != null) {
|
||||
actionsList.add(new ViewFileInTimelineAction(c, false));
|
||||
actionsList.add(ViewFileInTimelineAction.createViewFileAction(c));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
|
||||
@ -140,7 +140,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
//if this artifact has associated content, add the action to view the content in the timeline
|
||||
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||
if (null != file) {
|
||||
actionsList.add(new ViewFileInTimelineAction(file, true));
|
||||
actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
|
||||
}
|
||||
|
||||
return actionsList.toArray(new Action[actionsList.size()]);
|
||||
|
@ -27,6 +27,7 @@ import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
|
||||
@ -80,12 +81,13 @@ public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
|
||||
actions.add(null); // creates a menu separator
|
||||
}
|
||||
actions.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(), "DirectoryNode.viewInNewWin.text"), this));
|
||||
actions.add(ViewFileInTimelineAction.createViewFileAction(getContent()));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(ExtractAction.getInstance());
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(AddContentTagAction.getInstance());
|
||||
actions.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actions.toArray(new Action[0]);
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,7 +89,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
}
|
||||
actionsList.add(new NewWindowViewAction(Bundle.FileNode_getActions_viewInNewWin_text(), this));
|
||||
actionsList.add(new ExternalViewerAction(Bundle.FileNode_getActions_openInExtViewer_text(), this));
|
||||
actionsList.add(new ViewFileInTimelineAction(getContent(), false));
|
||||
actionsList.add(ViewFileInTimelineAction.createViewFileAction(getContent()));
|
||||
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
|
@ -47,8 +47,11 @@ import javafx.scene.control.TableView;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.util.StringConverter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
import org.controlsfx.validation.ValidationSupport;
|
||||
import org.controlsfx.validation.Validator;
|
||||
import org.joda.time.Interval;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -106,6 +109,7 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
ChronoField.HOUR_OF_DAY,
|
||||
ChronoField.MINUTE_OF_HOUR,
|
||||
ChronoField.SECOND_OF_MINUTE);
|
||||
private final ValidationSupport validationSupport;
|
||||
|
||||
/**
|
||||
* Common Private Constructor
|
||||
@ -114,6 +118,9 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
* @param eventIDS A List of eventIDs to present to the user to choose
|
||||
* from.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ShowInTimelineDialog.amountValidator.message=The entered amount must be parsable as a number.",
|
||||
"ShowInTimelineDialog.eventSelectionValidator.message=You must select an event."})
|
||||
private ShowInTimelineDialog(TimeLineController controller, List<Long> eventIDS) {
|
||||
this.controller = controller;
|
||||
|
||||
@ -135,6 +142,17 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
assert amountSpinner != null : "fx:id=\"amountsSpinner\" was not injected: check your FXML file 'ShowInTimelineDialog.fxml'.";
|
||||
assert unitComboBox != null : "fx:id=\"unitChoiceBox\" was not injected: check your FXML file 'ShowInTimelineDialog.fxml'.";
|
||||
|
||||
validationSupport = new ValidationSupport();
|
||||
validationSupport.registerValidator(amountSpinner.getEditor(), false, Validator.createPredicateValidator((String value) -> {
|
||||
try {
|
||||
Double.parseDouble(value);
|
||||
return true;
|
||||
} catch (NumberFormatException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}, Bundle.ShowInTimelineDialog_amountValidator_message()));
|
||||
|
||||
//configure dialog properties
|
||||
PromptDialogManager.setDialogIcons(this);
|
||||
|
||||
@ -148,6 +166,21 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
|
||||
///configure dialog controls
|
||||
amountSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 1000));
|
||||
amountSpinner.getValueFactory().setConverter(new StringConverter<Integer>() {
|
||||
@Override
|
||||
public String toString(Integer object) {
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer fromString(String string) {
|
||||
try {
|
||||
return Integer.valueOf(string);
|
||||
} catch (NumberFormatException ex) {
|
||||
return amountSpinner.getValue();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
unitComboBox.setButtonCell(new ChronoFieldListCell());
|
||||
unitComboBox.setCellFactory(comboBox -> new ChronoFieldListCell());
|
||||
@ -182,6 +215,8 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
chooseEventLabel.setManaged(false);
|
||||
eventTable.getSelectionModel().select(0);
|
||||
|
||||
getDialogPane().lookupButton(SHOW).disableProperty().bind(validationSupport.invalidProperty());
|
||||
|
||||
//set result converter that does not require selection.
|
||||
setResultConverter(buttonType -> {
|
||||
if (buttonType == SHOW) {
|
||||
@ -205,7 +240,7 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
|
||||
this(controller, controller.getEventsModel().getEventIDsForFile(file, false));
|
||||
|
||||
//require selection to enable show button
|
||||
getDialogPane().lookupButton(SHOW).disableProperty().bind(eventTable.getSelectionModel().selectedItemProperty().isNull());
|
||||
getDialogPane().lookupButton(SHOW).disableProperty().bind(validationSupport.invalidProperty().or(eventTable.getSelectionModel().selectedItemProperty().isNull()));
|
||||
|
||||
//set result converter that uses selection.
|
||||
setResultConverter(buttonType -> {
|
||||
|
@ -32,17 +32,24 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
public final class ViewFileInTimelineAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final AbstractFile file;
|
||||
|
||||
@NbBundle.Messages({"ViewFileInTimelineAction.fileSource.displayName=View File in Timeline... ",
|
||||
"ViewFileInTimelineAction.artifactSource.displayName=View Source File in Timeline... "})
|
||||
public ViewFileInTimelineAction(AbstractFile file, boolean isArtifactSource) {
|
||||
super(isArtifactSource
|
||||
? Bundle.ViewFileInTimelineAction_artifactSource_displayName()
|
||||
: Bundle.ViewFileInTimelineAction_fileSource_displayName());
|
||||
private ViewFileInTimelineAction(AbstractFile file, String displayName) {
|
||||
super(displayName);
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"ViewFileInTimelineAction.viewFile.displayName=View File in Timeline... "})
|
||||
public static ViewFileInTimelineAction createViewFileAction(AbstractFile file) {
|
||||
return new ViewFileInTimelineAction(file, Bundle.ViewFileInTimelineAction_viewFile_displayName());
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"ViewFileInTimelineAction.viewSourceFile.displayName=View Source File in Timeline... "})
|
||||
public static ViewFileInTimelineAction createViewSourceFileAction(AbstractFile file) {
|
||||
return new ViewFileInTimelineAction(file, Bundle.ViewFileInTimelineAction_viewSourceFile_displayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SystemAction.get(OpenTimelineAction.class).showFileInTimeline(file);
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.timeline.explorernodes;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -33,16 +34,19 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.SingleEvent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -107,20 +111,70 @@ public class EventNode extends DisplayableItemNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages({
|
||||
"EventNode.getAction.errorTitle=Error getting actions",
|
||||
"EventNode.getAction.linkedFileMessage=There was a problem getting actions for the selected result. "
|
||||
+ " The 'View File in Timeline' action will not be available."})
|
||||
public Action[] getActions(boolean context) {
|
||||
Action[] superActions = super.getActions(context);
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.addAll(Arrays.asList(superActions));
|
||||
|
||||
final Content content = getLookup().lookup(Content.class);
|
||||
final BlackboardArtifact artifact = getLookup().lookup(BlackboardArtifact.class);
|
||||
final AbstractFile sourceFile = getLookup().lookup(AbstractFile.class);
|
||||
|
||||
final List<Action> factoryActions = DataModelActionsFactory.getActions(content, artifact != null);
|
||||
/*
|
||||
* if this event is derived from an artifact, add actions to view the
|
||||
* source file and a "linked" file, if present.
|
||||
*/
|
||||
final BlackboardArtifact artifact = getLookup().lookup(BlackboardArtifact.class);
|
||||
if (artifact != null) {
|
||||
try {
|
||||
AbstractFile linkedfile = findLinked(artifact);
|
||||
if (linkedfile != null) {
|
||||
actionsList.add(ViewFileInTimelineAction.createViewFileAction(linkedfile));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
|
||||
MessageNotifyUtil.Notify.error(Bundle.EventNode_getAction_errorTitle(), Bundle.EventNode_getAction_linkedFileMessage());
|
||||
}
|
||||
|
||||
//if this event has associated content, add the action to view the content in the timeline
|
||||
if (null != sourceFile) {
|
||||
actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(sourceFile));
|
||||
}
|
||||
}
|
||||
|
||||
//get default actions for the file
|
||||
final List<Action> factoryActions = DataModelActionsFactory.getActions(sourceFile, artifact != null);
|
||||
|
||||
actionsList.addAll(factoryActions);
|
||||
return actionsList.toArray(new Action[actionsList.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* this code started as a cut and past of
|
||||
* DataResultFilterNode.GetPopupActionsDisplayableItemNodeVisitor.findLinked(BlackboardArtifactNode
|
||||
* ba)
|
||||
*
|
||||
*
|
||||
* @param artifact
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static private AbstractFile findLinked(BlackboardArtifact artifact) throws TskCoreException {
|
||||
|
||||
BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH_ID));
|
||||
|
||||
if (pathIDAttribute != null) {
|
||||
long contentID = pathIDAttribute.getValueLong();
|
||||
if (contentID != -1) {
|
||||
return artifact.getSleuthkitCase().getAbstractFileById(contentID);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
|
@ -356,7 +356,7 @@ class ListTimeline extends BorderPane {
|
||||
*/
|
||||
private void scrollTo(Integer index) {
|
||||
if (visibleEvents.contains(table.getItems().get(index)) == false) {
|
||||
table.scrollTo(index);
|
||||
table.scrollTo(index - visibleEvents.size() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,9 +111,13 @@ public class ListViewPane extends AbstractTimeLineView {
|
||||
|
||||
FilteredEventsModel eventsModel = getEventsModel();
|
||||
|
||||
Set<Long> selectedEventIDs;
|
||||
TimeLineController controller = getController();
|
||||
//grab the currently selected event
|
||||
Set<Long> selectedEventIDs = ImmutableSet.copyOf(getController().getSelectedEventIDs());
|
||||
|
||||
synchronized (controller) {
|
||||
selectedEventIDs = ImmutableSet.copyOf(controller.getSelectedEventIDs());
|
||||
}
|
||||
|
||||
//clear the chart and set the time range.
|
||||
resetView(eventsModel.getTimeRange());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user