diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index de261f16d2..12ba493380 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -190,3 +190,5 @@ ViewPreferencesPanel.hideRejectedResultsCheckbox.text=Hide rejected results ViewPreferencesPanel.hideOtherUsersTagsLabel.text=Hide other users' tags in the: ViewPreferencesPanel.centralRepoLabel.text=Do not use Central Repository for: ViewPreferencesPanel.commentsOccurencesColumnsCheckbox.text=C(omments) and O(ccurences) columns to reduce loading times +ViewPreferencesPanel.deletedFilesLimitCheckbox.text=Limit to 10,000 +ViewPreferencesPanel.deletedFilesLimitLabel.text=Limit number of deleted files displayed: diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form index 5ab351c170..ddeb57bd74 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.form @@ -79,65 +79,72 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -174,6 +181,11 @@ + + + + + @@ -327,6 +339,23 @@ + + + + + + + + + + + + + + + + + @@ -388,7 +417,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java index 7ab3bbc84e..51d4120449 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ViewPreferencesPanel.java @@ -25,6 +25,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CasePreferences; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; /** @@ -61,10 +62,12 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { dataSourcesHideSlackCheckbox.setSelected(UserPreferences.hideSlackFilesInDataSourcesTree()); viewsHideSlackCheckbox.setSelected(UserPreferences.hideSlackFilesInViewsTree()); - + commentsOccurencesColumnsCheckbox.setEnabled(EamDbUtil.useCentralRepo()); commentsOccurencesColumnsCheckbox.setSelected(UserPreferences.hideCentralRepoCommentsAndOccurrences()); + deletedFilesLimitCheckbox.setSelected(DeletedFilePreferences.getDefault().getShouldLimitDeletedFiles()); + // Current Case Settings boolean caseIsOpen = Case.isCaseOpen(); currentCaseSettingsPanel.setEnabled(caseIsOpen); @@ -91,6 +94,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { storeGroupItemsInTreeByDataSource(); DirectoryTreeTopComponent.getDefault().setShowRejectedResults(hideRejectedResultsCheckbox.isSelected() == false); + + DeletedFilePreferences.getDefault().setShouldLimitDeletedFiles(deletedFilesLimitCheckbox.isSelected()); } /** @@ -135,6 +140,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { hideOtherUsersTagsLabel = new javax.swing.JLabel(); commentsOccurencesColumnsCheckbox = new javax.swing.JCheckBox(); centralRepoLabel = new javax.swing.JLabel(); + deletedFilesLimitCheckbox = new javax.swing.JCheckBox(); + deletedFilesLimitLabel = new javax.swing.JLabel(); currentCaseSettingsPanel = new javax.swing.JPanel(); groupByDataSourceCheckbox = new javax.swing.JCheckBox(); currentSessionSettingsPanel = new javax.swing.JPanel(); @@ -228,6 +235,15 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { org.openide.awt.Mnemonics.setLocalizedText(centralRepoLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.centralRepoLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deletedFilesLimitCheckbox, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.deletedFilesLimitCheckbox.text")); // NOI18N + deletedFilesLimitCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + deletedFilesLimitCheckboxActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(deletedFilesLimitLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.deletedFilesLimitLabel.text")); // NOI18N + javax.swing.GroupLayout globalSettingsPanelLayout = new javax.swing.GroupLayout(globalSettingsPanel); globalSettingsPanel.setLayout(globalSettingsPanelLayout); globalSettingsPanelLayout.setHorizontalGroup( @@ -235,46 +251,51 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { .addGroup(globalSettingsPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(globalSettingsPanelLayout.createSequentialGroup() - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(hideKnownFilesLabel) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(globalSettingsPanelLayout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(dataSourcesHideSlackCheckbox) - .addComponent(viewsHideSlackCheckbox))) - .addComponent(hideSlackFilesLabel)) - .addGroup(globalSettingsPanelLayout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(dataSourcesHideKnownCheckbox) - .addComponent(viewsHideKnownCheckbox))))) - .addGap(18, 18, 18) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(displayTimeLabel) - .addGroup(globalSettingsPanelLayout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(keepCurrentViewerRadioButton) - .addComponent(useBestViewerRadioButton) - .addComponent(useGMTTimeRadioButton) - .addComponent(useLocalTimeRadioButton))) - .addComponent(selectFileLabel))) - .addComponent(hideOtherUsersTagsLabel) - .addComponent(centralRepoLabel) .addGroup(globalSettingsPanelLayout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(commentsOccurencesColumnsCheckbox) - .addComponent(hideOtherUsersTagsCheckbox)))) - .addContainerGap(16, Short.MAX_VALUE)) + .addComponent(hideOtherUsersTagsCheckbox) + .addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(hideKnownFilesLabel) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dataSourcesHideSlackCheckbox) + .addComponent(viewsHideSlackCheckbox))) + .addComponent(hideSlackFilesLabel)) + .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dataSourcesHideKnownCheckbox) + .addComponent(viewsHideKnownCheckbox))))) + .addGap(18, 18, 18) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(displayTimeLabel) + .addGroup(globalSettingsPanelLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(keepCurrentViewerRadioButton) + .addComponent(useBestViewerRadioButton) + .addComponent(useGMTTimeRadioButton) + .addComponent(useLocalTimeRadioButton))) + .addComponent(selectFileLabel))) + .addComponent(hideOtherUsersTagsLabel) + .addComponent(centralRepoLabel) + .addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 10, Short.MAX_VALUE))) + .addContainerGap()) ); globalSettingsPanelLayout.setVerticalGroup( globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(globalSettingsPanelLayout.createSequentialGroup() - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap() .addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(globalSettingsPanelLayout.createSequentialGroup() .addComponent(hideKnownFilesLabel) @@ -307,7 +328,12 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(centralRepoLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(commentsOccurencesColumnsCheckbox)) + .addComponent(commentsOccurencesColumnsCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(deletedFilesLimitLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) ); currentCaseSettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.currentCaseSettingsPanel.border.title"))); // NOI18N @@ -350,7 +376,7 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { currentSessionSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(currentSessionSettingsPanelLayout.createSequentialGroup() .addContainerGap() - .addComponent(hideRejectedResultsCheckbox) + .addComponent(hideRejectedResultsCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 259, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); currentSessionSettingsPanelLayout.setVerticalGroup( @@ -501,6 +527,14 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { } }//GEN-LAST:event_commentsOccurencesColumnsCheckboxActionPerformed + private void deletedFilesLimitCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deletedFilesLimitCheckboxActionPerformed + if (immediateUpdates) { + DeletedFilePreferences.getDefault().setShouldLimitDeletedFiles(deletedFilesLimitCheckbox.isSelected()); + } else { + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + }//GEN-LAST:event_deletedFilesLimitCheckboxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel centralRepoLabel; @@ -509,6 +543,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { private javax.swing.JPanel currentSessionSettingsPanel; private javax.swing.JCheckBox dataSourcesHideKnownCheckbox; private javax.swing.JCheckBox dataSourcesHideSlackCheckbox; + private javax.swing.JCheckBox deletedFilesLimitCheckbox; + private javax.swing.JLabel deletedFilesLimitLabel; private javax.swing.JLabel displayTimeLabel; private javax.swing.JPanel globalSettingsPanel; private javax.swing.JCheckBox groupByDataSourceCheckbox; @@ -527,4 +563,4 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel { private javax.swing.JCheckBox viewsHideKnownCheckbox; private javax.swing.JCheckBox viewsHideSlackCheckbox; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index 57bd68911c..55384344bc 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import static org.sleuthkit.autopsy.datamodel.Bundle.*; +import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; @@ -111,11 +112,11 @@ public class DeletedContent implements AutopsyVisitableItem { this.skCase = skCase; this.datasourceObjId = dsObjId; } - + long filteringDataSourceObjId() { return this.datasourceObjId; } - + @Override public T accept(AutopsyItemVisitor visitor) { return visitor.visit(this); @@ -191,9 +192,10 @@ public class DeletedContent implements AutopsyVisitableItem { * fired. Other nodes are listening to this for changes. */ private static final class DeletedContentsChildrenObservable extends Observable { + private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of( - Case.Events.DATA_SOURCE_ADDED, - Case.Events.CURRENT_CASE + Case.Events.DATA_SOURCE_ADDED, + Case.Events.CURRENT_CASE ); DeletedContentsChildrenObservable() { @@ -213,12 +215,11 @@ public class DeletedContent implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** - * + // @@@ COULD CHECK If the new file is deleted - * before notifying... Checking for a current case is a - * stop gap measure + update(); until a different way of - * handling the closing of cases is worked out. - * Currently, remote events may be received for a case - * that is already closed. + * + // @@@ COULD CHECK If the new file is deleted before + * notifying... Checking for a current case is a stop gap + * measure + update(); until a different way of handling the + * closing of cases is worked out. Currently, remote events + * may be received for a case that is already closed. */ try { Case.getCurrentCaseThrows(); @@ -234,10 +235,10 @@ public class DeletedContent implements AutopsyVisitableItem { || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { /** - * Checking for a current case is a stop gap measure - * until a different way of handling the closing of - * cases is worked out. Currently, remote events may be - * received for a case that is already closed. + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. */ try { Case.getCurrentCaseThrows(); @@ -282,7 +283,7 @@ public class DeletedContent implements AutopsyVisitableItem { // Use version that has observer for updates @Deprecated DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, long dsObjId) { - super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId ), true), Lookups.singleton(filter.getDisplayName())); + super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.datasourceObjId = dsObjId; init(); @@ -366,7 +367,7 @@ public class DeletedContent implements AutopsyVisitableItem { private final SleuthkitCase skCase; private final DeletedContent.DeletedContentFilter filter; private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName()); - private static final int MAX_OBJECTS = 10001; + private final Observable notifier; private final long datasourceObjId; @@ -385,7 +386,7 @@ public class DeletedContent implements AutopsyVisitableItem { @Override public void update(Observable o, Object arg) { refresh(true); - } + } } @Override @@ -408,18 +409,19 @@ public class DeletedContent implements AutopsyVisitableItem { + "There are more Deleted Files than can be displayed." + " Only the first {0} Deleted Files will be shown."}) protected boolean createKeys(List list) { + DeletedFilePreferences deletedPreferences = DeletedFilePreferences.getDefault(); List queryList = runFsQuery(); - if (queryList.size() == MAX_OBJECTS) { + if (deletedPreferences.getShouldLimitDeletedFiles() && queryList.size() == deletedPreferences.getDeletedFilesLimit()) { queryList.remove(queryList.size() - 1); // only show the dialog once - not each time we refresh if (maxFilesDialogShown == false) { maxFilesDialogShown = true; SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - DeletedContent_createKeys_maxObjects_msg(MAX_OBJECTS - 1)) + DeletedContent_createKeys_maxObjects_msg(deletedPreferences.getDeletedFilesLimit() - 1)) ); } - } + } list.addAll(queryList); return true; } @@ -463,10 +465,12 @@ public class DeletedContent implements AutopsyVisitableItem { } if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { - query += " AND data_source_obj_id = " + filteringDSObjId; + query += " AND data_source_obj_id = " + filteringDSObjId; + } + DeletedFilePreferences deletedPreferences = DeletedFilePreferences.getDefault(); + if (deletedPreferences.getShouldLimitDeletedFiles()) { + query += " LIMIT " + deletedPreferences.getDeletedFilesLimit(); //NON-NLS } - - query += " LIMIT " + MAX_OBJECTS; //NON-NLS return query; } diff --git a/Core/src/org/sleuthkit/autopsy/deletedFiles/DeletedFilePreferences.java b/Core/src/org/sleuthkit/autopsy/deletedFiles/DeletedFilePreferences.java new file mode 100644 index 0000000000..4eadd3611d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/deletedFiles/DeletedFilePreferences.java @@ -0,0 +1,171 @@ +/* + * 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.deletedFiles; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.CasePreferences; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; + +/** + * Class to store settings related to the display of deleted files. + */ +public class DeletedFilePreferences { + + private static final String SETTINGS_FILE = "DeletedFilePreferences.properties"; //NON-NLS + private static final String KEY_LIMIT_DELETED_FILES = "limitDeletedFiles"; //NON-NLS + private static final String KEY_LIMIT_VALUE = "limitValue"; + private static final String VALUE_TRUE = "true"; //NON-NLS + private static final String VALUE_FALSE = "false"; //NON-NLS + private static final int DEFAULT_MAX_OBJECTS = 10001; + private static final Logger logger = Logger.getLogger(CasePreferences.class.getName()); + private static DeletedFilePreferences defaultInstance; + private static boolean limitDeletedFiles = true; + private static int deletedFilesLimit = DEFAULT_MAX_OBJECTS; + + /** + * Get the settings for the display of deleted files. + * + * @return defaultInstance with freshly loaded + */ + public static synchronized DeletedFilePreferences getDefault() { + if (defaultInstance == null) { + defaultInstance = new DeletedFilePreferences(); + } + defaultInstance.loadFromStorage(); + return defaultInstance; + } + + /** + * Prevent instantiation. + */ + private DeletedFilePreferences() { + } + + /** + * Get the 'limitDeletedFiles' value. This can be true or false. It will + * default to true if it was not saved correctly previously.s + * + * @return true if the number of deleted files displayed should be limied, + * false if it should not be limited. + */ + public boolean getShouldLimitDeletedFiles() { + return limitDeletedFiles; + } + + /** + * Set the 'limitDeletedFiles' value to true or false. + * + * @param value true if the number of deleted files displayed should be + * limied, false if it should not be limited. + */ + public void setShouldLimitDeletedFiles(boolean value) { + limitDeletedFiles = value; + saveToStorage(); + DirectoryTreeTopComponent.getDefault().refreshContentTreeSafe(); + } + + /** + * Get the 'limitValue' value. This is an interger value and will default to + * DEFAULT_MAX_OBJECTS if it was not previously saved correctly. + * + * @return an integer representing the max number of deleted files to display. + */ + public int getDeletedFilesLimit() { + return deletedFilesLimit; + } + + /** + * Set the 'limitValue' for max number of deleted files to display. + * + * @param value an integer representing the max number of deleted files to display. + */ + public void setDeletedFilesLimit(int value) { + deletedFilesLimit = value; + saveToStorage(); + DirectoryTreeTopComponent.getDefault().refreshContentTreeSafe(); + + } + + /** + * Load deleted file preferences from the settings file. + */ + private void loadFromStorage() { + Path settingsFile = Paths.get(PlatformUtil.getUserConfigDirectory(), SETTINGS_FILE); //NON-NLS + if (settingsFile.toFile().exists()) { + // Read the settings + try (InputStream inputStream = Files.newInputStream(settingsFile)) { + Properties props = new Properties(); + props.load(inputStream); + String limitDeletedFilesValue = props.getProperty(KEY_LIMIT_DELETED_FILES); + if (limitDeletedFilesValue != null) { + switch (limitDeletedFilesValue) { + case VALUE_TRUE: + limitDeletedFiles = true; + break; + case VALUE_FALSE: + limitDeletedFiles = false; + break; + default: + logger.log(Level.WARNING, String.format("Unexpected value '%s' for limit deleted files using value of true instead", + limitDeletedFilesValue)); + limitDeletedFiles = true; + break; + } + } + String limitValue = props.getProperty(KEY_LIMIT_VALUE); + try { + if (limitValue != null) { + deletedFilesLimit = Integer.valueOf(limitValue); + + } + } catch (NumberFormatException ex) { + logger.log(Level.INFO, String.format("Unexpected value '%s' for limit, expected an integer using default of 10,001 instead", + limitValue)); + deletedFilesLimit = DEFAULT_MAX_OBJECTS; + } + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error reading deletedFilesPreferences file", ex); + } + } + } + + /** + * Store deleted file preferences in the settings file. + */ + private void saveToStorage() { + Path settingsFile = Paths.get(PlatformUtil.getUserConfigDirectory(), SETTINGS_FILE); //NON-NLS + Properties props = new Properties(); + props.setProperty(KEY_LIMIT_DELETED_FILES, (limitDeletedFiles ? VALUE_TRUE : VALUE_FALSE)); + props.setProperty(KEY_LIMIT_VALUE, String.valueOf(deletedFilesLimit)); + try (OutputStream fos = Files.newOutputStream(settingsFile)) { + props.store(fos, ""); //NON-NLS + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error writing deletedFilesPreferences file", ex); + } + } +}