Add new handshake dialog Redesign_Handshake_Dialog
authorThomas
Wed, 08 Mar 2017 16:23:28 +0100
branchRedesign_Handshake_Dialog
changeset 1587847597261903
parent 1583 33f126865e01
child 1588 dcde027ddbfc
Add new handshake dialog
AdapterCallbacks.cs
CryptableMailItem.cs
UI/FormRegionPrivacyStatus.cs
UI/HandshakeDialog.xaml
UI/HandshakeDialog.xaml.cs
UI/HandshakeItem.cs
UI/ValueConverters.cs
pEpForOutlook.csproj
     1.1 --- a/AdapterCallbacks.cs	Wed Mar 01 17:23:46 2017 +0100
     1.2 +++ b/AdapterCallbacks.cs	Wed Mar 08 16:23:28 2017 +0100
     1.3 @@ -18,7 +18,7 @@
     1.4      /// </remarks>
     1.5      internal class AdapterCallbacks : StandardOleMarshalObject, IpEpEngineCallbacks2
     1.6      {
     1.7 -        private static  FormHandshake        handshakeDialog         = null;
     1.8 +        private static  HandshakeDialog      handshakeDialog         = null;
     1.9          private static  Timer                timer                   = null;
    1.10          private const   int                  FAST_POLLING_INTERVAL   = 5000;    // 5 seconds in ms
    1.11          private const   int                  MAX_POLLING_COUNT       = 120;     // 120 times each 5 seconds => max. 10 minutes
    1.12 @@ -34,13 +34,11 @@
    1.13                                                     ref pEpIdentity partner,
    1.14                                                     SyncHandshakeSignal signal)
    1.15          {
    1.16 -            DialogResult dialogResult = DialogResult.Cancel;
    1.17 +            bool? dialogResult = null;
    1.18              SyncHandshakeResult handshakeResult = SyncHandshakeResult.SyncHandshakeCancel;
    1.19 -            FormControlHandshake.State state;
    1.20 +            HandshakeDialog.HandshakeMode mode;
    1.21              PEPIdentity ownIdentity;
    1.22              PEPIdentity partnerIdentity;
    1.23 -            pEpIdentity[] ownIdentities;
    1.24 -            PEPSettings.PEPAccountSettings acctSettings;
    1.25  
    1.26              Log.Verbose("NotifyHandshake: Started with signal " + signal.ToString());
    1.27  
    1.28 @@ -61,8 +59,7 @@
    1.29  
    1.30                  // We set the result in case of an reentrant call, so the
    1.31                  // "parent" also gets the information.
    1.32 -                handshakeDialog.DialogResult = DialogResult.Cancel;
    1.33 -                handshakeDialog.Dispose();
    1.34 +                handshakeDialog.DialogResult = null;
    1.35                  handshakeDialog = null;
    1.36              }
    1.37  
    1.38 @@ -96,26 +93,14 @@
    1.39                          }
    1.40                          catch { }
    1.41  
    1.42 -                        // Create settings
    1.43 -                        state = new FormControlHandshake.State(ownIdentity,
    1.44 -                                                               partnerIdentity,
    1.45 -                                                               Globals.ThisAddIn.Settings.TrustwordsCulture);
    1.46 -                        
    1.47                          // Specify handshake type
    1.48                          if (signal == SyncHandshakeSignal.SyncNotifyInitMoveOurDevice)
    1.49                          {
    1.50 -                            state.Mode = FormControlHandshake.State.HandshakeMode.SyncTypeB;
    1.51 +                            mode = HandshakeDialog.HandshakeMode.SyncTypeB;
    1.52                          }
    1.53                          else
    1.54                          {
    1.55 -                            state.Mode = FormControlHandshake.State.HandshakeMode.SyncTypeA;
    1.56 -                        }
    1.57 -
    1.58 -                        // Add own identities list to include in sync (this must be from the engine)
    1.59 -                        ownIdentities = ThisAddIn.PEPEngine.OwnIdentitiesRetrieve();
    1.60 -                        foreach (pEpIdentity ident in ownIdentities)
    1.61 -                        {
    1.62 -                            state.SyncList.Add(new PEPIdentity(ident));
    1.63 +                            mode = HandshakeDialog.HandshakeMode.SyncTypeA;
    1.64                          }
    1.65  
    1.66                          // Show handshake dialog
    1.67 @@ -129,71 +114,28 @@
    1.68                              {
    1.69                                  throw;
    1.70                              }
    1.71 -                            handshakeDialog.Dispose();
    1.72                          }
    1.73  
    1.74 -                        handshakeDialog = new FormHandshake();
    1.75 -                        handshakeDialog.StartPosition = FormStartPosition.CenterParent;
    1.76 -                        handshakeDialog.DisplayState = state;
    1.77 +                        handshakeDialog = new HandshakeDialog(ownIdentity,
    1.78 +                                                              partnerIdentity,
    1.79 +                                                              mode);
    1.80                          dialogResult = handshakeDialog.ShowDialog();
    1.81 -                        handshakeDialog?.Dispose(); // Dialog may have been set to null in a nested call
    1.82                          handshakeDialog = null;
    1.83  
    1.84                          // Send result back to the engine
    1.85                          switch (dialogResult)
    1.86                          {
    1.87 -                            case DialogResult.Yes:
    1.88 +                            case true:
    1.89                                  {
    1.90 -                                    /* Save the own identities sync list back to the engine.
    1.91 -                                     * This must be done separately using the original engine list in case the engine has more
    1.92 -                                     * own identities than accounts still in Outlook.
    1.93 -                                     */
    1.94 -                                    foreach (PEPIdentity ident in state.SyncList)
    1.95 -                                    {
    1.96 -                                        foreach (pEpIdentity ident2 in ownIdentities)
    1.97 -                                        {
    1.98 -                                            pEpIdentity ownIdent = ident2;
    1.99 -
   1.100 -                                            if (ident.EqualsByAddress(ownIdent.Address))
   1.101 -                                            {
   1.102 -                                                // Sync the engine's own identity flags
   1.103 -                                                if (ownIdent.GetIsSyncEnabled() != ident.IsSyncEnabled)
   1.104 -                                                {
   1.105 -                                                    if (ident.IsSyncEnabled)
   1.106 -                                                    {
   1.107 -                                                        ThisAddIn.PEPEngine.UnsetIdentityFlags(ref ownIdent, pEpIdentityFlags.pEpIdfNotForSync);
   1.108 -                                                    }
   1.109 -                                                    else
   1.110 -                                                    {
   1.111 -                                                        ThisAddIn.PEPEngine.SetIdentityFlags(ref ownIdent, pEpIdentityFlags.pEpIdfNotForSync);
   1.112 -                                                    }
   1.113 -                                                }
   1.114 -
   1.115 -                                                break;
   1.116 -                                            }
   1.117 -                                        }
   1.118 -                                    }
   1.119 -
   1.120 -                                    // Save the own identites back to settings
   1.121 -                                    foreach (PEPIdentity ident in state.SyncList)
   1.122 -                                    {
   1.123 -                                        acctSettings = Globals.ThisAddIn.Settings.GetAccountSettings(ident.Address);
   1.124 -
   1.125 -                                        if (acctSettings != null)
   1.126 -                                        {
   1.127 -                                            acctSettings.IsSyncEnabled = ident.IsSyncEnabled;
   1.128 -                                        }
   1.129 -                                    }
   1.130 -
   1.131                                      handshakeResult = SyncHandshakeResult.SyncHandshakeAccepted;
   1.132                                      break;
   1.133                                  }
   1.134 -                            case DialogResult.No:
   1.135 +                            case false:
   1.136                                  {
   1.137                                      handshakeResult = SyncHandshakeResult.SyncHandshakeRejected;
   1.138                                      break;
   1.139                                  }
   1.140 -                            case DialogResult.Cancel:
   1.141 +                            case null:
   1.142                              default: // this should never happen if we cover all enums
   1.143                                  {
   1.144                                      handshakeResult = SyncHandshakeResult.SyncHandshakeCancel;
     2.1 --- a/CryptableMailItem.cs	Wed Mar 01 17:23:46 2017 +0100
     2.2 +++ b/CryptableMailItem.cs	Wed Mar 08 16:23:28 2017 +0100
     2.3 @@ -2,7 +2,6 @@
     2.4  using System;
     2.5  using System.Collections.Generic;
     2.6  using System.ComponentModel;
     2.7 -using System.Runtime.InteropServices;
     2.8  using System.Threading;
     2.9  using Outlook = Microsoft.Office.Interop.Outlook;
    2.10  using System.Diagnostics;
    2.11 @@ -10,7 +9,7 @@
    2.12  namespace pEp
    2.13  {
    2.14      /// <summary>
    2.15 -    /// Wrapper for the outlook MailItem supporting encryption.
    2.16 +    /// Wrapper for the Outlook MailItem supporting encryption.
    2.17      /// </summary>
    2.18      internal class CryptableMailItem : INotifyPropertyChanged,
    2.19                                         IDisposable
     3.1 --- a/UI/FormRegionPrivacyStatus.cs	Wed Mar 01 17:23:46 2017 +0100
     3.2 +++ b/UI/FormRegionPrivacyStatus.cs	Wed Mar 08 16:23:28 2017 +0100
     3.3 @@ -93,7 +93,7 @@
     3.4  
     3.5          private CryptableMailItem       cryptableMailItem      = null;
     3.6          private bool                    displayMirrorRequested = false;
     3.7 -        FormHandshake                   form                   = null;
     3.8 +        private HandshakeDialog         handshakeDialog        = null;
     3.9          private bool                    isEnabled              = true;
    3.10          private bool?                   isExpandedPrevious     = null;
    3.11          private bool                    isManagerFormEnabled   = true;
    3.12 @@ -172,8 +172,6 @@
    3.13          /// </summary>
    3.14          private void BuildAndShowManager()
    3.15          {
    3.16 -            DialogResult result;
    3.17 -
    3.18              /* Resolve all recipients -- this ensures the identities list is correctly populated
    3.19               * 
    3.20               * Note: The PropertyChanged changed event must be disconnected before trying to resolve.
    3.21 @@ -191,20 +189,16 @@
    3.22                  Log.Verbose("BuildAndShowManager: Error resolving recipients. " + e.Message);
    3.23              }
    3.24  
    3.25 -            // Build the manager state
    3.26 +            // Build the dialog
    3.27              try
    3.28              {
    3.29 -                form = new FormHandshake();
    3.30 -                form.StartPosition = FormStartPosition.CenterParent;
    3.31 -                form.FormClosed += ManagerForm_FormClosed;
    3.32 -                form.DisplayState = new FormControlHandshake.State(this.cryptableMailItem.Myself,
    3.33 -                                                                   this.cryptableMailItem.From,
    3.34 -                                                                   this.cryptableMailItem.Recipients,
    3.35 -                                                                   this.cryptableMailItem.IsIncoming);
    3.36 -                // Update window if handshake dialog was updated
    3.37 -                form.DisplayState.OnUpdateStatus += ManagerForm_Updated;
    3.38 -
    3.39 -                result = form.ShowDialog(this.ParentForm);
    3.40 +                handshakeDialog = new HandshakeDialog(this.cryptableMailItem.Myself,
    3.41 +                                                          this.cryptableMailItem.From,
    3.42 +                                                          this.cryptableMailItem.Recipients,
    3.43 +                                                          this.cryptableMailItem.IsIncoming);
    3.44 +                handshakeDialog.OnUpdateStatus += HandshakeDialog_Updated;
    3.45 +                handshakeDialog.Closed += HandshakeDialog_Closed;
    3.46 +                handshakeDialog.ShowDialog();
    3.47              }
    3.48              catch (Exception e)
    3.49              {
    3.50 @@ -1147,11 +1141,24 @@
    3.51          }
    3.52  
    3.53          /// <summary>
    3.54 -        /// Event handler for when the manager form was updated.
    3.55 +        /// Event handler for when a handshake dialog was updated.
    3.56          /// </summary>
    3.57 -        private void ManagerForm_Updated(object sender, EventArgs e)
    3.58 +        private void HandshakeDialog_Updated(object sender, EventArgs e)
    3.59          {
    3.60 -            this.ImmediateRatingAndUIUpdate();
    3.61 +            this.RequestRatingAndUIUpdate();
    3.62 +        }
    3.63 +
    3.64 +        /// <summary>
    3.65 +        /// Event handler for when a handshake dialog was closed.
    3.66 +        /// </summary>
    3.67 +        private void HandshakeDialog_Closed(object sender, EventArgs e)
    3.68 +        {
    3.69 +            if (this.handshakeDialog != null)
    3.70 +            {
    3.71 +                this.handshakeDialog.OnUpdateStatus -= HandshakeDialog_Updated;
    3.72 +                this.handshakeDialog.Closed -= HandshakeDialog_Closed;
    3.73 +                this.handshakeDialog = null;
    3.74 +            }
    3.75          }
    3.76  
    3.77          /// <summary>
    3.78 @@ -1166,12 +1173,6 @@
    3.79                  this.managerForm = null;
    3.80              }
    3.81  
    3.82 -            if ((this.form != null) &&
    3.83 -                (this.form.DisplayState != null))
    3.84 -            {
    3.85 -                this.form.DisplayState.OnUpdateStatus -= ManagerForm_Updated;
    3.86 -            }
    3.87 -
    3.88              return;
    3.89          }
    3.90  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/UI/HandshakeDialog.xaml	Wed Mar 08 16:23:28 2017 +0100
     4.3 @@ -0,0 +1,298 @@
     4.4 +´╗┐<Window x:Class="pEp.UI.HandshakeDialog"
     4.5 +        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     4.6 +        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4.7 +        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     4.8 +        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     4.9 +        xmlns:core="clr-namespace:System;assembly=mscorlib"
    4.10 +        xmlns:p="clr-namespace:pEp.Properties"
    4.11 +        xmlns:local="clr-namespace:pEp.UI"
    4.12 +        x:ClassModifier="internal"
    4.13 +        mc:Ignorable="d"
    4.14 +        MinHeight="5"
    4.15 +        Height="Auto"
    4.16 +        Width="488"
    4.17 +        ResizeMode="NoResize"
    4.18 +        SizeToContent="Height"
    4.19 +        Background="{x:Static SystemColors.MenuBarBrush}"
    4.20 +        Icon="pack://application:,,,/pEp;component/Resources/ImageLogoSmall.png"
    4.21 +        WindowStartupLocation="CenterScreen">
    4.22 +    <Window.Resources>
    4.23 +        <ResourceDictionary>
    4.24 +            <!-- Converters -->
    4.25 +            <BooleanToVisibilityConverter x:Key="BoolToVisibility" />
    4.26 +            <local:IsActiveTabToBoolConverter x:Key="IsActiveTabToBool" />
    4.27 +            <local:ValueConverterGroup x:Key="IsActiveTabToVisibility">
    4.28 +                <local:IsActiveTabToBoolConverter />
    4.29 +                <BooleanToVisibilityConverter />
    4.30 +            </local:ValueConverterGroup>
    4.31 +            <local:ValueConverterGroup x:Key="IsActiveTabToBackground">
    4.32 +                <local:IsActiveTabToBoolConverter />
    4.33 +                <local:BooleanToBackgroundConverter />
    4.34 +            </local:ValueConverterGroup>
    4.35 +            <local:InvertBoolConverter x:Key="InvertBool" />
    4.36 +            <local:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibility" />
    4.37 +            <local:ValueConverterGroup x:Key="InvertBoolToVisibility">
    4.38 +                <local:InvertBoolConverter />
    4.39 +                <BooleanToVisibilityConverter />
    4.40 +            </local:ValueConverterGroup>
    4.41 +            <local:ValueConverterGroup x:Key="IsStandardModeToVisibility">
    4.42 +                <local:IsStandardModeToBoolConverter />
    4.43 +                <BooleanToVisibilityConverter />
    4.44 +            </local:ValueConverterGroup>
    4.45 +            <local:ValueConverterGroup x:Key="IsNotStandardModeToVisibility">
    4.46 +                <local:IsStandardModeToBoolConverter />
    4.47 +                <local:InvertBoolConverter />
    4.48 +                <BooleanToVisibilityConverter />
    4.49 +            </local:ValueConverterGroup>
    4.50 +            <local:ValueConverterGroup x:Key="IsStringEmptyToVisibility">
    4.51 +                <local:IsStringEmptyConverter />
    4.52 +                <local:InvertBoolConverter />
    4.53 +                <BooleanToVisibilityConverter />
    4.54 +            </local:ValueConverterGroup>
    4.55 +
    4.56 +            <!-- Dictionary -->
    4.57 +            <ResourceDictionary.MergedDictionaries>
    4.58 +                <ResourceDictionary Source="pack://application:,,,/pEp;component/Resources/Dictionary.xaml" />
    4.59 +            </ResourceDictionary.MergedDictionaries>
    4.60 +        </ResourceDictionary>
    4.61 +    </Window.Resources>
    4.62 +    <Grid Name="GridLayoutRoot"
    4.63 +          Margin="5">
    4.64 +        <Grid.RowDefinitions>
    4.65 +            <RowDefinition Height="Auto" />
    4.66 +            <RowDefinition Height="Auto" />
    4.67 +        </Grid.RowDefinitions>
    4.68 +
    4.69 +        <!--Information section-->
    4.70 +        <TextBlock Grid.Row="0"
    4.71 +                   Text="{Binding Path=ExplanationText, Mode=OneWay}"
    4.72 +                   TextWrapping="Wrap"
    4.73 +                   Margin="5,5,5,15" />
    4.74 +
    4.75 +        <!--Identities section-->
    4.76 +        <ItemsControl Grid.Row="1"
    4.77 +                      ItemsSource="{Binding Path=Items}">
    4.78 +            <ItemsControl.ItemTemplate>
    4.79 +                <DataTemplate>
    4.80 +
    4.81 +                    <!--Template for identities-->
    4.82 +                    <StackPanel>
    4.83 +                        <StackPanel.Style>
    4.84 +                            <Style TargetType="StackPanel">
    4.85 +                                <Setter Property="Background"
    4.86 +                                        Value="Transparent" />
    4.87 +                                <Style.Triggers>
    4.88 +                                    <MultiDataTrigger>
    4.89 +                                        <MultiDataTrigger.Conditions>
    4.90 +                                            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}"
    4.91 +                                                       Value="True" />
    4.92 +                                            <Condition Binding="{Binding Path=IsExpanded}"
    4.93 +                                                       Value="False" />
    4.94 +                                            <Condition Binding="{Binding Path=IsButtonVisible}"
    4.95 +                                                       Value="False" />
    4.96 +                                            <Condition Binding="{Binding Path=IsClickable}"
    4.97 +                                                       Value="True" />
    4.98 +                                        </MultiDataTrigger.Conditions>
    4.99 +                                        <Setter Property="Background"
   4.100 +                                                Value="{x:Static SystemColors.ControlLightBrush}" />
   4.101 +                                    </MultiDataTrigger>
   4.102 +                                </Style.Triggers>
   4.103 +                            </Style>
   4.104 +                        </StackPanel.Style>
   4.105 +
   4.106 +                        <!--The list entry-->
   4.107 +                        <Grid Name="IdentityGrid"
   4.108 +                              Background="Transparent"
   4.109 +                              Margin="5"
   4.110 +                              MinHeight="15"
   4.111 +                              MouseLeftButtonUp="IdentityGrid_MouseLeftButtonUp"
   4.112 +                              Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Mode, Converter={StaticResource IsStandardModeToVisibility}, ConverterParameter=Standard}">
   4.113 +                            <Grid.ColumnDefinitions>
   4.114 +                                <ColumnDefinition Width="Auto" />
   4.115 +                                <ColumnDefinition Width="*" />
   4.116 +                                <ColumnDefinition Width="Auto" />
   4.117 +                            </Grid.ColumnDefinitions>
   4.118 +
   4.119 +                            <!--The identity rating-->
   4.120 +                            <Image Grid.Column="0"
   4.121 +                                   Height="15"
   4.122 +                                   Stretch="Uniform"
   4.123 +                                   VerticalAlignment="Stretch"
   4.124 +                                   HorizontalAlignment="Center"
   4.125 +                                   Margin="0,0,5,0"
   4.126 +                                   Source="{Binding Path=ItemImage, Mode=OneWay}">
   4.127 +                            </Image>
   4.128 +
   4.129 +                            <!--The identity name-->
   4.130 +                            <TextBlock Grid.Column="1"
   4.131 +                                       HorizontalAlignment="Left"
   4.132 +                                       VerticalAlignment="Center"
   4.133 +                                       Margin="5,0"
   4.134 +                                       Text="{Binding Path=ItemName, Mode=OneWay}" />
   4.135 +
   4.136 +                            <!--Action button-->
   4.137 +                            <Button Grid.Column="2"
   4.138 +                                    Style="{StaticResource StyleTrustButton}"
   4.139 +                                    Visibility="{Binding Path=IsButtonVisible, Converter={StaticResource BoolToVisibility}}"
   4.140 +                                    Margin="5"
   4.141 +                                    HorizontalAlignment="Right"
   4.142 +                                    Content="{Binding Path=ButtonText, Mode=OneWay}"
   4.143 +                                    Click="ButtonTrust_Click" />
   4.144 +                        </Grid>
   4.145 +
   4.146 +                        <!--Advanced section-->
   4.147 +                        <StackPanel Visibility="{Binding Path=IsExpanded, Converter={StaticResource BoolToVisibility}}">
   4.148 +
   4.149 +                            <!--Tabs-->
   4.150 +                            <StackPanel Orientation="Horizontal"
   4.151 +                                        HorizontalAlignment="Right">
   4.152 +                                <Label Name="TrustwordsTabControl"
   4.153 +                                       MouseLeftButtonUp="TabControl_MouseLeftButtonUp"
   4.154 +                                       Content="{x:Static p:Resources.Handshake_TrustwordsText}"
   4.155 +                                       Visibility="{Binding Path=AreTabControlsVisible, Converter={StaticResource BoolToVisibility}}">
   4.156 +                                    <Label.Style>
   4.157 +                                        <Style TargetType="Label">
   4.158 +                                            <Setter Property="BorderBrush"
   4.159 +                                                    Value="LightGray" />
   4.160 +                                            <Setter Property="Background"
   4.161 +                                                    Value="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBackground}, ConverterParameter=Trustwords}" />
   4.162 +                                            <Setter Property="BorderThickness"
   4.163 +                                                    Value="1" />
   4.164 +                                            <Setter Property="Padding"
   4.165 +                                                    Value="10,5" />
   4.166 +                                            <Style.Triggers>
   4.167 +                                                <MultiDataTrigger>
   4.168 +                                                    <MultiDataTrigger.Conditions>
   4.169 +                                                        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}"
   4.170 +                                                                   Value="True" />
   4.171 +                                                        <Condition Binding="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBool}, ConverterParameter=Trustwords}"
   4.172 +                                                                   Value="False" />
   4.173 +                                                    </MultiDataTrigger.Conditions>
   4.174 +                                                    <Setter Property="Background"
   4.175 +                                                            Value="AliceBlue" />
   4.176 +                                                    <Setter Property="BorderBrush"
   4.177 +                                                            Value="LightSkyBlue" />
   4.178 +                                                </MultiDataTrigger>
   4.179 +                                            </Style.Triggers>
   4.180 +                                        </Style>
   4.181 +                                    </Label.Style>
   4.182 +                                </Label>
   4.183 +                                <Label Name="FingerprintTabControl"
   4.184 +                                       MouseLeftButtonUp="TabControl_MouseLeftButtonUp"
   4.185 +                                       Content="{x:Static p:Resources.Handshake_FingerprintText}"
   4.186 +                                       Visibility="{Binding Path=AreTabControlsVisible, Converter={StaticResource BoolToVisibility}}">
   4.187 +                                    <Label.Style>
   4.188 +                                        <Style TargetType="Label">
   4.189 +                                            <Setter Property="BorderBrush"
   4.190 +                                                    Value="LightGray" />
   4.191 +                                            <Setter Property="Background"
   4.192 +                                                    Value="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBackground}, ConverterParameter=Fingerprint}" />
   4.193 +                                            <Setter Property="BorderThickness"
   4.194 +                                                    Value="1" />
   4.195 +                                            <Setter Property="Padding"
   4.196 +                                                    Value="10,5" />
   4.197 +                                            <Style.Triggers>
   4.198 +                                                <MultiDataTrigger>
   4.199 +                                                    <MultiDataTrigger.Conditions>
   4.200 +                                                        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}"
   4.201 +                                                                   Value="True" />
   4.202 +                                                        <Condition Binding="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBool}, ConverterParameter=Fingerprint}"
   4.203 +                                                                   Value="False" />
   4.204 +                                                    </MultiDataTrigger.Conditions>
   4.205 +                                                    <Setter Property="Background"
   4.206 +                                                            Value="AliceBlue" />
   4.207 +                                                    <Setter Property="BorderBrush"
   4.208 +                                                            Value="LightSkyBlue" />
   4.209 +                                                </MultiDataTrigger>
   4.210 +                                            </Style.Triggers>
   4.211 +                                        </Style>
   4.212 +                                    </Label.Style>
   4.213 +                                </Label>
   4.214 +
   4.215 +                                <!--Language selector-->
   4.216 +                                <ComboBox Padding="10,2"
   4.217 +                                          VerticalContentAlignment="Center"
   4.218 +                                          ItemsSource="{Binding Path=TrustwordsCultureList, Mode=OneWay}"
   4.219 +                                          DisplayMemberPath="Value"
   4.220 +                                          SelectedValuePath="Key"
   4.221 +                                          SelectedValue="{Binding Path=TrustwordsCulture, Mode=TwoWay}" />
   4.222 +                            </StackPanel>
   4.223 +
   4.224 +                            <!-- Trustwords -->
   4.225 +                            <StackPanel Background="White"
   4.226 +                                        Visibility="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToVisibility}, ConverterParameter=Trustwords}">
   4.227 +                                <TextBlock Text="{Binding Path=TrustwordsShort}"
   4.228 +                                           Visibility="{Binding Path=AreTrustwordsExpanded, Converter={StaticResource InvertBoolToVisibility}}"
   4.229 +                                           TextWrapping="Wrap"
   4.230 +                                           Padding="10" />
   4.231 +                                <TextBlock Text="{Binding Path=TrustwordsFull}"
   4.232 +                                           Visibility="{Binding Path=AreTrustwordsExpanded, Converter={StaticResource BoolToVisibility}}"
   4.233 +                                           TextWrapping="Wrap"
   4.234 +                                           Padding="10" />
   4.235 +                                <TextBlock Text="..."
   4.236 +                                           Padding="10"
   4.237 +                                           MouseLeftButtonUp="TextBlock_MouseLeftButtonUp">
   4.238 +                                    <TextBlock.Style>
   4.239 +                                        <Style>
   4.240 +                                            <Style.Triggers>
   4.241 +                                                <Trigger Property="TextBlock.IsMouseOver"
   4.242 +                                                         Value="True">
   4.243 +                                                    <Setter Property="TextBlock.Background"
   4.244 +                                                            Value="AliceBlue" />
   4.245 +                                                </Trigger>
   4.246 +                                            </Style.Triggers>
   4.247 +                                        </Style>
   4.248 +                                    </TextBlock.Style>
   4.249 +                                </TextBlock>
   4.250 +                            </StackPanel>
   4.251 +
   4.252 +                            <!--Fingerprints-->
   4.253 +                            <StackPanel Background="White"
   4.254 +                                        Visibility="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToVisibility}, ConverterParameter=Fingerprint}">
   4.255 +                                <TextBlock Text="{Binding Path=Partner.UserName}"
   4.256 +                                           Margin="10,10,10,2" />
   4.257 +                                <TextBlock Text="{Binding Path=FingerprintPartner}"
   4.258 +                                           Margin="10,2,10,22" />
   4.259 +                                <TextBlock Text="{Binding Path=Myself.UserName}"
   4.260 +                                           Margin="10,10,10,2" />
   4.261 +                                <TextBlock Text="{Binding Path=FingerprintMyself}"
   4.262 +                                           Margin="10,2,10,10" />
   4.263 +                            </StackPanel>
   4.264 +
   4.265 +                            <!-- Buttons -->
   4.266 +                            <StackPanel Grid.Row="5"
   4.267 +                                        Orientation="Horizontal"
   4.268 +                                        HorizontalAlignment="Right">
   4.269 +                                <StackPanel.Margin>
   4.270 +                                    <Thickness Bottom="0"
   4.271 +                                               Left="0"
   4.272 +                                               Right="0"
   4.273 +                                               Top="{StaticResource Spacing}" />
   4.274 +                                </StackPanel.Margin>
   4.275 +                                <StackPanel.Children>
   4.276 +                                    <Button Style="{StaticResource StyleWrongButton}"
   4.277 +                                            HorizontalAlignment="Left"
   4.278 +                                            Margin="10,5"
   4.279 +                                            Content="{Binding Path=ExpandedButton2Text, FallbackValue=Wrong}"
   4.280 +                                            Click="ButtonWrong_Click" />
   4.281 +                                    <Button Style="{StaticResource StyleConfirmButton}"
   4.282 +                                            HorizontalAlignment="Left"
   4.283 +                                            Margin="10,5"
   4.284 +                                            Content="{Binding Path=ExpandedButton1Text, FallbackValue=Confirm}"
   4.285 +                                            Click="ButtonConfirm_Click"
   4.286 +                                            IsDefault="True" />
   4.287 +                                </StackPanel.Children>
   4.288 +                            </StackPanel>
   4.289 +                        </StackPanel>
   4.290 +
   4.291 +                        <!--Separator between items-->
   4.292 +                        <Separator Margin="5,5,5,0"
   4.293 +                                   Background="LightGray"
   4.294 +                                   Visibility="{Binding Path=IsSeparatorVisible, Converter={StaticResource BoolToVisibility}}" />
   4.295 +
   4.296 +                    </StackPanel>
   4.297 +                </DataTemplate>
   4.298 +            </ItemsControl.ItemTemplate>
   4.299 +        </ItemsControl>
   4.300 +    </Grid>
   4.301 +</Window>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/UI/HandshakeDialog.xaml.cs	Wed Mar 08 16:23:28 2017 +0100
     5.3 @@ -0,0 +1,794 @@
     5.4 +´╗┐using pEpCOMServerAdapterLib;
     5.5 +using System;
     5.6 +using System.Collections.Generic;
     5.7 +using System.Collections.ObjectModel;
     5.8 +using System.ComponentModel;
     5.9 +using System.Linq;
    5.10 +using System.Runtime.InteropServices;
    5.11 +using System.Windows;
    5.12 +using System.Windows.Controls;
    5.13 +using System.Windows.Input;
    5.14 +using System.Windows.Media.Imaging;
    5.15 +
    5.16 +namespace pEp.UI
    5.17 +{
    5.18 +    /// <summary>
    5.19 +    /// Interaction logic for HandshakeDialog.xaml
    5.20 +    /// </summary>
    5.21 +    internal partial class HandshakeDialog : Window,
    5.22 +                                             INotifyPropertyChanged,
    5.23 +                                             Interfaces.IReset
    5.24 +
    5.25 +    {
    5.26 +        public delegate void StatusUpdateHandler(object sender, EventArgs e);
    5.27 +
    5.28 +        /// <summary>
    5.29 +        /// Event raised when the state is updated.
    5.30 +        /// </summary>
    5.31 +        public event StatusUpdateHandler OnUpdateStatus;
    5.32 +
    5.33 +        /// <summary>
    5.34 +        /// Event raised when a property is changed on a component.
    5.35 +        /// </summary>
    5.36 +        public event PropertyChangedEventHandler PropertyChanged;
    5.37 +
    5.38 +        /// <summary>
    5.39 +        /// Enumeration to define the mode of the handshake.
    5.40 +        /// </summary>
    5.41 +        public enum HandshakeMode
    5.42 +        {
    5.43 +            /// <summary>
    5.44 +            /// Standard handshake for use with common messages and identities.
    5.45 +            /// </summary>
    5.46 +            Standard,
    5.47 +
    5.48 +            /// <summary>
    5.49 +            /// Special handshake for use with synchronization.
    5.50 +            /// This is to create a device group.
    5.51 +            /// </summary>
    5.52 +            SyncTypeA,
    5.53 +
    5.54 +            /// <summary>
    5.55 +            /// Special handshake for use with synchronization.
    5.56 +            /// This is to move a device from an existing device group to another one.
    5.57 +            /// </summary>
    5.58 +            SyncTypeB,
    5.59 +
    5.60 +            /// <summary>
    5.61 +            /// Special handshake for use with synchronization.
    5.62 +            /// This is to allow a device to join an existing device group.
    5.63 +            /// </summary>
    5.64 +            SyncTypeC
    5.65 +        }
    5.66 +
    5.67 +        private string                                  _ExplanationText;
    5.68 +        private PEPIdentity                             _From;
    5.69 +        private ObservableCollection<HandshakeItem>     _Items;
    5.70 +        private bool                                    _IsIncoming;
    5.71 +        private HandshakeMode                           _Mode;
    5.72 +        private PEPIdentity                             _Myself;
    5.73 +        private List<PEPIdentity>                       _Recipients;
    5.74 +        private PEPIdentity                             _SyncPartner;
    5.75 +
    5.76 +        /**************************************************************
    5.77 +         * 
    5.78 +         * Constructors
    5.79 +         * 
    5.80 +         *************************************************************/
    5.81 +
    5.82 +        /// <summary>
    5.83 +        /// Default constructor.
    5.84 +        /// </summary>
    5.85 +        public HandshakeDialog()
    5.86 +        {
    5.87 +            this.InitializeDialog();
    5.88 +        }
    5.89 +
    5.90 +        /// <summary>
    5.91 +        /// Constructor to build a key sync handshake dialog.
    5.92 +        /// </summary>
    5.93 +        /// <param name="ownIdentity">The Myself identity.</param>
    5.94 +        /// <param name="partnerIdentity">The Partner identity.</param>
    5.95 +        /// <param name="mode">The handshake mode.</param>
    5.96 +        public HandshakeDialog(PEPIdentity ownIdentity,
    5.97 +                               PEPIdentity partnerIdentity,
    5.98 +                               HandshakeMode mode)
    5.99 +        {
   5.100 +            this.InitializeDialog();
   5.101 +
   5.102 +            this.Myself = ownIdentity;
   5.103 +            this.SyncPartner = partnerIdentity;
   5.104 +            this.Mode = mode;
   5.105 +
   5.106 +            this.BuildDialog();
   5.107 +        }
   5.108 +
   5.109 +        /// <summary>
   5.110 +        /// Constructor to build a handshake dialog for a set of recipients.
   5.111 +        /// </summary>
   5.112 +        /// <param name="myself">The Myself identity.</param>
   5.113 +        /// <param name="from">The From Identity.</param>
   5.114 +        /// <param name="recipients">The list of recipients.</param>
   5.115 +        /// <param name="isIncoming">Whether the mail item is incoming or not.</param>
   5.116 +        public HandshakeDialog(PEPIdentity myself,
   5.117 +                               PEPIdentity from,
   5.118 +                               List<PEPIdentity> recipients,
   5.119 +                               bool isIncoming)
   5.120 +        {
   5.121 +            this.InitializeDialog();
   5.122 +
   5.123 +            this.Myself = myself;
   5.124 +            this.From = from;
   5.125 +            this.IsIncoming = isIncoming;
   5.126 +            this.Recipients = recipients;
   5.127 +
   5.128 +            this.BuildDialog();
   5.129 +        }
   5.130 +
   5.131 +        /**************************************************************
   5.132 +         * 
   5.133 +         * Property Accessors
   5.134 +         * 
   5.135 +         *************************************************************/
   5.136 +
   5.137 +        /// <summary>
   5.138 +        /// Gets or sets the explanatory text in the handshake window
   5.139 +        /// </summary>
   5.140 +        public string ExplanationText
   5.141 +        {
   5.142 +            get { return this._ExplanationText; }
   5.143 +            set
   5.144 +            {
   5.145 +                this._ExplanationText = value;
   5.146 +                this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
   5.147 +            }
   5.148 +        }
   5.149 +
   5.150 +        /// <summary>
   5.151 +        /// Gets or sets the From identity.
   5.152 +        /// </summary>
   5.153 +        public PEPIdentity From
   5.154 +        {
   5.155 +            get { return this._From; }
   5.156 +            set
   5.157 +            {
   5.158 +                this._From = value;
   5.159 +                this.RaisePropertyChangedEvent(nameof(this.From));
   5.160 +            }
   5.161 +        }
   5.162 +
   5.163 +        /// <summary>
   5.164 +        /// Gets or sets the items collection.
   5.165 +        /// </summary>
   5.166 +        public ObservableCollection<HandshakeItem> Items
   5.167 +        {
   5.168 +            get { return this._Items; }
   5.169 +            set
   5.170 +            {
   5.171 +                this._Items = value;
   5.172 +                this.RaisePropertyChangedEvent(nameof(this.Items));
   5.173 +            }
   5.174 +        }
   5.175 +
   5.176 +        /// <summary>
   5.177 +        /// Gets or sets whether the mail is incoming or not.
   5.178 +        /// </summary>
   5.179 +        public bool IsIncoming
   5.180 +        {
   5.181 +            get { return this._IsIncoming; }
   5.182 +            set
   5.183 +            {
   5.184 +                this._IsIncoming = value;
   5.185 +                this.RaisePropertyChangedEvent(nameof(this.IsIncoming));
   5.186 +            }
   5.187 +        }
   5.188 +
   5.189 +        /// <summary>
   5.190 +        /// Gets or sets the mode of the handshake.
   5.191 +        /// </summary>
   5.192 +        public HandshakeMode Mode
   5.193 +        {
   5.194 +            get { return (this._Mode); }
   5.195 +            set
   5.196 +            {
   5.197 +                this._Mode = value;
   5.198 +                this.RaisePropertyChangedEvent(nameof(this.Mode));
   5.199 +
   5.200 +                this.CalcDependentProperties();
   5.201 +            }
   5.202 +        }
   5.203 +
   5.204 +        /// <summary>
   5.205 +        /// Gets or sets the identity of myself.
   5.206 +        /// </summary>
   5.207 +        public PEPIdentity Myself
   5.208 +        {
   5.209 +            get { return (this._Myself); }
   5.210 +            set
   5.211 +            {
   5.212 +                this._Myself = value;
   5.213 +                this.RaisePropertyChangedEvent(nameof(this.Myself));
   5.214 +            }
   5.215 +        }
   5.216 +
   5.217 +        /// <summary>
   5.218 +        /// Gets or sets the list of recipients.
   5.219 +        /// </summary>
   5.220 +        public List<PEPIdentity> Recipients
   5.221 +        {
   5.222 +            get { return (this._Recipients); }
   5.223 +            set
   5.224 +            {
   5.225 +                this._Recipients = value;
   5.226 +                this.RaisePropertyChangedEvent(nameof(this.Recipients));
   5.227 +            }
   5.228 +        }
   5.229 +
   5.230 +        /// <summary>
   5.231 +        /// Gets or sets the sync partner identity.
   5.232 +        /// </summary>
   5.233 +        public PEPIdentity SyncPartner
   5.234 +        {
   5.235 +            get { return (this._SyncPartner); }
   5.236 +            set
   5.237 +            {
   5.238 +                this._SyncPartner = value;
   5.239 +                this.RaisePropertyChangedEvent(nameof(this.SyncPartner));
   5.240 +            }
   5.241 +        }
   5.242 +
   5.243 +        /**************************************************************
   5.244 +         * 
   5.245 +         * Event Handling
   5.246 +         * 
   5.247 +         *************************************************************/
   5.248 +
   5.249 +        /// <summary>
   5.250 +        /// Event handler for when an identity entry was clicked.
   5.251 +        /// </summary>
   5.252 +        private void IdentityGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
   5.253 +        {
   5.254 +            Grid grid = sender as Grid;
   5.255 +            if (grid != null)
   5.256 +            {
   5.257 +                HandshakeItem handshakeItem = grid.DataContext as HandshakeItem;
   5.258 +
   5.259 +                if ((handshakeItem != null) &&
   5.260 +                    (handshakeItem.IsClickable))
   5.261 +                {
   5.262 +                    foreach (var item in this._Items)
   5.263 +                    {
   5.264 +                        if (item.Equals(handshakeItem) == false)
   5.265 +                        {
   5.266 +                            item.IsExpanded = false;
   5.267 +                            item.IsButtonVisible = false;
   5.268 +                        }
   5.269 +                    }
   5.270 +
   5.271 +                    if (handshakeItem.IsExpandable)
   5.272 +                    {
   5.273 +                        handshakeItem.IsExpanded = !handshakeItem.IsExpanded;
   5.274 +                    }
   5.275 +                    else
   5.276 +                    {
   5.277 +                        handshakeItem.IsButtonVisible = true;
   5.278 +                    }
   5.279 +                }
   5.280 +            }
   5.281 +        }
   5.282 +
   5.283 +        /// <summary>
   5.284 +        /// Event handler for when a custom tab control is clicked.
   5.285 +        /// </summary>
   5.286 +        private void TabControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
   5.287 +        {
   5.288 +            Label label = sender as Label;
   5.289 +
   5.290 +            if (label != null)
   5.291 +            {
   5.292 +                HandshakeItem handshakeItem = label.DataContext as HandshakeItem;
   5.293 +
   5.294 +                if (handshakeItem != null)
   5.295 +                {
   5.296 +                    if (label.Name == "TrustwordsTabControl")
   5.297 +                    {
   5.298 +                        handshakeItem.ActiveTab = HandshakeItem.Tabs.Trustwords;
   5.299 +                    }
   5.300 +                    else if (label.Name == "FingerprintTabControl")
   5.301 +                    {
   5.302 +                        handshakeItem.ActiveTab = HandshakeItem.Tabs.Fingerprint;
   5.303 +                    }
   5.304 +                }
   5.305 +            }
   5.306 +        }
   5.307 +
   5.308 +        /// <summary>
   5.309 +        /// Event handler for when the three dots in trustwords mode are clicked.
   5.310 +        /// </summary>
   5.311 +        private void TextBlock_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
   5.312 +        {
   5.313 +            TextBlock textBlock = sender as TextBlock;
   5.314 +
   5.315 +            if (textBlock != null)
   5.316 +            {
   5.317 +                HandshakeItem handshakeItem = textBlock.DataContext as HandshakeItem;
   5.318 +
   5.319 +                if (handshakeItem != null)
   5.320 +                {
   5.321 +                    handshakeItem.AreTrustwordsExpanded = !handshakeItem.AreTrustwordsExpanded;
   5.322 +                }
   5.323 +            }
   5.324 +        }
   5.325 +
   5.326 +        /// <summary>
   5.327 +        /// Event handler for when a property is changed within the display state.
   5.328 +        /// </summary>
   5.329 +        private void DisplayState_PropertyChanged(object sender, PropertyChangedEventArgs e)
   5.330 +        {
   5.331 +            this.PropertyChanged?.Invoke(this, e);
   5.332 +            return;
   5.333 +        }
   5.334 +
   5.335 +        /// <summary>
   5.336 +        /// Event handler for when the confirm button is clicked.
   5.337 +        /// </summary>
   5.338 +        private void ButtonConfirm_Click(object sender, RoutedEventArgs e)
   5.339 +        {
   5.340 +            // In standard mode, update identity
   5.341 +            if (this._Mode == HandshakeMode.Standard)
   5.342 +            {
   5.343 +                pEpRating partnerIdentityRating;
   5.344 +                pEpColor partnerIdentityColor;
   5.345 +                pEpIdentity identityPartner;
   5.346 +
   5.347 +                Button btn = sender as Button;
   5.348 +                if (btn != null)
   5.349 +                {
   5.350 +                    HandshakeItem handshakeItem = btn.DataContext as HandshakeItem;
   5.351 +                    if ((handshakeItem != null) &&
   5.352 +                        (handshakeItem.Partner != null))
   5.353 +                    {
   5.354 +                        identityPartner = handshakeItem.Partner.ToCOMType();
   5.355 +                        try
   5.356 +                        {
   5.357 +                            identityPartner = ThisAddIn.PEPEngine.UpdateIdentity(identityPartner);
   5.358 +                            partnerIdentityRating = ThisAddIn.PEPEngine.IdentityRating(identityPartner);
   5.359 +                        }
   5.360 +                        catch (COMException ex)
   5.361 +                        {
   5.362 +                            partnerIdentityRating = pEpRating.pEpRatingUndefined;
   5.363 +                            Log.Warning("ButtonConfirm_Click: Failed to get identity rating, " + ex.ToString());
   5.364 +                        }
   5.365 +                        partnerIdentityColor = partnerIdentityRating.ToColor();
   5.366 +
   5.367 +                        // Process result
   5.368 +                        try
   5.369 +                        {
   5.370 +                            if (partnerIdentityColor == pEpColor.pEpColorRed)
   5.371 +                            {
   5.372 +                                ThisAddIn.PEPEngine.KeyResetTrust(ref identityPartner);
   5.373 +                            }
   5.374 +
   5.375 +                            identityPartner = ThisAddIn.PEPEngine.TrustPersonalKey(ref identityPartner);
   5.376 +
   5.377 +                        }
   5.378 +                        catch (Exception ex)
   5.379 +                        {
   5.380 +                            Log.Error("ButtonConfirm_Click: Error occured while trying to set trust: " + ex.ToString());
   5.381 +                        }
   5.382 +
   5.383 +                        this.Reload();
   5.384 +                    }
   5.385 +                }
   5.386 +            }
   5.387 +            // In key sync mode, close window
   5.388 +            else
   5.389 +            {
   5.390 +                this.DialogResult = true;
   5.391 +                this.Close();
   5.392 +            }
   5.393 +        }
   5.394 +
   5.395 +        /// <summary>
   5.396 +        /// Event handler for when the wrong button is clicked.
   5.397 +        /// </summary>
   5.398 +        private void ButtonWrong_Click(object sender, RoutedEventArgs e)
   5.399 +        {
   5.400 +            // In standard mode, update identity
   5.401 +            if (this._Mode == HandshakeMode.Standard)
   5.402 +            {
   5.403 +                Button btn = sender as Button;
   5.404 +                if (btn != null)
   5.405 +                {
   5.406 +                    HandshakeItem handshakeItem = btn.DataContext as HandshakeItem;
   5.407 +                    if ((handshakeItem != null) &&
   5.408 +                        (handshakeItem.Partner != null))
   5.409 +                    {
   5.410 +                        pEpIdentity identityPartner = handshakeItem.Partner.ToCOMType();
   5.411 +
   5.412 +                        // Set the trust to mistrusted
   5.413 +                        try
   5.414 +                        {
   5.415 +                            ThisAddIn.PEPEngine.KeyMistrusted(ref identityPartner);
   5.416 +                        }
   5.417 +                        catch (Exception ex)
   5.418 +                        {
   5.419 +                            Log.Error("ButtonWrong_Click: Error occured while trying to mistrust key: " + ex.ToString());
   5.420 +                        }
   5.421 +
   5.422 +                        this.Reload();
   5.423 +                    }
   5.424 +                }
   5.425 +            }
   5.426 +            // In key sync mode, close window
   5.427 +            else
   5.428 +            {
   5.429 +                this.DialogResult = false;
   5.430 +                this.Close();
   5.431 +            }
   5.432 +        }
   5.433 +
   5.434 +        /// <summary>
   5.435 +        /// Event handler for when the start/stop trusting button is clicked.
   5.436 +        /// </summary>
   5.437 +        private void ButtonTrust_Click(object sender, RoutedEventArgs e)
   5.438 +        {
   5.439 +            Button btn = sender as Button;
   5.440 +            if (btn != null)
   5.441 +            {
   5.442 +                HandshakeItem handshakeItem = btn.DataContext as HandshakeItem;
   5.443 +                if ((handshakeItem != null) &&
   5.444 +                    (handshakeItem.Partner != null))
   5.445 +                {
   5.446 +                    pEpIdentity identityPartner = handshakeItem.Partner.ToCOMType();
   5.447 +
   5.448 +                    // Reset trust. This applies for formerly trusted and mistrusted keys
   5.449 +                    try
   5.450 +                    {
   5.451 +                        ThisAddIn.PEPEngine.KeyResetTrust(ref identityPartner);
   5.452 +                    }
   5.453 +                    catch (Exception ex)
   5.454 +                    {
   5.455 +                        Log.Error("ButtonTrust_Click: Error occured while trying to reset trust: " + ex.ToString());
   5.456 +                    }
   5.457 +
   5.458 +                    this.Reload();
   5.459 +                }
   5.460 +            }
   5.461 +        }
   5.462 +
   5.463 +        /**************************************************************
   5.464 +         * 
   5.465 +         * Methods
   5.466 +         * 
   5.467 +         *************************************************************/
   5.468 +
   5.469 +        /// <summary>
   5.470 +        /// Initializes the dialog.
   5.471 +        /// </summary>
   5.472 +        private void InitializeDialog()
   5.473 +        {
   5.474 +            this.InitializeComponent();
   5.475 +            this.DataContext = this;
   5.476 +
   5.477 +            this.Reset();
   5.478 +        }
   5.479 +
   5.480 +        /// <summary>
   5.481 +        /// Raises the property changed event, if possible, with the given arguments.
   5.482 +        /// </summary>
   5.483 +        /// <param name="propertyName">The name of the property that changed.</param>
   5.484 +        private void RaisePropertyChangedEvent(string propertyName)
   5.485 +        {
   5.486 +            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   5.487 +            return;
   5.488 +        }
   5.489 +
   5.490 +        /// <summary>
   5.491 +        /// Reloads the current state.
   5.492 +        /// </summary>
   5.493 +        public void Reload()
   5.494 +        {
   5.495 +            // Rebuild state
   5.496 +            this.BuildDialog();
   5.497 +
   5.498 +            // Raise updated event
   5.499 +            OnUpdateStatus(null, new EventArgs());
   5.500 +        }
   5.501 +
   5.502 +        /// <summary>
   5.503 +        /// Builds a new key sync state.
   5.504 +        /// </summary>
   5.505 +        /// <param name="ownIdentity">The own identity.</param>
   5.506 +        /// <param name="partnerIdentity">The partner identity.</param>
   5.507 +        /// <param name="mode">The handshake mode.</param>
   5.508 +        public void BuildSyncState(PEPIdentity ownIdentity,
   5.509 +                                   PEPIdentity partnerIdentity,
   5.510 +                                   HandshakeMode mode)
   5.511 +        {
   5.512 +            this.Items = new ObservableCollection<HandshakeItem>();
   5.513 +
   5.514 +
   5.515 +        }
   5.516 +
   5.517 +        /// <summary>
   5.518 +        /// Builds the dialog.
   5.519 +        /// </summary>
   5.520 +        public void BuildDialog()
   5.521 +        {
   5.522 +            bool isMyself;
   5.523 +            int expandedItemCount = 0;
   5.524 +            int index = 0;
   5.525 +            BitmapImage imageForceUnencOn;
   5.526 +            BitmapImage imageGreen;
   5.527 +            BitmapImage imageNoColor;
   5.528 +            BitmapImage imageRed;
   5.529 +            BitmapImage imageYellow;
   5.530 +            HandshakeItem item;
   5.531 +
   5.532 +            this.Items = new ObservableCollection<HandshakeItem>();
   5.533 +
   5.534 +            if (this._Mode == HandshakeMode.Standard)
   5.535 +            {
   5.536 +                // Build standard dialog
   5.537 +                
   5.538 +                // Load all images from resources
   5.539 +                imageForceUnencOn = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImageForceUnencOn.png", UriKind.RelativeOrAbsolute));
   5.540 +                imageGreen = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusGreen.png", UriKind.RelativeOrAbsolute));
   5.541 +                imageNoColor = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusNoColor.png", UriKind.RelativeOrAbsolute));
   5.542 +                imageRed = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusRed.png", UriKind.RelativeOrAbsolute));
   5.543 +                imageYellow = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusYellow.png", UriKind.RelativeOrAbsolute));
   5.544 +
   5.545 +                // Get own identity rating
   5.546 +                try
   5.547 +                {
   5.548 +                    this.Myself.Rating = ThisAddIn.PEPEngine.IdentityRating(this.Myself.ToCOMType());
   5.549 +                }
   5.550 +                catch (COMException ex)
   5.551 +                {
   5.552 +                    this.Myself.Rating = pEpRating.pEpRatingUndefined;
   5.553 +                    Log.Warning("BuildState: Failed to get myself identity rating, " + ex.ToString());
   5.554 +                }
   5.555 +
   5.556 +                // Include the from identity for incoming messages at the beginning
   5.557 +                if ((IsIncoming) &&
   5.558 +                    (this.From != null) &&
   5.559 +                    (this.Recipients != null))
   5.560 +                {
   5.561 +                    Recipients.Insert(0, this.From);
   5.562 +                }
   5.563 +
   5.564 +                // Remove own identity from the list
   5.565 +                if ((this.Myself != null) &&
   5.566 +                    (this.Recipients != null))
   5.567 +                {
   5.568 +                    for (int i = (this.Recipients.Count - 1); i >= 0; i--)
   5.569 +                    {
   5.570 +                        if ((this.Recipients[i] != null) &&
   5.571 +                            (this.Recipients[i].EqualsByAddress(this.Myself)))
   5.572 +                        {
   5.573 +                            this.Recipients.RemoveAt(i);
   5.574 +                        }
   5.575 +                    }
   5.576 +                }
   5.577 +
   5.578 +                // Remove duplicates (by address) and add identities
   5.579 +                if (this.Recipients != null)
   5.580 +                {
   5.581 +                    this.Recipients = PEPIdentity.ToFlatList(this.Recipients);
   5.582 +                    this.Recipients = this.Recipients.GroupBy(x => x.Address).Select(x => x.First()).ToList();
   5.583 +                    foreach (PEPIdentity ident in this.Recipients)
   5.584 +                    {
   5.585 +                        if (ident.IsAddressValid)
   5.586 +                        {
   5.587 +                            // Update the partner identity to get a fingerprint, preserve IsForceUnencrypted
   5.588 +                            pEpIdentity partnerIdentity_s = ThisAddIn.PEPEngine.UpdateIdentity(ident.ToCOMType());
   5.589 +                            PEPIdentity partnerIdentity = new PEPIdentity(partnerIdentity_s);
   5.590 +                            partnerIdentity.IsForceUnencrypted = ident.IsForceUnencrypted;
   5.591 +
   5.592 +                            try
   5.593 +                            {
   5.594 +                                partnerIdentity.Rating = ThisAddIn.PEPEngine.IdentityRating(partnerIdentity_s);
   5.595 +                            }
   5.596 +                            catch (COMException ex)
   5.597 +                            {
   5.598 +                                partnerIdentity.Rating = pEpRating.pEpRatingUndefined;
   5.599 +                                Log.Warning("BuildState: Failed to get partner identity rating, " + ex.ToString());
   5.600 +                            }
   5.601 +
   5.602 +                            isMyself = PEPIdentity.GetIsOwnIdentity(partnerIdentity.Address);
   5.603 +
   5.604 +                            item = new HandshakeItem();
   5.605 +                            item.Myself = this.Myself;
   5.606 +                            item.Partner = partnerIdentity;
   5.607 +                            item.ItemName = partnerIdentity.UserName;
   5.608 +
   5.609 +                            // Check if non pEp user and show fingerprint tab in this case
   5.610 +                            if (partnerIdentity_s.CommType != pEpComType.pEpCtpEpUnconfirmed)
   5.611 +                            {
   5.612 +                                item.AreTabControlsVisible = true;
   5.613 +                            }
   5.614 +
   5.615 +                            // Set image
   5.616 +                            if ((partnerIdentity.IsForceUnencryptedBool) &&
   5.617 +                                (this.IsIncoming == false))
   5.618 +                            {
   5.619 +                                item.ItemImage = imageForceUnencOn;
   5.620 +                            }
   5.621 +                            else
   5.622 +                            {
   5.623 +                                switch (partnerIdentity.Rating.ToColor())
   5.624 +                                {
   5.625 +                                    case pEpColor.pEpColorGreen:
   5.626 +                                        item.ItemImage = imageGreen;
   5.627 +                                        break;
   5.628 +                                    case pEpColor.pEpColorYellow:
   5.629 +                                        item.ItemImage = imageYellow;
   5.630 +                                        break;
   5.631 +                                    case pEpColor.pEpColorRed:
   5.632 +                                        item.ItemImage = imageRed;
   5.633 +                                        break;
   5.634 +                                    case pEpColor.pEpColorNoColor:
   5.635 +                                        item.ItemImage = imageNoColor;
   5.636 +                                        break;
   5.637 +                                    default:
   5.638 +                                        item.ItemImage = null;
   5.639 +                                        break;
   5.640 +                                }
   5.641 +                            }
   5.642 +
   5.643 +                            // Set button
   5.644 +                            if ((isMyself) ||
   5.645 +                                ((partnerIdentity.IsForceUnencryptedBool) &&
   5.646 +                                 (this.IsIncoming == false)))
   5.647 +                            {
   5.648 +                                item.IsButtonVisible = false;
   5.649 +                                item.IsExpandable = false;
   5.650 +                                item.IsClickable = false;
   5.651 +                            }
   5.652 +                            else
   5.653 +                            {
   5.654 +                                switch (partnerIdentity.Rating.ToColor())
   5.655 +                                {
   5.656 +                                    case pEpColor.pEpColorGreen:
   5.657 +                                        {
   5.658 +                                            // Undo handshake
   5.659 +                                            item.IsButtonVisible = (expandedItemCount++ == 0);
   5.660 +                                            item.ButtonText = pEp.Properties.Resources.PrivacyStatus_StopTrusting;
   5.661 +
   5.662 +                                            break;
   5.663 +                                        }
   5.664 +                                    case pEpColor.pEpColorYellow:
   5.665 +                                        {
   5.666 +                                            // Do handshake
   5.667 +                                            item.IsExpandable = true;
   5.668 +                                            item.IsExpanded = (expandedItemCount++ == 0);
   5.669 +
   5.670 +                                            break;
   5.671 +                                        }
   5.672 +                                    case pEpColor.pEpColorRed:
   5.673 +                                        {
   5.674 +                                            // Redo handshake with confirmation
   5.675 +                                            item.IsButtonVisible = (expandedItemCount++ == 0);
   5.676 +                                            item.ButtonText = pEp.Properties.Resources.PrivacyStatus_Handshake;
   5.677 +
   5.678 +                                            break;
   5.679 +                                        }
   5.680 +                                    case pEpColor.pEpColorNoColor:
   5.681 +                                        {
   5.682 +                                            // Show item without buttons and not clickable
   5.683 +                                            item.IsButtonVisible = false;
   5.684 +                                            item.IsExpandable = false;
   5.685 +                                            item.IsClickable = false;
   5.686 +
   5.687 +                                            break;
   5.688 +                                        }
   5.689 +                                    default:
   5.690 +                                        {
   5.691 +                                            break;
   5.692 +                                        }
   5.693 +                                }
   5.694 +                            }
   5.695 +                        }
   5.696 +                        else // Invalid identity
   5.697 +                        {
   5.698 +                            item = new HandshakeItem();
   5.699 +                            item.ItemImage = null;
   5.700 +                            item.IsClickable = false;
   5.701 +                        }
   5.702 +
   5.703 +                        item.IsSeparatorVisible = (++index != Recipients.Count);
   5.704 +
   5.705 +                        this.Items.Add(item);
   5.706 +                    }
   5.707 +                }
   5.708 +                else
   5.709 +                {
   5.710 +                    Log.Error("BuildState: Recipients list is null.");
   5.711 +                }
   5.712 +            }
   5.713 +            // Build key sync dialog
   5.714 +            else
   5.715 +            {
   5.716 +                // Create one single sync item and add it to collection
   5.717 +                item = new HandshakeItem();
   5.718 +
   5.719 +                try
   5.720 +                {
   5.721 +                    item.Myself = this._Myself;
   5.722 +                    item.Partner = this._SyncPartner;
   5.723 +                    item.IsClickable = false;
   5.724 +                    item.IsExpanded = true;
   5.725 +                    item.IsSeparatorVisible = false;
   5.726 +                    item.ActiveTab = HandshakeItem.Tabs.Trustwords;
   5.727 +                }
   5.728 +                catch (Exception e)
   5.729 +                {
   5.730 +                    Log.Error("HandshakeDialog.BuildDialog: Error creating key sync item. " + e.Message);
   5.731 +                }
   5.732 +
   5.733 +                this.Items.Add(item);
   5.734 +            }
   5.735 +        }
   5.736 +
   5.737 +        /// <summary>
   5.738 +        /// Resets the object to it's default state/values.
   5.739 +        /// </summary>
   5.740 +        public void Reset()
   5.741 +        {
   5.742 +            // Set independent properties
   5.743 +            this._From = null;
   5.744 +            this._Items = new ObservableCollection<HandshakeItem>();
   5.745 +            this._IsIncoming = true;
   5.746 +            this._Mode = HandshakeMode.Standard;
   5.747 +            this._Myself = null;
   5.748 +            this._Recipients = new List<PEPIdentity>();
   5.749 +            this._SyncPartner = null;
   5.750 +
   5.751 +            this.RaisePropertyChangedEvent(nameof(this.From));
   5.752 +            this.RaisePropertyChangedEvent(nameof(this.Items));
   5.753 +            this.RaisePropertyChangedEvent(nameof(this.IsIncoming));
   5.754 +            this.RaisePropertyChangedEvent(nameof(this.Mode));
   5.755 +            this.RaisePropertyChangedEvent(nameof(this.Myself));
   5.756 +            this.RaisePropertyChangedEvent(nameof(this.Recipients));
   5.757 +            this.RaisePropertyChangedEvent(nameof(this.SyncPartner));
   5.758 +
   5.759 +            this.CalcDependentProperties();
   5.760 +
   5.761 +            return;
   5.762 +        }
   5.763 +
   5.764 +        /// <summary>
   5.765 +        /// Recalculates the dependent properties from the current independent property values. 
   5.766 +        /// This will raise property changed events.
   5.767 +        /// </summary>
   5.768 +        private void CalcDependentProperties()
   5.769 +        {
   5.770 +            switch (this.Mode)
   5.771 +            {
   5.772 +                case HandshakeMode.Standard:
   5.773 +                    this.ExplanationText = Properties.Resources.Handshake_StandardExplanationText;
   5.774 +                    this.Title = Properties.Resources.Handshake_StandardFormText;
   5.775 +                    break;
   5.776 +                case HandshakeMode.SyncTypeA:
   5.777 +                    this.ExplanationText = Properties.Resources.Handshake_SyncTypeAExplanationText;
   5.778 +                    this.Title = Properties.Resources.Handshake_SyncFormText;
   5.779 +                    break;
   5.780 +                case HandshakeMode.SyncTypeB:
   5.781 +                    this.ExplanationText = Properties.Resources.Handshake_SyncTypeBExplanationText;
   5.782 +                    this.Title = Properties.Resources.Handshake_SyncFormText;
   5.783 +                    break;
   5.784 +                case HandshakeMode.SyncTypeC:
   5.785 +                    this.ExplanationText = Properties.Resources.Handshake_SyncTypeCExplanationText;
   5.786 +                    this.Title = Properties.Resources.Handshake_SyncFormText;
   5.787 +                    break;
   5.788 +                default:
   5.789 +                    this.ExplanationText = string.Empty;
   5.790 +                    break;
   5.791 +            }
   5.792 +
   5.793 +            this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
   5.794 +            this.RaisePropertyChangedEvent(nameof(this.Title));
   5.795 +        }
   5.796 +    }
   5.797 +}
     6.1 --- a/UI/HandshakeItem.cs	Wed Mar 01 17:23:46 2017 +0100
     6.2 +++ b/UI/HandshakeItem.cs	Wed Mar 08 16:23:28 2017 +0100
     6.3 @@ -20,14 +20,14 @@
     6.4  
     6.5          public enum HandshakeMode
     6.6          {
     6.7 -            Default,
     6.8 +            Standard,
     6.9              Sync
    6.10          }
    6.11  
    6.12          public enum Tabs
    6.13          {
    6.14 -            Trustwords = 0,
    6.15 -            Fingerprint = 1
    6.16 +            Trustwords,
    6.17 +            Fingerprint
    6.18          }
    6.19  
    6.20          private Tabs                                        _ActiveTab;
    6.21 @@ -43,6 +43,7 @@
    6.22          private bool                                        _IsClickable;
    6.23          private bool                                        _IsExpanded;
    6.24          private bool                                        _IsExpandable;
    6.25 +        private bool                                        _IsSeparatorVisible;
    6.26          private ImageSource                                 _ItemImage;
    6.27          private string                                      _ItemName;
    6.28          private HandshakeMode                               _Mode;
    6.29 @@ -347,6 +348,19 @@
    6.30          }
    6.31  
    6.32          /// <summary>
    6.33 +        /// Gets or sets whether the separator at the end of this item is visible or not.
    6.34 +        /// </summary>
    6.35 +        public bool IsSeparatorVisible
    6.36 +        {
    6.37 +            get { return (this._IsSeparatorVisible); }
    6.38 +            set
    6.39 +            {
    6.40 +                this._IsSeparatorVisible = value;
    6.41 +                this.RaisePropertyChangedEvent(nameof(this.IsSeparatorVisible));
    6.42 +            }
    6.43 +        }
    6.44 +
    6.45 +        /// <summary>
    6.46          /// Gets or sets the text to display on the first expanded button.
    6.47          /// </summary>
    6.48          public string ExpandedButton1Text
    6.49 @@ -464,9 +478,10 @@
    6.50              this._IsClickable = true;
    6.51              this._IsExpanded = false;
    6.52              this._IsExpandable = false;
    6.53 +            this._IsSeparatorVisible = true;
    6.54              this._ItemImage = null;
    6.55              this._ItemName = null;
    6.56 -            this._Mode = HandshakeMode.Default;
    6.57 +            this._Mode = HandshakeMode.Standard;
    6.58              this._Myself = null;
    6.59              this._Partner = null;
    6.60              this._TrustwordsCulture = Globals.ThisAddIn.Settings.TrustwordsCulture;
    6.61 @@ -486,6 +501,7 @@
    6.62              this.RaisePropertyChangedEvent(nameof(this.IsClickable));
    6.63              this.RaisePropertyChangedEvent(nameof(this.IsExpanded));
    6.64              this.RaisePropertyChangedEvent(nameof(this.IsExpandable));
    6.65 +            this.RaisePropertyChangedEvent(nameof(this.IsSeparatorVisible));
    6.66              this.RaisePropertyChangedEvent(nameof(this.ItemImage));
    6.67              this.RaisePropertyChangedEvent(nameof(this.ItemName));
    6.68              this.RaisePropertyChangedEvent(nameof(this.Mode));
     7.1 --- a/UI/ValueConverters.cs	Wed Mar 01 17:23:46 2017 +0100
     7.2 +++ b/UI/ValueConverters.cs	Wed Mar 08 16:23:28 2017 +0100
     7.3 @@ -75,9 +75,49 @@
     7.4          }
     7.5      }
     7.6  
     7.7 +    /// <summary>
     7.8 +    /// Returns true if given parameter is equal to HandshakeMode.Standard. Otherwise false
     7.9 +    /// </summary>
    7.10 +    public class IsStandardModeToBoolConverter : IValueConverter
    7.11 +    {
    7.12 +        public object Convert(object value,
    7.13 +                              Type targetType,
    7.14 +                              object parameter,
    7.15 +                              CultureInfo culture)
    7.16 +        {
    7.17 +            bool result = false;
    7.18 +            string param = null;
    7.19 +            string val = null;
    7.20 +
    7.21 +            param = parameter as string;
    7.22 +
    7.23 +            try
    7.24 +            {
    7.25 +                val = Enum.GetName(typeof(HandshakeDialog.HandshakeMode), value);
    7.26 +            }
    7.27 +            catch
    7.28 +            {
    7.29 +                val = null;
    7.30 +            }
    7.31 +
    7.32 +            if ((param != null) &&
    7.33 +                (val != null) &&
    7.34 +                (val == param))
    7.35 +            {
    7.36 +                result = true;
    7.37 +            }
    7.38 +
    7.39 +            return result;
    7.40 +        }
    7.41 +
    7.42 +        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    7.43 +        {
    7.44 +            throw new NotImplementedException();
    7.45 +        }
    7.46 +    }
    7.47  
    7.48      /// <summary>
    7.49 -    /// Returns true if given parameter is same a active tab. Otherwise false
    7.50 +    /// Returns true if given parameter is same as an active tab. Otherwise false
    7.51      /// </summary>
    7.52      public class IsActiveTabToBoolConverter : IValueConverter
    7.53      {
     8.1 --- a/pEpForOutlook.csproj	Wed Mar 01 17:23:46 2017 +0100
     8.2 +++ b/pEpForOutlook.csproj	Wed Mar 08 16:23:28 2017 +0100
     8.3 @@ -366,6 +366,9 @@
     8.4      <Compile Include="UI\FormRegionPreviewUnencrypted2.Designer.cs">
     8.5        <DependentUpon>FormRegionPreviewUnencrypted2.cs</DependentUpon>
     8.6      </Compile>
     8.7 +    <Compile Include="UI\HandshakeDialog.xaml.cs">
     8.8 +      <DependentUpon>HandshakeDialog.xaml</DependentUpon>
     8.9 +    </Compile>
    8.10      <Compile Include="UI\HandshakeItem.cs" />
    8.11      <Compile Include="UI\RibbonCustomizations.cs" />
    8.12      <Compile Include="UI\FormManagePrivacyStatus.cs">
    8.13 @@ -538,6 +541,10 @@
    8.14        <SubType>Designer</SubType>
    8.15        <Generator>MSBuild:Compile</Generator>
    8.16      </Page>
    8.17 +    <Page Include="UI\HandshakeDialog.xaml">
    8.18 +      <SubType>Designer</SubType>
    8.19 +      <Generator>MSBuild:Compile</Generator>
    8.20 +    </Page>
    8.21      <Page Include="UI\PrivacyView.xaml">
    8.22        <SubType>Designer</SubType>
    8.23        <Generator>MSBuild:Compile</Generator>