mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Merge pull request #3840 from raman-bt/3866_tag_context_menu_reorder
3866 User defined tags appear first in tags menu
This commit is contained in:
commit
e8b64f7870
@ -37,8 +37,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Instances of this Action allow users to apply tags to blackboard artifacts.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"AddBlackboardArtifactTagAction.singularTagResult=Tag Result",
|
||||
"AddBlackboardArtifactTagAction.pluralTagResult=Tag Results",
|
||||
"AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag",
|
||||
"AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags",
|
||||
"# {0} - artifactName",
|
||||
"AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.",
|
||||
"AddBlackboardArtifactTagAction.taggingErr=Tagging Error"
|
||||
|
@ -38,8 +38,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Instances of this Action allow users to apply tags to content.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"AddContentTagAction.singularTagFile=Tag File",
|
||||
"AddContentTagAction.pluralTagFile=Tag Files",
|
||||
"AddContentTagAction.singularTagFile=Add File Tag",
|
||||
"AddContentTagAction.pluralTagFile=Add File Tags",
|
||||
"# {0} - fileName",
|
||||
"AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.",
|
||||
"AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag",
|
||||
|
@ -19,6 +19,8 @@
|
||||
package org.sleuthkit.autopsy.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
@ -92,6 +94,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
// Get the current set of tag names.
|
||||
Map<String, TagName> tagNamesMap = null;
|
||||
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||
try {
|
||||
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
||||
@ -101,6 +104,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
// Create a menu item for each of the existing and visible tags.
|
||||
// Selecting one of these menu items adds a tag with the associated tag name.
|
||||
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
||||
String tagDisplayName = entry.getKey();
|
||||
@ -114,15 +118,26 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
tagNameItem.addActionListener((ActionEvent e) -> {
|
||||
getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
|
||||
});
|
||||
|
||||
add(tagNameItem);
|
||||
|
||||
// Show custom tags before predefined tags in the menu
|
||||
if (standardTagNames.contains(tagDisplayName)) {
|
||||
standardTagMenuitems.add(tagNameItem);
|
||||
} else {
|
||||
add(tagNameItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getItemCount() > 0) {
|
||||
addSeparator();
|
||||
}
|
||||
|
||||
|
||||
standardTagMenuitems.forEach((menuItem) -> {
|
||||
add(menuItem);
|
||||
});
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Create a "Choose Tag and Comment..." menu item. Selecting this item initiates
|
||||
// a dialog that can be used to create or select a tag name with an
|
||||
// optional comment and adds a tag with the resulting name.
|
||||
|
@ -38,7 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* artifacts.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"DeleteBlackboardArtifactTagAction.deleteTag=Delete Tag",
|
||||
"DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s)",
|
||||
"# {0} - tagName",
|
||||
"DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
||||
"DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error"
|
||||
|
@ -37,7 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Instances of this Action allow users to delete tags applied to content.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"DeleteContentTagAction.deleteTag=Delete Tag",
|
||||
"DeleteContentTagAction.deleteTag=Remove Selected Tag(s)",
|
||||
"# {0} - tagName",
|
||||
"DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
||||
"DeleteContentTagAction.tagDelErr=Tag Deletion Error"
|
||||
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.actions;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.control.Alert;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* This Action allows users to replace a tag applied to blackboard
|
||||
* artifacts, with another tag
|
||||
*/
|
||||
public final class ReplaceBlackboardArtifactTagAction extends ReplaceTagAction<BlackboardArtifactTag> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ReplaceBlackboardArtifactTagAction.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// This class is a singleton to support multi-selection of nodes, since
|
||||
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||
private static ReplaceBlackboardArtifactTagAction instance;
|
||||
|
||||
public static synchronized ReplaceBlackboardArtifactTagAction getInstance() {
|
||||
if (null == instance) {
|
||||
instance = new ReplaceBlackboardArtifactTagAction();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ReplaceBlackboardArtifactTagAction() {
|
||||
super(MENU_TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the specified tag on the given artifact with the new one
|
||||
*
|
||||
* @param oldArtifactTag tag to be replaced
|
||||
* @param newTagName name of the tag to replace with
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"# {0} - old tag name",
|
||||
"# {1} - artifactID",
|
||||
"ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}."})
|
||||
@Override
|
||||
protected void replaceTag( BlackboardArtifactTag oldArtifactTag, TagName newTagName) {
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
TagsManager tagsManager;
|
||||
try {
|
||||
tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Error replacing artifact tag. No open case found.", ex); //NON-NLS
|
||||
Platform.runLater(()
|
||||
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceBlackboardArtifactTagAction_replaceTag_alert(oldArtifactTag.getName().getDisplayName(), oldArtifactTag.getArtifact().getArtifactID())).show()
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.log(Level.INFO, "Replacing tag {0} with tag {1} for artifact {2}", new Object[]{oldArtifactTag.getName().getDisplayName(), newTagName.getDisplayName(), oldArtifactTag.getContent().getName()}); //NON-NLS
|
||||
|
||||
tagsManager.deleteBlackboardArtifactTag(oldArtifactTag);
|
||||
tagsManager.addBlackboardArtifactTag(oldArtifactTag.getArtifact(), newTagName);
|
||||
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.SEVERE, "Error replacing artifact tag", tskCoreException); //NON-NLS
|
||||
Platform.runLater(()
|
||||
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceBlackboardArtifactTagAction_replaceTag_alert(oldArtifactTag.getName().getDisplayName(), oldArtifactTag.getArtifact().getArtifactID())).show()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
super.done();
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected exception while replacing artifact tag", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of tags selected by user to replace
|
||||
*
|
||||
* @return a list of tags
|
||||
*/
|
||||
@Override
|
||||
Collection<? extends BlackboardArtifactTag> getTagsToReplace() {
|
||||
return Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactTag.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.actions;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.control.Alert;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* This Action allow users to replace a content tag with another tag
|
||||
*/
|
||||
public final class ReplaceContentTagAction extends ReplaceTagAction<ContentTag> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ReplaceContentTagAction.class.getName());
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// This class is a singleton to support multi-selection of nodes, since
|
||||
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||
private static ReplaceContentTagAction instance;
|
||||
|
||||
public static synchronized ReplaceContentTagAction getInstance() {
|
||||
if (null == instance) {
|
||||
instance = new ReplaceContentTagAction();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ReplaceContentTagAction() {
|
||||
super(MENU_TEXT);
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - old tag name",
|
||||
"# {1} - content obj id",
|
||||
"ReplaceContentTagAction.replaceTag.alert=Unable to replace tag {0} for {1}."})
|
||||
@Override
|
||||
protected void replaceTag(ContentTag oldTag, TagName newTagName) {
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
TagsManager tagsManager;
|
||||
try {
|
||||
tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Error replacing artifact tag. No open case found.", ex); //NON-NLS
|
||||
Platform.runLater(()
|
||||
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceContentTagAction_replaceTag_alert(oldTag.getName().getDisplayName(), oldTag.getContent().getName())).show()
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.log(Level.INFO, "Replacing tag {0} with tag {1} for artifact {2}", new Object[]{oldTag.getName().getDisplayName(), newTagName.getDisplayName(), oldTag.getContent().getName()}); //NON-NLS
|
||||
|
||||
tagsManager.deleteContentTag(oldTag);
|
||||
tagsManager.addContentTag(oldTag.getContent(), newTagName);
|
||||
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.SEVERE, "Error replacing artifact tag", tskCoreException); //NON-NLS
|
||||
Platform.runLater(()
|
||||
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceContentTagAction_replaceTag_alert(oldTag.getName().getDisplayName(), oldTag.getContent().getName())).show()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
super.done();
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected exception while replacing content tag", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of content tags selected by user to replace
|
||||
*
|
||||
* @return a list of tags
|
||||
*/
|
||||
@Override
|
||||
Collection<? extends ContentTag> getTagsToReplace() {
|
||||
return Utilities.actionsGlobalContext().lookupAll(ContentTag.class);
|
||||
}
|
||||
|
||||
}
|
188
Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java
Normal file
188
Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Abstract class to define context action to replace a tag with another
|
||||
*
|
||||
* @param <T> tag type
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ReplaceTagAction.replaceTag=Replace Selected Tag(s) With"
|
||||
})
|
||||
abstract class ReplaceTagAction<T extends Tag> extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
protected static final String MENU_TEXT = NbBundle.getMessage(ReplaceTagAction.class,
|
||||
"ReplaceTagAction.replaceTag");
|
||||
|
||||
ReplaceTagAction(String menuText) {
|
||||
super(menuText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses of replaceTagAction should not override actionPerformed,
|
||||
* but instead override replaceTag.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("NoopMethodInAbstractClass")
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
}
|
||||
|
||||
protected String getActionDisplayName() {
|
||||
return MENU_TEXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to actually replace the selected tag with the given new tag
|
||||
*
|
||||
* @param oldTag
|
||||
* @param newTagName
|
||||
*/
|
||||
abstract protected void replaceTag(T oldTag, TagName newTagName);
|
||||
|
||||
/**
|
||||
* Returns elected tags which are to be replaced
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
abstract Collection<? extends T> getTagsToReplace();
|
||||
|
||||
|
||||
@Override
|
||||
public JMenuItem getPopupPresenter() {
|
||||
return new ReplaceTagMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instances of this class implement a context menu user interface for
|
||||
* selecting a tag name to replace the tag with
|
||||
*/
|
||||
private final class ReplaceTagMenu extends JMenu {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
ReplaceTagMenu() {
|
||||
super(getActionDisplayName());
|
||||
|
||||
final Collection<? extends T> selectedTags = getTagsToReplace();
|
||||
|
||||
// Get the current set of tag names.
|
||||
Map<String, TagName> tagNamesMap = null;
|
||||
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||
try {
|
||||
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
Logger.getLogger(ReplaceTagMenu.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||
}
|
||||
|
||||
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||
// Ideally we should'nt allow user to pick a replacement tag that's already been applied to an item
|
||||
// In the very least we don't allow them to pick the same tag as the one they are trying to replace
|
||||
Set<String> existingTagNames = new HashSet<>();
|
||||
if (!selectedTags.isEmpty()) {
|
||||
T firstTag = selectedTags.iterator().next();
|
||||
existingTagNames.add(firstTag.getName().getDisplayName());
|
||||
}
|
||||
|
||||
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
||||
String tagDisplayName = entry.getKey();
|
||||
String notableString = entry.getValue().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : "";
|
||||
JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString);
|
||||
// for the bookmark tag name only, added shortcut label
|
||||
if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) {
|
||||
tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT);
|
||||
}
|
||||
|
||||
// Add action to replace the tag
|
||||
tagNameItem.addActionListener((ActionEvent event) -> {
|
||||
selectedTags.forEach((oldtag) -> {
|
||||
replaceTag(oldtag, entry.getValue());
|
||||
});
|
||||
});
|
||||
|
||||
// Don't allow replacing a tag with same tag.
|
||||
if (existingTagNames.contains(tagDisplayName)) {
|
||||
tagNameItem.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
// Show custom tags before predefined tags in the menu
|
||||
if (standardTagNames.contains(tagDisplayName)) {
|
||||
standardTagMenuitems.add(tagNameItem);
|
||||
} else {
|
||||
add(tagNameItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags"));
|
||||
empty.setEnabled(false);
|
||||
add(empty);
|
||||
}
|
||||
|
||||
//
|
||||
if (this.getItemCount() > 0) {
|
||||
addSeparator();
|
||||
}
|
||||
standardTagMenuitems.forEach((menuItem) -> {
|
||||
add(menuItem);
|
||||
});
|
||||
|
||||
addSeparator();
|
||||
JMenuItem newTagMenuItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.newTag"));
|
||||
newTagMenuItem.addActionListener((ActionEvent event) -> {
|
||||
TagName newTagName = GetTagNameDialog.doDialog();
|
||||
if (null != newTagName) {
|
||||
selectedTags.forEach((oldtag) -> {
|
||||
replaceTag(oldtag, newTagName);
|
||||
});
|
||||
}
|
||||
});
|
||||
add(newTagMenuItem);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -121,6 +121,15 @@ public class TagsManager implements Closeable {
|
||||
return tagDisplayNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of names of standard/predefined tags
|
||||
*
|
||||
* @return list of predefined tag names
|
||||
*/
|
||||
public static List<String> getStandardTagNames() {
|
||||
return TagNameDefinition.getStandardTagNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a per case Autopsy service that manages the addition of
|
||||
* content and artifact tags to the case database.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2016 Basis Technology Corp.
|
||||
* Copyright 2013-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -28,7 +28,6 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||
@ -132,8 +131,8 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode {
|
||||
actions.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
|
||||
}
|
||||
actions.add(new ViewTaggedArtifactAction(BlackboardArtifactTagNode_viewSourceArtifact_text(), artifact));
|
||||
actions.addAll(DataModelActionsFactory.getActions(tag.getContent(), true));
|
||||
actions.add(DeleteBlackboardArtifactTagAction.getInstance());
|
||||
actions.addAll(DataModelActionsFactory.getActions(tag, true));
|
||||
|
||||
return actions.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -128,8 +127,9 @@ class ContentTagNode extends DisplayableItemNode {
|
||||
if (file != null) {
|
||||
actions.add(ViewFileInTimelineAction.createViewFileAction(file));
|
||||
}
|
||||
actions.addAll(DataModelActionsFactory.getActions(tag.getContent(), false));
|
||||
actions.add(DeleteContentTagAction.getInstance());
|
||||
|
||||
actions.addAll(DataModelActionsFactory.getActions(tag, false));
|
||||
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,12 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
@ -39,7 +43,9 @@ import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
import org.sleuthkit.datamodel.File;
|
||||
@ -351,6 +357,80 @@ public class DataModelActionsFactory {
|
||||
return actionsList;
|
||||
}
|
||||
|
||||
public static List<Action> getActions(ContentTag contentTag, boolean isArtifactSource) {
|
||||
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), contentTag.getContent()));
|
||||
final ContentTagNode tagNode = new ContentTagNode(contentTag);
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(new HashSearchAction(SEARCH_FOR_FILES_SAME_MD5, tagNode));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
|
||||
final Collection<AbstractFile> selectedFilesList =
|
||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||
if(selectedFilesList.size() == 1) {
|
||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||
}
|
||||
if(isArtifactSource) {
|
||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||
if(selectedArtifactsList.size() == 1) {
|
||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
actionsList.add(DeleteContentTagAction.getInstance());
|
||||
actionsList.add(ReplaceContentTagAction.getInstance());
|
||||
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actionsList;
|
||||
}
|
||||
|
||||
|
||||
public static List<Action> getActions(BlackboardArtifactTag artifactTag, boolean isArtifactSource) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), artifactTag.getContent()));
|
||||
final BlackboardArtifactTagNode tagNode = new BlackboardArtifactTagNode(artifactTag);
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
||||
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(new HashSearchAction(SEARCH_FOR_FILES_SAME_MD5, tagNode));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
|
||||
final Collection<AbstractFile> selectedFilesList =
|
||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||
if(selectedFilesList.size() == 1) {
|
||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||
}
|
||||
if(isArtifactSource) {
|
||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||
if(selectedArtifactsList.size() == 1) {
|
||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
actionsList.add(DeleteBlackboardArtifactTagAction.getInstance());
|
||||
actionsList.add(ReplaceBlackboardArtifactTagAction.getInstance());
|
||||
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actionsList;
|
||||
}
|
||||
|
||||
public static List<Action> getActions(Content content, boolean isArtifactSource) {
|
||||
if (content instanceof File) {
|
||||
return getActions((File) content, isArtifactSource);
|
||||
|
Loading…
x
Reference in New Issue
Block a user