/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.windows.WindowManager;
import java.awt.Cursor;
/**
* Panel used by the the open recent case option of the start window.
*/
class OpenRecentCasePanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(OpenRecentCasePanel.class.getName());
private static OpenRecentCasePanel instance;
private static String[] caseNames;
private static String[] casePaths;
private RecentCasesTableModel model;
/**
* Constructs a panel used by the the open recent case option of the start
* window.
*/
private OpenRecentCasePanel() {
initComponents();
}
/*
* Gets the singleton instance of the panel used by the the open recent case
* option of the start window.
*/
static OpenRecentCasePanel getInstance() {
if (instance == null) {
instance = new OpenRecentCasePanel();
}
instance.refreshRecentCasesTable();
return instance;
}
/**
* Adds an action listener to the cancel button.
*
* @param listener An action listener.
*/
void setCloseButtonActionListener(ActionListener listener) {
this.cancelButton.addActionListener(listener);
}
/**
* Retrieves all the recent cases and adds them to the table.
*/
private void refreshRecentCasesTable() {
caseNames = RecentCases.getInstance().getRecentCaseNames();
casePaths = RecentCases.getInstance().getRecentCasePaths();
model = new RecentCasesTableModel();
imagesTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
imagesTable.setModel(model);
int width = tableScrollPane.getPreferredSize().width;
imagesTable.getColumnModel().getColumn(0).setPreferredWidth((int) (.30 * width));
imagesTable.getColumnModel().getColumn(1).setPreferredWidth((int) (.70 * width));
// If there are any images, let's select the first one
if (imagesTable.getRowCount() > 0) {
imagesTable.setRowSelectionInterval(0, 0);
openButton.setEnabled(true);
} else {
openButton.setEnabled(false);
}
}
/*
* Opens the selected case.
*/
private void openCase() {
if (casePaths.length < 1) {
return;
}
final String casePath = casePaths[imagesTable.getSelectedRow()];
final String caseName = caseNames[imagesTable.getSelectedRow()];
if (!casePath.equals("")) {
try {
StartupWindowProvider.getInstance().close();
CueBannerPanel.closeOpenRecentCasesWindow();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error closing start up window", ex); //NON-NLS
}
/*
* Open the case.
*/
if (caseName.equals("") || casePath.equals("") || (!new File(casePath).exists())) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
JOptionPane.ERROR_MESSAGE);
RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore
if (Case.isCaseOpen() == false) {
StartupWindowProvider.getInstance().open();
}
} else {
SwingUtilities.invokeLater(() -> {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
});
new Thread(() -> {
try {
Case.open(casePath);
} catch (CaseActionException ex) {
SwingUtilities.invokeLater(() -> {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
ex.getMessage(), // Should be user-friendly
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
if (!Case.isCaseOpen()) {
StartupWindowProvider.getInstance().open();
}
});
}
}).start();
}
}
}
/**
* Table model to keep track of recent cases.
*/
private class RecentCasesTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
@Override
public int getRowCount() {
int count = 0;
for (String s : caseNames) {
if (!s.equals("")) {
count++;
}
}
return count;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public String getColumnName(int column) {
String colName = null;
switch (column) {
case 0:
colName = NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.colName.caseName");
break;
case 1:
colName = NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.colName.path");
break;
default:
break;
}
return colName;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object ret = null;
switch (columnIndex) {
case 0:
ret = caseNames[rowIndex];
break;
case 1:
ret = shortenPath(casePaths[rowIndex]);
break;
default:
logger.log(Level.SEVERE, "Invalid table column index: {0}", columnIndex); //NON-NLS
break;
}
return ret;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
/**
* Shortens a path to fit the display.
*
* @param path The path to shorten.
*
* @return The shortened path.
*/
private String shortenPath(String path) {
String shortenedPath = path;
if (shortenedPath.length() > 50) {
shortenedPath = path.substring(0, 10 + path.substring(10).indexOf(File.separator) + 1) + "..."
+ path.substring((path.length() - 20) + path.substring(path.length() - 20).indexOf(File.separator));
}
return shortenedPath;
}
}
/**
* 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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
cancelButton = new javax.swing.JButton();
openButton = new javax.swing.JButton();
tableScrollPane = new javax.swing.JScrollPane();
imagesTable = new javax.swing.JTable();
jLabel1.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.jLabel1.text")); // NOI18N
cancelButton.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.cancelButton.text")); // NOI18N
openButton.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.openButton.text")); // NOI18N
openButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
openButtonActionPerformed(evt);
}
});
imagesTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
}
));
imagesTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
imagesTable.setShowHorizontalLines(false);
imagesTable.setShowVerticalLines(false);
imagesTable.getTableHeader().setReorderingAllowed(false);
imagesTable.setUpdateSelectionOnSort(false);
imagesTable.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
imagesTableMouseClicked(evt);
}
});
imagesTable.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
imagesTableKeyPressed(evt);
}
});
tableScrollPane.setViewportView(imagesTable);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(292, 414, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tableScrollPane)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(openButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(cancelButton)))
.addContainerGap())))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cancelButton)
.addComponent(openButton))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
openCase();
}//GEN-LAST:event_openButtonActionPerformed
private void imagesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_imagesTableMouseClicked
// If it's a doubleclick
if (evt.getClickCount() == 2) {
openCase();
}
}//GEN-LAST:event_imagesTableMouseClicked
private void imagesTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_imagesTableKeyPressed
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
openCase();
}
}//GEN-LAST:event_imagesTableKeyPressed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton cancelButton;
private javax.swing.JTable imagesTable;
private javax.swing.JLabel jLabel1;
private javax.swing.JButton openButton;
private javax.swing.JScrollPane tableScrollPane;
// End of variables declaration//GEN-END:variables
}