mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 19:14:55 +00:00
Merge branch 'collaborative' of https://github.com/sleuthkit/autopsy into messaging
This commit is contained in:
commit
3cdfbf6934
@ -59,6 +59,7 @@ import org.sleuthkit.autopsy.coreutils.History;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
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;
|
||||||
|
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
||||||
import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager;
|
import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager;
|
||||||
import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewState;
|
import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewState;
|
||||||
import org.sleuthkit.autopsy.imagegallery.gui.NoGroupsDialog;
|
import org.sleuthkit.autopsy.imagegallery.gui.NoGroupsDialog;
|
||||||
@ -306,7 +307,8 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
private void restartWorker() {
|
private void restartWorker() {
|
||||||
if (dbWorkerThread != null) {
|
if (dbWorkerThread != null) {
|
||||||
dbWorkerThread.cancelAllTasks();
|
// Keep using the same worker thread if one exists
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
dbWorkerThread = new DBWorkerThread();
|
dbWorkerThread = new DBWorkerThread();
|
||||||
|
|
||||||
@ -345,6 +347,8 @@ public final class ImageGalleryController {
|
|||||||
public synchronized void reset() {
|
public synchronized void reset() {
|
||||||
LOGGER.info("resetting ImageGalleryControler to initial state.");
|
LOGGER.info("resetting ImageGalleryControler to initial state.");
|
||||||
selectionModel.clearSelection();
|
selectionModel.clearSelection();
|
||||||
|
setListeningEnabled(false);
|
||||||
|
ThumbnailCache.getDefault().clearCache();
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
historyManager.clear();
|
historyManager.clear();
|
||||||
});
|
});
|
||||||
@ -618,8 +622,16 @@ public final class ImageGalleryController {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
try{
|
||||||
DrawableFile<?> drawableFile = DrawableFile.create(getFile(), true);
|
DrawableFile<?> drawableFile = DrawableFile.create(getFile(), true);
|
||||||
db.updateFile(drawableFile);
|
db.updateFile(drawableFile);
|
||||||
|
} catch (NullPointerException ex){
|
||||||
|
// This is one of the places where we get many errors if the case is closed during processing.
|
||||||
|
// We don't want to print out a ton of exceptions if this is the case.
|
||||||
|
if(Case.isCaseOpen()){
|
||||||
|
Logger.getLogger(UpdateFileTask.class.getName()).log(Level.SEVERE, "Error in UpdateFile task");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +649,16 @@ public final class ImageGalleryController {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
try{
|
||||||
db.removeFile(getFile().getId());
|
db.removeFile(getFile().getId());
|
||||||
|
} catch (NullPointerException ex){
|
||||||
|
// This is one of the places where we get many errors if the case is closed during processing.
|
||||||
|
// We don't want to print out a ton of exceptions if this is the case.
|
||||||
|
if(Case.isCaseOpen()){
|
||||||
|
Logger.getLogger(RemoveFileTask.class.getName()).log(Level.SEVERE, "Case was closed out from underneath RemoveFile task");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,7 +765,7 @@ public final class ImageGalleryController {
|
|||||||
* netbeans and ImageGallery progress/status
|
* netbeans and ImageGallery progress/status
|
||||||
*/
|
*/
|
||||||
class PrePopulateDataSourceFiles extends InnerTask {
|
class PrePopulateDataSourceFiles extends InnerTask {
|
||||||
private Content dataSource;
|
private final Content dataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* here we grab by extension but in file_done listener we look at file
|
* here we grab by extension but in file_done listener we look at file
|
||||||
@ -821,8 +842,8 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "failed to transfer all database contents", ex);
|
Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "failed to transfer all database contents", ex);
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException | NullPointerException ex) {
|
||||||
Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.SEVERE, "Case was closed out from underneath CopyDataSource task", ex);
|
Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "Case was closed out from underneath prepopulating database");
|
||||||
}
|
}
|
||||||
|
|
||||||
progressHandle.finish();
|
progressHandle.finish();
|
||||||
|
@ -83,6 +83,13 @@ public enum ThumbnailCache {
|
|||||||
/** thread that saves generated thumbnails to disk for use later */
|
/** thread that saves generated thumbnails to disk for use later */
|
||||||
private final Executor imageSaver = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder().namingPattern("icon saver-%d").build());
|
private final Executor imageSaver = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder().namingPattern("icon saver-%d").build());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear out the cache between cases
|
||||||
|
*/
|
||||||
|
public final void clearCache() {
|
||||||
|
cache.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
/** get the cached thumbnail for the given file or generate a new one if
|
/** get the cached thumbnail for the given file or generate a new one if
|
||||||
* needed
|
* needed
|
||||||
*
|
*
|
||||||
@ -233,7 +240,7 @@ public enum ThumbnailCache {
|
|||||||
}
|
}
|
||||||
return bi;
|
return bi;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Could not read image: " + file.getName(), ex);
|
LOGGER.log(Level.WARNING, "Could not read image: " + file.getName());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import javafx.beans.property.ReadOnlyStringWrapper;
|
|||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,11 +62,11 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
|||||||
public final static DrawableAttribute<String> PATH
|
public final static DrawableAttribute<String> PATH
|
||||||
= new DrawableAttribute<>(AttributeName.PATH, "Path", true, "folder_picture.png", f -> Collections.singleton(f.getDrawablePath()));
|
= new DrawableAttribute<>(AttributeName.PATH, "Path", true, "folder_picture.png", f -> Collections.singleton(f.getDrawablePath()));
|
||||||
|
|
||||||
public final static DrawableAttribute<Long> CREATED_TIME
|
public final static DrawableAttribute<String> CREATED_TIME
|
||||||
= new DrawableAttribute<>( AttributeName.CREATED_TIME, "Created Time", true, "clock--plus.png", f -> Collections.singleton(f.getCrtime()));
|
= new DrawableAttribute<>( AttributeName.CREATED_TIME, "Created Time", true, "clock--plus.png", f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f)));
|
||||||
|
|
||||||
public final static DrawableAttribute<Long> MODIFIED_TIME
|
public final static DrawableAttribute<String> MODIFIED_TIME
|
||||||
= new DrawableAttribute<>( AttributeName.MODIFIED_TIME, "Modified Time", true, "clock--pencil.png", f -> Collections.singleton(f.getMtime()));
|
= new DrawableAttribute<>( AttributeName.MODIFIED_TIME, "Modified Time", true, "clock--pencil.png", f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f)));
|
||||||
|
|
||||||
public final static DrawableAttribute<String> MAKE
|
public final static DrawableAttribute<String> MAKE
|
||||||
= new DrawableAttribute<>( AttributeName.MAKE, "Camera Make", true, "camera.png", f -> Collections.singleton(f.getMake()));
|
= new DrawableAttribute<>( AttributeName.MAKE, "Camera Make", true, "camera.png", f -> Collections.singleton(f.getMake()));
|
||||||
|
@ -129,9 +129,9 @@ public class DrawableDB {
|
|||||||
|
|
||||||
volatile private Connection con;
|
volatile private Connection con;
|
||||||
|
|
||||||
private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy
|
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); //use fairness policy
|
||||||
|
|
||||||
private static final Lock DBLock = rwLock.writeLock(); //using exclusing lock for all db ops for now
|
private final Lock DBLock = rwLock.writeLock(); //using exclusing lock for all db ops for now
|
||||||
|
|
||||||
static {//make sure sqlite driver is loaded // possibly redundant
|
static {//make sure sqlite driver is loaded // possibly redundant
|
||||||
try {
|
try {
|
||||||
@ -149,7 +149,7 @@ public class DrawableDB {
|
|||||||
* MUST always call dbWriteUnLock() as early as possible, in the same thread
|
* MUST always call dbWriteUnLock() as early as possible, in the same thread
|
||||||
* where dbWriteLock() was called
|
* where dbWriteLock() was called
|
||||||
*/
|
*/
|
||||||
public static void dbWriteLock() {
|
public void dbWriteLock() {
|
||||||
//Logger.getLogger("LOCK").log(Level.INFO, "Locking " + rwLock.toString());
|
//Logger.getLogger("LOCK").log(Level.INFO, "Locking " + rwLock.toString());
|
||||||
DBLock.lock();
|
DBLock.lock();
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ public class DrawableDB {
|
|||||||
* dbWriteLock(). Call in "finally" block to ensure the lock is always
|
* dbWriteLock(). Call in "finally" block to ensure the lock is always
|
||||||
* released.
|
* released.
|
||||||
*/
|
*/
|
||||||
public static void dbWriteUnlock() {
|
public void dbWriteUnlock() {
|
||||||
//Logger.getLogger("LOCK").log(Level.INFO, "UNLocking " + rwLock.toString());
|
//Logger.getLogger("LOCK").log(Level.INFO, "UNLocking " + rwLock.toString());
|
||||||
DBLock.unlock();
|
DBLock.unlock();
|
||||||
}
|
}
|
||||||
@ -604,8 +604,12 @@ public class DrawableDB {
|
|||||||
|
|
||||||
tr.addUpdatedFile(f.getId());
|
tr.addUpdatedFile(f.getId());
|
||||||
|
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException | NullPointerException ex) {
|
||||||
|
// This is one of the places where we get an error if the case is closed during processing,
|
||||||
|
// which doesn't need to be reported here.
|
||||||
|
if(Case.isCaseOpen()){
|
||||||
LOGGER.log(Level.SEVERE, "failed to insert/update file" + f.getName(), ex);
|
LOGGER.log(Level.SEVERE, "failed to insert/update file" + f.getName(), ex);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
dbWriteUnlock();
|
dbWriteUnlock();
|
||||||
}
|
}
|
||||||
@ -915,7 +919,10 @@ public class DrawableDB {
|
|||||||
insertGroupStmt.setString(2, groupBy.attrName.toString());
|
insertGroupStmt.setString(2, groupBy.attrName.toString());
|
||||||
insertGroupStmt.execute();
|
insertGroupStmt.execute();
|
||||||
} catch (SQLException sQLException) {
|
} catch (SQLException sQLException) {
|
||||||
|
// Don't need to report it if the case was closed
|
||||||
|
if(Case.isCaseOpen()){
|
||||||
LOGGER.log(Level.SEVERE, "Unable to insert group", sQLException);
|
LOGGER.log(Level.SEVERE, "Unable to insert group", sQLException);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
dbWriteUnlock();
|
dbWriteUnlock();
|
||||||
}
|
}
|
||||||
@ -952,7 +959,7 @@ public class DrawableDB {
|
|||||||
return DrawableFile.create(controller.getSleuthKitCase().getAbstractFileById(id),
|
return DrawableFile.create(controller.getSleuthKitCase().getAbstractFileById(id),
|
||||||
areFilesAnalyzed(Collections.singleton(id)));
|
areFilesAnalyzed(Collections.singleton(id)));
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "there is no case open; failed to load file with id: " + id, ex);
|
LOGGER.log(Level.SEVERE, "there is no case open; failed to load file with id: " + id);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1160,7 +1167,12 @@ public class DrawableDB {
|
|||||||
fireRemovedFiles(removedFiles);
|
fireRemovedFiles(removedFiles);
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
|
if(Case.isCaseOpen()){
|
||||||
LOGGER.log(Level.SEVERE, "Error commiting drawable.db.", ex);
|
LOGGER.log(Level.SEVERE, "Error commiting drawable.db.", ex);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
LOGGER.log(Level.WARNING, "Error commiting drawable.db - case is closed.");
|
||||||
|
}
|
||||||
rollback();
|
rollback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1171,7 +1183,12 @@ public class DrawableDB {
|
|||||||
try {
|
try {
|
||||||
con.setAutoCommit(true);
|
con.setAutoCommit(true);
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
|
if(Case.isCaseOpen()){
|
||||||
LOGGER.log(Level.SEVERE, "Error setting auto-commit to true.", ex);
|
LOGGER.log(Level.SEVERE, "Error setting auto-commit to true.", ex);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
LOGGER.log(Level.SEVERE, "Error setting auto-commit to true - case is closed");
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
closed = true;
|
closed = true;
|
||||||
dbWriteUnlock();
|
dbWriteUnlock();
|
||||||
|
@ -174,6 +174,9 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
|||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Logger.getAnonymousLogger().log(Level.WARNING, "problem looking up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName(), ex);
|
Logger.getAnonymousLogger().log(Level.WARNING, "problem looking up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName(), ex);
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
|
} catch (IllegalStateException ex) {
|
||||||
|
Logger.getAnonymousLogger().log(Level.WARNING, "there is no case open; failed to look up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName());
|
||||||
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +285,10 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
|||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Logger.getLogger(DrawableFile.class.getName()).log(Level.WARNING, "problem looking up category for file " + this.getName(), ex);
|
Logger.getLogger(DrawableFile.class.getName()).log(Level.WARNING, "problem looking up category for file " + this.getName(), ex);
|
||||||
|
} catch (IllegalStateException ex){
|
||||||
|
// We get here many times if the case is closed during ingest, so don't print out a ton of warnings.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Image getThumbnail();
|
public abstract Image getThumbnail();
|
||||||
|
@ -563,6 +563,8 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
|
|||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.WARNING, "TSK error getting files in Category:" + category.getDisplayName(), ex);
|
LOGGER.log(Level.WARNING, "TSK error getting files in Category:" + category.getDisplayName(), ex);
|
||||||
throw ex;
|
throw ex;
|
||||||
|
} catch(IllegalStateException ex){
|
||||||
|
throw new TskCoreException("Case closed while getting files");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.imagegallery.gui;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.logging.Level;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.CacheHint;
|
import javafx.scene.CacheHint;
|
||||||
import javafx.scene.control.Control;
|
import javafx.scene.control.Control;
|
||||||
@ -88,7 +89,11 @@ public class DrawableTile extends SingleDrawableViewBase implements Category.Cat
|
|||||||
imageView.fitWidthProperty().bind(Toolbar.getDefault().sizeSliderValue());
|
imageView.fitWidthProperty().bind(Toolbar.getDefault().sizeSliderValue());
|
||||||
|
|
||||||
globalSelectionModel.lastSelectedProperty().addListener((observable, oldValue, newValue) -> {
|
globalSelectionModel.lastSelectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
try{
|
||||||
setEffect(Objects.equals(newValue, fileID) ? LAST_SELECTED_EFFECT : null);
|
setEffect(Objects.equals(newValue, fileID) ? LAST_SELECTED_EFFECT : null);
|
||||||
|
} catch (java.lang.IllegalStateException ex){
|
||||||
|
Logger.getLogger(DrawableTile.class.getName()).log(Level.WARNING, "Error displaying tile");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ import org.openide.util.Lookup;
|
|||||||
import org.openide.util.actions.Presenter;
|
import org.openide.util.actions.Presenter;
|
||||||
import org.openide.windows.TopComponent;
|
import org.openide.windows.TopComponent;
|
||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider;
|
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;
|
||||||
@ -112,9 +113,9 @@ import org.sleuthkit.autopsy.imagegallery.actions.NextUnseenGroup;
|
|||||||
import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter;
|
import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
||||||
|
import org.sleuthkit.autopsy.imagegallery.grouping.DrawableGroup;
|
||||||
import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewMode;
|
import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewMode;
|
||||||
import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewState;
|
import org.sleuthkit.autopsy.imagegallery.grouping.GroupViewState;
|
||||||
import org.sleuthkit.autopsy.imagegallery.grouping.DrawableGroup;
|
|
||||||
import org.sleuthkit.datamodel.TagName;
|
import org.sleuthkit.datamodel.TagName;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
@ -372,7 +373,12 @@ public class GroupPane extends BorderPane implements GroupView {
|
|||||||
//and assign fileIDs to gridView
|
//and assign fileIDs to gridView
|
||||||
if (grouping.get() == null) {
|
if (grouping.get() == null) {
|
||||||
Platform.runLater(gridView.getItems()::clear);
|
Platform.runLater(gridView.getItems()::clear);
|
||||||
|
// Reset the DrawableCell listeners from the old case
|
||||||
|
if(! Case.isCaseOpen()){
|
||||||
|
for(GroupPane.DrawableCell cell:cellMap.values()){
|
||||||
|
cell.resetItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
grouping.get().fileIds().addListener((Observable observable) -> {
|
grouping.get().fileIds().addListener((Observable observable) -> {
|
||||||
updateFiles();
|
updateFiles();
|
||||||
@ -627,6 +633,7 @@ public class GroupPane extends BorderPane implements GroupView {
|
|||||||
*/
|
*/
|
||||||
void setViewState(GroupViewState viewState) {
|
void setViewState(GroupViewState viewState) {
|
||||||
if (viewState == null) {
|
if (viewState == null) {
|
||||||
|
this.grouping.set(null);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
setCenter(null);
|
setCenter(null);
|
||||||
groupLabel.setText(null);
|
groupLabel.setText(null);
|
||||||
@ -655,9 +662,18 @@ public class GroupPane extends BorderPane implements GroupView {
|
|||||||
itemProperty().addListener((ObservableValue<? extends Long> observable, Long oldValue, Long newValue) -> {
|
itemProperty().addListener((ObservableValue<? extends Long> observable, Long oldValue, Long newValue) -> {
|
||||||
if (oldValue != null) {
|
if (oldValue != null) {
|
||||||
cellMap.remove(oldValue, DrawableCell.this);
|
cellMap.remove(oldValue, DrawableCell.this);
|
||||||
|
tile.setFile(null);
|
||||||
}
|
}
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
|
if(cellMap.containsKey(newValue)){
|
||||||
|
if(tile != null){
|
||||||
|
// Clear out the old value to prevent out-of-date listeners
|
||||||
|
// from activating.
|
||||||
|
cellMap.get(newValue).tile.setFile(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
cellMap.put(newValue, DrawableCell.this);
|
cellMap.put(newValue, DrawableCell.this);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -669,6 +685,10 @@ public class GroupPane extends BorderPane implements GroupView {
|
|||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
tile.setFile(item);
|
tile.setFile(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetItem(){
|
||||||
|
tile.setFile(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final List<KeyCode> categoryKeyCodes = Arrays.asList(KeyCode.NUMPAD0, KeyCode.NUMPAD1, KeyCode.NUMPAD2, KeyCode.NUMPAD3, KeyCode.NUMPAD4, KeyCode.NUMPAD5,
|
private static final List<KeyCode> categoryKeyCodes = Arrays.asList(KeyCode.NUMPAD0, KeyCode.NUMPAD1, KeyCode.NUMPAD2, KeyCode.NUMPAD3, KeyCode.NUMPAD4, KeyCode.NUMPAD5,
|
||||||
|
@ -359,6 +359,7 @@ public abstract class SingleDrawableViewBase extends AnchorPane implements Drawa
|
|||||||
if (Objects.equals(fileID, this.fileID) == false) {
|
if (Objects.equals(fileID, this.fileID) == false) {
|
||||||
this.fileID = fileID;
|
this.fileID = fileID;
|
||||||
disposeContent();
|
disposeContent();
|
||||||
|
|
||||||
if (this.fileID == null || Case.isCaseOpen() == false) {
|
if (this.fileID == null || Case.isCaseOpen() == false) {
|
||||||
Category.unregisterListener(this);
|
Category.unregisterListener(this);
|
||||||
TagUtils.unregisterListener(this);
|
TagUtils.unregisterListener(this);
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
||||||
<children>
|
<children>
|
||||||
<ProgressBar fx:id="bgTaskProgressBar" maxHeight="-1.0" maxWidth="-1.0" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" StackPane.alignment="CENTER" />
|
<ProgressBar fx:id="bgTaskProgressBar" maxHeight="-1.0" maxWidth="-1.0" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" StackPane.alignment="CENTER" />
|
||||||
<Label fx:id="bgTaskLabel" alignment="CENTER" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" labelFor="$uiTaskProgressBar" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="Regrouping" StackPane.alignment="CENTER">
|
<Label fx:id="bgTaskLabel" alignment="CENTER" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" labelFor="$uiTaskProgressBar" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="" StackPane.alignment="CENTER">
|
||||||
<StackPane.margin>
|
<StackPane.margin>
|
||||||
<Insets left="3.0" right="3.0" />
|
<Insets left="3.0" right="3.0" />
|
||||||
</StackPane.margin></Label>
|
</StackPane.margin></Label>
|
||||||
|
@ -66,8 +66,8 @@ public class StatusBar extends AnchorPane {
|
|||||||
assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert statusLabel != null : "fx:id=\"statusLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert statusLabel != null : "fx:id=\"statusLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert bgTaskLabel != null : "fx:id=\"uiTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert bgTaskLabel != null : "fx:id=\"bgTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert bgTaskProgressBar != null : "fx:id=\"uiTaskProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert bgTaskProgressBar != null : "fx:id=\"bgTaskProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
|
|
||||||
fileUpdateTaskLabel.textProperty().bind(controller.getFileUpdateQueueSizeProperty().asString().concat(" File Update Tasks"));//;setText(newSize.toString() + " File Update Tasks");
|
fileUpdateTaskLabel.textProperty().bind(controller.getFileUpdateQueueSizeProperty().asString().concat(" File Update Tasks"));//;setText(newSize.toString() + " File Update Tasks");
|
||||||
fileTaskProgresBar.progressProperty().bind(controller.getFileUpdateQueueSizeProperty().negate());
|
fileTaskProgresBar.progressProperty().bind(controller.getFileUpdateQueueSizeProperty().negate());
|
||||||
@ -78,7 +78,20 @@ public class StatusBar extends AnchorPane {
|
|||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
|
|
||||||
bgTaskProgressBar.progressProperty().bind(controller.regroupProgress());
|
controller.regroupProgress().addListener((ov, oldSize, newSize) -> {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
if(controller.regroupProgress().lessThan(1.0).get()){
|
||||||
|
// Regrouping in progress
|
||||||
|
bgTaskProgressBar.progressProperty().setValue(-1.0);
|
||||||
|
bgTaskLabel.setText("Regrouping");
|
||||||
|
} else{
|
||||||
|
// Clear the progress bar
|
||||||
|
bgTaskProgressBar.progressProperty().setValue(0.0);
|
||||||
|
bgTaskLabel.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
staleLabel.setTooltip(new Tooltip("Some data may be out of date. Enable listening to ingest in Tools | Options | Image /Video Gallery , after ingest is complete to update."));
|
staleLabel.setTooltip(new Tooltip("Some data may be out of date. Enable listening to ingest in Tools | Options | Image /Video Gallery , after ingest is complete to update."));
|
||||||
|
@ -22,6 +22,7 @@ import java.net.URL;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.logging.Level;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
@ -36,8 +37,10 @@ import javafx.scene.layout.VBox;
|
|||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import org.openide.util.Exceptions;
|
import org.openide.util.Exceptions;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
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.TagUtils;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
@ -111,7 +114,7 @@ public class SummaryTablePane extends AnchorPane implements Category.CategoryLis
|
|||||||
try {
|
try {
|
||||||
data.add(new Pair<>(cat, ImageGalleryController.getDefault().getGroupManager().countFilesWithCategory(cat)));
|
data.add(new Pair<>(cat, ImageGalleryController.getDefault().getGroupManager().countFilesWithCategory(cat)));
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Exceptions.printStackTrace(ex);
|
Logger.getLogger(SummaryTablePane.class.getName()).log(Level.WARNING, "Error performing category file count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
|
|||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -212,19 +213,28 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<KeywordHit> getOneHitPerObject(QueryResults queryResults) {
|
/**
|
||||||
List<KeywordHit> hits = new ArrayList<>();
|
* This method returns a collection of KeywordHits with lowest SolrObjectID-
|
||||||
Set<Long> uniqueObjectIds = new HashSet<>();
|
* Chunk-ID combination. The output generated is consistent across multiple
|
||||||
|
* runs.
|
||||||
|
* @param queryResults QueryResult object
|
||||||
|
* @return A consistent collection of keyword hits
|
||||||
|
*/
|
||||||
|
Collection<KeywordHit> getOneHitPerObject(QueryResults queryResults) {
|
||||||
|
HashMap<Long, KeywordHit> hits = new HashMap<Long, KeywordHit>();
|
||||||
for (Keyword keyWord : queryResults.getKeywords()) {
|
for (Keyword keyWord : queryResults.getKeywords()) {
|
||||||
for (KeywordHit hit : queryResults.getResults(keyWord)) {
|
for (KeywordHit hit : queryResults.getResults(keyWord)) {
|
||||||
long objectId = hit.getSolrObjectId();
|
// add hit with lowest SolrObjectID-Chunk-ID combination.
|
||||||
if (!uniqueObjectIds.contains(objectId)) {
|
if (!hits.containsKey(hit.getSolrObjectId())) {
|
||||||
uniqueObjectIds.add(objectId);
|
hits.put(hit.getSolrObjectId(), hit);
|
||||||
hits.add(hit);
|
} else {
|
||||||
|
if (hit.getChunkId() < hits.get(hit.getSolrObjectId()).getChunkId()) {
|
||||||
|
hits.put(hit.getSolrObjectId(), hit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hits;
|
}
|
||||||
|
return hits.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -268,11 +268,7 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
q.setQuery(theQueryStr);
|
q.setQuery(theQueryStr);
|
||||||
q.setRows(MAX_RESULTS);
|
q.setRows(MAX_RESULTS);
|
||||||
|
|
||||||
if (snippets) {
|
|
||||||
q.setFields(Server.Schema.ID.toString());
|
q.setFields(Server.Schema.ID.toString());
|
||||||
} else {
|
|
||||||
q.setFields(Server.Schema.ID.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (KeywordQueryFilter filter : filters) {
|
for (KeywordQueryFilter filter : filters) {
|
||||||
q.addFilterQuery(filter.toString());
|
q.addFilterQuery(filter.toString());
|
||||||
@ -326,6 +322,7 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
List<String> snippetList = highlightResponse.get(docId).get(Server.Schema.TEXT.toString());
|
List<String> snippetList = highlightResponse.get(docId).get(Server.Schema.TEXT.toString());
|
||||||
// list is null if there wasn't a snippet
|
// list is null if there wasn't a snippet
|
||||||
if (snippetList != null) {
|
if (snippetList != null) {
|
||||||
|
snippetList.sort(null);
|
||||||
snippet = EscapeUtil.unEscapeHtml(snippetList.get(0)).trim();
|
snippet = EscapeUtil.unEscapeHtml(snippetList.get(0)).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,6 +435,8 @@ class LuceneQuery implements KeywordSearchQuery {
|
|||||||
if (contentHighlights == null) {
|
if (contentHighlights == null) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
|
// Sort contentHighlights in order to get consistently same snippet.
|
||||||
|
contentHighlights.sort(null);
|
||||||
// extracted content is HTML-escaped, but snippet goes in a plain text field
|
// extracted content is HTML-escaped, but snippet goes in a plain text field
|
||||||
return EscapeUtil.unEscapeHtml(contentHighlights.get(0)).trim();
|
return EscapeUtil.unEscapeHtml(contentHighlights.get(0)).trim();
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ class QueryResults {
|
|||||||
*/
|
*/
|
||||||
private Collection<KeywordHit> getOneHitPerObject(Keyword keyword) {
|
private Collection<KeywordHit> getOneHitPerObject(Keyword keyword) {
|
||||||
|
|
||||||
HashMap<Long, KeywordHit> hits = new HashMap();
|
HashMap<Long, KeywordHit> hits = new HashMap<Long, KeywordHit>();
|
||||||
|
|
||||||
// create a list of KeywordHits. KeywordHits with lowest chunkID is added the the list.
|
// create a list of KeywordHits. KeywordHits with lowest chunkID is added the the list.
|
||||||
for(KeywordHit hit: getResults(keyword)) {
|
for(KeywordHit hit: getResults(keyword)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user