19 package org.sleuthkit.autopsy.discovery.ui;
21 import com.github.lgooddatepicker.optionalusertools.DateChangeListener;
22 import com.github.lgooddatepicker.zinternaltools.DateChangeEvent;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.time.LocalDate;
26 import java.time.Period;
27 import java.time.ZoneId;
28 import java.util.List;
29 import java.util.logging.Level;
31 import javax.swing.JCheckBox;
32 import javax.swing.JLabel;
33 import javax.swing.JSpinner;
34 import javax.swing.event.ListSelectionListener;
35 import org.openide.util.NbBundle;
46 class DateFilterPanel
extends AbstractDiscoveryFilterPanel {
48 private static final long serialVersionUID = 1L;
49 private static final long SECS_PER_DAY = 86400;
50 private static final Logger logger = Logger.getLogger(DateFilterPanel.class.getName());
55 @NbBundle.Messages({
"# {0} - timeZone",
56 "DateFilterPanel.dateRange.text=Date Range ({0}):"})
57 @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
60 rangeRadioButton.setText(Bundle.DateFilterPanel_dateRange_text(Utils.getUserPreferredZoneId().toString()));
62 ((JSpinner.DefaultEditor) daysSpinner.getEditor()).getTextField().setEditable(
false);
64 startDatePicker.getComponentDateTextField().setEditable(
false);
65 endDatePicker.getComponentDateTextField().setEditable(
false);
74 private void initComponents() {
76 buttonGroup1 =
new javax.swing.ButtonGroup();
77 dateFilterCheckBox =
new javax.swing.JCheckBox();
78 jPanel1 =
new javax.swing.JPanel();
79 daysSpinner =
new javax.swing.JSpinner();
80 daysLabel =
new javax.swing.JLabel();
81 mostRecentRadioButton =
new javax.swing.JRadioButton();
82 startCheckBox =
new javax.swing.JCheckBox();
83 startDatePicker =
new com.github.lgooddatepicker.components.DatePicker();
84 endDatePicker =
new com.github.lgooddatepicker.components.DatePicker();
85 endCheckBox =
new javax.swing.JCheckBox();
86 rangeRadioButton =
new javax.swing.JRadioButton();
88 org.openide.awt.Mnemonics.setLocalizedText(dateFilterCheckBox,
org.openide.util.NbBundle.getMessage(DateFilterPanel.class,
"DateFilterPanel.dateFilterCheckBox.text"));
89 dateFilterCheckBox.addActionListener(
new java.awt.event.ActionListener() {
90 public void actionPerformed(java.awt.event.ActionEvent evt) {
91 dateFilterCheckBoxActionPerformed(evt);
95 daysSpinner.setModel(
new javax.swing.SpinnerNumberModel(7, 1, 100000, 1));
96 daysSpinner.setEditor(
new javax.swing.JSpinner.NumberEditor(daysSpinner,
""));
97 daysSpinner.setEnabled(
false);
98 daysSpinner.setPreferredSize(
new java.awt.Dimension(75, 26));
99 daysSpinner.setValue(7);
101 org.openide.awt.Mnemonics.setLocalizedText(daysLabel,
org.openide.util.NbBundle.getMessage(DateFilterPanel.class,
"DateFilterPanel.daysLabel.text"));
102 daysLabel.setEnabled(
false);
104 buttonGroup1.add(mostRecentRadioButton);
105 mostRecentRadioButton.setSelected(
true);
106 org.openide.awt.Mnemonics.setLocalizedText(mostRecentRadioButton,
org.openide.util.NbBundle.getMessage(DateFilterPanel.class,
"DateFilterPanel.mostRecentRadioButton.text"));
107 mostRecentRadioButton.setEnabled(
false);
108 mostRecentRadioButton.addChangeListener(
new javax.swing.event.ChangeListener() {
109 public void stateChanged(javax.swing.event.ChangeEvent evt) {
110 mostRecentRadioButtonStateChanged(evt);
114 org.openide.awt.Mnemonics.setLocalizedText(startCheckBox,
org.openide.util.NbBundle.getMessage(DateFilterPanel.class,
"DateFilterPanel.startCheckBox.text"));
115 startCheckBox.setEnabled(
false);
116 startCheckBox.addChangeListener(
new javax.swing.event.ChangeListener() {
117 public void stateChanged(javax.swing.event.ChangeEvent evt) {
118 startCheckBoxStateChanged(evt);
122 startDatePicker.setDate(LocalDate.now());
123 startDatePicker.setEnabled(
false);
124 startDatePicker.setMinimumSize(
new java.awt.Dimension(60, 22));
125 startDatePicker.setPreferredSize(
new java.awt.Dimension(110, 22));
127 endDatePicker.setDate(LocalDate.now());
128 endDatePicker.setEnabled(
false);
129 endDatePicker.setMinimumSize(
new java.awt.Dimension(60, 22));
130 endDatePicker.setPreferredSize(
new java.awt.Dimension(110, 22));
132 org.openide.awt.Mnemonics.setLocalizedText(endCheckBox,
org.openide.util.NbBundle.getMessage(DateFilterPanel.class,
"DateFilterPanel.endCheckBox.text"));
133 endCheckBox.setEnabled(
false);
134 endCheckBox.addChangeListener(
new javax.swing.event.ChangeListener() {
135 public void stateChanged(javax.swing.event.ChangeEvent evt) {
136 endCheckBoxStateChanged(evt);
140 buttonGroup1.add(rangeRadioButton);
141 rangeRadioButton.setEnabled(
false);
142 rangeRadioButton.addChangeListener(
new javax.swing.event.ChangeListener() {
143 public void stateChanged(javax.swing.event.ChangeEvent evt) {
144 rangeRadioButtonStateChanged(evt);
148 javax.swing.GroupLayout jPanel1Layout =
new javax.swing.GroupLayout(jPanel1);
149 jPanel1.setLayout(jPanel1Layout);
150 jPanel1Layout.setHorizontalGroup(
151 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
152 .addGroup(jPanel1Layout.createSequentialGroup()
153 .addComponent(mostRecentRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
154 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
155 .addComponent(daysSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
156 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
157 .addComponent(daysLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE))
158 .addComponent(rangeRadioButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
159 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
161 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
162 .addComponent(endCheckBox)
163 .addComponent(startCheckBox))
164 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
165 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
166 .addComponent(endDatePicker, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
167 .addComponent(startDatePicker, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
169 jPanel1Layout.setVerticalGroup(
170 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
171 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
172 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
173 .addComponent(mostRecentRadioButton)
174 .addComponent(daysSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
175 .addComponent(daysLabel))
176 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
177 .addComponent(rangeRadioButton)
178 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
179 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
180 .addComponent(startCheckBox)
181 .addComponent(startDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
182 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
183 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
184 .addComponent(endCheckBox)
185 .addComponent(endDatePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
189 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
190 this.setLayout(layout);
191 layout.setHorizontalGroup(
192 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
193 .addGroup(layout.createSequentialGroup()
195 .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
198 layout.setVerticalGroup(
199 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
200 .addGroup(layout.createSequentialGroup()
202 .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
207 private void startCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {
208 startDatePicker.setEnabled(startCheckBox.isEnabled() && startCheckBox.isSelected());
211 private void endCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {
212 endDatePicker.setEnabled(endCheckBox.isEnabled() && endCheckBox.isSelected());
215 private void dateFilterCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {
216 rangeRadioButton.setEnabled(dateFilterCheckBox.isSelected());
217 mostRecentRadioButton.setEnabled(dateFilterCheckBox.isSelected());
218 rangeRadioButton.firePropertyChange(
"DateFilterChange", !rangeRadioButton.isEnabled(), rangeRadioButton.isEnabled());
219 mostRecentRadioButton.firePropertyChange(
"DateFilterChange", !mostRecentRadioButton.isEnabled(), mostRecentRadioButton.isEnabled());
222 private void mostRecentRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {
223 daysSpinner.setEnabled(mostRecentRadioButton.isSelected());
224 daysLabel.setEnabled(mostRecentRadioButton.isSelected());
227 private void rangeRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {
228 startCheckBox.setEnabled(rangeRadioButton.isEnabled() && rangeRadioButton.isSelected());
229 endCheckBox.setEnabled(rangeRadioButton.isEnabled() && rangeRadioButton.isSelected());
230 startCheckBox.firePropertyChange(
"StartButtonChange",
true,
false);
231 endCheckBox.firePropertyChange(
"EndButtonChange",
true,
false);
234 @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
236 void configurePanel(
boolean selected, List<?> selectedItems) {
237 dateFilterCheckBox.setSelected(selected);
238 if (dateFilterCheckBox.isEnabled() && dateFilterCheckBox.isSelected()) {
239 mostRecentRadioButton.setEnabled(
true);
240 rangeRadioButton.setEnabled(
true);
241 mostRecentRadioButton.setSelected(
true);
243 mostRecentRadioButton.setEnabled(
false);
244 rangeRadioButton.setEnabled(
false);
248 @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
250 JCheckBox getCheckbox() {
251 return dateFilterCheckBox;
255 JLabel getAdditionalLabel() {
259 @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
261 void addListeners(ActionListener actionListener, ListSelectionListener listListener) {
262 dateFilterCheckBox.addActionListener(actionListener);
263 startCheckBox.addActionListener(actionListener);
264 endCheckBox.addActionListener(actionListener);
265 rangeRadioButton.addActionListener(actionListener);
266 mostRecentRadioButton.addActionListener(actionListener);
267 startDatePicker.addDateChangeListener(
new DateChangeListener() {
269 public void dateChanged(DateChangeEvent event) {
270 actionListener.actionPerformed(
new ActionEvent(startDatePicker, ActionEvent.ACTION_PERFORMED,
"StartDateChanged"));
273 endDatePicker.addDateChangeListener(
new DateChangeListener() {
275 public void dateChanged(DateChangeEvent event) {
276 actionListener.actionPerformed(
new ActionEvent(endDatePicker, ActionEvent.ACTION_PERFORMED,
"EndDateChanged"));
281 @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
282 @NbBundle.Messages({
"DateFilterPanel.invalidRange.text=Range or Only Last must be selected.",
283 "DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter.",
284 "DateFilterPanel.startAfterEnd.text=Start date should be before the end date when both are enabled."})
286 String checkForError() {
287 if (dateFilterCheckBox.isSelected()) {
288 if (!(rangeRadioButton.isSelected() || mostRecentRadioButton.isSelected())) {
289 return Bundle.DateFilterPanel_invalidRange_text();
290 }
else if (rangeRadioButton.isSelected() && !(startCheckBox.isSelected() || endCheckBox.isSelected())) {
291 return Bundle.DateFilterPanel_startOrEndNeeded_text();
292 }
else if (startCheckBox.isSelected() && endCheckBox.isSelected() && startDatePicker.getDate().isAfter(endDatePicker.getDate())) {
294 return Bundle.DateFilterPanel_startAfterEnd_text();
300 @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
302 AbstractFilter getFilter() {
303 if (dateFilterCheckBox.isSelected()) {
304 LocalDate startDate = LocalDate.MIN;
305 LocalDate endDate = LocalDate.MAX;
306 ZoneId zone = Utils.getUserPreferredZoneId();
307 if (rangeRadioButton.isSelected() && (startCheckBox.isSelected() || endCheckBox.isSelected())) {
308 if (startCheckBox.isSelected() && startDatePicker.getDate() != null) {
309 startDate = startDatePicker.getDate();
311 if (endCheckBox.isSelected() && endDatePicker.getDate() != null) {
312 endDate = endDatePicker.getDate().plus(Period.ofDays(1));
314 }
else if (dateFilterCheckBox.isSelected() && mostRecentRadioButton.isSelected()) {
316 startDate = LocalDate.ofEpochDay(Case.getCurrentCase().getSleuthkitCase().getTimelineManager().getMaxEventTime() / SECS_PER_DAY).minus(Period.ofDays((Integer) daysSpinner.getValue()));
317 }
catch (TskCoreException ex) {
318 startDate = LocalDate.now().minus(Period.ofDays((Integer) daysSpinner.getValue()));
319 logger.log(Level.WARNING,
"Unable to get most recent event time from database, using current date instead.");
322 return new SearchFiltering.ArtifactDateRangeFilter(startDate.atStartOfDay(zone).toEpochSecond(), endDate.atStartOfDay(zone).toEpochSecond());
327 private javax.swing.ButtonGroup buttonGroup1;
328 private javax.swing.JCheckBox dateFilterCheckBox;
329 private javax.swing.JLabel daysLabel;
330 private javax.swing.JSpinner daysSpinner;
331 private javax.swing.JCheckBox endCheckBox;
332 private com.github.lgooddatepicker.components.DatePicker endDatePicker;
333 private javax.swing.JPanel jPanel1;
334 private javax.swing.JRadioButton mostRecentRadioButton;
335 private javax.swing.JRadioButton rangeRadioButton;
336 private javax.swing.JCheckBox startCheckBox;
337 private com.github.lgooddatepicker.components.DatePicker startDatePicker;
341 void addListSelectionListener(ListSelectionListener listener) {
342 throw new UnsupportedOperationException(
"Not supported yet.");
346 boolean isFilterSupported() {