From 7473024d23992ade172b4093fc8e12f66122eaca Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Tue, 18 Dec 2012 14:06:58 -0500 Subject: [PATCH 1/3] Updated code in method DataContentTopComponent.setupTabs() to remove logic that changed to the tab with the highest priority. Now, the tab selected by the user does not change when nodes are selected. This change is in support of Github issue #99: https://github.com/sleuthkit/autopsy/issues/99 --- .../DataContentTopComponent.java | 37 +++++++------------ .../DataContentViewerString.java | 2 +- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java index 721928e257..49f9bc86f2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java @@ -52,6 +52,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC private boolean isDefault; // Different DataContentViewers private List viewers = new ArrayList(); + // contains a list of the undocked TCs private static ArrayList newWindowList = new ArrayList(); private static final String PREFERRED_ID = "DataContentTopComponent"; @@ -291,34 +292,22 @@ public final class DataContentTopComponent extends TopComponent implements DataC */ public void setupTabs(Node selectedNode) { + int currTabIndex = dataContentTabbedPane.getSelectedIndex(); int totalTabs = dataContentTabbedPane.getTabCount(); - - int maxPreferred = 0; - int indexOfPreferred = 0; + for (int i = 0; i < totalTabs; ++i) { + UpdateWrapper dcv = viewers.get(i); + dcv.resetComponent(); - if (totalTabs > 0) { // make sure there are tabs to reset - for (int i = 0; i < totalTabs; i++) { - UpdateWrapper dcv = viewers.get(i); - dcv.resetComponent(); - - // disable an unsupported tab (ex: picture viewer) - boolean dcvSupported = dcv.isSupported(selectedNode); - if (! dcvSupported) { - dataContentTabbedPane.setEnabledAt(i, false); - } else { - dataContentTabbedPane.setEnabledAt(i, true); - int currentPreferred = dcv.isPreferred(selectedNode, dcvSupported); - if (currentPreferred > maxPreferred) { - indexOfPreferred = i; - maxPreferred = currentPreferred; - } - - } + // disable an unsupported tab (ex: picture viewer) + boolean dcvSupported = dcv.isSupported(selectedNode); + if (!dcvSupported) { + dataContentTabbedPane.setEnabledAt(i, false); + } else { + dataContentTabbedPane.setEnabledAt(i, true); } - // set the display of the tab - dataContentTabbedPane.setSelectedIndex(indexOfPreferred); - viewers.get(indexOfPreferred).setNode(selectedNode); } + + viewers.get(currTabIndex).setNode(selectedNode); } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java index dcfd151efa..aea4116a0d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java @@ -482,7 +482,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC @Override public int isPreferred(Node node, boolean isSupported) { if(node != null && isSupported){ - return 2; + return 1; } else { return 0; } From a2664b3348626d7aa75c5a8cfdc4f865f2bd319e Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Tue, 18 Dec 2012 14:18:04 -0500 Subject: [PATCH 2/3] Deleted DataContentViewerPicture.[java|form] that is no longer needed. --- .../DataContentViewerPicture.form | 45 ---- .../DataContentViewerPicture.java | 193 ------------------ 2 files changed, 238 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form delete mode 100644 Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form deleted file mode 100644 index 43f9a88aea..0000000000 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form +++ /dev/null @@ -1,45 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java deleted file mode 100644 index 5d1491b6fc..0000000000 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.corecomponents; - -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Image; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import javax.imageio.ImageIO; -import javax.swing.JPanel; -import org.openide.nodes.Node; -import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.File; -import org.sleuthkit.datamodel.FsContent; -import org.sleuthkit.datamodel.TskException; - -/** - * File content viewer capable of displaying some image formats. - */ -//@ServiceProvider(service = DataContentViewer.class) -public class DataContentViewerPicture extends javax.swing.JPanel implements DataContentViewer { - - // for error handling - private JPanel caller; - private String className = this.getClass().toString(); - - /** Creates new form DataContentViewerPicture */ - public DataContentViewerPicture() { - initComponents(); - this.resetComponent(); - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - picViewerScrollPanel = new javax.swing.JScrollPane(); - picLabel = new javax.swing.JLabel(); - - picLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - picLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerPicture.class, "DataContentViewerPicture.picLabel.text")); // NOI18N - picLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - picViewerScrollPanel.setViewportView(picLabel); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(picViewerScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 589, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(picViewerScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel picLabel; - private javax.swing.JScrollPane picViewerScrollPanel; - // End of variables declaration//GEN-END:variables - - @Override - public void setNode(Node selectedNode) { - // change the cursor to "waiting cursor" for this operation - this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - if (selectedNode != null) { - try { - // read the byte of the image file - - Content content = selectedNode.getLookup().lookup(Content.class); - byte[] dataSource = new byte[(int) content.getSize()]; - int bytesRead = content.read(dataSource, 0, content.getSize()); - - // create the input stream for the content - if (bytesRead > 0) { - InputStream is = new ByteArrayInputStream(dataSource); - - Image image = ImageIO.read(is); // create the image - - if (image!= null) - this.picLabel.setIcon(new javax.swing.ImageIcon(image)); // show the file - } - - - } catch (TskException ex) { - // TODO: maybe make errors bubble - Logger.getLogger(this.className).log(Level.WARNING, "Error while trying to display the picture content.", ex); - } catch (Exception ex) { - Logger.getLogger(this.className).log(Level.WARNING, "Error while trying to display the picture content.", ex); - } - } - } finally { - this.setCursor(null); - } - } - - @Override - public String getTitle() { - return "Picture View"; - } - - @Override - public String getToolTip() { - return "Displays supported image files."; - } - - @Override - public DataContentViewer getInstance() { - return new DataContentViewerPicture(); - } - - @Override - public void resetComponent() { - this.picLabel.setText(""); - //this.picLabel.setIcon(null); - } - - @Override - public boolean isSupported(Node node) { - if (node != null) { - // Note: only supports JPG, GIF, and PNG for now - /*return node.getDisplayName().toLowerCase().endsWith(".jpg") - || node.getDisplayName().toLowerCase().endsWith(".jpeg") - || node.getDisplayName().toLowerCase().endsWith(".jpe") - || node.getDisplayName().toLowerCase().endsWith(".jfif") - || node.getDisplayName().toLowerCase().endsWith(".gif") - || node.getDisplayName().toLowerCase().endsWith(".bmp") - || //node.getDisplayName().toLowerCase().endsWith(".tif") || - //node.getDisplayName().toLowerCase().endsWith(".tiff") || - //node.getDisplayName().toLowerCase().endsWith(".tga") || - node.getDisplayName().toLowerCase().endsWith(".png");*/ - File file = node.getLookup().lookup(File.class); - - if (file != null) { - return file.getSize() > 0 - && (file.getName().toLowerCase().endsWith(".jpg") - || file.getName().toLowerCase().endsWith(".jpeg") - || file.getName().toLowerCase().endsWith(".jpe") - || file.getName().toLowerCase().endsWith(".jfif") - || file.getName().toLowerCase().endsWith(".gif") - || file.getName().toLowerCase().endsWith(".bmp") - || //node.getName().toLowerCase().endsWith(".tif") || - //node.getName().toLowerCase().endsWith(".tiff") || - //node.getName().toLowerCase().endsWith(".tga") || - file.getName().toLowerCase().endsWith(".png")); - } else { - return false; - } - } else { - return false; - } - } - - @Override - public int isPreferred(Node node, boolean isSupported) { - if(isSupported) { - return 1; - } else { - return 0; - } - } - - @Override - public Component getComponent() { - return this; - } -} From adae62df4acccbb84b9500417e7e01b735bd4ce3 Mon Sep 17 00:00:00 2001 From: Tim McIver Date: Wed, 19 Dec 2012 14:58:39 -0500 Subject: [PATCH 3/3] Updated DataContentViewerMedia to use SwingWorker to do updates to progress slider and duration label. Also added code to clear the duration label in reset method so that duration of previous video does not remain when a new video is selected. --- .../DataContentViewerMedia.java | 166 +++++++++++------- 1 file changed, 100 insertions(+), 66 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index ea0a2c03a0..2857368f12 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -25,6 +25,7 @@ import java.util.concurrent.CancellationException; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.BoxLayout; +import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -59,6 +60,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo private long durationMillis = 0; private boolean autoTracking = false; // true if the slider is moving automatically private final Object playbinLock = new Object(); // lock for synchronization of playbin2 player + private VideoProgressWorker videoProgressWorker; /** * Creates new form DataContentViewerVideo @@ -186,6 +188,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo if (selectedNode == null) { return; } + + // get rid of any existing videoProgressWorker thread + if (videoProgressWorker != null) { + videoProgressWorker.cancel(true); + videoProgressWorker = null; + } File file = selectedNode.getLookup().lookup(File.class); if (file == null) { @@ -303,15 +311,19 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } private void reset() { + // reset the progress label text on the event dispatch thread + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + progressLabel.setText(" "); + } + }); synchronized (playbinLock) { if (playbin2 != null) { if (playbin2.isPlaying()) { playbin2.stop(); } playbin2.setState(State.NULL); -// try { -// Thread.sleep(20); // gstreamer needs to catch up -// } catch (InterruptedException ex) { } if (playbin2.getState().equals(State.NULL)) { playbin2.dispose(); } @@ -397,8 +409,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo this.jFile = jFile; } - ; - @Override protected Object doInBackground() throws Exception { success = false; @@ -444,7 +454,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo progressLabel.setText("Error buffering file"); return; } - ClockTime dur = null; + ClockTime dur = null; synchronized (playbinLock) { playbin2.play(); // must play, then pause and get state to get duration. playbin2.pause(); @@ -454,73 +464,97 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo duration = dur.toString(); durationMillis = dur.toMillis(); - progressSlider.setMaximum((int) durationMillis); - progressSlider.setMinimum(0); - final String finalDuration; - if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { - finalDuration = duration.substring(3); - progressLabel.setText("00:00/" + duration); - } else { - finalDuration = duration; - progressLabel.setText("00:00:00/" + duration); - } - synchronized (playbinLock) { - playbin2.play(); - } - pauseButton.setText("||"); - new Thread(new Runnable() { - private boolean isPlayBinReady() { - synchronized (playbinLock) { - return playbin2 != null && !playbin2.getState().equals(State.NULL); - } - } - + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - long positionMillis = 0; - while (positionMillis < durationMillis - && isPlayBinReady() ) { - ClockTime pos = null; - synchronized (playbinLock) { - pos = playbin2.queryPosition(); - } - position = pos.toString(); - positionMillis = pos.toMillis(); - - if (position.length() == 8) { - position = position.substring(3); - } - progressLabel.setText(position + "/" + finalDuration); - autoTracking = true; - progressSlider.setValue((int) positionMillis); - autoTracking = false; - try { - Thread.sleep(20); - } catch (InterruptedException ex) { - } - } - if (finalDuration.length() == 5) { - progressLabel.setText("00:00/" + finalDuration); + progressSlider.setMaximum((int) durationMillis); + progressSlider.setMinimum(0); + final String finalDuration; + if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { + finalDuration = duration.substring(3); + progressLabel.setText("00:00/" + duration); } else { - progressLabel.setText("00:00:00/" + finalDuration); + finalDuration = duration; + progressLabel.setText("00:00:00/" + duration); } - // If it reached the end - if (progressSlider.getValue() == progressSlider.getMaximum()) { - restartVideo(); - } - } - - public void restartVideo() { synchronized (playbinLock) { - if (playbin2 != null) { - playbin2.stop(); - playbin2.setState(State.READY); // ready to be played again - } + playbin2.play(); } - pauseButton.setText("►"); - progressSlider.setValue(0); + pauseButton.setText("||"); + videoProgressWorker = new VideoProgressWorker(); + videoProgressWorker.execute(); } - }).start(); + }); + } + } + + private class VideoProgressWorker extends SwingWorker { + + private boolean isPlayBinReady() { + synchronized (playbinLock) { + return playbin2 != null && !playbin2.getState().equals(State.NULL); + } + } + + public void restartVideo() { + synchronized (playbinLock) { + if (playbin2 != null) { + playbin2.stop(); + playbin2.setState(State.READY); // ready to be played again + } + } + pauseButton.setText("►"); + progressSlider.setValue(0); + } + + @Override + protected Object doInBackground() throws Exception { + long positionMillis = 0; + String finalDuration = ""; + while (positionMillis < durationMillis + && isPlayBinReady() && !isCancelled()) { + ClockTime pos = null; + synchronized (playbinLock) { + pos = playbin2.queryPosition(); + } + String position = pos.toString(); + positionMillis = pos.toMillis(); + + if (position.length() == 8) { + position = position.substring(3); + } + + String duration = playbin2.queryDuration().toString(); + if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { + finalDuration = duration.substring(3); + progressLabel.setText("00:00/" + duration); + } else { + finalDuration = duration; + progressLabel.setText("00:00:00/" + duration); + } + + progressLabel.setText(position + "/" + finalDuration); + autoTracking = true; + progressSlider.setValue((int) positionMillis); + autoTracking = false; + try { + Thread.sleep(20); + } catch (InterruptedException ex) { + throw ex; + } + } + + if (finalDuration.length() == 5) { + progressLabel.setText("00:00/" + finalDuration); + } else { + progressLabel.setText("00:00:00/" + finalDuration); + } + // If it reached the end + if (progressSlider.getValue() == progressSlider.getMaximum()) { + restartVideo(); + } + + return null; } } }