diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/EpochTimeCellRenderer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/EpochTimeCellRenderer.java index 057ab30d14..723c1ef0f3 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/EpochTimeCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/EpochTimeCellRenderer.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2018 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.contentviewers; @@ -17,8 +30,8 @@ import org.openide.nodes.Node; import org.sleuthkit.autopsy.coreutils.Logger; /** + * Custom Cell renderer to display a SQLite column cell as readable Epoch date/time * - * @author raman */ public class EpochTimeCellRenderer extends DefaultTableCellRenderer { @@ -26,40 +39,52 @@ public class EpochTimeCellRenderer extends DefaultTableCellRenderer { private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName()); private static final String FORMAT_STRING = "yyyy/MM/dd HH:mm:ss"; //NON-NLS - private static final SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_STRING); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(FORMAT_STRING); private final boolean renderAsEpoch; - public EpochTimeCellRenderer(boolean renderAsEpoch) { + EpochTimeCellRenderer(boolean renderAsEpoch) { this.renderAsEpoch = renderAsEpoch; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - if (value != null) { - - String textStr = "No Value"; + + // Set the forceground/background so its obvious when the cell is selected. + if (isSelected) { + super.setForeground(table.getSelectionForeground()); + super.setBackground(table.getSelectionBackground()); + } else { + super.setForeground( table.getForeground()); + super.setBackground( table.getBackground()); + } + + if (value == null) { + setText(""); + } + else { + String textStr = ""; try { + // get the col property value if (value instanceof Node.Property) { - Node.Property np = (Node.Property)value; - textStr = np.getValue().toString(); + Node.Property nodeProp = (Node.Property)value; + textStr = nodeProp.getValue().toString(); } + if (renderAsEpoch) { long epochTime = Long.parseUnsignedLong(textStr); if (epochTime > 0 ) { - - Font f = getFont(); - setFont(f.deriveFont(f.getStyle() | Font.ITALIC)); - setText(dateFormat.format(new Date(epochTime))); + Font font = getFont(); + setFont(font.deriveFont(font.getStyle() | Font.ITALIC)); + setText(DATE_FORMAT.format(new Date(epochTime))); } else { setText(textStr); } } - else { + else { // Display raw data setText(textStr); } - } catch (NumberFormatException e) { setText(textStr); @@ -69,12 +94,12 @@ public class EpochTimeCellRenderer extends DefaultTableCellRenderer { LOGGER.log(Level.SEVERE, "Error in getting column value.", ex); //NON-NLS } } - else { - setText(""); - } return this; } + boolean isRenderingAsEpoch() { + return this.renderAsEpoch; + } } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java index 12ef2d09f1..02a08f7037 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableRowFactory.java @@ -18,17 +18,12 @@ */ package org.sleuthkit.autopsy.contentviewers; -import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; -import javax.swing.AbstractAction; import javax.swing.Action; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; -import org.netbeans.swing.outline.Outline; import org.openide.nodes.AbstractNode; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; @@ -36,13 +31,15 @@ import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.sleuthkit.autopsy.datamodel.NodeProperty; +/** + * Factory class to generate nodes for SQLite table rows + */ public class SQLiteTableRowFactory extends ChildFactory { private final List> rows; - //private final Outline outline; private final List colActions; - public SQLiteTableRowFactory(List> rows, List actions ) { + SQLiteTableRowFactory(List> rows, List actions ) { this.rows = rows; this.colActions = actions; } @@ -68,13 +65,15 @@ public class SQLiteTableRowFactory extends ChildFactory { } +/** + * + * Node for SQLite table row + */ class SQLiteTableRowNode extends AbstractNode { private final Map row; - //private final Outline outline; private final List nodeActions; - SQLiteTableRowNode(Map row, List actions) { super(Children.LEAF); this.row = row; @@ -84,21 +83,20 @@ class SQLiteTableRowNode extends AbstractNode { @Override protected Sheet createSheet() { - Sheet s = super.createSheet(); - Sheet.Set properties = s.get(Sheet.PROPERTIES); + Sheet sheet = super.createSheet(); + Sheet.Set properties = sheet.get(Sheet.PROPERTIES); if (properties == null) { properties = Sheet.createPropertiesSet(); - s.put(properties); + sheet.put(properties); } for (Map.Entry col : row.entrySet()) { String colName = col.getKey(); String colVal = col.getValue().toString(); - properties.put(new NodeProperty<>(colName, colName, colName, colVal)); // NON-NLS } - return s; + return sheet; } @Override @@ -106,10 +104,8 @@ class SQLiteTableRowNode extends AbstractNode { List actions = new ArrayList<>(); actions.addAll(Arrays.asList(super.getActions(context))); - actions.addAll(nodeActions); - //actions.add(parseColAction); - + return actions.toArray(new Action[actions.size()]); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java index fa2c9991e8..77c0814c55 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteTableView.java @@ -27,6 +27,8 @@ import java.util.Map; import java.util.Objects; import javax.swing.AbstractAction; import javax.swing.Action; +import javax.swing.JMenu; +import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.ListSelectionModel; @@ -41,7 +43,12 @@ import org.netbeans.swing.outline.Outline; import org.openide.explorer.ExplorerManager; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; +import org.openide.util.NbBundle; +import org.openide.util.actions.Presenter; +/** + * Panel to display a SQLite table + */ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { private final org.openide.explorer.view.OutlineView outlineView; @@ -68,6 +75,7 @@ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { outline.setRowSelectionAllowed(false); outline.setRootVisible(false); + outline.setCellSelectionEnabled(true); explorerManager = new ExplorerManager(); } @@ -76,6 +84,10 @@ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { * * @param tableRows */ + @NbBundle.Messages({"SQLiteTableView.DisplayAs.text=Display as", + "SQLiteTableView.DisplayAsMenuItem.Date=Date", + "SQLiteTableView.DisplayAsMenuItem.RawData=Raw Data" + }) void setupTable(List> tableRows) { @@ -110,10 +122,8 @@ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { List nodeActions = new ArrayList<>(); - nodeActions.add(new ParseColAction("Parse column as Epoch time", outline, new EpochTimeCellRenderer(true)) ); - //nodeActions.add(new ParseColAction("Display column as original type", outline, new DefaultTableCellRenderer()) ); - nodeActions.add(new ParseColAction("Display column as original type", outline, new EpochTimeCellRenderer(false)) ); - + nodeActions.add(new ParseColAction(Bundle.SQLiteTableView_DisplayAs_text(), outline) ); + explorerManager.setRootContext(new AbstractNode(Children.create(new SQLiteTableRowFactory(tableRows, nodeActions), true))); return false; } @@ -173,26 +183,77 @@ class SQLiteTableView extends JPanel implements ExplorerManager.Provider { // End of variables declaration//GEN-END:variables -private class ParseColAction extends AbstractAction { + /** + * Action to handle "Display as" menu item. + * + */ + private class ParseColAction extends AbstractAction implements Presenter.Popup { private final Outline outline; - private TableCellRenderer colCellRenderer; + private final String displayName; - - private ParseColAction(String displayName, Outline outline, TableCellRenderer colCellRenderer ) { + ParseColAction(String displayName, Outline outline ) { super(displayName); this.outline = outline; - this.colCellRenderer = colCellRenderer; + this.displayName = displayName; } @Override public void actionPerformed(ActionEvent e) { + + } - int selCol = outline.getSelectedColumn(); - - TableColumnModel columnModel = outline.getColumnModel(); - - TableColumn column = columnModel.getColumn(selCol); - column.setCellRenderer(colCellRenderer); + @Override + public JMenuItem getPopupPresenter() { + return new DisplayColAsMenu(); + } + + /** + * Class to SubMenu for "Display As" menu + */ + private class DisplayColAsMenu extends JMenu { + + DisplayColAsMenu() { + super(displayName); + initMenu(); + } + + final void initMenu() { + + int selCol = outline.getSelectedColumn(); + if (selCol < 0 ) { + selCol = 1; + } + + TableColumnModel columnModel = outline.getColumnModel(); + TableColumn column = columnModel.getColumn(selCol); + + JMenuItem parseAsEpochItem = new JMenuItem(Bundle.SQLiteTableView_DisplayAsMenuItem_Date()); + parseAsEpochItem.addActionListener((ActionEvent evt) -> { + column.setCellRenderer(new EpochTimeCellRenderer(true)); + }); + parseAsEpochItem.setEnabled(false); + add(parseAsEpochItem); + + JMenuItem parseAsOriginalItem = new JMenuItem(Bundle.SQLiteTableView_DisplayAsMenuItem_RawData()); + parseAsOriginalItem.addActionListener((ActionEvent evt) -> { + column.setCellRenderer(new EpochTimeCellRenderer(false)); + }); + parseAsOriginalItem.setEnabled(false); + add(parseAsOriginalItem); + + // Enable the relevant menuitem based on the current display state of the column + TableCellRenderer currRenderer = column.getCellRenderer(); + if (currRenderer instanceof EpochTimeCellRenderer) { + if (((EpochTimeCellRenderer) currRenderer).isRenderingAsEpoch()) { + parseAsOriginalItem.setEnabled(true); + } else { + parseAsEpochItem.setEnabled(true); + } + } + else { + parseAsEpochItem.setEnabled(true); + } + } } } }