diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index 7096f241c2..95919f7988 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -59,7 +59,7 @@ import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
public class Case implements SleuthkitCase.ErrorObserver {
private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed
- private static final String appName = Version.getName() + " " + autopsyVer;
+ private static String appName = null;
/**
* Property name that indicates the name of the current case has changed.
* Fired with the case is renamed, and when the current case is
@@ -507,6 +507,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
* @return appName
*/
public static String getAppName() {
+ if ((appName == null ) || appName.equals("")) {
+ appName = WindowManager.getDefault().getMainWindow().getTitle();
+ }
return appName;
}
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form
index 48d26daaa7..14aac889e5 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form
@@ -39,6 +39,8 @@
+
+
@@ -61,6 +63,7 @@
+
@@ -196,5 +199,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java
index 3f74c742b0..496afb71c3 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java
@@ -22,6 +22,7 @@ import java.awt.Color;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
+import java.util.Arrays;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import org.sleuthkit.autopsy.coreutils.Logger;
@@ -61,6 +62,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private int curPage;
private int totalPages;
private int curPageImages;
+ private int iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM;
private final PageUpdater pageUpdater = new PageUpdater();
/**
@@ -111,6 +113,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
filePathLabel = new javax.swing.JLabel();
goToPageLabel = new javax.swing.JLabel();
goToPageField = new javax.swing.JTextField();
+ thumbnailSizeComboBox = new javax.swing.JComboBox();
thumbnailScrollPanel.setPreferredSize(new java.awt.Dimension(582, 348));
@@ -160,6 +163,14 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
}
});
+ thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Small Thumbnails", "Medium Thumbnails", "Large Thumbnails" }));
+ thumbnailSizeComboBox.setSelectedIndex(1);
+ thumbnailSizeComboBox.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ thumbnailSizeComboBoxActionPerformed(evt);
+ }
+ });
+
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@@ -186,8 +197,10 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
.addGap(12, 12, 12)
.addComponent(imagesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)))
- .addContainerGap())
+ .addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -203,7 +216,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
.addComponent(imagesLabel)
.addComponent(imagesRangeLabel)
.addComponent(goToPageLabel)
- .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, 0)
.addComponent(thumbnailScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -223,6 +237,38 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
goToPage(goToPageField.getText());
}//GEN-LAST:event_goToPageFieldActionPerformed
+ private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thumbnailSizeComboBoxActionPerformed
+
+ iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; //default size
+ switch(thumbnailSizeComboBox.getSelectedIndex()) {
+ case 0:
+ iconSize = ThumbnailViewNode.ICON_SIZE_SMALL;
+ break;
+ case 2:
+ iconSize = ThumbnailViewNode.ICON_SIZE_LARGE;
+ break;
+ }
+
+ Node root = em.getRootContext();
+ for (Children c : Arrays.asList(root.getChildren()) ) {
+ ((ThumbnailViewChildren)c).setIconSize(iconSize);
+ }
+
+ for (Node page : root.getChildren().getNodes()) {
+ for (Node node : page.getChildren().getNodes()) {
+ ((ThumbnailViewNode)node).setIconSize(iconSize);
+ }
+ }
+
+ // Temporarily set the explored context to the root, instead of a child node.
+ // This is a workaround hack to convince org.openide.explorer.ExplorerManager to
+ // update even though the new and old Node values are identical. This in turn
+ // will cause the entire view to update completely. After this we
+ // immediately set the node back to the current child by calling switchPage().
+ em.setExploredContext(root);
+ switchPage();
+ }//GEN-LAST:event_thumbnailSizeComboBoxActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel filePathLabel;
private javax.swing.JTextField goToPageField;
@@ -235,6 +281,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private javax.swing.JButton pagePrevButton;
private javax.swing.JLabel pagesLabel;
private javax.swing.JScrollPane thumbnailScrollPanel;
+ private javax.swing.JComboBox thumbnailSizeComboBox;
// End of variables declaration//GEN-END:variables
@Override
@@ -260,8 +307,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
if (givenNode != null) {
- ThumbnailViewChildren childNode = new ThumbnailViewChildren(givenNode);
-
+ ThumbnailViewChildren childNode = new ThumbnailViewChildren(givenNode, iconSize);
+
final Node root = new AbstractNode(childNode);
pageUpdater.setRoot(root);
root.addNodeListener(pageUpdater);
@@ -390,7 +437,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
progress.start();
progress.switchToIndeterminate();
Node root = em.getRootContext();
- Node pageNode = root.getChildren().getNodeAt(curPage - 1);
+ Node pageNode = root.getChildren().getNodeAt(curPage - 1);
em.setExploredContext(pageNode);
curPageImages = pageNode.getChildren().getNodesCount();
return null;
@@ -400,8 +447,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
protected void done() {
progress.finish();
setCursor(null);
- updateControls();
-
+ updateControls();
}
}.execute();
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java
index 3ad547d12a..7c4284cbf3 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java
@@ -52,15 +52,17 @@ class ThumbnailViewChildren extends Children.Keys {
private final HashMap> pages = new HashMap>();
private int totalImages = 0;
private int totalPages = 0;
+ private int iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM;
private static final Logger logger = Logger.getLogger(ThumbnailViewChildren.class.getName());
/**
* the constructor
*/
- ThumbnailViewChildren(Node arg) {
+ ThumbnailViewChildren(Node arg, int iconSize) {
super(true); //support lazy loading
this.parent = arg;
+ this.iconSize = iconSize;
//
}
@@ -153,6 +155,10 @@ class ThumbnailViewChildren extends Children.Keys {
return false;
}
+ public void setIconSize(int iconSize) {
+ this.iconSize = iconSize;
+ }
+
private static class IsSupportedContentVisitor extends ContentVisitor.Default {
private final List SUPP_EXTENSIONS;
@@ -255,7 +261,7 @@ class ThumbnailViewChildren extends Children.Keys {
@Override
protected Node[] createNodes(Node wrapped) {
if (wrapped != null) {
- final ThumbnailViewNode thumb = new ThumbnailViewNode(wrapped);
+ final ThumbnailViewNode thumb = new ThumbnailViewNode(wrapped, iconSize);
return new Node[]{thumb};
} else {
return new Node[]{};
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java
index ef562ae0c4..b69c7db3f5 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java
@@ -49,16 +49,21 @@ import org.sleuthkit.datamodel.TskException;
*/
class ThumbnailViewNode extends FilterNode {
- private SoftReference iconCache;
+ private SoftReference iconCache = null;
private static final Image defaultIcon = new ImageIcon("/org/sleuthkit/autopsy/images/file-icon.png").getImage();
private static final Logger logger = Logger.getLogger(ThumbnailViewNode.class.getName());
+ static final int ICON_SIZE_SMALL = 50;
+ static final int ICON_SIZE_MEDIUM = 100;
+ static final int ICON_SIZE_LARGE = 200;
+ private int iconSize = ICON_SIZE_MEDIUM;
//private final BufferedImage defaultIconBI;
/**
* the constructor
*/
- ThumbnailViewNode(Node arg) {
+ ThumbnailViewNode(Node arg, int iconSize) {
super(arg, Children.LEAF);
+ this.iconSize = iconSize;
}
@Override
@@ -73,36 +78,31 @@ class ThumbnailViewNode extends FilterNode {
@Override
public Image getIcon(int type) {
Image icon = null;
-
+
if (iconCache != null) {
icon = iconCache.get();
}
-
if (icon == null) {
Content content = this.getLookup().lookup(Content.class);
if (content != null) {
+ // If a thumbnail file is already saved locally
if (getFile(content.getId()).exists()) {
try {
- icon = ImageIO.read(getFile(content.getId()));
- if (icon == null) {
+ BufferedImage bicon = ImageIO.read(getFile(content.getId()));
+ if (bicon == null) {
icon = ThumbnailViewNode.defaultIcon;
+ } else if (bicon.getWidth() != iconSize) {
+ icon = generateAndSaveIcon(content);
+ } else {
+ icon = bicon;
}
} catch (IOException ex) {
icon = ThumbnailViewNode.defaultIcon;
}
- } else {
- try {
- icon = generateIcon(content);
- if (icon == null) {
- icon = ThumbnailViewNode.defaultIcon;
- } else {
- ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId()));
- }
- } catch (IOException ex) {
- logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex);
- }
+ } else { // Make a new icon
+ icon = generateAndSaveIcon(content);
}
} else {
icon = ThumbnailViewNode.defaultIcon;
@@ -110,14 +110,33 @@ class ThumbnailViewNode extends FilterNode {
iconCache = new SoftReference(icon);
}
-
+
return icon;
}
+ private Image generateAndSaveIcon(Content content) {
+ Image icon = null;
+ try {
+ icon = generateIcon(content);
+ if (icon == null) {
+ icon = ThumbnailViewNode.defaultIcon;
+ } else {
+ File f = getFile(content.getId());
+ if (f.exists()) {
+ f.delete();
+ }
+ ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId()));
+ }
+ } catch (IOException ex) {
+ logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex);
+ }
+ return icon;
+ }
+
/*
* Generate a scaled image
*/
- static private BufferedImage generateIcon(Content content) {
+ private BufferedImage generateIcon(Content content) {
InputStream inputStream = null;
try {
@@ -127,7 +146,8 @@ class ThumbnailViewNode extends FilterNode {
logger.log(Level.WARNING, "No image reader for file: " + content.getName());
return null;
}
- BufferedImage biScaled = ScalrWrapper.resizeFast(bi, 100, 100);
+ BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconSize);
+
return biScaled;
}catch (OutOfMemoryError e) {
logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e);
@@ -151,4 +171,10 @@ class ThumbnailViewNode extends FilterNode {
private static File getFile(long id) {
return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".jpg");
}
+
+ public void setIconSize(int iconSize) {
+ this.iconSize = iconSize;
+ iconCache = null;
+ }
+
}