19 package org.sleuthkit.autopsy.centralrepository.persona;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.ComponentAdapter;
24 import java.awt.event.ComponentEvent;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.logging.Level;
29 import javax.swing.JOptionPane;
30 import javax.swing.JTable;
31 import javax.swing.ListSelectionModel;
32 import javax.swing.event.AncestorListener;
33 import javax.swing.event.AncestorEvent;
34 import javax.swing.event.ListSelectionEvent;
35 import javax.swing.event.ListSelectionListener;
36 import javax.swing.table.DefaultTableModel;
37 import org.openide.DialogDisplayer;
38 import org.openide.NotifyDescriptor;
39 import org.openide.util.NbBundle.Messages;
40 import org.openide.windows.RetainLocation;
41 import org.openide.windows.TopComponent;
42 import org.openide.windows.WindowManager;
52 @TopComponent.Description(preferredID =
"PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
53 @TopComponent.Registration(mode =
"personas", openAtStartup =
false)
54 @RetainLocation(
"personas")
55 @SuppressWarnings(
"PMD.SingularField")
58 private static final long serialVersionUID = 1L;
62 private List<Persona> currentResults = null;
66 "PersonasTopComponent_Name=Personas",
67 "PersonasTopComponent_delete_exception_Title=Delete failure",
68 "PersonasTopComponent_delete_exception_msg=Failed to delete persona.",
69 "PersonasTopComponent_delete_confirmation_Title=Are you sure?",
70 "PersonasTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?",})
73 setName(Bundle.PersonasTopComponent_Name());
75 searchBtn.addActionListener(
new ActionListener() {
77 public void actionPerformed(ActionEvent e) {
82 editBtn.addActionListener(
new ActionListener() {
84 public void actionPerformed(ActionEvent e) {
90 createBtn.addActionListener(
new ActionListener() {
92 public void actionPerformed(ActionEvent e) {
98 deleteBtn.addActionListener(
new ActionListener() {
100 public void actionPerformed(ActionEvent e) {
101 NotifyDescriptor confirm =
new NotifyDescriptor.Confirmation(
102 Bundle.PersonasTopComponent_delete_confirmation_msg(),
103 Bundle.PersonasTopComponent_delete_confirmation_Title(),
104 NotifyDescriptor.YES_NO_OPTION);
105 DialogDisplayer.getDefault().notify(confirm);
106 if (confirm.getValue().equals(NotifyDescriptor.YES_OPTION)) {
108 if (selectedPersona != null) {
112 logger.log(Level.SEVERE,
"Failed to delete persona: " + selectedPersona.
getName(), ex);
114 Bundle.PersonasTopComponent_delete_exception_msg(),
115 Bundle.PersonasTopComponent_delete_exception_Title(),
116 JOptionPane.ERROR_MESSAGE);
125 resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
126 resultsTable.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
128 public void valueChanged(ListSelectionEvent e) {
129 handleSelectionChange(e);
133 searchNameRadio.addActionListener((ActionEvent e) -> {
134 searchField.setText(
"");
137 searchAccountRadio.addActionListener((ActionEvent e) -> {
138 searchField.setText(
"");
141 createAccountBtn.addActionListener(
new ActionListener() {
143 public void actionPerformed(ActionEvent e) {
152 addComponentListener(
new ComponentAdapter() {
154 public void componentShown(ComponentEvent e) {
155 resetSearchControls();
156 setKeywordSearchEnabled(
false,
true);
167 public void callback(
Persona persona) {
168 if (persona != null) {
169 searchField.setText(
"");
171 int personaRow = currentResults.indexOf(persona);
172 resultsTable.getSelectionModel().setSelectionInterval(personaRow, personaRow);
173 handleSelectionChange();
175 createBtn.setEnabled(
true);
183 searchField.setText(
"");
184 searchNameRadio.setSelected(
true);
185 searchAccountRadio.setSelected(
false);
196 if (setFilterCb && cbFilterByKeyword.isSelected() != selected) {
197 cbFilterByKeyword.setSelected(selected);
200 searchField.setEnabled(selected);
201 searchNameRadio.setEnabled(selected);
202 searchAccountRadio.setEnabled(selected);
207 void setPersona(
int index) {
208 Persona persona = currentResults.get(index);
209 selectedPersona = persona;
210 editBtn.setEnabled(
true);
211 deleteBtn.setEnabled(
true);
217 final class PersonaFilterTableModel
extends DefaultTableModel {
219 private static final long serialVersionUID = 1L;
221 PersonaFilterTableModel(Object[][] rows, String[] colNames) {
222 super(rows, colNames);
226 public boolean isCellEditable(
int row,
int column) {
232 if (e.getValueIsAdjusting()) {
235 handleSelectionChange();
239 int selectedRow = resultsTable.getSelectedRow();
240 if (selectedRow != -1) {
241 setPersona(resultsTable.getSelectedRow());
244 detailsPanel.clear();
249 Object[][] rows =
new Object[results.size()][2];
251 for (
Persona result : results) {
252 rows[i] =
new Object[]{result.getId(), result.getName()};
255 PersonaFilterTableModel updatedTableModel =
new PersonaFilterTableModel(
257 new String[]{
"ID",
"Name"}
260 resultsTable.setModel(updatedTableModel);
261 currentResults =
new ArrayList<>(results);
264 resultsTable.getColumnModel().getColumn(0).setMaxWidth(100);
265 resultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
269 "PersonasTopComponent_search_exception_Title=There was a failure during the search. Try opening a case to fully initialize the central repository database.",
270 "PersonasTopComponent_search_exception_msg=Failed to search personas.",
271 "PersonasTopComponent_noCR_msg=Central Repository is not enabled.",})
275 logger.log(Level.SEVERE,
"Central Repository is not enabled, but execute search was called.");
276 JOptionPane.showMessageDialog(
this,
277 Bundle.PersonasTopComponent_search_exception_Title(),
278 Bundle.PersonasTopComponent_noCR_msg(),
279 JOptionPane.ERROR_MESSAGE);
283 Collection<Persona> results;
285 if (cbFilterByKeyword.isSelected()) {
286 if (searchNameRadio.isSelected()) {
295 logger.log(Level.SEVERE,
"Failed to search personas", ex);
296 JOptionPane.showMessageDialog(
this,
297 Bundle.PersonasTopComponent_search_exception_Title(),
298 Bundle.PersonasTopComponent_search_exception_msg(),
299 JOptionPane.ERROR_MESSAGE);
303 resultsTable.clearSelection();
304 updateResultsTable(results);
305 editBtn.setEnabled(
false);
306 deleteBtn.setEnabled(
false);
311 super.componentOpened();
312 WindowManager.getDefault().setTopComponentFloating(
this,
true);
323 searchButtonGroup =
new javax.swing.ButtonGroup();
324 introTextScrollPane =
new javax.swing.JScrollPane();
325 introText =
new javax.swing.JTextArea();
326 mainSplitPane =
new javax.swing.JSplitPane();
327 searchPanel =
new javax.swing.JPanel();
328 searchField =
new javax.swing.JTextField();
329 searchNameRadio =
new javax.swing.JRadioButton();
330 searchAccountRadio =
new javax.swing.JRadioButton();
331 searchBtn =
new javax.swing.JButton();
332 resultsPane =
new javax.swing.JScrollPane();
333 resultsTable =
new javax.swing.JTable();
334 createAccountBtn =
new javax.swing.JButton();
335 editBtn =
new javax.swing.JButton();
336 deleteBtn =
new javax.swing.JButton();
337 createButtonSeparator =
new javax.swing.JSeparator();
338 createBtn =
new javax.swing.JButton();
339 cbFilterByKeyword =
new javax.swing.JCheckBox();
340 detailsScrollPane =
new javax.swing.JScrollPane();
345 introTextScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
347 introText.setBackground(getBackground());
348 introText.setColumns(20);
349 introText.setLineWrap(
true);
350 introText.setRows(5);
351 introText.setText(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.introText.text"));
352 introText.setWrapStyleWord(
true);
353 introText.setFocusable(
false);
354 introTextScrollPane.setViewportView(introText);
356 mainSplitPane.setDividerLocation(400);
358 searchField.setText(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.searchField.text"));
360 searchButtonGroup.add(searchNameRadio);
361 searchNameRadio.setSelected(
true);
362 org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.searchNameRadio.text"));
364 searchButtonGroup.add(searchAccountRadio);
365 org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.searchAccountRadio.text"));
367 org.openide.awt.Mnemonics.setLocalizedText(searchBtn,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.searchBtn.text"));
369 resultsTable.setToolTipText(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.resultsTable.toolTipText"));
370 resultsTable.getTableHeader().setReorderingAllowed(
false);
371 resultsPane.setViewportView(resultsTable);
372 if (resultsTable.getColumnModel().getColumnCount() > 0) {
373 resultsTable.getColumnModel().getColumn(0).setMaxWidth(25);
374 resultsTable.getColumnModel().getColumn(0).setHeaderValue(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.resultsTable.columnModel.title0"));
375 resultsTable.getColumnModel().getColumn(1).setHeaderValue(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.resultsTable.columnModel.title1"));
378 org.openide.awt.Mnemonics.setLocalizedText(createAccountBtn,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.createAccountBtn.text"));
380 org.openide.awt.Mnemonics.setLocalizedText(editBtn,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.editBtn.text"));
381 editBtn.setEnabled(
false);
383 org.openide.awt.Mnemonics.setLocalizedText(deleteBtn,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.deleteBtn.text"));
384 deleteBtn.setEnabled(
false);
386 org.openide.awt.Mnemonics.setLocalizedText(createBtn,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.createBtn.text"));
388 org.openide.awt.Mnemonics.setLocalizedText(cbFilterByKeyword,
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class,
"PersonasTopComponent.cbFilterByKeyword.text"));
389 cbFilterByKeyword.addActionListener(
new java.awt.event.ActionListener() {
390 public void actionPerformed(java.awt.event.ActionEvent evt) {
391 cbFilterByKeywordActionPerformed(evt);
395 javax.swing.GroupLayout searchPanelLayout =
new javax.swing.GroupLayout(searchPanel);
396 searchPanel.setLayout(searchPanelLayout);
397 searchPanelLayout.setHorizontalGroup(
398 searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
399 .addGroup(searchPanelLayout.createSequentialGroup()
401 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
402 .addComponent(createButtonSeparator)
403 .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
404 .addComponent(searchField)
405 .addGroup(searchPanelLayout.createSequentialGroup()
406 .addComponent(searchNameRadio)
407 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
408 .addComponent(searchAccountRadio)
409 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
410 .addComponent(searchBtn))
411 .addGroup(searchPanelLayout.createSequentialGroup()
412 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
413 .addComponent(createAccountBtn)
414 .addGroup(searchPanelLayout.createSequentialGroup()
415 .addComponent(createBtn)
416 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
417 .addComponent(editBtn)
418 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
419 .addComponent(deleteBtn))
420 .addComponent(cbFilterByKeyword))
421 .addGap(0, 50, Short.MAX_VALUE)))
424 searchPanelLayout.setVerticalGroup(
425 searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
426 .addGroup(searchPanelLayout.createSequentialGroup()
427 .addComponent(cbFilterByKeyword)
429 .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
430 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
431 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
432 .addComponent(searchNameRadio)
433 .addComponent(searchAccountRadio)
434 .addComponent(searchBtn))
435 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
436 .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 302, javax.swing.GroupLayout.PREFERRED_SIZE)
437 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
438 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
439 .addComponent(editBtn)
440 .addComponent(createBtn)
441 .addComponent(deleteBtn))
442 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
443 .addComponent(createButtonSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
444 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
445 .addComponent(createAccountBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
449 mainSplitPane.setLeftComponent(searchPanel);
451 detailsScrollPane.setViewportView(detailsPanel);
453 mainSplitPane.setRightComponent(detailsScrollPane);
455 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
456 this.setLayout(layout);
457 layout.setHorizontalGroup(
458 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
459 .addComponent(introTextScrollPane)
460 .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 724, Short.MAX_VALUE)
462 layout.setVerticalGroup(
463 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
464 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
465 .addComponent(introTextScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
466 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
467 .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE))
472 setKeywordSearchEnabled(cbFilterByKeyword.isSelected(),
false);
javax.swing.JRadioButton searchNameRadio
javax.swing.JCheckBox cbFilterByKeyword
javax.swing.JPanel searchPanel
void handleSelectionChange()
void handleSelectionChange(ListSelectionEvent e)
javax.swing.JButton createAccountBtn
javax.swing.JSplitPane mainSplitPane
static Collection< Persona > getPersonaByName(String partialName)
javax.swing.JScrollPane introTextScrollPane
javax.swing.JTextField searchField
javax.swing.JScrollPane resultsPane
void cbFilterByKeywordActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JButton searchBtn
javax.swing.JSeparator createButtonSeparator
javax.swing.JButton editBtn
javax.swing.JScrollPane detailsScrollPane
javax.swing.JTable resultsTable
javax.swing.JButton deleteBtn
void resetSearchControls()
void setKeywordSearchEnabled(boolean selected, boolean setFilterCb)
javax.swing.ButtonGroup searchButtonGroup
javax.swing.JTextArea introText
synchronized static Logger getLogger(String name)
org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel
void updateResultsTable(Collection< Persona > results)
javax.swing.JButton createBtn
static Collection< Persona > getPersonaByAccountIdentifierLike(String partialName)
javax.swing.JRadioButton searchAccountRadio
static boolean isEnabled()