mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into 6332-annotationViewer
This commit is contained in:
commit
3dce7f528b
@ -1563,11 +1563,12 @@ public class Case {
|
|||||||
*
|
*
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
* This should not be called from the event dispatch thread (EDT)
|
||||||
*
|
*
|
||||||
* @param newTag new ContentTag added
|
* @param newTag The added ContentTag.
|
||||||
* @param deletedTag Removed ContentTag
|
* @param deletedTagList List of ContentTags that were removed as a result
|
||||||
|
* of the addition of newTag.
|
||||||
*/
|
*/
|
||||||
public void notifyContentTagAdded(ContentTag newTag, ContentTag deletedTag) {
|
public void notifyContentTagAdded(ContentTag newTag, List<ContentTag> deletedTagList) {
|
||||||
eventPublisher.publish(new ContentTagAddedEvent(newTag, deletedTag));
|
eventPublisher.publish(new ContentTagAddedEvent(newTag, deletedTagList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1627,11 +1628,12 @@ public class Case {
|
|||||||
*
|
*
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
* This should not be called from the event dispatch thread (EDT)
|
||||||
*
|
*
|
||||||
* @param newTag new BlackboardArtifactTag added
|
* @param newTag The added ContentTag.
|
||||||
* @param removedTag The BlackboardArtifactTag that was removed.
|
* @param removedTagList List of ContentTags that were removed as a result
|
||||||
|
* of the addition of newTag.
|
||||||
*/
|
*/
|
||||||
public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, BlackboardArtifactTag removedTag) {
|
public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, List<BlackboardArtifactTag> removedTagList) {
|
||||||
eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(newTag, removedTag));
|
eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(newTag, removedTagList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
package org.sleuthkit.autopsy.casemodule.events;
|
package org.sleuthkit.autopsy.casemodule.events;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
@ -30,7 +32,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* Event sent when a black board artifact tag is added.
|
* Event sent when a black board artifact tag is added.
|
||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent<BlackboardArtifactTag> implements Serializable {
|
public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent<BlackboardArtifactTag, DeletedBlackboardArtifactTagInfo> implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -38,8 +40,8 @@ public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent<BlackboardArt
|
|||||||
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString(), newTag);
|
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString(), newTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlackBoardArtifactTagAddedEvent(BlackboardArtifactTag newTag, BlackboardArtifactTag removedTag) {
|
public BlackBoardArtifactTagAddedEvent(BlackboardArtifactTag newTag, List<BlackboardArtifactTag> removedTagList) {
|
||||||
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString(), newTag, (removedTag != null ? new DeletedBlackboardArtifactTagInfo(removedTag) : null));
|
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString(), newTag, (removedTagList != null ? getDeletedInfo(removedTagList) : null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,4 +56,24 @@ public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent<BlackboardArt
|
|||||||
BlackboardArtifactTag getTagByID() throws NoCurrentCaseException, TskCoreException {
|
BlackboardArtifactTag getTagByID() throws NoCurrentCaseException, TskCoreException {
|
||||||
return Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagByTagID(getTagID());
|
return Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagByTagID(getTagID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a list of DeletedContentTagInfo objects from a list of
|
||||||
|
* BlackboardArtifactTags.
|
||||||
|
*
|
||||||
|
* @param deletedTagList List of deleted ContentTags.
|
||||||
|
*
|
||||||
|
* @return List of DeletedContentTagInfo objects or empty list if
|
||||||
|
* deletedTagList was empty or null.
|
||||||
|
*/
|
||||||
|
private static List<DeletedBlackboardArtifactTagInfo> getDeletedInfo(List<BlackboardArtifactTag> deletedTagList) {
|
||||||
|
List<DeletedBlackboardArtifactTagInfo> deletedInfoList = new ArrayList<>();
|
||||||
|
if (deletedTagList != null) {
|
||||||
|
for (BlackboardArtifactTag tag : deletedTagList) {
|
||||||
|
deletedInfoList.add(new DeletedBlackboardArtifactTagInfo(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deletedInfoList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
package org.sleuthkit.autopsy.casemodule.events;
|
package org.sleuthkit.autopsy.casemodule.events;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
@ -30,7 +32,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* An event that is fired when a ContentTag is added.
|
* An event that is fired when a ContentTag is added.
|
||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
public class ContentTagAddedEvent extends TagAddedEvent<ContentTag> implements Serializable {
|
public class ContentTagAddedEvent extends TagAddedEvent<ContentTag, DeletedContentTagInfo> implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -38,8 +40,8 @@ public class ContentTagAddedEvent extends TagAddedEvent<ContentTag> implements S
|
|||||||
super(Case.Events.CONTENT_TAG_ADDED.toString(), newTag);
|
super(Case.Events.CONTENT_TAG_ADDED.toString(), newTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentTagAddedEvent(ContentTag newTag, ContentTag deletedTag) {
|
public ContentTagAddedEvent(ContentTag newTag, List<ContentTag> deletedTagList) {
|
||||||
super(Case.Events.CONTENT_TAG_ADDED.toString(), newTag, (deletedTag != null ? new DeletedContentTagInfo(deletedTag) : null));
|
super(Case.Events.CONTENT_TAG_ADDED.toString(), newTag, getDeletedInfo(deletedTagList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +52,26 @@ public class ContentTagAddedEvent extends TagAddedEvent<ContentTag> implements S
|
|||||||
* @throws NoCurrentCaseException
|
* @throws NoCurrentCaseException
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
ContentTag getTagByID() throws NoCurrentCaseException, TskCoreException {
|
ContentTag getTagByID() throws NoCurrentCaseException, TskCoreException {
|
||||||
return Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagByTagID(getTagID());
|
return Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagByTagID(getTagID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a list of DeletedContentTagInfo objects from a list of ContentTags.
|
||||||
|
*
|
||||||
|
* @param deletedTagList List of deleted ContentTags.
|
||||||
|
*
|
||||||
|
* @return List of DeletedContentTagInfo objects or empty list if deletedTagList was empty or null.
|
||||||
|
*/
|
||||||
|
private static List<DeletedContentTagInfo> getDeletedInfo(List<ContentTag> deletedTagList) {
|
||||||
|
List<DeletedContentTagInfo> deletedInfoList = new ArrayList<>();
|
||||||
|
if (deletedTagList != null) {
|
||||||
|
for (ContentTag tag : deletedTagList) {
|
||||||
|
deletedInfoList.add(new DeletedContentTagInfo(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deletedInfoList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
package org.sleuthkit.autopsy.casemodule.events;
|
package org.sleuthkit.autopsy.casemodule.events;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.TagDeletedEvent.DeletedTagInfo;
|
import org.sleuthkit.autopsy.casemodule.events.TagDeletedEvent.DeletedTagInfo;
|
||||||
@ -30,7 +32,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
/**
|
/**
|
||||||
* Base Class for events that are fired when a Tag is added
|
* Base Class for events that are fired when a Tag is added
|
||||||
*/
|
*/
|
||||||
abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Serializable {
|
abstract class TagAddedEvent<T extends Tag, V extends DeletedTagInfo<T>> extends AutopsyEvent implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -39,6 +41,8 @@ abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Seri
|
|||||||
* re-loaded from the database in getNewValue()
|
* re-loaded from the database in getNewValue()
|
||||||
*/
|
*/
|
||||||
private transient T tag;
|
private transient T tag;
|
||||||
|
|
||||||
|
private List<V> deletedTagInfoList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The id of the tag that was added. This will be used to re-load the
|
* The id of the tag that was added. This will be used to re-load the
|
||||||
@ -50,10 +54,19 @@ abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Seri
|
|||||||
this(propertyName, addedTag, null);
|
this(propertyName, addedTag, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
TagAddedEvent(String propertyName, T addedTag, DeletedTagInfo<T> deletedTagInfo) {
|
/**
|
||||||
super(propertyName, deletedTagInfo, null);
|
* Construct a TagAddedEvent.
|
||||||
|
*
|
||||||
|
* @param propertyName Name of property changing
|
||||||
|
* @param addedTag Instance of added tag.
|
||||||
|
* @param deletedTagInfoList List of tags deleted as a result of the
|
||||||
|
* addition of addedTag.
|
||||||
|
*/
|
||||||
|
TagAddedEvent(String propertyName, T addedTag, List<V> deletedTagInfoList) {
|
||||||
|
super(propertyName, deletedTagInfoList, null);
|
||||||
tag = addedTag;
|
tag = addedTag;
|
||||||
tagID = addedTag.getId();
|
tagID = addedTag.getId();
|
||||||
|
this.deletedTagInfoList = deletedTagInfoList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +86,7 @@ abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Seri
|
|||||||
public T getAddedTag() {
|
public T getAddedTag() {
|
||||||
return getNewValue();
|
return getNewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getNewValue() {
|
public T getNewValue() {
|
||||||
/**
|
/**
|
||||||
@ -95,6 +108,21 @@ abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Seri
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of tags that were removed as a result of the addition
|
||||||
|
* of the T.
|
||||||
|
*
|
||||||
|
* @return A list of removed tags or null if no tags were removed.
|
||||||
|
*/
|
||||||
|
public List<V> getDeletedTags() {
|
||||||
|
return deletedTagInfoList != null ? Collections.unmodifiableList(deletedTagInfoList) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getOldValue() {
|
||||||
|
return getDeletedTags();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* implementors should override this to lookup the appropriate kind of tag
|
* implementors should override this to lookup the appropriate kind of tag
|
||||||
|
@ -80,7 +80,7 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
|
|||||||
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_TWO_NAME, new TagNameDefinition(CATEGORY_TWO_NAME, "", TagName.HTML_COLOR.LIME, TskData.FileKnown.BAD));
|
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_TWO_NAME, new TagNameDefinition(CATEGORY_TWO_NAME, "", TagName.HTML_COLOR.LIME, TskData.FileKnown.BAD));
|
||||||
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_THREE_NAME, new TagNameDefinition(CATEGORY_THREE_NAME, "", TagName.HTML_COLOR.YELLOW, TskData.FileKnown.BAD));
|
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_THREE_NAME, new TagNameDefinition(CATEGORY_THREE_NAME, "", TagName.HTML_COLOR.YELLOW, TskData.FileKnown.BAD));
|
||||||
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FOUR_NAME, new TagNameDefinition(CATEGORY_FOUR_NAME, "", TagName.HTML_COLOR.PURPLE, TskData.FileKnown.UNKNOWN));
|
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FOUR_NAME, new TagNameDefinition(CATEGORY_FOUR_NAME, "", TagName.HTML_COLOR.PURPLE, TskData.FileKnown.UNKNOWN));
|
||||||
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FIVE_NAME, new TagNameDefinition(CATEGORY_FIVE_NAME, "", TagName.HTML_COLOR.SILVER, TskData.FileKnown.UNKNOWN));
|
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FIVE_NAME, new TagNameDefinition(CATEGORY_FIVE_NAME, "", TagName.HTML_COLOR.FUCHSIA, TskData.FileKnown.UNKNOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -481,7 +481,7 @@ public class TagsManager implements Closeable {
|
|||||||
try {
|
try {
|
||||||
Case currentCase = Case.getCurrentCaseThrows();
|
Case currentCase = Case.getCurrentCaseThrows();
|
||||||
|
|
||||||
currentCase.notifyContentTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags().get(0));
|
currentCase.notifyContentTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags());
|
||||||
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
throw new TskCoreException("Added a tag to a closed case", ex);
|
throw new TskCoreException("Added a tag to a closed case", ex);
|
||||||
@ -701,7 +701,7 @@ public class TagsManager implements Closeable {
|
|||||||
TaggingManager.BlackboardArtifactTagChange tagChange = caseDb.getTaggingManager().addArtifactTag(artifact, tagName, comment);
|
TaggingManager.BlackboardArtifactTagChange tagChange = caseDb.getTaggingManager().addArtifactTag(artifact, tagName, comment);
|
||||||
try {
|
try {
|
||||||
Case currentCase = Case.getCurrentCaseThrows();
|
Case currentCase = Case.getCurrentCaseThrows();
|
||||||
currentCase.notifyBlackBoardArtifactTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags().get(0));
|
currentCase.notifyBlackBoardArtifactTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags());
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
throw new TskCoreException("Added a tag to a closed case", ex);
|
throw new TskCoreException("Added a tag to a closed case", ex);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil;
|
||||||
@ -62,6 +63,11 @@ import org.sleuthkit.datamodel.Image;
|
|||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
|
||||||
|
import org.sleuthkit.datamodel.Account;
|
||||||
|
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
||||||
|
import org.sleuthkit.datamodel.CommunicationsUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for ingest events and update entries in the Central Repository
|
* Listen for ingest events and update entries in the Central Repository
|
||||||
@ -337,6 +343,94 @@ public class IngestEventsListener {
|
|||||||
event = evt;
|
event = evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically creates personas from all the TSK_CONTACT artifacts
|
||||||
|
* found in a data source.
|
||||||
|
*
|
||||||
|
* @param dataSource Data source that was just analyzed.
|
||||||
|
* @throws TskCoreException If there is any error getting contact
|
||||||
|
* artifacts from case database.
|
||||||
|
* @throws CentralRepoException If there is an error in creating
|
||||||
|
* personas in the Central Repo.
|
||||||
|
*/
|
||||||
|
private void autoGenerateContactPersonas(Content dataSource) throws TskCoreException, CentralRepoException {
|
||||||
|
|
||||||
|
Blackboard blackboard;
|
||||||
|
try {
|
||||||
|
blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
|
||||||
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all TSK_CONTACT artifacts in this data source.
|
||||||
|
List<BlackboardArtifact> contactArtifacts = blackboard.getArtifacts(TSK_CONTACT.getTypeID(), dataSource.getId());
|
||||||
|
for (BlackboardArtifact artifact : contactArtifacts) {
|
||||||
|
|
||||||
|
BlackboardAttribute nameAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME));
|
||||||
|
String personaName = (nameAttr != null) ? nameAttr.getValueString() : null;
|
||||||
|
|
||||||
|
// Get phone number and email attributes.
|
||||||
|
BlackboardAttribute phoneAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
|
||||||
|
BlackboardAttribute homePhoneAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME));
|
||||||
|
BlackboardAttribute mobilePhoneAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE));
|
||||||
|
BlackboardAttribute emailAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL));
|
||||||
|
|
||||||
|
Persona persona = personaFromContactAttribute(null, Account.Type.PHONE, phoneAttr, personaName);
|
||||||
|
persona = personaFromContactAttribute(persona, Account.Type.PHONE, homePhoneAttr, personaName);
|
||||||
|
persona = personaFromContactAttribute(persona, Account.Type.PHONE, mobilePhoneAttr, personaName);
|
||||||
|
personaFromContactAttribute(persona, Account.Type.EMAIL, emailAttr, personaName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets central repo account for the given attribute for a TSK_CONTACT
|
||||||
|
* artifact. Associates the given persona with that account. Creates a
|
||||||
|
* Persona, if one isn't provided.
|
||||||
|
*
|
||||||
|
* @param persona Persona to associate with the account. May be null, in
|
||||||
|
* which case a persona is created first.
|
||||||
|
* @param accountType Account type of account to be associated.
|
||||||
|
* @param attribute Attribute form which get the account id.
|
||||||
|
* @param personaName Persona name, if a persona needs to be created.
|
||||||
|
* @return Persona created or associated with the account.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error in normalizing the
|
||||||
|
* account id.
|
||||||
|
* @throws CentralRepoException If there is an erorr is getting the
|
||||||
|
* account or associating the persona with it.
|
||||||
|
*/
|
||||||
|
private Persona personaFromContactAttribute(Persona persona, Account.Type accountType, BlackboardAttribute attribute, String personaName) throws CentralRepoException, TskCoreException {
|
||||||
|
|
||||||
|
Persona personaToReturn = persona;
|
||||||
|
if (attribute != null) {
|
||||||
|
|
||||||
|
String accountId = attribute.getValueString();
|
||||||
|
if (CommunicationsUtils.isValidAccountId(accountType, accountId)) {
|
||||||
|
if (accountType == Account.Type.PHONE) {
|
||||||
|
accountId = CommunicationsUtils.normalizePhoneNum(accountId);
|
||||||
|
} else if (accountType == Account.Type.EMAIL) {
|
||||||
|
accountId = CommunicationsUtils.normalizeEmailAddress(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
CentralRepoAccount.CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountType.getTypeName());
|
||||||
|
CentralRepoAccount crAccount = CentralRepository.getInstance().getOrCreateAccount(crAccountType, accountId);
|
||||||
|
|
||||||
|
PersonaAccount personaAccount;
|
||||||
|
// If persona doesnt exist, create one
|
||||||
|
if (persona == null) {
|
||||||
|
personaAccount = Persona.createPersonaForAccount(personaName, "Auto generated contact persona", Persona.PersonaStatus.UNKNOWN, crAccount, "Found in contact book entry", Persona.Confidence.DERIVED);
|
||||||
|
personaToReturn = personaAccount.getPersona();
|
||||||
|
} else {
|
||||||
|
persona.addAccountToPersona(crAccount, "Found in contact book entry", Persona.Confidence.DERIVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return personaToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// clear the tracker to reduce memory usage
|
// clear the tracker to reduce memory usage
|
||||||
@ -411,6 +505,8 @@ public class IngestEventsListener {
|
|||||||
correlationDataSource.setSha256(imageSha256Hash);
|
correlationDataSource.setSha256(imageSha256Hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// automatically generate persona from contact artifacts.
|
||||||
|
autoGenerateContactPersonas(dataSource);
|
||||||
}
|
}
|
||||||
} catch (CentralRepoException ex) {
|
} catch (CentralRepoException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format(
|
LOGGER.log(Level.SEVERE, String.format(
|
||||||
|
@ -257,6 +257,6 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
|||||||
return waypointMostRecent;
|
return waypointMostRecent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return -1L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,6 +657,17 @@ public final class EventsModel {
|
|||||||
}
|
}
|
||||||
return postTagsDeleted(updatedEventIDs);
|
return postTagsDeleted(updatedEventIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the events model for a data source added event.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error reading model data from the
|
||||||
|
* case database.
|
||||||
|
*/
|
||||||
|
synchronized void handleDataSourceAdded() throws TskCoreException {
|
||||||
|
populateDataSourcesCache();
|
||||||
|
invalidateCaches(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the events model for an artifact tag deleted event and publishes
|
* Updates the events model for an artifact tag deleted event and publishes
|
||||||
@ -782,7 +793,6 @@ public final class EventsModel {
|
|||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
*/
|
*/
|
||||||
public synchronized void invalidateCaches(Collection<Long> updatedEventIDs) throws TskCoreException {
|
public synchronized void invalidateCaches(Collection<Long> updatedEventIDs) throws TskCoreException {
|
||||||
populateDataSourcesCache();
|
|
||||||
minEventTimeCache.invalidateAll();
|
minEventTimeCache.invalidateAll();
|
||||||
maxEventTimeCache.invalidateAll();
|
maxEventTimeCache.invalidateAll();
|
||||||
idsToEventsCache.invalidateAll(emptyIfNull(updatedEventIDs));
|
idsToEventsCache.invalidateAll(emptyIfNull(updatedEventIDs));
|
||||||
|
@ -783,7 +783,7 @@ public class TimeLineController {
|
|||||||
break;
|
break;
|
||||||
case DATA_SOURCE_ADDED:
|
case DATA_SOURCE_ADDED:
|
||||||
future = executor.submit(() -> {
|
future = executor.submit(() -> {
|
||||||
filteredEvents.invalidateCaches(null);
|
filteredEvents.handleDataSourceAdded();
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -79,6 +79,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
|||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TagSet;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
@ -107,6 +108,8 @@ public final class ImageGalleryController {
|
|||||||
Case.Events.CONTENT_TAG_DELETED,
|
Case.Events.CONTENT_TAG_DELETED,
|
||||||
Case.Events.DATA_SOURCE_DELETED
|
Case.Events.DATA_SOURCE_DELETED
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static final String CATEGORY_TAG_SET_PREFIX = "Project VIC";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is an image gallery controller per case. It is created during the
|
* There is an image gallery controller per case. It is created during the
|
||||||
@ -228,14 +231,16 @@ public final class ImageGalleryController {
|
|||||||
void startUp() throws TskCoreException {
|
void startUp() throws TskCoreException {
|
||||||
selectionModel = new FileIDSelectionModel(this);
|
selectionModel = new FileIDSelectionModel(this);
|
||||||
thumbnailCache = new ThumbnailCache(this);
|
thumbnailCache = new ThumbnailCache(this);
|
||||||
|
|
||||||
|
TagSet categoryTagSet = getCategoryTagSet();
|
||||||
/*
|
/*
|
||||||
* TODO (JIRA-5212): The next two lines need to be executed in this
|
* TODO (JIRA-5212): The next two lines need to be executed in this
|
||||||
* order. Why? This suggests there is some inappropriate coupling
|
* order. Why? This suggests there is some inappropriate coupling
|
||||||
* between the DrawableDB and GroupManager classes.
|
* between the DrawableDB and GroupManager classes.
|
||||||
*/
|
*/
|
||||||
groupManager = new GroupManager(this);
|
groupManager = new GroupManager(this);
|
||||||
drawableDB = DrawableDB.getDrawableDB(this);
|
drawableDB = DrawableDB.getDrawableDB(this, categoryTagSet);
|
||||||
categoryManager = new CategoryManager(this);
|
categoryManager = new CategoryManager(this, categoryTagSet);
|
||||||
tagsManager = new DrawableTagsManager(this);
|
tagsManager = new DrawableTagsManager(this);
|
||||||
tagsManager.registerListener(groupManager);
|
tagsManager.registerListener(groupManager);
|
||||||
tagsManager.registerListener(categoryManager);
|
tagsManager.registerListener(categoryManager);
|
||||||
@ -720,6 +725,28 @@ public final class ImageGalleryController {
|
|||||||
private static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws FileTypeDetector.FileTypeDetectorInitException {
|
private static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws FileTypeDetector.FileTypeDetectorInitException {
|
||||||
return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile);
|
return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the TagSet with the image gallery categories.
|
||||||
|
*
|
||||||
|
* @return Category TagSet.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private TagSet getCategoryTagSet() throws TskCoreException {
|
||||||
|
List<TagSet> tagSetList = getCaseDatabase().getTaggingManager().getTagSets();
|
||||||
|
if (tagSetList != null && !tagSetList.isEmpty()) {
|
||||||
|
for (TagSet set : tagSetList) {
|
||||||
|
if (set.getName().startsWith(CATEGORY_TAG_SET_PREFIX)) {
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we get to here the Project VIC Test set wasn't found;
|
||||||
|
throw new TskCoreException("Error loading Project VIC tag set: Tag set not found.");
|
||||||
|
} else {
|
||||||
|
throw new TskCoreException("Error loading Project VIC tag set: Tag set not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A listener for ingest module application events.
|
* A listener for ingest module application events.
|
||||||
|
@ -27,7 +27,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A task that updates one drawable file in the drawables database.
|
* A task that updates one drawable file in the drawable database.
|
||||||
*/
|
*/
|
||||||
class UpdateDrawableFileTask extends DrawableDbTask {
|
class UpdateDrawableFileTask extends DrawableDbTask {
|
||||||
|
|
||||||
@ -60,5 +60,5 @@ class UpdateDrawableFileTask extends DrawableDbTask {
|
|||||||
Logger.getLogger(UpdateDrawableFileTask.class.getName()).log(Level.SEVERE, "Error in update file task", ex); //NON-NLS
|
Logger.getLogger(UpdateDrawableFileTask.class.getName()).log(Level.SEVERE, "Error in update file task", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
package org.sleuthkit.autopsy.imagegallery.actions;
|
package org.sleuthkit.autopsy.imagegallery.actions;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -27,9 +30,10 @@ import java.util.Set;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javafx.collections.ObservableSet;
|
import javafx.collections.ObservableSet;
|
||||||
|
import javafx.embed.swing.SwingFXUtils;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Menu;
|
import javafx.scene.control.Menu;
|
||||||
import javafx.scene.control.MenuItem;
|
import javafx.scene.control.MenuItem;
|
||||||
import javafx.scene.image.ImageView;
|
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.input.KeyCodeCombination;
|
import javafx.scene.input.KeyCodeCombination;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -41,9 +45,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.DrawableDbTask;
|
import org.sleuthkit.autopsy.imagegallery.DrawableDbTask;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager;
|
||||||
@ -51,6 +53,7 @@ import org.sleuthkit.datamodel.ContentTag;
|
|||||||
import org.sleuthkit.datamodel.Tag;
|
import org.sleuthkit.datamodel.Tag;
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action that associates a drawable file with a Project Vic category.
|
* An action that associates a drawable file with a Project Vic category.
|
||||||
@ -62,24 +65,24 @@ public class CategorizeAction extends Action {
|
|||||||
|
|
||||||
private final ImageGalleryController controller;
|
private final ImageGalleryController controller;
|
||||||
private final UndoRedoManager undoManager;
|
private final UndoRedoManager undoManager;
|
||||||
private final DhsImageCategory cat;
|
|
||||||
private final Set<Long> selectedFileIDs;
|
private final Set<Long> selectedFileIDs;
|
||||||
private final Boolean createUndo;
|
private final Boolean createUndo;
|
||||||
|
private final TagName tagName;
|
||||||
|
|
||||||
public CategorizeAction(ImageGalleryController controller, DhsImageCategory cat, Set<Long> selectedFileIDs) {
|
public CategorizeAction(ImageGalleryController controller, TagName tagName, Set<Long> selectedFileIDs) {
|
||||||
this(controller, cat, selectedFileIDs, true);
|
this(controller, tagName, selectedFileIDs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CategorizeAction(ImageGalleryController controller, DhsImageCategory cat, Set<Long> selectedFileIDs, Boolean createUndo) {
|
private CategorizeAction(ImageGalleryController controller, TagName tagName, Set<Long> selectedFileIDs, Boolean createUndo) {
|
||||||
super(cat.getDisplayName());
|
super(tagName.getDisplayName());
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
this.undoManager = controller.getUndoManager();
|
this.undoManager = controller.getUndoManager();
|
||||||
this.cat = cat;
|
|
||||||
this.selectedFileIDs = selectedFileIDs;
|
this.selectedFileIDs = selectedFileIDs;
|
||||||
this.createUndo = createUndo;
|
this.createUndo = createUndo;
|
||||||
setGraphic(cat.getGraphic());
|
this.tagName = tagName;
|
||||||
|
setGraphic(getGraphic(tagName));
|
||||||
setEventHandler(actionEvent -> addCatToFiles(selectedFileIDs));
|
setEventHandler(actionEvent -> addCatToFiles(selectedFileIDs));
|
||||||
setAccelerator(new KeyCodeCombination(KeyCode.getKeyCode(Integer.toString(cat.getCategoryNumber()))));
|
setAccelerator(new KeyCodeCombination(KeyCode.getKeyCode(getCategoryNumberFromTagName(tagName))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static public Menu getCategoriesMenu(ImageGalleryController controller) {
|
static public Menu getCategoriesMenu(ImageGalleryController controller) {
|
||||||
@ -87,8 +90,18 @@ public class CategorizeAction extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final void addCatToFiles(Set<Long> ids) {
|
final void addCatToFiles(Set<Long> ids) {
|
||||||
Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{ids.toString(), cat.getDisplayName()}); //NON-NLS
|
Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{ids.toString(), tagName.getDisplayName()}); //NON-NLS
|
||||||
controller.queueDBTask(new CategorizeDrawableFileTask(ids, cat, createUndo));
|
controller.queueDBTask(new CategorizeDrawableFileTask(ids, tagName, createUndo));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCategoryNumberFromTagName(TagName tagName) {
|
||||||
|
String displayName = tagName.getDisplayName();
|
||||||
|
if (displayName.contains("CAT")) {
|
||||||
|
String[] split = displayName.split(":");
|
||||||
|
split = split[0].split("-");
|
||||||
|
return split[1];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,8 +117,8 @@ public class CategorizeAction extends Action {
|
|||||||
|
|
||||||
// Each category get an item in the sub-menu. Selecting one of these menu items adds
|
// Each category get an item in the sub-menu. Selecting one of these menu items adds
|
||||||
// a tag with the associated category.
|
// a tag with the associated category.
|
||||||
for (final DhsImageCategory cat : DhsImageCategory.values()) {
|
for (TagName tagName : controller.getCategoryManager().getCategories()) {
|
||||||
MenuItem categoryItem = ActionUtils.createMenuItem(new CategorizeAction(controller, cat, selected));
|
MenuItem categoryItem = ActionUtils.createMenuItem(new CategorizeAction(controller, tagName, selected));
|
||||||
getItems().add(categoryItem);
|
getItems().add(categoryItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,54 +137,39 @@ public class CategorizeAction extends Action {
|
|||||||
final Set<Long> fileIDs;
|
final Set<Long> fileIDs;
|
||||||
|
|
||||||
final boolean createUndo;
|
final boolean createUndo;
|
||||||
final DhsImageCategory cat;
|
final TagName catTagName;
|
||||||
|
|
||||||
CategorizeDrawableFileTask(Set<Long> fileIDs, @Nonnull DhsImageCategory cat, boolean createUndo) {
|
CategorizeDrawableFileTask(Set<Long> fileIDs, @Nonnull TagName catTagName, boolean createUndo) {
|
||||||
super();
|
super();
|
||||||
this.fileIDs = fileIDs;
|
this.fileIDs = fileIDs;
|
||||||
java.util.Objects.requireNonNull(cat);
|
java.util.Objects.requireNonNull(catTagName);
|
||||||
this.cat = cat;
|
this.catTagName = catTagName;
|
||||||
this.createUndo = createUndo;
|
this.createUndo = createUndo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final DrawableTagsManager tagsManager = controller.getTagsManager();
|
final DrawableTagsManager tagsManager = controller.getTagsManager();
|
||||||
final CategoryManager categoryManager = controller.getCategoryManager();
|
Map<Long, TagName> oldCats = new HashMap<>();
|
||||||
Map<Long, DhsImageCategory> oldCats = new HashMap<>();
|
|
||||||
TagName tagName = categoryManager.getTagName(cat);
|
|
||||||
for (long fileID : fileIDs) {
|
for (long fileID : fileIDs) {
|
||||||
try {
|
try {
|
||||||
DrawableFile file = controller.getFileFromID(fileID); //drawable db access
|
DrawableFile file = controller.getFileFromID(fileID); //drawable db access
|
||||||
if (createUndo) {
|
if (createUndo) {
|
||||||
DhsImageCategory oldCat = file.getCategory(); //drawable db access
|
TagName oldCatTagName = file.getCategory(); //drawable db access
|
||||||
TagName oldCatTagName = categoryManager.getTagName(oldCat);
|
if (false == catTagName.equals(oldCatTagName)) {
|
||||||
if (false == tagName.equals(oldCatTagName)) {
|
oldCats.put(fileID, oldCatTagName);
|
||||||
oldCats.put(fileID, oldCat);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ContentTag> fileTags = tagsManager.getContentTags(file);
|
final List<ContentTag> fileTags = tagsManager.getContentTags(file);
|
||||||
if (tagName == categoryManager.getTagName(DhsImageCategory.ZERO)) {
|
|
||||||
// delete all cat tags for cat-0
|
if (fileTags.stream()
|
||||||
fileTags.stream()
|
.map(Tag::getName)
|
||||||
.filter(tag -> CategoryManager.isCategoryTagName(tag.getName()))
|
.filter(tagName::equals)
|
||||||
.forEach((ct) -> {
|
.collect(Collectors.toList()).isEmpty()) {
|
||||||
try {
|
tagsManager.addContentTag(file, tagName, "");
|
||||||
tagsManager.deleteContentTag(ct);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Error removing old categories result", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
//add cat tag if no existing cat tag for that cat
|
|
||||||
if (fileTags.stream()
|
|
||||||
.map(Tag::getName)
|
|
||||||
.filter(tagName::equals)
|
|
||||||
.collect(Collectors.toList()).isEmpty()) {
|
|
||||||
tagsManager.addContentTag(file, tagName, "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error categorizing result", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error categorizing result", ex); //NON-NLS
|
||||||
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
|
||||||
@ -183,7 +181,7 @@ public class CategorizeAction extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (createUndo && oldCats.isEmpty() == false) {
|
if (createUndo && oldCats.isEmpty() == false) {
|
||||||
undoManager.addToUndo(new CategorizationChange(controller, cat, oldCats));
|
undoManager.addToUndo(new CategorizationChange(controller, catTagName, oldCats));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,14 +192,14 @@ public class CategorizeAction extends Action {
|
|||||||
@Immutable
|
@Immutable
|
||||||
private final class CategorizationChange implements UndoRedoManager.UndoableCommand {
|
private final class CategorizationChange implements UndoRedoManager.UndoableCommand {
|
||||||
|
|
||||||
private final DhsImageCategory newCategory;
|
private final TagName newTagNameCategory;
|
||||||
private final ImmutableMap<Long, DhsImageCategory> oldCategories;
|
private final ImmutableMap<Long, TagName> oldTagNameCategories;
|
||||||
private final ImageGalleryController controller;
|
private final ImageGalleryController controller;
|
||||||
|
|
||||||
CategorizationChange(ImageGalleryController controller, DhsImageCategory newCategory, Map<Long, DhsImageCategory> oldCategories) {
|
CategorizationChange(ImageGalleryController controller, TagName newTagNameCategory, Map<Long, TagName> oldTagNameCategories) {
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
this.newCategory = newCategory;
|
this.newTagNameCategory = newTagNameCategory;
|
||||||
this.oldCategories = ImmutableMap.copyOf(oldCategories);
|
this.oldTagNameCategories = ImmutableMap.copyOf(oldTagNameCategories);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,7 +208,7 @@ public class CategorizeAction extends Action {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
new CategorizeAction(controller, newCategory, this.oldCategories.keySet(), false)
|
new CategorizeAction(controller, newTagNameCategory, this.oldTagNameCategories.keySet(), false)
|
||||||
.handle(null);
|
.handle(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,10 +219,42 @@ public class CategorizeAction extends Action {
|
|||||||
@Override
|
@Override
|
||||||
public void undo() {
|
public void undo() {
|
||||||
|
|
||||||
for (Map.Entry<Long, DhsImageCategory> entry : oldCategories.entrySet()) {
|
for (Map.Entry<Long, TagName> entry : oldTagNameCategories.entrySet()) {
|
||||||
new CategorizeAction(controller, entry.getValue(), Collections.singleton(entry.getKey()), false)
|
new CategorizeAction(controller, entry.getValue(), Collections.singleton(entry.getKey()), false)
|
||||||
.handle(null);
|
.handle(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an BufferedImage to use as the icon for the given TagName.
|
||||||
|
*
|
||||||
|
* @param tagName The category TagName.
|
||||||
|
*
|
||||||
|
* @return TagName Icon BufferedImage.
|
||||||
|
*/
|
||||||
|
private BufferedImage getImageForTagName(TagName tagName) {
|
||||||
|
BufferedImage off_image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
Graphics2D g2 = off_image.createGraphics();
|
||||||
|
|
||||||
|
g2.setColor(java.awt.Color.decode(tagName.getColor().getRgbValue()));
|
||||||
|
g2.fillRect(0, 0, 16, 16);
|
||||||
|
|
||||||
|
g2.setColor(Color.BLACK);
|
||||||
|
g2.drawRect(0, 0, 16, 16);
|
||||||
|
return off_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Node which is a ImageView of the icon for the given TagName.
|
||||||
|
*
|
||||||
|
* @param tagname
|
||||||
|
*
|
||||||
|
* @return Node for use as the TagName menu item graphic.
|
||||||
|
*/
|
||||||
|
private Node getGraphic(TagName tagname) {
|
||||||
|
BufferedImage buff_image = getImageForTagName(tagname);
|
||||||
|
return new ImageView(SwingFXUtils.toFXImage(buff_image, null));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import java.util.logging.Level;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
||||||
import javafx.geometry.VPos;
|
import javafx.geometry.VPos;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonBar;
|
import javafx.scene.control.ButtonBar;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
@ -37,9 +38,9 @@ import javafx.scene.layout.VBox;
|
|||||||
import static org.apache.commons.lang.ObjectUtils.notEqual;
|
import static org.apache.commons.lang.ObjectUtils.notEqual;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +51,7 @@ public class CategorizeGroupAction extends CategorizeAction {
|
|||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(CategorizeGroupAction.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(CategorizeGroupAction.class.getName());
|
||||||
|
|
||||||
public CategorizeGroupAction(DhsImageCategory newCat, ImageGalleryController controller) {
|
public CategorizeGroupAction(TagName newCat, ImageGalleryController controller) {
|
||||||
super(controller, newCat, null);
|
super(controller, newCat, null);
|
||||||
setEventHandler(actionEvent -> {
|
setEventHandler(actionEvent -> {
|
||||||
controller.getViewState().getGroup().ifPresent(group -> {
|
controller.getViewState().getGroup().ifPresent(group -> {
|
||||||
@ -60,12 +61,12 @@ public class CategorizeGroupAction extends CategorizeAction {
|
|||||||
//if they have preveiously disabled the warning, just go ahead and apply categories.
|
//if they have preveiously disabled the warning, just go ahead and apply categories.
|
||||||
addCatToFiles(ImmutableSet.copyOf(fileIDs));
|
addCatToFiles(ImmutableSet.copyOf(fileIDs));
|
||||||
} else {
|
} else {
|
||||||
final Map<DhsImageCategory, Long> catCountMap = new HashMap<>();
|
final Map<TagName, Long> catCountMap = new HashMap<>();
|
||||||
|
|
||||||
for (Long fileID : fileIDs) {
|
for (Long fileID : fileIDs) {
|
||||||
try {
|
try {
|
||||||
DhsImageCategory category = controller.getFileFromID(fileID).getCategory();
|
TagName category = controller.getFileFromID(fileID).getCategory();
|
||||||
if (false == DhsImageCategory.ZERO.equals(category) && newCat.equals(category) == false) {
|
if (category != null && newCat.equals(category) == false) {
|
||||||
catCountMap.merge(category, 1L, Long::sum);
|
catCountMap.merge(category, 1L, Long::sum);
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
@ -90,18 +91,19 @@ public class CategorizeGroupAction extends CategorizeAction {
|
|||||||
"CategorizeGroupAction.fileCountMessage={0} with {1}",
|
"CategorizeGroupAction.fileCountMessage={0} with {1}",
|
||||||
"CategorizeGroupAction.dontShowAgain=Don't show this message again",
|
"CategorizeGroupAction.dontShowAgain=Don't show this message again",
|
||||||
"CategorizeGroupAction.fileCountHeader=Files in the following categories will have their categories overwritten: "})
|
"CategorizeGroupAction.fileCountHeader=Files in the following categories will have their categories overwritten: "})
|
||||||
private void showConfirmationDialog(final Map<DhsImageCategory, Long> catCountMap, DhsImageCategory newCat, ObservableList<Long> fileIDs) {
|
private void showConfirmationDialog(final Map<TagName, Long> catCountMap, TagName newCat, ObservableList<Long> fileIDs) {
|
||||||
|
|
||||||
ButtonType categorizeButtonType
|
ButtonType categorizeButtonType
|
||||||
= new ButtonType(Bundle.CategorizeGroupAction_OverwriteButton_text(), ButtonBar.ButtonData.APPLY);
|
= new ButtonType(Bundle.CategorizeGroupAction_OverwriteButton_text(), ButtonBar.ButtonData.APPLY);
|
||||||
|
|
||||||
VBox textFlow = new VBox();
|
VBox textFlow = new VBox();
|
||||||
|
|
||||||
for (Map.Entry<DhsImageCategory, Long> entry : catCountMap.entrySet()) {
|
for (Map.Entry<TagName, Long> entry : catCountMap.entrySet()) {
|
||||||
if (entry.getValue() > 0
|
|
||||||
&& notEqual(entry.getKey(), newCat)) {
|
if (entry != null && entry.getValue() > 0
|
||||||
|
&& notEqual(entry.getKey(), newCat)) {
|
||||||
Label label = new Label(Bundle.CategorizeGroupAction_fileCountMessage(entry.getValue(), entry.getKey().getDisplayName()),
|
Label label = new Label(Bundle.CategorizeGroupAction_fileCountMessage(entry.getValue(), entry.getKey().getDisplayName()),
|
||||||
entry.getKey().getGraphic());
|
getGraphic(entry.getKey()));
|
||||||
label.setContentDisplay(ContentDisplay.RIGHT);
|
label.setContentDisplay(ContentDisplay.RIGHT);
|
||||||
textFlow.getChildren().add(label);
|
textFlow.getChildren().add(label);
|
||||||
}
|
}
|
||||||
@ -127,4 +129,8 @@ public class CategorizeGroupAction extends CategorizeAction {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Node getGraphic(TagName tagName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,14 @@
|
|||||||
package org.sleuthkit.autopsy.imagegallery.actions;
|
package org.sleuthkit.autopsy.imagegallery.actions;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CategorizeSelectedFilesAction extends CategorizeAction {
|
public class CategorizeSelectedFilesAction extends CategorizeAction {
|
||||||
|
|
||||||
public CategorizeSelectedFilesAction(DhsImageCategory cat, ImageGalleryController controller) {
|
public CategorizeSelectedFilesAction(TagName cat, ImageGalleryController controller) {
|
||||||
super(controller, cat, null);
|
super(controller, cat, null);
|
||||||
setEventHandler(actionEvent ->
|
setEventHandler(actionEvent ->
|
||||||
addCatToFiles(controller.getSelectionModel().getSelected())
|
addCatToFiles(controller.getSelectionModel().getSelected())
|
||||||
|
@ -24,8 +24,11 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.eventbus.AsyncEventBus;
|
import com.google.common.eventbus.AsyncEventBus;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -33,11 +36,13 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent.DeletedContentTagInfo;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
import org.sleuthkit.datamodel.TagSet;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,8 +61,6 @@ public class CategoryManager {
|
|||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(CategoryManager.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(CategoryManager.class.getName());
|
||||||
|
|
||||||
private final ImageGalleryController controller;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the DrawableDB that backs the category counts cache. The counts are
|
* the DrawableDB that backs the category counts cache. The counts are
|
||||||
* initialized from this, and the counting of CAT-0 is always delegated to
|
* initialized from this, and the counting of CAT-0 is always delegated to
|
||||||
@ -65,6 +68,8 @@ public class CategoryManager {
|
|||||||
*/
|
*/
|
||||||
private final DrawableDB drawableDb;
|
private final DrawableDB drawableDb;
|
||||||
|
|
||||||
|
private final TagSet categoryTagSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to distribute CategoryChangeEvents
|
* Used to distribute CategoryChangeEvents
|
||||||
*/
|
*/
|
||||||
@ -79,32 +84,20 @@ public class CategoryManager {
|
|||||||
* the count related methods go through this cache, which loads initial
|
* the count related methods go through this cache, which loads initial
|
||||||
* values from the database if needed.
|
* values from the database if needed.
|
||||||
*/
|
*/
|
||||||
private final LoadingCache<DhsImageCategory, LongAdder> categoryCounts
|
private final LoadingCache<TagName, LongAdder> categoryCounts
|
||||||
= CacheBuilder.newBuilder().build(CacheLoader.from(this::getCategoryCountHelper));
|
= CacheBuilder.newBuilder().build(CacheLoader.from(this::getCategoryCountHelper));
|
||||||
/**
|
|
||||||
* cached TagNames corresponding to Categories, looked up from
|
|
||||||
* autopsyTagManager at initial request or if invalidated by case change.
|
|
||||||
*/
|
|
||||||
private final LoadingCache<DhsImageCategory, TagName> catTagNameMap
|
|
||||||
= CacheBuilder.newBuilder().build(new CacheLoader<DhsImageCategory, TagName>() {
|
|
||||||
@Override
|
|
||||||
public TagName load(DhsImageCategory cat) throws TskCoreException {
|
|
||||||
return getController().getTagsManager().getTagName(cat);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public CategoryManager(ImageGalleryController controller) {
|
public CategoryManager(ImageGalleryController controller, TagSet categoryTagSet) throws TskCoreException {
|
||||||
this.controller = controller;
|
|
||||||
this.drawableDb = controller.getDrawablesDatabase();
|
this.drawableDb = controller.getDrawablesDatabase();
|
||||||
|
this.categoryTagSet = categoryTagSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageGalleryController getController() {
|
public List<TagName> getCategories() {
|
||||||
return controller;
|
return Collections.unmodifiableList(getSortedTagNames(categoryTagSet.getTagNames()));
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized public void invalidateCaches() {
|
synchronized public void invalidateCaches() {
|
||||||
categoryCounts.invalidateAll();
|
categoryCounts.invalidateAll();
|
||||||
catTagNameMap.invalidateAll();
|
|
||||||
fireChange(Collections.emptyList(), null);
|
fireChange(Collections.emptyList(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,16 +108,8 @@ public class CategoryManager {
|
|||||||
*
|
*
|
||||||
* @return the number of files with the given Category
|
* @return the number of files with the given Category
|
||||||
*/
|
*/
|
||||||
synchronized public long getCategoryCount(DhsImageCategory cat) {
|
synchronized public long getCategoryCount(TagName tagName) {
|
||||||
if (cat == DhsImageCategory.ZERO) {
|
return categoryCounts.getUnchecked(tagName).sum();
|
||||||
// Keeping track of the uncategorized files is a bit tricky while ingest
|
|
||||||
// is going on, so always use the list of file IDs we already have along with the
|
|
||||||
// other category counts instead of trying to track it separately.
|
|
||||||
long allOtherCatCount = getCategoryCount(DhsImageCategory.ONE) + getCategoryCount(DhsImageCategory.TWO) + getCategoryCount(DhsImageCategory.THREE) + getCategoryCount(DhsImageCategory.FOUR) + getCategoryCount(DhsImageCategory.FIVE);
|
|
||||||
return drawableDb.getNumberOfImageFilesInList() - allOtherCatCount;
|
|
||||||
} else {
|
|
||||||
return categoryCounts.getUnchecked(cat).sum();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,10 +118,8 @@ public class CategoryManager {
|
|||||||
*
|
*
|
||||||
* @param cat the Category to increment
|
* @param cat the Category to increment
|
||||||
*/
|
*/
|
||||||
synchronized public void incrementCategoryCount(DhsImageCategory cat) {
|
synchronized public void incrementCategoryCount(TagName tagName) {
|
||||||
if (cat != DhsImageCategory.ZERO) {
|
categoryCounts.getUnchecked(tagName).increment();
|
||||||
categoryCounts.getUnchecked(cat).increment();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,10 +128,8 @@ public class CategoryManager {
|
|||||||
*
|
*
|
||||||
* @param cat the Category to decrement
|
* @param cat the Category to decrement
|
||||||
*/
|
*/
|
||||||
synchronized public void decrementCategoryCount(DhsImageCategory cat) {
|
synchronized public void decrementCategoryCount(TagName tagName) {
|
||||||
if (cat != DhsImageCategory.ZERO) {
|
categoryCounts.getUnchecked(tagName).decrement();
|
||||||
categoryCounts.getUnchecked(cat).decrement();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,14 +142,14 @@ public class CategoryManager {
|
|||||||
* @return a LongAdder whose value is set to the number of file with the
|
* @return a LongAdder whose value is set to the number of file with the
|
||||||
* given Category
|
* given Category
|
||||||
*/
|
*/
|
||||||
synchronized private LongAdder getCategoryCountHelper(DhsImageCategory cat) {
|
synchronized private LongAdder getCategoryCountHelper(TagName cat) {
|
||||||
LongAdder longAdder = new LongAdder();
|
LongAdder longAdder = new LongAdder();
|
||||||
longAdder.decrement();
|
longAdder.decrement();
|
||||||
try {
|
try {
|
||||||
longAdder.add(drawableDb.getCategoryCount(cat));
|
longAdder.add(drawableDb.getCategoryCount(cat));
|
||||||
longAdder.increment();
|
longAdder.increment();
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Case closed while getting files"); //NON-NLS
|
LOGGER.log(Level.WARNING, "Case closed while getting files", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
return longAdder;
|
return longAdder;
|
||||||
}
|
}
|
||||||
@ -178,8 +159,8 @@ public class CategoryManager {
|
|||||||
*
|
*
|
||||||
* @param fileIDs
|
* @param fileIDs
|
||||||
*/
|
*/
|
||||||
public void fireChange(Collection<Long> fileIDs, DhsImageCategory newCategory) {
|
public void fireChange(Collection<Long> fileIDs, TagName tagName) {
|
||||||
categoryEventBus.post(new CategoryChangeEvent(fileIDs, newCategory));
|
categoryEventBus.post(new CategoryChangeEvent(fileIDs, tagName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,68 +197,66 @@ public class CategoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the TagName used to store this Category in the main autopsy db.
|
* Returns true if the given TagName is a category tag.
|
||||||
*
|
*
|
||||||
* @return the TagName used for this Category
|
* @param tName TagName
|
||||||
|
*
|
||||||
|
* @return True if tName is a category tag.
|
||||||
*/
|
*/
|
||||||
synchronized public TagName getTagName(DhsImageCategory cat) {
|
public boolean isCategoryTagName(TagName tName) {
|
||||||
return catTagNameMap.getUnchecked(cat);
|
return categoryTagSet.getTagNames().contains(tName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given TagName is not a category tag.
|
||||||
|
*
|
||||||
|
* Keep for use in location were a reference to this function is passed.
|
||||||
|
*
|
||||||
|
* @param tName TagName
|
||||||
|
*
|
||||||
|
* @return True if the given tName is not a category tag.
|
||||||
|
*/
|
||||||
|
public boolean isNotCategoryTagName(TagName tName) {
|
||||||
|
return !isCategoryTagName(tName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DhsImageCategory categoryFromTagName(TagName tagName) {
|
/**
|
||||||
return DhsImageCategory.fromDisplayName(tagName.getDisplayName());
|
* Returns the category tag set.
|
||||||
}
|
*
|
||||||
|
* @return
|
||||||
public static boolean isCategoryTagName(TagName tName) {
|
*/
|
||||||
return DhsImageCategory.isCategoryName(tName.getDisplayName());
|
TagSet getCategorySet() {
|
||||||
}
|
return categoryTagSet;
|
||||||
|
|
||||||
public static boolean isNotCategoryTagName(TagName tName) {
|
|
||||||
return DhsImageCategory.isNotCategoryName(tName.getDisplayName());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void handleTagAdded(ContentTagAddedEvent event) {
|
public void handleTagAdded(ContentTagAddedEvent event) {
|
||||||
final ContentTag addedTag = event.getAddedTag();
|
final ContentTag addedTag = event.getAddedTag();
|
||||||
if (isCategoryTagName(addedTag.getName())) {
|
|
||||||
final DrawableTagsManager tagsManager = controller.getTagsManager();
|
|
||||||
try {
|
|
||||||
//remove old category tag(s) if necessary
|
|
||||||
for (ContentTag ct : tagsManager.getContentTags(addedTag.getContent())) {
|
|
||||||
if (ct.getId() != addedTag.getId()
|
|
||||||
&& CategoryManager.isCategoryTagName(ct.getName())) {
|
|
||||||
try {
|
|
||||||
tagsManager.deleteContentTag(ct);
|
|
||||||
} catch (TskCoreException tskException) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Failed to delete content tag. Unable to maintain categories in a consistent state.", tskException); //NON-NLS
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (TskCoreException tskException) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Failed to get content tags for content. Unable to maintain category in a consistent state.", tskException); //NON-NLS
|
|
||||||
}
|
|
||||||
DhsImageCategory newCat = CategoryManager.categoryFromTagName(addedTag.getName());
|
|
||||||
if (newCat != DhsImageCategory.ZERO) {
|
|
||||||
incrementCategoryCount(newCat);
|
|
||||||
}
|
|
||||||
|
|
||||||
fireChange(Collections.singleton(addedTag.getContent().getId()), newCat);
|
List<DeletedContentTagInfo> removedTags = event.getDeletedTags();
|
||||||
|
if (removedTags != null) {
|
||||||
|
for (DeletedContentTagInfo tagInfo : removedTags) {
|
||||||
|
handleDeletedInfo(tagInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCategoryTagName(addedTag.getName())) {
|
||||||
|
incrementCategoryCount(addedTag.getName());
|
||||||
|
fireChange(Collections.singleton(addedTag.getContent().getId()), addedTag.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void handleTagDeleted(ContentTagDeletedEvent event) {
|
public void handleTagDeleted(ContentTagDeletedEvent event) {
|
||||||
final ContentTagDeletedEvent.DeletedContentTagInfo deletedTagInfo = event.getDeletedTagInfo();
|
final ContentTagDeletedEvent.DeletedContentTagInfo deletedTagInfo = event.getDeletedTagInfo();
|
||||||
|
handleDeletedInfo(deletedTagInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDeletedInfo(DeletedContentTagInfo deletedTagInfo) {
|
||||||
TagName tagName = deletedTagInfo.getName();
|
TagName tagName = deletedTagInfo.getName();
|
||||||
if (isCategoryTagName(tagName)) {
|
if (isCategoryTagName(tagName)) {
|
||||||
|
decrementCategoryCount(tagName);
|
||||||
DhsImageCategory deletedCat = CategoryManager.categoryFromTagName(tagName);
|
|
||||||
if (deletedCat != DhsImageCategory.ZERO) {
|
|
||||||
decrementCategoryCount(deletedCat);
|
|
||||||
}
|
|
||||||
fireChange(Collections.singleton(deletedTagInfo.getContentID()), null);
|
fireChange(Collections.singleton(deletedTagInfo.getContentID()), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,16 +269,16 @@ public class CategoryManager {
|
|||||||
public static class CategoryChangeEvent {
|
public static class CategoryChangeEvent {
|
||||||
|
|
||||||
private final ImmutableSet<Long> fileIDs;
|
private final ImmutableSet<Long> fileIDs;
|
||||||
private final DhsImageCategory newCategory;
|
private final TagName tagName;
|
||||||
|
|
||||||
public CategoryChangeEvent(Collection<Long> fileIDs, DhsImageCategory newCategory) {
|
public CategoryChangeEvent(Collection<Long> fileIDs, TagName tagName) {
|
||||||
super();
|
super();
|
||||||
this.fileIDs = ImmutableSet.copyOf(fileIDs);
|
this.fileIDs = ImmutableSet.copyOf(fileIDs);
|
||||||
this.newCategory = newCategory;
|
this.tagName = tagName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DhsImageCategory getNewCategory() {
|
public TagName getNewCategory() {
|
||||||
return newCategory;
|
return tagName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -309,4 +288,18 @@ public class CategoryManager {
|
|||||||
return fileIDs;
|
return fileIDs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TagName> getSortedTagNames(List<TagName> tagNames) {
|
||||||
|
Comparator<TagName> compareByDisplayName = new Comparator<TagName>() {
|
||||||
|
@Override
|
||||||
|
public int compare(TagName tagName1, TagName tagName2) {
|
||||||
|
return tagName1.getDisplayName().compareTo(tagName2.getDisplayName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
List<TagName> sortedTagNames = new ArrayList<>(tagNames);
|
||||||
|
sortedTagNames.sort(compareByDisplayName);
|
||||||
|
|
||||||
|
return sortedTagNames;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.imagegallery.datamodel;
|
package org.sleuthkit.autopsy.imagegallery.datamodel;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -89,15 +88,17 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
|||||||
* //TODO: this has lead to awkward hard to maintain code, and little
|
* //TODO: this has lead to awkward hard to maintain code, and little
|
||||||
* advantage. move categories into DrawableDB?
|
* advantage. move categories into DrawableDB?
|
||||||
*/
|
*/
|
||||||
public final static DrawableAttribute<DhsImageCategory> CATEGORY
|
public final static DrawableAttribute<TagName> CATEGORY
|
||||||
= new DrawableAttribute<DhsImageCategory>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
|
= new DrawableAttribute<TagName>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
|
||||||
false,
|
false,
|
||||||
"category-icon.png", //NON-NLS
|
"category-icon.png", //NON-NLS
|
||||||
f -> Collections.singleton(f.getCategory())) {
|
f -> Collections.singleton(f.getCategory())) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node getGraphicForValue(DhsImageCategory val) {
|
public Node getGraphicForValue(TagName val) {
|
||||||
return val.getGraphic();
|
|
||||||
|
return null;
|
||||||
|
//return val.getGraphic();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -235,9 +236,13 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
|||||||
.filter(value -> (value != null && value.toString().isEmpty() == false))
|
.filter(value -> (value != null && value.toString().isEmpty() == false))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
/* There is a catch-all here because the code in the try block executes third-party
|
/*
|
||||||
library calls that throw unchecked exceptions. See JIRA-5144, where an IllegalStateException
|
* There is a catch-all here because the code in the try block
|
||||||
was thrown because a file's MIME type was incorrectly identified as a picture type. */
|
* executes third-party library calls that throw unchecked
|
||||||
|
* exceptions. See JIRA-5144, where an IllegalStateException was
|
||||||
|
* thrown because a file's MIME type was incorrectly identified as a
|
||||||
|
* picture type.
|
||||||
|
*/
|
||||||
logger.log(Level.WARNING, "Exception while getting image attributes", ex); //NON-NLS
|
logger.log(Level.WARNING, "Exception while getting image attributes", ex); //NON-NLS
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,9 @@ import java.util.logging.Level;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
import javax.annotation.concurrent.GuardedBy;
|
||||||
import javax.swing.SortOrder;
|
import javax.swing.SortOrder;
|
||||||
import static org.apache.commons.lang3.ObjectUtils.notEqual;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.FileTypeUtils;
|
import org.sleuthkit.autopsy.imagegallery.FileTypeUtils;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule;
|
||||||
@ -80,6 +78,7 @@ import org.sleuthkit.datamodel.TskDataException;
|
|||||||
import org.sleuthkit.datamodel.VersionNumber;
|
import org.sleuthkit.datamodel.VersionNumber;
|
||||||
import org.sqlite.SQLiteJDBCLoader;
|
import org.sqlite.SQLiteJDBCLoader;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import org.sleuthkit.datamodel.TagSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to the image gallery database and selected tables in the case
|
* Provides access to the image gallery database and selected tables in the case
|
||||||
@ -250,7 +249,7 @@ public final class DrawableDB {
|
|||||||
* could not be correctly initialized for Image
|
* could not be correctly initialized for Image
|
||||||
* Gallery use.
|
* Gallery use.
|
||||||
*/
|
*/
|
||||||
private DrawableDB(Path dbPath, ImageGalleryController controller) throws IOException, SQLException, TskCoreException {
|
private DrawableDB(Path dbPath, ImageGalleryController controller, TagSet standardCategories) throws IOException, SQLException, TskCoreException {
|
||||||
this.dbPath = dbPath;
|
this.dbPath = dbPath;
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
caseDb = this.controller.getCaseDatabase();
|
caseDb = this.controller.getCaseDatabase();
|
||||||
@ -259,7 +258,7 @@ public final class DrawableDB {
|
|||||||
dbWriteLock();
|
dbWriteLock();
|
||||||
try {
|
try {
|
||||||
con = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toString()); //NON-NLS
|
con = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toString()); //NON-NLS
|
||||||
if (!initializeDBSchema() || !upgradeDBSchema() || !prepareStatements() || !initializeStandardGroups() || !removeDeletedDataSources() || !initializeImageList()) {
|
if (!initializeDBSchema() || !upgradeDBSchema() || !prepareStatements() || !initializeStandardGroups(standardCategories) || !removeDeletedDataSources() || !initializeImageList()) {
|
||||||
close();
|
close();
|
||||||
throw new TskCoreException("Failed to initialize drawables database for Image Gallery use"); //NON-NLS
|
throw new TskCoreException("Failed to initialize drawables database for Image Gallery use"); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -297,12 +296,13 @@ public final class DrawableDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initializeStandardGroups() {
|
private boolean initializeStandardGroups(TagSet standardCategories) {
|
||||||
CaseDbTransaction caseDbTransaction = null;
|
CaseDbTransaction caseDbTransaction = null;
|
||||||
try {
|
try {
|
||||||
caseDbTransaction = caseDb.beginTransaction();
|
caseDbTransaction = caseDb.beginTransaction();
|
||||||
for (DhsImageCategory cat : DhsImageCategory.values()) {
|
|
||||||
insertGroup(cat.getDisplayName(), DrawableAttribute.CATEGORY, caseDbTransaction);
|
for(TagName tagName: standardCategories.getTagNames()) {
|
||||||
|
insertGroup(tagName.getDisplayName(), DrawableAttribute.CATEGORY, caseDbTransaction);
|
||||||
}
|
}
|
||||||
caseDbTransaction.commit();
|
caseDbTransaction.commit();
|
||||||
return true;
|
return true;
|
||||||
@ -466,7 +466,7 @@ public final class DrawableDB {
|
|||||||
*
|
*
|
||||||
* @throws org.sleuthkit.datamodel.TskCoreException
|
* @throws org.sleuthkit.datamodel.TskCoreException
|
||||||
*/
|
*/
|
||||||
public static DrawableDB getDrawableDB(ImageGalleryController controller) throws TskCoreException {
|
public static DrawableDB getDrawableDB(ImageGalleryController controller, TagSet standardCategories) throws TskCoreException {
|
||||||
Path dbPath = ImageGalleryModule.getModuleOutputDir(controller.getCase()).resolve("drawable.db");
|
Path dbPath = ImageGalleryModule.getModuleOutputDir(controller.getCase()).resolve("drawable.db");
|
||||||
try {
|
try {
|
||||||
deleteDatabaseIfOlderVersion(dbPath);
|
deleteDatabaseIfOlderVersion(dbPath);
|
||||||
@ -477,14 +477,14 @@ public final class DrawableDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new DrawableDB(dbPath, controller);
|
return new DrawableDB(dbPath, controller, standardCategories);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new TskCoreException("Failed to create drawables database directory", ex); //NON-NLS
|
throw new TskCoreException("Failed to create drawables database directory", ex); //NON-NLS
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new TskCoreException("Failed to create/open the drawables database", ex); //NON-NLS
|
throw new TskCoreException("Failed to create/open the drawables database", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the specified table exists in Drawable DB
|
* Checks if the specified table exists in Drawable DB
|
||||||
*
|
*
|
||||||
@ -2068,7 +2068,7 @@ public final class DrawableDB {
|
|||||||
case MIME_TYPE:
|
case MIME_TYPE:
|
||||||
return groupManager.getFileIDsWithMimeType((String) groupKey.getValue());
|
return groupManager.getFileIDsWithMimeType((String) groupKey.getValue());
|
||||||
case CATEGORY:
|
case CATEGORY:
|
||||||
return groupManager.getFileIDsWithCategory((DhsImageCategory) groupKey.getValue());
|
return groupManager.getFileIDsWithCategory((TagName) groupKey.getValue());
|
||||||
case TAGS:
|
case TAGS:
|
||||||
return groupManager.getFileIDsWithTag((TagName) groupKey.getValue());
|
return groupManager.getFileIDsWithTag((TagName) groupKey.getValue());
|
||||||
}
|
}
|
||||||
@ -2269,9 +2269,8 @@ public final class DrawableDB {
|
|||||||
*
|
*
|
||||||
* @return the number of the with the given category
|
* @return the number of the with the given category
|
||||||
*/
|
*/
|
||||||
public long getCategoryCount(DhsImageCategory cat) {
|
public long getCategoryCount(TagName tagName) {
|
||||||
try {
|
try {
|
||||||
TagName tagName = controller.getTagsManager().getTagName(cat);
|
|
||||||
if (nonNull(tagName)) {
|
if (nonNull(tagName)) {
|
||||||
return caseDb.getContentTagsByTagName(tagName).stream()
|
return caseDb.getContentTagsByTagName(tagName).stream()
|
||||||
.map(ContentTag::getContent)
|
.map(ContentTag::getContent)
|
||||||
@ -2280,7 +2279,7 @@ public final class DrawableDB {
|
|||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
logger.log(Level.WARNING, "Case closed while getting files"); //NON-NLS
|
logger.log(Level.WARNING, "Case closed while getting files", ex); //NON-NLS
|
||||||
} catch (TskCoreException ex1) {
|
} catch (TskCoreException ex1) {
|
||||||
logger.log(Level.SEVERE, "Failed to get content tags by tag name.", ex1); //NON-NLS
|
logger.log(Level.SEVERE, "Failed to get content tags by tag name.", ex1); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -2314,7 +2313,6 @@ public final class DrawableDB {
|
|||||||
DrawableTagsManager tagsManager = controller.getTagsManager();
|
DrawableTagsManager tagsManager = controller.getTagsManager();
|
||||||
|
|
||||||
String catTagNameIDs = tagsManager.getCategoryTagNames().stream()
|
String catTagNameIDs = tagsManager.getCategoryTagNames().stream()
|
||||||
.filter(tagName -> notEqual(tagName.getDisplayName(), DhsImageCategory.ZERO.getDisplayName()))
|
|
||||||
.map(TagName::getId)
|
.map(TagName::getId)
|
||||||
.map(Object::toString)
|
.map(Object::toString)
|
||||||
.collect(Collectors.joining(",", "(", ")"));
|
.collect(Collectors.joining(",", "(", ")"));
|
||||||
|
@ -40,8 +40,8 @@ import org.apache.commons.lang3.text.WordUtils;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.FileTypeUtils;
|
import org.sleuthkit.autopsy.imagegallery.FileTypeUtils;
|
||||||
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -94,15 +94,19 @@ public abstract class DrawableFile {
|
|||||||
|
|
||||||
private final SimpleBooleanProperty analyzed;
|
private final SimpleBooleanProperty analyzed;
|
||||||
|
|
||||||
private final SimpleObjectProperty<DhsImageCategory> category = new SimpleObjectProperty<>(null);
|
private final SimpleObjectProperty<TagName> categoryTagName = new SimpleObjectProperty<>(null);
|
||||||
|
|
||||||
private String make;
|
private String make;
|
||||||
|
|
||||||
private String model;
|
private String model;
|
||||||
|
|
||||||
|
private final CategoryManager categoryManager;
|
||||||
|
|
||||||
protected DrawableFile(AbstractFile file, Boolean analyzed) {
|
protected DrawableFile(AbstractFile file, Boolean analyzed) {
|
||||||
this.analyzed = new SimpleBooleanProperty(analyzed);
|
this.analyzed = new SimpleBooleanProperty(analyzed);
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
|
categoryManager = ImageGalleryController.getController(Case.getCurrentCase()).getCategoryManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isVideo();
|
public abstract boolean isVideo();
|
||||||
@ -229,32 +233,30 @@ public abstract class DrawableFile {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCategory(DhsImageCategory category) {
|
public TagName getCategory() {
|
||||||
categoryProperty().set(category);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public DhsImageCategory getCategory() {
|
|
||||||
updateCategory();
|
updateCategory();
|
||||||
return category.get();
|
return categoryTagName.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleObjectProperty<DhsImageCategory> categoryProperty() {
|
public SimpleObjectProperty<TagName> categoryProperty() {
|
||||||
return category;
|
return categoryTagName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the category property to the most severe one found
|
* Update the category property.
|
||||||
*/
|
*/
|
||||||
private void updateCategory() {
|
private void updateCategory() {
|
||||||
try {
|
try {
|
||||||
category.set(getContentTags().stream()
|
List<ContentTag> contentTags = getContentTags();
|
||||||
.map(Tag::getName).filter(CategoryManager::isCategoryTagName)
|
TagName tag = null;
|
||||||
.map(TagName::getDisplayName)
|
for (ContentTag ct : contentTags) {
|
||||||
.map(DhsImageCategory::fromDisplayName)
|
TagName tagName = ct.getName();
|
||||||
.sorted().findFirst() //sort by severity and take the first
|
if (categoryManager.isCategoryTagName(tagName)) {
|
||||||
.orElse(DhsImageCategory.ZERO)
|
tag = tagName;
|
||||||
);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
categoryTagName.set(tag);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.WARNING, "problem looking up category for " + this.getContentPathSafe(), ex); //NON-NLS
|
LOGGER.log(Level.WARNING, "problem looking up category for " + this.getContentPathSafe(), ex); //NON-NLS
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
|
@ -20,10 +20,11 @@ package org.sleuthkit.autopsy.imagegallery.datamodel;
|
|||||||
|
|
||||||
import com.google.common.eventbus.AsyncEventBus;
|
import com.google.common.eventbus.AsyncEventBus;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
@ -33,7 +34,6 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
@ -54,10 +54,16 @@ public final class DrawableTagsManager {
|
|||||||
private static final Image BOOKMARK_IMAGE = new Image("/org/sleuthkit/autopsy/images/star-bookmark-icon-16.png");
|
private static final Image BOOKMARK_IMAGE = new Image("/org/sleuthkit/autopsy/images/star-bookmark-icon-16.png");
|
||||||
|
|
||||||
private final TagsManager autopsyTagsManager;
|
private final TagsManager autopsyTagsManager;
|
||||||
/** The tag name corresponding to the "built-in" tag "Follow Up" */
|
/**
|
||||||
|
* The tag name corresponding to the "built-in" tag "Follow Up"
|
||||||
|
*/
|
||||||
private final TagName followUpTagName;
|
private final TagName followUpTagName;
|
||||||
private final TagName bookmarkTagName;
|
private final TagName bookmarkTagName;
|
||||||
|
|
||||||
|
private final ImageGalleryController controller;
|
||||||
|
|
||||||
|
private final Comparator<TagName> compareByDisplayName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to distribute TagsChangeEvents
|
* Used to distribute TagsChangeEvents
|
||||||
*/
|
*/
|
||||||
@ -74,6 +80,14 @@ public final class DrawableTagsManager {
|
|||||||
this.autopsyTagsManager = controller.getCase().getServices().getTagsManager();
|
this.autopsyTagsManager = controller.getCase().getServices().getTagsManager();
|
||||||
followUpTagName = getTagName(Bundle.DrawableTagsManager_followUp());
|
followUpTagName = getTagName(Bundle.DrawableTagsManager_followUp());
|
||||||
bookmarkTagName = getTagName(Bundle.DrawableTagsManager_bookMark());
|
bookmarkTagName = getTagName(Bundle.DrawableTagsManager_bookMark());
|
||||||
|
this.controller = controller;
|
||||||
|
|
||||||
|
compareByDisplayName = new Comparator<TagName>() {
|
||||||
|
@Override
|
||||||
|
public int compare(TagName tagName1, TagName tagName2) {
|
||||||
|
return tagName1.getDisplayName().compareTo(tagName2.getDisplayName());
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,25 +143,26 @@ public final class DrawableTagsManager {
|
|||||||
* @throws org.sleuthkit.datamodel.TskCoreException
|
* @throws org.sleuthkit.datamodel.TskCoreException
|
||||||
*/
|
*/
|
||||||
public List<TagName> getNonCategoryTagNames() throws TskCoreException {
|
public List<TagName> getNonCategoryTagNames() throws TskCoreException {
|
||||||
return autopsyTagsManager.getAllTagNames().stream()
|
List<TagName> nonCategoryTagNames = new ArrayList<>();
|
||||||
.filter(CategoryManager::isNotCategoryTagName)
|
List<TagName> allTags = autopsyTagsManager.getAllTagNames();
|
||||||
.distinct().sorted()
|
for (TagName tag : allTags) {
|
||||||
.collect(Collectors.toList());
|
if (controller.getCategoryManager().isNotCategoryTagName(tag)) {
|
||||||
|
nonCategoryTagNames.add(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nonCategoryTagNames.sort(compareByDisplayName);
|
||||||
|
return nonCategoryTagNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the TagNames that are categories
|
* Get all the TagNames that are categories
|
||||||
*
|
*
|
||||||
* @return All the TagNames that are categories, in alphabetical order by
|
* @return All the TagNames that are categories.
|
||||||
* displayName.
|
|
||||||
*
|
*
|
||||||
* @throws org.sleuthkit.datamodel.TskCoreException
|
* @throws org.sleuthkit.datamodel.TskCoreException
|
||||||
*/
|
*/
|
||||||
public List<TagName> getCategoryTagNames() throws TskCoreException {
|
public List<TagName> getCategoryTagNames() throws TskCoreException {
|
||||||
return autopsyTagsManager.getAllTagNames().stream()
|
return controller.getCategoryManager().getCategorySet().getTagNames();
|
||||||
.filter(CategoryManager::isCategoryTagName)
|
|
||||||
.distinct().sorted()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -190,15 +205,11 @@ public final class DrawableTagsManager {
|
|||||||
returnTagName = autopsyTagsManager.getDisplayNamesToTagNamesMap().get(displayName);
|
returnTagName = autopsyTagsManager.getDisplayNamesToTagNamesMap().get(displayName);
|
||||||
if (returnTagName != null) {
|
if (returnTagName != null) {
|
||||||
return returnTagName;
|
return returnTagName;
|
||||||
}
|
}
|
||||||
throw new TskCoreException("Tag name exists but an error occured in retrieving it", ex);
|
throw new TskCoreException("Tag name exists but an error occured in retrieving it", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagName getTagName(DhsImageCategory cat) throws TskCoreException {
|
|
||||||
return getTagName(cat.getDisplayName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContentTag addContentTag(DrawableFile file, TagName tagName, String comment) throws TskCoreException {
|
public ContentTag addContentTag(DrawableFile file, TagName tagName, String comment) throws TskCoreException {
|
||||||
return autopsyTagsManager.addContentTag(file.getAbstractFile(), tagName, comment);
|
return autopsyTagsManager.addContentTag(file.getAbstractFile(), tagName, comment);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ public class VideoFile extends DrawableFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the genereric video thumbnail.
|
* Get the generic video thumbnail.
|
||||||
*
|
*
|
||||||
* @return The thumbnail.
|
* @return The thumbnail.
|
||||||
*/
|
*/
|
||||||
|
@ -59,6 +59,7 @@ public class GroupKey<T extends Comparable<T>> implements Comparable<GroupKey<T>
|
|||||||
|
|
||||||
public String getValueDisplayName() {
|
public String getValueDisplayName() {
|
||||||
return Objects.equals(attr, DrawableAttribute.TAGS)
|
return Objects.equals(attr, DrawableAttribute.TAGS)
|
||||||
|
|| Objects.equals(attr, DrawableAttribute.CATEGORY)
|
||||||
? ((TagName) getValue()).getDisplayName()
|
? ((TagName) getValue()).getDisplayName()
|
||||||
: Objects.toString(getValue(), "unknown");
|
: Objects.toString(getValue(), "unknown");
|
||||||
}
|
}
|
||||||
@ -74,8 +75,9 @@ public class GroupKey<T extends Comparable<T>> implements Comparable<GroupKey<T>
|
|||||||
|
|
||||||
hash = 79 * hash + Objects.hashCode(this.val);
|
hash = 79 * hash + Objects.hashCode(this.val);
|
||||||
hash = 79 * hash + Objects.hashCode(this.attr);
|
hash = 79 * hash + Objects.hashCode(this.attr);
|
||||||
if (this.dataSource != null)
|
if (this.dataSource != null) {
|
||||||
hash = 79 * hash + (int)this.dataSource.getId();
|
hash = 79 * hash + (int) this.dataSource.getId();
|
||||||
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
@ -99,20 +101,20 @@ public class GroupKey<T extends Comparable<T>> implements Comparable<GroupKey<T>
|
|||||||
if (!Objects.equals(this.attr, other.attr)) {
|
if (!Objects.equals(this.attr, other.attr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data source is significant only for PATH based groups.
|
// Data source is significant only for PATH based groups.
|
||||||
if (this.attr == DrawableAttribute.PATH) {
|
if (this.attr == DrawableAttribute.PATH) {
|
||||||
if (this.dataSource != null && other.dataSource != null) {
|
if (this.dataSource != null && other.dataSource != null) {
|
||||||
return this.dataSource.getId() == other.dataSource.getId();
|
return this.dataSource.getId() == other.dataSource.getId();
|
||||||
} else if (this.dataSource == null && other.dataSource == null) {
|
} else if (this.dataSource == null && other.dataSource == null) {
|
||||||
// neither group has a datasource
|
// neither group has a datasource
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// one group has a datasource, other doesn't
|
// one group has a datasource, other doesn't
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ import javax.annotation.concurrent.GuardedBy;
|
|||||||
import javax.swing.SortOrder;
|
import javax.swing.SortOrder;
|
||||||
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
|
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
|
||||||
import static org.apache.commons.lang3.ObjectUtils.notEqual;
|
import static org.apache.commons.lang3.ObjectUtils.notEqual;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
@ -70,9 +69,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.coreutils.LoggedTask;
|
import org.sleuthkit.autopsy.coreutils.LoggedTask;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
||||||
@ -106,23 +103,23 @@ public class GroupManager {
|
|||||||
private final ImageGalleryController controller;
|
private final ImageGalleryController controller;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of the current path group
|
* Keeps track of the current path group - a change in path indicates the
|
||||||
* - a change in path indicates the current path group is analyzed
|
* current path group is analyzed
|
||||||
*/
|
*/
|
||||||
@GuardedBy("this") //NOPMD
|
@GuardedBy("this") //NOPMD
|
||||||
private GroupKey<?> currentPathGroup = null;
|
private GroupKey<?> currentPathGroup = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list of all analyzed groups - i.e. groups that are ready to be shown to user.
|
* list of all analyzed groups - i.e. groups that are ready to be shown to
|
||||||
* These are groups under the selected groupBy attribute.
|
* user. These are groups under the selected groupBy attribute.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("this") //NOPMD
|
@GuardedBy("this") //NOPMD
|
||||||
private final ObservableList<DrawableGroup> analyzedGroups = FXCollections.observableArrayList();
|
private final ObservableList<DrawableGroup> analyzedGroups = FXCollections.observableArrayList();
|
||||||
private final ObservableList<DrawableGroup> unmodifiableAnalyzedGroups = FXCollections.unmodifiableObservableList(analyzedGroups);
|
private final ObservableList<DrawableGroup> unmodifiableAnalyzedGroups = FXCollections.unmodifiableObservableList(analyzedGroups);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list of unseen groups
|
* list of unseen groups These are groups under the selected groupBy
|
||||||
* These are groups under the selected groupBy attribute.
|
* attribute.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("this") //NOPMD
|
@GuardedBy("this") //NOPMD
|
||||||
private final ObservableList<DrawableGroup> unSeenGroups = FXCollections.observableArrayList();
|
private final ObservableList<DrawableGroup> unSeenGroups = FXCollections.observableArrayList();
|
||||||
@ -186,15 +183,15 @@ public class GroupManager {
|
|||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
synchronized public Set<GroupKey<?>> getAllGroupKeysForFile(DrawableFile file) throws TskCoreException, TskDataException {
|
synchronized public Set<GroupKey<?>> getAllGroupKeysForFile(DrawableFile file) throws TskCoreException, TskDataException {
|
||||||
Set<GroupKey<?>> resultSet = new HashSet<>();
|
Set<GroupKey<?>> resultSet = new HashSet<>();
|
||||||
|
|
||||||
for (DrawableAttribute<?> attr: DrawableAttribute.getGroupableAttrs()) {
|
for (DrawableAttribute<?> attr : DrawableAttribute.getGroupableAttrs()) {
|
||||||
for (Comparable<?> val : attr.getValue(file)) {
|
for (Comparable<?> val : attr.getValue(file)) {
|
||||||
|
|
||||||
if (attr == DrawableAttribute.PATH) {
|
if (attr == DrawableAttribute.PATH) {
|
||||||
resultSet.add(new GroupKey(attr, val, file.getDataSource()));
|
resultSet.add(new GroupKey(attr, val, file.getDataSource()));
|
||||||
} else if (attr == DrawableAttribute.TAGS) {
|
} else if (attr == DrawableAttribute.TAGS) {
|
||||||
//don't show groups for the categories when grouped by tags.
|
//don't show groups for the categories when grouped by tags.
|
||||||
if (CategoryManager.isNotCategoryTagName((TagName) val)) {
|
if (controller.getCategoryManager().isNotCategoryTagName((TagName) val)) {
|
||||||
resultSet.add(new GroupKey(attr, val, null));
|
resultSet.add(new GroupKey(attr, val, null));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -204,9 +201,8 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Returns GroupKeys for all the Groups the given file is a part of.
|
* Returns GroupKeys for all the Groups the given file is a part of.
|
||||||
*
|
*
|
||||||
@ -225,7 +221,7 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param groupKey
|
* @param groupKey
|
||||||
*
|
*
|
||||||
@ -244,7 +240,7 @@ public class GroupManager {
|
|||||||
setGroupBy(DrawableAttribute.PATH);
|
setGroupBy(DrawableAttribute.PATH);
|
||||||
setSortOrder(SortOrder.ASCENDING);
|
setSortOrder(SortOrder.ASCENDING);
|
||||||
setDataSource(null);
|
setDataSource(null);
|
||||||
|
|
||||||
unSeenGroups.forEach(controller.getCategoryManager()::unregisterListener);
|
unSeenGroups.forEach(controller.getCategoryManager()::unregisterListener);
|
||||||
unSeenGroups.clear();
|
unSeenGroups.clear();
|
||||||
analyzedGroups.forEach(controller.getCategoryManager()::unregisterListener);
|
analyzedGroups.forEach(controller.getCategoryManager()::unregisterListener);
|
||||||
@ -300,12 +296,12 @@ public class GroupManager {
|
|||||||
public ListenableFuture<?> markGroupUnseen(DrawableGroup group) {
|
public ListenableFuture<?> markGroupUnseen(DrawableGroup group) {
|
||||||
return exec.submit(() -> {
|
return exec.submit(() -> {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
getDrawableDB().markGroupUnseen(group.getGroupKey());
|
getDrawableDB().markGroupUnseen(group.getGroupKey());
|
||||||
// only update and reshuffle if its new results
|
// only update and reshuffle if its new results
|
||||||
if (group.isSeen() == true) {
|
if (group.isSeen() == true) {
|
||||||
group.setSeen(false);
|
group.setSeen(false);
|
||||||
}
|
}
|
||||||
// The group may already be in 'unseen' state, e.g. when new files are added,
|
// The group may already be in 'unseen' state, e.g. when new files are added,
|
||||||
// but not be on the unseenGroupsList yet.
|
// but not be on the unseenGroupsList yet.
|
||||||
updateUnSeenGroups(group);
|
updateUnSeenGroups(group);
|
||||||
@ -314,7 +310,7 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update unseenGroups list accordingly based on the current status of
|
* Update unseenGroups list accordingly based on the current status of
|
||||||
* 'group'. Removes it if it is seen or adds it if it is unseen.
|
* 'group'. Removes it if it is seen or adds it if it is unseen.
|
||||||
@ -322,13 +318,13 @@ public class GroupManager {
|
|||||||
* @param group
|
* @param group
|
||||||
*/
|
*/
|
||||||
synchronized private void updateUnSeenGroups(DrawableGroup group) {
|
synchronized private void updateUnSeenGroups(DrawableGroup group) {
|
||||||
if (group.isSeen()) {
|
if (group.isSeen()) {
|
||||||
unSeenGroups.removeAll(group);
|
unSeenGroups.removeAll(group);
|
||||||
} else if (unSeenGroups.contains(group) == false &&
|
} else if (unSeenGroups.contains(group) == false
|
||||||
getGroupBy() == group.getGroupKey().getAttribute()) {
|
&& getGroupBy() == group.getGroupKey().getAttribute()) {
|
||||||
unSeenGroups.add(group);
|
unSeenGroups.add(group);
|
||||||
}
|
}
|
||||||
sortUnseenGroups();
|
sortUnseenGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -390,7 +386,7 @@ public class GroupManager {
|
|||||||
switch (groupKey.getAttribute().attrName) {
|
switch (groupKey.getAttribute().attrName) {
|
||||||
//these cases get special treatment
|
//these cases get special treatment
|
||||||
case CATEGORY:
|
case CATEGORY:
|
||||||
return getFileIDsWithCategory((DhsImageCategory) groupKey.getValue());
|
return getFileIDsWithCategory((TagName) groupKey.getValue());
|
||||||
case TAGS:
|
case TAGS:
|
||||||
return getFileIDsWithTag((TagName) groupKey.getValue());
|
return getFileIDsWithTag((TagName) groupKey.getValue());
|
||||||
case MIME_TYPE:
|
case MIME_TYPE:
|
||||||
@ -405,33 +401,18 @@ public class GroupManager {
|
|||||||
|
|
||||||
// @@@ This was kind of slow in the profiler. Maybe we should cache it.
|
// @@@ This was kind of slow in the profiler. Maybe we should cache it.
|
||||||
// Unless the list of file IDs is necessary, use countFilesWithCategory() to get the counts.
|
// Unless the list of file IDs is necessary, use countFilesWithCategory() to get the counts.
|
||||||
synchronized public Set<Long> getFileIDsWithCategory(DhsImageCategory category) throws TskCoreException {
|
synchronized public Set<Long> getFileIDsWithCategory(TagName category) throws TskCoreException {
|
||||||
Set<Long> fileIDsToReturn = Collections.emptySet();
|
Set<Long> fileIDsToReturn = Collections.emptySet();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final DrawableTagsManager tagsManager = controller.getTagsManager();
|
final DrawableTagsManager tagsManager = controller.getTagsManager();
|
||||||
if (category == DhsImageCategory.ZERO) {
|
|
||||||
Set<Long> fileIDs = new HashSet<>();
|
|
||||||
for (TagName catTagName : tagsManager.getCategoryTagNames()) {
|
|
||||||
if (notEqual(catTagName.getDisplayName(), DhsImageCategory.ZERO.getDisplayName())) {
|
|
||||||
tagsManager.getContentTagsByTagName(catTagName).stream()
|
|
||||||
.filter(ct -> ct.getContent() instanceof AbstractFile)
|
|
||||||
.map(ct -> ct.getContent().getId())
|
|
||||||
.filter(getDrawableDB()::isInDB)
|
|
||||||
.forEach(fileIDs::add);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileIDsToReturn = getDrawableDB().findAllFileIdsWhere("obj_id NOT IN (" + StringUtils.join(fileIDs, ',') + ")"); //NON-NLS
|
List<ContentTag> contentTags = tagsManager.getContentTagsByTagName(category);
|
||||||
} else {
|
fileIDsToReturn = contentTags.stream()
|
||||||
|
.filter(ct -> ct.getContent() instanceof AbstractFile)
|
||||||
List<ContentTag> contentTags = tagsManager.getContentTagsByTagName(tagsManager.getTagName(category));
|
.filter(ct -> getDrawableDB().isInDB(ct.getContent().getId()))
|
||||||
fileIDsToReturn = contentTags.stream()
|
.map(ct -> ct.getContent().getId())
|
||||||
.filter(ct -> ct.getContent() instanceof AbstractFile)
|
.collect(Collectors.toSet());
|
||||||
.filter(ct -> getDrawableDB().isInDB(ct.getContent().getId()))
|
|
||||||
.map(ct -> ct.getContent().getId())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.WARNING, "TSK error getting files in Category:" + category.getDisplayName(), ex); //NON-NLS
|
logger.log(Level.WARNING, "TSK error getting files in Category:" + category.getDisplayName(), ex); //NON-NLS
|
||||||
throw ex;
|
throw ex;
|
||||||
@ -552,14 +533,14 @@ public class GroupManager {
|
|||||||
synchronized public void handleTagAdded(ContentTagAddedEvent evt) {
|
synchronized public void handleTagAdded(ContentTagAddedEvent evt) {
|
||||||
GroupKey<?> newGroupKey = null;
|
GroupKey<?> newGroupKey = null;
|
||||||
final long fileID = evt.getAddedTag().getContent().getId();
|
final long fileID = evt.getAddedTag().getContent().getId();
|
||||||
if (getGroupBy() == DrawableAttribute.CATEGORY && CategoryManager.isCategoryTagName(evt.getAddedTag().getName())) {
|
if (getGroupBy() == DrawableAttribute.CATEGORY && controller.getCategoryManager().isCategoryTagName(evt.getAddedTag().getName())) {
|
||||||
newGroupKey = new GroupKey<>(DrawableAttribute.CATEGORY, CategoryManager.categoryFromTagName(evt.getAddedTag().getName()), getDataSource());
|
newGroupKey = new GroupKey<>(DrawableAttribute.CATEGORY, evt.getAddedTag().getName(), getDataSource());
|
||||||
for (GroupKey<?> oldGroupKey : groupMap.keySet()) {
|
for (GroupKey<?> oldGroupKey : groupMap.keySet()) {
|
||||||
if (oldGroupKey.equals(newGroupKey) == false) {
|
if (oldGroupKey.equals(newGroupKey) == false) {
|
||||||
removeFromGroup(oldGroupKey, fileID);
|
removeFromGroup(oldGroupKey, fileID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (getGroupBy() == DrawableAttribute.TAGS && CategoryManager.isNotCategoryTagName(evt.getAddedTag().getName())) {
|
} else if (getGroupBy() == DrawableAttribute.TAGS && controller.getCategoryManager().isNotCategoryTagName(evt.getAddedTag().getName())) {
|
||||||
newGroupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName(), getDataSource());
|
newGroupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName(), getDataSource());
|
||||||
}
|
}
|
||||||
if (newGroupKey != null) {
|
if (newGroupKey != null) {
|
||||||
@ -569,7 +550,8 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an analyzed file to the in-memory group data structures. Marks the group as unseen.
|
* Adds an analyzed file to the in-memory group data structures. Marks the
|
||||||
|
* group as unseen.
|
||||||
*
|
*
|
||||||
* @param group Group being added to (will be null if a group has not yet
|
* @param group Group being added to (will be null if a group has not yet
|
||||||
* been created)
|
* been created)
|
||||||
@ -584,16 +566,20 @@ public class GroupManager {
|
|||||||
//if there wasn't already a DrawableGroup, then check if this group is now
|
//if there wasn't already a DrawableGroup, then check if this group is now
|
||||||
// in an appropriate state to get one made.
|
// in an appropriate state to get one made.
|
||||||
// Path group, for example, only gets a DrawableGroup created when all files are analyzed
|
// Path group, for example, only gets a DrawableGroup created when all files are analyzed
|
||||||
/* NOTE: With the current (Jan 2019) behavior of how we detect a PATH group as being analyzed, the group
|
/*
|
||||||
* is not marked as analyzed until we add a file for another folder. So, when the last picture in a folder
|
* NOTE: With the current (Jan 2019) behavior of how we detect a
|
||||||
* is added to the group, the call to 'populateIfAnalyzed' will still not return a group and therefore this
|
* PATH group as being analyzed, the group is not marked as analyzed
|
||||||
* method will never mark the group as unseen. */
|
* until we add a file for another folder. So, when the last picture
|
||||||
|
* in a folder is added to the group, the call to
|
||||||
|
* 'populateIfAnalyzed' will still not return a group and therefore
|
||||||
|
* this method will never mark the group as unseen.
|
||||||
|
*/
|
||||||
group = popuplateIfAnalyzed(groupKey, null);
|
group = popuplateIfAnalyzed(groupKey, null);
|
||||||
} else {
|
} else {
|
||||||
//if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it.
|
//if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it.
|
||||||
group.addFile(fileID);
|
group.addFile(fileID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the seen status for the group (if it is currently considered analyzed)
|
// reset the seen status for the group (if it is currently considered analyzed)
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
markGroupUnseen(group);
|
markGroupUnseen(group);
|
||||||
@ -605,18 +591,14 @@ public class GroupManager {
|
|||||||
GroupKey<?> groupKey = null;
|
GroupKey<?> groupKey = null;
|
||||||
final ContentTagDeletedEvent.DeletedContentTagInfo deletedTagInfo = evt.getDeletedTagInfo();
|
final ContentTagDeletedEvent.DeletedContentTagInfo deletedTagInfo = evt.getDeletedTagInfo();
|
||||||
final TagName deletedTagName = deletedTagInfo.getName();
|
final TagName deletedTagName = deletedTagInfo.getName();
|
||||||
if (getGroupBy() == DrawableAttribute.CATEGORY && CategoryManager.isCategoryTagName(deletedTagName)) {
|
if (getGroupBy() == DrawableAttribute.CATEGORY && controller.getCategoryManager().isCategoryTagName(deletedTagName)) {
|
||||||
groupKey = new GroupKey<>(DrawableAttribute.CATEGORY, CategoryManager.categoryFromTagName(deletedTagName), null);
|
groupKey = new GroupKey<>(DrawableAttribute.CATEGORY, deletedTagName, null);
|
||||||
} else if (getGroupBy() == DrawableAttribute.TAGS && CategoryManager.isNotCategoryTagName(deletedTagName)) {
|
} else if (getGroupBy() == DrawableAttribute.TAGS && controller.getCategoryManager().isNotCategoryTagName(deletedTagName)) {
|
||||||
groupKey = new GroupKey<>(DrawableAttribute.TAGS, deletedTagName, null);
|
groupKey = new GroupKey<>(DrawableAttribute.TAGS, deletedTagName, null);
|
||||||
}
|
}
|
||||||
if (groupKey != null) {
|
if (groupKey != null) {
|
||||||
final long fileID = deletedTagInfo.getContentID();
|
final long fileID = deletedTagInfo.getContentID();
|
||||||
DrawableGroup g = removeFromGroup(groupKey, fileID);
|
DrawableGroup g = removeFromGroup(groupKey, fileID);
|
||||||
|
|
||||||
if (controller.getCategoryManager().getTagName(DhsImageCategory.ZERO).equals(deletedTagName) == false) {
|
|
||||||
addFileToGroup(null, new GroupKey<>(DrawableAttribute.CATEGORY, DhsImageCategory.ZERO, null), fileID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,13 +635,13 @@ public class GroupManager {
|
|||||||
try {
|
try {
|
||||||
DrawableFile file = getDrawableDB().getFileFromID(fileId);
|
DrawableFile file = getDrawableDB().getFileFromID(fileId);
|
||||||
String pathVal = file.getDrawablePath();
|
String pathVal = file.getDrawablePath();
|
||||||
GroupKey<?> pathGroupKey = new GroupKey<>(DrawableAttribute.PATH,pathVal, file.getDataSource());
|
GroupKey<?> pathGroupKey = new GroupKey<>(DrawableAttribute.PATH, pathVal, file.getDataSource());
|
||||||
|
|
||||||
updateCurrentPathGroup(pathGroupKey);
|
updateCurrentPathGroup(pathGroupKey);
|
||||||
} catch (TskCoreException | TskDataException ex) {
|
} catch (TskCoreException | TskDataException ex) {
|
||||||
logger.log(Level.WARNING, "Error getting drawabledb for fileId " + fileId, ex);
|
logger.log(Level.WARNING, "Error getting drawabledb for fileId " + fileId, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update all the groups that this file belongs to
|
// Update all the groups that this file belongs to
|
||||||
Set<GroupKey<?>> groupsForFile = getAllGroupKeysForFile(fileId);
|
Set<GroupKey<?>> groupsForFile = getAllGroupKeysForFile(fileId);
|
||||||
for (GroupKey<?> gk : groupsForFile) {
|
for (GroupKey<?> gk : groupsForFile) {
|
||||||
@ -672,45 +654,45 @@ public class GroupManager {
|
|||||||
//we fire this event for all files so that the category counts get updated during initial db population
|
//we fire this event for all files so that the category counts get updated during initial db population
|
||||||
controller.getCategoryManager().fireChange(updatedFileIDs, null);
|
controller.getCategoryManager().fireChange(updatedFileIDs, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given path is different from the current path group.
|
* Checks if the given path is different from the current path group. If so,
|
||||||
* If so, updates the current path group as analyzed, and sets current path
|
* updates the current path group as analyzed, and sets current path group
|
||||||
* group to the given path.
|
* to the given path.
|
||||||
*
|
*
|
||||||
* The idea is that when the path of the files being processed changes,
|
* The idea is that when the path of the files being processed changes, we
|
||||||
* we have moved from one folder to the next, and the group for the
|
* have moved from one folder to the next, and the group for the previous
|
||||||
* previous PATH can be considered as analyzed and can be displayed.
|
* PATH can be considered as analyzed and can be displayed.
|
||||||
*
|
*
|
||||||
* NOTE: this a close approximation for when all files in a folder have been processed,
|
* NOTE: this a close approximation for when all files in a folder have been
|
||||||
* but there's some room for error - files may go down the ingest pipleline
|
* processed, but there's some room for error - files may go down the ingest
|
||||||
* out of order or the events may not always arrive in the same order
|
* pipleline out of order or the events may not always arrive in the same
|
||||||
*
|
* order
|
||||||
* @param groupKey
|
*
|
||||||
|
* @param groupKey
|
||||||
*/
|
*/
|
||||||
synchronized private void updateCurrentPathGroup(GroupKey<?> groupKey) {
|
synchronized private void updateCurrentPathGroup(GroupKey<?> groupKey) {
|
||||||
try {
|
try {
|
||||||
if (groupKey.getAttribute() == DrawableAttribute.PATH) {
|
if (groupKey.getAttribute() == DrawableAttribute.PATH) {
|
||||||
|
|
||||||
if (this.currentPathGroup == null) {
|
if (this.currentPathGroup == null) {
|
||||||
currentPathGroup = groupKey;
|
currentPathGroup = groupKey;
|
||||||
}
|
} else if (groupKey.getValue().toString().equalsIgnoreCase(this.currentPathGroup.getValue().toString()) == false) {
|
||||||
else if (groupKey.getValue().toString().equalsIgnoreCase(this.currentPathGroup.getValue().toString()) == false) {
|
|
||||||
// mark the last path group as analyzed
|
// mark the last path group as analyzed
|
||||||
getDrawableDB().markGroupAnalyzed(currentPathGroup);
|
getDrawableDB().markGroupAnalyzed(currentPathGroup);
|
||||||
popuplateIfAnalyzed(currentPathGroup, null);
|
popuplateIfAnalyzed(currentPathGroup, null);
|
||||||
|
|
||||||
currentPathGroup = groupKey;
|
currentPathGroup = groupKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (TskCoreException ex) {
|
||||||
catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.SEVERE, String.format("Error setting is_analyzed status for group: %s", groupKey.getValue().toString()), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error setting is_analyzed status for group: %s", groupKey.getValue().toString()), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets current path group, after marking the current path group as analyzed.
|
* Resets current path group, after marking the current path group as
|
||||||
|
* analyzed.
|
||||||
*/
|
*/
|
||||||
synchronized public void resetCurrentPathGroup() {
|
synchronized public void resetCurrentPathGroup() {
|
||||||
try {
|
try {
|
||||||
@ -719,11 +701,11 @@ public class GroupManager {
|
|||||||
popuplateIfAnalyzed(currentPathGroup, null);
|
popuplateIfAnalyzed(currentPathGroup, null);
|
||||||
currentPathGroup = null;
|
currentPathGroup = null;
|
||||||
}
|
}
|
||||||
}
|
} catch (TskCoreException ex) {
|
||||||
catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.SEVERE, String.format("Error resetting last path group: %s", currentPathGroup.getValue().toString()), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error resetting last path group: %s", currentPathGroup.getValue().toString()), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the group is analyzed (or other criteria based on grouping) and should
|
* If the group is analyzed (or other criteria based on grouping) and should
|
||||||
* be shown to the user, then add it to the appropriate data structures so
|
* be shown to the user, then add it to the appropriate data structures so
|
||||||
@ -768,12 +750,12 @@ public class GroupManager {
|
|||||||
controller.getCategoryManager().registerListener(group);
|
controller.getCategoryManager().registerListener(group);
|
||||||
groupMap.put(groupKey, group);
|
groupMap.put(groupKey, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to analyzedGroups only if it's the a group with the selected groupBy attribute
|
// Add to analyzedGroups only if it's the a group with the selected groupBy attribute
|
||||||
if ((analyzedGroups.contains(group) == false) &&
|
if ((analyzedGroups.contains(group) == false)
|
||||||
(getGroupBy() == group.getGroupKey().getAttribute())) {
|
&& (getGroupBy() == group.getGroupKey().getAttribute())) {
|
||||||
analyzedGroups.add(group);
|
analyzedGroups.add(group);
|
||||||
sortAnalyzedGroups();
|
sortAnalyzedGroups();
|
||||||
}
|
}
|
||||||
updateUnSeenGroups(group);
|
updateUnSeenGroups(group);
|
||||||
|
|
||||||
@ -944,11 +926,11 @@ public class GroupManager {
|
|||||||
switch (groupBy.attrName) {
|
switch (groupBy.attrName) {
|
||||||
//these cases get special treatment
|
//these cases get special treatment
|
||||||
case CATEGORY:
|
case CATEGORY:
|
||||||
results.putAll(null, Arrays.asList(DhsImageCategory.values()));
|
results.putAll(null, controller.getCategoryManager().getCategories());
|
||||||
break;
|
break;
|
||||||
case TAGS:
|
case TAGS:
|
||||||
results.putAll(null, controller.getTagsManager().getTagNamesInUse().stream()
|
results.putAll(null, controller.getTagsManager().getTagNamesInUse().stream()
|
||||||
.filter(CategoryManager::isNotCategoryTagName)
|
.filter(controller.getCategoryManager()::isNotCategoryTagName)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -63,9 +63,7 @@ public class GroupSortBy implements Comparator<DrawableGroup> {
|
|||||||
*/
|
*/
|
||||||
public final static GroupSortBy PRIORITY
|
public final static GroupSortBy PRIORITY
|
||||||
= new GroupSortBy(Bundle.GroupSortBy_priority(), "hashset_hits.png",
|
= new GroupSortBy(Bundle.GroupSortBy_priority(), "hashset_hits.png",
|
||||||
Comparator.comparing(DrawableGroup::getHashHitDensity)
|
Comparator.comparing(DrawableGroup::getHashHitDensity).reversed());
|
||||||
.thenComparing(Comparator.comparing(DrawableGroup::getUncategorizedCount))
|
|
||||||
.reversed());
|
|
||||||
|
|
||||||
private final static ObservableList<GroupSortBy> values = FXCollections.unmodifiableObservableList(FXCollections.observableArrayList(PRIORITY, NONE, GROUP_BY_VALUE, FILE_COUNT));
|
private final static ObservableList<GroupSortBy> values = FXCollections.unmodifiableObservableList(FXCollections.observableArrayList(PRIORITY, NONE, GROUP_BY_VALUE, FILE_COUNT));
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public final class GuiUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a MenuItem that performs the given action and also set the Action
|
* Create a MenuItem that performs the given action and also set the Action
|
||||||
* as the action for the given Button. Usefull to have a SplitMenuButton
|
* as the action for the given Button. Useful to have a SplitMenuButton
|
||||||
* remember the last chosen menu item as its action.
|
* remember the last chosen menu item as its action.
|
||||||
*
|
*
|
||||||
* @param button
|
* @param button
|
||||||
|
@ -34,10 +34,10 @@ import javafx.scene.layout.VBox;
|
|||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager.CategoryChangeEvent;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager.CategoryChangeEvent;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays summary statistics (counts) for each group
|
* Displays summary statistics (counts) for each group
|
||||||
@ -45,13 +45,13 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager.CategoryChan
|
|||||||
public class SummaryTablePane extends AnchorPane {
|
public class SummaryTablePane extends AnchorPane {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TableColumn<Pair<DhsImageCategory, Long>, String> catColumn;
|
private TableColumn<Pair<TagName, Long>, String> catColumn;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TableColumn<Pair<DhsImageCategory, Long>, Long> countColumn;
|
private TableColumn<Pair<TagName, Long>, Long> countColumn;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TableView<Pair<DhsImageCategory, Long>> tableView;
|
private TableView<Pair<TagName, Long>> tableView;
|
||||||
|
|
||||||
private final ImageGalleryController controller;
|
private final ImageGalleryController controller;
|
||||||
|
|
||||||
@ -97,9 +97,9 @@ public class SummaryTablePane extends AnchorPane {
|
|||||||
*/
|
*/
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void handleCategoryChanged(CategoryChangeEvent evt) {
|
public void handleCategoryChanged(CategoryChangeEvent evt) {
|
||||||
final ObservableList<Pair<DhsImageCategory, Long>> data = FXCollections.observableArrayList();
|
final ObservableList<Pair<TagName, Long>> data = FXCollections.observableArrayList();
|
||||||
if (Case.isCaseOpen()) {
|
if (Case.isCaseOpen()) {
|
||||||
for (DhsImageCategory cat : DhsImageCategory.values()) {
|
for (TagName cat : controller.getCategoryManager().getCategories()) {
|
||||||
data.add(new Pair<>(cat, controller.getCategoryManager().getCategoryCount(cat)));
|
data.add(new Pair<>(cat, controller.getCategoryManager().getCategoryCount(cat)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,9 @@ package org.sleuthkit.autopsy.imagegallery.gui;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -64,7 +61,6 @@ import static org.sleuthkit.autopsy.casemodule.Case.Events.DATA_SOURCE_ADDED;
|
|||||||
import static org.sleuthkit.autopsy.casemodule.Case.Events.DATA_SOURCE_DELETED;
|
import static org.sleuthkit.autopsy.casemodule.Case.Events.DATA_SOURCE_DELETED;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.actions.CategorizeGroupAction;
|
import org.sleuthkit.autopsy.imagegallery.actions.CategorizeGroupAction;
|
||||||
@ -220,13 +216,13 @@ public class Toolbar extends ToolBar {
|
|||||||
});
|
});
|
||||||
initTagMenuButton();
|
initTagMenuButton();
|
||||||
|
|
||||||
CategorizeGroupAction cat5GroupAction = new CategorizeGroupAction(DhsImageCategory.FIVE, controller);
|
CategorizeGroupAction cat5GroupAction = new CategorizeGroupAction(controller.getCategoryManager().getCategories().get(0), controller);
|
||||||
catGroupMenuButton.setOnAction(cat5GroupAction);
|
catGroupMenuButton.setOnAction(cat5GroupAction);
|
||||||
catGroupMenuButton.setText(cat5GroupAction.getText());
|
catGroupMenuButton.setText(cat5GroupAction.getText());
|
||||||
catGroupMenuButton.setGraphic(cat5GroupAction.getGraphic());
|
catGroupMenuButton.setGraphic(cat5GroupAction.getGraphic());
|
||||||
catGroupMenuButton.showingProperty().addListener(showing -> {
|
catGroupMenuButton.showingProperty().addListener(showing -> {
|
||||||
if (catGroupMenuButton.isShowing()) {
|
if (catGroupMenuButton.isShowing()) {
|
||||||
List<MenuItem> categoryMenues = Lists.transform(Arrays.asList(DhsImageCategory.values()),
|
List<MenuItem> categoryMenues = Lists.transform(controller.getCategoryManager().getCategories(),
|
||||||
cat -> GuiUtils.createAutoAssigningMenuItem(catGroupMenuButton, new CategorizeGroupAction(cat, controller)));
|
cat -> GuiUtils.createAutoAssigningMenuItem(catGroupMenuButton, new CategorizeGroupAction(cat, controller)));
|
||||||
catGroupMenuButton.getItems().setAll(categoryMenues);
|
catGroupMenuButton.getItems().setAll(categoryMenues);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
|||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
@ -34,10 +36,11 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
import org.sleuthkit.datamodel.TagName.HTML_COLOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for classes that are views of a single DrawableFile. Implementation
|
* Interface for classes that are views of a single DrawableFile. Implementation
|
||||||
@ -54,19 +57,9 @@ public interface DrawableView {
|
|||||||
|
|
||||||
static final CornerRadii CAT_CORNER_RADII = new CornerRadii(3);
|
static final CornerRadii CAT_CORNER_RADII = new CornerRadii(3);
|
||||||
|
|
||||||
static final Border HASH_BORDER = new Border(new BorderStroke(Color.PURPLE, BorderStrokeStyle.DASHED, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
Border HASH_BORDER = new Border(new BorderStroke(Color.CYAN, BorderStrokeStyle.DASHED, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
||||||
|
|
||||||
static final Border CAT1_BORDER = new Border(new BorderStroke(DhsImageCategory.ONE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
Map<String, Border> BORDER_MAP = new HashMap<>();
|
||||||
|
|
||||||
static final Border CAT2_BORDER = new Border(new BorderStroke(DhsImageCategory.TWO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
|
||||||
|
|
||||||
static final Border CAT3_BORDER = new Border(new BorderStroke(DhsImageCategory.THREE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
|
||||||
|
|
||||||
static final Border CAT4_BORDER = new Border(new BorderStroke(DhsImageCategory.FOUR.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
|
||||||
|
|
||||||
static final Border CAT5_BORDER = new Border(new BorderStroke(DhsImageCategory.FIVE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
|
||||||
|
|
||||||
static final Border CAT0_BORDER = new Border(new BorderStroke(DhsImageCategory.ZERO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
|
||||||
|
|
||||||
Region getCategoryBorderRegion();
|
Region getCategoryBorderRegion();
|
||||||
|
|
||||||
@ -115,38 +108,38 @@ public interface DrawableView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Border getCategoryBorder(DhsImageCategory category) {
|
/**
|
||||||
if (category != null) {
|
* Get the boarder for the given category.
|
||||||
switch (category) {
|
*
|
||||||
case ONE:
|
* Static instances of the boarders will lazily constructed and stored in
|
||||||
return CAT1_BORDER;
|
* the BORDER_MAP.
|
||||||
case TWO:
|
*
|
||||||
return CAT2_BORDER;
|
* @param category
|
||||||
case THREE:
|
*
|
||||||
return CAT3_BORDER;
|
* @return
|
||||||
case FOUR:
|
*/
|
||||||
return CAT4_BORDER;
|
static Border getCategoryBorder(TagName category) {
|
||||||
case FIVE:
|
Border border = null;
|
||||||
return CAT5_BORDER;
|
if (category != null && category.getColor() != HTML_COLOR.NONE) {
|
||||||
case ZERO:
|
border = BORDER_MAP.get(category.getDisplayName());
|
||||||
default:
|
|
||||||
return CAT0_BORDER;
|
|
||||||
|
|
||||||
|
if (border == null) {
|
||||||
|
border = new Border(new BorderStroke(Color.web(category.getColor().getRgbValue()), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS));
|
||||||
|
BORDER_MAP.put(category.getDisplayName(), border);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return CAT0_BORDER;
|
|
||||||
}
|
}
|
||||||
|
return border;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
|
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
|
||||||
default DhsImageCategory updateCategory() {
|
default TagName updateCategory() {
|
||||||
if (getFile().isPresent()) {
|
if (getFile().isPresent()) {
|
||||||
final DhsImageCategory category = getFile().map(DrawableFile::getCategory).orElse(DhsImageCategory.ZERO);
|
final TagName tagNameCat = getFile().map(DrawableFile::getCategory).orElse(null);
|
||||||
final Border border = hasHashHit() && (category == DhsImageCategory.ZERO) ? HASH_BORDER : getCategoryBorder(category);
|
final Border border = hasHashHit() ? HASH_BORDER : getCategoryBorder(tagNameCat);
|
||||||
Platform.runLater(() -> getCategoryBorderRegion().setBorder(border));
|
Platform.runLater(() -> getCategoryBorderRegion().setBorder(border));
|
||||||
return category;
|
return tagNameCat;
|
||||||
} else {
|
} else {
|
||||||
return DhsImageCategory.ZERO;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,35 +182,6 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<HBox fx:id="catSegmentedContainer" alignment="CENTER" maxWidth="-Infinity" spacing="5.0">
|
|
||||||
<children>
|
|
||||||
<Label fx:id="catHeadingLabel" text="Category:">
|
|
||||||
<graphic>
|
|
||||||
<ImageView fitHeight="16.0" fitWidth="16.0" mouseTransparent="true" pickOnBounds="true" preserveRatio="true">
|
|
||||||
<image>
|
|
||||||
<Image url="@../../images/category-icon.png" />
|
|
||||||
</image>
|
|
||||||
</ImageView>
|
|
||||||
</graphic>
|
|
||||||
</Label>
|
|
||||||
<SegmentedButton fx:id="catSegmentedButton">
|
|
||||||
<buttons>
|
|
||||||
<RadioButton fx:id="cat0Toggle" mnemonicParsing="false" text="0" HBox.hgrow="ALWAYS">
|
|
||||||
<toggleGroup>
|
|
||||||
<ToggleGroup fx:id="cat" />
|
|
||||||
</toggleGroup></RadioButton>
|
|
||||||
<RadioButton fx:id="cat1Toggle" mnemonicParsing="false" style="" styleClass="button" text="1" toggleGroup="$cat" HBox.hgrow="ALWAYS" />
|
|
||||||
<RadioButton id="Cat2Toggle" fx:id="cat2Toggle" mnemonicParsing="false" styleClass="button" text="2" toggleGroup="$cat" HBox.hgrow="ALWAYS" />
|
|
||||||
<RadioButton fx:id="cat3Toggle" mnemonicParsing="false" styleClass="button" text="3" toggleGroup="$cat" HBox.hgrow="ALWAYS" />
|
|
||||||
<RadioButton fx:id="cat4Toggle" mnemonicParsing="false" styleClass="button" text="4" toggleGroup="$cat" HBox.hgrow="ALWAYS" />
|
|
||||||
<RadioButton fx:id="cat5Toggle" mnemonicParsing="false" text="5" toggleGroup="$cat" HBox.hgrow="ALWAYS" />
|
|
||||||
</buttons>
|
|
||||||
</SegmentedButton>
|
|
||||||
</children>
|
|
||||||
<padding>
|
|
||||||
<Insets left="5.0" />
|
|
||||||
</padding>
|
|
||||||
</HBox>
|
|
||||||
</items>
|
</items>
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
</children>
|
</children>
|
||||||
|
@ -19,12 +19,10 @@
|
|||||||
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import static com.google.common.collect.Lists.transform;
|
import static com.google.common.collect.Lists.transform;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import static java.util.Arrays.asList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -50,7 +48,6 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
|
|||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.collections.ObservableSet;
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
@ -86,10 +83,7 @@ import static javafx.scene.input.KeyCode.UP;
|
|||||||
import javafx.scene.input.KeyEvent;
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.Border;
|
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.BorderStroke;
|
|
||||||
import javafx.scene.layout.BorderStrokeStyle;
|
|
||||||
import javafx.scene.layout.BorderWidths;
|
import javafx.scene.layout.BorderWidths;
|
||||||
import javafx.scene.layout.CornerRadii;
|
import javafx.scene.layout.CornerRadii;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
@ -111,7 +105,6 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||||
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
|
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
|
||||||
@ -134,6 +127,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
|||||||
import static org.sleuthkit.autopsy.imagegallery.gui.GuiUtils.createAutoAssigningMenuItem;
|
import static org.sleuthkit.autopsy.imagegallery.gui.GuiUtils.createAutoAssigningMenuItem;
|
||||||
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
||||||
import static org.sleuthkit.autopsy.imagegallery.utils.TaskUtils.addFXCallback;
|
import static org.sleuthkit.autopsy.imagegallery.utils.TaskUtils.addFXCallback;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -176,19 +170,6 @@ public class GroupPane extends BorderPane {
|
|||||||
private SplitMenuButton tagSelectedSplitMenu;
|
private SplitMenuButton tagSelectedSplitMenu;
|
||||||
@FXML
|
@FXML
|
||||||
private ToolBar headerToolBar;
|
private ToolBar headerToolBar;
|
||||||
@FXML
|
|
||||||
private ToggleButton cat0Toggle;
|
|
||||||
@FXML
|
|
||||||
private ToggleButton cat1Toggle;
|
|
||||||
@FXML
|
|
||||||
private ToggleButton cat2Toggle;
|
|
||||||
@FXML
|
|
||||||
private ToggleButton cat3Toggle;
|
|
||||||
@FXML
|
|
||||||
private ToggleButton cat4Toggle;
|
|
||||||
@FXML
|
|
||||||
private ToggleButton cat5Toggle;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private SegmentedButton segButton;
|
private SegmentedButton segButton;
|
||||||
|
|
||||||
@ -220,11 +201,6 @@ public class GroupPane extends BorderPane {
|
|||||||
@FXML
|
@FXML
|
||||||
private Label catContainerLabel;
|
private Label catContainerLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private Label catHeadingLabel;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private HBox catSegmentedContainer;
|
|
||||||
@FXML
|
|
||||||
private HBox catSplitMenuContainer;
|
private HBox catSplitMenuContainer;
|
||||||
|
|
||||||
private final ListeningExecutorService exec = TaskUtils.getExecutorForClass(GroupPane.class);
|
private final ListeningExecutorService exec = TaskUtils.getExecutorForClass(GroupPane.class);
|
||||||
@ -244,12 +220,18 @@ public class GroupPane extends BorderPane {
|
|||||||
|
|
||||||
private ContextMenu contextMenu;
|
private ContextMenu contextMenu;
|
||||||
|
|
||||||
/** the current GroupViewMode of this GroupPane */
|
/**
|
||||||
|
* the current GroupViewMode of this GroupPane
|
||||||
|
*/
|
||||||
private final SimpleObjectProperty<GroupViewMode> groupViewMode = new SimpleObjectProperty<>(GroupViewMode.TILE);
|
private final SimpleObjectProperty<GroupViewMode> groupViewMode = new SimpleObjectProperty<>(GroupViewMode.TILE);
|
||||||
|
|
||||||
/** the grouping this pane is currently the view for */
|
/**
|
||||||
|
* the grouping this pane is currently the view for
|
||||||
|
*/
|
||||||
private final ReadOnlyObjectWrapper<DrawableGroup> grouping = new ReadOnlyObjectWrapper<>();
|
private final ReadOnlyObjectWrapper<DrawableGroup> grouping = new ReadOnlyObjectWrapper<>();
|
||||||
|
|
||||||
|
private final Map<String, ToggleButton> toggleButtonMap = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map from fileIDs to their assigned cells in the tile view. This is used
|
* Map from fileIDs to their assigned cells in the tile view. This is used
|
||||||
* to determine whether fileIDs are visible or are offscreen. No entry
|
* to determine whether fileIDs are visible or are offscreen. No entry
|
||||||
@ -278,7 +260,7 @@ public class GroupPane extends BorderPane {
|
|||||||
undoAction = new UndoAction(controller);
|
undoAction = new UndoAction(controller);
|
||||||
redoAction = new RedoAction(controller);
|
redoAction = new RedoAction(controller);
|
||||||
|
|
||||||
FXMLConstructor.construct(this, "GroupPane.fxml"); //NON-NLS
|
FXMLConstructor.construct(this, "GroupPane.fxml"); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupViewMode getGroupViewMode() {
|
GroupViewMode getGroupViewMode() {
|
||||||
@ -307,7 +289,35 @@ public class GroupPane extends BorderPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void syncCatToggle(DrawableFile file) {
|
void syncCatToggle(DrawableFile file) {
|
||||||
getToggleForCategory(file.getCategory()).setSelected(true);
|
TagName tagName = file.getCategory();
|
||||||
|
if (tagName != null) {
|
||||||
|
getToggleForCategory(tagName).setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a toggle button for the given TagName.
|
||||||
|
*
|
||||||
|
* @param tagName TagName to create a button for.
|
||||||
|
*
|
||||||
|
* @return A new instance of a ToggleButton.
|
||||||
|
*/
|
||||||
|
private ToggleButton getToggleForCategory(TagName tagName) {
|
||||||
|
|
||||||
|
ToggleButton button = toggleButtonMap.get(tagName.getDisplayName());
|
||||||
|
|
||||||
|
if (button == null) {
|
||||||
|
String[] split = tagName.getDisplayName().split(":");
|
||||||
|
split = split[0].split("-");
|
||||||
|
|
||||||
|
int category = Integer.parseInt(split[1]);
|
||||||
|
|
||||||
|
button = new ToggleButton();
|
||||||
|
button.setText(Integer.toString(category));
|
||||||
|
|
||||||
|
toggleButtonMap.put(tagName.getDisplayName(), button);
|
||||||
|
}
|
||||||
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void activateTileViewer() {
|
public void activateTileViewer() {
|
||||||
@ -353,25 +363,6 @@ public class GroupPane extends BorderPane {
|
|||||||
return grouping.getReadOnlyProperty();
|
return grouping.getReadOnlyProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ToggleButton getToggleForCategory(DhsImageCategory category) {
|
|
||||||
switch (category) {
|
|
||||||
case ZERO:
|
|
||||||
return cat0Toggle;
|
|
||||||
case ONE:
|
|
||||||
return cat1Toggle;
|
|
||||||
case TWO:
|
|
||||||
return cat2Toggle;
|
|
||||||
case THREE:
|
|
||||||
return cat3Toggle;
|
|
||||||
case FOUR:
|
|
||||||
return cat4Toggle;
|
|
||||||
case FIVE:
|
|
||||||
return cat5Toggle;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Unknown category: " + category.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called automatically during constructor by FXMLConstructor.
|
* called automatically during constructor by FXMLConstructor.
|
||||||
*
|
*
|
||||||
@ -384,12 +375,6 @@ public class GroupPane extends BorderPane {
|
|||||||
"GroupPane.catContainerLabel.displayText=Categorize Selected File:",
|
"GroupPane.catContainerLabel.displayText=Categorize Selected File:",
|
||||||
"GroupPane.catHeadingLabel.displayText=Category:"})
|
"GroupPane.catHeadingLabel.displayText=Category:"})
|
||||||
void initialize() {
|
void initialize() {
|
||||||
assert cat0Toggle != null : "fx:id=\"cat0Toggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
|
||||||
assert cat1Toggle != null : "fx:id=\"cat1Toggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
|
||||||
assert cat2Toggle != null : "fx:id=\"cat2Toggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
|
||||||
assert cat3Toggle != null : "fx:id=\"cat3Toggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
|
||||||
assert cat4Toggle != null : "fx:id=\"cat4Toggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
|
||||||
assert cat5Toggle != null : "fx:id=\"cat5Toggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
|
||||||
assert gridView != null : "fx:id=\"tilePane\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
assert gridView != null : "fx:id=\"tilePane\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
||||||
assert catSelectedSplitMenu != null : "fx:id=\"grpCatSplitMenu\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
assert catSelectedSplitMenu != null : "fx:id=\"grpCatSplitMenu\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
||||||
assert tagSelectedSplitMenu != null : "fx:id=\"grpTagSplitMenu\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
assert tagSelectedSplitMenu != null : "fx:id=\"grpTagSplitMenu\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
||||||
@ -399,21 +384,6 @@ public class GroupPane extends BorderPane {
|
|||||||
assert tileToggle != null : "fx:id=\"tileToggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
assert tileToggle != null : "fx:id=\"tileToggle\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
||||||
assert seenByOtherExaminersCheckBox != null : "fx:id=\"seenByOtherExaminersCheckBox\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
assert seenByOtherExaminersCheckBox != null : "fx:id=\"seenByOtherExaminersCheckBox\" was not injected: check your FXML file 'GroupPane.fxml'.";
|
||||||
|
|
||||||
for (DhsImageCategory cat : DhsImageCategory.values()) {
|
|
||||||
ToggleButton toggleForCategory = getToggleForCategory(cat);
|
|
||||||
toggleForCategory.setBorder(new Border(new BorderStroke(cat.getColor(), BorderStrokeStyle.SOLID, CORNER_RADII_2, BORDER_WIDTHS_2)));
|
|
||||||
toggleForCategory.getStyleClass().remove("radio-button");
|
|
||||||
toggleForCategory.getStyleClass().add("toggle-button");
|
|
||||||
toggleForCategory.selectedProperty().addListener((ov, wasSelected, toggleSelected) -> {
|
|
||||||
if (toggleSelected && slideShowPane != null) {
|
|
||||||
slideShowPane.getFileID().ifPresent(fileID -> {
|
|
||||||
selectionModel.clearAndSelect(fileID);
|
|
||||||
new CategorizeAction(controller, cat, ImmutableSet.of(fileID)).handle(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//configure flashing glow animation on next unseen group button
|
//configure flashing glow animation on next unseen group button
|
||||||
flashAnimation.setCycleCount(Timeline.INDEFINITE);
|
flashAnimation.setCycleCount(Timeline.INDEFINITE);
|
||||||
flashAnimation.setAutoReverse(true);
|
flashAnimation.setAutoReverse(true);
|
||||||
@ -447,14 +417,14 @@ public class GroupPane extends BorderPane {
|
|||||||
},
|
},
|
||||||
throwable -> logger.log(Level.SEVERE, "Error getting tag names.", throwable)//NON-NLS
|
throwable -> logger.log(Level.SEVERE, "Error getting tag names.", throwable)//NON-NLS
|
||||||
);
|
);
|
||||||
CategorizeSelectedFilesAction cat5SelectedAction = new CategorizeSelectedFilesAction(DhsImageCategory.FIVE, controller);
|
CategorizeSelectedFilesAction cat5SelectedAction = new CategorizeSelectedFilesAction(controller.getCategoryManager().getCategories().get(0), controller);
|
||||||
|
|
||||||
catSelectedSplitMenu.setOnAction(cat5SelectedAction);
|
catSelectedSplitMenu.setOnAction(cat5SelectedAction);
|
||||||
|
|
||||||
catSelectedSplitMenu.setText(cat5SelectedAction.getText());
|
catSelectedSplitMenu.setText(cat5SelectedAction.getText());
|
||||||
catSelectedSplitMenu.setGraphic(cat5SelectedAction.getGraphic());
|
catSelectedSplitMenu.setGraphic(cat5SelectedAction.getGraphic());
|
||||||
|
|
||||||
List<MenuItem> categoryMenues = transform(asList(DhsImageCategory.values()),
|
List<MenuItem> categoryMenues = transform(controller.getCategoryManager().getCategories(),
|
||||||
cat -> createAutoAssigningMenuItem(catSelectedSplitMenu, new CategorizeSelectedFilesAction(cat, controller)));
|
cat -> createAutoAssigningMenuItem(catSelectedSplitMenu, new CategorizeSelectedFilesAction(cat, controller)));
|
||||||
catSelectedSplitMenu.getItems().setAll(categoryMenues);
|
catSelectedSplitMenu.getItems().setAll(categoryMenues);
|
||||||
|
|
||||||
@ -466,16 +436,21 @@ public class GroupPane extends BorderPane {
|
|||||||
bottomLabel.setText(Bundle.GroupPane_bottomLabel_displayText());
|
bottomLabel.setText(Bundle.GroupPane_bottomLabel_displayText());
|
||||||
headerLabel.setText(Bundle.GroupPane_hederLabel_displayText());
|
headerLabel.setText(Bundle.GroupPane_hederLabel_displayText());
|
||||||
catContainerLabel.setText(Bundle.GroupPane_catContainerLabel_displayText());
|
catContainerLabel.setText(Bundle.GroupPane_catContainerLabel_displayText());
|
||||||
catHeadingLabel.setText(Bundle.GroupPane_catHeadingLabel_displayText());
|
|
||||||
//show categorization controls depending on group view mode
|
// This seems to be the only way to make sure the when the user switches
|
||||||
headerToolBar.getItems().remove(catSegmentedContainer);
|
// to SLIDE_SHOW the first time that the undo\redo buttons are removed.
|
||||||
|
headerToolBar.getItems().remove(undoButton);
|
||||||
|
headerToolBar.getItems().remove(redoButton);
|
||||||
|
headerToolBar.getItems().add(undoButton);
|
||||||
|
headerToolBar.getItems().add(redoButton);
|
||||||
|
|
||||||
groupViewMode.addListener((ObservableValue<? extends GroupViewMode> observable, GroupViewMode oldValue, GroupViewMode newValue) -> {
|
groupViewMode.addListener((ObservableValue<? extends GroupViewMode> observable, GroupViewMode oldValue, GroupViewMode newValue) -> {
|
||||||
if (newValue == GroupViewMode.SLIDE_SHOW) {
|
if (newValue == GroupViewMode.SLIDE_SHOW) {
|
||||||
headerToolBar.getItems().remove(catSplitMenuContainer);
|
headerToolBar.getItems().remove(undoButton);
|
||||||
headerToolBar.getItems().add(catSegmentedContainer);
|
headerToolBar.getItems().remove(redoButton);
|
||||||
} else {
|
} else {
|
||||||
headerToolBar.getItems().remove(catSegmentedContainer);
|
headerToolBar.getItems().add(undoButton);
|
||||||
headerToolBar.getItems().add(catSplitMenuContainer);
|
headerToolBar.getItems().add(redoButton);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -527,7 +502,7 @@ public class GroupPane extends BorderPane {
|
|||||||
//listen to tile selection and make sure it is visible in scroll area
|
//listen to tile selection and make sure it is visible in scroll area
|
||||||
selectionModel.lastSelectedProperty().addListener((observable, oldFileID, newFileId) -> {
|
selectionModel.lastSelectedProperty().addListener((observable, oldFileID, newFileId) -> {
|
||||||
if (groupViewMode.get() == GroupViewMode.SLIDE_SHOW
|
if (groupViewMode.get() == GroupViewMode.SLIDE_SHOW
|
||||||
&& slideShowPane != null) {
|
&& slideShowPane != null) {
|
||||||
slideShowPane.setFile(newFileId);
|
slideShowPane.setFile(newFileId);
|
||||||
} else {
|
} else {
|
||||||
scrollToFileID(newFileId);
|
scrollToFileID(newFileId);
|
||||||
@ -775,42 +750,9 @@ public class GroupPane extends BorderPane {
|
|||||||
selectAllFiles();
|
selectAllFiles();
|
||||||
t.consume();
|
t.consume();
|
||||||
}
|
}
|
||||||
ObservableSet<Long> selected = selectionModel.getSelected();
|
|
||||||
if (selected.isEmpty() == false) {
|
|
||||||
DhsImageCategory cat = keyCodeToCat(t.getCode());
|
|
||||||
if (cat != null) {
|
|
||||||
new CategorizeAction(controller, cat, selected).handle(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DhsImageCategory keyCodeToCat(KeyCode t) {
|
|
||||||
if (t != null) {
|
|
||||||
switch (t) {
|
|
||||||
case NUMPAD0:
|
|
||||||
case DIGIT0:
|
|
||||||
return DhsImageCategory.ZERO;
|
|
||||||
case NUMPAD1:
|
|
||||||
case DIGIT1:
|
|
||||||
return DhsImageCategory.ONE;
|
|
||||||
case NUMPAD2:
|
|
||||||
case DIGIT2:
|
|
||||||
return DhsImageCategory.TWO;
|
|
||||||
case NUMPAD3:
|
|
||||||
case DIGIT3:
|
|
||||||
return DhsImageCategory.THREE;
|
|
||||||
case NUMPAD4:
|
|
||||||
case DIGIT4:
|
|
||||||
return DhsImageCategory.FOUR;
|
|
||||||
case NUMPAD5:
|
|
||||||
case DIGIT5:
|
|
||||||
return DhsImageCategory.FIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleArrows(KeyEvent t) {
|
private void handleArrows(KeyEvent t) {
|
||||||
Long lastSelectFileId = selectionModel.lastSelectedProperty().get();
|
Long lastSelectFileId = selectionModel.lastSelectedProperty().get();
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -56,7 +56,6 @@ import org.openide.util.NbBundle;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
||||||
@ -165,20 +164,50 @@ public class MetaDataPane extends DrawableUIBase {
|
|||||||
titledPane.setText(Bundle.MetaDataPane_titledPane_displayName());
|
titledPane.setText(Bundle.MetaDataPane_titledPane_displayName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the display string for the given pair.
|
||||||
|
*
|
||||||
|
* @param p A DrawableAttribute and its collection.
|
||||||
|
*
|
||||||
|
* @return The string to display.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static private String getValueDisplayString(Pair<DrawableAttribute<?>, Collection<?>> p) {
|
private String getValueDisplayString(Pair<DrawableAttribute<?>, Collection<?>> p) {
|
||||||
if (p.getKey() == DrawableAttribute.TAGS) {
|
if (p.getKey() == DrawableAttribute.TAGS || p.getKey() == DrawableAttribute.CATEGORY) {
|
||||||
return ((Collection<TagName>) p.getValue()).stream()
|
return getTagDisplayNames((Collection<TagName>) p.getValue(), p.getKey());
|
||||||
.map(TagName::getDisplayName)
|
|
||||||
.filter(DhsImageCategory::isNotCategoryName)
|
|
||||||
.collect(Collectors.joining(" ; "));
|
|
||||||
} else {
|
} else {
|
||||||
return p.getValue().stream()
|
return p.getValue().stream()
|
||||||
.map(value -> Objects.toString(value, ""))
|
.map(value -> Objects.toString(value, ""))
|
||||||
.collect(Collectors.joining(" ; "));
|
.collect(Collectors.joining(" ; "));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the list of TagName displayNames for either Tags or Categories.
|
||||||
|
*
|
||||||
|
* @param tagNameList List of TagName values
|
||||||
|
* @param attribute A DrawableAttribute value either CATEGORY or TAGS
|
||||||
|
*
|
||||||
|
* @return A list of TagNames separated by ; or an empty string.
|
||||||
|
*/
|
||||||
|
private String getTagDisplayNames(Collection<TagName> tagNameList, DrawableAttribute<?> attribute) {
|
||||||
|
String displayStr = "";
|
||||||
|
CategoryManager controller = getController().getCategoryManager();
|
||||||
|
List<String> nameList = new ArrayList<>();
|
||||||
|
if (tagNameList != null && !tagNameList.isEmpty()) {
|
||||||
|
for (TagName tagName : tagNameList) {
|
||||||
|
if ((attribute == DrawableAttribute.CATEGORY && controller.isCategoryTagName(tagName))
|
||||||
|
|| (attribute == DrawableAttribute.TAGS && !controller.isCategoryTagName(tagName))) {
|
||||||
|
nameList.add(tagName.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayStr = String.join(";", nameList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return displayStr;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized protected void setFileHelper(Long newFileID) {
|
synchronized protected void setFileHelper(Long newFileID) {
|
||||||
setFileIDOpt(Optional.ofNullable(newFileID));
|
setFileIDOpt(Optional.ofNullable(newFileID));
|
||||||
|
@ -50,12 +50,12 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
|||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
|
||||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
|
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile;
|
||||||
import org.sleuthkit.autopsy.imagegallery.gui.VideoPlayer;
|
import org.sleuthkit.autopsy.imagegallery.gui.VideoPlayer;
|
||||||
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableUIBase.exec;
|
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableUIBase.exec;
|
||||||
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableView.CAT_BORDER_WIDTH;
|
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableView.CAT_BORDER_WIDTH;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the files of a group one at a time. Designed to be embedded in a
|
* Displays the files of a group one at a time. Designed to be embedded in a
|
||||||
@ -297,14 +297,14 @@ public class SlideShowView extends DrawableTileBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ThreadConfined(type = ThreadType.ANY)
|
@ThreadConfined(type = ThreadType.ANY)
|
||||||
public DhsImageCategory updateCategory() {
|
public TagName updateCategory() {
|
||||||
Optional<DrawableFile> file = getFile();
|
Optional<DrawableFile> file = getFile();
|
||||||
if (file.isPresent()) {
|
if (file.isPresent()) {
|
||||||
DhsImageCategory updateCategory = super.updateCategory();
|
TagName updateCategory = super.updateCategory();
|
||||||
Platform.runLater(() -> getGroupPane().syncCatToggle(file.get()));
|
Platform.runLater(() -> getGroupPane().syncCatToggle(file.get()));
|
||||||
return updateCategory;
|
return updateCategory;
|
||||||
} else {
|
} else {
|
||||||
return DhsImageCategory.ZERO;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +117,7 @@ class GroupCellFactory {
|
|||||||
final Node graphic = (group.getGroupByAttribute() == DrawableAttribute.TAGS)
|
final Node graphic = (group.getGroupByAttribute() == DrawableAttribute.TAGS)
|
||||||
? controller.getTagsManager().getGraphic((TagName) group.getGroupByValue())
|
? controller.getTagsManager().getGraphic((TagName) group.getGroupByValue())
|
||||||
: group.getGroupKey().getGraphic();
|
: group.getGroupKey().getGraphic();
|
||||||
|
|
||||||
final String text = getCellText(cell);
|
final String text = getCellText(cell);
|
||||||
final String style = getSeenStyleClass(cell);
|
final String style = getSeenStyleClass(cell);
|
||||||
|
|
||||||
@ -157,10 +158,10 @@ class GroupCellFactory {
|
|||||||
*/
|
*/
|
||||||
private String getCountsText(GroupCell<?> cell) {
|
private String getCountsText(GroupCell<?> cell) {
|
||||||
return cell.getGroup()
|
return cell.getGroup()
|
||||||
.map(group ->
|
.map(group
|
||||||
" (" + (sortOrder.get() == GroupComparators.ALPHABETICAL
|
-> " (" + (sortOrder.get() == GroupComparators.ALPHABETICAL
|
||||||
? group.getSize()
|
? group.getSize()
|
||||||
: sortOrder.get().getFormattedValueOfGroup(group)) + ")"
|
: sortOrder.get().getFormattedValueOfGroup(group)) + ")"
|
||||||
).orElse(""); //if item is null or group is null
|
).orElse(""); //if item is null or group is null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,12 +114,8 @@ final class ExtractSru extends Extract {
|
|||||||
|
|
||||||
AbstractFile sruAbstractFile = getSruFile(dataSource, tempDirPath);
|
AbstractFile sruAbstractFile = getSruFile(dataSource, tempDirPath);
|
||||||
|
|
||||||
String sruFileName = tempDirPath + File.separator + sruAbstractFile.getId() + "_" + sruAbstractFile.getName();
|
if (sruAbstractFile == null) {
|
||||||
|
return; //If we cannot find the srudb.dat file we cannot proceed which is ok
|
||||||
if (sruFileName == null) {
|
|
||||||
this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_srudb_dat());
|
|
||||||
logger.log(Level.SEVERE, "SRUDB.dat file not found"); //NON-NLS
|
|
||||||
return; //If we cannot find the srudb.dat file we cannot proceed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String sruDumper = getPathForSruDumper();
|
final String sruDumper = getPathForSruDumper();
|
||||||
@ -135,6 +131,7 @@ final class ExtractSru extends Extract {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
String modOutFile = modOutPath + File.separator + sruAbstractFile.getId() + "_srudb.db3";
|
String modOutFile = modOutPath + File.separator + sruAbstractFile.getId() + "_srudb.db3";
|
||||||
|
String sruFileName = tempDirPath + File.separator + sruAbstractFile.getId() + "_" + sruAbstractFile.getName();
|
||||||
|
|
||||||
extractSruFiles(sruDumper, sruFileName, modOutFile, tempDirPath, softwareHiveFileName);
|
extractSruFiles(sruDumper, sruFileName, modOutFile, tempDirPath, softwareHiveFileName);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user