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:
Richard Cordovano 2018-06-15 11:10:22 -04:00 committed by GitHub
commit e8b64f7870
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 553 additions and 16 deletions

View File

@ -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"

View File

@ -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",

View File

@ -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.

View File

@ -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"

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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);
}
}

View 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);
}
}
}

View File

@ -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.

View File

@ -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]);
}

View File

@ -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()]);
}

View File

@ -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);