Jakub Niedermertl has uploaded a new change for review.

Change subject: VM Icons - editor
......................................................................

VM Icons - editor

Change-Id: Ibd5e8c120282e35d5940a66286d600b128c57753
Signed-off-by: Jakub Niedermertl <jnied...@redhat.com>
---
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/OsQueryParameters.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationTemplates.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/CommonGinUiBinderWidgets.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/HasAccess.java
A 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/CompositeHandlerRegistration.java
A 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.java
A 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.ui.xml
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/TabName.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/IconWithDefault.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconValidation.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconWithDefaultValidation.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/ValidationResult.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
20 files changed, 830 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/85/37985/1

diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java
index bc9d9a8..c02e05e 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java
@@ -34,6 +34,7 @@
     private boolean copyTemplatePermissions;
     private boolean applyChangesLater;
     private boolean updateNuma;
+    // TODO jakub add private String vmIcon;
 
     /*
      * This parameter is needed at update to make sure that when we get a null 
watchdog from rest-api it is not meant to
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/OsQueryParameters.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/OsQueryParameters.java
index 4a807f3..0dab93a 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/OsQueryParameters.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/OsQueryParameters.java
@@ -57,5 +57,6 @@
         GetOsNames,
         GetOsArchitectures,
         GetDefaultOSes
+        // TODO jakub add 'GetOsIcons'
     }
 }
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
index 6ede749..7123c41 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
@@ -748,6 +748,27 @@
     @DefaultStringValue("Clone Name")
     String clonedVmName();
 
+    @DefaultStringValue("Icon")
+    String iconTabVmPopup();
+
+    @DefaultStringValue("New Icon")
+    String newIconVmPopup();
+
+    @DefaultStringValue("Current Icon")
+    String currentIconVmPopup();
+
+    @DefaultStringValue("Upload")
+    String uploadIconVmPopup();
+
+    @DefaultStringValue("Use default")
+    String useDefaultIconVmPopup();
+
+    @DefaultStringValue("Discard changes")
+    String discardChangesIconVmPopup();
+
+    @DefaultStringValue("Icons limitations: max dimensions: width 150px, 
heigth 120px; max size 24kB; supported formats: jpg, png, gif")
+    String iconLimitationsIconVmPopup();
+
     // Permissions
     @DefaultStringValue("Inherited Permission")
     String inheritedPermission();
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationTemplates.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationTemplates.java
index fb94750..f054bcd 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationTemplates.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationTemplates.java
@@ -47,9 +47,15 @@
     @Template("<ul style='margin-top:0'>{0}</ul>")
     SafeHtml unsignedList(SafeHtml list);
 
+    @Template("<ul>{0}</ul>")
+    SafeHtml unorderedList(SafeHtml items);
+
     @Template("<li>{0}</li>")
     SafeHtml listItem(SafeHtml item);
 
+    @Template("<li>{0}</li>")
+    SafeHtml listItem(String item);
+
     @Template("{0} <sub>{1}</sub>")
     SafeHtml sub(String main, String sub);
 
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/CommonGinUiBinderWidgets.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/CommonGinUiBinderWidgets.java
index 0d0c7ed..19f68cb 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/CommonGinUiBinderWidgets.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/CommonGinUiBinderWidgets.java
@@ -1,25 +1,29 @@
 package org.ovirt.engine.ui.common.gin;
 
 import com.google.gwt.inject.client.Ginjector;
+import org.ovirt.engine.ui.common.widget.editor.IconEditorWidget;
 import 
org.ovirt.engine.ui.common.widget.uicommon.popup.vm.SerialNumberPolicyWidget;
 
 /**
  * Ginjector extension containing views that make use of the GWTP GinUiBinder.
  *
  * Every view that makes use of GIN dependency injection and is to be embedded 
in a .ui.xml file --ex:
+ * <pre>
  * <code>
- *     <w:MyWidget />
+ *     &lt;w:MyWidget />
  *
  *     public class MyWidget {
- *         @Inject
+ *         {@literal @}Inject
  *         public MyWidget(ApplicationResources resources, MyOtherDependency 
dep) {
  *             // ...
  *         }
  *     }
  * </code>
+ * </pre>
  *
  * Must be registered in this interface.
  */
 public interface CommonGinUiBinderWidgets extends Ginjector {
     SerialNumberPolicyWidget getSerialNumberPolicyWidget();
+    IconEditorWidget getIconEditorWidget();
 }
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/HasAccess.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/HasAccess.java
index df4eb9b..71512b7 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/HasAccess.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/HasAccess.java
@@ -2,6 +2,10 @@
 
 /**
  * Widgets that implement this interface have a user access policy associated 
with them.
+ * <p>
+ *     Inaccessible widgets should be hidden. Usually using
+ *     {@link com.google.gwt.user.client.ui.Widget#setVisible(boolean)}
+ * </p>
  */
 public interface HasAccess {
 
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/CompositeHandlerRegistration.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/CompositeHandlerRegistration.java
new file mode 100644
index 0000000..fcc8b6d
--- /dev/null
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/CompositeHandlerRegistration.java
@@ -0,0 +1,26 @@
+package org.ovirt.engine.ui.common.widget.editor;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class CompositeHandlerRegistration implements HandlerRegistration {
+
+    private final List<HandlerRegistration> registrations;
+
+    private CompositeHandlerRegistration(List<HandlerRegistration> 
registrations) {
+        this.registrations = registrations;
+    }
+
+    public static CompositeHandlerRegistration of(HandlerRegistration... 
registrations) {
+        return new CompositeHandlerRegistration(Arrays.asList(registrations));
+    }
+
+    @Override
+    public void removeHandler() {
+        for(HandlerRegistration registration : registrations) {
+            registration.removeHandler();
+        }
+    }
+}
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.java
new file mode 100644
index 0000000..04dd68f
--- /dev/null
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.java
@@ -0,0 +1,349 @@
+package org.ovirt.engine.ui.common.widget.editor;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.editor.client.LeafValueEditor;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.resources.client.CssResource;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.uibinder.client.UiHandler;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FileUpload;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.inject.Inject;
+import org.ovirt.engine.ui.common.CommonApplicationConstants;
+import org.ovirt.engine.ui.common.CommonApplicationResources;
+import org.ovirt.engine.ui.common.CommonApplicationTemplates;
+import org.ovirt.engine.ui.common.editor.UiCommonEditor;
+import org.ovirt.engine.ui.common.widget.AbstractValidatedWidget;
+import org.ovirt.engine.ui.common.widget.dialog.InfoIcon;
+import org.ovirt.engine.ui.uicommonweb.models.vms.IconWithDefault;
+import org.ovirt.engine.ui.uicommonweb.validation.IconValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.ValidationResult;
+
+import java.util.List;
+
+/**
+ * Icon editor. It allows to set custom icon to VM-like entities.
+ */
+public class IconEditorWidget extends AbstractValidatedWidget
+        implements LeafValueEditor<IconWithDefault>,
+                   HasValueChangeHandlers<IconWithDefault>,
+                   UiCommonEditor<IconWithDefault> {
+
+    interface ViewUiBinder extends UiBinder<HTMLPanel, IconEditorWidget> {
+        ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
+    }
+
+    protected interface Style extends CssResource {
+        String grey();
+        String iconImageDisabled();
+    }
+
+    @UiField
+    protected Style style;
+
+    @UiField
+    protected Image image;
+
+    @UiField
+    protected Button uploadButton;
+
+    @UiField(provided = true)
+    protected InfoIcon uploadInfoIcon;
+
+    @UiField
+    protected FileUpload fileUpload;
+
+    @UiField
+    protected Button defaultButton;
+
+    @UiField
+    protected HTML errorMessageHtml;
+
+    protected final CommonApplicationTemplates templates;
+
+    /**
+     * current value, the visible image <br/>
+     * in dataUri format
+     */
+    private String icon;
+
+    /**
+     * default value (given by OS of VM) <br/>
+     * in dataUri format
+     */
+    private String defaultIcon;
+
+    /**
+     * relates to {@link com.google.gwt.user.client.ui.HasEnabled} 
implementation
+     */
+    private boolean enabled;
+
+    /**
+     * relates to {@link org.ovirt.engine.ui.common.widget.HasAccess} 
implementation
+     */
+    private boolean accessible;
+
+    @Inject
+    public IconEditorWidget(CommonApplicationConstants constants,
+                            CommonApplicationTemplates templates,
+                            CommonApplicationResources resources) {
+        this.templates = templates;
+        uploadInfoIcon = new InfoIcon(
+                
SafeHtmlUtils.fromTrustedString(constants.iconLimitationsIconVmPopup()), 
resources);
+        initWidget(ViewUiBinder.uiBinder.createAndBindUi(this));
+        fileUpload.getElement().setAttribute("accept", 
"image/gif,image/jpeg,image/png"); //$NON-NLS-1$ //$NON-NLS-2$
+        fileUpload.addChangeHandler(new ChangeHandler() {
+            @Override
+            public void onChange(ChangeEvent event) {
+                IconEditorWidget.this.readUploadedIconFile();
+            }
+        });
+        fileUpload.getElement().setTabIndex(-1); // can be moved to *.ui.xml 
file in form of attribute `tabIndex="-1"` since GWT 2.7.0
+
+        KeyPressHandler preventEnterKeyPressHandler = 
createPreventEnterKeyPressHandler();
+        uploadButton.addKeyPressHandler(preventEnterKeyPressHandler);
+        defaultButton.addKeyPressHandler(preventEnterKeyPressHandler);
+
+        setEnabled(true);
+        setAccessible(true);
+    }
+
+    private KeyPressHandler createPreventEnterKeyPressHandler() {
+        return new KeyPressHandler() {
+            @Override
+            public void onKeyPress(KeyPressEvent event) {
+                if (!event.isAnyModifierKeyDown()
+                        && event.getNativeEvent().getKeyCode() == 
KeyCodes.KEY_ENTER
+                        && event.getUnicodeCharCode() == 0) {
+                    event.preventDefault();
+                }
+            }
+        };
+    }
+
+    @Override
+    public void setValue(IconWithDefault value) {
+        setIcon(value.getIcon());
+        defaultIcon = value.getDefaultIcon();
+    }
+
+    @Override
+    public IconWithDefault getValue() {
+        return new IconWithDefault(icon, defaultIcon);
+    }
+
+    @Override
+    protected Widget getValidatedWidget() {
+        return this;
+    }
+
+    @UiHandler("uploadButton")
+    void onUploadIconButton(ClickEvent event) {
+        clickElement(fileUpload.getElement());
+    }
+
+    @UiHandler("defaultButton")
+    void onDefaultIconButton(ClickEvent event) {
+        setIcon(defaultIcon);
+    }
+
+    /**
+     * There is FileUpload#click() method since GWT 2.7.0.
+     */
+    native void clickElement(Element element) /*-{
+        element.click();
+    }-*/;
+
+    protected void setIcon(String icon) {
+        final String oldIcon = this.icon;
+        this.icon = icon;
+        final ValidationResult validation = (new 
IconValidation()).validate(icon);
+        updateErrorIconLabel(validation);
+        image.getElement().setAttribute("src", icon); //$NON-NLS-1$
+        ValueChangeEvent.fireIfNotEqual(this,
+                new IconWithDefault(oldIcon, defaultIcon),
+                new IconWithDefault(icon, defaultIcon));
+    }
+
+    private void updateErrorIconLabel(ValidationResult validation) {
+        if (!validation.getSuccess() && validation.getReasons().isEmpty()) {
+            throw new IllegalArgumentException("Unsuccessful validation 
without any reason not allowed."); //$NON-NLS-1$
+        }
+        updateErrorIconLabel(validation.getReasons());
+    }
+
+    private void updateErrorIconLabel(List<String> reasons) {
+        if (reasons.isEmpty()) {
+            errorMessageHtml.setHTML(SafeHtmlUtils.EMPTY_SAFE_HTML);
+        } else {
+            final SafeHtml htmlReasons = toUnorderedList(reasons);
+            errorMessageHtml.setHTML(htmlReasons);
+        }
+    }
+
+    private SafeHtml toUnorderedList(List<String> stringItems) {
+        SafeHtmlBuilder builder = new SafeHtmlBuilder();
+        for (String stringItem : stringItems) {
+            builder.append(templates.listItem(stringItem));
+        }
+        return templates.unorderedList(builder.toSafeHtml());
+    }
+
+    native void readUploadedIconFile() /*-{
+        var inputFileElement = 
th...@org.ovirt.engine.ui.common.widget.editor.IconEditorWidget::fileuplo...@com.google.gwt.user.client.ui.FileUpload::getElement()();
+        var self = this;
+        var javaCallback = $entry(function (dataUri) {
+            return 
se...@org.ovirt.engine.ui.common.widget.editor.IconEditorWidget::setIcon(Ljava/lang/String;)(dataUri);
+        });
+        if (inputFileElement.files.length > 0) {
+            var file = inputFileElement.files[0];
+            var fileReader = new FileReader();
+            fileReader.onload = onFileRead;
+            fileReader.readAsDataURL(file);
+        }
+
+        function onFileRead(event) {
+            var iconDataUri = event.target.result;
+            javaCallback(iconDataUri);
+        }
+    }-*/;
+
+    native void preventDefaultEnterBehavior(Element element) /*-{
+        element.addEvent
+    }-*/;
+
+
+    // see com.google.gwt.user.client.ui.ValueListBox.addValueChangeHandler()
+    @Override
+    public HandlerRegistration 
addValueChangeHandler(ValueChangeHandler<IconWithDefault> handler) {
+        return this.addHandler(handler, ValueChangeEvent.getType());
+    }
+
+    @Override
+    public void markAsValid() {
+        super.markAsValid();
+        getValidatedWidgetStyle().setBorderColor("transparent"); //$NON-NLS-1$
+    }
+
+    @Override
+    public void markAsInvalid(List<String> validationHints) {
+        super.markAsInvalid(validationHints);
+        updateErrorIconLabel(validationHints);
+    }
+
+    @Override
+    public LeafValueEditor<IconWithDefault> getActualEditor() {
+        return this;
+    }
+
+    @Override
+    public int getTabIndex() {
+        return uploadButton.getTabIndex();
+    }
+
+    @Override
+    public void setAccessKey(char key) {
+        uploadButton.setAccessKey(key);
+    }
+
+    @Override
+    public void setFocus(boolean focused) {
+        uploadButton.setFocus(focused);
+    }
+
+    @Override
+    public void setTabIndex(int index) {
+        uploadButton.setTabIndex(index);
+        defaultButton.setTabIndex(index);
+    }
+
+    @Override
+    public void disable(String disabilityHint) {
+        setEnabled(false, disabilityHint);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        setEnabled(true, ""); //$NON-NLS-1$
+    }
+
+    protected void setEnabled(boolean enabled, String hint) {
+        this.enabled = enabled;
+        uploadButton.setEnabled(enabled);
+        uploadButton.setTitle(hint);
+        defaultButton.setEnabled(enabled);
+        defaultButton.setTitle(hint);
+        ensureStyleNamePresent(errorMessageHtml, !enabled, style.grey());
+        errorMessageHtml.setTitle(hint);
+        ensureStyleNamePresent(image, !enabled, style.iconImageDisabled());
+        image.setTitle(hint);
+    }
+
+    private static void ensureStyleNamePresent(UIObject object, boolean 
styleNameExists, String styleName) {
+        if (styleNameExists) {
+            object.addStyleName(styleName);
+        } else {
+            object.removeStyleName(styleName);
+        }
+    }
+
+    @Override
+    public boolean isAccessible() {
+        return accessible;
+    }
+
+    @Override
+    public void setAccessible(boolean accessible) {
+        this.accessible = accessible;
+        setVisible(accessible);
+    }
+
+    @Override
+    public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+        return CompositeHandlerRegistration.of(
+                uploadButton.addKeyDownHandler(handler),
+                defaultButton.addKeyDownHandler(handler));
+    }
+
+    @Override
+    public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+        return CompositeHandlerRegistration.of(
+                uploadButton.addKeyPressHandler(handler),
+                defaultButton.addKeyPressHandler(handler));
+    }
+
+    @Override
+    public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
+        return CompositeHandlerRegistration.of(
+                uploadButton.addKeyUpHandler(handler),
+                defaultButton.addKeyUpHandler(handler));
+    }
+
+
+}
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.ui.xml
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.ui.xml
new file mode 100644
index 0000000..ec7142f
--- /dev/null
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/IconEditorWidget.ui.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent";>
+<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
+             xmlns:g="urn:import:com.google.gwt.user.client.ui"
+             xmlns:d="urn:import:org.ovirt.engine.ui.common.widget.dialog">
+
+    <ui:with field='resources' 
type='org.ovirt.engine.ui.common.CommonApplicationResources'/>
+    <ui:with field='constants' 
type='org.ovirt.engine.ui.common.CommonApplicationConstants'/>
+
+    <ui:style 
type="org.ovirt.engine.ui.common.widget.editor.IconEditorWidget.Style">
+
+        .iconImage {
+            display: block;
+            height: 120px;
+            width: 150px;
+            border: thin solid rgb(211, 211, 211);
+        }
+
+        .iconImageDisabled {
+            opacity: 0.4;
+        }
+
+        .horizontal-spacing > tbody > tr > td {
+            padding-left: 10px;
+        }
+
+        .inline-block {
+            display: inline-block
+        }
+
+        .iconButton {
+            margin: 0px 0px 10px;
+            min-width: 110px;
+        }
+
+        .iconButton:focus {
+            outline: thin black dotted;
+        }
+
+        .hidden {
+            display: none;
+        }
+
+        .grey {
+            color: grey;
+        }
+
+        .iconInfoIcon {
+            margin: 0px 7px;
+        }
+
+        .iconErrorHtml {
+            position: relative;
+            bottom: 0px;
+            left: 0px;
+            margin: 10px;
+        }
+
+        .iconErrorHtml ul {
+            padding-left: 13px;
+        }
+
+        .no-border {
+            border: none;
+        }
+
+    </ui:style>
+
+
+    <g:HTMLPanel addStyleNames="{style.no-border}">
+        <g:HorizontalPanel addStyleNames="{style.horizontal-spacing}">
+            <g:Image ui:field="image" addStyleNames="{style.iconImage}"/>
+            <g:VerticalPanel>
+                <g:FlowPanel>
+                    <g:Button ui:field="uploadButton" 
text="{constants.uploadIconVmPopup}"
+                              addStyleNames="{style.inline-block} 
{style.iconButton}"/>
+                    <d:InfoIcon ui:field="uploadInfoIcon"
+                                addStyleNames="{style.inline-block} 
{style.iconInfoIcon}"/>
+                    <g:HTMLPanel addStyleNames="{style.hidden}">
+                        <g:FileUpload ui:field="fileUpload"/>
+                    </g:HTMLPanel>
+                </g:FlowPanel>
+                <g:Button ui:field="defaultButton" 
text="{constants.useDefaultIconVmPopup}"
+                          addStyleNames="{style.iconButton}"/>
+            </g:VerticalPanel>
+        </g:HorizontalPanel>
+        <g:HTML ui:field="errorMessageHtml" 
addStyleNames="{style.iconErrorHtml}"/>
+    </g:HTMLPanel>
+
+</ui:UiBinder>
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
index d3b2867..16319c4 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
@@ -27,6 +27,7 @@
 import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.ValueLabel;
 import com.google.gwt.user.client.ui.Widget;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -71,6 +72,7 @@
 import org.ovirt.engine.ui.common.widget.dialog.tab.DialogTab;
 import org.ovirt.engine.ui.common.widget.dialog.tab.DialogTabPanel;
 import org.ovirt.engine.ui.common.widget.editor.EntityModelCellTable;
+import org.ovirt.engine.ui.common.widget.editor.IconEditorWidget;
 import org.ovirt.engine.ui.common.widget.editor.ListModelListBoxEditor;
 import org.ovirt.engine.ui.common.widget.editor.ListModelListBoxOnlyEditor;
 import 
org.ovirt.engine.ui.common.widget.editor.ListModelTypeAheadChangeableListBoxEditor;
@@ -864,6 +866,15 @@
     @Ignore
     protected DialogTabPanel mainTabPanel;
 
+    // ==Icon Tab==
+    @UiField
+    @Ignore
+    protected DialogTab iconTab;
+
+    @UiField
+    @Path("icon.entity")
+    protected IconEditorWidget iconEditorWidget;
+
     private UnitVmModel unitVmModel;
 
     private final Driver driver = GWT.create(Driver.class);
@@ -993,6 +1004,7 @@
         getTabNameMapping().put(TabName.POOL_TAB, this.poolTab);
         getTabNameMapping().put(TabName.RESOURCE_ALLOCATION_TAB, 
this.resourceAllocationTab);
         getTabNameMapping().put(TabName.SYSTEM_TAB, this.systemTab);
+        getTabNameMapping().put(TabName.ICON_TAB, this.iconTab);
     }
 
     private void initDetachableFields() {
@@ -1501,6 +1513,9 @@
         numOfSocketsEditorWithDetachable.setLabel(constants.numOfSockets());
         emulatedMachine.setLabel(constants.emulatedMachineLabel());
         customCpu.setLabel(constants.cpuModelLabel());
+
+        // Icon tab
+        iconTab.setLabel(constants.iconTabVmPopup());
     }
 
     protected void applyStyles() {
@@ -2004,6 +2019,10 @@
         // ==Custom Properties Tab==
         nextTabIndex = customPropertiesTab.setTabIndexes(nextTabIndex);
 
+        // ==Icon Tab==
+        nextTabIndex = iconTab.setTabIndexes(nextTabIndex);
+        iconEditorWidget.setTabIndex(nextTabIndex++);
+
         return nextTabIndex;
     }
 
@@ -2063,7 +2082,8 @@
                 rngDeviceTab,
                 highAvailabilityTab,
                 poolTab,
-                systemTab);
+                systemTab,
+                iconTab);
     }
 
     protected List<Widget> adancedFieldsFromGeneralTab() {
@@ -2119,7 +2139,8 @@
                 highAvailabilityTab,
                 resourceAllocationTab,
                 customPropertiesTab,
-                rngDeviceTab
+                rngDeviceTab,
+                iconTab
         );
     }
 
@@ -2151,7 +2172,8 @@
             bootOptionsTab,
             customPropertiesTab,
             systemTab,
-            rngDeviceTab
+            rngDeviceTab,
+            iconTab
         );
     }
 
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
index c6c8901..ae89f1f 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
@@ -426,6 +426,42 @@
         .overrideMigrationDowntimeContentEditor {
             width: 20px;
         }
+
+        .iconImage {
+            height: 120px;
+            width: 150px;
+            border: thin solid rgb(211, 211, 211);
+            display: block;
+        }
+
+        .horizontal-spacing > tbody > tr > td {
+            margin-left: 10px;
+        }
+
+        .inline-block {
+            display: inline-block
+        }
+
+        .iconButton {
+            margin: 0px 0px 5px;
+            min-width: 110px;
+        }
+
+        .hidden {
+            display: none;
+        }
+
+        .iconInfoIcon {
+            margin: 0px 7px;
+        }
+
+        .iconErrorLabel {
+            position: relative;
+            bottom: 0px;
+            left: 0px;
+            margin: 10px;
+        }
+
     </ui:style>
 
     <t:DialogTabPanel width="100%" height="100%" ui:field="mainTabPanel">
@@ -784,6 +820,13 @@
                 </t:content>
             </t:DialogTab>
         </t:tab>
+        <t:tab>
+            <t:DialogTab ui:field="iconTab">
+                <t:content>
+                    <e:IconEditorWidget ui:field="iconEditorWidget" />
+                </t:content>
+            </t:DialogTab>
+        </t:tab>
     </t:DialogTabPanel>
 
 </ui:UiBinder>
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
index f330cda..30a8eef 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
@@ -770,6 +770,10 @@
         return result;
     }
 
+    public static <T> List<T> concatTypesafe(List<T>... lists) {
+        return concat(lists);
+    }
+
     public static <T> ArrayList<T> union(ArrayList<ArrayList<T>> lists)
     {
         HashSet<T> set = new HashSet<T>();
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/TabName.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/TabName.java
index ccbd4d9..02e81b1 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/TabName.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/TabName.java
@@ -24,6 +24,7 @@
     RESOURCE_ALLOCATION_TAB,
     SYSTEM_TAB,
     TAB_RNG,
-    FIRST_RUN;
+    FIRST_RUN,
+    ICON_TAB;
 
 }
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/IconWithDefault.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/IconWithDefault.java
new file mode 100644
index 0000000..fcb9731
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/IconWithDefault.java
@@ -0,0 +1,66 @@
+package org.ovirt.engine.ui.uicommonweb.models.vms;
+
+/**
+ * Bean holding two icons in dataUri format.
+ *
+ * <p>
+ * {@link #icon} carries data in both directions between {@link UnitVmModel} 
and
+ * {@link IconEditor}
+ * </p>
+ * <p>
+ *     {@link #defaultIcon} is used to one-direction communication {@link 
UnitVmModel} -> {@link IconEditor}
+ * </p>
+ */
+public class IconWithDefault {
+
+    /**
+     * Icon - this value changes over time during model-view communication
+     */
+    private final String icon;
+
+    /**
+     * Default (VM OS based) icon. It allows user to reset custom icon 
settings.
+     */
+    private final String defaultIcon;
+
+    public IconWithDefault(String icon, String defaultIcon) {
+        this.icon = icon;
+        this.defaultIcon = defaultIcon;
+    }
+
+    public String getIcon() {
+        return icon;
+    }
+
+    public String getDefaultIcon() {
+        return defaultIcon;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof IconWithDefault)) return false;
+
+        IconWithDefault that = (IconWithDefault) o;
+
+        if (defaultIcon != null ? !defaultIcon.equals(that.defaultIcon) : 
that.defaultIcon != null) return false;
+        if (icon != null ? !icon.equals(that.icon) : that.icon != null) return 
false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = icon != null ? icon.hashCode() : 0;
+        result = 31 * result + (defaultIcon != null ? defaultIcon.hashCode() : 
0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "IconWithDefault{" + //$NON-NLS-1$
+                "icon='" + icon.substring(0, 30) + "…'" + //$NON-NLS-1$ 
//$NON-NLS-2$
+                ", defaultIcon='" + defaultIcon.substring(0, 30) + "'" + 
//$NON-NLS-1$ //$NON-NLS-2$
+                '}';
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
index d1cef78..360558f 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
@@ -67,6 +67,7 @@
 import 
org.ovirt.engine.ui.uicommonweb.validation.I18NExtraNameOrNoneValidation;
 import org.ovirt.engine.ui.uicommonweb.validation.I18NNameValidation;
 import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.IconWithDefaultValidation;
 import org.ovirt.engine.ui.uicommonweb.validation.IntegerValidation;
 import org.ovirt.engine.ui.uicommonweb.validation.LengthValidation;
 import 
org.ovirt.engine.ui.uicommonweb.validation.NoTrimmingWhitespacesValidation;
@@ -200,6 +201,20 @@
         this.nicsWithLogicalNetworks = nicsWithLogicalNetworks;
     }
 
+    //TODO jakub add initialization, validation, saving
+    /**
+     * VM icon
+     */
+    private EntityModel<IconWithDefault> icon;
+
+    public EntityModel<IconWithDefault> getIcon() {
+        return icon;
+    }
+
+    public void setIcon(EntityModel<IconWithDefault> icon) {
+        this.icon = icon;
+    }
+
     /**
      * Note: We assume that this method is called only once, on the creation 
stage of the model. if this assumption is
      * changed (i.e the VM can attached/detached from a pool after the model 
is created), this method should be modified
@@ -284,6 +299,9 @@
             // ==Custom Properties Tab==
             getCustomProperties().setIsChangable(false);
             getCustomPropertySheet().setIsChangable(false);
+
+            // ==Icon Tab==
+            getIcon().setIsChangable(false);
 
             vmAttachedToPool = true;
         }
@@ -1713,6 +1731,11 @@
         getAutoConverge().setItems(Arrays.asList(null, true, false));
         setMigrateCompressed(new NotChangableForVmInPoolListModel<Boolean>());
         getMigrateCompressed().setItems(Arrays.asList(null, true, false));
+        setIcon(new EntityModel<IconWithDefault>());
+        // TODO jakub delete
+        this.getIcon().setEntity(new IconWithDefault(
+                
"data:image/gif;base64,R0lGODdhlgB4AOf/AAUCCAIEAAAFCQMGEQQJGAIOCQUMHgYPJgwRBAkWCAcTMggbBw8cGg4cKA8dMw0dPwokDBIjEBkhEiAfEg0pBBgmChQmTRgoNRcoQhoqLxkuERssKhAyExIxHB8vGyQvFR4wIhg1CyI0DiE1GEcsFDEyGi0zIyQ2QSQ3OyA1XTQ3EiY4NSQ2UB4/Hh1BEyg9JyZAFCo+ICk9LzE/Di4/GDI9ITRBCC1FCis/ZTBDSjJEQzJFPzJDVjBDYzNDXjNKHy5NKytQIj9JLS9QGj1LIzdMLENKITpOGzZMPTNRFThNNj5PFUhMFjBKgDtSJ0RNP1BNJzxNaD1OYk5OMz9QUEBRSztPcVhRGkJSWkJUbzteKURVaUVcL1ZZHExaMEhcKEFfIEVaSFBXSThjG0tdIEhcPERhF1ZdNUZmE2FZTEtccKFKLkZdf0pfelVgW1RhYlFha0JvIjRjxmRmKVJkdFNqOFFkeltqI05tLFhqLVVnVURmm2JnPlFvJV1oSEtvOVVvHkFnq0dyL0d0H2JsHzlrzUFsv1RsintoP3BqUFhsg3dsLlxufoRtHl9veGZxbGVxcVV+InF2H1R+KkRy1Ft7OFN+OXN1OVR/Ml98MWh5N3ByZW15K2N6R2F+LHN2TGt4anF4WUN71mp6g2h6jFZ+vnZ9eXJ+fmCML16NO2aBokyD22GMRWWMO2uLO3OJOnaHSWuLSHSCi4ODaWSFtYGEd1WI2ZKIQIOJZI+LLo2IVoWOP3mJnX+LlHiXRZSLanKaPnKZSK6LJLWGRISNj4WWOIGWRIiNiW2cSF2S4WOS1HacVoaXWZWTiJqTepeVgXmlUKicMYSkUY2iTZaam5mhT4CpS56hRW+k5oSuSa2hU3mn4auhj6Wil42nzbGji4Op25yvXJ6ubrKmhZ2ov7GsdsSodrazQqqsr!
 
buyn7izqMWwosGymt+vZbK4wca+daS+476+u83DtNTErLzL4tXPq97Om8bR3+TNsN3Uw+TUu9Pa5e3m0PTnsvDnxPn35iwAAAAAlgB4AAAI/gDvCRw4cJ/BgwgRFtx3jx48cODgwduGLZnFZMqUXbyYUdk2cN68SQwJblvHjslsqVypcpXLlzBFyZwpKibNm5RyisrJk2chSoWCCh0qVI7Ro0iTEiSYsKlCgvQcQoTnDSK2jLSy0srIseO2jxDBXcVocWVKlithqn15U+1Nmjp39pybk6jdpHiRLmXqNCHUqBLDhvXGixSpQ4i3dj2J7aPJlBfNop1say3bt6veapbJUy4lz0DtFs2bV+DBe+5SL2TotCHgwCXBelNFihHiQ4rYqNKIESXGxiU1qixbljJLyzFdbsYZtydon6ILyZFOWqnBe/vIkUKX2iG9fVHp/mFn6FriQ6oQv2IDR5tUbja425DiRcui74zrwXHdeNY4ZeRrLdfZTpzNVYghdRVlCHVDVWfUafcURkwv7kwEj1QXhvcQWF9xiE1jtDHiXhtW0MEIHbIQw4t+/ClDizcm+QaZf/4BaNNyns2kkyGBZIVgUEBNF5SQRJGG3UDzySILOTA69pF5DlH04ZTqgZgiMbKMskUbjnRJjCnq9MKifYfI4s42GIXEW3E00gggjgXKNZMhe/iATjPk/BhadKPhdaFrhQW6opMdplfllIjSMkoz3XTTzDGjqAGHI4yccow83LgDjn202AGJOpsq40g85KzZX5v/IQenTKXQguBM/ntIwcMxv8RTSlA8GrLggqKRNpVEhhnWiyy8VNXYoYgmWxEtbByzzjrqxLOJOo6YSMcopuTDDjqbYsQGHfGgUyotkMiDjje8KTMcqpNZVlNlq1RGky0y7bEdLaIYIkogVkghBSTPyOMNj02w4c0euvJq1JB4BRXbR7QNS80xsnBX0rHHdogousocYkc3+OCzTjzczEONG!
 
ic6Qow63DiyGy2HtMFIN7LIQ84hdMBRSzzoEncqu2vB61JaNGVWCBuQdENOKfk20YOssmwCiauB+ODDKG3sEYh0BzbodSGHqBIWbdR0s043l+pzZsYdHkqOO7zEDAc3Ic+jzjzzdKOG/h05U0NNL2q0wYYVWaB8DJj5OKKGGpDkk4+mtmBUGbvHwTR5KaqgozS9NwXSRjObsDPwHv3yIMUWp0jRhCh78GC662xsbRevRB2GGG2ymA1tyf7kQ4/GGn8IDjnqrCPPKXY4QrfIYOqDzhZqXEuMI20IboUVbGxBBzHdcKNPN1LYwQg6+uiTjzeRR0a50EOvUgobjLAzDy+lZBZvTXts0YwpiZCzBw4+iIKsfAAHNTSBTjyIQhSsJgUrBOKBuuKaaG6DGJXRbR7rSMc8/MEPfZDDUBnzRjzkIbJ0xMMOo1hHyNTxBmqYC3p24AU16GAHNkQhC1FoQ/RWxg155OMN/nAgBffmwY/zbSR9qBoa+0rRBik8qxf1s0Up6MUvRzQDEjnghRV6EMAF+kAKBuRRFHpwPTL2AAdR4IED+QQ2xNhBEbxARzrwIQ91pIMfHTQfL4olFuDwooN2m9AhRqGOkHEDEmWTRRbagBtG2EFwasgC4VBWNm7kAx3HeIOlLoXHffTsiOuDly32ULhnEaMJgSBdIAyBAyno7A1SoEMUcMBFH3AxfFYwhNNwYIVDDK4HPTDdFgJBJEMsLCi+jBkjZKGODrJjHfPQRx75EY9RyEJsX6FFL/iBj3z0wnaE7CA3qHGKUzBikbghxSPZsEjC2UEW8ajFPNLxiH1Q4RTE/jhGNP3hD0/a52c0qkm8pMhOLHDjG9SQAg5o2YQ6bWFScHBlFFKQAmA+jQckCsQuyYg9L/IAC3tgoyqqpwhGENJxGMSbNPXRu1PIohdiYw81OpgPWdRGZujoYC265AhFVA83hckCG0hkhejJgh/d0Ic8ILGPZjwCEsfQxwb9oY99hAoyAKVRKfZgQywcY39bSMFCU9CvKKgBeq7MggXESksBzpKtXMyCXBUYQCkcYldBWaWQ!
 
YoYbJcWjGfmQB96imQ98+CMejhiFYnmhilF0w3HqOAwjSiqLfPADEont6U/5tk42DE5Sp/hHN9RxvEvV4g2mmIdh/TGOfNzDVFlF/gtX6/e+LURhC44wBSToYIWxcrEHLNhS4dRKS2BuwbYUPSMXbzjXMfJyD5RYkBxwEFJkIkYN6PCbI0jruO4SER2kkIUjbDqKU9hxhorAzbXMi1RKOYIUJE2vLz372WsFFh3EgAMdqJGPRzRDpfz4BjtsphHYUiYZpMtCEwiaheN2CQ5b6K1FLWpWO0SYosW1gnNpudDryRWHwMSBUHWl0QBqDWyepUN2R7Gd7kqziPxAh0khkaVyHqMb1KjeG5dZtnz8gxqTTa8d3oiYwbUzCiiMRz4mBAc7RJUb3GDHN1TLDvmpo1QcKcVZ+pOMUmg4Ck1olVwdHNEo9JaXWwRm/hbsoIYc4iC5CgwxLXt7PcJJMs0kakITUvDFLfDAB3uIGRtIEY9esJi068gHEeWBR3QooryjoMMpEHmMuDFSEYrIUo8TR0FMK+KRhCORD+igsnhMqBeS1kc6uJGOZkATU/JAKC32kBVVsEHL/HmfW3HQhENADw5YcAQcxnjGLVqtBzc8Ky7XKkAp2FKsIeboXNNshRRYwALB9Bey7SrUUcRDFtRARw9zKs1m/CPG8hEvbiFhaFJ4NmaK6FLZSEsNOyDG05iOmVzZMOounYIao+gFbuMBKWqYohmMKuf+SLHILChCDbfeSIKz8OwUnFVSuI2oLXlZSwUGzqx0yMKb/jVsyx5U9IbKJRzKLWrtFChwrACMmRp6gQ7H1lEd6pDm8f7xYzUoQp1RqFSWbMeGUTDi6POOFnzdaAf3PFKobTDr0RMroig4ouZS6IUpykkMOmBhFNUihcfbvIeLeNlfIn9zCixMh9MpztlnpCULeHDcLeBwcWqo9vX4bHI0ShKYXUT5m6/NcYoavnpqqFgv5BEP/kZTH7Wo2T+e!
 
dwihRkHSSvomI9UhCxGVrRksqzcjPYbpIbdhkTc8Og1NdHmAS8ERp1AsKdoORikcxgd7g7hFvOxWkVP08trjQfK2MGGLns62tz1um4FJUR6YHNlmBrwCb1htwsuZotf2ZRZG/hFufjQjp/ykJzrk8Q91bKHybcBt7BX76TYgVrGN4l6rGRFfOGJah23PwtE/3fT0uxSMWfJedmA1aiAFPxdJgWMFGbEH0CdJI7cFQLQFuOcIY2RLdVY4WyAFCtRgW2AHW5QFFLVxcycFFgViZjZ40HZGhmdtgjNoK4NUx8APLQUHvVAu+UAHp5d+sGdTh/Fz8mAijkUxx5AOx+BTa4Zv8JV1WzJZjyQ+dpAF+mVh40VDiqBmW8AIlCIFbWAHPbBVX3ZDs4QD0VNAfyYpY7RAc1U4keRxx1WBbVZRJvdFJdcDcpVmaidWG3eHKUAi25dz3xNV/tANdFBSJ0UNMERq/rH3c4eAhfIwWYtCDKNwDJynb21QepjWYCezhabHNwhIQ9FjGG/0gdpjdFKwZlvgWSSIbLbVA5UYSRSnPbw1fRsIRpHkA1ngL87GAsDHVizgAyywUMBEfXGndnSogthnAZ8FT+XDDd3AD/PwCCZCCoRkLtVDByZiCiyWXr3wBugAB5HYDaYgC8dwDHTgMYvkaW+UBY5ADdSjiZ9mjdCTM9bYJbVhB8l3LeI1ZI90erY0OAD0aZJ0W9aoBtBnVn5Wdx5nOl4EixjGAsBlUQFkd32ndsn3ZmqHjFbwaEoWWEmVDqcQjaOQD+mQD6SAMtYYe4ahCAaHarnzKJA2iPuI/m9sBgdZomNvxDd0AD1q8GDCFixnBT3j1VP6GDMb2FsOZ48gZ41naFaL4y8ZqIoLtECno18i54vHJn0aOJHY9lBqYJGDNzgq6UNKJQ+r1nks5m13ZIiYRmruoQh0oA6C+E4IN2lZcpP1N2TRI4APh5cmEo80mElBpFiRtjjjNQolRYVnJVfANGQ49FDwyECkVkAZ6Gdx1Yt1dTp7M3cJRGxWaTV5iG08EFFxh33Vw0zRBE3z8A0t83P!
 
SWDbm4ghNR4+ehnOUAm6QQmNt+Ui4MWT8d3S8GTiVaI2MMIbUwChvMApf4lKOgAXeaJjWWHrHRXFIVosQdTpW81Bdclyn/pOKY+SQX+QvCpRAARR3wPVFaeQDFoAD6flFf7aCFuBwxBBYSqVBdtNT0sh98yYL4nN0kxVe3XMK40UNnRdku2lvbIaX+zmPwzlkJ2JhD3UM7JAObnAKtdAMtWAKFwoJ69cl1hRpaKV8DSZsDmZLkgIJkIAFBZiBc9iLYJSTCpSBplNy3ulFtuSQ0PeLKLiHhJYOfihgrUZDJuUIx0AMoNcL+3l0hmFezTA9LyWUlYhpe/Nwe3OThgF2nWegn/aTdCBP87A/zcANFvoMz7A/pzAsJlpOAAcHjFB3QKkGPtAlpRhvjgBEP+lsCuSdYJSBhcNmauA6vcgCgGo13umZ/lajhwv1TiLZDfKgVGgDoOIDdsSQTzRTG9JoIiZlcNNjaEFWevp4oJ5mGEg6IltIQ9FJB28wR612UOzwDAeVDmgzpMRQTpbCjooFbNrzBliAW0Y3htkpgThEqAGkbIsjPoOYRrJimYAKqBiAAbroixZgo2P1Tj7EKIlKDZAYmypjKd1gmCLCU4mVIh3qSDTkMUMGim/kdFNqjSYSSaoXPdDjBnTzDetwUN8gplDmpY8ypKZgClgyKb3AU29QLS+FJcI2KcNJd7JCo7hIhdYiga7zZw+brMkqqMDkkIZnUo91OPIwr2jDrZRSTqbAjsHCoV2iJIoFm/r4qTalegMZ/jjaAwdYsjjqmjNYgAWP4AzfIK84yw0VWgvMuAlgWgu1MI77CqDH+a88hY+9YGjVEo0nQgeL47Cns67CeSJ+ZjpSoJl/5pm9OH2AynwpoFj8NaTsAJfWOqD4WF4oyQsBWC3j5VJGR0MM2iWQ8Ahz+gZv4AZ4q6akkFv8sFTx+GtYIAWmIKbj8A3OAGVCWwvO0A0VOqaLyyhDegpv0LbWWKU!
 
meyJnpV8IKUAdmKVQa6mzpz2y8rBbW6Pb5os2ygJ6AArqkA/HIEetNqQDalKygE+x1wt+A3b6BXvH4FL8yQjARgVYQAVUkANUoANVEAZhoAd64AaY1Q3+gA/dUC1s/no6byC0zjAO4wC5m3BwFtoNz+C4+1oLo/Uo4Yi0lKKumeUIhZEzVqt8UapOeCecoJqTpes6FKuLzaa6gFoEfhAKrpoOEaoOSypeR4ec+UQM1IBzOMeONtYNpxBeYIcFOcADyhqoc0cFVbC8zvsItSBV6TA9OcmmWCC0mzALs/AMtQAKjwAKtUAM2Tu+x2Cim2C+8WC27MhTowAHk+KthfG0Hchm+Jai8SgioBo9bfewngmGspKLgCoEZVAHuBAKuCA/eXMMAFcb+BSy6EBajycPB0cM0zLBjmC8xnvBzAqoJ5ADJ4ACxru8zKsHz8CjkBi/wFa3F1q+s1AL37tT/rmFcNPjCG7wCJvgauqQXZNGY2DHww+WJcOpxPyJrjwwnKEqImtqLVD7Z3nqLzEKqFEgBELABXVQyuOgWq3WDCipWOiQw4FlWfhgPq3Grz1svDpwwRiMATxwArucxserA0gwx3oQBm5Qwz0lKVjwBo/gBoW8r6AAwy1st767pJFGyMwcu5ozPR06p46cMwMaPU+LxLRnv8Giesd1dMqGVlZDd3+GAT4QAzFQBF7gBXXAB5+AC+PAo9QgjcSQwz5URCvFUvygDtTwBjmAvMebyxfAAm28y7t80Mi7A8E8x8yrt3UKbMyZAzULBwaNt7nqCJBgCkPqtm9QBW5wTwxM/rAP5sMzm4Em9bRKXM6uo65IXBsPloHWeHxtZ5nHuqxC4AdTIARFoARcUNR1EArPoCTPEFh3VD54A0jzBApVgMa3fAJzx8sn0Ma4DKg8kAM6wMFy3LzDXAUXLAXLetZonda6DHuQQLCM8AZojAWZJ17JnKtampM8AM5Wa6mCKStVC3a868M168lgBGGWSXcswKw//QlTUAMvAARO4AVlUARl4LwCfEd4JD9kaaGPIAZPkLxpjNWi3dWJjdYX0M!
 
bKG9ZiXQVWjQHX5trXdm0PYAEPsKwP8AAsICmJZXTA1sHEqyRKgtGDHY8pijKzp9ffCmw82ciBLdw5MJVZy9X+/oIBF3AGZ/ALuCAENRDPRdDdZTDPZRDA44BH+dANmyAGyXvQoE0FKJDVXs3LGKysaJ3YWq28zDvRzDvVJwDbso0Bt/3fAI7bD2V0W4AFVaC8VHCc1iQLNdvgG93go6h6maXg3JzM4hWwk+bRDq7RWJDVWc0DwpYDMSAEn1DiUxADSsDdRUAETvDdkv0M8zALYuDbEA3R7H3BBy3fFrCsO57VF/DjWp0DSDDk973aOeDftB3gSn7bujx7porGxPutsVrXDl6zOsCcJKuho6BJsapJCX4Ky+wGIg0JzMzMCc7hEI0CCE0FI+4H9xwKQT0CI77ilE3ZZRDeZYAEUJ4D/u3N56C9364926+9rHxe6CdwAQd9AsobzDqwA8N853rA2v+d5Ev+3w7gADzwcF7dwcz5Bm1NDI/Qwb4dx09QBVDVzM8MCoWMcEPrBptg3puQBq/ODTIOCpuwCQe+ASiQAReQASsAAiuwARsAzwEMBX4ABTXgAR4gykBQBEIAAkrw3VxQBkJQBU8QBlN9vAdtwfu944PuAAuNAYnuxqft4yewAjtQBSiAAlUgA8xbBsxLBSfgAEuuALdt7w+gAPquACyQA8urBE9Q5kLruGLg2QVfBTuwA2JwyKkuBq2rB5vAqtzwDCpcx88QChX/DJvQ2U8Q7CuwAijQ679uAsIO/s8/bQRuLgQysOwx0OwvsAEgUARO4ARFMAVFUNRFgARejQI8cNa17QDLytDsfgEOEPLlzgKnnQGHjgISve46wAASfedhAO85QO+Vru/5vu8PAO7+/gRi4MeJsMLc4AyJkAYO3/Eo8AQU7/BiMAVmvwNPMAs5S/ZhP/G14AYRhQENkAEoIAM78PEfz/cb0PEbwAAdEAM14OZnQAQx8AIgAAIyAAIvUA!
 
QMIPndTQTeXdTwvgOAbtvLetpubLyHjtBanQEZ4NUrIANIoO4o0Oh/P+R3Du/q7t/3vu+2f/sKAO7oDvFKEAazsL3j8AuJ8AR60Oh6kA6moPQ7oARTIAY6/qADeuAMOIvrQH4AW68AB2AABNAA22/6pn8B2z8A4g8Aj/8CU+AHRWDyJvD4lg/5L6Di6R8Dmg/vh/7fGJDV687nan7oOqDmCb8CAKGjyg4dBVFkyKBDRpWCSJSEgagnzI4TFxwowJhR48YDDhqgqMIwTKhfJXGJGYgkFDtuJxxcOFHlCQoUOnY8caOjwQGMB3wSABp0wNABBIgOBQAABIgOSz28gArVxNKoL2JAVYK1CBcuTspUsYgBQw4dJw7mMIv2AgqzKwYOXIHwhFkUOTLkoLkDyY4dMsIoeVgFBcYHGzlufHlCRxg/oUL5kVgFSZlx7GZVOdHgRIYLDRo4/vDZ8aKCA0CPnj6aVLUMqCAiPH0qFYQMDzFsx1jK+kWZIk6cAAFSZu8OmmVzHJ9Lc27ntSvKLoepg61mtih2ON/QFwlEJC4VOABN2rBhnxd2hClTxk8ZPWXQz3LmJ8zez6FJG/BoQL9p1KlV/7fKAxAYyO2FDqwCwaqrrHphqRiKgNCJIryIkIsylCBOB7x0oAKvucADrwGYNMvgoBV24OyCCzZQboUVDspgBRkW4uwlEH0aLzQdHcjgPN7+Yqyx9SDSATQDQtuvqP78+081AQR4AYgRQJBAggRt80BABWOorUHWgHiQiAkhLMO3C0+8gIccVlgORPA686yBGPna/uGztl5MDoW4YjwRBRV3Cm00HAfVMbQGNkAipAwaONEm4mosdD+jliSqyf+e7ABLEDzI9EENBLzStiJiiECCF4oYAcIxUwViKwvLkGGHKlZQETzRNIuTz4LiYkFEPVfw1aYVNtDBRedQqO+AI0ErtFkk9fPsoo58Gu2BSA0QitIBLHXyydpiOPA2JyjEjalWHwQzghFG0KCIH1Rl90EnuKrDCy/OzMBNX5krCyEV//3IxYP05EvgDWTU4QJnm9VPP5+Od!
 
BbiQK8NatLTuMVYAN0W8CDVH5z4QcwXPNAATA5+4GLUByFMFd5TfZPQXi/q8EOJRT8TMa4LEvo3RDhL/iTWxYOve/FgGdhktlBbj2wYYoeVfXrhhyXN9mKML/X2KgkWiJIGVGN417YWOhjBtzApFOIDVSV09+OYubC3jjpgfcKzEznjuaLP/vRs5xX22iBoYyGFGj/wnpZYR6cRlxrqio3ir9KMA6BcAMo9KMIDCRI4lQYibKMhhhFEf80J0YUAHcIfPuYCZQlR5uKLOmKW2486jnYxzwwqAjjOnJVAwtjr/G2AaWh3MhLxppdnvvmGH7f6agAsp7z6ADwQIoECFhidCCJoGL2GGDQQ4jVUIxBihA9imJcr2bmooysn6tACjz+cIMKLrrjIY+4NSpSOn3gHp77ZDTDAewES/jZAAM8YL2rKKpzzCEC1oEgKW1Rb0tWoZz0OLqUABZBA97zwPfW9QG0SwFypahABEMTgC2DQQv3AgIf6faF+dcBDDuXGBSKgrH9KyA4IWDQXvcWpVox6QhHKAATgbYBphYOiBB83RSpSETWXstQGOVi9AjDggxHogLpoMC7bEAF7VeKSa1j4Af05QXZ1AAMY8jDHONZRh++CX/yUeCadETBXegFMDNIDvJ04z2HME4rFilIxbWWQW0960harRz0QJoABlkxABTQQAxrQ4GMLqEGVPBCBF0QgARKIAMvmB0c85OELeIgFLDQBC1gwgxn1IgJXxvWxucVACbTynWdQ/rABv2BFCUUATFwM2bQJNpORRIFeI6/ILUlukXoVIIIECoAAARRgdJsMmRMSUAMQgDBLVALBAj4wggiE4Ah/AMMXjvCFPLzCF/f0hStsqYk6yO5dLfBNJ+ZVhh38D2eMkpEMkCCDAx4zDE6U4vOseBpF9gcA26rUtrAWyWpaj3of8F4EPoCABZSBC6J7EBcgMCoEFCABCIDp9j7wAQ1owAk5bF89kYGMZSwjG!
 
D/96TJiUYn7wWCVcpubDG7GAGLORkYOkYEQCHoBAxRveVO8YDSlySTpdbSaH0XZD/JghBFw4QhFiEAEbCqC70WgANVraW1oCoEfaAEMKeNfJmKx/tdYLAOfxliGNAS7DKLODn79K8P/EgqCvmwABA5ZqAKtyszIVQxbz9wqUqSnGq9KknrucuMd5kAEeRYhAQmIQA9JyMUHrVOtFXCXFpwwgh/QE5aVqEQsXLFXWTIjGNCAhjSE2gmkyq0IHVCC3ISg0KwowZcL3UADKajIiUbvohbd7PQ621EukAFlZCBtHo6ggbQuIAZEqEAMhPDWAEggl1xKACdpAAMgtKCT39MCM8DQh0y4ohW8tWcwejrgZbCip6yIxR/+kMNRFaFmrJGBEBkQJ2dWDZoVfVJ2NSyApGhxu9bzQh4+dgTa1oHEtklAx1BVBAkEwKVFgMGDIsC+/tDVVHTq+wEr+/tTX8TCF8FoBSuEjInfQmOnRg6sLTvBlR8ggQFCY8CEKaxVSk0vwxrWYOU+XE0VnMFzdQgd/GibzQRwjwMj8ABMOQcBDXzBCescHwRG6YEKVAACHLgpHjLxW8FKI6hCtgQrgPpTZATDF+EIx2+FWoQCBE7KQGkA5JzZH0hWGpJYntyWO2oEJpy3DpuEHwyI4IQWXiWtHljAAiBQSrD9QAMp/tQHT7uABGggCHHEg4GFuotbDNiWsTDGoIHqC8ECt6exAMKAGuDFCUeZARYTAFGeNIArTw9r192opS2taa/WgAgi+AJ4wcZDNC9gxmU2d6o5NmNS/mmTeyOFaboX4AQtJKGGfMiDNsyBCCMIAQq6sMc7wuFnYQcDGcCFhjV4ygotdMCLBWBgA6aNmolz+JEWb5K2IcntD9dgBBWobQwqMMYipBqVtEbt+CJAa/OiGgETUGcMTosAFNI6Ak5wAcpoEApNcMIevzBBCRLRj3YEvMh9NnhQEb5ToZ50QFHuYrRPY+mMcbjaVtY4x7c7OnXNdsZEGEECRofWAKSYdNpDQAfMXYISjFICLS17WhEQgBi0gANB6AoOmfGJT/Dh!
 
F/awhzlg0QqEI1yw9/ypNIBrcJ5WImUxYMBQCiB1aV96cgXI4pU3rnWv0sALtCXDF1Q24/39/uCUo+MSzWsAARCcskpz5+IpGVD2Bdi0E0GggSYyUQlb8r4cn/gCK/o8/Gkg2vh93qmghVyJOgDhBR+seMUngHnLWZxyJqgB5Trs0QBwlPNcRq/3QmYbDXABDB/Dwxd+ELoQOKEAU/iEW9/6wQ9ykb2UyyQM/qAFDTDDE5ioBFZIhVhgBlioBDyoBFdIPMEqPuNzQERDOiCLhU7ohDKIABnwookbAPeSAA5zsdlDgPiqgwgwge/7vg+ogPX5AHPTgDKYLy34ARjQgj4gAyeoABGogyIgAliggZf6oJi6PxejHJeCgFcCM1jYPdzCLU0whkrQgiOYId0KBmvoM2OY/oYrDIdqeMAHnAZmiAV+ioG3CwAASAAa+IJPmAAAaK8Y+AAh6JjZkoFTmjsrM8Ht+gCReoFZEx0IgACQoYDacjPzcrMv0AQy4AIaULdUayn2eis1gwD4kS0yyIQcWsI5MsQRMCoozARkGD6CCwZXAMVMeAVjIEVSvMIGDAdxUEUla6U86IQFQIARYCsmGIEFWJ1TgpC587A6lKQpaLu0igA+rIAyQxkYCwHZIQJv+x4yOALfgIBE1B5GhKkQXAARQBkc+kJN0IQ82EYn8JwKWAAlWIAQAIM9kwZrQEdrAK6dQoZUcEd3BMUgE7JWaAVMwARXyIQkxINRnMAPoIE5/ugCPqgBEeACBPAAIhiCGODFD9ukj6uA8uIY7oGBIJCtI8iDOZiDGTACJ3AlEWAz8lq504KrWdOeBIAAGIgfszoCz7mB9WsXETCvakwCBMyEHyu8dASGdkwFVsAtAUwFS7CEA1wwPBCE8yODPjhAPGDDLiAEQ5ynERCCF+KCNFTDzqpKr/JADrKEP6AfGFydHHOCIzgCQJwhTbgEgMwDBNSCILA7DoCAkBzCbVK3kaOA!
 
svoBTPwBPIOBUWGzMDQB7jmCIRiCGwCDBCyydVw6d8SEoLSEVjjAtcw5GPiBGIABMriBJIgnJ1iCQiSDJVgCODKDPtAEPjiD1EsK6+Gs/sq5Mo/aRcoRhNd8TaCUTUsYqhyiRG18BU3ILVawhLVsSz5EudNCpRkTqzrIMQ0QgfmiqxBwl9CJAXWqtR8YOQ34gTiqhFY4OCPbqVT4rZ36rwMEgyH4ASAwpUxRqyOwxhDopCXAAzLgzHL0hFeoJWPosU44AxOAve7jIMuZABPwzydIAxOYgI56zT+ITUGwBNiMg9dUQiWkxwfFBEFgSw7ogAqlUKbYJDb0pCM4QPEyK1eDgb2srUNMlQRwF+4BOTIggzjCTnc8uHrUs1aQBmRoBTBIAifQgAWgHLmLgSEIAS64AS6AAcy00SV4oXxshf5SwCqEBfuMgenbIhWA/oISSIN8+Ad20IUSqB7t6r4DhE3GBMovbdBKAMoHTQV5/IMg4AAOoAAKtdAW0AAVSK8jWNEZ0jNNCLfXscjYqYMKmBfVogHCJFJYygQw+AOejAMzQMDAcoLKHEYleMQfEIEhAIP2E0xKDU/MVNEb0DPc0itQDAZgoEJfWAYvrE25oUDi6oR6+Id/4Ic06D4TqAAPcDEToCVXaNAE1dWgzFXZBLQY+gPZXLIK7QAOeA0NuAQvoIEZuARJUFEyqARNOIL8SZkbpIEkcLPVETnTCQEYgIAQCBlcMwMzMMP++YIkGILa+4G361Ea+oGZNKsQtashgAFKTYIQhQHPtKNM/nhQehS2VtitPsADS7hHWlIy9NqaF7ieGKiGatiFXXiFiH0F3OLVXvXV5dMCF9BYF7A7C22dlVOBGfACJpCEc+gCJiCDV8gEG4yBJeACb6pXNeUADdicFXypEKy1I1iCPNCFS4ACKOiCS2CGTtCCmXMpGMCD8Gy/G6gfGBABkPlKLYCBj1OXH1hRzKyEOJiEfuVaewRKTDjTeEQFVPAFPHgpKrnBhtWGhm3YhyXT5cstBJ1NoHxHSwACYq1QDTjGPCCCKRCCEDuCXZAETpg!
 
jwv2CTjoCLeCe1alFo71ZNSuz/KkBTjOCM/iESygHJkgz/UyAEJjXChjSGcLRrwwC/icYAhcgr5eigSUAA8KMozgAW8W0x9ldTIKN3TNVzCQwLzWLgIa9BrZ1WIglWAHkTYKdzeJ1x61M07bkABiAGy8YLTNsJVh4hTogAjLIAxUFGW/VpBF4xq1JtZUDxrSqs5mSHZlLACiwh+l7KzWMxcHE0RDATDPgggrASyhMAheAgNMqQ8wUzNel3Xd0x0nwWti83UoIghAYOZj8IGNgW21Y210gxVeQRyGLR66FUEEYgiCoLyA4ghkgrc9Jq+3NBE8oxDn6ghT+ATjVgA5gswrlwxiW4bcMRj7UALCrACjohynIzxAUgSMwqgTGVDB4SEw8AswMAbdKtRE4AsIc/uLYtF0Blt0AboUfeMb8Q90CuIOe2wW2fdhRnOBX0K18MjgzrVsJbYEW0AI9goHUnbHa0DNRlGA8Xb+21IA1XVMNmOE9pmFg/AAd1gUuQoCRC9EfoNfLjKOHpAAYOGIwEAFtOq0I+AGxdN0ZQlADtsd3JGDaxQQ8eMtZ4wAXgIEEYMYvqIRXKEBx6IQ8sCVxKIdyYAZ+DTJLAIMvTdD9m1AY4IBS2t9Ze7kK4B9NeFhYyAPTqbsWuLGamlk+3uNSOa0PmIJ+sIcAmDtq/IAfCAHB1Nh6A4Mi0AAKcKc4ogFIlgB/bOLLHALMtM2kRVDYtUdB2L8NptRR9kHUkt8K/tAEGuBQZiQDZtgKWIgFVy4HcWiF5JVNLcBjCkWCUVoAO3vGaaS1ADgDI4gAJmCG3ATiNE7jM1sX0akpZuZD8VXEU5oCe+iHCajmSBYBIk2CG8BUGvhmRk6CJAjD9lIrF2jdmQ4CF2jiSyXSMQDqMYChIYghFwiBBdgm2BvHJBABMhCBPNCrZqyDJDhAVxi+dRy0VBAEyHTLlUu1GF65FETqObiFCVABJsgD3Fqy22DrdUnojwZ!
 
rcwvGldumEijpfvgEOaSx2lpRM4gjzLRBvb1Mp4a9MqzXdE5nPFhJGtCkel1hiizKBNYC2GyB05o/DQhREYABz8mhGwhL3MID/k8AhilUvIRbx+xcR97UYBdYZnNDLVNaALKOANAdWEvAgzoIAg4GjmNugdFZl5qiAApw6Gf06pstAUToB7z+gDoQAREAgyMA10pOWhhqwxm4ASMVAZii5iH1zJkG6hsQAamNwZYsSdemOVTSnBCEu3a6ARqggCIw5zqAgVcCz0oAA//CznRER2gAslbISdRehj9o40RMtW+7syAYgziIg9kkqrXM7fpC5htr3hCoKc0JRkVEABPQ4X7QBRqwzCHlguSkAcGc6emegYleAmakgSmYgBKQAPm9ASB2Jy1g7Fyj1yGogw+IxkmiHsvRbmoOAaM+yZliF322b/G+qUwg/jJ1XLoc2jGDc9FgoOXTdUs+DB0XuDWgFoQxQFdKLVAF04INZss09twgoIAYqIEJkICaioCXS4RQ8Ad/mAW1KSMhKIFQANJ6nV8wmIEZoNPOVAEVMAIV+GMmWAKxTE4jqBI+iJ0fIEwn+OQg1DJdFAAEoACjjgAaeI20MkNcy4MZqM7rPEzgSgX+ykd2RPWdkvKtrlcExLV1TlONhYEgx/IgAHMHx2ktUE8auMPZbvMJSIRZ4Id8EAP/NIEX8M8p4AdcCNF03q874ARCuIM7IARCONk+v4JhaIQrAIM76IIuGPQSEAIj8IIfWII7QGAbdKshDEHUBAAEwOxRZkM6/hs581NRTZDUWm6F/T5tx6wEsE31gE+w/coEPNUfPOCnM/ADL+CDT8jLNQVnjSXq3CYDPGjUI5jQrq4Ay52FTTD2j3+Gf6iHb7uBFcUDTsiFlE/5W5gDMxAtYYD5RsAD0bqES2ACz2GrFOcECk6/yWzzsss+7fJx5JwX62XsTnICMnhYfB8BLYiDfddvdQyGGQL4IzvtpIsFG+0D0fQDPziDORhNP0iEobOHT/AeIkCdB8njmvKnLwgCGGBeDahcMRADD/h4/+QHV8WFH86DOCKDLp!
 
iDXciFXegC5+6DO8iFRoD5OSADJmCCOWBsYgQD7N3iO5jp8AxDGtAFEygA/v+cADW3RhoQhFaSnW0Mt1dIxSWggBsYRWnIhqiXhhw6x6hXRypUx7KdoYLv+jPIgyblAz5gwmrQBkTQBb4r/lB4zgWgkg9wJSLwVlj8wSnggycQAxL8+FpoVZEPy1eafCYgghlIcUnVWTKYgytQ/O9vbsZeoQoIZW8VASPgghDI5vYLSybg4c///BLgAhjcTt6cBIEFCC1JNL2qJJCZJjKxrGVjmC1bsGAPrVGsKE0aNGvIMIEhQ+aOpk9nPn26xEeIkyV5QH7iU/LWLUQ1IEBAEEACkzxLjlQQM+vnr1+fxDyRYOKoiRL5/jH9h2vnl45M5sxRIYIGViZk8lxp/nTLhQgNGiBUiFEBhgsXYIZUSJCApoYINPJwIcJlyoQACCbgIrMWGTRkgpFFbGX4sOFUhjGlSiVYWkSMFCdCg5wKU6U6ISpU+LHVjx8+U4QQOXIED5gkYC4Nu3JN2BoVFCAkKIDgw5Rx49glSuMsaNBZUxKBDo2IX9N/zI7EgHFkhogunCoFoaFixowld5YsucH9xo8QC2LMofHjBtsIC2oHSKBBRB4KR/LgmmWiwAQ+R7iQEVxYMSsBsuJYRAUCyEorlvwRBAxBBKFFHZ38EUtEwAQTixNuubUAEXlM8cQUU9SggRNcqAYGGK+0M4w27yBSQU0BQAHFBBNM8c03/uwI54xu5ZQzji6h4DLkJ/zw448/Ts3wBRHWqXDFHETAAIMIXszARBdMwFjBCCPQENcIizABww1aVGBTAGkuQIEKTIgAg0dMGFHDLOyM1AUyjemZoCWCCGIJoIEKiiAmrSwTyx9cgFZGgzBo0BYCCUSqIWk1HPWCBxW8eUMSecCySz/+2POLHhHEuIg2KpRQQhrfmPOqOf4Y+Y8uLX0iZCL+OGOPPf38ogIufgjxQZtzjEgGdljO0QUNs0!
 
laQAEgfNDIIjQckQQZTKhwZgATqKCCJHPMkMccklyiySX1BHWJYHqmEgyAgfqZ2hBBDAEGHvL6+Ucn/f4hiBZDDPED/g20uYUAAhEgIMELZn0ghHk3gJHHLrfUY887QRpBQwkmNBLNIh2XgIg57bRjTj1NiQQFSZ8goi6v/YwDBY+JTEHDF3ec8cMS2XmUByd3gHEElWfWwEQui1RAgwjEMqFtCY00AoUkucxxyS3a3ALLJbpcolVjiBlWYCtkW4IH2multXYLa7vtgr1a/BBBAhF4sIAEU5QgRBkVEPfmvbCUU4095kQTDSGXzDHFGajeAsUUJJs8DDuyMpXIjKC1VA8/9aRsziLj6FMPLiJkRwgssHDCiSZ55KHJHWaYgUe2Uy2yCI01rIowsVELc0UXiyiujTZdeKqJJ0swYZgrzR8W/szYhRWG2NlDpBUC9hxwQAH33dO0Ht4J2GjCFHq8UENpWqBdjj8Xa3P4LnfMUULjWs+4yDDm9GOPkUk6ZUQJQsSHK9TDH/vrx6tiZg8fleMdiuPEuZawi2rsYheAQAMG79AFQmhLBUZQQR2IgIAKfHARuQjXGc7ABz5AgQbjygMeaLC8VmSihq9oHg5z2Dxf+MIVfTADJlyBIFZYwnoUCEH3uPe9BYQvTQEogAn0IAQ+lIMMldAELNLBFHtoIxeHe8cnoDAHmNyCKu8oHCLeMQdOEM5XUChBIsZRDj6QwQi74MTt8niLd7xDHNWoRuvwkIcvkEETuyCEJK5xw1iQ/qsLu5gDE2agApUkoAJnUIENRGCEOXlAAhr6QAVCgYAadKEVzXvFKzLhCVTeEIeeeGUmmheLWVaiD33ABCZYMUs8aCEILkgiTSDwgQ9IIFILE0Mi6lGOTzCja1rURzkIkQthROMW5WDGLiQhCUKQgRBa+wUJEOEFMOyiHK/ShY+6sIQgzE6VmSDX6yqRiUm0AhjAUIwrytYKTNTBC1i6RFa0lQsIeoEISyDD0oZZAwHopZJOLMACELCJCZRghs2r4SpfqdFXeEKVGgVEDWvovBrioRKVsIRJe!
 
RmEH8BgCF9wQpOo9IEafIsIRPgAFPjwC3+U4wqXkMThrrELX7zi/g5MmA8hbrELMjhhBj/AAxZhAotPzOEMTrgBJwhhwTis5A41pGcrUoEKxIi1FejigzgKQjubyu8DImASDWKwANtMAAB6kYAEAmDXAuQ1ESQgwRUKBL1TZqIPsAxpYW3ZB7ThYbGpOUJUTPqHSqCGsVr4Q0lj6YpYUPYIqqrRXqagiyxVzYvR2IUxODEDGtjgDpyY4DSIWsPVvWJ1mtBEJchwUCN44Qj4siUuMTEJXB7GFb4whjHEIY5wGKMVqDiuMaZhjGIgFxaty4MXdGeCGtWoAE7Ui038CgUVSKMi9ryoRztaQ8WmDUWmmZIIknhE9EDoB7OhCQdaWlIudGwC/nsBbQn82YVcEDga10BuHmhwUE1wIrrT+COEKVjBO+4ilZStQx1eB4vohiMcyv3wh6thDFRCF7nVuAaKUxzhP054F9b9QkFjoDsJJMIEOgjARSpiDchArxWTmERI2YsaFKlmK3kgww2oFBYlQmABS2Sik1UFXgkQEynW6UI0THuODh/hB0cggyqRO+I7AO0SLW6xmFGJ3Ad3uM0dlq6YTSzhM1cwwnSu8CtQy8pU1qF1TqiBLwRbXvNCD5eJVawZ8IUvoLEuD1IJJqSd/L0E6AWAHxhBBCTggQ+UQALfAqppb8EELkDWI314RTGuIeJK/MF1XrVhno0hjWnQuta2/j6uradRjAdDmNcrZjGa74xnV6DSE8ROZSbs+a7j2hMY0zBvKlyRCUz0IQ627Mii70CI1W1FE18IAaSbLKkEGOUoJfCA3Y6yaZo+yYQnBFkFFhABMoGhD4BwhUZdKbZ8hvUwYy0bDwPu4FnPWroG56ExShznhTM8zaw89ivdZZhmX2TQO46IK4ar2GwDwhN9uINGNcEHJUA5AiCQAQgkMFdyI6AE432jCqCAiGUl7RagFgETNQCD13kCE2MYxCB+/!
 
ONUTEKsqDg60YUeCaEzfRJLX3rTEZPPHQa86lYf8cP33MMc4lJPR0eFPYMRaIr4whO+mIY99xkHFL3uDtrG/lqLyqGLM3iBC70MAQeaDGUPkO+DM5I5IhxJCOFxIpGa+EF2bmCDPPRhDGOIQxyCHvSif73yqIjE052Oecw3XfJAh/wgMIgGoE8erP4+OjCM20Me6jCHah+DINwVNoG/8hXTtZC0Bfm6S/iIeHKHRUgn8Uo8OAEGISD1TgqqgmJ6ekZtkk7hd5ELTwACEHfQ7RJQ5PjHk/7Hlv/65jE/CPFHwvNAnwTp0096yD++/ZEXrunFVtzmeeIwlxlCEpIQe8W0AuHIfWWDFQN1GUPq6IIupM5tcdRw/Rj8Ud8Q0IQILMG2ScJ23IAIbIkKDBMmldYJEYL1kdkSnAgYmIHjgkWe5E3C9x1d+KUf+g0C6Klf+kGeDMbB9tVgDZ4f00Fd0xUdRziIC8SBWDnbNVCXR3HUKzyY3B2g62hCY3nC5aEC0+GSIPzS6SCSNgVNalDJdRjBVFzDCW3TR7jd9YXgCNagCUJdJKTg5bVgDL7g+s0gHLKfDdqgCY5f+X0e0LVfQAAAOw==",
 //$NON-NLS-1$
+                
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAB4CAYAAAAQTwsQAAADNklEQVR4nO3cTUpbYQCF4aPioBZ0AdoN9G8FFgSdNNQOFe0KbEe2VCcKWY9TR8VRodz7xWZP6SBKLdWg1yTnevI+cCeOzHdeot7ESAAAAAAAAAAAwKBIg9TLfbYzzT0+YYVyj09YodzjE1Yo9/iEFco9PmGFco9PWKHc4xNWKPf4hBXKPT5hhXKPT1ih3OMTVij3+IQVyj0+YYVyj09YodzjE1Yo9/iEFco9PmGFco9PWKHc4xNWKPf4hBXKPT5hhXKPT1ih3OMTVij3+IQVyj0+YYVyj09YodzjE1Yo9/iEFco9PmGFco9PWKHc4xNWKPf4hBXKPT5hhXKPT1ih3OMTVij3+IQVyj0+YYVyj09YodzjE1Yo9/iEFco9PmGFco9PWKHc4xNWKPf4hBXKPT5hhXKPT1ih3OMTVij3+IQVyj0+YSFPV/MqWlNP71RrV0VfVOtYRaeqteH+9vDUXGhFtbZU9E21uiOuDfe3iqegryXV2r56RhoVFHHhniq9Ua3jBwRFXBjhTAuq9bFhUMSFW/S1qFqfxhAVceHK8JlqnFERF6Qx/fgjLtxQ9HaCURHXTPqh5+rpaAphEddM6enDlKIirplxoZUH3vwkLtxDrS1DVMQVbaA51fpqDIu4Iv3UC3NUxBVp+NYXd1TEFafWbguCIq44RZ9bEBNxxWn+lhjiwgie+1fEFa/NYRWduo8HTbX3R2FXPR25jwdNtfOX9+vrwH08aKp9txtuXjvu40FT7bpB+u9VtO4+HjRVtGYP6K6r0qr7eNBUO16E/v/q6VADzbmPB4/hfdvM7delNt3HgscqWm7Z/awTFS27jwXjUE39rcl3X0Ud93FgXM61NMV/prj76um7Kj1zHwfGafg5Dd6wfumV+xgwCbW2jWG9d!
 
z98TMqZFlRpb+pRVdpTV/Puh49J6mtRlfanGNW++lp0P2xMw5kWpvJPrEUdDXimmj2/9Vr1RP5aPFLRS/fDg9O5llTUGdNN1BMVdbilgL+KljV8+eewQVCHutQmd9Rxt4HmVGlVReuqtaNaB7r+OO7hs9rx1dd2VLSuSqu8oAwAAAAAAAAAAAAAAAAAAAAAQDv9AeKA+xpCWfFnAAAAAElFTkSuQmCC"));
 //$NON-NLS-1$
     }
 
     public void initialize(SystemTreeItemModel SystemTreeSelectedItem)
@@ -2709,6 +2732,9 @@
         boolean vmInitIsValid = getVmInitModel().validate();
         setValidTab(TabName.FIRST_RUN, vmInitIsValid);
 
+        getIcon().validateEntity(new IValidation[]{new 
IconWithDefaultValidation()});
+        setValidTab(TabName.ICON_TAB, getIcon().getIsValid());
+
         boolean isValid = hwPartValid && vmInitIsValid && allTabsValid();
         getValid().setEntity(isValid);
         ValidationCompleteEvent.fire(getEventBus(), this);
@@ -2797,6 +2823,7 @@
         setValidTab(TabName.CONSOLE_TAB, true);
         setValidTab(TabName.INITIAL_RUN_TAB, true);
         setValidTab(TabName.GENERAL_TAB, true);
+        setValidTab(TabName.ICON_TAB, true);
         getValid().setEntity(true);
     }
 
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconValidation.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconValidation.java
new file mode 100644
index 0000000..036265e
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconValidation.java
@@ -0,0 +1,112 @@
+package org.ovirt.engine.ui.uicommonweb.validation;
+
+import com.google.gwt.user.client.ui.Image;
+import org.ovirt.engine.ui.uicommonweb.Linq;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+import java.util.List;
+
+/**
+ * It validates icons size, dimensions and file format.
+ */
+public class IconValidation implements IValidation {
+
+    @Override
+    public ValidationResult validate(Object iconObject) {
+        if (iconObject instanceof String) {
+            final String iconString = (String) iconObject;
+            return validate(iconString);
+        }
+        throw new IllegalArgumentException(
+                "Illegal argument type: " + iconObject == null ? "null" : 
iconObject.getClass().toString()); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    private ValidationResult validate(String icon) {
+        ValidationResult typeValidation = validateType(icon);
+        if (!typeValidation.getSuccess()) {
+            return typeValidation;
+        }
+        ValidationResult dimensionsValidation = validateDimensions(icon);
+        ValidationResult sizeValidation = validateSize(icon);
+        if (dimensionsValidation.getSuccess() && sizeValidation.getSuccess()) {
+            return ValidationResult.ok();
+        }
+        final List<String> reasons = 
Linq.concatTypesafe(dimensionsValidation.getReasons(), 
sizeValidation.getReasons());
+        return new ValidationResult(false, reasons);
+    }
+
+    /**
+     * Max width 150px, max height 120px
+     */
+    private ValidationResult validateDimensions(String icon) {
+        final int maxWidth = 150;
+        final int maxHeight = 120;
+        final Image image = new Image(icon);
+        boolean valid = image.getWidth() <= maxWidth
+                && image.getHeight() <= maxHeight;
+        if (valid) {
+            return ValidationResult.ok();
+        }
+        return ValidationResult.fail(
+                
ConstantsManager.getInstance().getMessages().iconDimensionsTooLarge(
+                        image.getWidth(), image.getWidth(), maxWidth, 
maxHeight));
+    }
+
+    /**
+     * The dataUri string has to fit in 32kB.
+     * Ratio base64encoded/raw data is approx. 4/3.
+     */
+    private ValidationResult validateSize(String icon) {
+        final int maxEncodedSize = 32 * 1024;
+        final int maxRawSize = new Double(maxEncodedSize * (3d/4d) / 
1024).intValue(); // just estimate for users, in kB
+        boolean valid = maxEncodedSize > icon.length();
+        if (valid) {
+            return ValidationResult.ok();
+        }
+        return ValidationResult.fail(
+                
ConstantsManager.getInstance().getMessages().iconFileTooLarge(maxRawSize));
+    }
+
+    /**
+     * Magic numbers
+     * <pre>
+     *     png 89 50 4e 47 0d 0a 1a 0a
+     *     jpg ff d8 ff
+     *     gif 'GIF87a' or 'GIF89a'
+     * </pre>
+     */
+    private ValidationResult validateType(String icon) {
+        final String iconBase64Data = dataUriToBase64Data(icon);
+        final String iconRawData = atob(iconBase64Data);
+        final String[] magicNumbers = new String[] {
+                "\u0089\u0050\u004e\u0047\r\n\u001a\n", //$NON-NLS-1$ // png
+                "\u00ff\u00d8\u00ff", //$NON-NLS-1$ // png
+                "GIF87a", //$NON-NLS-1$ // gif
+                "GIF89a" //$NON-NLS-1$ // gif
+        };
+        for (String magicNumber : magicNumbers) {
+            if (iconRawData.startsWith(magicNumber)) {
+                return ValidationResult.ok();
+            }
+        }
+        return 
ValidationResult.fail(ConstantsManager.getInstance().getMessages().invalidIconFormat("png,
 jpg, gif")); //$NON-NLS-1$
+    }
+
+    private native String atob(String encodedString) /*-{
+        return atob(encodedString);
+    }-*/;
+
+
+    /**
+     * Datauri format:
+     * <pre>
+     *     data:[&lt;MIME-type>][;charset=<encoding>][;base64],&lt;data>
+     * </pre>
+     * @param dataUri
+     * @return base46 part of datauri
+     */
+    private String dataUriToBase64Data(String dataUri) {
+        final int commaIndex = dataUri.indexOf(","); //$NON-NLS-1$
+        return dataUri.substring(commaIndex + 1);
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconWithDefaultValidation.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconWithDefaultValidation.java
new file mode 100644
index 0000000..c0e7adca
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/IconWithDefaultValidation.java
@@ -0,0 +1,23 @@
+package org.ovirt.engine.ui.uicommonweb.validation;
+
+import org.ovirt.engine.ui.uicommonweb.models.vms.IconWithDefault;
+
+/**
+ * TODO jakub add javadoc
+ */
+public class IconWithDefaultValidation implements IValidation {
+
+    @Override
+    public ValidationResult validate(Object value) {
+        if (value instanceof IconWithDefault) {
+            final IconWithDefault iconWithDefault = (IconWithDefault) value;
+            return validate(iconWithDefault);
+        }
+        throw new IllegalArgumentException(
+                "Illegal argument type: " + value == null ? "null" : 
value.getClass().toString()); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    private ValidationResult validate(IconWithDefault iconWithDefault) {
+        return new IconValidation().validate(iconWithDefault.getIcon());
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/ValidationResult.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/ValidationResult.java
index 99ded31..fef57e7 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/ValidationResult.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/validation/ValidationResult.java
@@ -33,7 +33,7 @@
 
     public ValidationResult()
     {
-        this(true, new ArrayList<String>());
+        this(true, new ArrayList<String>(0));
     }
 
     public ValidationResult(boolean success, List<String> reasons) {
@@ -48,4 +48,12 @@
     public static ValidationResult fail(String... reasons) {
         return new ValidationResult(false, Arrays.asList(reasons));
     }
+
+    @Override
+    public String toString() {
+        return "ValidationResult{" + //$NON-NLS-1$
+                "success=" + privateSuccess + //$NON-NLS-1$
+                ", reasons=" + privateReasons + //$NON-NLS-1$
+                "}"; //$NON-NLS-1$
+    }
 }
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
index aa836f0..c0cd5d7 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
@@ -944,7 +944,9 @@
     String diskExistsOnAllActiveStorageDomainsMsg();
 
     @DefaultStringValue("The Template that the VM is based on does not exist 
on any active Storage Domain")
-    String noActiveStorageDomainWithTemplateMsg();;
+    String noActiveStorageDomainWithTemplateMsg();
+
+    ;
 
     @DefaultStringValue("Field value should follow: 
<parameter=value;parameter=value;...>")
     String fieldValueShouldFollowMsg();
@@ -2500,4 +2502,4 @@
 
     @DefaultStringValue("This field is not a valid Guid (use 0-9,A-F format: 
00000000-0000-0000-0000-000000000000)")
     String invalidGuidMsg();
-}
+}
\ No newline at end of file
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
index 64d019b..3eb59e4 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
@@ -1,5 +1,7 @@
 package org.ovirt.engine.ui.uicompat;
 
+import com.google.gwt.i18n.client.Messages;
+
 import java.util.Date;
 import java.util.List;
 
@@ -415,4 +417,13 @@
 
     @DefaultMessage("Do you approve trusting self signed certificate subject 
{0}, SHA-1 fingerprint {1}?")
     String approveRootCertificateTrust(String subject, String sha1Fingerprint);
+
+    @DefaultMessage("Icon dimensions are too large: {0}x{1}, maximum allowed: 
{2}x{3}")
+    String iconDimensionsTooLarge(int width, int height, int maxWidht, int 
maxHeight);
+
+    @DefaultMessage("Icon file is too large. Maximum size is {0}kB.")
+    String iconFileTooLarge(int maxSize);
+
+    @DefaultMessage("Unknown file format. Supported formats are {0}.")
+    String invalidIconFormat(String s);
 }


-- 
To view, visit http://gerrit.ovirt.org/37985
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibd5e8c120282e35d5940a66286d600b128c57753
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Jakub Niedermertl <jnied...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to