fix accout type icons in the DirectoryTree

This commit is contained in:
millmanorama 2018-02-26 18:12:26 +01:00
parent 14a55af19c
commit 291c33dc63
17 changed files with 83 additions and 79 deletions

View File

@ -52,7 +52,7 @@ final class AccountDeviceInstanceNode extends AbstractNode {
this.account = accountDeviceInstanceKey.getAccountDeviceInstance().getAccount(); this.account = accountDeviceInstanceKey.getAccountDeviceInstance().getAccount();
setName(account.getTypeSpecificID()); setName(account.getTypeSpecificID());
setDisplayName(getName()); setDisplayName(getName());
setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/" + Utils.getIconFileName(account.getAccountType())); setIconBaseWithExtension(Utils.getIconFilePath(account.getAccountType()));
} }
AccountDeviceInstance getAccountDeviceInstance() { AccountDeviceInstance getAccountDeviceInstance() {

View File

@ -168,8 +168,7 @@ final class CommunicationsGraph extends mxGraph {
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID()); scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5)); scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5));
scopes.put("iconFileName", CommunicationsGraph.class.getResource("/org/sleuthkit/autopsy/communications/images/" scopes.put("iconFileName", CommunicationsGraph.class.getResource( Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
+ Utils.getIconFileName(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey)); scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey));
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL); scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell)); scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell));
@ -194,8 +193,7 @@ final class CommunicationsGraph extends mxGraph {
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID()); scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
scopes.put("size", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5)); scopes.put("size", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5));
scopes.put("iconFileName", CommunicationsGraph.class.getResource("/org/sleuthkit/autopsy/communications/images/" scopes.put("iconFileName", CommunicationsGraph.class.getResource( Utils.getIconFilePath(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
+ Utils.getIconFileName(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey)); scopes.put("pinned", pinnedAccountModel.isAccountPinned(adiKey));
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL); scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell)); scopes.put("locked", lockedVertexModel.isVertexLocked((mxCell) cell));
@ -310,7 +308,7 @@ final class CommunicationsGraph extends mxGraph {
Set<Long> accountIDs = relatedAccounts.keySet(); Set<Long> accountIDs = relatedAccounts.keySet();
Map<Relationship.RelationshipKey, Long> relationshipCounts = commsManager.getRelationshipCounts(accountIDs, currentFilter); Map<Relationship.RelationshipKey, Long> relationshipCounts = commsManager.getRelationshipCountsBetween(accountIDs, currentFilter);
int total = relationshipCounts.size(); int total = relationshipCounts.size();
int k = 0; int k = 0;

View File

@ -244,7 +244,7 @@
<Component class="javax.swing.JLabel" name="devicesLabel"> <Component class="javax.swing.JLabel" name="devicesLabel">
<Properties> <Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/image.png"/> <Image iconType="3" name="/org/sleuthkit/autopsy/images/image.png"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.devicesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>

View File

@ -201,8 +201,7 @@ final public class FiltersPanel extends JPanel {
accountTypeMap.computeIfAbsent(type, t -> { accountTypeMap.computeIfAbsent(type, t -> {
final JCheckBox jCheckBox = new JCheckBox( final JCheckBox jCheckBox = new JCheckBox(
"<html><table cellpadding=0><tr><td><img src=\"" "<html><table cellpadding=0><tr><td><img src=\""
+ FiltersPanel.class.getResource("/org/sleuthkit/autopsy/communications/images/" + FiltersPanel.class.getResource(Utils.getIconFilePath(type))
+ Utils.getIconFileName(type))
+ "\"/></td><td width=" + 3 + "><td>" + type.getDisplayName() + "</td></tr></table></html>", + "\"/></td><td width=" + 3 + "><td>" + type.getDisplayName() + "</td></tr></table></html>",
true true
); );
@ -327,7 +326,7 @@ final public class FiltersPanel extends JPanel {
} }
}); });
devicesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/image.png"))); // NOI18N 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 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.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllDevicesButton.text")); // NOI18N

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.communications;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.Account;
/** /**
@ -37,36 +38,12 @@ class Utils {
} }
/** /**
* The file name of the icon for the given Account Type. Will not include * Get the path of the icon for the given Account Type.
* the path but will include the extension.
* *
* @return The file name of the icon for the given Account Type. * @return The path of the icon for the given Account Type.
*/ */
static final String getIconFileName(Account.Type type) { static final String getIconFilePath(Account.Type type) {
if (type.equals(Account.Type.CREDIT_CARD)) { return Accounts.getIconFilePath(type);
return "credit-card.png";
} else if (type.equals(Account.Type.DEVICE)) {
return "image.png";
} else if (type.equals(Account.Type.EMAIL)) {
return "email.png";
} else if (type.equals(Account.Type.FACEBOOK)) {
return "facebook.png";
} else if (type.equals(Account.Type.INSTAGRAM)) {
return "instagram.png";
} else if (type.equals(Account.Type.MESSAGING_APP)) {
return "messaging.png";
} else if (type.equals(Account.Type.PHONE)) {
return "phone.png";
} else if (type.equals(Account.Type.TWITTER)) {
return "twitter.png";
} else if (type.equals(Account.Type.WEBSITE)) {
return "web-file.png";
} else if (type.equals(Account.Type.WHATSAPP)) {
return "WhatsApp.png";
} else {
//there could be a default icon instead...
throw new IllegalArgumentException("Unknown Account.Type: " + type.getTypeName());
}
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2017 Basis Technology Corp. * Copyright 2011-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -54,7 +54,6 @@ import org.openide.nodes.Node;
import org.openide.nodes.NodeNotFoundException; import org.openide.nodes.NodeNotFoundException;
import org.openide.nodes.NodeOp; import org.openide.nodes.NodeOp;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.Utilities; import org.openide.util.Utilities;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
@ -73,7 +72,6 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountFileInstance;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -89,6 +87,7 @@ import org.sleuthkit.datamodel.TskData.DbType;
final public class Accounts implements AutopsyVisitableItem { final public class Accounts implements AutopsyVisitableItem {
private static final Logger LOGGER = Logger.getLogger(Accounts.class.getName()); private static final Logger LOGGER = Logger.getLogger(Accounts.class.getName());
private static final String iconBasePath = "/org/sleuthkit/autopsy/images/"; //NON-NLS
@NbBundle.Messages("AccountsRootNode.name=Accounts") @NbBundle.Messages("AccountsRootNode.name=Accounts")
final public static String NAME = Bundle.AccountsRootNode_name(); final public static String NAME = Bundle.AccountsRootNode_name();
@ -126,7 +125,7 @@ final public class Accounts implements AutopsyVisitableItem {
* results from db queries. * results from db queries.
* *
* @return A clause that will or will not filter out rejected artifacts * @return A clause that will or will not filter out rejected artifacts
* based on the state of showRejected. * based on the state of showRejected.
*/ */
private String getRejectedArtifactFilterClause() { private String getRejectedArtifactFilterClause() {
return showRejected ? " " : " AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() + " "; //NON-NLS return showRejected ? " " : " AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() + " "; //NON-NLS
@ -137,7 +136,7 @@ final public class Accounts implements AutopsyVisitableItem {
* or off. * or off.
* *
* @return An Action that will toggle whether rejected artifacts are shown * @return An Action that will toggle whether rejected artifacts are shown
* in the tree rooted by this Accounts instance. * in the tree rooted by this Accounts instance.
*/ */
public Action newToggleShowRejectedAction() { public Action newToggleShowRejectedAction() {
return new ToggleShowRejected(); return new ToggleShowRejected();
@ -225,8 +224,8 @@ final public class Accounts implements AutopsyVisitableItem {
private class AccountTypeFactory extends ObservingChildren<String> { private class AccountTypeFactory extends ObservingChildren<String> {
/* /*
* The pcl is in this class because it has the easiest mechanisms to * The pcl is in this class because it has the easiest mechanisms to add
* add and remove itself during its life cycles. * and remove itself during its life cycles.
*/ */
private final PropertyChangeListener pcl = new PropertyChangeListener() { private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override @Override
@ -310,23 +309,21 @@ final public class Accounts implements AutopsyVisitableItem {
} }
@Override @Override
protected Node[] createNodesForKey(String key) { protected Node[] createNodesForKey(String acountTypeName) {
String accountType = key; if (Account.Type.CREDIT_CARD.getTypeName().equals(acountTypeName)) {
if (accountType.equals(Account.Type.CREDIT_CARD.getTypeName())) {
return new Node[]{new CreditCardNumberAccountTypeNode()}; return new Node[]{new CreditCardNumberAccountTypeNode()};
} else { } else {
String accountTypeDisplayname;
try { try {
accountTypeDisplayname = skCase.getCommunicationsManager().getAccountType(accountType).getDisplayName(); Account.Type accountType = skCase.getCommunicationsManager().getAccountType(acountTypeName);
return new Node[]{new DefaultAccountTypeNode(accountType)};
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error getting display name for account type. ", ex); LOGGER.log(Level.SEVERE, "Error getting display name for account type. ", ex);
accountTypeDisplayname = accountType;
} }
return new Node[]{new DefaultAccountTypeNode(key, accountTypeDisplayname)}; return new Node[]{};
} }
} }
@Override @Override
@ -350,10 +347,10 @@ final public class Accounts implements AutopsyVisitableItem {
final private class DefaultAccountFactory extends ObservingChildren<Long> { final private class DefaultAccountFactory extends ObservingChildren<Long> {
private final String accountTypeName; private final Account.Type accountType;
private DefaultAccountFactory(String accountTypeName) { private DefaultAccountFactory(Account.Type accountType) {
this.accountTypeName = accountTypeName; this.accountType = accountType;
} }
private final PropertyChangeListener pcl = new PropertyChangeListener() { private final PropertyChangeListener pcl = new PropertyChangeListener() {
@ -424,13 +421,13 @@ final public class Accounts implements AutopsyVisitableItem {
@Override @Override
protected boolean createKeys(List<Long> list) { protected boolean createKeys(List<Long> list) {
String query String query =
= "SELECT blackboard_artifacts.artifact_id " //NON-NLS "SELECT blackboard_artifacts.artifact_id " //NON-NLS
+ " FROM blackboard_artifacts " //NON-NLS + " FROM blackboard_artifacts " //NON-NLS
+ " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS
+ " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() //NON-NLS + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() //NON-NLS
+ " AND blackboard_attributes.value_text = '" + accountTypeName + "'" //NON-NLS + " AND blackboard_attributes.value_text = '" + accountType.getTypeName() + "'" //NON-NLS
+ getRejectedArtifactFilterClause(); //NON-NLS + getRejectedArtifactFilterClause(); //NON-NLS
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
ResultSet rs = results.getResultSet();) { ResultSet rs = results.getResultSet();) {
@ -473,10 +470,10 @@ final public class Accounts implements AutopsyVisitableItem {
*/ */
final public class DefaultAccountTypeNode extends DisplayableItemNode { final public class DefaultAccountTypeNode extends DisplayableItemNode {
private DefaultAccountTypeNode(String accountTypeName, String accountTypeDisplayName) { private DefaultAccountTypeNode(Account.Type accountType) {
super(Children.create(new DefaultAccountFactory(accountTypeName), true), Lookups.singleton(accountTypeDisplayName)); super(Children.create(new DefaultAccountFactory(accountType), true), Lookups.singleton(accountType));
setName(accountTypeDisplayName); setName(accountType.getDisplayName());
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/credit-cards.png"); //NON-NLS this.setIconBaseWithExtension(getIconFilePath(accountType)); //NON-NLS
} }
@Override @Override
@ -1161,13 +1158,13 @@ final public class Accounts implements AutopsyVisitableItem {
* take the result of a group_concat SQLite operation and split it into a * take the result of a group_concat SQLite operation and split it into a
* set of X using the mapper to to convert from string to X * set of X using the mapper to to convert from string to X
* *
* @param <X> the type of elements to return * @param <X> the type of elements to return
* @param groupConcat a string containing the group_concat result ( a comma * @param groupConcat a string containing the group_concat result ( a comma
* separated list) * separated list)
* @param mapper a function from String to X * @param mapper a function from String to X
* *
* @return a Set of X, each element mapped from one element of the original * @return a Set of X, each element mapped from one element of the original
* comma delimited string * comma delimited string
*/ */
static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) { static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
return StringUtils.isBlank(groupConcat) ? Collections.emptyList() return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
@ -1187,8 +1184,8 @@ final public class Accounts implements AutopsyVisitableItem {
/** /**
* Constructor * Constructor
* *
* @param key The FileWithCCN that backs this node. * @param key The FileWithCCN that backs this node.
* @param content The Content object the key represents. * @param content The Content object the key represents.
* @param lookupContents The contents of this Node's lookup. It should * @param lookupContents The contents of this Node's lookup. It should
* contain the content object and the account artifacts. * contain the content object and the account artifacts.
*/ */
@ -1465,11 +1462,11 @@ final public class Accounts implements AutopsyVisitableItem {
} }
return sheet; return sheet;
} }
private void updateSheet() { private void updateSheet() {
this.setSheet(createSheet()); this.setSheet(createSheet());
} }
} }
/** /**
@ -1601,7 +1598,7 @@ final public class Accounts implements AutopsyVisitableItem {
super(artifact, "org/sleuthkit/autopsy/images/credit-card.png"); //NON-NLS super(artifact, "org/sleuthkit/autopsy/images/credit-card.png"); //NON-NLS
this.artifact = artifact; this.artifact = artifact;
setName("" + this.artifact.getArtifactID()); setName("" + this.artifact.getArtifactID());
reviewStatusBus.register(this); reviewStatusBus.register(this);
} }
@ -1628,13 +1625,13 @@ final public class Accounts implements AutopsyVisitableItem {
Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(), Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
Bundle.Accounts_FileWithCCNNode_noDescription(), Bundle.Accounts_FileWithCCNNode_noDescription(),
artifact.getReviewStatus().getDisplayName())); artifact.getReviewStatus().getDisplayName()));
return sheet; return sheet;
} }
@Subscribe @Subscribe
void handleReviewStatusChange(ReviewStatusChangeEvent event) { void handleReviewStatusChange(ReviewStatusChangeEvent event) {
// Update the node if event includes this artifact // Update the node if event includes this artifact
event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> { event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
return _item; return _item;
@ -1642,11 +1639,11 @@ final public class Accounts implements AutopsyVisitableItem {
updateSheet(); updateSheet();
}); });
} }
private void updateSheet() { private void updateSheet() {
this.setSheet(createSheet()); this.setSheet(createSheet());
} }
} }
private final class ToggleShowRejected extends AbstractAction { private final class ToggleShowRejected extends AbstractAction {
@ -1755,14 +1752,47 @@ final public class Accounts implements AutopsyVisitableItem {
} }
} }
private class ReviewStatusChangeEvent { static private class ReviewStatusChangeEvent {
Collection<? extends BlackboardArtifact> artifacts; Collection<? extends BlackboardArtifact> artifacts;
BlackboardArtifact.ReviewStatus newReviewStatus; BlackboardArtifact.ReviewStatus newReviewStatus;
public ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) { ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
this.artifacts = artifacts; this.artifacts = artifacts;
this.newReviewStatus = newReviewStatus; this.newReviewStatus = newReviewStatus;
} }
} }
/**
* Get the path of the icon for the given Account Type.
*
* @return The path of the icon for the given Account Type.
*/
public static String getIconFilePath(Account.Type type) {
if (type.equals(Account.Type.CREDIT_CARD)) {
return iconBasePath + "credit-card.png";
} else if (type.equals(Account.Type.DEVICE)) {
return iconBasePath + "image.png";
} else if (type.equals(Account.Type.EMAIL)) {
return iconBasePath + "email.png";
} else if (type.equals(Account.Type.FACEBOOK)) {
return iconBasePath + "facebook.png";
} else if (type.equals(Account.Type.INSTAGRAM)) {
return iconBasePath + "instagram.png";
} else if (type.equals(Account.Type.MESSAGING_APP)) {
return iconBasePath + "messaging.png";
} else if (type.equals(Account.Type.PHONE)) {
return iconBasePath + "phone.png";
} else if (type.equals(Account.Type.TWITTER)) {
return iconBasePath + "twitter.png";
} else if (type.equals(Account.Type.WEBSITE)) {
return iconBasePath + "web-file.png";
} else if (type.equals(Account.Type.WHATSAPP)) {
return iconBasePath + "WhatsApp.png";
} else {
//there could be a default icon instead...
throw new IllegalArgumentException("Unknown Account.Type: " + type.getTypeName());
}
}
} }

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 710 B

After

Width:  |  Height:  |  Size: 710 B

View File

Before

Width:  |  Height:  |  Size: 541 B

After

Width:  |  Height:  |  Size: 541 B

View File

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 804 B

View File

Before

Width:  |  Height:  |  Size: 829 B

After

Width:  |  Height:  |  Size: 829 B

View File

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 488 B

View File

Before

Width:  |  Height:  |  Size: 656 B

After

Width:  |  Height:  |  Size: 656 B