mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07:42 +00:00
Merge remote-tracking branch 'upstream/release-4.12.0' into 5035-for-PR
This commit is contained in:
commit
557fc43ee0
@ -45,6 +45,9 @@
|
||||
|
||||
<dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/>
|
||||
<dependency conf="core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.3"/>
|
||||
<dependency org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/>
|
||||
<!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
|
||||
<dependency org="javax.ws.rs" name="javax.ws.rs-api" rev="2.0"/>
|
||||
<override org="jakarta.ws.rs" module="jakarta.ws.rs-api" rev="2.1.5"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
@ -111,6 +111,10 @@ file.reference.grpc-context-1.19.0.jar=release/modules/ext/grpc-context-1.19.0.j
|
||||
file.reference.opencensus-api-0.19.2.jar=release/modules/ext/opencensus-api-0.19.2.jar
|
||||
file.reference.opencensus-contrib-http-util-0.19.2.jar=release/modules/ext/opencensus-contrib-http-util-0.19.2.jar
|
||||
file.reference.threetenbp-1.3.3.jar=release/modules/ext/threetenbp-1.3.3.jar
|
||||
file.reference.okhttp-2.7.5-javadoc.jar=release/modules/ext/okhttp-2.7.5-javadoc.jar
|
||||
file.reference.okhttp-2.7.5-sources.jar=release/modules/ext/okhttp-2.7.5-sources.jar
|
||||
file.reference.okhttp-2.7.5.jar=release/modules/ext/okhttp-2.7.5.jar
|
||||
file.reference.okio-1.6.0.jar=release/modules/ext/okio-1.6.0.jar
|
||||
javac.source=1.8
|
||||
javac.compilerargs=-Xlint -Xlint:-serial
|
||||
license.file=../LICENSE-2.0.txt
|
||||
|
@ -773,6 +773,14 @@
|
||||
<runtime-relative-path>ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/okhttp-2.7.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/okhttp-2.7.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/okio-1.6.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/okio-1.6.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
|
@ -238,13 +238,7 @@ OpenMultiUserCasePanel.cancelButton.text=Cancel
|
||||
OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case...
|
||||
OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case
|
||||
OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name
|
||||
LogicalImagerPanel.jLabel1.text=Insert external drive
|
||||
LogicalImagerPanel.scanButton.text=Scan
|
||||
LogicalImagerPanel.jLabel6.text=Or, pick a Logical Imager folder
|
||||
LogicalImagerPanel.browseButton.text=Browse
|
||||
LogicalImagerPanel.topLabel.text=Import Autopsy Imager Results
|
||||
LogicalImagerPanel.selectDriveLabel.text=Select Drive
|
||||
LogicalImagerPanel.messageLabel.text=Error/Status message
|
||||
UnpackagePortableCaseDialog.desc2Label.text=Portable Case Report Module.
|
||||
UnpackagePortableCaseDialog.desc1Label.text=Unpackage a portable case so it can be opened in Autopsy. Portable cases are created through the
|
||||
UnpackagePortableCaseDialog.exitButton.text=Exit
|
||||
@ -259,4 +253,13 @@ UnpackagePortableCaseProgressDialog.cancelButton.text=Cancel
|
||||
UnpackagePortableCaseProgressDialog.okButton.text=OK
|
||||
UnpackagePortableCaseProgressDialog.resultLabel.text=resultLabel
|
||||
UnpackagePortableCaseDialog.extractLabel.text=Folder to extract to:
|
||||
UnpackagePortableCaseDialog.caseLabel.text=Portable Case:
|
||||
UnpackagePortableCaseDialog.caseLabel.text=Portable Case:
|
||||
LogicalImagerPanel.importRadioButton.text=Import From External Drive
|
||||
LogicalImagerPanel.manualRadioButton.text=Manually Choose Folder
|
||||
LogicalImagerPanel.importRadioButton.toolTipText=
|
||||
LogicalImagerPanel.pathTextField.text=
|
||||
LogicalImagerPanel.selectFolderLabel.text=Selected Folder:
|
||||
LogicalImagerPanel.refreshButton.text=Refresh
|
||||
LogicalImagerPanel.selectFromDriveLabel.text=Select Acquisition From Drive
|
||||
LogicalImagerPanel.selectDriveLabel.text=Select Drive
|
||||
LogicalImagerPanel.messageTextArea.text=
|
||||
|
@ -191,7 +191,6 @@ LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}
|
||||
LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected.
|
||||
LogicalImagerPanel.imageTable.columnModel.title0=Hostname
|
||||
LogicalImagerPanel.imageTable.columnModel.title1=Extracted Date
|
||||
LogicalImagerPanel.messageLabel.clickScanOrBrowse=Click SCAN or BROWSE button to find images
|
||||
# {0} - sparseImageDirectory
|
||||
# {1} - image
|
||||
LogicalImagerPanel.messageLabel.directoryDoesNotContainSparseImage=Directory {0} does not contain {1}
|
||||
@ -201,7 +200,6 @@ LogicalImagerPanel.messageLabel.driveHasNoImages=Drive has no images
|
||||
LogicalImagerPanel.messageLabel.noExternalDriveFound=No drive found
|
||||
LogicalImagerPanel.messageLabel.noImageSelected=No image selected
|
||||
LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for sparse_image.vhd ...
|
||||
LogicalImagerPanel.messageLabel.selectedImage=Selected folder
|
||||
LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=Select acquisition from Drive
|
||||
Menu/Case/OpenRecentCase=Open Recent Case
|
||||
CTL_CaseDeleteAction=Delete Case
|
||||
@ -475,13 +473,7 @@ OpenMultiUserCasePanel.cancelButton.text=Cancel
|
||||
OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case...
|
||||
OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case
|
||||
OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name
|
||||
LogicalImagerPanel.jLabel1.text=Insert external drive
|
||||
LogicalImagerPanel.scanButton.text=Scan
|
||||
LogicalImagerPanel.jLabel6.text=Or, pick a Logical Imager folder
|
||||
LogicalImagerPanel.browseButton.text=Browse
|
||||
LogicalImagerPanel.topLabel.text=Import Autopsy Imager Results
|
||||
LogicalImagerPanel.selectDriveLabel.text=Select Drive
|
||||
LogicalImagerPanel.messageLabel.text=Error/Status message
|
||||
UnpackagePortableCaseDialog.desc2Label.text=Portable Case Report Module.
|
||||
UnpackagePortableCaseDialog.desc1Label.text=Unpackage a portable case so it can be opened in Autopsy. Portable cases are created through the
|
||||
UnpackagePortableCaseDialog.exitButton.text=Exit
|
||||
@ -497,3 +489,12 @@ UnpackagePortableCaseProgressDialog.okButton.text=OK
|
||||
UnpackagePortableCaseProgressDialog.resultLabel.text=resultLabel
|
||||
UnpackagePortableCaseDialog.extractLabel.text=Folder to extract to:
|
||||
UnpackagePortableCaseDialog.caseLabel.text=Portable Case:
|
||||
LogicalImagerPanel.importRadioButton.text=Import From External Drive
|
||||
LogicalImagerPanel.manualRadioButton.text=Manually Choose Folder
|
||||
LogicalImagerPanel.importRadioButton.toolTipText=
|
||||
LogicalImagerPanel.pathTextField.text=
|
||||
LogicalImagerPanel.selectFolderLabel.text=Selected Folder:
|
||||
LogicalImagerPanel.refreshButton.text=Refresh
|
||||
LogicalImagerPanel.selectFromDriveLabel.text=Select Acquisition From Drive
|
||||
LogicalImagerPanel.selectDriveLabel.text=Select Drive
|
||||
LogicalImagerPanel.messageTextArea.text=
|
||||
|
@ -1,6 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.6" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<NonVisualComponents>
|
||||
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[0, 65]"/>
|
||||
@ -25,118 +29,146 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="238" max="-2" attributes="0"/>
|
||||
<Component id="topLabel" min="-2" pref="163" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="messageLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="jSeparator1" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="selectDriveLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="289" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="scanButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="126" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="selectFolderLabel" min="-2" pref="81" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
|
||||
<Component id="pathTextField" min="-2" pref="474" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="jSeparator2" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="41" pref="41" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="driveListScrollPane" alignment="0" min="-2" pref="160" max="-2" attributes="0"/>
|
||||
<Component id="refreshButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="imageScrollPane" min="-2" pref="377" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="20" pref="20" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="manualRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="driveListScrollPane" min="-2" pref="211" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="selectAcquisitionFromDriveLabel" min="-2" pref="305" max="-2" attributes="0"/>
|
||||
<Component id="imageScrollPane" min="-2" pref="346" max="-2" attributes="0"/>
|
||||
<Component id="importRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="selectDriveLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="113" max="-2" attributes="0"/>
|
||||
<Component id="selectFromDriveLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="346" max="-2" attributes="0"/>
|
||||
<Component id="jLabel6" min="-2" pref="154" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="144" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" pref="116" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="48" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="568" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="14" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="topLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
|
||||
<Component id="importRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="2" attributes="0">
|
||||
<Component id="selectDriveLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectFromDriveLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="scanButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" pref="4" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="selectDriveLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectAcquisitionFromDriveLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="imageScrollPane" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="driveListScrollPane" pref="194" max="32767" attributes="0"/>
|
||||
<Component id="driveListScrollPane" pref="186" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
|
||||
<Component id="messageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="154" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="manualRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jSeparator2" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="selectFolderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="61" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="topLabel">
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.topLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Component class="javax.swing.JRadioButton" name="importRadioButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="buttonGroup1"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="scanButton">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.scanButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.importRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.importRadioButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="scanButtonActionPerformed"/>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="messageLabel">
|
||||
<Component class="javax.swing.JRadioButton" name="manualRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="buttonGroup1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.manualRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="manualRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="pathTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.messageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.pathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="disabledTextColor" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" id="black" palette="1" red="0" type="palette"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="selectFolderLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.selectFolderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -147,6 +179,13 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="selectFromDriveLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.selectFromDriveLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="driveListScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
@ -162,7 +201,7 @@
|
||||
<Property name="selectionMode" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="driveListMouseClicked"/>
|
||||
<EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="driveListMouseReleased"/>
|
||||
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="driveListKeyReleased"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
@ -171,28 +210,14 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="selectAcquisitionFromDriveLabel">
|
||||
<Component class="javax.swing.JButton" name="refreshButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.selectAcquisitionFromDriveLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel6">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.jLabel6.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="refreshButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="imageScrollPane">
|
||||
@ -224,13 +249,56 @@
|
||||
<Property name="updateSelectionOnSort" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="imageTableMouseClicked"/>
|
||||
<EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="imageTableMouseReleased"/>
|
||||
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="imageTableKeyReleased"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator2">
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextArea" name="messageTextArea">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" id="red" palette="1" red="ff" type="palette"/>
|
||||
</Property>
|
||||
<Property name="lineWrap" type="boolean" value="true"/>
|
||||
<Property name="rows" type="int" value="3"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.messageTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="disabledTextColor" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" id="red" palette="1" red="ff" type="palette"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<BindingProperties>
|
||||
<BindingProperty name="editable" source="messageTextArea" sourcePath="false" target="messageTextArea" targetPath="editable" updateStrategy="0" immediately="false"/>
|
||||
</BindingProperties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileStore;
|
||||
@ -46,7 +47,6 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
* select a file.
|
||||
*/
|
||||
@Messages({
|
||||
"LogicalImagerPanel.messageLabel.selectedImage=Selected folder",
|
||||
"LogicalImagerPanel.messageLabel.noImageSelected=No image selected",
|
||||
"LogicalImagerPanel.messageLabel.driveHasNoImages=Drive has no images",
|
||||
"LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=Select acquisition from Drive",})
|
||||
@ -55,7 +55,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String SPARSE_IMAGE_VHD = "sparse_image.vhd"; //NON-NLS
|
||||
private static final String SELECTED_IMAGE = Bundle.LogicalImagerPanel_messageLabel_selectedImage();
|
||||
private static final String NO_IMAGE_SELECTED = Bundle.LogicalImagerPanel_messageLabel_noImageSelected();
|
||||
private static final String DRIVE_HAS_NO_IMAGES = Bundle.LogicalImagerPanel_messageLabel_driveHasNoImages();
|
||||
private static final String[] EMPTY_LIST_DATA = {};
|
||||
@ -75,6 +74,7 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
private LogicalImagerPanel(String context) {
|
||||
this.contextName = context;
|
||||
initComponents();
|
||||
jScrollPane1.setBorder(null);
|
||||
clearImageTable();
|
||||
}
|
||||
|
||||
@ -86,13 +86,9 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
*
|
||||
* @return instance of the LogicalImagerPanel
|
||||
*/
|
||||
@Messages({
|
||||
"LogicalImagerPanel.messageLabel.clickScanOrBrowse=Click SCAN or BROWSE button to find images"
|
||||
})
|
||||
public static synchronized LogicalImagerPanel createInstance(String context) {
|
||||
LogicalImagerPanel instance = new LogicalImagerPanel(context);
|
||||
// post-constructor initialization of listener support without leaking references of uninitialized objects
|
||||
instance.messageLabel.setText(Bundle.LogicalImagerPanel_messageLabel_clickScanOrBrowse());
|
||||
instance.imageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
return instance;
|
||||
}
|
||||
@ -104,43 +100,68 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
bindingGroup = new org.jdesktop.beansbinding.BindingGroup();
|
||||
|
||||
topLabel = new javax.swing.JLabel();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
scanButton = new javax.swing.JButton();
|
||||
messageLabel = new javax.swing.JLabel();
|
||||
buttonGroup1 = new javax.swing.ButtonGroup();
|
||||
browseButton = new javax.swing.JButton();
|
||||
importRadioButton = new javax.swing.JRadioButton();
|
||||
manualRadioButton = new javax.swing.JRadioButton();
|
||||
pathTextField = new javax.swing.JTextField();
|
||||
selectFolderLabel = new javax.swing.JLabel();
|
||||
selectDriveLabel = new javax.swing.JLabel();
|
||||
selectFromDriveLabel = new javax.swing.JLabel();
|
||||
driveListScrollPane = new javax.swing.JScrollPane();
|
||||
driveList = new javax.swing.JList<>();
|
||||
selectAcquisitionFromDriveLabel = new javax.swing.JLabel();
|
||||
jLabel6 = new javax.swing.JLabel();
|
||||
browseButton = new javax.swing.JButton();
|
||||
refreshButton = new javax.swing.JButton();
|
||||
imageScrollPane = new javax.swing.JScrollPane();
|
||||
imageTable = new javax.swing.JTable();
|
||||
jSeparator1 = new javax.swing.JSeparator();
|
||||
jSeparator2 = new javax.swing.JSeparator();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
messageTextArea = new javax.swing.JTextArea();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(0, 65));
|
||||
setPreferredSize(new java.awt.Dimension(403, 65));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(topLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.topLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.jLabel1.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(scanButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.scanButton.text")); // NOI18N
|
||||
scanButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.browseButton.text")); // NOI18N
|
||||
browseButton.setEnabled(false);
|
||||
browseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
scanButtonActionPerformed(evt);
|
||||
browseButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(messageLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageLabel.text")); // NOI18N
|
||||
buttonGroup1.add(importRadioButton);
|
||||
importRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(importRadioButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.importRadioButton.text")); // NOI18N
|
||||
importRadioButton.setToolTipText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.importRadioButton.toolTipText")); // NOI18N
|
||||
importRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
importRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
buttonGroup1.add(manualRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(manualRadioButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.manualRadioButton.text")); // NOI18N
|
||||
manualRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
manualRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
pathTextField.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.pathTextField.text")); // NOI18N
|
||||
pathTextField.setDisabledTextColor(java.awt.Color.black);
|
||||
pathTextField.setEnabled(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectFolderLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectFolderLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectDriveLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectFromDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectFromDriveLabel.text")); // NOI18N
|
||||
|
||||
driveList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
driveList.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
driveListMouseClicked(evt);
|
||||
public void mouseReleased(java.awt.event.MouseEvent evt) {
|
||||
driveListMouseReleased(evt);
|
||||
}
|
||||
});
|
||||
driveList.addKeyListener(new java.awt.event.KeyAdapter() {
|
||||
@ -150,14 +171,10 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
});
|
||||
driveListScrollPane.setViewportView(driveList);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectAcquisitionFromDriveLabel, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.selectAcquisitionFromDriveLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.jLabel6.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.browseButton.text")); // NOI18N
|
||||
browseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.refreshButton.text")); // NOI18N
|
||||
refreshButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
browseButtonActionPerformed(evt);
|
||||
refreshButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
@ -178,8 +195,8 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
imageTable.getTableHeader().setReorderingAllowed(false);
|
||||
imageTable.setUpdateSelectionOnSort(false);
|
||||
imageTable.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
imageTableMouseClicked(evt);
|
||||
public void mouseReleased(java.awt.event.MouseEvent evt) {
|
||||
imageTableMouseReleased(evt);
|
||||
}
|
||||
});
|
||||
imageTable.addKeyListener(new java.awt.event.KeyAdapter() {
|
||||
@ -190,72 +207,94 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
imageScrollPane.setViewportView(imageTable);
|
||||
imageTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
jScrollPane1.setBorder(null);
|
||||
|
||||
messageTextArea.setBackground(new java.awt.Color(240, 240, 240));
|
||||
messageTextArea.setColumns(20);
|
||||
messageTextArea.setForeground(java.awt.Color.red);
|
||||
messageTextArea.setLineWrap(true);
|
||||
messageTextArea.setRows(3);
|
||||
messageTextArea.setText(org.openide.util.NbBundle.getMessage(LogicalImagerPanel.class, "LogicalImagerPanel.messageTextArea.text")); // NOI18N
|
||||
messageTextArea.setBorder(null);
|
||||
messageTextArea.setDisabledTextColor(java.awt.Color.red);
|
||||
messageTextArea.setEnabled(false);
|
||||
messageTextArea.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
|
||||
org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, messageTextArea, org.jdesktop.beansbinding.ELProperty.create("false"), messageTextArea, org.jdesktop.beansbinding.BeanProperty.create("editable"));
|
||||
bindingGroup.addBinding(binding);
|
||||
|
||||
jScrollPane1.setViewportView(messageTextArea);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(238, 238, 238)
|
||||
.addComponent(topLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 163, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(28, 28, 28)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(messageLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(selectDriveLabel)
|
||||
.addGap(289, 289, 289))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addComponent(scanButton)
|
||||
.addGap(126, 126, 126)))
|
||||
.addGap(36, 36, 36)
|
||||
.addComponent(browseButton))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(driveListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 211, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(28, 28, 28)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(selectAcquisitionFromDriveLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 346, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(346, 346, 346)
|
||||
.addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 154, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(144, 144, 144)
|
||||
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 116, javax.swing.GroupLayout.PREFERRED_SIZE))))
|
||||
.addContainerGap(48, Short.MAX_VALUE))))
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(selectFolderLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(13, 13, 13)
|
||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 474, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(41, 41, 41)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(driveListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(refreshButton))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 377, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(20, 20, 20)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(manualRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(browseButton))
|
||||
.addComponent(importRadioButton)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(selectDriveLabel)
|
||||
.addGap(113, 113, 113)
|
||||
.addComponent(selectFromDriveLabel))))))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 568, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap(14, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(topLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel1)
|
||||
.addComponent(jLabel6))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(scanButton)
|
||||
.addComponent(browseButton))
|
||||
.addGap(16, 16, 16)
|
||||
.addComponent(importRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
|
||||
.addComponent(selectDriveLabel)
|
||||
.addComponent(selectAcquisitionFromDriveLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(selectFromDriveLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
||||
.addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 194, Short.MAX_VALUE))
|
||||
.addGap(26, 26, 26)
|
||||
.addComponent(messageLabel)
|
||||
.addGap(154, 154, 154))
|
||||
.addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 186, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(refreshButton)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(browseButton)
|
||||
.addComponent(manualRadioButton))
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(selectFolderLabel)
|
||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(6, 6, 6))
|
||||
);
|
||||
|
||||
bindingGroup.bind();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
public static String humanReadableByteCount(long bytes, boolean si) {
|
||||
@ -268,47 +307,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); //NON-NLS
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for sparse_image.vhd ...",
|
||||
"LogicalImagerPanel.messageLabel.noExternalDriveFound=No drive found"
|
||||
})
|
||||
private void scanButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scanButtonActionPerformed
|
||||
// Scan external drives for sparse_image.vhd
|
||||
clearImageTable();
|
||||
setNormalMessage(Bundle.LogicalImagerPanel_messageLabel_scanningExternalDrives());
|
||||
List<String> listData = new ArrayList<>();
|
||||
File[] roots = File.listRoots();
|
||||
int firstRemovableDrive = -1;
|
||||
int i = 0;
|
||||
for (File root : roots) {
|
||||
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
|
||||
long spaceInBytes = root.getTotalSpace();
|
||||
String sizeWithUnit = humanReadableByteCount(spaceInBytes, false);
|
||||
listData.add(root + " (" + description + ") (" + sizeWithUnit + ")");
|
||||
if (firstRemovableDrive == -1) {
|
||||
try {
|
||||
FileStore fileStore = Files.getFileStore(root.toPath());
|
||||
if ((boolean) fileStore.getAttribute("volume:isRemovable")) { //NON-NLS
|
||||
firstRemovableDrive = i;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
; // skip
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
driveList.setListData(listData.toArray(new String[0]));
|
||||
if (!listData.isEmpty()) {
|
||||
// auto-select the first external drive, if any
|
||||
driveList.setSelectedIndex(firstRemovableDrive == -1 ? 0 : firstRemovableDrive);
|
||||
driveListMouseClicked(null);
|
||||
driveList.requestFocusInWindow();
|
||||
} else {
|
||||
setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_noExternalDriveFound());
|
||||
}
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
}//GEN-LAST:event_scanButtonActionPerformed
|
||||
|
||||
@Messages({
|
||||
"# {0} - sparseImageDirectory",
|
||||
"# {1} - image",
|
||||
@ -333,7 +331,7 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
return;
|
||||
}
|
||||
choosenImageDirPath = Paths.get(path);
|
||||
setNormalMessage(SELECTED_IMAGE + " " + path);
|
||||
setNormalMessage(path);
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
} else {
|
||||
setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_directoryFormatInvalid(path));
|
||||
@ -348,7 +346,7 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
int index = imageTable.getSelectedRow();
|
||||
if (index != -1) {
|
||||
choosenImageDirPath = Paths.get((String) imageTableModel.getValueAt(index, 2));
|
||||
setNormalMessage(SELECTED_IMAGE + " " + choosenImageDirPath.toString());
|
||||
setNormalMessage(choosenImageDirPath.toString());
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
} else {
|
||||
choosenImageDirPath = null;
|
||||
@ -357,10 +355,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void imageTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_imageTableMouseClicked
|
||||
imageTableSelect();
|
||||
}//GEN-LAST:event_imageTableMouseClicked
|
||||
|
||||
private void driveListSelect() {
|
||||
String selectedStr = driveList.getSelectedValue();
|
||||
if (selectedStr == null) {
|
||||
@ -398,7 +392,7 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
selectAcquisitionFromDriveLabel.setText(Bundle.LogicalImagerPanel_selectAcquisitionFromDriveLabel_text()
|
||||
selectFromDriveLabel.setText(Bundle.LogicalImagerPanel_selectAcquisitionFromDriveLabel_text()
|
||||
+ " " + driveLetter);
|
||||
imageTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
imageTable.setModel(imageTableModel);
|
||||
@ -411,6 +405,10 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
choosenImageDirPath = null;
|
||||
setErrorMessage(DRIVE_HAS_NO_IMAGES);
|
||||
}
|
||||
} else {
|
||||
clearImageTable();
|
||||
choosenImageDirPath = null;
|
||||
setErrorMessage(DRIVE_HAS_NO_IMAGES);
|
||||
}
|
||||
}
|
||||
|
||||
@ -421,13 +419,14 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
}
|
||||
|
||||
private void setErrorMessage(String msg) {
|
||||
messageLabel.setForeground(Color.red);
|
||||
messageLabel.setText(msg);
|
||||
messageTextArea.setForeground(Color.red);
|
||||
messageTextArea.setText(msg);
|
||||
pathTextField.setText("");
|
||||
}
|
||||
|
||||
private void setNormalMessage(String msg) {
|
||||
messageLabel.setForeground(Color.black);
|
||||
messageLabel.setText(msg);
|
||||
pathTextField.setText(msg);
|
||||
messageTextArea.setText("");
|
||||
}
|
||||
|
||||
private void clearImageTable() {
|
||||
@ -436,43 +435,138 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
fixImageTableColumnWidth();
|
||||
}
|
||||
|
||||
private void driveListMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_driveListMouseClicked
|
||||
driveListSelect();
|
||||
private void toggleMouseAndKeyListeners(Component component, boolean isEnable) {
|
||||
component.setEnabled(isEnable);
|
||||
}
|
||||
|
||||
private void manualRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manualRadioButtonActionPerformed
|
||||
browseButton.setEnabled(true);
|
||||
|
||||
// disable import panel
|
||||
toggleMouseAndKeyListeners(driveList, false);
|
||||
toggleMouseAndKeyListeners(driveListScrollPane, false);
|
||||
toggleMouseAndKeyListeners(imageScrollPane, false);
|
||||
toggleMouseAndKeyListeners(imageTable, false);
|
||||
|
||||
refreshButton.setEnabled(false);
|
||||
|
||||
choosenImageDirPath = null;
|
||||
setNormalMessage("");
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
}//GEN-LAST:event_driveListMouseClicked
|
||||
}//GEN-LAST:event_manualRadioButtonActionPerformed
|
||||
|
||||
private void importRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importRadioButtonActionPerformed
|
||||
browseButton.setEnabled(false);
|
||||
|
||||
toggleMouseAndKeyListeners(driveList, true);
|
||||
toggleMouseAndKeyListeners(driveListScrollPane, true);
|
||||
toggleMouseAndKeyListeners(imageScrollPane, true);
|
||||
toggleMouseAndKeyListeners(imageTable, true);
|
||||
|
||||
refreshButton.setEnabled(true);
|
||||
|
||||
choosenImageDirPath = null;
|
||||
setNormalMessage("");
|
||||
refreshButton.doClick();
|
||||
}//GEN-LAST:event_importRadioButtonActionPerformed
|
||||
|
||||
@Messages({
|
||||
"LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for sparse_image.vhd ...",
|
||||
"LogicalImagerPanel.messageLabel.noExternalDriveFound=No drive found"
|
||||
})
|
||||
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
|
||||
// Scan external drives for sparse_image.vhd
|
||||
clearImageTable();
|
||||
setNormalMessage(Bundle.LogicalImagerPanel_messageLabel_scanningExternalDrives());
|
||||
List<String> listData = new ArrayList<>();
|
||||
File[] roots = File.listRoots();
|
||||
int firstRemovableDrive = -1;
|
||||
int i = 0;
|
||||
for (File root : roots) {
|
||||
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
|
||||
long spaceInBytes = root.getTotalSpace();
|
||||
String sizeWithUnit = humanReadableByteCount(spaceInBytes, false);
|
||||
listData.add(root + " (" + description + ") (" + sizeWithUnit + ")");
|
||||
if (firstRemovableDrive == -1) {
|
||||
try {
|
||||
FileStore fileStore = Files.getFileStore(root.toPath());
|
||||
if ((boolean) fileStore.getAttribute("volume:isRemovable")) { //NON-NLS
|
||||
firstRemovableDrive = i;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
; // skip
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
driveList.setListData(listData.toArray(new String[0]));
|
||||
if (!listData.isEmpty()) {
|
||||
// auto-select the first external drive, if any
|
||||
driveList.setSelectedIndex(firstRemovableDrive == -1 ? 0 : firstRemovableDrive);
|
||||
driveListMouseReleased(null);
|
||||
driveList.requestFocusInWindow();
|
||||
} else {
|
||||
setErrorMessage(Bundle.LogicalImagerPanel_messageLabel_noExternalDriveFound());
|
||||
}
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
}//GEN-LAST:event_refreshButtonActionPerformed
|
||||
|
||||
private void driveListKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_driveListKeyReleased
|
||||
driveListSelect();
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
if (importRadioButton.isSelected()) {
|
||||
driveListSelect();
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
}
|
||||
}//GEN-LAST:event_driveListKeyReleased
|
||||
|
||||
private void imageTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_imageTableKeyReleased
|
||||
imageTableSelect();
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
if (importRadioButton.isSelected()) {
|
||||
imageTableSelect();
|
||||
}
|
||||
}//GEN-LAST:event_imageTableKeyReleased
|
||||
|
||||
private void imageTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_imageTableMouseReleased
|
||||
if (importRadioButton.isSelected()) {
|
||||
imageTableSelect();
|
||||
}
|
||||
}//GEN-LAST:event_imageTableMouseReleased
|
||||
|
||||
private void driveListMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_driveListMouseReleased
|
||||
if (importRadioButton.isSelected()) {
|
||||
driveListSelect();
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), true, false);
|
||||
}
|
||||
}//GEN-LAST:event_driveListMouseReleased
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.JList<String> driveList;
|
||||
private javax.swing.JScrollPane driveListScrollPane;
|
||||
private javax.swing.JScrollPane imageScrollPane;
|
||||
private javax.swing.JTable imageTable;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel6;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private javax.swing.JLabel messageLabel;
|
||||
private javax.swing.JButton scanButton;
|
||||
private javax.swing.JLabel selectAcquisitionFromDriveLabel;
|
||||
private javax.swing.JRadioButton importRadioButton;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JSeparator jSeparator2;
|
||||
private javax.swing.JRadioButton manualRadioButton;
|
||||
private javax.swing.JTextArea messageTextArea;
|
||||
private javax.swing.JTextField pathTextField;
|
||||
private javax.swing.JButton refreshButton;
|
||||
private javax.swing.JLabel selectDriveLabel;
|
||||
private javax.swing.JLabel topLabel;
|
||||
private javax.swing.JLabel selectFolderLabel;
|
||||
private javax.swing.JLabel selectFromDriveLabel;
|
||||
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
public void reset() {
|
||||
//reset the UI elements to default
|
||||
choosenImageDirPath = null;
|
||||
setNormalMessage("");
|
||||
driveList.setListData(EMPTY_LIST_DATA);
|
||||
clearImageTable();
|
||||
setNormalMessage(Bundle.LogicalImagerPanel_messageLabel_clickScanOrBrowse());
|
||||
if (importRadioButton.isSelected()) {
|
||||
refreshButton.doClick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -488,10 +582,6 @@ public class LogicalImagerPanel extends JPanel implements DocumentListener {
|
||||
return choosenImageDirPath;
|
||||
}
|
||||
|
||||
public void setMessageLabel(String message) {
|
||||
messageLabel.setText(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
* @return caseName the case name from the case name text field
|
||||
*/
|
||||
String getCaseName() {
|
||||
return this.caseNameTextField.getText();
|
||||
return this.caseNameTextField.getText().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +109,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
* @return baseDirectory the base directory from the case dir text field
|
||||
*/
|
||||
String getCaseParentDir() {
|
||||
String parentDir = this.caseParentDirTextField.getText();
|
||||
String parentDir = this.caseParentDirTextField.getText().trim();
|
||||
if (parentDir.endsWith(File.separator) == false) {
|
||||
parentDir = parentDir + File.separator;
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ DataSourceSummaryDialog.window.title=Data Sources Summary
|
||||
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
|
||||
DataSourceSummaryNode.column.files.header=Files
|
||||
DataSourceSummaryNode.column.results.header=Results
|
||||
DataSourceSummaryNode.column.status.header=Ingest Status
|
||||
DataSourceSummaryNode.column.tags.header=Tags
|
||||
DataSourceSummaryNode.column.type.header=Type
|
||||
DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source
|
||||
|
@ -37,8 +37,10 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryNode.DataSourceSummaryEntryNode;
|
||||
import static javax.swing.SwingConstants.RIGHT;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -50,9 +52,10 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceBrowser.class.getName());
|
||||
private static final int COUNT_COLUMN_WIDTH = 25;
|
||||
private static final int USAGE_COLUMN_WIDTH = 120;
|
||||
private static final int DATA_SOURCE_COLUMN_WIDTH = 325;
|
||||
private static final int COUNT_COLUMN_WIDTH = 20;
|
||||
private static final int INGEST_STATUS_WIDTH = 50;
|
||||
private static final int USAGE_COLUMN_WIDTH = 110;
|
||||
private static final int DATA_SOURCE_COLUMN_WIDTH = 280;
|
||||
private final Outline outline;
|
||||
private final org.openide.explorer.view.OutlineView outlineView;
|
||||
private final ExplorerManager explorerManager;
|
||||
@ -69,6 +72,7 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
outlineView = new org.openide.explorer.view.OutlineView();
|
||||
this.setVisible(true);
|
||||
outlineView.setPropertyColumns(
|
||||
Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(),
|
||||
Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(),
|
||||
Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(),
|
||||
Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_results_header(),
|
||||
@ -90,6 +94,8 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
column.setPreferredWidth(COUNT_COLUMN_WIDTH);
|
||||
} else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_type_header())) {
|
||||
column.setPreferredWidth(USAGE_COLUMN_WIDTH);
|
||||
} else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_status_header())) {
|
||||
column.setPreferredWidth(INGEST_STATUS_WIDTH);
|
||||
} else {
|
||||
column.setPreferredWidth(DATA_SOURCE_COLUMN_WIDTH);
|
||||
}
|
||||
@ -182,6 +188,47 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the DataSourceBrowser to display up to date status information for
|
||||
* the data sources.
|
||||
*
|
||||
* @param dataSourceId the ID of the data source which should be updated
|
||||
* @param newStatus the new status which the data source should have
|
||||
*/
|
||||
void refresh(long dataSourceId, IngestJobInfo.IngestJobStatusType newStatus) {
|
||||
|
||||
//attempt to update the status of any datasources that had status which was STARTED
|
||||
for (DataSourceSummary summary : dataSourceSummaryList) {
|
||||
if (summary.getDataSource().getId() == dataSourceId) {
|
||||
summary.setIngestStatus(newStatus);
|
||||
}
|
||||
}
|
||||
//figure out which nodes were previously selected
|
||||
Node[] selectedNodes = explorerManager.getSelectedNodes();
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList));
|
||||
List<Node> nodesToSelect = new ArrayList<>();
|
||||
for (Node node : explorerManager.getRootContext().getChildren().getNodes()) {
|
||||
if (node instanceof DataSourceSummaryEntryNode) {
|
||||
//there should only be one selected node as multi-select is disabled
|
||||
for (Node selectedNode : selectedNodes) {
|
||||
if (((DataSourceSummaryEntryNode) node).getDataSource().equals(((DataSourceSummaryEntryNode) selectedNode).getDataSource())) {
|
||||
nodesToSelect.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//reselect the previously selected Nodes
|
||||
try {
|
||||
explorerManager.setSelectedNodes(nodesToSelect.toArray(new Node[nodesToSelect.size()]));
|
||||
} catch (PropertyVetoException ex) {
|
||||
logger.log(Level.WARNING, "Error selecting previously selected nodes", ex);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -18,15 +18,27 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Wrapper object for a DataSource and the information associated with it.
|
||||
*
|
||||
*/
|
||||
class DataSourceSummary {
|
||||
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DataSourceSummary.class.getName());
|
||||
private static final String INGEST_JOB_STATUS_QUERY = "status_id FROM ingest_jobs WHERE obj_id=";
|
||||
private final DataSource dataSource;
|
||||
private IngestJobStatusType status = null;
|
||||
private final String type;
|
||||
private final long filesCount;
|
||||
private final long resultsCount;
|
||||
@ -45,12 +57,26 @@ class DataSourceSummary {
|
||||
*/
|
||||
DataSourceSummary(DataSource dSource, String typeValue, Long numberOfFiles, Long numberOfResults, Long numberOfTags) {
|
||||
dataSource = dSource;
|
||||
getStatusFromDatabase();
|
||||
type = typeValue == null ? "" : typeValue;
|
||||
filesCount = numberOfFiles == null ? 0 : numberOfFiles;
|
||||
resultsCount = numberOfResults == null ? 0 : numberOfResults;
|
||||
tagsCount = numberOfTags == null ? 0 : numberOfTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status of the ingest job from the case database
|
||||
*/
|
||||
private void getStatusFromDatabase() {
|
||||
try {
|
||||
IngestJobQueryCallback callback = new IngestJobQueryCallback();
|
||||
Case.getCurrentCaseThrows().getSleuthkitCase().getCaseDbAccessManager().select(INGEST_JOB_STATUS_QUERY + dataSource.getId(), callback);
|
||||
status = callback.getStatus();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error getting status for data source from case database", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DataSource
|
||||
*
|
||||
@ -60,6 +86,16 @@ class DataSourceSummary {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually set the ingest job status
|
||||
*
|
||||
* @param ingestStatus the status which the ingest job should have
|
||||
* currently, null to display empty string
|
||||
*/
|
||||
void setIngestStatus(IngestJobStatusType ingestStatus) {
|
||||
status = ingestStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of this DataSource
|
||||
*
|
||||
@ -87,6 +123,16 @@ class DataSourceSummary {
|
||||
return resultsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IngestJobStatusType associated with this data source.
|
||||
*
|
||||
* @return the IngestJobStatusType associated with this data source. Can be
|
||||
* null if the IngestJobStatusType is not STARTED or COMPLETED.
|
||||
*/
|
||||
IngestJobStatusType getIngestStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of tagged content objects in this DataSource
|
||||
*
|
||||
@ -95,4 +141,40 @@ class DataSourceSummary {
|
||||
long getTagsCount() {
|
||||
return tagsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to parse result set, getting the status to be associated with
|
||||
* this data source
|
||||
*/
|
||||
class IngestJobQueryCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
private IngestJobStatusType jobStatus = null;
|
||||
|
||||
@Override
|
||||
public void process(ResultSet rs) {
|
||||
try {
|
||||
while (rs.next()) {
|
||||
IngestJobStatusType currentStatus = IngestJobStatusType.fromID(rs.getInt("status_id"));
|
||||
if (currentStatus == IngestJobStatusType.COMPLETED) {
|
||||
jobStatus = currentStatus;
|
||||
} else if (currentStatus == IngestJobStatusType.STARTED) {
|
||||
jobStatus = currentStatus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Error getting status for ingest job", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status which was determined for this callback
|
||||
*
|
||||
* @return the status of the data source which was queried for
|
||||
*/
|
||||
IngestJobStatusType getStatus() {
|
||||
return jobStatus;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,18 @@
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo;
|
||||
|
||||
/**
|
||||
* Dialog for displaying the Data Sources Summary information
|
||||
@ -38,7 +42,6 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
private final DataSourceSummaryDetailsPanel detailsPanel;
|
||||
private final DataSourceBrowser dataSourcesPanel;
|
||||
private final IngestJobInfoPanel ingestHistoryPanel;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceSummaryDialog.class.getName());
|
||||
|
||||
/**
|
||||
* Creates new form DataSourceSummaryDialog for displaying a summary of the
|
||||
@ -73,6 +76,17 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
this.repaint();
|
||||
}
|
||||
});
|
||||
//add listener to refresh jobs with Started status when they complete
|
||||
IngestManager.getInstance().addIngestJobEventListener((PropertyChangeEvent evt) -> {
|
||||
if (evt instanceof DataSourceAnalysisCompletedEvent) {
|
||||
DataSourceAnalysisCompletedEvent dsEvent = (DataSourceAnalysisCompletedEvent) evt;
|
||||
if (dsEvent.getResult() == Reason.ANALYSIS_COMPLETED) {
|
||||
dataSourcesPanel.refresh(dsEvent.getDataSource().getId(), IngestJobInfo.IngestJobStatusType.COMPLETED);
|
||||
} else if (dsEvent.getResult() == Reason.ANALYSIS_CANCELLED) {
|
||||
dataSourcesPanel.refresh(dsEvent.getDataSource().getId(), null);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.pack();
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
static final class DataSourceSummaryEntryNode extends AbstractNode {
|
||||
|
||||
private final DataSource dataSource;
|
||||
private final String status;
|
||||
private final String type;
|
||||
private final long filesCount;
|
||||
private final long resultsCount;
|
||||
@ -124,6 +125,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
DataSourceSummaryEntryNode(DataSourceSummary dataSourceSummary) {
|
||||
super(Children.LEAF);
|
||||
dataSource = dataSourceSummary.getDataSource();
|
||||
status = dataSourceSummary.getIngestStatus() == null ? "" : dataSourceSummary.getIngestStatus().getDisplayName();
|
||||
type = dataSourceSummary.getType();
|
||||
filesCount = dataSourceSummary.getFilesCount();
|
||||
resultsCount = dataSourceSummary.getResultsCount();
|
||||
@ -143,6 +145,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
}
|
||||
|
||||
@Messages({"DataSourceSummaryNode.column.dataSourceName.header=Data Source Name",
|
||||
"DataSourceSummaryNode.column.status.header=Ingest Status",
|
||||
"DataSourceSummaryNode.column.type.header=Type",
|
||||
"DataSourceSummaryNode.column.files.header=Files",
|
||||
"DataSourceSummaryNode.column.results.header=Results",
|
||||
@ -157,6 +160,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
}
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_dataSourceName_header(), Bundle.DataSourceSummaryNode_column_dataSourceName_header(), Bundle.DataSourceSummaryNode_column_dataSourceName_header(),
|
||||
dataSource));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), status));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(),
|
||||
type));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(),
|
||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule.services;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -30,15 +31,18 @@ import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskData.DbType;
|
||||
|
||||
/**
|
||||
* A per case Autopsy service that manages the addition of content and artifact
|
||||
@ -48,6 +52,32 @@ public class TagsManager implements Closeable {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName());
|
||||
private final SleuthkitCase caseDb;
|
||||
|
||||
static {
|
||||
//Create the contentviewer tags table (beta) if the current case does not
|
||||
//have the table present
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> {
|
||||
if (evt.getNewValue() != null) {
|
||||
Case currentCase = (Case) evt.getNewValue();
|
||||
try {
|
||||
CaseDbAccessManager caseDb = currentCase.getSleuthkitCase().getCaseDbAccessManager();
|
||||
if (caseDb.tableExists(ContentViewerTagManager.TABLE_NAME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentCase.getSleuthkitCase().getDatabaseType().equals(DbType.SQLITE)) {
|
||||
caseDb.createTable(ContentViewerTagManager.TABLE_NAME, ContentViewerTagManager.TABLE_SCHEMA_SQLITE);
|
||||
} else if (currentCase.getSleuthkitCase().getDatabaseType().equals(DbType.POSTGRESQL)) {
|
||||
caseDb.createTable(ContentViewerTagManager.TABLE_NAME, ContentViewerTagManager.TABLE_SCHEMA_POSTGRESQL);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE,
|
||||
String.format("Unable to create the %s table for image tag storage.",
|
||||
ContentViewerTagManager.TABLE_NAME), ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not a given tag display name contains an illegal
|
||||
|
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.services.contentviewertags;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* A per case Autopsy service that manages the addition of content viewer tags
|
||||
* to the case database. This manager is also responsible for serializing and
|
||||
* deserializing instances of your tag data objects for persistence and
|
||||
* retrieval.
|
||||
*/
|
||||
public class ContentViewerTagManager {
|
||||
|
||||
//Used to convert Java beans into the physical representation that will be stored
|
||||
//in the database.
|
||||
private static final ObjectMapper SERIALIZER = new ObjectMapper();
|
||||
|
||||
public static final String TABLE_NAME = "beta_tag_app_data";
|
||||
public static final String TABLE_SCHEMA_SQLITE = "(app_data_id INTEGER PRIMARY KEY, "
|
||||
+ "content_tag_id INTEGER NOT NULL, app_data TEXT NOT NULL, "
|
||||
+ "FOREIGN KEY(content_tag_id) REFERENCES content_tags(tag_id))";
|
||||
public static final String TABLE_SCHEMA_POSTGRESQL = "(app_data_id BIGSERIAL PRIMARY KEY, "
|
||||
+ "content_tag_id INTEGER NOT NULL, app_data TEXT NOT NULL, "
|
||||
+ "FOREIGN KEY(content_tag_id) REFERENCES content_tags(tag_id))";
|
||||
|
||||
private static final String INSERT_TAG_DATA = "(content_tag_id, app_data) VALUES (%d, '%s')";
|
||||
private static final String UPDATE_TAG_DATA = "SET content_tag_id = %d, app_data = '%s' WHERE app_data_id = %d";
|
||||
private static final String SELECT_TAG_DATA = "* FROM " + TABLE_NAME + " WHERE content_tag_id = %d";
|
||||
private static final String DELETE_TAG_DATA = "WHERE app_data_id = %d";
|
||||
|
||||
/**
|
||||
* Creates and saves a new ContentViewerTag in the case database. The
|
||||
* generic tag data instance T will be automatically serialized into a
|
||||
* storable format.
|
||||
*
|
||||
* @param <T> Generic class type that will be serialized into a storable
|
||||
* format for persistence.
|
||||
* @param contentTag ContentTag that this ContentViewerTag is associated
|
||||
* with (1:1).
|
||||
* @param tagDataBean Data instance that contains the tag information to be
|
||||
* persisted.
|
||||
* @return An instance of a ContentViewerTag of type T, which contains all
|
||||
* the stored information.
|
||||
*
|
||||
* @throws SerializationException Thrown if the tag data instance T could
|
||||
* not be serialized into a storable format.
|
||||
* @throws TskCoreException Thrown if this operation did not successfully
|
||||
* persist in the case database.
|
||||
* @throws NoCurrentCaseException Thrown if invocation of this method occurs
|
||||
* when no case is open.
|
||||
*/
|
||||
public static <T> ContentViewerTag<T> saveTag(ContentTag contentTag, T tagDataBean)
|
||||
throws SerializationException, TskCoreException, NoCurrentCaseException {
|
||||
try {
|
||||
long contentTagId = contentTag.getId();
|
||||
String serialAppData = SERIALIZER.writeValueAsString(tagDataBean);
|
||||
String insertTemplateInstance = String.format(INSERT_TAG_DATA,
|
||||
contentTagId, serialAppData);
|
||||
long insertId = Case.getCurrentCaseThrows()
|
||||
.getSleuthkitCase()
|
||||
.getCaseDbAccessManager()
|
||||
.insert(TABLE_NAME, insertTemplateInstance);
|
||||
return new ContentViewerTag<>(insertId, contentTag, tagDataBean);
|
||||
} catch (JsonProcessingException ex) {
|
||||
throw new SerializationException("Unable to convert object instance into a storable format", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ContentViewerTag instance with the new tag data T and
|
||||
* persists the changes to the case database.
|
||||
*
|
||||
* @param <T> Generic class type that will be serialized into a storable
|
||||
* format.
|
||||
* @param oldTag ContentViewerTag instance to be updated
|
||||
* @param tagDataBean Data instance that contains the updated information to
|
||||
* be persisted.
|
||||
*
|
||||
* @throws SerializationException Thrown if the tag data instance T could
|
||||
* not be serialized into a storable format.
|
||||
* @throws TskCoreException Thrown if this operation did not successfully
|
||||
* persist in the case database.
|
||||
* @throws NoCurrentCaseException Thrown if invocation of this method occurs
|
||||
* when no case is open.
|
||||
*/
|
||||
public static <T> ContentViewerTag<T> updateTag(ContentViewerTag<T> oldTag, T tagDataBean)
|
||||
throws SerializationException, TskCoreException, NoCurrentCaseException {
|
||||
try {
|
||||
String serialAppData = SERIALIZER.writeValueAsString(tagDataBean);
|
||||
String updateTemplateInstance = String.format(UPDATE_TAG_DATA,
|
||||
oldTag.getContentTag().getId(), serialAppData, oldTag.getId());
|
||||
Case.getCurrentCaseThrows()
|
||||
.getSleuthkitCase()
|
||||
.getCaseDbAccessManager()
|
||||
.update(TABLE_NAME, updateTemplateInstance);
|
||||
return new ContentViewerTag<>(oldTag.getId(), oldTag.getContentTag(), tagDataBean);
|
||||
} catch (JsonProcessingException ex) {
|
||||
throw new SerializationException("Unable to convert object instance into a storable format", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a ContentViewerTag instance that is associated with the
|
||||
* specified ContentTag. The Java class T that represents the technical
|
||||
* details of the tag should be passed so that automatic binding can take
|
||||
* place.
|
||||
*
|
||||
* @param <T> Generic class type that will be instantiated and filled in
|
||||
* with data.
|
||||
* @param contentTag ContentTag that this ContentViewerTag is associated
|
||||
* with (1:1)
|
||||
* @param clazz Generic class that will be instantiated and filled in with
|
||||
* data.
|
||||
* @return ContentViewerTag with an instance of T as a member variable or
|
||||
* null if the content tag does not have an associated ContentViewerTag of
|
||||
* type T.
|
||||
*
|
||||
* @throws TskCoreException Thrown if this operation did not successfully
|
||||
* persist in the case database.
|
||||
* @throws NoCurrentCaseException Thrown if invocation of this method occurs
|
||||
* when no case is open.
|
||||
*/
|
||||
public static <T> ContentViewerTag<T> getTag(ContentTag contentTag, Class<T> clazz) throws TskCoreException, NoCurrentCaseException {
|
||||
String selectTemplateInstance = String.format(SELECT_TAG_DATA, contentTag.getId());
|
||||
final ResultWrapper<ContentViewerTag<T>> result = new ResultWrapper<>();
|
||||
Case.getCurrentCaseThrows()
|
||||
.getSleuthkitCase()
|
||||
.getCaseDbAccessManager()
|
||||
.select(selectTemplateInstance, (ResultSet rs) -> {
|
||||
try {
|
||||
if (rs.next()) {
|
||||
long tagId = rs.getLong(1);
|
||||
String appDetails = rs.getString(3);
|
||||
try {
|
||||
T instance = SERIALIZER.readValue(appDetails, clazz);
|
||||
result.setResult(new ContentViewerTag<>(tagId, contentTag, instance));
|
||||
} catch (IOException ex) {
|
||||
//Databind for type T failed. Not a system error
|
||||
//but rather a logic error on the part of the caller.
|
||||
result.setResult(null);
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
result.setException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
if (result.hasException()) {
|
||||
throw new TskCoreException("Unable to select tag from case db", result.getException());
|
||||
}
|
||||
|
||||
return result.getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for holding state in the CaseDbAccessQueryCallback.
|
||||
* CaseDbAccessQueryCallback has no support for exception handling.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
private static class ResultWrapper<T> {
|
||||
|
||||
private T result;
|
||||
private SQLException ex = null;
|
||||
|
||||
public void setResult(T result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public void setException(SQLException ex) {
|
||||
this.ex = ex;
|
||||
}
|
||||
|
||||
public boolean hasException() {
|
||||
return this.ex != null;
|
||||
}
|
||||
|
||||
public SQLException getException() {
|
||||
return ex;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the content viewer tag with the specified id.
|
||||
*
|
||||
* @param contentViewerTag ContentViewerTag to delete
|
||||
* @throws TskCoreException Thrown if this operation did not successfully
|
||||
* persist in the case database.
|
||||
* @throws NoCurrentCaseException Thrown if invocation of this method occurs
|
||||
* when no case is open.
|
||||
*/
|
||||
public static <T> void deleteTag(ContentViewerTag<T> contentViewerTag) throws TskCoreException, NoCurrentCaseException {
|
||||
String deleteTemplateInstance = String.format(DELETE_TAG_DATA, contentViewerTag.getId());
|
||||
Case.getCurrentCaseThrows()
|
||||
.getSleuthkitCase()
|
||||
.getCaseDbAccessManager()
|
||||
.delete(TABLE_NAME, deleteTemplateInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents a stored tag in the case database. It is a wrapper
|
||||
* for the tag id, the attached Content tag object, and the Java bean
|
||||
* instance that describes the technical details for reconstructing the tag.
|
||||
*
|
||||
* @param <T> Generic class type that will be instantiated and filled in
|
||||
* with data.
|
||||
*/
|
||||
public static class ContentViewerTag<T> {
|
||||
|
||||
private final long id;
|
||||
private final ContentTag contentTag;
|
||||
private final T details;
|
||||
|
||||
private ContentViewerTag(long id, ContentTag contentTag, T details) {
|
||||
this.id = id;
|
||||
this.contentTag = contentTag;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ContentTag getContentTag() {
|
||||
return contentTag;
|
||||
}
|
||||
|
||||
public T getDetails() {
|
||||
return details;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* System exception thrown in the event that class instance T could not be
|
||||
* properly serialized.
|
||||
*/
|
||||
public static class SerializationException extends Exception {
|
||||
|
||||
public SerializationException(String message, Exception source) {
|
||||
super(message, source);
|
||||
}
|
||||
}
|
||||
|
||||
//Prevent this class from being instantiated.
|
||||
private ContentViewerTagManager() {
|
||||
}
|
||||
}
|
@ -75,6 +75,10 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
|
||||
public AccountsBrowser() {
|
||||
initComponents();
|
||||
|
||||
jSplitPane1.setResizeWeight(0.5);
|
||||
jSplitPane1.setDividerLocation(0.75);
|
||||
|
||||
outline = outlineView.getOutline();
|
||||
outlineView.setPropertyColumns(
|
||||
"device", Bundle.AccountNode_device(),
|
||||
@ -118,7 +122,7 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
|
||||
final int rows = Math.min(100, outline.getRowCount());
|
||||
|
||||
for (int column = 0; column < outline.getModel().getColumnCount(); column++) {
|
||||
for (int column = 0; column < outline.getColumnCount(); column++) {
|
||||
int columnWidthLimit = 500;
|
||||
int columnWidth = 0;
|
||||
|
||||
|
@ -11,34 +11,10 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="filtersPane" min="-2" pref="265" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseVisualizeTabPane" pref="786" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="filtersPane" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="browseVisualizeTabPane" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JTabbedPane" name="browseVisualizeTabPane">
|
||||
<Properties>
|
||||
@ -51,6 +27,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="15" insetsRight="15" anchor="18" weightX="0.75" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
@ -85,11 +66,11 @@
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="org.sleuthkit.autopsy.communications.FiltersPanel" name="filtersPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[256, 495]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="15" insetsBottom="15" insetsRight="5" anchor="18" weightX="0.25" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -22,12 +22,13 @@ import com.google.common.eventbus.Subscribe;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.LayoutStyle;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.Mode;
|
||||
@ -93,39 +94,39 @@ public final class CVTTopComponent extends TopComponent {
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
GridBagConstraints gridBagConstraints;
|
||||
|
||||
browseVisualizeTabPane = new JTabbedPane();
|
||||
accountsBrowser = new AccountsBrowser();
|
||||
vizPanel = new VisualizationPanel();
|
||||
filtersPane = new FiltersPanel();
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
browseVisualizeTabPane.setFont(new Font("Tahoma", 0, 18)); // NOI18N
|
||||
browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/table.png")), accountsBrowser); // NOI18N
|
||||
browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.vizPanel.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/emblem-web.png")), vizPanel); // NOI18N
|
||||
|
||||
filtersPane.setMinimumSize(new Dimension(256, 495));
|
||||
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(filtersPane, GroupLayout.PREFERRED_SIZE, 265, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(browseVisualizeTabPane, GroupLayout.PREFERRED_SIZE, 786, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(filtersPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGap(5, 5, 5))
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addComponent(browseVisualizeTabPane)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
gridBagConstraints = new GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 0.75;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new Insets(15, 0, 15, 15);
|
||||
add(browseVisualizeTabPane, gridBagConstraints);
|
||||
browseVisualizeTabPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName")); // NOI18N
|
||||
|
||||
gridBagConstraints = new GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 0.25;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new Insets(15, 15, 15, 5);
|
||||
add(filtersPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
|
@ -11,493 +11,487 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="18"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,-54,0,0,1,-40"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="devicesPane" max="32767" attributes="0"/>
|
||||
<Component id="accountTypesPane" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="filtersTitleLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="applyFiltersButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="dateRangePane" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="needsRefreshLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="limitPane" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="filtersTitleLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="applyFiltersButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="refreshButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="needsRefreshLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
|
||||
<Component id="devicesPane" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="accountTypesPane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="dateRangePane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="limitPane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="applyFiltersButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/tick.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.applyFiltersButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="filtersTitleLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/funnel.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.filtersTitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="accountTypesPane">
|
||||
<Container class="javax.swing.JPanel" name="topPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="24" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="accountTypesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="accountTypeRequiredLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="unCheckAllAccountTypesButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="checkAllAccountTypesButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="accountTypesScrollPane" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="accountTypesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="accountTypeRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="accountTypesScrollPane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="checkAllAccountTypesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="unCheckAllAccountTypesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="accountTypesLabel">
|
||||
<Component class="javax.swing.JLabel" name="filtersTitleLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/accounts.png"/>
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/funnel.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.filtersTitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="accountTypesScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[2, 200]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="accountTypeListPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="accountTypeRequiredLabel">
|
||||
<Component class="javax.swing.JButton" name="refreshButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypeRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="applyFiltersButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/tick.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.applyFiltersButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="needsRefreshLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.needsRefreshLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="devicesPane">
|
||||
<Container class="javax.swing.JScrollPane" name="scrollPane">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="devicesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="deviceRequiredLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="unCheckAllDevicesButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="checkAllDevicesButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="devicesScrollPane" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="devicesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deviceRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="devicesScrollPane" pref="94" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="checkAllDevicesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="unCheckAllDevicesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="5" pref="5" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="devicesLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/image.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.devicesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="devicesScrollPane">
|
||||
<Properties>
|
||||
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 75]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JPanel" name="mainPanel">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="devicesListPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[4, 100]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JPanel" name="limitPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="15" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="mostRecentLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.mostRecentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="9" insetsBottom="0" insetsRight="9" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="limitComboBox">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="6">
|
||||
<StringItem index="0" value="All"/>
|
||||
<StringItem index="1" value="10000"/>
|
||||
<StringItem index="2" value="5000"/>
|
||||
<StringItem index="3" value="1000"/>
|
||||
<StringItem index="4" value="500"/>
|
||||
<StringItem index="5" value="100"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="limitComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="limitTitlePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="9" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="limitHeaderLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitHeaderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="limitErrorMsgLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitErrorMsgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="deviceRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.deviceRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="dateRangePane">
|
||||
<Container class="javax.swing.JPanel" name="dateRangePane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="endCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="endDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="startCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="startDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="endCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="endDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="startCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="startDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="startDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="startCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="endDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="endCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="startDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="startCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="endDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="endCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="startDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="dateRangeLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/calendar.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.dateRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="startCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.startCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="startCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="endCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.endCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="endCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="endDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="refreshButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="needsRefreshLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.needsRefreshLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="limitPane">
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="startDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="dateRangeLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/calendar.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.dateRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="startCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.startCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="startCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="endCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.endCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="endCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="endDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="devicesPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="100" insetsTop="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="limitHeaderLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="limitErrorMsgLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="mostRecentLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="limitComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="limitHeaderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="limitErrorMsgLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="mostRecentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="limitComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="32" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="limitHeaderLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitHeaderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="mostRecentLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.mostRecentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="limitComboBox">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="6">
|
||||
<StringItem index="0" value="All"/>
|
||||
<StringItem index="1" value="10000"/>
|
||||
<StringItem index="2" value="5000"/>
|
||||
<StringItem index="3" value="1000"/>
|
||||
<StringItem index="4" value="500"/>
|
||||
<StringItem index="5" value="100"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="limitComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="limitErrorMsgLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitErrorMsgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="12" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="devicesLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/image.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.devicesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="9" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="devicesScrollPane">
|
||||
<Properties>
|
||||
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 75]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="devicesListPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[4, 100]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="deviceRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.deviceRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="9" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="accountTypesPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="12" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="accountTypesLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/accounts.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="accountTypesScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[2, 200]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="accountTypeListPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="accountTypeRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypeRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -394,135 +394,123 @@ final public class FiltersPanel extends JPanel {
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
applyFiltersButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/tick.png"))); // NOI18N
|
||||
applyFiltersButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.applyFiltersButton.text")); // NOI18N
|
||||
applyFiltersButton.setPreferredSize(null);
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
topPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
filtersTitleLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/funnel.png"))); // NOI18N
|
||||
filtersTitleLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.filtersTitleLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
topPane.add(filtersTitleLabel, gridBagConstraints);
|
||||
|
||||
unCheckAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllAccountTypesButton.text")); // NOI18N
|
||||
unCheckAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
refreshButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N
|
||||
refreshButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.refreshButton.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
topPane.add(refreshButton, gridBagConstraints);
|
||||
|
||||
applyFiltersButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/tick.png"))); // NOI18N
|
||||
applyFiltersButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.applyFiltersButton.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
topPane.add(applyFiltersButton, gridBagConstraints);
|
||||
|
||||
needsRefreshLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.needsRefreshLabel.text")); // NOI18N
|
||||
needsRefreshLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
topPane.add(needsRefreshLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_END;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
add(topPane, gridBagConstraints);
|
||||
|
||||
scrollPane.setBorder(null);
|
||||
|
||||
mainPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
limitPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
mostRecentLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.mostRecentLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 9, 0, 9);
|
||||
limitPane.add(mostRecentLabel, gridBagConstraints);
|
||||
|
||||
limitComboBox.setEditable(true);
|
||||
limitComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "All", "10000", "5000", "1000", "500", "100" }));
|
||||
limitComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
unCheckAllAccountTypesButtonActionPerformed(evt);
|
||||
limitComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
limitPane.add(limitComboBox, gridBagConstraints);
|
||||
|
||||
accountTypesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/accounts.png"))); // NOI18N
|
||||
accountTypesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypesLabel.text")); // NOI18N
|
||||
limitTitlePanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
checkAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllAccountTypesButton.text")); // NOI18N
|
||||
checkAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllAccountTypesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
limitHeaderLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitHeaderLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
limitTitlePanel.add(limitHeaderLabel, gridBagConstraints);
|
||||
|
||||
accountTypesScrollPane.setPreferredSize(new java.awt.Dimension(2, 200));
|
||||
limitErrorMsgLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
limitErrorMsgLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitErrorMsgLabel.text")); // NOI18N
|
||||
limitErrorMsgLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
limitErrorMsgLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
limitTitlePanel.add(limitErrorMsgLabel, gridBagConstraints);
|
||||
|
||||
accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
accountTypesScrollPane.setViewportView(accountTypeListPane);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 9, 0);
|
||||
limitPane.add(limitTitlePanel, gridBagConstraints);
|
||||
|
||||
accountTypeRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
accountTypeRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypeRequiredLabel.text")); // NOI18N
|
||||
accountTypeRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
accountTypeRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
|
||||
javax.swing.GroupLayout accountTypesPaneLayout = new javax.swing.GroupLayout(accountTypesPane);
|
||||
accountTypesPane.setLayout(accountTypesPaneLayout);
|
||||
accountTypesPaneLayout.setHorizontalGroup(
|
||||
accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, accountTypesPaneLayout.createSequentialGroup()
|
||||
.addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addComponent(accountTypesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(accountTypeRequiredLabel))
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(unCheckAllAccountTypesButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(checkAllAccountTypesButton))
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(accountTypesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
accountTypesPaneLayout.setVerticalGroup(
|
||||
accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(accountTypesLabel)
|
||||
.addComponent(accountTypeRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(accountTypesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(checkAllAccountTypesButton)
|
||||
.addComponent(unCheckAllAccountTypesButton)))
|
||||
);
|
||||
|
||||
unCheckAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllDevicesButton.text")); // NOI18N
|
||||
unCheckAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
unCheckAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
devicesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/image.png"))); // NOI18N
|
||||
devicesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.devicesLabel.text")); // NOI18N
|
||||
|
||||
checkAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllDevicesButton.text")); // NOI18N
|
||||
checkAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
devicesScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
devicesScrollPane.setMinimumSize(new java.awt.Dimension(27, 75));
|
||||
|
||||
devicesListPane.setMinimumSize(new java.awt.Dimension(4, 100));
|
||||
devicesListPane.setLayout(new javax.swing.BoxLayout(devicesListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
devicesScrollPane.setViewportView(devicesListPane);
|
||||
|
||||
deviceRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
deviceRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.deviceRequiredLabel.text")); // NOI18N
|
||||
deviceRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
deviceRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
|
||||
javax.swing.GroupLayout devicesPaneLayout = new javax.swing.GroupLayout(devicesPane);
|
||||
devicesPane.setLayout(devicesPaneLayout);
|
||||
devicesPaneLayout.setHorizontalGroup(
|
||||
devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addComponent(devicesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(deviceRequiredLabel))
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(unCheckAllDevicesButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(checkAllDevicesButton))
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(devicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
devicesPaneLayout.setVerticalGroup(
|
||||
devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addGroup(devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(devicesLabel)
|
||||
.addComponent(deviceRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(devicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(checkAllDevicesButton)
|
||||
.addComponent(unCheckAllDevicesButton))
|
||||
.addGap(5, 5, 5))
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 15, 0);
|
||||
mainPanel.add(limitPane, gridBagConstraints);
|
||||
|
||||
startDatePicker.setEnabled(false);
|
||||
|
||||
@ -582,97 +570,177 @@ final public class FiltersPanel extends JPanel {
|
||||
.addComponent(endCheckBox)))
|
||||
);
|
||||
|
||||
refreshButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N
|
||||
refreshButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.refreshButton.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
|
||||
mainPanel.add(dateRangePane, gridBagConstraints);
|
||||
|
||||
needsRefreshLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.needsRefreshLabel.text")); // NOI18N
|
||||
needsRefreshLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
devicesPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
limitHeaderLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitHeaderLabel.text")); // NOI18N
|
||||
|
||||
mostRecentLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.mostRecentLabel.text")); // NOI18N
|
||||
|
||||
limitComboBox.setEditable(true);
|
||||
limitComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "All", "10000", "5000", "1000", "500", "100" }));
|
||||
limitComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
unCheckAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllDevicesButton.text")); // NOI18N
|
||||
unCheckAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
limitComboBoxActionPerformed(evt);
|
||||
unCheckAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 9);
|
||||
devicesPane.add(unCheckAllDevicesButton, gridBagConstraints);
|
||||
|
||||
limitErrorMsgLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
limitErrorMsgLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitErrorMsgLabel.text")); // NOI18N
|
||||
limitErrorMsgLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
limitErrorMsgLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
devicesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/image.png"))); // NOI18N
|
||||
devicesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.devicesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 9, 0);
|
||||
devicesPane.add(devicesLabel, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout limitPaneLayout = new javax.swing.GroupLayout(limitPane);
|
||||
limitPane.setLayout(limitPaneLayout);
|
||||
limitPaneLayout.setHorizontalGroup(
|
||||
limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(limitPaneLayout.createSequentialGroup()
|
||||
.addComponent(limitHeaderLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(limitErrorMsgLabel)
|
||||
.addContainerGap())
|
||||
.addGroup(limitPaneLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(mostRecentLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(limitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
limitPaneLayout.setVerticalGroup(
|
||||
limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(limitPaneLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(limitHeaderLabel)
|
||||
.addComponent(limitErrorMsgLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(mostRecentLabel)
|
||||
.addComponent(limitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 32, Short.MAX_VALUE))
|
||||
);
|
||||
checkAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllDevicesButton.text")); // NOI18N
|
||||
checkAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0);
|
||||
devicesPane.add(checkAllDevicesButton, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(devicesPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(accountTypesPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(filtersTitleLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(applyFiltersButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(refreshButton))
|
||||
.addComponent(dateRangePane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(needsRefreshLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(limitPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(filtersTitleLabel)
|
||||
.addComponent(applyFiltersButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(refreshButton))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(needsRefreshLabel)
|
||||
.addGap(4, 4, 4)
|
||||
.addComponent(devicesPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(accountTypesPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(dateRangePane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(limitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
devicesScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
devicesScrollPane.setMinimumSize(new java.awt.Dimension(27, 75));
|
||||
|
||||
devicesListPane.setMinimumSize(new java.awt.Dimension(4, 100));
|
||||
devicesListPane.setLayout(new javax.swing.BoxLayout(devicesListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
devicesScrollPane.setViewportView(devicesListPane);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
devicesPane.add(devicesScrollPane, gridBagConstraints);
|
||||
|
||||
deviceRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
deviceRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.deviceRequiredLabel.text")); // NOI18N
|
||||
deviceRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
deviceRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 9, 0);
|
||||
devicesPane.add(deviceRequiredLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.ipady = 100;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
|
||||
mainPanel.add(devicesPane, gridBagConstraints);
|
||||
|
||||
accountTypesPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
unCheckAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllAccountTypesButton.text")); // NOI18N
|
||||
unCheckAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
unCheckAllAccountTypesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 9);
|
||||
accountTypesPane.add(unCheckAllAccountTypesButton, gridBagConstraints);
|
||||
|
||||
accountTypesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/accounts.png"))); // NOI18N
|
||||
accountTypesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
accountTypesPane.add(accountTypesLabel, gridBagConstraints);
|
||||
|
||||
checkAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllAccountTypesButton.text")); // NOI18N
|
||||
checkAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllAccountTypesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0);
|
||||
accountTypesPane.add(checkAllAccountTypesButton, gridBagConstraints);
|
||||
|
||||
accountTypesScrollPane.setPreferredSize(new java.awt.Dimension(2, 200));
|
||||
|
||||
accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
accountTypesScrollPane.setViewportView(accountTypeListPane);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0);
|
||||
accountTypesPane.add(accountTypesScrollPane, gridBagConstraints);
|
||||
|
||||
accountTypeRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
accountTypeRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypeRequiredLabel.text")); // NOI18N
|
||||
accountTypeRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
accountTypeRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
accountTypesPane.add(accountTypeRequiredLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
|
||||
mainPanel.add(accountTypesPane, gridBagConstraints);
|
||||
|
||||
scrollPane.setViewportView(mainPanel);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(scrollPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
/**
|
||||
@ -933,11 +1001,15 @@ final public class FiltersPanel extends JPanel {
|
||||
private final javax.swing.JLabel limitErrorMsgLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel limitHeaderLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JPanel limitPane = new javax.swing.JPanel();
|
||||
private final javax.swing.JPanel limitTitlePanel = new javax.swing.JPanel();
|
||||
private final javax.swing.JPanel mainPanel = new javax.swing.JPanel();
|
||||
private final javax.swing.JLabel mostRecentLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel needsRefreshLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JButton refreshButton = new javax.swing.JButton();
|
||||
private final javax.swing.JScrollPane scrollPane = new javax.swing.JScrollPane();
|
||||
private final javax.swing.JCheckBox startCheckBox = new javax.swing.JCheckBox();
|
||||
private final com.github.lgooddatepicker.components.DatePicker startDatePicker = new com.github.lgooddatepicker.components.DatePicker();
|
||||
private final javax.swing.JPanel topPane = new javax.swing.JPanel();
|
||||
private final javax.swing.JButton unCheckAllAccountTypesButton = new javax.swing.JButton();
|
||||
private final javax.swing.JButton unCheckAllDevicesButton = new javax.swing.JButton();
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
@ -44,3 +44,4 @@ SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Other O
|
||||
SummaryViewer_Creation_Date_Title=Creation Date
|
||||
SummaryViewer_FileRefNameColumn_Title=Path
|
||||
SummaryViewer_TabTitle=Summary
|
||||
SummeryViewer_FileRef_Message=<Select one Accout to see File References>
|
||||
|
@ -11,29 +11,38 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="contactPane" max="32767" attributes="0"/>
|
||||
<Component id="outlineViewPanel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="outlineViewPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="contactPane" pref="332" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane" name="contactPane">
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane" name="contactPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -23,7 +23,6 @@ import java.awt.KeyboardFocusManager;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import static javax.swing.SwingUtilities.isDescendingFrom;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
import org.netbeans.swing.outline.Outline;
|
||||
@ -126,6 +125,9 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer{
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
});
|
||||
|
||||
splitPane.setResizeWeight(0.5);
|
||||
splitPane.setDividerLocation(0.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,29 +185,32 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer{
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
splitPane = new javax.swing.JSplitPane();
|
||||
contactPane = new org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane();
|
||||
outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(outlineViewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(outlineViewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, 332, Short.MAX_VALUE))
|
||||
);
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
splitPane.setRightComponent(contactPane);
|
||||
splitPane.setLeftComponent(outlineViewPanel);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(splitPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane contactPane;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel;
|
||||
private javax.swing.JSplitPane splitPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -11,58 +11,57 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="thumbnailViewer" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="contentViewer" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="separator" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="thumbnailViewer" pref="350" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="separator" min="-2" pref="2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="contentViewer" min="-2" pref="450" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail" name="thumbnailViewer">
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[350, 102]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM)"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="separator">
|
||||
</Component>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail" name="thumbnailViewer">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[350, 102]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM)"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -65,6 +65,11 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
* Creates new form ThumbnailViewer
|
||||
*/
|
||||
public MediaViewer() {
|
||||
initComponents();
|
||||
|
||||
splitPane.setResizeWeight(0.5);
|
||||
splitPane.setDividerLocation(0.5);
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
|
||||
|
||||
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
|
||||
@ -87,8 +92,6 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
}
|
||||
};
|
||||
|
||||
initComponents();
|
||||
|
||||
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
handleNodeSelectionChange();
|
||||
@ -190,43 +193,37 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
splitPane = new javax.swing.JSplitPane();
|
||||
thumbnailViewer = new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM);
|
||||
contentViewer = new MessageDataContent();
|
||||
separator = new javax.swing.JSeparator();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
|
||||
thumbnailViewer.setMinimumSize(new java.awt.Dimension(350, 102));
|
||||
thumbnailViewer.setPreferredSize(new java.awt.Dimension(450, 400));
|
||||
splitPane.setLeftComponent(thumbnailViewer);
|
||||
|
||||
contentViewer.setPreferredSize(new java.awt.Dimension(450, 400));
|
||||
splitPane.setRightComponent(contentViewer);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(thumbnailViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(contentViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(separator)
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(thumbnailViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(contentViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(3, 3, 3))
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(splitPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
|
||||
private javax.swing.JSeparator separator;
|
||||
private javax.swing.JSplitPane splitPane;
|
||||
private org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail thumbnailViewer;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
@ -18,13 +18,10 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications.relationships;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
@ -40,7 +37,6 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHO
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TimeUtilities;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.communications.Utils;
|
||||
@ -72,7 +68,6 @@ final class MessageNode extends BlackboardArtifactNode {
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
List<Tag> tags = getAllTagsFromDatabase();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
@ -81,17 +76,6 @@ final class MessageNode extends BlackboardArtifactNode {
|
||||
|
||||
sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS
|
||||
|
||||
addScoreProperty(sheetSet, tags);
|
||||
|
||||
CorrelationAttributeInstance correlationAttribute = null;
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
correlationAttribute = getCorrelationAttributeInstance();
|
||||
}
|
||||
addCommentProperty(sheetSet, tags, correlationAttribute);
|
||||
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
addCountProperty(sheetSet, correlationAttribute);
|
||||
}
|
||||
final BlackboardArtifact artifact = getArtifact();
|
||||
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||
|
@ -11,32 +11,41 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,3,13,0,0,2,103"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="contentViewer" max="32767" attributes="0"/>
|
||||
<Component id="outlineViewPanel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="outlineViewPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="contentViewer" pref="390" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="bottom"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -23,7 +23,6 @@ import java.awt.KeyboardFocusManager;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import static javax.swing.SwingUtilities.isDescendingFrom;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
import org.netbeans.swing.outline.Outline;
|
||||
@ -68,6 +67,8 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
public MessagesViewer() {
|
||||
initComponents();
|
||||
|
||||
splitPane.setResizeWeight(0.5);
|
||||
|
||||
outlineViewPanel.hideOutlineView(Bundle.MessageViewer_no_messages());
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(outlineViewPanel.getExplorerManager(), getActionMap()));
|
||||
@ -138,6 +139,8 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
});
|
||||
|
||||
outlineViewPanel.setTableColumnsWidth(5,10,10,15,50,10);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -192,29 +195,32 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
splitPane = new javax.swing.JSplitPane();
|
||||
contentViewer = new MessageDataContent();
|
||||
outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(outlineViewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(outlineViewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE))
|
||||
);
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
splitPane.setBottomComponent(contentViewer);
|
||||
splitPane.setLeftComponent(outlineViewPanel);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(splitPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel;
|
||||
private javax.swing.JSplitPane splitPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -21,6 +24,7 @@
|
||||
<SubComponents>
|
||||
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
|
||||
<Properties>
|
||||
<Property name="horizontalScrollBarPolicy" type="int" value="32"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 400]"/>
|
||||
</Property>
|
||||
|
@ -19,7 +19,9 @@
|
||||
package org.sleuthkit.autopsy.communications.relationships;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import static org.openide.explorer.ExplorerUtils.createLookup;
|
||||
import org.openide.explorer.view.OutlineView;
|
||||
@ -98,7 +100,20 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana
|
||||
super.setEnabled(enabled);
|
||||
outlineView.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public void setTableColumnsWidth(double... percentages) {
|
||||
JTable table = outlineView.getOutline();
|
||||
double total = 0;
|
||||
for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) {
|
||||
total += percentages[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) {
|
||||
TableColumn column = table.getColumnModel().getColumn(i);
|
||||
column.setPreferredWidth((int) (table.getPreferredSize().width * (percentages[i] / total)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -112,8 +127,10 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana
|
||||
messagePanel = new javax.swing.JPanel();
|
||||
messageLabel = new javax.swing.JLabel();
|
||||
|
||||
setEnabled(false);
|
||||
setLayout(new java.awt.CardLayout(5, 5));
|
||||
|
||||
outlineView.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||
outlineView.setPreferredSize(new java.awt.Dimension(300, 400));
|
||||
add(outlineView, "outlineCard");
|
||||
|
||||
|
@ -11,42 +11,22 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Component id="scrollPane" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Component id="scrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="scrollPane">
|
||||
<Properties>
|
||||
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JTabbedPane" name="tabPane">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="1" insetsLeft="1" insetsBottom="1" insetsRight="1" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JTabbedPane" name="tabPane">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
|
||||
</Events>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -54,9 +54,7 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
|
||||
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
|
||||
tabPane.add(contactsViewer.getDisplayName(), contactsViewer);
|
||||
tabPane.add(mediaViewer.getDisplayName(), mediaViewer);
|
||||
|
||||
|
||||
tabPane.add(mediaViewer.getDisplayName(), mediaViewer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,33 +76,26 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
scrollPane = new javax.swing.JScrollPane();
|
||||
tabPane = new javax.swing.JTabbedPane();
|
||||
|
||||
scrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
tabPane.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
tabPaneStateChanged(evt);
|
||||
}
|
||||
});
|
||||
scrollPane.setViewportView(tabPane);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 400, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(scrollPane, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 300, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(scrollPane))
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
|
||||
add(tabPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged
|
||||
@ -121,7 +112,6 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JScrollPane scrollPane;
|
||||
private javax.swing.JTabbedPane tabPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
@ -11,36 +11,10 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,3,70,0,0,4,-35"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="countsPanel" max="32767" attributes="0"/>
|
||||
<Component id="fileReferencesPanel" alignment="0" pref="485" max="32767" attributes="0"/>
|
||||
<Component id="caseReferencesPanel" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="countsPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="fileReferencesPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="caseReferencesPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="countsPanel">
|
||||
<Properties>
|
||||
@ -52,6 +26,11 @@
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
@ -183,7 +162,7 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="org.sleuthkit.autopsy.communications.OutlineViewPanel" name="fileReferencesPanel">
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="fileReferencesPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
@ -192,12 +171,14 @@
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[472, 300]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.OutlineViewPanel" name="caseReferencesPanel">
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="caseReferencesPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
@ -206,10 +187,12 @@
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[472, 300]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -46,7 +46,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
"SummaryViewer_FileRefNameColumn_Title=Path",
|
||||
"SummaryViewer_CaseRefNameColumn_Title=Case Name",
|
||||
"SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Other Occurrences>",
|
||||
"SummaryViewer_Creation_Date_Title=Creation Date"
|
||||
"SummaryViewer_Creation_Date_Title=Creation Date",
|
||||
"SummeryViewer_FileRef_Message=<Select one Accout to see File References>",
|
||||
})
|
||||
|
||||
/**
|
||||
@ -70,6 +71,9 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.SummaryViewer_CaseRefNameColumn_Title());
|
||||
|
||||
clearControls();
|
||||
|
||||
caseReferencesPanel.hideOutlineView(Bundle.SummaryViewer_CentralRepository_Message());
|
||||
fileReferencesPanel.hideOutlineView(Bundle.SummeryViewer_FileRef_Message());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,7 +100,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
if (info.getAccounts().size() != 1) {
|
||||
setEnabled(false);
|
||||
clearControls();
|
||||
|
||||
|
||||
fileReferencesPanel.hideOutlineView(Bundle.SummeryViewer_FileRef_Message());
|
||||
} else {
|
||||
SelectionSummary summaryDetails = info.getSummary();
|
||||
|
||||
@ -105,6 +110,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
contactsDataLabel.setText(Integer.toString(summaryDetails.getContactsCnt()));
|
||||
emailDataLabel.setText(Integer.toString(summaryDetails.getEmailCnt()));
|
||||
messagesDataLabel.setText(Integer.toString(summaryDetails.getMessagesCnt()));
|
||||
|
||||
fileReferencesPanel.showOutlineView();
|
||||
|
||||
fileReferencesPanel.setNode(new AbstractNode(Children.create(new AccountSourceContentChildNodeFactory(info.getAccounts()), true)));
|
||||
caseReferencesPanel.setNode(new AbstractNode(Children.create(new CorrelationCaseChildNodeFactory(info.getAccounts()), true)));
|
||||
@ -178,6 +185,7 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
countsPanel = new javax.swing.JPanel();
|
||||
emailLabel = new javax.swing.JLabel();
|
||||
@ -193,6 +201,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
fileReferencesPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
caseReferencesPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
countsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.countsPanel.border.title"))); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(emailLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.emailLabel.text")); // NOI18N
|
||||
@ -262,35 +272,33 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
add(countsPanel, gridBagConstraints);
|
||||
|
||||
fileReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.fileReferencesPanel.border.title"))); // NOI18N
|
||||
fileReferencesPanel.setPreferredSize(new java.awt.Dimension(472, 300));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(fileReferencesPanel, gridBagConstraints);
|
||||
|
||||
caseReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.caseReferencesPanel.border.title"))); // NOI18N
|
||||
caseReferencesPanel.setPreferredSize(new java.awt.Dimension(472, 300));
|
||||
|
||||
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)
|
||||
.addComponent(countsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(fileReferencesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 485, Short.MAX_VALUE)
|
||||
.addComponent(caseReferencesPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(countsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(fileReferencesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(caseReferencesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(caseReferencesPanel, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
|
@ -89,3 +89,4 @@ MediaPlayerPanel.VolumeIcon.text=\ \ \ \ \ Volume
|
||||
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
|
||||
MediaPlayerPanel.playButton.text=\u25ba
|
||||
MediaPlayerPanel.infoLabel.text=No Errors
|
||||
MediaViewImagePanel.tagsMenu.text_1=Tags Menu
|
||||
|
@ -44,7 +44,11 @@ MediaPlayerPanel.timeFormat=%02d:%02d:%02d
|
||||
MediaPlayerPanel.unknownTime=Unknown
|
||||
MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory.
|
||||
MediaViewImagePanel.errorLabel.text=Could not load file into Media View.
|
||||
MediaViewImagePanel.exportSaveText=Save
|
||||
MediaViewImagePanel.externalViewerButton.text=Open in External Viewer Ctrl+E
|
||||
MediaViewImagePanel.fileChooserTitle=Choose a save location
|
||||
MediaViewImagePanel.successfulExport=Tagged image was successfully saved.
|
||||
MediaViewImagePanel.unsuccessfulExport=Unable to export tagged image to disk.
|
||||
MediaViewVideoPanel.pauseButton.text=\u25ba
|
||||
MediaViewVideoPanel.progressLabel.text=00:00
|
||||
MediaViewVideoPanel.infoLabel.text=info
|
||||
@ -151,6 +155,7 @@ MediaPlayerPanel.VolumeIcon.text=\ \ \ \ \ Volume
|
||||
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
|
||||
MediaPlayerPanel.playButton.text=\u25ba
|
||||
MediaPlayerPanel.infoLabel.text=No Errors
|
||||
MediaViewImagePanel.tagsMenu.text_1=Tags Menu
|
||||
# {0} - tableName
|
||||
SQLiteViewer.readTable.errorText=Error getting rows for table: {0}
|
||||
# {0} - tableName
|
||||
|
@ -11,30 +11,8 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.HtmlPanel" name="htmlPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Form>
|
||||
|
@ -37,17 +37,18 @@ final class HtmlViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(HtmlViewer.class.getName());
|
||||
|
||||
private static final String[] SUPPORTED_MIMETYPES = new String[]{
|
||||
"text/html",
|
||||
"application/xhtml+xml"
|
||||
};
|
||||
private final org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
|
||||
/**
|
||||
* Creates new form HtmlViewerPanel
|
||||
*/
|
||||
HtmlViewer() {
|
||||
initComponents();
|
||||
this.add(htmlPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,31 +82,12 @@ final class HtmlViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
|
||||
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()
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@Override
|
||||
public List<String> getSupportedMIMETypes() {
|
||||
return Arrays.asList(SUPPORTED_MIMETYPES);
|
||||
|
@ -19,7 +19,7 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,100,0,0,3,117"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
@ -200,6 +200,44 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="zoomResetButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[32767, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalGlue"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="tagsMenu">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaViewImagePanel.tagsMenu.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 21]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 21]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 21]"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="tagsMenuMousePressed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -20,18 +20,31 @@ package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import static java.util.Objects.nonNull;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ListChangeListener.Change;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
@ -45,19 +58,39 @@ import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFileChooser;
|
||||
import javafx.scene.Node;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.controlsfx.control.MaskerPane;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.python.google.common.collect.Lists;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import org.sleuthkit.autopsy.actions.GetTagNameAndCommentDialog;
|
||||
import org.sleuthkit.autopsy.actions.GetTagNameAndCommentDialog.TagNameAndComment;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.ContentViewerTag;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.SerializationException;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagsUtility;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagControls;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagRegion;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagCreator;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTag;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagsGroup;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Image viewer part of the Media View layered pane. Uses JavaFX to display the
|
||||
@ -70,17 +103,30 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPanel {
|
||||
|
||||
private static final Image EXTERNAL = new Image(MediaViewImagePanel.class.getResource("/org/sleuthkit/autopsy/images/external.png").toExternalForm());
|
||||
private final static Logger LOGGER = Logger.getLogger(MediaViewImagePanel.class.getName());
|
||||
|
||||
private final boolean fxInited;
|
||||
|
||||
private JFXPanel fxPanel;
|
||||
private Group imageGroup;
|
||||
private ImageTaggingTool tagger;
|
||||
private AbstractFile file;
|
||||
private Group masterGroup;
|
||||
private ImageTagsGroup tagsGroup;
|
||||
private ImageTagCreator imageTagCreator;
|
||||
private ImageView fxImageView;
|
||||
private ScrollPane scrollPane;
|
||||
private final ProgressBar progressBar = new ProgressBar();
|
||||
private final MaskerPane maskerPane = new MaskerPane();
|
||||
|
||||
private final JPopupMenu popupMenu = new JPopupMenu();
|
||||
private final JMenuItem createTagMenuItem;
|
||||
private final JMenuItem deleteTagMenuItem;
|
||||
private final JMenuItem hideTagsMenuItem;
|
||||
private final JMenuItem exportTagsMenuItem;
|
||||
|
||||
private final JFileChooser exportChooser;
|
||||
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
private double zoomRatio;
|
||||
private double rotation; // Can be 0, 90, 180, and 270.
|
||||
|
||||
@ -116,33 +162,163 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
public MediaViewImagePanel() {
|
||||
initComponents();
|
||||
fxInited = org.sleuthkit.autopsy.core.Installer.isJavaFxInited();
|
||||
|
||||
exportChooser = new JFileChooser();
|
||||
exportChooser.setDialogTitle(Bundle.MediaViewImagePanel_fileChooserTitle());
|
||||
|
||||
//Build popupMenu when Tags Menu button is pressed.
|
||||
createTagMenuItem = new JMenuItem("Create");
|
||||
createTagMenuItem.addActionListener((event) -> createTag());
|
||||
popupMenu.add(createTagMenuItem);
|
||||
|
||||
popupMenu.add(new JSeparator());
|
||||
|
||||
deleteTagMenuItem = new JMenuItem("Delete");
|
||||
deleteTagMenuItem.addActionListener((event) -> deleteTag());
|
||||
popupMenu.add(deleteTagMenuItem);
|
||||
|
||||
popupMenu.add(new JSeparator());
|
||||
|
||||
hideTagsMenuItem = new JMenuItem("Hide");
|
||||
hideTagsMenuItem.addActionListener((event) -> showOrHideTags());
|
||||
popupMenu.add(hideTagsMenuItem);
|
||||
|
||||
popupMenu.add(new JSeparator());
|
||||
|
||||
exportTagsMenuItem = new JMenuItem("Export");
|
||||
exportTagsMenuItem.addActionListener((event) -> exportTags());
|
||||
popupMenu.add(exportTagsMenuItem);
|
||||
|
||||
popupMenu.setPopupSize(300, 150);
|
||||
|
||||
if (fxInited) {
|
||||
Platform.runLater(() -> {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// build jfx ui (we could do this in FXML?)
|
||||
fxImageView = new ImageView(); // will hold image
|
||||
masterGroup = new Group(fxImageView);
|
||||
tagsGroup = new ImageTagsGroup(fxImageView);
|
||||
tagsGroup.getChildren().addListener((Change<? extends Node> c) -> {
|
||||
if (c.getList().isEmpty()) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.EMPTY));
|
||||
}
|
||||
});
|
||||
|
||||
// build jfx ui (we could do this in FXML?)
|
||||
fxImageView = new ImageView(); // will hold image
|
||||
imageGroup = new Group();
|
||||
imageGroup.getChildren().add(fxImageView);
|
||||
scrollPane = new ScrollPane(imageGroup); // scrolls and sizes imageview
|
||||
scrollPane.getStyleClass().add("bg"); //NOI18N
|
||||
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
subscribeTagMenuItemsToStateChanges();
|
||||
|
||||
fxPanel = new JFXPanel(); // bridge jfx-swing
|
||||
Scene scene = new Scene(scrollPane); //root of jfx tree
|
||||
scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); //NOI18N
|
||||
fxPanel.setScene(scene);
|
||||
masterGroup.getChildren().add(tagsGroup);
|
||||
|
||||
fxImageView.setSmooth(true);
|
||||
fxImageView.setCache(true);
|
||||
//Update buttons when users select (or unselect) image tags.
|
||||
tagsGroup.addFocusChangeListener((event) -> {
|
||||
if (event.getPropertyName().equals(ImageTagControls.NOT_FOCUSED.getName())) {
|
||||
if (masterGroup.getChildren().contains(imageTagCreator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
add(fxPanel);//add jfx ui to JPanel
|
||||
});
|
||||
if (tagsGroup.getChildren().isEmpty()) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.EMPTY));
|
||||
} else {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.CREATE));
|
||||
}
|
||||
} else if (event.getPropertyName().equals(ImageTagControls.FOCUSED.getName())) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.SELECTED));
|
||||
}
|
||||
});
|
||||
|
||||
scrollPane = new ScrollPane(masterGroup); // scrolls and sizes imageview
|
||||
scrollPane.getStyleClass().add("bg"); //NOI18N
|
||||
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
|
||||
fxPanel = new JFXPanel(); // bridge jfx-swing
|
||||
Scene scene = new Scene(scrollPane); //root of jfx tree
|
||||
scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); //NOI18N
|
||||
fxPanel.setScene(scene);
|
||||
|
||||
fxImageView.setSmooth(true);
|
||||
fxImageView.setCache(true);
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
add(fxPanel);//add jfx ui to JPanel
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tags menu item enabling and disabling given the state of the
|
||||
* content viewer. For example, when the tags group is empty (no tags on image),
|
||||
* disable delete menu item, hide menu item, and export menu item.
|
||||
*/
|
||||
private void subscribeTagMenuItemsToStateChanges() {
|
||||
pcs.addPropertyChangeListener((event) -> {
|
||||
State currentState = (State) event.getNewValue();
|
||||
switch (currentState) {
|
||||
case CREATE:
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case SELECTED:
|
||||
if (masterGroup.getChildren().contains(imageTagCreator)) {
|
||||
imageTagCreator.disconnect();
|
||||
masterGroup.getChildren().remove(imageTagCreator);
|
||||
}
|
||||
createTagMenuItem.setEnabled(false);
|
||||
deleteTagMenuItem.setEnabled(true);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case HIDDEN:
|
||||
createTagMenuItem.setEnabled(false);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
hideTagsMenuItem.setText(DisplayOptions.SHOW_TAGS.getName());
|
||||
exportTagsMenuItem.setEnabled(false);
|
||||
break;
|
||||
case VISIBLE:
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
hideTagsMenuItem.setText(DisplayOptions.HIDE_TAGS.getName());
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case DEFAULT:
|
||||
case EMPTY:
|
||||
if (masterGroup.getChildren().contains(imageTagCreator)) {
|
||||
imageTagCreator.disconnect();
|
||||
}
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setText(DisplayOptions.HIDE_TAGS.getName());
|
||||
exportTagsMenuItem.setEnabled(false);
|
||||
break;
|
||||
case NONEMPTY:
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case DISABLE:
|
||||
createTagMenuItem.setEnabled(false);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(false);
|
||||
exportTagsMenuItem.setEnabled(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isInited() {
|
||||
return fxInited;
|
||||
}
|
||||
@ -154,10 +330,11 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
Platform.runLater(() -> {
|
||||
fxImageView.setViewport(new Rectangle2D(0, 0, 0, 0));
|
||||
fxImageView.setImage(null);
|
||||
tagger.defaultSettings();
|
||||
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.DEFAULT));
|
||||
masterGroup.getChildren().clear();
|
||||
scrollPane.setContent(null);
|
||||
scrollPane.setContent(imageGroup);
|
||||
scrollPane.setContent(masterGroup);
|
||||
});
|
||||
}
|
||||
|
||||
@ -205,14 +382,31 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
|
||||
try {
|
||||
Image fxImage = readImageTask.get();
|
||||
masterGroup.getChildren().clear();
|
||||
tagsGroup.getChildren().clear();
|
||||
this.file = file;
|
||||
if (nonNull(fxImage)) {
|
||||
// We have a non-null image, so let's show it.
|
||||
fxImageView.setImage(fxImage);
|
||||
imageGroup.getChildren().remove(tagger);
|
||||
tagger = new ImageTaggingTool(fxImageView, Color.RED);
|
||||
imageGroup.getChildren().add(tagger);
|
||||
resetView();
|
||||
scrollPane.setContent(imageGroup);
|
||||
masterGroup.getChildren().add(fxImageView);
|
||||
masterGroup.getChildren().add(tagsGroup);
|
||||
|
||||
try {
|
||||
List<ContentTag> tags = Case.getCurrentCase().getServices()
|
||||
.getTagsManager().getContentTagsByContent(file);
|
||||
|
||||
List<ContentViewerTag<ImageTagRegion>> contentViewerTags = getContentViewerTags(tags);
|
||||
//Add all image tags
|
||||
tagsGroup = buildImageTagsGroup(contentViewerTags);
|
||||
if (!tagsGroup.getChildren().isEmpty()) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.NONEMPTY));
|
||||
}
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not retrieve image tags for file in case db", ex); //NON-NLS
|
||||
}
|
||||
scrollPane.setContent(masterGroup);
|
||||
} else {
|
||||
showErrorNode(Bundle.MediaViewImagePanel_errorLabel_text(), file);
|
||||
}
|
||||
@ -252,6 +446,52 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all ContentViewerTags that are of type 'ImageTagRegion' for the
|
||||
* current file.
|
||||
*
|
||||
* @param contentTags
|
||||
* @return
|
||||
* @throws TskCoreException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
private List<ContentViewerTag<ImageTagRegion>> getContentViewerTags(List<ContentTag> contentTags)
|
||||
throws TskCoreException, NoCurrentCaseException {
|
||||
List<ContentViewerTag<ImageTagRegion>> contentViewerTags = new ArrayList<>();
|
||||
for (ContentTag contentTag : contentTags) {
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = ContentViewerTagManager
|
||||
.getTag(contentTag, ImageTagRegion.class);
|
||||
if (contentViewerTag == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
contentViewerTags.add(contentViewerTag);
|
||||
}
|
||||
return contentViewerTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds ImageTag instances from stored ContentViewerTags of the
|
||||
* appropriate type.
|
||||
*
|
||||
* @param contentTags
|
||||
* @return
|
||||
* @throws TskCoreException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
private ImageTagsGroup buildImageTagsGroup(List<ContentViewerTag<ImageTagRegion>> contentViewerTags) {
|
||||
|
||||
contentViewerTags.forEach(contentViewerTag -> {
|
||||
/**
|
||||
* Build the image tag, add an edit event call back to persist all
|
||||
* edits made on this image tag instance.
|
||||
*/
|
||||
tagsGroup.getChildren().add(buildImageTag(contentViewerTag));
|
||||
});
|
||||
|
||||
return tagsGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return supported mime types
|
||||
*/
|
||||
@ -303,6 +543,10 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
zoomInButton = new javax.swing.JButton();
|
||||
jSeparator2 = new javax.swing.JToolBar.Separator();
|
||||
zoomResetButton = new javax.swing.JButton();
|
||||
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0));
|
||||
filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
tagsMenu = new javax.swing.JButton();
|
||||
|
||||
setBackground(new java.awt.Color(0, 0, 0));
|
||||
addComponentListener(new java.awt.event.ComponentAdapter() {
|
||||
@ -406,6 +650,23 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
}
|
||||
});
|
||||
toolbar.add(zoomResetButton);
|
||||
toolbar.add(filler1);
|
||||
toolbar.add(filler2);
|
||||
toolbar.add(jPanel1);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(tagsMenu, org.openide.util.NbBundle.getMessage(MediaViewImagePanel.class, "MediaViewImagePanel.tagsMenu.text_1")); // NOI18N
|
||||
tagsMenu.setFocusable(false);
|
||||
tagsMenu.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tagsMenu.setMaximumSize(new java.awt.Dimension(75, 21));
|
||||
tagsMenu.setMinimumSize(new java.awt.Dimension(75, 21));
|
||||
tagsMenu.setPreferredSize(new java.awt.Dimension(75, 21));
|
||||
tagsMenu.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tagsMenu.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mousePressed(java.awt.event.MouseEvent evt) {
|
||||
tagsMenuMousePressed(evt);
|
||||
}
|
||||
});
|
||||
toolbar.add(tagsMenu);
|
||||
|
||||
add(toolbar);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
@ -450,12 +711,234 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
updateView();
|
||||
}//GEN-LAST:event_formComponentResized
|
||||
|
||||
/**
|
||||
* Deletes the selected tag when the Delete button is pressed in the Tag
|
||||
* Menu.
|
||||
*/
|
||||
private void deleteTag() {
|
||||
Platform.runLater(() -> {
|
||||
ImageTag tagInFocus = tagsGroup.getFocus();
|
||||
if (tagInFocus == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = tagInFocus.getContentViewerTag();
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
ContentViewerTagManager.deleteTag(contentViewerTag);
|
||||
Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(contentViewerTag.getContentTag());
|
||||
tagsGroup.getChildren().remove(tagInFocus);
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not delete image tag in case db", ex); //NON-NLS
|
||||
}
|
||||
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.CREATE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables create tag logic when the Create button is pressed in the Tags
|
||||
* Menu.
|
||||
*/
|
||||
private void createTag() {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.DISABLE));
|
||||
imageTagCreator = new ImageTagCreator(fxImageView);
|
||||
|
||||
PropertyChangeListener newTagListener = (event) -> {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
ImageTagRegion tag = (ImageTagRegion) event.getNewValue();
|
||||
//Ask the user for tag name and comment
|
||||
TagNameAndComment result = GetTagNameAndCommentDialog.doDialog();
|
||||
if (result != null) {
|
||||
//Persist and build image tag
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = storeImageTag(tag, result);
|
||||
ImageTag imageTag = buildImageTag(contentViewerTag);
|
||||
tagsGroup.getChildren().add(imageTag);
|
||||
} catch (TskCoreException | SerializationException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not save new image tag in case db", ex); //NON-NLS
|
||||
}
|
||||
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
}
|
||||
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.CREATE));
|
||||
});
|
||||
|
||||
//Remove image tag creator from panel
|
||||
Platform.runLater(() -> {
|
||||
imageTagCreator.disconnect();
|
||||
masterGroup.getChildren().remove(imageTagCreator);
|
||||
});
|
||||
};
|
||||
|
||||
imageTagCreator.addNewTagListener(newTagListener);
|
||||
Platform.runLater(() -> masterGroup.getChildren().add(imageTagCreator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ImageTag instance from the ContentViewerTag.
|
||||
*
|
||||
* @param contentViewerTag
|
||||
* @return
|
||||
*/
|
||||
private ImageTag buildImageTag(ContentViewerTag<ImageTagRegion> contentViewerTag) {
|
||||
ImageTag imageTag = new ImageTag(contentViewerTag, fxImageView);
|
||||
|
||||
//Automatically persist edits made by user
|
||||
imageTag.subscribeToEditEvents((edit) -> {
|
||||
try {
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
ImageTagRegion newRegion = (ImageTagRegion) edit.getNewValue();
|
||||
ContentViewerTagManager.updateTag(contentViewerTag, newRegion);
|
||||
} catch (SerializationException | TskCoreException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not save edit for image tag in case db", ex); //NON-NLS
|
||||
}
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
return imageTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the image tag by creating a ContentTag instance and associating
|
||||
* the ImageTagRegion data with it in the case database.
|
||||
*
|
||||
* @param data
|
||||
* @param result
|
||||
*/
|
||||
private ContentViewerTag<ImageTagRegion> storeImageTag(ImageTagRegion data, TagNameAndComment result)
|
||||
throws TskCoreException, SerializationException, NoCurrentCaseException {
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
try {
|
||||
ContentTag contentTag = Case.getCurrentCaseThrows().getServices().getTagsManager()
|
||||
.addContentTag(file, result.getTagName(), result.getComment());
|
||||
return ContentViewerTagManager.saveTag(contentTag, data);
|
||||
} finally {
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides or show tags when the Hide or Show button is pressed in the Tags
|
||||
* Menu.
|
||||
*/
|
||||
private void showOrHideTags() {
|
||||
Platform.runLater(() -> {
|
||||
if (DisplayOptions.HIDE_TAGS.getName().equals(hideTagsMenuItem.getText())) {
|
||||
//Temporarily remove the tags group and update buttons
|
||||
masterGroup.getChildren().remove(tagsGroup);
|
||||
hideTagsMenuItem.setText(DisplayOptions.SHOW_TAGS.getName());
|
||||
tagsGroup.clearFocus();
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.HIDDEN));
|
||||
} else {
|
||||
//Add tags group back in and update buttons
|
||||
masterGroup.getChildren().add(tagsGroup);
|
||||
hideTagsMenuItem.setText(DisplayOptions.HIDE_TAGS.getName());
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.VISIBLE));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"MediaViewImagePanel.exportSaveText=Save",
|
||||
"MediaViewImagePanel.successfulExport=Tagged image was successfully saved.",
|
||||
"MediaViewImagePanel.unsuccessfulExport=Unable to export tagged image to disk.",
|
||||
"MediaViewImagePanel.fileChooserTitle=Choose a save location"
|
||||
})
|
||||
private void exportTags() {
|
||||
tagsGroup.clearFocus();
|
||||
exportChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
//Always base chooser location to export folder
|
||||
exportChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory()));
|
||||
int returnVal = exportChooser.showDialog(this, Bundle.MediaViewImagePanel_exportSaveText());
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
new SwingWorker<Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
try {
|
||||
//Retrieve content viewer tags
|
||||
List<ContentTag> tags = Case.getCurrentCase().getServices()
|
||||
.getTagsManager().getContentTagsByContent(file);
|
||||
List<ContentViewerTag<ImageTagRegion>> contentViewerTags = getContentViewerTags(tags);
|
||||
|
||||
//Pull out image tag regions
|
||||
Collection<ImageTagRegion> regions = contentViewerTags.stream()
|
||||
.map(cvTag -> cvTag.getDetails()).collect(Collectors.toList());
|
||||
|
||||
//Apply tags to image and write to file
|
||||
BufferedImage pngImage = ImageTagsUtility.writeTags(file, regions, "png");
|
||||
Path output = Paths.get(exportChooser.getSelectedFile().getPath(),
|
||||
FilenameUtils.getBaseName(file.getName()) + "-with_tags.png"); //NON-NLS
|
||||
ImageIO.write(pngImage, "png", output.toFile());
|
||||
|
||||
JOptionPane.showMessageDialog(null, Bundle.MediaViewImagePanel_successfulExport());
|
||||
} catch (TskCoreException | NoCurrentCaseException | IOException ex) {
|
||||
LOGGER.log(Level.WARNING, "Unable to export tagged image to disk", ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(null, Bundle.MediaViewImagePanel_unsuccessfulExport());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void tagsMenuMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tagsMenuMousePressed
|
||||
popupMenu.show(tagsMenu, -300 + tagsMenu.getWidth(), tagsMenu.getHeight() + 3);
|
||||
}//GEN-LAST:event_tagsMenuMousePressed
|
||||
|
||||
/**
|
||||
* Display states for the show/hide tags button.
|
||||
*/
|
||||
enum DisplayOptions {
|
||||
HIDE_TAGS("Hide"),
|
||||
SHOW_TAGS("Show");
|
||||
|
||||
private final String name;
|
||||
|
||||
DisplayOptions(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Different states that the content viewer can be in. These states drive
|
||||
* which buttons are enabled for tagging.
|
||||
*/
|
||||
enum State {
|
||||
HIDDEN,
|
||||
VISIBLE,
|
||||
SELECTED,
|
||||
CREATE,
|
||||
EMPTY,
|
||||
NONEMPTY,
|
||||
DEFAULT,
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.Box.Filler filler1;
|
||||
private javax.swing.Box.Filler filler2;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JToolBar.Separator jSeparator1;
|
||||
private javax.swing.JToolBar.Separator jSeparator2;
|
||||
private javax.swing.JButton rotateLeftButton;
|
||||
private javax.swing.JButton rotateRightButton;
|
||||
private javax.swing.JTextField rotationTextField;
|
||||
private javax.swing.JButton tagsMenu;
|
||||
private javax.swing.JToolBar toolbar;
|
||||
private javax.swing.JButton zoomInButton;
|
||||
private javax.swing.JButton zoomOutButton;
|
||||
@ -601,8 +1084,8 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
// Add the transforms in reverse order of intended execution.
|
||||
// Note: They MUST be added in this order to ensure translate is
|
||||
// executed last.
|
||||
imageGroup.getTransforms().clear();
|
||||
imageGroup.getTransforms().addAll(translate, rotate, scale);
|
||||
masterGroup.getTransforms().clear();
|
||||
masterGroup.getTransforms().addAll(translate, rotate, scale);
|
||||
|
||||
// Adjust scroll bar positions for view changes.
|
||||
if (viewportWidth > fxPanel.getWidth()) {
|
||||
@ -618,107 +1101,4 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
rotationTextField.setText((int) rotation + "°");
|
||||
zoomTextField.setText((Math.round(zoomRatio * 100.0)) + "%");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables users to 'tag' a region of an image by clicking and dragging a
|
||||
* rectangle overtop.
|
||||
*/
|
||||
class ImageTaggingTool extends Rectangle {
|
||||
|
||||
private final double imageWidth;
|
||||
private final double imageHeight;
|
||||
private final double imageOriginX;
|
||||
private final double imageOriginY;
|
||||
|
||||
//Origin of the drag event.
|
||||
private double rectangleOriginX;
|
||||
private double rectangleOriginY;
|
||||
|
||||
//Rectangle lines should be 1.5% of the image. This level of thickness has
|
||||
//a good balance between visual acuity and loss of selection at the borders
|
||||
//of the image.
|
||||
private double lineThicknessAsPercent = 1.5;
|
||||
|
||||
/**
|
||||
* Adds tagging support to an image, where the 'tag' rectangle will be
|
||||
* the specified color.
|
||||
*
|
||||
* @param image Image to tag
|
||||
* @param color Color of the 'tag' rectangle
|
||||
*/
|
||||
private ImageTaggingTool(ImageView image, Color color) {
|
||||
defaultSettings();
|
||||
|
||||
imageWidth = image.getImage().getWidth();
|
||||
imageHeight = image.getImage().getHeight();
|
||||
imageOriginX = image.getX();
|
||||
imageOriginY = image.getY();
|
||||
|
||||
setStroke(color);
|
||||
setFill(color.deriveColor(0, 0, 0, 0));
|
||||
|
||||
//Calculate how many pixels the stroke width should be to guarentee
|
||||
//a consistent % of image consumed by the rectangle border.
|
||||
double min = Math.min(imageWidth, imageHeight);
|
||||
double lineThicknessPixels = min * lineThicknessAsPercent / 100.0;
|
||||
setStrokeWidth(lineThicknessPixels);
|
||||
setVisible(false);
|
||||
|
||||
//Create a rectangle by left clicking on the image
|
||||
image.setOnMousePressed((MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Reset box on new click.
|
||||
defaultSettings();
|
||||
|
||||
rectangleOriginX = event.getX();
|
||||
rectangleOriginY = event.getY();
|
||||
|
||||
setX(rectangleOriginX);
|
||||
setY(rectangleOriginY);
|
||||
});
|
||||
|
||||
//Adjust the rectangle by dragging the left mouse button
|
||||
image.setOnMouseDragged((MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the rectangle is contained within image boundaries and
|
||||
* that the line thickness is kept within bounds.
|
||||
*/
|
||||
double newX = Math.min(Math.max(event.getX(), imageOriginX)
|
||||
+ lineThicknessPixels / 2, imageWidth - lineThicknessPixels / 2);
|
||||
double newY = Math.min(Math.max(event.getY(), imageOriginY)
|
||||
+ lineThicknessPixels / 2, imageHeight - lineThicknessPixels / 2);
|
||||
|
||||
setVisible(true);
|
||||
double offsetX = newX - rectangleOriginX;
|
||||
if (offsetX < 0) {
|
||||
setX(newX);
|
||||
}
|
||||
setWidth(Math.abs(offsetX));
|
||||
|
||||
double offsetY = newY - rectangleOriginY;
|
||||
if (offsetY < 0) {
|
||||
setY(newY);
|
||||
}
|
||||
setHeight(Math.abs(offsetY));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the rectangle to default dimensions.
|
||||
*/
|
||||
public final void defaultSettings() {
|
||||
setX(0);
|
||||
setY(0);
|
||||
setWidth(0);
|
||||
setHeight(0);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -271,22 +271,7 @@
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="htmlPanel" alignment="0" pref="647" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="htmlPanel" alignment="0" pref="362" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.HtmlPanel" name="htmlPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="rtfbodyScrollPane">
|
||||
<Properties>
|
||||
|
@ -87,7 +87,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
private static final int ATTM_TAB_INDEX = 4;
|
||||
|
||||
private final List<JTextComponent> textAreas;
|
||||
|
||||
private final org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
/**
|
||||
* Artifact currently being displayed
|
||||
*/
|
||||
@ -101,6 +101,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
@NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
|
||||
public MessageContentViewer() {
|
||||
initComponents();
|
||||
htmlPane.add(htmlPanel);
|
||||
envelopePanel.setBackground(new Color(0, 0, 0, 38));
|
||||
drp = DataResultPanel.createInstanceUninitialized(Bundle.MessageContentViewer_AtrachmentsPanel_title(), "", new TableFilterNode(Node.EMPTY, false), 0, null);
|
||||
attachmentsScrollPane.setViewportView(drp);
|
||||
@ -153,7 +154,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
textbodyScrollPane = new javax.swing.JScrollPane();
|
||||
textbodyTextArea = new javax.swing.JTextArea();
|
||||
htmlPane = new javax.swing.JPanel();
|
||||
htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
rtfbodyScrollPane = new javax.swing.JScrollPane();
|
||||
rtfbodyTextPane = new javax.swing.JTextPane();
|
||||
attachmentsPanel = new javax.swing.JPanel();
|
||||
@ -266,17 +266,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.textbodyScrollPane.TabConstraints.tabTitle"), textbodyScrollPane); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout htmlPaneLayout = new javax.swing.GroupLayout(htmlPane);
|
||||
htmlPane.setLayout(htmlPaneLayout);
|
||||
htmlPaneLayout.setHorizontalGroup(
|
||||
htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)
|
||||
);
|
||||
htmlPaneLayout.setVerticalGroup(
|
||||
htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
htmlPane.setLayout(new java.awt.BorderLayout());
|
||||
msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
|
||||
|
||||
rtfbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
@ -357,7 +347,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
private javax.swing.JScrollPane headersScrollPane;
|
||||
private javax.swing.JTextArea headersTextArea;
|
||||
private javax.swing.JPanel htmlPane;
|
||||
private org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel;
|
||||
private javax.swing.JTabbedPane msgbodyTabbedPane;
|
||||
private javax.swing.JScrollPane rtfbodyScrollPane;
|
||||
private javax.swing.JTextPane rtfbodyTextPane;
|
||||
@ -534,7 +523,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
textComponent.setCaretPosition(0); //make sure we start at the top
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final boolean hasText = attributeText.length() > 0;
|
||||
|
||||
msgbodyTabbedPane.setEnabledAt(index, hasText);
|
||||
@ -680,18 +669,18 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Set<String> keepProps = new HashSet<>(Arrays.asList(
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
|
||||
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
|
||||
|
||||
//Remove all other props except for the ones above
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
for(Property<?> p : sheetSet.getProperties()) {
|
||||
if(!keepProps.contains(p.getName())){
|
||||
for (Property<?> p : sheetSet.getProperties()) {
|
||||
if (!keepProps.contains(p.getName())) {
|
||||
sheetSet.remove(p.getName());
|
||||
}
|
||||
}
|
||||
|
343
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTag.java
Executable file
343
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTag.java
Executable file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.contentviewers.imagetagging;
|
||||
|
||||
import com.sun.javafx.event.EventDispatchChainImpl;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.ContentViewerTag;
|
||||
|
||||
/**
|
||||
* A tagged region displayed over an image. This class contains a "physical tag"
|
||||
* and 8 edit "handles". The physical tag is a plain old rectangle that defines
|
||||
* the tag boundaries. The edit handles serve two purposes. One is to represent
|
||||
* selection. All 8 edit handles will become visible overtop the physical tag
|
||||
* when the user clicks on the rectangle. The other purpose is to allow the user to edit
|
||||
* and manipulate the physical tag boundaries (hence the name, edit handle).
|
||||
* This class should be treated as a logical image tag.
|
||||
*/
|
||||
public final class ImageTag extends Group {
|
||||
|
||||
// Used to tell the 8 edit handles to hide if this tag is no longer selected
|
||||
private final EventDispatchChainImpl ALL_CHILDREN;
|
||||
|
||||
//Notifies listeners that the user has editted the tag boundaries
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
//The underlying presistent tag details that this image tag originates from
|
||||
private final ContentViewerTag<ImageTagRegion> appTag;
|
||||
|
||||
public ImageTag(ContentViewerTag<ImageTagRegion> contentViewerTag, ImageView image) {
|
||||
ALL_CHILDREN = new EventDispatchChainImpl();
|
||||
this.appTag = contentViewerTag;
|
||||
|
||||
this.getChildren().addListener((ListChangeListener<Node>) change -> {
|
||||
change.next();
|
||||
change.getAddedSubList().forEach((node) -> ALL_CHILDREN.append(node.getEventDispatcher()));
|
||||
});
|
||||
|
||||
ImageTagRegion details = contentViewerTag.getDetails();
|
||||
PhysicalTag physicalTag = new PhysicalTag(details);
|
||||
|
||||
//Defines the max allowable boundary that a user may drag any given handle.
|
||||
Boundary dragBoundary = (x, y) -> {
|
||||
double boundingX = image.getX();
|
||||
double boundingY = image.getY();
|
||||
double width = image.getImage().getWidth();
|
||||
double height = image.getImage().getHeight();
|
||||
|
||||
return x > boundingX + details.getStrokeThickness() / 2
|
||||
&& x < boundingX + width - details.getStrokeThickness() / 2
|
||||
&& y > boundingY + details.getStrokeThickness() / 2
|
||||
&& y < boundingY + height - details.getStrokeThickness() / 2;
|
||||
};
|
||||
|
||||
EditHandle bottomLeft = new EditHandle(physicalTag)
|
||||
.setPosition(Position.bottom(), Position.left())
|
||||
.setDrag(dragBoundary, Draggable.bottom(), Draggable.left());
|
||||
|
||||
EditHandle bottomRight = new EditHandle(physicalTag)
|
||||
.setPosition(Position.bottom(), Position.right())
|
||||
.setDrag(dragBoundary, Draggable.bottom(), Draggable.right());
|
||||
|
||||
EditHandle topLeft = new EditHandle(physicalTag)
|
||||
.setPosition(Position.top(), Position.left())
|
||||
.setDrag(dragBoundary, Draggable.top(), Draggable.left());
|
||||
|
||||
EditHandle topRight = new EditHandle(physicalTag)
|
||||
.setPosition(Position.top(), Position.right())
|
||||
.setDrag(dragBoundary, Draggable.top(), Draggable.right());
|
||||
|
||||
EditHandle bottomMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.bottom(), Position.xMiddle())
|
||||
.setDrag(dragBoundary, Draggable.bottom());
|
||||
|
||||
EditHandle topMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.top(), Position.xMiddle())
|
||||
.setDrag(dragBoundary, Draggable.top());
|
||||
|
||||
EditHandle rightMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.right(), Position.yMiddle())
|
||||
.setDrag(dragBoundary, Draggable.right());
|
||||
|
||||
EditHandle leftMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.left(), Position.yMiddle())
|
||||
.setDrag(dragBoundary, Draggable.left());
|
||||
|
||||
//The "logical" tag is the Group
|
||||
this.getChildren().addAll(physicalTag, bottomLeft, bottomRight, topLeft,
|
||||
topRight, bottomMiddle, topMiddle, rightMiddle, leftMiddle);
|
||||
|
||||
Tooltip.install(this, new Tooltip(contentViewerTag.getContentTag()
|
||||
.getName().getDisplayName()));
|
||||
|
||||
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
|
||||
this.addEventHandler(ImageTagControls.FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new listener for edit events. These events are generated when a
|
||||
* user drags on one of the edit "knobs" of the tag.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void subscribeToEditEvents(PropertyChangeListener listener) {
|
||||
pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content viewer tag that this class represents.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ContentViewerTag<ImageTagRegion> getContentViewerTag() {
|
||||
return appTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain old rectangle that represents an unselected Image Tag
|
||||
*/
|
||||
class PhysicalTag extends Rectangle {
|
||||
|
||||
public PhysicalTag(ImageTagRegion details) {
|
||||
this.setStroke(Color.RED);
|
||||
this.setFill(Color.RED.deriveColor(0, 0, 0, 0));
|
||||
this.setStrokeWidth(details.getStrokeThickness());
|
||||
|
||||
setX(details.getX());
|
||||
setY(details.getY());
|
||||
setWidth(details.getWidth());
|
||||
setHeight(details.getHeight());
|
||||
|
||||
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> this.setOpacity(1));
|
||||
this.addEventHandler(ImageTagControls.FOCUSED, event -> this.setOpacity(0.5));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a portable description of the tag region.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ImageTagRegion getState() {
|
||||
return new ImageTagRegion()
|
||||
.setX(this.getX())
|
||||
.setY(this.getY())
|
||||
.setWidth(this.getWidth())
|
||||
.setHeight(this.getHeight())
|
||||
.setStrokeThickness(this.getStrokeWidth());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draggable "knob" used to manipulate the physical tag boundaries.
|
||||
*/
|
||||
class EditHandle extends Circle {
|
||||
|
||||
private final PhysicalTag parent;
|
||||
|
||||
public EditHandle(PhysicalTag parent) {
|
||||
this.setVisible(false);
|
||||
|
||||
//Hide when the tag is not selected.
|
||||
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> this.setVisible(false));
|
||||
this.addEventHandler(ImageTagControls.FOCUSED, event -> this.setVisible(true));
|
||||
|
||||
this.setRadius(parent.getStrokeWidth());
|
||||
this.setFill(parent.getStroke());
|
||||
|
||||
this.setOnDragDetected(event -> {
|
||||
this.getParent().setCursor(Cursor.CLOSED_HAND);
|
||||
});
|
||||
|
||||
this.setOnMouseReleased(event -> {
|
||||
this.getParent().setCursor(Cursor.DEFAULT);
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this, "Tag Edit", null, parent.getState()));
|
||||
});
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the positioning of this edit handle on the physical tag.
|
||||
*
|
||||
* @param vals
|
||||
* @return
|
||||
*/
|
||||
public EditHandle setPosition(Position... vals) {
|
||||
for (Position pos : vals) {
|
||||
parent.widthProperty().addListener((obs, oldVal, newVal) -> pos.set(parent, this));
|
||||
parent.heightProperty().addListener((obs, oldVal, newVal) -> pos.set(parent, this));
|
||||
pos.set(parent, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the drag capabilities for manipulating the physical tag.
|
||||
*
|
||||
* @param bounds
|
||||
* @param vals
|
||||
* @return
|
||||
*/
|
||||
public EditHandle setDrag(Boundary bounds, Draggable... vals) {
|
||||
this.setOnMouseDragged((event) -> {
|
||||
for (Draggable drag : vals) {
|
||||
drag.perform(parent, event, bounds);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Position strategies for "sticking" to a location on the physical tag when
|
||||
* it is resized.
|
||||
*/
|
||||
static interface Position {
|
||||
|
||||
void set(PhysicalTag parent, Circle knob);
|
||||
|
||||
static Position left() {
|
||||
return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty());
|
||||
}
|
||||
|
||||
static Position right() {
|
||||
return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth()));
|
||||
}
|
||||
|
||||
static Position top() {
|
||||
return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty());
|
||||
}
|
||||
|
||||
static Position bottom() {
|
||||
return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight()));
|
||||
}
|
||||
|
||||
static Position xMiddle() {
|
||||
return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth() / 2));
|
||||
}
|
||||
|
||||
static Position yMiddle() {
|
||||
return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight() / 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the bounding box for which dragging is allowable.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
static interface Boundary {
|
||||
|
||||
boolean isPointInBounds(double x, double y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag strategies for manipulating the physical tag from a given side of
|
||||
* the rectangle.
|
||||
*/
|
||||
static interface Draggable {
|
||||
|
||||
void perform(PhysicalTag parent, MouseEvent event, Boundary b);
|
||||
|
||||
static Draggable bottom() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaY = event.getY() - parent.getY();
|
||||
if (deltaY > 0) {
|
||||
parent.setHeight(deltaY);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Draggable top() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaY = parent.getY() + parent.getHeight() - event.getY();
|
||||
if (deltaY < parent.getY() + parent.getHeight() && deltaY > 0) {
|
||||
parent.setHeight(deltaY);
|
||||
parent.setY(event.getY());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Draggable left() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaX = parent.getX() + parent.getWidth() - event.getX();
|
||||
if (deltaX < parent.getX() + parent.getWidth() && deltaX > 0) {
|
||||
parent.setWidth(deltaX);
|
||||
parent.setX(event.getX());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Draggable right() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaX = event.getX() - parent.getX();
|
||||
if (deltaX > 0) {
|
||||
parent.setWidth(deltaX);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.contentviewers.imagetagging;
|
||||
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventType;
|
||||
|
||||
/**
|
||||
* Focus events for ImageTags to consume. These events trigger selection behavior
|
||||
* on ImageTags and are originated from the ImageTagsGroup class.
|
||||
*/
|
||||
public class ImageTagControls {
|
||||
public static final EventType<Event> NOT_FOCUSED = new EventType<>("NOT_FOCUSED");
|
||||
public static final EventType<Event> FOCUSED = new EventType<>("FOCUSED");
|
||||
}
|
180
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagCreator.java
Executable file
180
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagCreator.java
Executable file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.contentviewers.imagetagging;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
|
||||
/**
|
||||
* Creates image tags. This class attaches itself to a source image, waiting
|
||||
* for mouse press, mouse drag, and mouse release events. Upon a mouse release
|
||||
* event, any listeners are updated with the portable description of the new tag
|
||||
* boundaries (ImageTagRegion).
|
||||
*/
|
||||
public final class ImageTagCreator extends Rectangle {
|
||||
|
||||
//Origin of the drag event.
|
||||
private double rectangleOriginX, rectangleOriginY;
|
||||
|
||||
//Rectangle lines should be 1.5% of the image. This level of thickness has
|
||||
//a good balance between visual acuity and loss of selection at the borders
|
||||
//of the image.
|
||||
private final static double LINE_THICKNESS_PERCENT = 1.5;
|
||||
private final double minArea;
|
||||
|
||||
//Used to update listeners of the new tag boundaries
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
private final EventHandler<MouseEvent> mousePressed;
|
||||
private final EventHandler<MouseEvent> mouseDragged;
|
||||
private final EventHandler<MouseEvent> mouseReleased;
|
||||
|
||||
//Handles the unregistering this ImageTagCreator from mouse press, mouse drag,
|
||||
//and mouse release events of the source image.
|
||||
private final Runnable disconnectRunnable;
|
||||
|
||||
/**
|
||||
* Adds tagging support to an image, where the 'tag' rectangle will be the
|
||||
* specified color.
|
||||
*
|
||||
* @param image Image to tag
|
||||
*/
|
||||
public ImageTagCreator(ImageView image) {
|
||||
setStroke(Color.RED);
|
||||
setFill(Color.RED.deriveColor(0, 0, 0, 0));
|
||||
|
||||
//Calculate how many pixels the stroke width should be to guarentee
|
||||
//a consistent % of image consumed by the rectangle border.
|
||||
double min = Math.min(image.getImage().getWidth(), image.getImage().getHeight());
|
||||
double lineThicknessPixels = min * LINE_THICKNESS_PERCENT / 100.0;
|
||||
setStrokeWidth(lineThicknessPixels);
|
||||
minArea = lineThicknessPixels * lineThicknessPixels;
|
||||
setVisible(false);
|
||||
|
||||
this.mousePressed = (MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Reset box on new click.
|
||||
defaultSettings();
|
||||
rectangleOriginX = event.getX();
|
||||
rectangleOriginY = event.getY();
|
||||
|
||||
setX(rectangleOriginX);
|
||||
setY(rectangleOriginY);
|
||||
};
|
||||
|
||||
image.addEventHandler(MouseEvent.MOUSE_PRESSED, this.mousePressed);
|
||||
|
||||
this.mouseDragged = (MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double currentX = event.getX(), currentY = event.getY();
|
||||
|
||||
/**
|
||||
* Ensure the rectangle is contained within image boundaries and
|
||||
* that the line thickness is kept within bounds.
|
||||
*/
|
||||
double newX = Math.min(Math.max(currentX, image.getX())
|
||||
+ lineThicknessPixels / 2, image.getImage().getWidth() - lineThicknessPixels / 2);
|
||||
double newY = Math.min(Math.max(currentY, image.getY())
|
||||
+ lineThicknessPixels / 2, image.getImage().getHeight() - lineThicknessPixels / 2);
|
||||
|
||||
setVisible(true);
|
||||
double offsetX = newX - rectangleOriginX;
|
||||
if (offsetX < 0) {
|
||||
setX(newX);
|
||||
}
|
||||
setWidth(Math.abs(offsetX));
|
||||
|
||||
double offsetY = newY - rectangleOriginY;
|
||||
if (offsetY < 0) {
|
||||
setY(newY);
|
||||
}
|
||||
setHeight(Math.abs(offsetY));
|
||||
};
|
||||
|
||||
image.addEventHandler(MouseEvent.MOUSE_DRAGGED, this.mouseDragged);
|
||||
|
||||
this.mouseReleased = event -> {
|
||||
//Reject any drags that are too small to count as a meaningful tag.
|
||||
//Meaningful is described as having an area that is visible that is
|
||||
//not consumed by the thickness of the stroke.
|
||||
if ((this.getWidth() - this.getStrokeWidth())
|
||||
* (this.getHeight() - this.getStrokeWidth()) <= minArea) {
|
||||
defaultSettings();
|
||||
return;
|
||||
}
|
||||
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, "New Tag",
|
||||
null, new ImageTagRegion()
|
||||
.setX(this.getX())
|
||||
.setY(this.getY())
|
||||
.setWidth(this.getWidth())
|
||||
.setHeight(this.getHeight())
|
||||
.setStrokeThickness(lineThicknessPixels)));
|
||||
};
|
||||
|
||||
image.addEventHandler(MouseEvent.MOUSE_RELEASED, this.mouseReleased);
|
||||
|
||||
//Used to remove itself from mouse events on the source image
|
||||
disconnectRunnable = () -> {
|
||||
defaultSettings();
|
||||
image.removeEventHandler(MouseEvent.MOUSE_RELEASED, mouseReleased);
|
||||
image.removeEventHandler(MouseEvent.MOUSE_DRAGGED, mouseDragged);
|
||||
image.removeEventHandler(MouseEvent.MOUSE_PRESSED, mousePressed);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a PCL for new tag events. Listeners are updated with a portable
|
||||
* description (ImageTagRegion) of the new tag, which represent the
|
||||
* rectangle boundaries.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void addNewTagListener(PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes itself from mouse events on the source image.
|
||||
*/
|
||||
public void disconnect() {
|
||||
this.disconnectRunnable.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the rectangle to default dimensions.
|
||||
*/
|
||||
private void defaultSettings() {
|
||||
setWidth(0);
|
||||
setHeight(0);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.contentviewers.imagetagging;
|
||||
|
||||
/**
|
||||
* Bean representation of an image tag. This class is used for storage and
|
||||
* retrieval of ImageTags from the case database.
|
||||
*/
|
||||
public class ImageTagRegion {
|
||||
|
||||
/**
|
||||
* These fields will be serialized and stored in the case database by the
|
||||
* ContentViewerTagManager.
|
||||
*/
|
||||
private double x;
|
||||
private double y;
|
||||
private double width;
|
||||
private double height;
|
||||
|
||||
private double strokeThickness;
|
||||
|
||||
public ImageTagRegion setStrokeThickness(double thickness) {
|
||||
this.strokeThickness = thickness;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setX(double x) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setWidth(double width) {
|
||||
this.width = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setY(double y) {
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setHeight(double height) {
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public double getStrokeThickness() {
|
||||
return strokeThickness;
|
||||
}
|
||||
}
|
134
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsGroup.java
Executable file
134
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsGroup.java
Executable file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.contentviewers.imagetagging;
|
||||
|
||||
import com.sun.javafx.event.EventDispatchChainImpl;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javafx.event.Event;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
|
||||
/**
|
||||
* Manages the focus and z-ordering of ImageTags. Only one image tag may be
|
||||
* selected at a time. Image tags show their 8 edit "handles" upon selection
|
||||
* (see ImageTag class for more details) and get the highest z-ordering to make
|
||||
* editing easier. This class is responsible for setting and dropping focus as
|
||||
* the user navigates from tag to tag. The ImageTag is treated as a logical
|
||||
* unit, however it's underlying representation consists of the physical
|
||||
* rectangle and the 8 edit handles. JavaFX will report selection on the Node
|
||||
* level (so either the Rectangle, or a singe edit handle), which makes keeping
|
||||
* the entire image tag in focus a non-trivial problem.
|
||||
*/
|
||||
public final class ImageTagsGroup extends Group {
|
||||
|
||||
private final EventDispatchChainImpl NO_OP_CHAIN = new EventDispatchChainImpl();
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
private volatile ImageTag currentFocus;
|
||||
|
||||
public ImageTagsGroup(Node backDrop) {
|
||||
|
||||
//Reset focus of current selection if the back drop has focus.
|
||||
backDrop.setOnMousePressed((mouseEvent) -> {
|
||||
if (currentFocus != null) {
|
||||
currentFocus.getEventDispatcher().dispatchEvent(
|
||||
new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
|
||||
}
|
||||
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
ImageTagControls.NOT_FOCUSED.getName(), currentFocus, null));
|
||||
currentFocus = null;
|
||||
});
|
||||
|
||||
//Set the focus of selected tag
|
||||
this.addEventFilter(MouseEvent.MOUSE_PRESSED, (MouseEvent e) -> {
|
||||
if (!e.isPrimaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Pull out the logical image tag that this node is associated with
|
||||
Node topLevelChild = e.getPickResult().getIntersectedNode();
|
||||
while (!this.getChildren().contains(topLevelChild)) {
|
||||
topLevelChild = topLevelChild.getParent();
|
||||
}
|
||||
|
||||
requestFocus((ImageTag) topLevelChild);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to focus change events on Image tags.
|
||||
*
|
||||
* @param fcl PCL to be notified which Image tag has been selected.
|
||||
*/
|
||||
public void addFocusChangeListener(PropertyChangeListener fcl) {
|
||||
this.pcs.addPropertyChangeListener(fcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image tag that current has focus.
|
||||
*
|
||||
* @return ImageTag instance or null if no tag is in focus.
|
||||
*/
|
||||
public ImageTag getFocus() {
|
||||
return currentFocus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current focus
|
||||
*/
|
||||
public void clearFocus() {
|
||||
if(currentFocus != null) {
|
||||
resetFocus(currentFocus);
|
||||
currentFocus = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the logical image tag that it is no longer in focus.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
private void resetFocus(ImageTag n) {
|
||||
n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, ImageTagControls.NOT_FOCUSED.getName(), n, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the logical image that it is in focus.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
private void requestFocus(ImageTag n) {
|
||||
if (n.equals(currentFocus)) {
|
||||
return;
|
||||
} else if (currentFocus != null && !currentFocus.equals(n)) {
|
||||
resetFocus(currentFocus);
|
||||
}
|
||||
|
||||
n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.FOCUSED), NO_OP_CHAIN);
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, ImageTagControls.FOCUSED.getName(), currentFocus, n));
|
||||
|
||||
currentFocus = n;
|
||||
n.toFront();
|
||||
}
|
||||
}
|
141
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsUtility.java
Executable file
141
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsUtility.java
Executable file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.contentviewers.imagetagging;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.core.MatOfInt;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Utility class for handling content viewer tags on images.
|
||||
*/
|
||||
public final class ImageTagsUtility {
|
||||
|
||||
/**
|
||||
* Sizes for thumbnails
|
||||
*/
|
||||
public enum IconSize {
|
||||
SMALL(50),
|
||||
MEDIUM(100),
|
||||
LARGE(200);
|
||||
|
||||
private final int SIZE;
|
||||
|
||||
IconSize(int size) {
|
||||
this.SIZE = size;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds the tag regions into an image.
|
||||
*
|
||||
* @param file Base Image
|
||||
* @param tagRegions Tag regions to be saved into the image
|
||||
* @param outputEncoding Format of image (jpg, png, etc). See OpenCV for
|
||||
* supported formats. Do not include a "."
|
||||
* @return Output image as a BufferedImage
|
||||
*
|
||||
* @throws TskCoreException Cannot read from abstract file
|
||||
* @throws IOException Could not create buffered image from OpenCV result
|
||||
*/
|
||||
public static BufferedImage writeTags(AbstractFile file, Collection<ImageTagRegion> tagRegions,
|
||||
String outputEncoding) throws TskCoreException, IOException {
|
||||
byte[] imageInMemory = new byte[(int) file.getSize()];
|
||||
file.read(imageInMemory, 0, file.getSize());
|
||||
Mat originalImage = Highgui.imdecode(new MatOfByte(imageInMemory), Highgui.IMREAD_UNCHANGED);
|
||||
|
||||
tagRegions.forEach((region) -> {
|
||||
Core.rectangle(
|
||||
originalImage, //Matrix obj of the image
|
||||
new Point(region.getX(), region.getY()), //p1
|
||||
new Point(region.getX() + region.getWidth(), region.getY() + region.getHeight()), //p2
|
||||
new Scalar(0, 0, 255), //Scalar object for color
|
||||
(int) Math.rint(region.getStrokeThickness())
|
||||
);
|
||||
});
|
||||
|
||||
MatOfByte matOfByte = new MatOfByte();
|
||||
MatOfInt params = new MatOfInt(Highgui.IMWRITE_JPEG_QUALITY, 100);
|
||||
Highgui.imencode("." + outputEncoding, originalImage, matOfByte, params);
|
||||
|
||||
try (ByteArrayInputStream imageStream = new ByteArrayInputStream(matOfByte.toArray())) {
|
||||
BufferedImage result = ImageIO.read(imageStream);
|
||||
originalImage.release();
|
||||
matOfByte.release();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thumbnail version of the image with tags applied.
|
||||
*
|
||||
* @param file Input file to apply tags & produce thumbnail from
|
||||
* @param tagRegions Tags to apply
|
||||
* @param iconSize Size of the output thumbnail
|
||||
* @param outputEncoding Format of thumbnail (jpg, png, etc). See OpenCV for
|
||||
* supported formats. Do not include a "."
|
||||
* @return BufferedImage representing the thumbnail
|
||||
*
|
||||
* @throws TskCoreException Could not read from file
|
||||
* @throws IOException Could not create buffered image from OpenCV result
|
||||
*/
|
||||
public static BufferedImage makeThumbnail(AbstractFile file, Collection<ImageTagRegion> tagRegions,
|
||||
IconSize iconSize, String outputEncoding) throws TskCoreException, IOException {
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
BufferedImage result = writeTags(file, tagRegions, outputEncoding);
|
||||
ImageIO.write(result, outputEncoding, baos);
|
||||
Mat markedUpImage = Highgui.imdecode(new MatOfByte(baos.toByteArray()), Highgui.IMREAD_UNCHANGED);
|
||||
Mat thumbnail = new Mat();
|
||||
Size resize = new Size(iconSize.getSize(), iconSize.getSize());
|
||||
|
||||
Imgproc.resize(markedUpImage, thumbnail, resize);
|
||||
MatOfByte matOfByte = new MatOfByte();
|
||||
Highgui.imencode("." + outputEncoding, thumbnail, matOfByte);
|
||||
|
||||
try (ByteArrayInputStream thumbnailStream = new ByteArrayInputStream(matOfByte.toArray())) {
|
||||
BufferedImage thumbnailImage = ImageIO.read(thumbnailStream);
|
||||
thumbnail.release();
|
||||
matOfByte.release();
|
||||
markedUpImage.release();
|
||||
return thumbnailImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ImageTagsUtility() {
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* A DataContentViewer that displays text with the TextViewers available.
|
||||
@ -90,6 +91,17 @@ public class TextContentViewer implements DataContentViewer {
|
||||
if (node == null) {
|
||||
return false;
|
||||
}
|
||||
// get the node's File, if it has one
|
||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// disable the text content viewer for directories and empty files
|
||||
if (file.isDir() || file.getSize() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return panel.isSupported(node);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class TextContentViewerPanel extends javax.swing.JPanel implements DataCo
|
||||
}
|
||||
|
||||
/**
|
||||
* Deterime wether the content viewer which displays this panel isSupported.
|
||||
* Determine whether the content viewer which displays this panel isSupported.
|
||||
* This panel is supported if any of the TextViewer's displayed in it are
|
||||
* supported.
|
||||
*
|
||||
|
@ -217,3 +217,4 @@ DataResultViewerTable.pageNumLabel.text=
|
||||
DataResultViewerTable.pageLabel.text=Page:
|
||||
ViewPreferencesPanel.maxResultsLabel.text=Maximum number of Results to show in table:
|
||||
ViewPreferencesPanel.maxResultsLabel.toolTipText=<html>\nSetting this value to 0 will display all results in the results table.\n<br>Note that setting this value to 0 may result in poor UI responsiveness when there are large numbers of results.\n</html>
|
||||
DataResultViewerTable.exportCSVButton.text=Save table as CSV
|
||||
|
@ -32,6 +32,7 @@ DataResultViewerTable.commentRenderer.noComment.toolTip=No comments found
|
||||
DataResultViewerTable.commentRenderer.tagComment.toolTip=Comment exists on associated tag(s)
|
||||
DataResultViewerTable.countRender.name=O
|
||||
DataResultViewerTable.countRender.toolTip=O(ccurrences) indicates the number of data sources containing the item in the Central Repository
|
||||
DataResultViewerTable.exportCSVButtonActionPerformed.empty=No data to export
|
||||
DataResultViewerTable.firstColLbl=Name
|
||||
DataResultViewerTable.goToPageTextField.err=Invalid page number
|
||||
# {0} - totalPages
|
||||
@ -270,3 +271,4 @@ DataResultViewerTable.pageNumLabel.text=
|
||||
DataResultViewerTable.pageLabel.text=Page:
|
||||
ViewPreferencesPanel.maxResultsLabel.text=Maximum number of Results to show in table:
|
||||
ViewPreferencesPanel.maxResultsLabel.toolTipText=<html>\nSetting this value to 0 will display all results in the results table.\n<br>Note that setting this value to 0 may result in poor UI responsiveness when there are large numbers of results.\n</html>
|
||||
DataResultViewerTable.exportCSVButton.text=Save table as CSV
|
||||
|
@ -16,13 +16,13 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="outlineView" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace pref="608" max="32767" attributes="0"/>
|
||||
<Component id="outlineView" pref="904" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pageNumLabel" min="-2" pref="53" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
<Component id="pagesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="pagePrevButton" linkSize="1" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
@ -32,14 +32,15 @@
|
||||
<Component id="gotoPageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="gotoPageTextField" min="-2" pref="33" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="exportCSVButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="2" attributes="0">
|
||||
<Component id="pageLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pageNumLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
@ -48,9 +49,10 @@
|
||||
<Component id="pageNextButton" linkSize="2" alignment="2" min="-2" pref="15" max="-2" attributes="0"/>
|
||||
<Component id="gotoPageLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="gotoPageTextField" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exportCSVButton" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="outlineView" pref="324" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
<Component id="outlineView" pref="321" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -164,5 +166,15 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="gotoPageTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="exportCSVButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerTable.exportCSVButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="exportCSVButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -77,6 +77,7 @@ import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
|
||||
@ -176,6 +177,13 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
initComponents();
|
||||
|
||||
initializePagingSupport();
|
||||
|
||||
/*
|
||||
* Disable the CSV export button for the common properties results
|
||||
*/
|
||||
if (this instanceof org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributesSearchResultsViewerTable) {
|
||||
exportCSVButton.setEnabled(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the child OutlineView (explorer view) component.
|
||||
@ -293,20 +301,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
/*
|
||||
* If the given node is not null and has children, set it as the
|
||||
* root context of the child OutlineView, otherwise make an
|
||||
* "empty"node the root context.
|
||||
*
|
||||
* IMPORTANT NOTE: This is the first of many times where a
|
||||
* getChildren call on the current root node causes all of the
|
||||
* children of the root node to be created and defeats lazy child
|
||||
* node creation, if it is enabled. It also likely leads to many
|
||||
* case database round trips.
|
||||
*/
|
||||
if (rootNode != null && rootNode.getChildren().getNodesCount() > 0) {
|
||||
this.rootNode = rootNode;
|
||||
|
||||
if (rootNode != null) {
|
||||
/**
|
||||
* Check to see if we have previously created a paging support
|
||||
* class for this node.
|
||||
@ -355,6 +350,21 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
// No-op
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* If the given node is not null and has children, set it as the
|
||||
* root context of the child OutlineView, otherwise make an
|
||||
* "empty"node the root context.
|
||||
*
|
||||
* IMPORTANT NOTE: This is the first of many times where a
|
||||
* getChildren call on the current root node causes all of the
|
||||
* children of the root node to be created and defeats lazy child
|
||||
* node creation, if it is enabled. It also likely leads to many
|
||||
* case database round trips.
|
||||
*/
|
||||
if (rootNode != null && rootNode.getChildren().getNodesCount() > 0) {
|
||||
this.rootNode = rootNode;
|
||||
|
||||
this.getExplorerManager().setRootContext(this.rootNode);
|
||||
setupTable();
|
||||
@ -1291,6 +1301,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
outlineView = new OutlineView(DataResultViewerTable.FIRST_COLUMN_LABEL);
|
||||
gotoPageLabel = new javax.swing.JLabel();
|
||||
gotoPageTextField = new javax.swing.JTextField();
|
||||
exportCSVButton = new javax.swing.JButton();
|
||||
|
||||
pageLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.pageLabel.text")); // NOI18N
|
||||
|
||||
@ -1338,17 +1349,24 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
}
|
||||
});
|
||||
|
||||
exportCSVButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.exportCSVButton.text")); // NOI18N
|
||||
exportCSVButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
exportCSVButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap(608, Short.MAX_VALUE)
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 904, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(pageLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pageNumLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGap(14, 14, 14)
|
||||
.addComponent(pagesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
@ -1358,7 +1376,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
.addComponent(gotoPageLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(gotoPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(exportCSVButton))
|
||||
);
|
||||
|
||||
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {pageNextButton, pagePrevButton});
|
||||
@ -1366,7 +1385,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGap(3, 3, 3)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
|
||||
.addComponent(pageLabel)
|
||||
.addComponent(pageNumLabel)
|
||||
@ -1374,9 +1393,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
.addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(gotoPageLabel)
|
||||
.addComponent(gotoPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 324, Short.MAX_VALUE)
|
||||
.addComponent(gotoPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(exportCSVButton))
|
||||
.addGap(3, 3, 3)
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -1397,7 +1417,19 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
pagingSupport.gotoPage();
|
||||
}//GEN-LAST:event_gotoPageTextFieldActionPerformed
|
||||
|
||||
@NbBundle.Messages({"DataResultViewerTable.exportCSVButtonActionPerformed.empty=No data to export"
|
||||
})
|
||||
private void exportCSVButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportCSVButtonActionPerformed
|
||||
Node currentRoot = this.getExplorerManager().getRootContext();
|
||||
if (currentRoot != null && currentRoot.getChildren().getNodesCount() > 0) {
|
||||
org.sleuthkit.autopsy.directorytree.ExportCSVAction.saveNodesToCSV(java.util.Arrays.asList(currentRoot.getChildren().getNodes()), this);
|
||||
} else {
|
||||
MessageNotifyUtil.Message.info(Bundle.DataResultViewerTable_exportCSVButtonActionPerformed_empty());
|
||||
}
|
||||
}//GEN-LAST:event_exportCSVButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton exportCSVButton;
|
||||
private javax.swing.JLabel gotoPageLabel;
|
||||
private javax.swing.JTextField gotoPageTextField;
|
||||
private org.openide.explorer.view.OutlineView outlineView;
|
||||
|
@ -11,217 +11,278 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-119,0,0,4,73"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="iconView" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="pageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pageNumLabel" min="-2" pref="95" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pagesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pagePrevButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="pageNextButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="goToPageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="goToPageField" min="-2" pref="54" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="imagesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="imagesRangeLabel" min="-2" pref="91" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="thumbnailSizeComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="30" max="-2" attributes="0"/>
|
||||
<Component id="sortButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="sortLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="filePathLabel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="2" attributes="0">
|
||||
<Component id="pageLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pageNumLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pagesLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pagePrevButton" alignment="2" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<Component id="pageNextButton" alignment="2" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<Component id="goToPageLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="goToPageField" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="imagesLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="imagesRangeLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="thumbnailSizeComboBox" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="sortButton" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="sortLabel" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
|
||||
<Component id="iconView" pref="322" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="filePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="pageLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="pagesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="pagePrevButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pagePrevButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 0, 2, 0]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[55, 23]"/>
|
||||
</Property>
|
||||
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pagePrevButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="pageNextButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pageNextButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[2, 0, 2, 0]"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 23]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 23]"/>
|
||||
</Property>
|
||||
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pageNextButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="imagesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.imagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="imagesRangeLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.imagesRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="pageNumLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pageNumLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="buttonBarPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||
<BorderConstraints direction="North"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
|
||||
<Property name="alignment" type="int" value="0"/>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="pagesPanel">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="pageNumberPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="pageLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="23" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="pageNumLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pageNumLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="15" anchor="23" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="pageButtonPanel">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="pagesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="17" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="pagePrevButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pagePrevButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pagePrevButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="2" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="pageNextButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.pageNextButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="disabledIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 23]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 23]"/>
|
||||
</Property>
|
||||
<Property name="rolloverIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pageNextButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="2" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="15" anchor="23" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="pageGotoPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="goToPageLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.goToPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="17" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="goToPageField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.goToPageField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageFieldActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="2" fill="0" ipadX="75" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="15" anchor="23" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="imagePane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="imagesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.imagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="imagesRangeLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.imagesRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="15" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JComboBox" name="thumbnailSizeComboBox">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="thumbnailSizeComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox<>()"/>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="sortPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="sortLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.sortLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="sortButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.sortButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="sortButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="0" insetsRight="9" anchor="23" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="filePathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.filePathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="goToPageLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.goToPageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="goToPageField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.goToPageField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="goToPageFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="thumbnailSizeComboBox">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="thumbnailSizeComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JComboBox<>()"/>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||
<BorderConstraints direction="South"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.openide.explorer.view.IconView" name="iconView">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="sortButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.sortButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="sortButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="sortLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultViewerThumbnail.sortLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||
<BorderConstraints direction="Center"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -122,6 +122,11 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
currentPage = -1;
|
||||
totalPages = 0;
|
||||
currentPageImages = 0;
|
||||
|
||||
// The GUI builder is using FlowLayout therefore this change so have no
|
||||
// impact on the initally designed layout. This change will just effect
|
||||
// how the components are laid out as size of the window changes.
|
||||
buttonBarPanel.setLayout(new WrapLayout(java.awt.FlowLayout.LEFT));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,33 +137,84 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
buttonBarPanel = new javax.swing.JPanel();
|
||||
pagesPanel = new javax.swing.JPanel();
|
||||
pageNumberPane = new javax.swing.JPanel();
|
||||
pageLabel = new javax.swing.JLabel();
|
||||
pageNumLabel = new javax.swing.JLabel();
|
||||
pageButtonPanel = new javax.swing.JPanel();
|
||||
pagesLabel = new javax.swing.JLabel();
|
||||
pagePrevButton = new javax.swing.JButton();
|
||||
pageNextButton = new javax.swing.JButton();
|
||||
imagesLabel = new javax.swing.JLabel();
|
||||
imagesRangeLabel = new javax.swing.JLabel();
|
||||
pageNumLabel = new javax.swing.JLabel();
|
||||
filePathLabel = new javax.swing.JLabel();
|
||||
pageGotoPane = new javax.swing.JPanel();
|
||||
goToPageLabel = new javax.swing.JLabel();
|
||||
goToPageField = new javax.swing.JTextField();
|
||||
imagePane = new javax.swing.JPanel();
|
||||
imagesLabel = new javax.swing.JLabel();
|
||||
imagesRangeLabel = new javax.swing.JLabel();
|
||||
thumbnailSizeComboBox = new javax.swing.JComboBox<>();
|
||||
iconView = new org.openide.explorer.view.IconView();
|
||||
sortButton = new javax.swing.JButton();
|
||||
sortPane = new javax.swing.JPanel();
|
||||
sortLabel = new javax.swing.JLabel();
|
||||
sortButton = new javax.swing.JButton();
|
||||
filePathLabel = new javax.swing.JLabel();
|
||||
iconView = new org.openide.explorer.view.IconView();
|
||||
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
|
||||
buttonBarPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
|
||||
|
||||
pagesPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
pageNumberPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
pageLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 9);
|
||||
pageNumberPane.add(pageLabel, gridBagConstraints);
|
||||
|
||||
pageNumLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageNumLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
|
||||
pageNumberPane.add(pageNumLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
pagesPanel.add(pageNumberPane, gridBagConstraints);
|
||||
|
||||
buttonBarPanel.add(pagesPanel);
|
||||
|
||||
pageButtonPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
pagesLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pagesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 9);
|
||||
pageButtonPanel.add(pagesLabel, gridBagConstraints);
|
||||
|
||||
pagePrevButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N
|
||||
pagePrevButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pagePrevButton.text")); // NOI18N
|
||||
pagePrevButton.setBorder(null);
|
||||
pagePrevButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N
|
||||
pagePrevButton.setFocusable(false);
|
||||
pagePrevButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
pagePrevButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
|
||||
pagePrevButton.setPreferredSize(new java.awt.Dimension(55, 23));
|
||||
pagePrevButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
pagePrevButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png"))); // NOI18N
|
||||
pagePrevButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
pagePrevButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -166,13 +222,20 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
pagePrevButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridheight = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
pageButtonPanel.add(pagePrevButton, gridBagConstraints);
|
||||
|
||||
pageNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N
|
||||
pageNextButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageNextButton.text")); // NOI18N
|
||||
pageNextButton.setBorder(null);
|
||||
pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N
|
||||
pageNextButton.setFocusable(false);
|
||||
pageNextButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
|
||||
pageNextButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
pageNextButton.setMaximumSize(new java.awt.Dimension(27, 23));
|
||||
pageNextButton.setMinimumSize(new java.awt.Dimension(27, 23));
|
||||
pageNextButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png"))); // NOI18N
|
||||
@ -182,16 +245,27 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
pageNextButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridheight = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
|
||||
pageButtonPanel.add(pageNextButton, gridBagConstraints);
|
||||
|
||||
imagesLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.imagesLabel.text")); // NOI18N
|
||||
buttonBarPanel.add(pageButtonPanel);
|
||||
|
||||
imagesRangeLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.imagesRangeLabel.text")); // NOI18N
|
||||
|
||||
pageNumLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.pageNumLabel.text")); // NOI18N
|
||||
|
||||
filePathLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.filePathLabel.text")); // NOI18N
|
||||
pageGotoPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
goToPageLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.goToPageLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 9);
|
||||
pageGotoPane.add(goToPageLabel, gridBagConstraints);
|
||||
|
||||
goToPageField.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.goToPageField.text")); // NOI18N
|
||||
goToPageField.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -199,12 +273,49 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
goToPageFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridheight = 2;
|
||||
gridBagConstraints.ipadx = 75;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
|
||||
pageGotoPane.add(goToPageField, gridBagConstraints);
|
||||
|
||||
buttonBarPanel.add(pageGotoPane);
|
||||
|
||||
imagePane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
imagesLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.imagesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 9);
|
||||
imagePane.add(imagesLabel, gridBagConstraints);
|
||||
|
||||
imagesRangeLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.imagesRangeLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
|
||||
imagePane.add(imagesRangeLabel, gridBagConstraints);
|
||||
|
||||
buttonBarPanel.add(imagePane);
|
||||
|
||||
thumbnailSizeComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
thumbnailSizeComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
buttonBarPanel.add(thumbnailSizeComboBox);
|
||||
|
||||
sortPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
sortLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.sortLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
sortPane.add(sortLabel, gridBagConstraints);
|
||||
|
||||
sortButton.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.sortButton.text")); // NOI18N
|
||||
sortButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -212,65 +323,20 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
sortButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 9);
|
||||
sortPane.add(sortButton, gridBagConstraints);
|
||||
|
||||
sortLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.sortLabel.text")); // NOI18N
|
||||
buttonBarPanel.add(sortPane);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(pageLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pageNumLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(pagesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(goToPageLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(12, 12, 12)
|
||||
.addComponent(imagesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(30, 30, 30)
|
||||
.addComponent(sortButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(sortLabel))
|
||||
.addComponent(filePathLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
|
||||
.addComponent(pageLabel)
|
||||
.addComponent(pageNumLabel)
|
||||
.addComponent(pagesLabel)
|
||||
.addComponent(pagePrevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(goToPageLabel)
|
||||
.addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(imagesLabel)
|
||||
.addComponent(imagesRangeLabel)
|
||||
.addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(sortButton)
|
||||
.addComponent(sortLabel))
|
||||
.addGap(13, 13, 13)
|
||||
.addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, 322, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(filePathLabel))
|
||||
);
|
||||
add(buttonBarPanel, java.awt.BorderLayout.NORTH);
|
||||
|
||||
filePathLabel.setText(org.openide.util.NbBundle.getMessage(DataResultViewerThumbnail.class, "DataResultViewerThumbnail.filePathLabel.text")); // NOI18N
|
||||
add(filePathLabel, java.awt.BorderLayout.SOUTH);
|
||||
add(iconView, java.awt.BorderLayout.CENTER);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void pagePrevButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pagePrevButtonActionPerformed
|
||||
@ -355,19 +421,26 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JPanel buttonBarPanel;
|
||||
private javax.swing.JLabel filePathLabel;
|
||||
private javax.swing.JTextField goToPageField;
|
||||
private javax.swing.JLabel goToPageLabel;
|
||||
private org.openide.explorer.view.IconView iconView;
|
||||
private javax.swing.JPanel imagePane;
|
||||
private javax.swing.JLabel imagesLabel;
|
||||
private javax.swing.JLabel imagesRangeLabel;
|
||||
private javax.swing.JPanel pageButtonPanel;
|
||||
private javax.swing.JPanel pageGotoPane;
|
||||
private javax.swing.JLabel pageLabel;
|
||||
private javax.swing.JButton pageNextButton;
|
||||
private javax.swing.JLabel pageNumLabel;
|
||||
private javax.swing.JPanel pageNumberPane;
|
||||
private javax.swing.JButton pagePrevButton;
|
||||
private javax.swing.JLabel pagesLabel;
|
||||
private javax.swing.JPanel pagesPanel;
|
||||
private javax.swing.JButton sortButton;
|
||||
private javax.swing.JLabel sortLabel;
|
||||
private javax.swing.JPanel sortPane;
|
||||
private javax.swing.JComboBox<String> thumbnailSizeComboBox;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@ -679,5 +752,5 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
@ -55,6 +56,9 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
groupByDataSourceCheckbox.setEnabled(evt.getNewValue() != null);
|
||||
});
|
||||
this.timeZoneList.setListData(TimeZoneUtils.createTimeZoneList().stream().toArray(String[]::new));
|
||||
|
||||
// Disable manual editing of max results spinner
|
||||
((JSpinner.DefaultEditor)maxResultsSpinner.getEditor()).getTextField().setEditable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
203
Core/src/org/sleuthkit/autopsy/corecomponents/WrapLayout.java
Executable file
203
Core/src/org/sleuthkit/autopsy/corecomponents/WrapLayout.java
Executable file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.corecomponents;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* FlowLayout subclass that fully supports wrapping of components.
|
||||
*
|
||||
* Originally written by Rob Camick
|
||||
* https://tips4java.wordpress.com/2008/11/06/wrap-layout/
|
||||
*/
|
||||
class WrapLayout extends FlowLayout {
|
||||
|
||||
/**
|
||||
* Constructs a new <code>WrapLayout</code> with a left alignment and a
|
||||
* default 5-unit horizontal and vertical gap.
|
||||
*/
|
||||
public WrapLayout() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>FlowLayout</code> with the specified alignment
|
||||
* and a default 5-unit horizontal and vertical gap. The value of the
|
||||
* alignment argument must be one of <code>WrapLayout</code>,
|
||||
* <code>WrapLayout</code>, or <code>WrapLayout</code>.
|
||||
*
|
||||
* @param align the alignment value
|
||||
*/
|
||||
public WrapLayout(int align) {
|
||||
super(align);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new flow layout manager with the indicated alignment and
|
||||
* the indicated horizontal and vertical gaps.
|
||||
* <p>
|
||||
* The value of the alignment argument must be one of
|
||||
* <code>WrapLayout</code>, <code>WrapLayout</code>, or
|
||||
* <code>WrapLayout</code>.
|
||||
*
|
||||
* @param align the alignment value
|
||||
* @param hgap the horizontal gap between components
|
||||
* @param vgap the vertical gap between components
|
||||
*/
|
||||
public WrapLayout(int align, int hgap, int vgap) {
|
||||
super(align, hgap, vgap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred dimensions for this layout given the
|
||||
* <i>visible</i> components in the specified target container.
|
||||
*
|
||||
* @param target the component which needs to be laid out
|
||||
*
|
||||
* @return the preferred dimensions to lay out the subcomponents of the
|
||||
* specified container
|
||||
*/
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container target) {
|
||||
return layoutSize(target, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum dimensions needed to layout the <i>visible</i>
|
||||
* components contained in the specified target container.
|
||||
*
|
||||
* @param target the component which needs to be laid out
|
||||
*
|
||||
* @return the minimum dimensions to lay out the subcomponents of the
|
||||
* specified container
|
||||
*/
|
||||
@Override
|
||||
public Dimension minimumLayoutSize(Container target) {
|
||||
Dimension minimum = layoutSize(target, false);
|
||||
minimum.width -= (getHgap() + 1);
|
||||
return minimum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum or preferred dimension needed to layout the
|
||||
* target container.
|
||||
*
|
||||
* @param target target to get layout size for
|
||||
* @param preferred should preferred size be calculated
|
||||
*
|
||||
* @return the dimension to layout the target container
|
||||
*/
|
||||
private Dimension layoutSize(Container target, boolean preferred) {
|
||||
synchronized (target.getTreeLock()) {
|
||||
// Each row must fit with the width allocated to the containter.
|
||||
// When the container width = 0, the preferred width of the container
|
||||
// has not yet been calculated so lets ask for the maximum.
|
||||
|
||||
int targetWidth = target.getSize().width;
|
||||
Container container = target;
|
||||
|
||||
while (container.getSize().width == 0 && container.getParent() != null) {
|
||||
container = container.getParent();
|
||||
}
|
||||
|
||||
targetWidth = container.getSize().width;
|
||||
|
||||
if (targetWidth == 0) {
|
||||
targetWidth = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
int hgap = getHgap();
|
||||
int vgap = getVgap();
|
||||
Insets insets = target.getInsets();
|
||||
int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
|
||||
int maxWidth = targetWidth - horizontalInsetsAndGap;
|
||||
|
||||
// Fit components into the allowed width
|
||||
Dimension dim = new Dimension(0, 0);
|
||||
int rowWidth = 0;
|
||||
int rowHeight = 0;
|
||||
|
||||
int nmembers = target.getComponentCount();
|
||||
|
||||
for (int i = 0; i < nmembers; i++) {
|
||||
Component m = target.getComponent(i);
|
||||
|
||||
if (m.isVisible()) {
|
||||
Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
|
||||
|
||||
// Can't add the component to current row. Start a new row.
|
||||
if (rowWidth + d.width > maxWidth) {
|
||||
addRow(dim, rowWidth, rowHeight);
|
||||
rowWidth = 0;
|
||||
rowHeight = 0;
|
||||
}
|
||||
|
||||
// Add a horizontal gap for all components after the first
|
||||
if (rowWidth != 0) {
|
||||
rowWidth += hgap;
|
||||
}
|
||||
|
||||
rowWidth += d.width;
|
||||
rowHeight = Math.max(rowHeight, d.height);
|
||||
}
|
||||
}
|
||||
|
||||
addRow(dim, rowWidth, rowHeight);
|
||||
|
||||
dim.width += horizontalInsetsAndGap;
|
||||
dim.height += insets.top + insets.bottom + vgap * 2;
|
||||
|
||||
// When using a scroll pane or the DecoratedLookAndFeel we need to
|
||||
// make sure the preferred size is less than the size of the
|
||||
// target containter so shrinking the container size works
|
||||
// correctly. Removing the horizontal gap is an easy way to do this.
|
||||
Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);
|
||||
|
||||
if (scrollPane != null && target.isValid()) {
|
||||
dim.width -= (hgap + 1);
|
||||
}
|
||||
|
||||
return dim;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A new row has been completed. Use the dimensions of this row to
|
||||
* update the preferred size for the container.
|
||||
*
|
||||
* @param dim update the width and height when appropriate @param
|
||||
* rowWidth the width of the row to add @param rowHeight the height of
|
||||
* the row to add
|
||||
*/
|
||||
private void addRow(Dimension dim, int rowWidth, int rowHeight) {
|
||||
dim.width = Math.max(dim.width, rowWidth);
|
||||
|
||||
if (dim.height > 0) {
|
||||
dim.height += getVgap();
|
||||
}
|
||||
|
||||
dim.height += rowHeight;
|
||||
}
|
||||
}
|
@ -221,7 +221,8 @@ public class StringExtract {
|
||||
StringExtractResult resWin = null;
|
||||
if (enableUTF8 && resUTF16 != null) {
|
||||
resWin = runUTF16 && resUTF16.numChars > resUTF8.numChars ? resUTF16 : resUTF8;
|
||||
} else if (enableUTF16) {
|
||||
} else if (runUTF16) {
|
||||
//Only let resUTF16 "win" if it was actually run.
|
||||
resWin = resUTF16;
|
||||
} else if (enableUTF8) {
|
||||
resWin = resUTF8;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
@ -27,8 +26,6 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
@ -65,6 +62,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
@ -76,15 +74,10 @@ import org.sleuthkit.datamodel.TskData;
|
||||
public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
|
||||
@NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
|
||||
private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
|
||||
|
||||
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
|
||||
Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED, Case.Events.CR_COMMENT_CHANGED);
|
||||
|
||||
private static final ExecutorService translationPool;
|
||||
private static final Integer MAX_POOL_SIZE = 10;
|
||||
|
||||
/**
|
||||
* @param abstractFile file to wrap
|
||||
*/
|
||||
@ -101,7 +94,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
}
|
||||
|
||||
if (UserPreferences.displayTranslatedFileNames()) {
|
||||
AbstractAbstractFileNode.translationPool.submit(new TranslationTask(
|
||||
backgroundTasksPool.submit(new TranslationTask(
|
||||
new WeakReference<>(this), weakPcl));
|
||||
}
|
||||
|
||||
@ -110,13 +103,6 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
static {
|
||||
//Initialize this pool only once! This will be used by every instance of AAFN
|
||||
//to do their heavy duty SCO column and translation updates.
|
||||
translationPool = Executors.newFixedThreadPool(MAX_POOL_SIZE,
|
||||
new ThreadFactoryBuilder().setNameFormat("translation-task-thread-%d").build());
|
||||
}
|
||||
|
||||
/**
|
||||
* The finalizer removes event listeners as the BlackboardArtifactNode is
|
||||
* being garbage collected. Yes, we know that finalizers are considered to
|
||||
@ -137,16 +123,6 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event signals to indicate the background tasks have completed processing.
|
||||
* Currently, we have one property task in the background:
|
||||
*
|
||||
* 1) Retreiving the translation of the file name
|
||||
*/
|
||||
enum NodeSpecificEvents {
|
||||
TRANSLATION_AVAILABLE,
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
|
||||
@ -190,7 +166,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
} else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
|
||||
ContentTagAddedEvent event = (ContentTagAddedEvent) evt;
|
||||
if (event.getAddedTag().getContent().equals(content)) {
|
||||
List<ContentTag> tags = getContentTagsFromDatabase();
|
||||
List<Tag> tags = this.getAllTagsFromDatabase();
|
||||
Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
|
||||
Score value = scorePropAndDescr.getLeft();
|
||||
String descr = scorePropAndDescr.getRight();
|
||||
@ -202,7 +178,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
} else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
|
||||
ContentTagDeletedEvent event = (ContentTagDeletedEvent) evt;
|
||||
if (event.getDeletedTagInfo().getContentID() == content.getId()) {
|
||||
List<ContentTag> tags = getContentTagsFromDatabase();
|
||||
List<Tag> tags = getAllTagsFromDatabase();
|
||||
Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
|
||||
Score value = scorePropAndDescr.getLeft();
|
||||
String descr = scorePropAndDescr.getRight();
|
||||
@ -214,7 +190,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
} else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) {
|
||||
CommentChangedEvent event = (CommentChangedEvent) evt;
|
||||
if (event.getContentID() == content.getId()) {
|
||||
List<ContentTag> tags = getContentTagsFromDatabase();
|
||||
List<Tag> tags = getAllTagsFromDatabase();
|
||||
CorrelationAttributeInstance attribute = getCorrelationAttributeInstance();
|
||||
updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)));
|
||||
}
|
||||
@ -223,6 +199,18 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
//Set the tooltip
|
||||
this.setShortDescription(content.getName());
|
||||
updateSheet(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, content.getName()));
|
||||
} else if (eventType.equals(NodeSpecificEvents.SCO_AVAILABLE.toString())) {
|
||||
SCOData scoData = (SCOData) evt.getNewValue();
|
||||
if (scoData.getScoreAndDescription() != null) {
|
||||
updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoData.getScoreAndDescription().getRight(), scoData.getScoreAndDescription().getLeft()));
|
||||
}
|
||||
if (scoData.getComment() != null) {
|
||||
updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, scoData.getComment()));
|
||||
}
|
||||
if (scoData.getCountAndDescription() != null
|
||||
&& !UserPreferences.hideCentralRepoCommentsAndOccurrences()) {
|
||||
updateSheet(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), scoData.getCountAndDescription().getRight(), scoData.getCountAndDescription().getLeft()));
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
@ -235,38 +223,6 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
*/
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
|
||||
|
||||
/**
|
||||
* Updates the values of the properties in the current property sheet with
|
||||
* the new properties being passed in. Only if that property exists in the
|
||||
* current sheet will it be applied. That way, we allow for subclasses to
|
||||
* add their own (or omit some!) properties and we will not accidentally
|
||||
* disrupt their UI.
|
||||
*
|
||||
* Race condition if not synchronized. Only one update should be applied at
|
||||
* a time.
|
||||
*
|
||||
* @param newProps New file property instances to be updated in the current
|
||||
* sheet.
|
||||
*/
|
||||
private synchronized void updateSheet(NodeProperty<?>... newProps) {
|
||||
//Refresh ONLY those properties in the sheet currently. Subclasses may have
|
||||
//only added a subset of our properties or their own props.s
|
||||
Sheet visibleSheet = this.getSheet();
|
||||
Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES);
|
||||
Property<?>[] visibleProps = visibleSheetSet.getProperties();
|
||||
for (NodeProperty<?> newProp : newProps) {
|
||||
for (int i = 0; i < visibleProps.length; i++) {
|
||||
if (visibleProps[i].getName().equals(newProp.getName())) {
|
||||
visibleProps[i] = newProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
visibleSheetSet.put(visibleProps);
|
||||
visibleSheet.put(visibleSheetSet);
|
||||
//setSheet() will notify Netbeans to update this node in the UI.
|
||||
this.setSheet(visibleSheet);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called when the node is first initialized. Any new updates or
|
||||
* changes happen by directly manipulating the sheet. That means we can fire
|
||||
@ -368,18 +324,17 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
properties.add(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, ""));
|
||||
}
|
||||
|
||||
//SCO column prereq info..
|
||||
List<ContentTag> tags = getContentTagsFromDatabase();
|
||||
CorrelationAttributeInstance attribute = getCorrelationAttributeInstance();
|
||||
|
||||
Pair<DataResultViewerTable.Score, String> scoreAndDescription = getScorePropertyAndDescription(tags);
|
||||
properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoreAndDescription.getRight(), scoreAndDescription.getLeft()));
|
||||
DataResultViewerTable.HasCommentStatus comment = getCommentProperty(tags, attribute);
|
||||
properties.add(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, comment));
|
||||
if (!UserPreferences.hideCentralRepoCommentsAndOccurrences()) {
|
||||
Pair<Long, String> countAndDescription = getCountPropertyAndDescription(attribute);
|
||||
properties.add(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), countAndDescription.getRight(), countAndDescription.getLeft()));
|
||||
// Create place holders for S C O
|
||||
properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), VALUE_LOADING, ""));
|
||||
properties.add(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), VALUE_LOADING, ""));
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
properties.add(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), VALUE_LOADING, ""));
|
||||
}
|
||||
|
||||
// Get the SCO columns data in a background task
|
||||
backgroundTasksPool.submit(new GetSCOTask(
|
||||
new WeakReference<>(this), weakPcl));
|
||||
|
||||
properties.add(new NodeProperty<>(LOCATION.toString(), LOCATION.toString(), NO_DESCR, getContentPath(content)));
|
||||
properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getMtime(), content)));
|
||||
properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCtime(), content)));
|
||||
@ -437,19 +392,19 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
|
||||
@NbBundle.Messages({
|
||||
"AbstractAbstractFileNode.createSheet.count.displayName=O",
|
||||
"AbstractAbstractFileNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated",
|
||||
"AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
|
||||
"# {0} - occuranceCount",
|
||||
"AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurances of the correlation value"})
|
||||
Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance attribute) {
|
||||
"# {0} - occurenceCount",
|
||||
"AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurences of the MD5 correlation value"})
|
||||
@Override
|
||||
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription) {
|
||||
Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
|
||||
String description = Bundle.AbstractAbstractFileNode_createSheet_count_noCentralRepo_description();
|
||||
String description = defaultDescription;
|
||||
try {
|
||||
//don't perform the query if there is no correlation value
|
||||
if (attribute != null && StringUtils.isNotBlank(attribute.getCorrelationValue())) {
|
||||
count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(attribute.getCorrelationType(), attribute.getCorrelationValue());
|
||||
if (attributeType != null && StringUtils.isNotBlank(attributeValue)) {
|
||||
count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(attributeType, attributeValue);
|
||||
description = Bundle.AbstractAbstractFileNode_createSheet_count_description(count);
|
||||
} else if (attribute != null) {
|
||||
} else if (attributeType != null) {
|
||||
description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description();
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
@ -457,7 +412,6 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
} catch (CorrelationAttributeNormalizationException ex) {
|
||||
logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex);
|
||||
}
|
||||
|
||||
return Pair.of(count, description);
|
||||
}
|
||||
|
||||
@ -468,7 +422,8 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
"AbstractAbstractFileNode.createSheet.taggedFile.description=File has been tagged.",
|
||||
"AbstractAbstractFileNode.createSheet.notableTaggedFile.description=File tagged with notable tag.",
|
||||
"AbstractAbstractFileNode.createSheet.noScore.description=No score"})
|
||||
Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<ContentTag> tags) {
|
||||
@Override
|
||||
protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
|
||||
DataResultViewerTable.Score score = DataResultViewerTable.Score.NO_SCORE;
|
||||
String description = Bundle.AbstractAbstractFileNode_createSheet_noScore_description();
|
||||
if (content.getKnown() == TskData.FileKnown.BAD) {
|
||||
@ -486,7 +441,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
if (!tags.isEmpty() && (score == DataResultViewerTable.Score.NO_SCORE || score == DataResultViewerTable.Score.INTERESTING_SCORE)) {
|
||||
score = DataResultViewerTable.Score.INTERESTING_SCORE;
|
||||
description = Bundle.AbstractAbstractFileNode_createSheet_taggedFile_description();
|
||||
for (ContentTag tag : tags) {
|
||||
for (Tag tag : tags) {
|
||||
if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
|
||||
score = DataResultViewerTable.Score.NOTABLE_SCORE;
|
||||
description = Bundle.AbstractAbstractFileNode_createSheet_notableTaggedFile_description();
|
||||
@ -499,11 +454,12 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
|
||||
@NbBundle.Messages({
|
||||
"AbstractAbstractFileNode.createSheet.comment.displayName=C"})
|
||||
HasCommentStatus getCommentProperty(List<ContentTag> tags, CorrelationAttributeInstance attribute) {
|
||||
@Override
|
||||
protected HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
|
||||
|
||||
DataResultViewerTable.HasCommentStatus status = !tags.isEmpty() ? DataResultViewerTable.HasCommentStatus.TAG_NO_COMMENT : DataResultViewerTable.HasCommentStatus.NO_COMMENT;
|
||||
|
||||
for (ContentTag tag : tags) {
|
||||
for (Tag tag : tags) {
|
||||
if (!StringUtils.isBlank(tag.getComment())) {
|
||||
//if the tag is null or empty or contains just white space it will indicate there is not a comment
|
||||
status = DataResultViewerTable.HasCommentStatus.TAG_COMMENT;
|
||||
@ -571,7 +527,13 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
|
||||
return tags;
|
||||
}
|
||||
|
||||
CorrelationAttributeInstance getCorrelationAttributeInstance() {
|
||||
@Override
|
||||
protected List<Tag> getAllTagsFromDatabase() {
|
||||
return new ArrayList<>(getContentTagsFromDatabase());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorrelationAttributeInstance getCorrelationAttributeInstance() {
|
||||
CorrelationAttributeInstance attribute = null;
|
||||
if (EamDb.isEnabled() && !UserPreferences.hideCentralRepoCommentsAndOccurrences()) {
|
||||
attribute = EamArtifactUtil.getInstanceFromContent(content);
|
||||
|
@ -18,20 +18,30 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
@ -51,27 +61,60 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
||||
private static final Logger logger = Logger.getLogger(AbstractContentNode.class.getName());
|
||||
|
||||
/**
|
||||
* Handles aspects that depend on the Content object
|
||||
*
|
||||
* @param content Underlying Content instances
|
||||
* A pool of background tasks to run any long computation needed to populate
|
||||
* this node.
|
||||
*/
|
||||
AbstractContentNode(T content) {
|
||||
this(content, Lookups.singleton(content) );
|
||||
static final ExecutorService backgroundTasksPool;
|
||||
private static final Integer MAX_POOL_SIZE = 10;
|
||||
|
||||
/**
|
||||
* Default no description string
|
||||
*/
|
||||
@NbBundle.Messages({"AbstractContentNode.nodescription=no description",
|
||||
"AbstractContentNode.valueLoading=value loading"})
|
||||
protected static final String NO_DESCR = Bundle.AbstractContentNode_nodescription();
|
||||
protected static final String VALUE_LOADING = Bundle.AbstractContentNode_valueLoading();
|
||||
|
||||
/**
|
||||
* Event signals to indicate the background tasks have completed processing.
|
||||
* Currently, we have one property task in the background:
|
||||
*
|
||||
* 1) Retrieving the translation of the file name
|
||||
*/
|
||||
enum NodeSpecificEvents {
|
||||
TRANSLATION_AVAILABLE,
|
||||
SCO_AVAILABLE
|
||||
}
|
||||
|
||||
static {
|
||||
//Initialize this pool only once! This will be used by every instance of AAFN
|
||||
//to do their heavy duty SCO column and translation updates.
|
||||
backgroundTasksPool = Executors.newFixedThreadPool(MAX_POOL_SIZE,
|
||||
new ThreadFactoryBuilder().setNameFormat("content-node-background-task-%d").build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles aspects that depend on the Content object
|
||||
*
|
||||
* @param content Underlying Content instances
|
||||
* @param lookup The Lookup object for the node.
|
||||
*/
|
||||
AbstractContentNode(T content) {
|
||||
this(content, Lookups.singleton(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles aspects that depend on the Content object
|
||||
*
|
||||
* @param content Underlying Content instances
|
||||
* @param lookup The Lookup object for the node.
|
||||
*/
|
||||
AbstractContentNode(T content, Lookup lookup) {
|
||||
super(Children.create(new ContentChildren(content), true), lookup);
|
||||
super(Children.create(new ContentChildren(content), false), lookup);
|
||||
this.content = content;
|
||||
//super.setName(ContentUtils.getSystemName(content));
|
||||
super.setName("content_" + Long.toString(content.getId())); //NON-NLS
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the content data associated with this node
|
||||
*
|
||||
@ -100,40 +143,40 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
||||
public boolean hasVisibleContentChildren() {
|
||||
return contentHasVisibleContentChildren(content);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the given content object has children. Useful for lazy
|
||||
* loading.
|
||||
*
|
||||
*
|
||||
* @param c The content object to look for children on
|
||||
*
|
||||
* @return true if has children
|
||||
*/
|
||||
public static boolean contentHasVisibleContentChildren(Content c){
|
||||
public static boolean contentHasVisibleContentChildren(Content c) {
|
||||
if (c != null) {
|
||||
|
||||
|
||||
try {
|
||||
if( ! c.hasChildren()) {
|
||||
if (!c.hasChildren()) {
|
||||
return false;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
|
||||
|
||||
logger.log(Level.SEVERE, "Error checking if the node has children, for content: " + c, ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String query = "SELECT COUNT(obj_id) AS count FROM "
|
||||
+ " ( SELECT obj_id FROM tsk_objects WHERE par_obj_id = " + c.getId() + " AND type = "
|
||||
+ TskData.ObjectType.ARTIFACT.getObjectType()
|
||||
+ " INTERSECT SELECT artifact_obj_id FROM blackboard_artifacts WHERE obj_id = " + c.getId()
|
||||
+ " AND (artifact_type_id = " + ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
|
||||
+ " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() + ") "
|
||||
+ " UNION SELECT obj_id FROM tsk_objects WHERE par_obj_id = " + c.getId()
|
||||
+ " AND type = " + TskData.ObjectType.ABSTRACTFILE.getObjectType() + ") AS OBJECT_IDS"; //NON-NLS;
|
||||
|
||||
|
||||
+ " ( SELECT obj_id FROM tsk_objects WHERE par_obj_id = " + c.getId() + " AND type = "
|
||||
+ TskData.ObjectType.ARTIFACT.getObjectType()
|
||||
+ " INTERSECT SELECT artifact_obj_id FROM blackboard_artifacts WHERE obj_id = " + c.getId()
|
||||
+ " AND (artifact_type_id = " + ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
|
||||
+ " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() + ") "
|
||||
+ " UNION SELECT obj_id FROM tsk_objects WHERE par_obj_id = " + c.getId()
|
||||
+ " AND type = " + TskData.ObjectType.ABSTRACTFILE.getObjectType() + ") AS OBJECT_IDS"; //NON-NLS;
|
||||
|
||||
try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
|
||||
ResultSet resultSet = dbQuery.getResultSet();
|
||||
if(resultSet.next()){
|
||||
if (resultSet.next()) {
|
||||
return (0 < resultSet.getInt("count"));
|
||||
}
|
||||
} catch (TskCoreException | SQLException | NoCurrentCaseException ex) {
|
||||
@ -142,7 +185,7 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the underlying content object has children Useful for lazy
|
||||
* loading.
|
||||
@ -162,7 +205,7 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
||||
|
||||
return hasChildren;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return ids of children of the underlying content. The ids can be treated
|
||||
* as keys - useful for lazy loading.
|
||||
@ -240,4 +283,83 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
|
||||
public int read(byte[] buf, long offset, long len) throws TskException {
|
||||
return content.read(buf, offset, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the values of the properties in the current property sheet with
|
||||
* the new properties being passed in. Only if that property exists in the
|
||||
* current sheet will it be applied. That way, we allow for subclasses to
|
||||
* add their own (or omit some!) properties and we will not accidentally
|
||||
* disrupt their UI.
|
||||
*
|
||||
* Race condition if not synchronized. Only one update should be applied at
|
||||
* a time.
|
||||
*
|
||||
* @param newProps New file property instances to be updated in the current
|
||||
* sheet.
|
||||
*/
|
||||
protected synchronized void updateSheet(NodeProperty<?>... newProps) {
|
||||
//Refresh ONLY those properties in the sheet currently. Subclasses may have
|
||||
//only added a subset of our properties or their own props.s
|
||||
Sheet visibleSheet = this.getSheet();
|
||||
Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES);
|
||||
Property<?>[] visibleProps = visibleSheetSet.getProperties();
|
||||
for (NodeProperty<?> newProp : newProps) {
|
||||
for (int i = 0; i < visibleProps.length; i++) {
|
||||
if (visibleProps[i].getName().equals(newProp.getName())) {
|
||||
visibleProps[i] = newProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
visibleSheetSet.put(visibleProps);
|
||||
visibleSheet.put(visibleSheetSet);
|
||||
//setSheet() will notify Netbeans to update this node in the UI.
|
||||
this.setSheet(visibleSheet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and returns a list of all tags associated with this content node.
|
||||
*
|
||||
* @return list of tags associated with the node.
|
||||
*/
|
||||
abstract protected List<Tag> getAllTagsFromDatabase();
|
||||
|
||||
/**
|
||||
* Returns correlation attribute instance for the underlying content of the
|
||||
* node.
|
||||
*
|
||||
* @return correlation attribute instance for the underlying content of the
|
||||
* node.
|
||||
*/
|
||||
abstract protected CorrelationAttributeInstance getCorrelationAttributeInstance();
|
||||
|
||||
/**
|
||||
* Returns Score property for the node.
|
||||
*
|
||||
* @param tags list of tags.
|
||||
*
|
||||
* @return Score property for the underlying content of the node.
|
||||
*/
|
||||
abstract protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags);
|
||||
|
||||
/**
|
||||
* Returns comment property for the node.
|
||||
*
|
||||
* @param tags list of tags
|
||||
* @param attribute correlation attribute instance
|
||||
*
|
||||
* @return Comment property for the underlying content of the node.
|
||||
*/
|
||||
abstract protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute);
|
||||
|
||||
/**
|
||||
* Returns occurrences/count property for the node.
|
||||
*
|
||||
* @param attributeType the type of the attribute to count
|
||||
* @param attributeValue the value of the attribute to count
|
||||
* @param defaultDescription a description to use when none is determined by
|
||||
* the getCountPropertyAndDescription method
|
||||
*
|
||||
* @return count property for the underlying content of the node.
|
||||
*/
|
||||
abstract protected Pair<Long, String> getCountPropertyAndDescription(Type attributeType, String attributeValue, String defaultDescription);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -22,6 +22,7 @@ import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -37,6 +38,7 @@ import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.Action;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
@ -50,16 +52,19 @@ import org.sleuthkit.autopsy.casemodule.events.CommentChangedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.Score;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.HasCommentStatus;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool;
|
||||
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||
@ -96,9 +101,6 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
|
||||
private List<NodeProperty<? extends Object>> customProperties;
|
||||
|
||||
private final static String NO_DESCR = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.noDesc.text");
|
||||
|
||||
|
||||
/*
|
||||
* Artifact types which should have the full unique path of the associated
|
||||
* content as a property.
|
||||
@ -150,6 +152,18 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
removeListeners();
|
||||
contentCache.invalidateAll();
|
||||
}
|
||||
} else if (eventType.equals(NodeSpecificEvents.SCO_AVAILABLE.toString())) {
|
||||
SCOData scoData = (SCOData) evt.getNewValue();
|
||||
if (scoData.getScoreAndDescription() != null) {
|
||||
updateSheet(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_score_name(), Bundle.BlackboardArtifactNode_createSheet_score_displayName(), scoData.getScoreAndDescription().getRight(), scoData.getScoreAndDescription().getLeft()));
|
||||
}
|
||||
if (scoData.getComment() != null) {
|
||||
updateSheet(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_comment_name(), Bundle.BlackboardArtifactNode_createSheet_comment_displayName(), NO_DESCR, scoData.getComment()));
|
||||
}
|
||||
if (scoData.getCountAndDescription() != null
|
||||
&& !UserPreferences.hideCentralRepoCommentsAndOccurrences()) {
|
||||
updateSheet(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_count_name(), Bundle.BlackboardArtifactNode_createSheet_count_displayName(), scoData.getCountAndDescription().getRight(), scoData.getCountAndDescription().getLeft()));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -319,7 +333,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
}
|
||||
return srcName;
|
||||
}
|
||||
|
||||
|
||||
@NbBundle.Messages({
|
||||
"BlackboardArtifactNode.createSheet.artifactType.displayName=Result Type",
|
||||
"BlackboardArtifactNode.createSheet.artifactType.name=Result Type",
|
||||
@ -335,8 +349,6 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
List<Tag> tags = getAllTagsFromDatabase();
|
||||
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
@ -351,17 +363,17 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
NO_DESCR,
|
||||
this.getSourceName()));
|
||||
|
||||
addScoreProperty(sheetSet, tags);
|
||||
|
||||
CorrelationAttributeInstance correlationAttribute = null;
|
||||
// Create place holders for S C O
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_score_name(), Bundle.BlackboardArtifactNode_createSheet_score_displayName(), VALUE_LOADING, ""));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_comment_name(), Bundle.BlackboardArtifactNode_createSheet_comment_displayName(), VALUE_LOADING, ""));
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
correlationAttribute = getCorrelationAttributeInstance();
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_count_name(), Bundle.BlackboardArtifactNode_createSheet_count_displayName(), VALUE_LOADING, ""));
|
||||
}
|
||||
addCommentProperty(sheetSet, tags, correlationAttribute);
|
||||
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
addCountProperty(sheetSet, correlationAttribute);
|
||||
}
|
||||
// Get the SCO columns data in a background task
|
||||
backgroundTasksPool.submit(new GetSCOTask(
|
||||
new WeakReference<>(this), weakPcl));
|
||||
|
||||
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
try {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||
@ -520,6 +532,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
* @return a list of tags which on the artifact or the file it is associated
|
||||
* with
|
||||
*/
|
||||
@Override
|
||||
protected final List<Tag> getAllTagsFromDatabase() {
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
try {
|
||||
@ -569,6 +582,13 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correlation attribute for the associated file
|
||||
*
|
||||
* @return the correlation attribute for the file associated with this
|
||||
* BlackboardArtifactNode
|
||||
*/
|
||||
@Override
|
||||
protected final CorrelationAttributeInstance getCorrelationAttributeInstance() {
|
||||
CorrelationAttributeInstance correlationAttribute = null;
|
||||
if (EamDb.isEnabled()) {
|
||||
@ -581,16 +601,37 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
* Used by (subclasses of) BlackboardArtifactNode to add the comment
|
||||
* property to their sheets.
|
||||
*
|
||||
* @param sheetSet the modifiable Sheet.Set returned by
|
||||
* Sheet.get(Sheet.PROPERTIES)
|
||||
* @param sheetSet the modifiable Sheet.Set to add the property to
|
||||
* @param tags the list of tags associated with the file
|
||||
* @param attribute the correlation attribute associated with this
|
||||
* artifact's associated file, null if central repo is not
|
||||
* enabled
|
||||
*
|
||||
* @deprecated Use the GetSCOTask to get this data on a background
|
||||
* thread..., and then update the property sheet asynchronously
|
||||
*/
|
||||
@NbBundle.Messages({"BlackboardArtifactNode.createSheet.comment.name=C",
|
||||
"BlackboardArtifactNode.createSheet.comment.displayName=C"})
|
||||
@Deprecated
|
||||
protected final void addCommentProperty(Sheet.Set sheetSet, List<Tag> tags, CorrelationAttributeInstance attribute) {
|
||||
HasCommentStatus status = getCommentProperty(tags, attribute);
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_comment_name(), Bundle.BlackboardArtifactNode_createSheet_comment_displayName(), NO_DESCR,
|
||||
status));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the comment property for the node
|
||||
*
|
||||
* @param tags the list of tags associated with the file
|
||||
* @param attribute the correlation attribute associated with this
|
||||
* artifact's associated file, null if central repo is not
|
||||
* enabled
|
||||
*
|
||||
* @return comment property
|
||||
*/
|
||||
@Override
|
||||
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
|
||||
|
||||
HasCommentStatus status = tags.size() > 0 ? HasCommentStatus.TAG_NO_COMMENT : HasCommentStatus.NO_COMMENT;
|
||||
for (Tag tag : tags) {
|
||||
if (!StringUtils.isBlank(tag.getComment())) {
|
||||
@ -609,17 +650,18 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
status = HasCommentStatus.CR_COMMENT;
|
||||
}
|
||||
}
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_comment_name(), Bundle.BlackboardArtifactNode_createSheet_comment_displayName(), NO_DESCR,
|
||||
status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by (subclasses of) BlackboardArtifactNode to add the Score property
|
||||
* to their sheets.
|
||||
*
|
||||
* @param sheetSet the modifiable Sheet.Set returned by
|
||||
* Sheet.get(Sheet.PROPERTIES)
|
||||
* @param sheetSet the modifiable Sheet.Set to add the property to
|
||||
* @param tags the list of tags associated with the file
|
||||
*
|
||||
* @deprecated Use the GetSCOTask to get this data on a background
|
||||
* thread..., and then update the property sheet asynchronously
|
||||
*/
|
||||
@NbBundle.Messages({"BlackboardArtifactNode.createSheet.score.name=S",
|
||||
"BlackboardArtifactNode.createSheet.score.displayName=S",
|
||||
@ -628,7 +670,21 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
"BlackboardArtifactNode.createSheet.taggedItem.description=Result or associated file has been tagged.",
|
||||
"BlackboardArtifactNode.createSheet.notableTaggedItem.description=Result or associated file tagged with notable tag.",
|
||||
"BlackboardArtifactNode.createSheet.noScore.description=No score"})
|
||||
protected final void addScoreProperty(Sheet.Set sheetSet, List<Tag> tags) {
|
||||
@Deprecated
|
||||
protected final void addScorePropertyAndDescription(Sheet.Set sheetSet, List<Tag> tags) {
|
||||
Pair<DataResultViewerTable.Score, String> scoreAndDescription = getScorePropertyAndDescription(tags);
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_score_name(), Bundle.BlackboardArtifactNode_createSheet_score_displayName(), scoreAndDescription.getRight(), scoreAndDescription.getLeft()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the score property for the node.
|
||||
*
|
||||
* @param tags the list of tags associated with the file
|
||||
*
|
||||
* @return score property and description
|
||||
*/
|
||||
@Override
|
||||
protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
|
||||
Score score = Score.NO_SCORE;
|
||||
String description = Bundle.BlackboardArtifactNode_createSheet_noScore_description();
|
||||
if (associated instanceof AbstractFile) {
|
||||
@ -673,34 +729,63 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
}
|
||||
}
|
||||
}
|
||||
sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_score_name(), Bundle.BlackboardArtifactNode_createSheet_score_displayName(), description, score));
|
||||
|
||||
return Pair.of(score, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by (subclasses of) BlackboardArtifactNode to add the Occurrences
|
||||
* property to their sheets.
|
||||
*
|
||||
* @param sheetSet the modifiable Sheet.Set to add the property to
|
||||
* @param attribute correlation attribute instance
|
||||
*
|
||||
* @deprecated Use the GetSCOTask to get this data on a background
|
||||
* thread..., and then update the property sheet asynchronously
|
||||
*/
|
||||
@NbBundle.Messages({"BlackboardArtifactNode.createSheet.count.name=O",
|
||||
"BlackboardArtifactNode.createSheet.count.displayName=O",
|
||||
"BlackboardArtifactNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated",
|
||||
"BlackboardArtifactNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this artifact's associated file when the column was populated",
|
||||
"# {0} - occuranceCount",
|
||||
"BlackboardArtifactNode.createSheet.count.description=There were {0} datasource(s) found with occurances of the correlation value"})
|
||||
|
||||
"BlackboardArtifactNode.createSheet.count.noCorrelationAttributes.description=No correlation properties found",
|
||||
"BlackboardArtifactNode.createSheet.count.noCorrelationValues.description=Unable to find other occurrences because no value exists for the available correlation property",
|
||||
"# {0} - occurenceCount",
|
||||
"# {1} - attributeType",
|
||||
"BlackboardArtifactNode.createSheet.count.description=There were {0} datasource(s) found with occurrences of the correlation value of type {1}"})
|
||||
@Deprecated
|
||||
protected final void addCountProperty(Sheet.Set sheetSet, CorrelationAttributeInstance attribute) {
|
||||
Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
|
||||
String description = Bundle.BlackboardArtifactNode_createSheet_count_noCentralRepo_description();
|
||||
Pair<Long, String> countAndDescription = getCountPropertyAndDescription(attribute.getCorrelationType(), attribute.getCorrelationValue(), Bundle.BlackboardArtifactNode_createSheet_count_noCorrelationAttributes_description());
|
||||
sheetSet.put(
|
||||
new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_count_name(), Bundle.BlackboardArtifactNode_createSheet_count_displayName(), countAndDescription.getRight(), countAndDescription.getLeft()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Occurrences property for the node.
|
||||
*
|
||||
* @param attributeType the type of the attribute to count
|
||||
* @param attributeValue the value of the attribute to count
|
||||
* @param defaultDescription a description to use when none is determined by
|
||||
* the getCountPropertyAndDescription method
|
||||
*
|
||||
* @return count and description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected Pair<Long, String> getCountPropertyAndDescription(Type attributeType, String attributeValue, String defaultDescription) {
|
||||
Long count = -1L;
|
||||
String description = defaultDescription;
|
||||
try {
|
||||
//don't perform the query if there is no correlation value
|
||||
if (attribute != null && StringUtils.isNotBlank(attribute.getCorrelationValue())) {
|
||||
count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(attribute.getCorrelationType(), attribute.getCorrelationValue());
|
||||
description = Bundle.BlackboardArtifactNode_createSheet_count_description(count);
|
||||
} else if (attribute != null) {
|
||||
description = Bundle.BlackboardArtifactNode_createSheet_count_hashLookupNotRun_description();
|
||||
if (attributeType != null && StringUtils.isNotBlank(attributeValue)) {
|
||||
count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(attributeType, attributeValue);
|
||||
description = Bundle.BlackboardArtifactNode_createSheet_count_description(count, attributeType.getDisplayName());
|
||||
} else if (attributeType != null) {
|
||||
description = Bundle.BlackboardArtifactNode_createSheet_count_noCorrelationValues_description();
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex);
|
||||
} catch (CorrelationAttributeNormalizationException ex) {
|
||||
logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex);
|
||||
}
|
||||
sheetSet.put(
|
||||
new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_count_name(), Bundle.BlackboardArtifactNode_createSheet_count_displayName(), description, count));
|
||||
return Pair.of(count, description);
|
||||
}
|
||||
|
||||
private void updateSheet() {
|
||||
|
@ -1,16 +1,14 @@
|
||||
AbstractAbstractFileNode.accessTimeColLbl=Access Time
|
||||
AbstractAbstractFileNode.addFileProperty.desc=no description
|
||||
AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.
|
||||
AbstractAbstractFileNode.changeTimeColLbl=Change Time
|
||||
AbstractAbstractFileNode.createdTimeColLbl=Created Time
|
||||
AbstractAbstractFileNode.createSheet.comment.displayName=C
|
||||
AbstractAbstractFileNode.createSheet.comment.name=C
|
||||
# {0} - occuranceCount
|
||||
AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurances of the correlation value
|
||||
# {0} - occurenceCount
|
||||
AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurences of the MD5 correlation value
|
||||
AbstractAbstractFileNode.createSheet.count.displayName=O
|
||||
AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated
|
||||
AbstractAbstractFileNode.createSheet.count.name=O
|
||||
AbstractAbstractFileNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated
|
||||
AbstractAbstractFileNode.createSheet.interestingResult.description=File has interesting result associated with it.
|
||||
AbstractAbstractFileNode.createSheet.noScore.description=No score
|
||||
AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.
|
||||
@ -37,6 +35,8 @@ AbstractAbstractFileNode.tagsProperty.displayName=Tags
|
||||
AbstractAbstractFileNode.typeDirColLbl=Type(Dir)
|
||||
AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)
|
||||
AbstractAbstractFileNode.useridColLbl=UserID
|
||||
AbstractContentNode.nodescription=no description
|
||||
AbstractContentNode.valueLoading=value loading
|
||||
AbstractFsContentNode.noDesc.text=no description
|
||||
ArtifactStringContent.attrsTableHeader.sources=Source(s)
|
||||
ArtifactStringContent.attrsTableHeader.type=Type
|
||||
@ -53,12 +53,13 @@ BlackboardArtifactNode.createSheet.artifactType.displayName=Result Type
|
||||
BlackboardArtifactNode.createSheet.artifactType.name=Result Type
|
||||
BlackboardArtifactNode.createSheet.comment.displayName=C
|
||||
BlackboardArtifactNode.createSheet.comment.name=C
|
||||
# {0} - occuranceCount
|
||||
BlackboardArtifactNode.createSheet.count.description=There were {0} datasource(s) found with occurances of the correlation value
|
||||
# {0} - occurenceCount
|
||||
# {1} - attributeType
|
||||
BlackboardArtifactNode.createSheet.count.description=There were {0} datasource(s) found with occurrences of the correlation value of type {1}
|
||||
BlackboardArtifactNode.createSheet.count.displayName=O
|
||||
BlackboardArtifactNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this artifact's associated file when the column was populated
|
||||
BlackboardArtifactNode.createSheet.count.name=O
|
||||
BlackboardArtifactNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated
|
||||
BlackboardArtifactNode.createSheet.count.noCorrelationAttributes.description=No correlation properties found
|
||||
BlackboardArtifactNode.createSheet.count.noCorrelationValues.description=Unable to find other occurrences because no value exists for the available correlation property
|
||||
BlackboardArtifactNode.createSheet.fileSize.displayName=Size
|
||||
BlackboardArtifactNode.createSheet.fileSize.name=Size
|
||||
BlackboardArtifactNode.createSheet.interestingResult.description=Result has an interesting result associated with it.
|
||||
@ -114,6 +115,8 @@ FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype
|
||||
FileTypesByMimeTypeNode.createSheet.mediaType.desc=no description
|
||||
FileTypesByMimeTypeNode.createSheet.mediaType.displayName=Type
|
||||
FileTypesByMimeTypeNode.createSheet.mediaType.name=Type
|
||||
GetSCOTask.occurrences.defaultDescription=No correlation properties found
|
||||
GetSCOTask.occurrences.multipleProperties=Multiple different correlation properties exist for this result
|
||||
ImageNode.action.runIngestMods.text=Run Ingest Modules
|
||||
ImageNode.createSheet.deviceId.desc=Device ID of the image
|
||||
ImageNode.createSheet.deviceId.displayName=Device ID
|
||||
|
@ -36,6 +36,7 @@ import org.sleuthkit.autopsy.actions.ReplaceBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
@ -92,6 +93,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -119,6 +121,7 @@ public class DataModelActionsFactory {
|
||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, slackFileNode));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -155,6 +158,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());//
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -189,6 +193,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -223,6 +228,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -257,6 +263,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -291,6 +298,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -325,6 +333,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -379,6 +388,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
@ -415,6 +425,7 @@ public class DataModelActionsFactory {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
if (isArtifactSource) {
|
||||
|
@ -57,7 +57,7 @@ public class DataSourcesNode extends DisplayableItemNode {
|
||||
}
|
||||
|
||||
public DataSourcesNode(long dsObjId) {
|
||||
super(Children.create(new DataSourcesNodeChildren(dsObjId), true), Lookups.singleton(NAME));
|
||||
super(Children.create(new DataSourcesNodeChildren(dsObjId), false), Lookups.singleton(NAME));
|
||||
displayName = (dsObjId > 0) ? NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.group_by_datasource.name") : NAME;
|
||||
init();
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -37,7 +36,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -59,7 +57,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
public class DeletedContent implements AutopsyVisitableItem {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
|
||||
"DeletedContent.allDelFilter.text=All"})
|
||||
@ -105,11 +103,11 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
|
||||
public DeletedContent(SleuthkitCase skCase, long dsObjId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = dsObjId;
|
||||
this.filteringDSObjId = dsObjId;
|
||||
}
|
||||
|
||||
long filteringDataSourceObjId() {
|
||||
return this.datasourceObjId;
|
||||
return this.filteringDSObjId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -439,7 +437,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
|
||||
}
|
||||
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
return query;
|
||||
|
@ -28,6 +28,7 @@ import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
@ -89,6 +90,7 @@ public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
|
||||
actionsList.add(ViewFileInTimelineAction.createViewFileAction(content));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new RunIngestModulesAction(content));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
|
@ -28,7 +28,6 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -40,7 +39,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -88,7 +86,7 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
}
|
||||
private SleuthkitCase skCase;
|
||||
private final EmailResults emailResults;
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
|
||||
|
||||
@ -110,7 +108,7 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
*/
|
||||
public EmailExtracted(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
emailResults = new EmailResults();
|
||||
}
|
||||
|
||||
@ -162,8 +160,8 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
+ "attribute_type_id=" + pathAttrId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId;
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
|
||||
|
@ -26,7 +26,6 @@ import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
@ -35,7 +34,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -64,7 +62,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
private SleuthkitCase skCase; // set to null after case has been closed
|
||||
private Blackboard blackboard;
|
||||
public static final String NAME = NbBundle.getMessage(RootNode.class, "ExtractedContentNode.name.text");
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
/**
|
||||
* Constructs extracted content object
|
||||
@ -83,7 +81,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
*/
|
||||
public ExtractedContent(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
this.blackboard = skCase.getBlackboard();
|
||||
}
|
||||
|
||||
@ -307,8 +305,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
protected boolean createKeys(List<BlackboardArtifact.Type> list) {
|
||||
if (skCase != null) {
|
||||
try {
|
||||
List<BlackboardArtifact.Type> types = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) ?
|
||||
blackboard.getArtifactTypesInUse(datasourceObjId) :
|
||||
List<BlackboardArtifact.Type> types = (filteringDSObjId > 0) ?
|
||||
blackboard.getArtifactTypesInUse(filteringDSObjId) :
|
||||
skCase.getArtifactTypesInUse() ;
|
||||
|
||||
types.removeAll(doNotShow);
|
||||
@ -372,8 +370,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
// a performance increase might be had by adding a
|
||||
// "getBlackboardArtifactCount()" method to skCase
|
||||
try {
|
||||
this.childCount = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) ?
|
||||
blackboard.getArtifactsCount(type.getTypeID(), datasourceObjId) :
|
||||
this.childCount = (filteringDSObjId > 0) ?
|
||||
blackboard.getArtifactsCount(type.getTypeID(), filteringDSObjId) :
|
||||
skCase.getBlackboardArtifactsTypeCount(type.getTypeID());
|
||||
} catch (TskException ex) {
|
||||
Logger.getLogger(TypeNode.class.getName())
|
||||
@ -501,8 +499,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
protected List<BlackboardArtifact> makeKeys() {
|
||||
if (skCase != null) {
|
||||
try {
|
||||
return Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? blackboard.getArtifacts(type.getTypeID(), datasourceObjId)
|
||||
return (filteringDSObjId > 0)
|
||||
? blackboard.getArtifacts(type.getTypeID(), filteringDSObjId)
|
||||
: skCase.getBlackboardArtifacts(type.getTypeID());
|
||||
} catch (TskException ex) {
|
||||
Logger.getLogger(ArtifactFactory.class.getName()).log(Level.SEVERE, "Couldn't get blackboard artifacts from database", ex); //NON-NLS
|
||||
|
@ -32,6 +32,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
@ -173,6 +174,7 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
actionsList.add(null); // Creates an item separator
|
||||
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // Creates an item separator
|
||||
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
@ -24,7 +24,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -37,9 +36,7 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -63,7 +60,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
public class FileSize implements AutopsyVisitableItem {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
public enum FileSizeFilter implements AutopsyVisitableItem {
|
||||
|
||||
@ -105,7 +102,7 @@ public class FileSize implements AutopsyVisitableItem {
|
||||
|
||||
public FileSize(SleuthkitCase skCase, long dsObjId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = dsObjId;
|
||||
this.filteringDSObjId = dsObjId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,7 +115,7 @@ public class FileSize implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
long filteringDataSourceObjId() {
|
||||
return this.datasourceObjId;
|
||||
return this.filteringDSObjId;
|
||||
}
|
||||
/*
|
||||
* Root node. Children are nodes for specific sizes.
|
||||
@ -437,7 +434,7 @@ public class FileSize implements AutopsyVisitableItem {
|
||||
query = query + " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() + ")"; //NON-NLS
|
||||
|
||||
// filter by datasource if indicated in case preferences
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -39,7 +38,6 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -366,7 +364,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
+ (UserPreferences.hideKnownFilesInViewsTree()
|
||||
? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"
|
||||
: " ")
|
||||
+ (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
+ (filteringDataSourceObjId() > 0
|
||||
? " AND data_source_obj_id = " + filteringDataSourceObjId()
|
||||
: " ")
|
||||
+ " AND (extension IN (" + filter.getFilter().stream()
|
||||
|
@ -28,7 +28,6 @@ import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -42,7 +41,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideKnownFilesInViewsTree;
|
||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTree;
|
||||
@ -103,7 +101,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
||||
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||
+ "))"
|
||||
+ ( Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) ? " AND data_source_obj_id = " + this.filteringDataSourceObjId() : " ")
|
||||
+ ( (filteringDataSourceObjId() > 0) ? " AND data_source_obj_id = " + this.filteringDataSourceObjId() : " ")
|
||||
+ (hideKnownFilesInViewsTree() ? (" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")") : "");
|
||||
}
|
||||
|
||||
|
129
Core/src/org/sleuthkit/autopsy/datamodel/GetSCOTask.java
Normal file
129
Core/src/org/sleuthkit/autopsy/datamodel/GetSCOTask.java
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Background task to get Score, Comment and Occurrences values for an Abstract
|
||||
* content node.
|
||||
*
|
||||
*/
|
||||
class GetSCOTask implements Runnable {
|
||||
|
||||
private final WeakReference<AbstractContentNode<?>> weakNodeRef;
|
||||
private final PropertyChangeListener listener;
|
||||
private static final Logger logger = Logger.getLogger(GetSCOTask.class.getName());
|
||||
|
||||
GetSCOTask(WeakReference<AbstractContentNode<?>> weakContentRef, PropertyChangeListener listener) {
|
||||
this.weakNodeRef = weakContentRef;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Messages({"GetSCOTask.occurrences.defaultDescription=No correlation properties found",
|
||||
"GetSCOTask.occurrences.multipleProperties=Multiple different correlation properties exist for this result"})
|
||||
@Override
|
||||
public void run() {
|
||||
AbstractContentNode<?> contentNode = weakNodeRef.get();
|
||||
|
||||
//Check for stale reference
|
||||
if (contentNode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the SCO column values
|
||||
List<Tag> tags = contentNode.getAllTagsFromDatabase();
|
||||
CorrelationAttributeInstance fileAttribute = contentNode.getCorrelationAttributeInstance();
|
||||
|
||||
SCOData scoData = new SCOData();
|
||||
scoData.setScoreAndDescription(contentNode.getScorePropertyAndDescription(tags));
|
||||
scoData.setComment(contentNode.getCommentProperty(tags, fileAttribute));
|
||||
|
||||
if (!UserPreferences.hideCentralRepoCommentsAndOccurrences()) {
|
||||
Type type = null;
|
||||
String value = null;
|
||||
String description = Bundle.GetSCOTask_occurrences_defaultDescription();
|
||||
if (contentNode instanceof BlackboardArtifactNode) {
|
||||
BlackboardArtifact bbArtifact = ((BlackboardArtifactNode) contentNode).getArtifact();
|
||||
//for specific artifact types we still want to display information for the file instance correlation attribute
|
||||
if (bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()
|
||||
|| bbArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
try {
|
||||
if (bbArtifact.getParent() instanceof AbstractFile) {
|
||||
type = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(CorrelationAttributeInstance.FILES_TYPE_ID);
|
||||
value = ((AbstractFile) bbArtifact.getParent()).getMd5Hash();
|
||||
}
|
||||
} catch (TskCoreException | EamDbException ex) {
|
||||
logger.log(Level.WARNING, "Unable to get correlation type or value to determine value for O column for artifact", ex);
|
||||
}
|
||||
} else {
|
||||
List<CorrelationAttributeInstance> listOfPossibleAttributes = EamArtifactUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false);
|
||||
if (listOfPossibleAttributes.size() > 1) {
|
||||
//Don't display anything if there is more than 1 correlation property for an artifact but let the user know
|
||||
description = Bundle.GetSCOTask_occurrences_multipleProperties();
|
||||
} else if (!listOfPossibleAttributes.isEmpty()) {
|
||||
//there should only be one item in the list
|
||||
type = listOfPossibleAttributes.get(0).getCorrelationType();
|
||||
value = listOfPossibleAttributes.get(0).getCorrelationValue();
|
||||
}
|
||||
}
|
||||
} else if (contentNode.getContent() instanceof AbstractFile) {
|
||||
//use the file instance correlation attribute if the node is not a BlackboardArtifactNode
|
||||
try {
|
||||
type = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(CorrelationAttributeInstance.FILES_TYPE_ID);
|
||||
value = ((AbstractFile) contentNode.getContent()).getMd5Hash();
|
||||
} catch (EamDbException ex) {
|
||||
logger.log(Level.WARNING, "Unable to get correlation type to determine value for O column for file", ex);
|
||||
}
|
||||
}
|
||||
scoData.setCountAndDescription(contentNode.getCountPropertyAndDescription(type, value, description));
|
||||
}
|
||||
|
||||
// signal SCO data is available.
|
||||
if (listener
|
||||
!= null) {
|
||||
listener.propertyChange(new PropertyChangeEvent(
|
||||
AutopsyEvent.SourceType.LOCAL.toString(),
|
||||
AbstractAbstractFileNode.NodeSpecificEvents.SCO_AVAILABLE.toString(),
|
||||
null, scoData));
|
||||
}
|
||||
}
|
||||
}
|
@ -30,7 +30,6 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -42,7 +41,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -65,7 +63,7 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
private static final Logger logger = Logger.getLogger(HashsetHits.class.getName());
|
||||
private SleuthkitCase skCase;
|
||||
private final HashsetResults hashsetResults;
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
|
||||
/**
|
||||
@ -87,7 +85,7 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
*/
|
||||
public HashsetHits(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
hashsetResults = new HashsetResults();
|
||||
}
|
||||
|
||||
@ -142,8 +140,8 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
+ "attribute_type_id=" + setNameId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId;
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
|
||||
|
@ -28,12 +28,15 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor;
|
||||
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
|
||||
@ -47,6 +50,7 @@ import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.autopsy.datamodel.BaseChildFactory.NoSuchEventBusException;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
|
||||
/**
|
||||
* This class is used to represent the "Node" for the image. The children of
|
||||
@ -126,7 +130,7 @@ public class ImageNode extends AbstractContentNode<Image> {
|
||||
"ImageNode.createSheet.type.text=Image",
|
||||
"ImageNode.createSheet.sectorSize.name=Sector Size (Bytes)",
|
||||
"ImageNode.createSheet.sectorSize.displayName=Sector Size (Bytes)",
|
||||
"ImageNode.createSheet.sectorSize.desc=Sector size of the image in bytes.",
|
||||
"ImageNode.createSheet.sectorSize.desc=Sector size of the image in bytes.",
|
||||
"ImageNode.createSheet.timezone.name=Timezone",
|
||||
"ImageNode.createSheet.timezone.displayName=Timezone",
|
||||
"ImageNode.createSheet.timezone.desc=Timezone of the image",
|
||||
@ -250,4 +254,75 @@ public class ImageNode extends AbstractContentNode<Image> {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads and returns a list of all tags associated with this content node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @return list of tags associated with the node.
|
||||
*/
|
||||
@Override
|
||||
protected List<Tag> getAllTagsFromDatabase() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns correlation attribute instance for the underlying content of the
|
||||
* node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @return correlation attribute instance for the underlying content of the
|
||||
* node.
|
||||
*/
|
||||
@Override
|
||||
protected CorrelationAttributeInstance getCorrelationAttributeInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Score property for the node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @param tags list of tags.
|
||||
*
|
||||
* @return Score property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
|
||||
return Pair.of(DataResultViewerTable.Score.NO_SCORE, NO_DESCR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns comment property for the node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @param tags list of tags
|
||||
* @param attribute correlation attribute instance
|
||||
*
|
||||
* @return Comment property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
|
||||
return DataResultViewerTable.HasCommentStatus.NO_COMMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns occurrences/count property for the node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @param attributeType the type of the attribute to count
|
||||
* @param attributeValue the value of the attribute to coun
|
||||
* @param defaultDescription a description to use when none is determined by
|
||||
* the getCountPropertyAndDescription method
|
||||
*
|
||||
* @return count property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription) {
|
||||
return Pair.of(-1L, NO_DESCR);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -42,7 +41,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
@ -61,7 +59,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
private static final Logger logger = Logger.getLogger(InterestingHits.class.getName());
|
||||
private SleuthkitCase skCase;
|
||||
private final InterestingResults interestingResults = new InterestingResults();
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -82,7 +80,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
*/
|
||||
public InterestingHits(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
interestingResults.update();
|
||||
}
|
||||
|
||||
@ -133,8 +131,8 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
+ "attribute_type_id=" + setNameId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId;
|
||||
if (filteringDSObjId > 0) {
|
||||
query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
|
||||
|
@ -31,7 +31,6 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -45,7 +44,6 @@ import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
|
||||
@ -76,7 +74,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final KeywordResults keywordResults;
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
/**
|
||||
* String used in the instance MAP so that exact matches and substring can
|
||||
@ -123,7 +121,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
*/
|
||||
public KeywordHits(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
keywordResults = new KeywordResults();
|
||||
}
|
||||
|
||||
@ -344,8 +342,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
String queryStr = KEYWORD_HIT_ATTRIBUTES_QUERY;
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
queryStr += " AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId;
|
||||
if (filteringDSObjId > 0) {
|
||||
queryStr += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(queryStr)) {
|
||||
|
@ -29,6 +29,7 @@ import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
@ -105,6 +106,7 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
||||
|
@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
@ -82,6 +83,7 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
|
||||
actionsList.add(null); // creates a menu separator
|
||||
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
||||
|
@ -25,6 +25,7 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||
import org.sleuthkit.datamodel.SleuthkitVisitableItem;
|
||||
|
||||
/**
|
||||
* Children implementation for the root node of a ContentNode tree. Accepts a
|
||||
@ -34,6 +35,7 @@ public class RootContentChildren extends Children.Keys<Object> {
|
||||
|
||||
private final Collection<? extends Object> contentKeys;
|
||||
private final CreateAutopsyNodeVisitor createAutopsyNodeVisitor = new CreateAutopsyNodeVisitor();
|
||||
private final CreateSleuthkitNodeVisitor createSleuthkitNodeVisitor = new CreateSleuthkitNodeVisitor();
|
||||
|
||||
/**
|
||||
* @param contentKeys root Content objects for the Node tree
|
||||
@ -68,7 +70,7 @@ public class RootContentChildren extends Children.Keys<Object> {
|
||||
if (key instanceof AutopsyVisitableItem) {
|
||||
return new Node[] {((AutopsyVisitableItem)key).accept(createAutopsyNodeVisitor)};
|
||||
} else {
|
||||
return null;
|
||||
return new Node[] {((SleuthkitVisitableItem)key).accept(createSleuthkitNodeVisitor)};
|
||||
}
|
||||
}
|
||||
|
||||
|
56
Core/src/org/sleuthkit/autopsy/datamodel/SCOData.java
Normal file
56
Core/src/org/sleuthkit/autopsy/datamodel/SCOData.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.datamodel;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
|
||||
/**
|
||||
* Container to bag the S C & O data for an abstract file node.
|
||||
*
|
||||
*/
|
||||
class SCOData {
|
||||
|
||||
private Pair<DataResultViewerTable.Score, String> scoreAndDescription = null;
|
||||
private DataResultViewerTable.HasCommentStatus comment = null;
|
||||
private Pair<Long, String> countAndDescription = null;
|
||||
|
||||
Pair<DataResultViewerTable.Score, String> getScoreAndDescription() {
|
||||
return scoreAndDescription;
|
||||
}
|
||||
|
||||
DataResultViewerTable.HasCommentStatus getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
Pair<Long, String> getCountAndDescription() {
|
||||
return countAndDescription;
|
||||
}
|
||||
|
||||
void setScoreAndDescription(Pair<DataResultViewerTable.Score, String> scoreAndDescription) {
|
||||
this.scoreAndDescription = scoreAndDescription;
|
||||
}
|
||||
void setComment(DataResultViewerTable.HasCommentStatus comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
void setCountAndDescription(Pair<Long, String> countAndDescription) {
|
||||
this.countAndDescription = countAndDescription;
|
||||
}
|
||||
|
||||
}
|
@ -28,6 +28,7 @@ import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
@ -85,6 +86,7 @@ public class SlackFileNode extends AbstractFsContentNode<AbstractFile> {
|
||||
NbBundle.getMessage(this.getClass(), "SlackFileNode.getActions.viewInNewWin.text"), this));
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
||||
|
@ -25,6 +25,7 @@ import javax.swing.Action;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
@ -61,6 +62,7 @@ public abstract class SpecialDirectoryNode extends AbstractAbstractFileNode<Spec
|
||||
Bundle.SpecialDirectoryNode_getActions_viewInNewWin_text(), this));
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(ExtractAction.getInstance());
|
||||
actions.add(ExportCSVAction.getInstance());
|
||||
actions.add(null); // creates a menu separator
|
||||
actions.add(new FileSearchAction(Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
|
||||
if (content.isDataSource()) {
|
||||
|
@ -23,7 +23,6 @@ import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
@ -35,7 +34,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
@ -61,14 +59,14 @@ public class Tags implements AutopsyVisitableItem {
|
||||
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
Tags() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
Tags(long dsObjId) {
|
||||
this.datasourceObjId = dsObjId;
|
||||
this.filteringDSObjId = dsObjId;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,7 +79,7 @@ public class Tags implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
long filteringDataSourceObjId() {
|
||||
return this.datasourceObjId;
|
||||
return this.filteringDSObjId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -156,7 +154,7 @@ public class Tags implements AutopsyVisitableItem {
|
||||
|
||||
private class TagNameNodeFactory extends ChildFactory.Detachable<TagName> implements Observer {
|
||||
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
|
||||
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
|
||||
@ -219,7 +217,7 @@ public class Tags implements AutopsyVisitableItem {
|
||||
* @param objId data source object id
|
||||
*/
|
||||
TagNameNodeFactory(long objId) {
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
|
||||
}
|
||||
|
||||
@ -246,12 +244,12 @@ public class Tags implements AutopsyVisitableItem {
|
||||
List<TagName> tagNamesInUse;
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
tagNamesInUse = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(datasourceObjId, userName)
|
||||
tagNamesInUse = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(filteringDSObjId, userName)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(userName);
|
||||
} else {
|
||||
tagNamesInUse = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId)
|
||||
tagNamesInUse = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(filteringDSObjId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse();
|
||||
}
|
||||
Collections.sort(tagNamesInUse);
|
||||
@ -303,17 +301,17 @@ public class Tags implements AutopsyVisitableItem {
|
||||
TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, datasourceObjId, userName);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, datasourceObjId, userName);
|
||||
if (filteringDSObjId > 0) {
|
||||
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, filteringDSObjId, userName);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, filteringDSObjId, userName);
|
||||
} else {
|
||||
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
||||
}
|
||||
} else {
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId);
|
||||
if (filteringDSObjId > 0) {
|
||||
tagsCount = tm.getContentTagsCountByTagName(tagName, filteringDSObjId);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, filteringDSObjId);
|
||||
} else {
|
||||
tagsCount = tm.getContentTagsCountByTagName(tagName);
|
||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||
@ -424,12 +422,12 @@ public class Tags implements AutopsyVisitableItem {
|
||||
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
tagsCount = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, datasourceObjId, userName)
|
||||
tagsCount = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, filteringDSObjId, userName)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName);
|
||||
} else {
|
||||
tagsCount = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId)
|
||||
tagsCount = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, filteringDSObjId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName);
|
||||
}
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
@ -486,8 +484,8 @@ public class Tags implements AutopsyVisitableItem {
|
||||
protected boolean createKeys(List<ContentTag> keys) {
|
||||
// Use the content tags bearing the specified tag name as the keys.
|
||||
try {
|
||||
List<ContentTag> contentTags = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, datasourceObjId)
|
||||
List<ContentTag> contentTags = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, filteringDSObjId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName);
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
@ -544,12 +542,12 @@ public class Tags implements AutopsyVisitableItem {
|
||||
try {
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
tagsCount = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, datasourceObjId, userName)
|
||||
tagsCount = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, filteringDSObjId, userName)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
||||
} else {
|
||||
tagsCount = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId)
|
||||
tagsCount = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, filteringDSObjId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName);
|
||||
}
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
@ -606,8 +604,8 @@ public class Tags implements AutopsyVisitableItem {
|
||||
protected boolean createKeys(List<BlackboardArtifactTag> keys) {
|
||||
try {
|
||||
// Use the blackboard artifact tags bearing the specified tag name as the keys.
|
||||
List<BlackboardArtifactTag> artifactTags = Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, datasourceObjId)
|
||||
List<BlackboardArtifactTag> artifactTags = (filteringDSObjId > 0)
|
||||
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, filteringDSObjId)
|
||||
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName);
|
||||
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||
|
@ -25,10 +25,14 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR;
|
||||
import org.sleuthkit.autopsy.datamodel.BaseChildFactory.NoSuchEventBusException;
|
||||
import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
@ -39,12 +43,14 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.datamodel.Volume;
|
||||
import org.sleuthkit.autopsy.directorytree.FileSystemDetailsAction;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
|
||||
/**
|
||||
* This class is used to represent the "Node" for the volume. Its child is the
|
||||
* root directory of a file system
|
||||
*/
|
||||
public class VolumeNode extends AbstractContentNode<Volume> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(VolumeNode.class.getName());
|
||||
|
||||
/**
|
||||
@ -212,4 +218,76 @@ public class VolumeNode extends AbstractContentNode<Volume> {
|
||||
public String getItemType() {
|
||||
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and returns a list of all tags associated with this content node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @return list of tags associated with the node.
|
||||
*/
|
||||
@Override
|
||||
protected List<Tag> getAllTagsFromDatabase() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns correlation attribute instance for the underlying content of the
|
||||
* node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @return correlation attribute instance for the underlying content of the
|
||||
* node.
|
||||
*/
|
||||
@Override
|
||||
protected CorrelationAttributeInstance getCorrelationAttributeInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Score property for the node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @param tags list of tags.
|
||||
*
|
||||
* @return Score property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
|
||||
return Pair.of(DataResultViewerTable.Score.NO_SCORE, NO_DESCR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns comment property for the node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @param tags list of tags
|
||||
* @param attribute correlation attribute instance
|
||||
*
|
||||
* @return Comment property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
|
||||
return DataResultViewerTable.HasCommentStatus.NO_COMMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns occurrences/count property for the node.
|
||||
*
|
||||
* Null implementation of an abstract method.
|
||||
*
|
||||
* @param attributeType the type of the attribute to count
|
||||
* @param attributeValue the value of the attribute to coun
|
||||
* @param defaultDescription a description to use when none is determined by
|
||||
* the getCountPropertyAndDescription method
|
||||
*
|
||||
* @return count property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription) {
|
||||
return Pair.of(-1L, NO_DESCR);
|
||||
}
|
||||
}
|
||||
|
@ -57,9 +57,7 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.AutopsyItemVisitor;
|
||||
@ -96,7 +94,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
final public static String NAME = Bundle.AccountsRootNode_name();
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final long datasourceObjId;
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
|
||||
private final EventBus reviewStatusBus = new EventBus("ReviewStatusBus");
|
||||
|
||||
@ -123,7 +121,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
*/
|
||||
public Accounts(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = objId;
|
||||
this.filteringDSObjId = objId;
|
||||
|
||||
this.rejectActionInstance = new RejectAccounts();
|
||||
this.approveActionInstance = new ApproveAccounts();
|
||||
@ -153,8 +151,8 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
* based on the CasePreferences groupItemsInTreeByDataSource setting
|
||||
*/
|
||||
private String getFilterByDataSourceClause() {
|
||||
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
|
||||
return " AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId + " ";
|
||||
if (filteringDSObjId > 0) {
|
||||
return " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId + " ";
|
||||
}
|
||||
|
||||
return " ";
|
||||
|
@ -1,3 +1,8 @@
|
||||
CSVWriter.done.notifyMsg.error=Error exporting to CSV file
|
||||
# {0} - Output file
|
||||
CSVWriter.done.notifyMsg.success=Wrote to {0}
|
||||
CSVWriter.progress.cancelling=Cancelling
|
||||
CSVWriter.progress.extracting=Exporting to CSV file
|
||||
CTL_DirectoryTreeTopComponent=Directory Tree
|
||||
DataResultFilterNode.viewSourceArtifact.text=View Source Result
|
||||
# {0} - dataSourceCount
|
||||
@ -5,6 +10,11 @@ DirectoryTreeTopComponent.componentOpened.groupDataSources.text=This case contai
|
||||
DirectoryTreeTopComponent.componentOpened.groupDataSources.title=Group by data source?
|
||||
DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.
|
||||
DirectoryTreeTopComponent.resultsView.title=Listing
|
||||
ExportCSV.saveNodesToCSV.empty=No data to export
|
||||
# {0} - Output file
|
||||
ExportCSV.saveNodesToCSV.fileExists=File {0} already exists
|
||||
ExportCSV.saveNodesToCSV.noCurrentCase=No open case available
|
||||
ExportCSV.title.text=Export selected rows to CSV
|
||||
ExternalViewerAction.actionPerformed.failure.exe.message=The file is an executable and will not be opened.
|
||||
ExternalViewerAction.actionPerformed.failure.IO.message=There is no associated editor for files of this type or the associated application failed to launch.
|
||||
ExternalViewerAction.actionPerformed.failure.missingFile.message=The file no longer exists.
|
||||
|
@ -372,6 +372,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
}
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
|
@ -125,6 +125,7 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
|
||||
}
|
||||
}
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actionsList;
|
||||
}
|
||||
@ -142,6 +143,7 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
|
||||
}
|
||||
}
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actionsList;
|
||||
}
|
||||
@ -150,6 +152,7 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
|
||||
public List<? extends Action> visit(final DerivedFile d) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
||||
final Collection<AbstractFile> selectedFilesList =
|
||||
@ -166,6 +169,7 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
|
||||
public List<? extends Action> visit(final LocalFile d) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
||||
final Collection<AbstractFile> selectedFilesList =
|
||||
@ -182,6 +186,7 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
|
||||
public List<? extends Action> visit(final org.sleuthkit.datamodel.File d) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.add(ExtractAction.getInstance());
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
|
||||
final Collection<AbstractFile> selectedFilesList =
|
||||
|
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this content 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.directorytree;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import org.netbeans.api.progress.ProgressHandle;
|
||||
import org.openide.util.Cancellable;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Node.PropertySet;
|
||||
import org.openide.nodes.Node.Property;
|
||||
|
||||
/**
|
||||
* Exports CSV version of result nodes to a location selected by the user.
|
||||
*/
|
||||
public final class ExportCSVAction extends AbstractAction {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExportCSVAction.class.getName());
|
||||
private final static String DEFAULT_FILENAME = "Results";
|
||||
private final static List<String> columnsToSkip = Arrays.asList(AbstractFilePropertyType.SCORE.toString(),
|
||||
AbstractFilePropertyType.COMMENT.toString(), AbstractFilePropertyType.OCCURRENCES.toString());
|
||||
|
||||
private static String userDefinedExportPath;
|
||||
|
||||
// This class is a singleton to support multi-selection of nodes, since
|
||||
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||
private static ExportCSVAction instance;
|
||||
|
||||
/**
|
||||
* Get an instance of the Action. See above for why
|
||||
* the class is a singleton.
|
||||
*
|
||||
* @return the instance
|
||||
*/
|
||||
public static synchronized ExportCSVAction getInstance() {
|
||||
if (null == instance) {
|
||||
instance = new ExportCSVAction();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for the action.
|
||||
*/
|
||||
@NbBundle.Messages({"ExportCSV.title.text=Export selected rows to CSV"})
|
||||
private ExportCSVAction() {
|
||||
super(Bundle.ExportCSV_title_text());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks user to choose destination, then extracts content to destination
|
||||
* (recursing on directories).
|
||||
*
|
||||
* @param e The action event.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Collection<? extends Node> selectedNodes = Utilities.actionsGlobalContext().lookupAll(Node.class);
|
||||
saveNodesToCSV(selectedNodes, (Component)e.getSource());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the selected nodes to a CSV file
|
||||
*
|
||||
* @param nodesToExport the nodes to save
|
||||
* @param component
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"# {0} - Output file",
|
||||
"ExportCSV.saveNodesToCSV.fileExists=File {0} already exists",
|
||||
"ExportCSV.saveNodesToCSV.noCurrentCase=No open case available",
|
||||
"ExportCSV.saveNodesToCSV.empty=No data to export"})
|
||||
public static void saveNodesToCSV(Collection<? extends Node> nodesToExport, Component component) {
|
||||
|
||||
if (nodesToExport.isEmpty()) {
|
||||
MessageNotifyUtil.Message.info(Bundle.ExportCSV_saveNodesToCSV_empty());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Set up the file chooser with a default name and either the Export
|
||||
// folder or the last used folder.
|
||||
String fileName = getDefaultOutputFileName(nodesToExport.iterator().next().getParentNode());
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setCurrentDirectory(new File(getExportDirectory(Case.getCurrentCaseThrows())));
|
||||
fileChooser.setSelectedFile(new File(fileName));
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
|
||||
|
||||
int returnVal = fileChooser.showSaveDialog(component);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
|
||||
// Get the file name, appending .csv if necessary
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
|
||||
selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
|
||||
}
|
||||
|
||||
// Save the directory used for next time
|
||||
updateExportDirectory(selectedFile.getParent(), Case.getCurrentCaseThrows());
|
||||
|
||||
if (selectedFile.exists()) {
|
||||
logger.log(Level.SEVERE, "File {0} already exists", selectedFile.getAbsolutePath()); //NON-NLS
|
||||
MessageNotifyUtil.Message.info(Bundle.ExportCSV_saveNodesToCSV_fileExists(selectedFile));
|
||||
return;
|
||||
}
|
||||
|
||||
CSVWriter writer = new CSVWriter(nodesToExport, selectedFile);
|
||||
writer.execute();
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
JOptionPane.showMessageDialog(component, Bundle.ExportCSV_saveNodesToCSV_noCurrentCase());
|
||||
logger.log(Level.INFO, "Exception while getting open case.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default name for the CSV output.
|
||||
*
|
||||
* @param parent The parent node for the selected nodes
|
||||
*
|
||||
* @return the default name
|
||||
*/
|
||||
private static String getDefaultOutputFileName(Node parent) {
|
||||
String dateStr = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS", Calendar.getInstance());
|
||||
|
||||
if (parent != null) {
|
||||
// The first value in the property set is generally a reasonable name
|
||||
for (PropertySet set : parent.getPropertySets()) {
|
||||
for (Property<?> prop : set.getProperties()) {
|
||||
try {
|
||||
String parentName = prop.getValue().toString();
|
||||
|
||||
// Strip off the count (if present)
|
||||
parentName = parentName.replaceAll("\\([0-9]+\\)$", "");
|
||||
|
||||
// Strip out any invalid characters
|
||||
parentName = parentName.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||
|
||||
return parentName + " " + dateStr;
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
logger.log(Level.WARNING, "Failed to get property set value as string", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return DEFAULT_FILENAME + " " + dateStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the export directory path.
|
||||
*
|
||||
* @param openCase The current case.
|
||||
*
|
||||
* @return The export directory path.
|
||||
*/
|
||||
private static String getExportDirectory(Case openCase) {
|
||||
String caseExportPath = openCase.getExportDirectory();
|
||||
|
||||
if (userDefinedExportPath == null) {
|
||||
return caseExportPath;
|
||||
}
|
||||
|
||||
File file = new File(userDefinedExportPath);
|
||||
if (file.exists() == false || file.isDirectory() == false) {
|
||||
return caseExportPath;
|
||||
}
|
||||
|
||||
return userDefinedExportPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the default export directory. If the directory path matches the
|
||||
* case export directory, then the directory used will always match the
|
||||
* export directory of any given case. Otherwise, the path last used will be
|
||||
* saved.
|
||||
*
|
||||
* @param exportPath The export path.
|
||||
* @param openCase The current case.
|
||||
*/
|
||||
private static void updateExportDirectory(String exportPath, Case openCase) {
|
||||
if (exportPath.equalsIgnoreCase(openCase.getExportDirectory())) {
|
||||
userDefinedExportPath = null;
|
||||
} else {
|
||||
userDefinedExportPath = exportPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thread that does the actual extraction work
|
||||
*/
|
||||
private static class CSVWriter extends SwingWorker<Object, Void> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CSVWriter.class.getName());
|
||||
private ProgressHandle progress;
|
||||
|
||||
private final Collection<? extends Node> nodesToExport;
|
||||
private final File outputFile;
|
||||
|
||||
/**
|
||||
* Create an instance of the CSVWriter.
|
||||
*
|
||||
* @param extractionTasks List of file extraction tasks.
|
||||
*/
|
||||
CSVWriter(Collection<? extends Node> nodesToExport, File outputFile) {
|
||||
this.nodesToExport = nodesToExport;
|
||||
this.outputFile = outputFile;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"CSVWriter.progress.extracting=Exporting to CSV file",
|
||||
"CSVWriter.progress.cancelling=Cancelling"})
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
if (nodesToExport.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set up progress bar.
|
||||
final String displayName = Bundle.CSVWriter_progress_extracting();
|
||||
progress = ProgressHandle.createHandle(displayName, new Cancellable() {
|
||||
@Override
|
||||
public boolean cancel() {
|
||||
if (progress != null) {
|
||||
progress.setDisplayName(Bundle.CSVWriter_progress_cancelling());
|
||||
}
|
||||
return ExportCSVAction.CSVWriter.this.cancel(true);
|
||||
}
|
||||
});
|
||||
progress.start();
|
||||
progress.switchToIndeterminate();
|
||||
|
||||
try (BufferedWriter br = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), StandardCharsets.UTF_8))) {
|
||||
// Write BOM
|
||||
br.write('\ufeff');
|
||||
|
||||
// Write the header
|
||||
List<String> headers = new ArrayList<>();
|
||||
PropertySet[] sets = nodesToExport.iterator().next().getPropertySets();
|
||||
for(PropertySet set : sets) {
|
||||
for (Property<?> prop : set.getProperties()) {
|
||||
if ( ! columnsToSkip.contains(prop.getDisplayName())) {
|
||||
headers.add(prop.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
br.write(listToCSV(headers));
|
||||
|
||||
// Write each line
|
||||
Iterator<?> nodeIterator = nodesToExport.iterator();
|
||||
while (nodeIterator.hasNext()) {
|
||||
if (this.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Node node = (Node)nodeIterator.next();
|
||||
List<String> values = new ArrayList<>();
|
||||
sets = node.getPropertySets();
|
||||
for(PropertySet set : sets) {
|
||||
for (Property<?> prop : set.getProperties()) {
|
||||
if ( ! columnsToSkip.contains(prop.getDisplayName())) {
|
||||
values.add(escapeQuotes(prop.getValue().toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
br.write(listToCSV(values));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape any quotes in the string
|
||||
*
|
||||
* @param original
|
||||
*
|
||||
* @return the string with quotes escaped
|
||||
*/
|
||||
private String escapeQuotes(String original) {
|
||||
return original.replaceAll("\"", "\\\\\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert list of values to a comma separated string.
|
||||
*
|
||||
* @param values Values to convert
|
||||
*
|
||||
* @return values as CSV
|
||||
*/
|
||||
private String listToCSV(List<String> values) {
|
||||
return "\"" + String.join("\",\"", values) + "\"\n";
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"CSVWriter.done.notifyMsg.error=Error exporting to CSV file",
|
||||
"# {0} - Output file",
|
||||
"CSVWriter.done.notifyMsg.success=Wrote to {0}"})
|
||||
@Override
|
||||
protected void done() {
|
||||
boolean msgDisplayed = false;
|
||||
try {
|
||||
super.get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, "Fatal error during file extraction", ex); //NON-NLS
|
||||
MessageNotifyUtil.Message.info(Bundle.CSVWriter_done_notifyMsg_error());
|
||||
msgDisplayed = true;
|
||||
} catch (java.util.concurrent.CancellationException ex) {
|
||||
// catch and ignore if we were cancelled
|
||||
} finally {
|
||||
progress.finish();
|
||||
if (!this.isCancelled() && !msgDisplayed) {
|
||||
MessageNotifyUtil.Message.info(Bundle.CSVWriter_done_notifyMsg_success(outputFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ OptionsCategory_Name_InterestingItemDefinitions=Interesting Files
|
||||
OptionsCategory_Keywords_InterestingItemDefinitions=InterestingItemDefinitions
|
||||
InterestingItemsIdentifierIngestModule.moduleName=Interesting Files Identifier
|
||||
InterestingItemsIdentifierIngestModule.moduleDescription=Identifies interesting items as defined by interesting item rule sets.
|
||||
FilesSetPanel.interesting.title=Interesting Files Set
|
||||
FilesSetPanel.interesting.title=Interesting Files Set Rule
|
||||
FilesSetPanel.interesting.messages.filesSetsMustBeNamed=Interesting files sets must be named.
|
||||
FilesSetPanel.messages.filesSetsReservedName=You have chosen a name reserved by the software, please choose a different name.
|
||||
FilesSetPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files
|
||||
@ -31,13 +31,13 @@ FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *
|
||||
FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression.
|
||||
FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0}
|
||||
FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists.
|
||||
FilesSetRulePanel.pathSeparatorInfoLabel.text=Use / as path separator
|
||||
FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names
|
||||
FilesIdentifierIngestJobSettingsPanel.border.title=Select interesting files sets to enable during ingest:
|
||||
FilesSetRulePanel.jLabel1.text=Type:
|
||||
FilesSetRulePanel.interesting.jLabel5.text=Enter information about files that you want to find.
|
||||
FilesSetRulePanel.ingest.jLabel5.text=Enter information about files that you want to run ingest on.
|
||||
FilesSetRulePanel.nameCheck.text=Name:
|
||||
FilesSetRulePanel.pathCheck.text=Path Substring:
|
||||
FilesSetRulePanel.pathCheck.text=Folder Name:
|
||||
FilesSetRulePanel.filesRadioButton.text=Files
|
||||
FilesSetRulePanel.dirsRadioButton.text=Directories
|
||||
FilesSetDefsPanel.interesting.setsListLabel.text=Rule Sets:
|
||||
|
@ -37,6 +37,8 @@ FilesSetPanel.ingest.createNewFilter=Create/edit file ingest filters...
|
||||
FilesSetPanel.ingest.messages.filtersMustBeNamed=File ingest filters must be named.
|
||||
FilesSetPanel.rule.title=File Filter Rule
|
||||
FilesSetRulePanel.bytes=Bytes
|
||||
#{0} - regex
|
||||
FilesSetRulePanel.CommaInRegexWarning=Warning: Comma(s) in the file extension field will be interpreted as part of a regex and will not split the entry into multiple extensions (Entered: "{0}")
|
||||
FilesSetRulePanel.DaysIncludedEmptyError=Number of days included cannot be empty.
|
||||
FilesSetRulePanel.DaysIncludedInvalidError=Number of days included must be a positive integer.
|
||||
FilesSetRulePanel.gigaBytes=Gigabytes
|
||||
@ -60,7 +62,7 @@ OptionsCategory_Name_InterestingItemDefinitions=Interesting Files
|
||||
OptionsCategory_Keywords_InterestingItemDefinitions=InterestingItemDefinitions
|
||||
InterestingItemsIdentifierIngestModule.moduleName=Interesting Files Identifier
|
||||
InterestingItemsIdentifierIngestModule.moduleDescription=Identifies interesting items as defined by interesting item rule sets.
|
||||
FilesSetPanel.interesting.title=Interesting Files Set
|
||||
FilesSetPanel.interesting.title=Interesting Files Set Rule
|
||||
FilesSetPanel.interesting.messages.filesSetsMustBeNamed=Interesting files sets must be named.
|
||||
FilesSetPanel.messages.filesSetsReservedName=You have chosen a name reserved by the software, please choose a different name.
|
||||
FilesSetPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files
|
||||
@ -85,13 +87,13 @@ FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *
|
||||
FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression.
|
||||
FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0}
|
||||
FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists.
|
||||
FilesSetRulePanel.pathSeparatorInfoLabel.text=Use / as path separator
|
||||
FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names
|
||||
FilesIdentifierIngestJobSettingsPanel.border.title=Select interesting files sets to enable during ingest:
|
||||
FilesSetRulePanel.jLabel1.text=Type:
|
||||
FilesSetRulePanel.interesting.jLabel5.text=Enter information about files that you want to find.
|
||||
FilesSetRulePanel.ingest.jLabel5.text=Enter information about files that you want to run ingest on.
|
||||
FilesSetRulePanel.nameCheck.text=Name:
|
||||
FilesSetRulePanel.pathCheck.text=Path Substring:
|
||||
FilesSetRulePanel.pathCheck.text=Folder Name:
|
||||
FilesSetRulePanel.filesRadioButton.text=Files
|
||||
FilesSetRulePanel.dirsRadioButton.text=Directories
|
||||
FilesSetDefsPanel.interesting.setsListLabel.text=Rule Sets:
|
||||
|
@ -832,6 +832,7 @@
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new javax.swing.DefaultComboBoxModel<String>(new String[] {""})" type="code"/>
|
||||
</Property>
|
||||
|
@ -22,6 +22,8 @@ import java.awt.EventQueue;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -278,6 +280,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
//enable the new button
|
||||
FilesSetDefsPanel.this.newSetButton.setEnabled(canBeEnabled);
|
||||
FilesSetDefsPanel.this.importSetButton.setEnabled(canBeEnabled);
|
||||
|
||||
// Get the selected interesting files set and populate the set
|
||||
// components.
|
||||
FilesSet selectedSet = FilesSetDefsPanel.this.setsList.getSelectedValue();
|
||||
@ -294,14 +297,26 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
FilesSetDefsPanel.this.copySetButton.setEnabled(canBeEnabled);
|
||||
FilesSetDefsPanel.this.exportSetButton.setEnabled(true);
|
||||
// Populate the rule definitions list, sorted by name.
|
||||
TreeMap<String, FilesSet.Rule> rules = new TreeMap<>(selectedSet.getRules());
|
||||
rules.values().forEach((rule) -> {
|
||||
List<FilesSet.Rule> rules = new ArrayList<>(selectedSet.getRules().values());
|
||||
Collections.sort(rules, new Comparator<FilesSet.Rule>() {
|
||||
@Override
|
||||
public int compare(FilesSet.Rule rule1, FilesSet.Rule rule2) {
|
||||
return rule1.toString().compareTo(rule2.toString());
|
||||
}
|
||||
});
|
||||
rules.forEach((rule) -> {
|
||||
FilesSetDefsPanel.this.rulesListModel.addElement(rule);
|
||||
});
|
||||
// Select the first rule by default.
|
||||
if (!FilesSetDefsPanel.this.rulesListModel.isEmpty()) {
|
||||
FilesSetDefsPanel.this.rulesList.setSelectedIndex(0);
|
||||
}
|
||||
} else {
|
||||
// Disable the edit, delete, copy, and export buttons
|
||||
FilesSetDefsPanel.this.editSetButton.setEnabled(false);
|
||||
FilesSetDefsPanel.this.deleteSetButton.setEnabled(false);
|
||||
FilesSetDefsPanel.this.copySetButton.setEnabled(false);
|
||||
FilesSetDefsPanel.this.exportSetButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,6 +811,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(FilesSetDefsPanel.class, "FilesSetDefsPanel.jLabel7.text")); // NOI18N
|
||||
|
||||
mimeTypeComboBox.setBackground(new java.awt.Color(240, 240, 240));
|
||||
mimeTypeComboBox.setEditable(true);
|
||||
mimeTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(new String[] {""}));
|
||||
mimeTypeComboBox.setEnabled(false);
|
||||
mimeTypeComboBox.setMinimumSize(new java.awt.Dimension(0, 20));
|
||||
|
@ -57,7 +57,9 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
"FilesSetRulePanel.NoPathError=Path cannot be empty",
|
||||
"FilesSetRulePanel.DaysIncludedEmptyError=Number of days included cannot be empty.",
|
||||
"FilesSetRulePanel.DaysIncludedInvalidError=Number of days included must be a positive integer.",
|
||||
"FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)."
|
||||
"FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected).",
|
||||
"#{0} - regex",
|
||||
"FilesSetRulePanel.CommaInRegexWarning=Warning: Comma(s) in the file extension field will be interpreted as part of a regex and will not split the entry into multiple extensions (Entered: \"{0}\")",
|
||||
})
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -130,6 +132,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
this.setButtons(okButton, cancelButton);
|
||||
|
||||
updateNameTextFieldPrompt();
|
||||
setComponentsForSearchType();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -358,6 +361,16 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
return false;
|
||||
}
|
||||
if (this.nameRegexCheckbox.isSelected()) {
|
||||
|
||||
// If extension is also selected and the regex contains a comma, display a warning
|
||||
// since it is unclear whether the comma is part of a regex or is separating extensions.
|
||||
if (this.extensionRadioButton.isSelected() && this.nameTextField.getText().contains(",")) {
|
||||
NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
|
||||
Bundle.FilesSetRulePanel_CommaInRegexWarning(this.nameTextField.getText()),
|
||||
NotifyDescriptor.WARNING_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(notifyDesc);
|
||||
}
|
||||
|
||||
try {
|
||||
Pattern.compile(this.nameTextField.getText());
|
||||
} catch (PatternSyntaxException ex) {
|
||||
|
@ -48,18 +48,18 @@ import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JPanel;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.Services;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.ContentViewerTag;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagRegion;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagsUtility;
|
||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -731,6 +731,29 @@ class ReportHTML implements TableReportModule {
|
||||
logger.log(Level.SEVERE, "Output writer is null. Page was not initialized before writing.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all associated image tags.
|
||||
*
|
||||
* @param contentTags
|
||||
* @return
|
||||
*/
|
||||
private List<ImageTagRegion> getTaggedRegions(List<ContentTag> contentTags) {
|
||||
ArrayList<ImageTagRegion> tagRegions = new ArrayList<>();
|
||||
contentTags.forEach((contentTag) -> {
|
||||
try {
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = ContentViewerTagManager
|
||||
.getTag(contentTag, ImageTagRegion.class);
|
||||
if (contentViewerTag != null) {
|
||||
tagRegions.add(contentViewerTag.getDetails());
|
||||
}
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
logger.log(Level.WARNING, "Could not get content viewer tag "
|
||||
+ "from case db for content_tag with id %d", contentTag.getId());
|
||||
}
|
||||
});
|
||||
return tagRegions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the body of the thumbnails table.
|
||||
@ -770,13 +793,54 @@ class ReportHTML implements TableReportModule {
|
||||
}
|
||||
|
||||
AbstractFile file = (AbstractFile) content;
|
||||
List<ContentTag> contentTags = new ArrayList<>();
|
||||
|
||||
String thumbnailPath = null;
|
||||
String imageWithTagsFullPath = null;
|
||||
try {
|
||||
//Get content tags and all image tags
|
||||
contentTags = Case.getCurrentCase().getServices()
|
||||
.getTagsManager().getContentTagsByContent(file);
|
||||
List<ImageTagRegion> imageTags = getTaggedRegions(contentTags);
|
||||
|
||||
if(!imageTags.isEmpty()) {
|
||||
//Write the tags to the fullsize and thumbnail images
|
||||
BufferedImage fullImageWithTags = ImageTagsUtility.writeTags(file, imageTags, "png");
|
||||
|
||||
BufferedImage thumbnailImageWithTags = ImageTagsUtility.makeThumbnail(file,
|
||||
imageTags, ImageTagsUtility.IconSize.MEDIUM, "png");
|
||||
|
||||
String fileName = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(file.getName());
|
||||
|
||||
//Create paths in report to write tagged images
|
||||
File thumbnailImageWithTagsFile = Paths.get(thumbsPath, FilenameUtils.removeExtension(fileName) + ".png").toFile();
|
||||
String fullImageWithTagsPath = makeCustomUniqueFilePath(file, "thumbs_fullsize");
|
||||
fullImageWithTagsPath = FilenameUtils.removeExtension(fullImageWithTagsPath) + ".png";
|
||||
File fullImageWithTagsFile = Paths.get(fullImageWithTagsPath).toFile();
|
||||
|
||||
//Save images
|
||||
ImageIO.write(thumbnailImageWithTags, "png", thumbnailImageWithTagsFile);
|
||||
ImageIO.write(fullImageWithTags, "png", fullImageWithTagsFile);
|
||||
|
||||
thumbnailPath = THUMBS_REL_PATH + thumbnailImageWithTagsFile.getName();
|
||||
//Relative path
|
||||
imageWithTagsFullPath = fullImageWithTagsPath.substring(subPath.length());
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Could not get tags for file.", ex); //NON-NLS
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could make marked up thumbnail.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
// save copies of the orginal image and thumbnail image
|
||||
String thumbnailPath = prepareThumbnail(file);
|
||||
if(thumbnailPath == null) {
|
||||
thumbnailPath = prepareThumbnail(file);
|
||||
}
|
||||
|
||||
if (thumbnailPath == null) {
|
||||
continue;
|
||||
}
|
||||
String contentPath = saveContent(file, "thumbs_fullsize"); //NON-NLS
|
||||
String contentPath = saveContent(file, "original"); //NON-NLS
|
||||
String nameInImage;
|
||||
try {
|
||||
nameInImage = file.getUniquePath();
|
||||
@ -785,32 +849,27 @@ class ReportHTML implements TableReportModule {
|
||||
}
|
||||
|
||||
StringBuilder linkToThumbnail = new StringBuilder();
|
||||
linkToThumbnail.append("<div id='thumbnail_link'>");
|
||||
linkToThumbnail.append("<a href=\""); //NON-NLS
|
||||
linkToThumbnail.append(contentPath);
|
||||
linkToThumbnail.append("\" target=\"_top\">");
|
||||
linkToThumbnail.append("<img src=\"").append(thumbnailPath).append("\" title=\"").append(nameInImage).append("\"/>"); //NON-NLS
|
||||
linkToThumbnail.append("</a><br>"); //NON-NLS
|
||||
linkToThumbnail.append(file.getName()).append("<br>"); //NON-NLS
|
||||
|
||||
Services services = currentCase.getServices();
|
||||
TagsManager tagsManager = services.getTagsManager();
|
||||
try {
|
||||
List<ContentTag> tags = tagsManager.getContentTagsByContent(content);
|
||||
if (tags.size() > 0) {
|
||||
linkToThumbnail.append(NbBundle.getMessage(this.getClass(), "ReportHTML.thumbLink.tags"));
|
||||
}
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
ContentTag tag = tags.get(i);
|
||||
String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : "";
|
||||
linkToThumbnail.append(tag.getName().getDisplayName()).append(notableString);
|
||||
if (i != tags.size() - 1) {
|
||||
linkToThumbnail.append(", ");
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Could not find get tags for file.", ex); //NON-NLS
|
||||
linkToThumbnail.append("<div id='thumbnail_link'><a href=\"")
|
||||
.append((imageWithTagsFullPath != null) ? imageWithTagsFullPath : contentPath)
|
||||
.append("\" target=\"_top\"><img src=\"")
|
||||
.append(thumbnailPath).append("\" title=\"").append(nameInImage).append("\"/></a><br>") //NON-NLS
|
||||
.append(file.getName()).append("<br>"); //NON-NLS
|
||||
if(imageWithTagsFullPath != null) {
|
||||
linkToThumbnail.append("<a href=\"").append(contentPath).append("\" target=\"_top\">View Original</a><br>");
|
||||
}
|
||||
|
||||
if (!contentTags.isEmpty()) {
|
||||
linkToThumbnail.append(NbBundle.getMessage(this.getClass(), "ReportHTML.thumbLink.tags"));
|
||||
}
|
||||
for (int i = 0; i < contentTags.size(); i++) {
|
||||
ContentTag tag = contentTags.get(i);
|
||||
String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : "";
|
||||
linkToThumbnail.append(tag.getName().getDisplayName()).append(notableString);
|
||||
if (i != contentTags.size() - 1) {
|
||||
linkToThumbnail.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
linkToThumbnail.append("</div>");
|
||||
currentRow.add(linkToThumbnail.toString());
|
||||
|
||||
@ -839,17 +898,8 @@ class ReportHTML implements TableReportModule {
|
||||
|| file.getType() == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS
|
||||
|| file.getType() == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a local copy of the given file in the reports folder.
|
||||
*
|
||||
* @param file File to save
|
||||
* @param dirName Custom top-level folder to use to store the files in (tag
|
||||
* name, etc.)
|
||||
*
|
||||
* @return Path to where file was stored (relative to root of HTML folder)
|
||||
*/
|
||||
public String saveContent(AbstractFile file, String dirName) {
|
||||
|
||||
private String makeCustomUniqueFilePath(AbstractFile file, String dirName) {
|
||||
// clean up the dir name passed in
|
||||
String dirName2 = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(dirName);
|
||||
|
||||
@ -883,16 +933,32 @@ class ReportHTML implements TableReportModule {
|
||||
}
|
||||
localFilePath.append(File.separator);
|
||||
localFilePath.append(fileName);
|
||||
|
||||
return localFilePath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a local copy of the given file in the reports folder.
|
||||
*
|
||||
* @param file File to save
|
||||
* @param dirName Custom top-level folder to use to store the files in (tag
|
||||
* name, etc.)
|
||||
*
|
||||
* @return Path to where file was stored (relative to root of HTML folder)
|
||||
*/
|
||||
public String saveContent(AbstractFile file, String dirName) {
|
||||
|
||||
String localFilePath = makeCustomUniqueFilePath(file, dirName);
|
||||
|
||||
// If the local file doesn't already exist, create it now.
|
||||
// The existence check is necessary because it is possible to apply multiple tags with the same tagName to a file.
|
||||
File localFile = new File(localFilePath.toString());
|
||||
File localFile = new File(localFilePath);
|
||||
if (!localFile.exists()) {
|
||||
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||
}
|
||||
|
||||
// get the relative path
|
||||
return localFilePath.toString().substring(subPath.length());
|
||||
return localFilePath.substring(subPath.length());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,4 +120,13 @@ public final class TextTranslationService {
|
||||
public boolean hasProvider() {
|
||||
return selectedTranslator.isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hard limit for translation request sizes.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getMaxPayloadSize() {
|
||||
return selectedTranslator.get().getMaxPayloadSize();
|
||||
}
|
||||
}
|
||||
|
@ -56,4 +56,11 @@ public interface TextTranslator {
|
||||
* Save the settings as they have been modified in the component.
|
||||
*/
|
||||
void saveSettings();
|
||||
|
||||
/**
|
||||
* Returns the hard limit for translation request sizes.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int getMaxPayloadSize();
|
||||
}
|
||||
|
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 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.texttranslation.translators;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.Response;
|
||||
import java.awt.Component;
|
||||
import java.io.IOException;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.texttranslation.TextTranslator;
|
||||
import org.sleuthkit.autopsy.texttranslation.TranslationException;
|
||||
|
||||
/**
|
||||
* Translates text by making HTTP requests to Bing Translator. This requires a
|
||||
* valid subscription key for a Microsoft Azure account.
|
||||
*/
|
||||
@ServiceProvider(service = TextTranslator.class)
|
||||
public class BingTranslator implements TextTranslator {
|
||||
|
||||
//The target language follows the to= in the string below. You can include multiple target
|
||||
//languages separated by commas. A full list of supported languages is here:
|
||||
//https://docs.microsoft.com/en-us/azure/cognitive-services/translator/language-support
|
||||
private static final String BASE_URL = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=";
|
||||
private static final int MAX_STRING_LENGTH = 5000;
|
||||
private final BingTranslatorSettingsPanel settingsPanel;
|
||||
private final BingTranslatorSettings settings = new BingTranslatorSettings();
|
||||
// This sends messages to Microsoft.
|
||||
private final OkHttpClient CLIENT = new OkHttpClient();
|
||||
|
||||
/**
|
||||
* Create a Bing Translator
|
||||
*/
|
||||
public BingTranslator() {
|
||||
settingsPanel = new BingTranslatorSettingsPanel(settings.getAuthenticationKey(), settings.getTargetLanguageCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tranlationurl for the specified language code
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param languageCode language code for language to translate to
|
||||
*
|
||||
* @return a string representation of the url to request translation from
|
||||
*/
|
||||
static String getTranlatorUrl(String languageCode) {
|
||||
return BASE_URL + languageCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an input text to the JSON format required by Bing Translator,
|
||||
* posts it to Microsoft, and returns the JSON text response.
|
||||
*
|
||||
* @param string The input text to be translated.
|
||||
*
|
||||
* @return The translation response as a JSON string
|
||||
*
|
||||
* @throws IOException if the request could not be executed due to
|
||||
* cancellation, a connectivity problem or timeout.
|
||||
*/
|
||||
public String postTranslationRequest(String string) throws IOException {
|
||||
MediaType mediaType = MediaType.parse("application/json");
|
||||
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("Text", string);
|
||||
jsonArray.add(jsonObject);
|
||||
String bodyString = jsonArray.toString();
|
||||
|
||||
RequestBody body = RequestBody.create(mediaType,
|
||||
bodyString);
|
||||
Request request = new Request.Builder()
|
||||
.url(getTranlatorUrl(settings.getTargetLanguageCode())).post(body)
|
||||
.addHeader("Ocp-Apim-Subscription-Key", settings.getAuthenticationKey())
|
||||
.addHeader("Content-type", "application/json").build();
|
||||
Response response = CLIENT.newCall(request).execute();
|
||||
return response.body().string();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translate(String string) throws TranslationException {
|
||||
if (settings.getAuthenticationKey() == null || settings.getAuthenticationKey().isEmpty()) {
|
||||
throw new TranslationException("Bing Translator has not been configured, authentication key needs to be specified");
|
||||
}
|
||||
String toTranslate = string.trim();
|
||||
//Translates some text into English, without specifying the source langauge.
|
||||
|
||||
//Google Translate required us to replace (\r\n|\n) with <br />
|
||||
//but Bing Translator doesn not have that requirement.
|
||||
//The free account has a maximum file size. If you have a paid account,
|
||||
//you probably still want to limit file size to prevent accidentally
|
||||
//translating very large documents.
|
||||
if (toTranslate.length() > MAX_STRING_LENGTH) {
|
||||
toTranslate = toTranslate.substring(0, MAX_STRING_LENGTH);
|
||||
}
|
||||
|
||||
try {
|
||||
String response = postTranslationRequest(toTranslate);
|
||||
return parseJSONResponse(response);
|
||||
} catch (IOException | TranslationException ex) {
|
||||
throw new TranslationException("Exception while attempting to translate using BingTranslator", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Messages({"BingTranslator.name.text=Bing Translator"})
|
||||
@Override
|
||||
public String getName() {
|
||||
return Bundle.BingTranslator_name_text();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent() {
|
||||
return settingsPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
settings.setAuthenticationKey(settingsPanel.getAuthenticationKey());
|
||||
settings.setTargetLanguageCode(settingsPanel.getTargetLanguageCode());
|
||||
settings.saveSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the response to get the translated text
|
||||
*
|
||||
* @param json_text the json which was received as a response to a
|
||||
* translation request
|
||||
*
|
||||
* @return the translated text
|
||||
*
|
||||
* @throws TranslationException
|
||||
*/
|
||||
private String parseJSONResponse(String json_text) throws TranslationException {
|
||||
/*
|
||||
* Here is an example of the text we get from Bing when input is "gato",
|
||||
* the Spanish word for cat: [ { "detectedLanguage": { "language": "es",
|
||||
* "score": 1.0 }, "translations": [ { "text": "cat", "to": "en" } ] } ]
|
||||
*/
|
||||
JsonParser parser = new JsonParser();
|
||||
try {
|
||||
JsonArray responses = parser.parse(json_text).getAsJsonArray();
|
||||
//As far as I know, there's always exactly one item in the array.
|
||||
JsonObject response0 = responses.get(0).getAsJsonObject();
|
||||
JsonArray translations = response0.getAsJsonArray("translations");
|
||||
JsonObject translation0 = translations.get(0).getAsJsonObject();
|
||||
return translation0.get("text").getAsString();
|
||||
} catch (IllegalStateException | ClassCastException | NullPointerException | IndexOutOfBoundsException e) {
|
||||
throw new TranslationException("JSON text does not match Bing Translator scheme: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPayloadSize() {
|
||||
return MAX_STRING_LENGTH;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user