aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2017-12-28 15:16:27 +0200
committerAvi Levkovich <avi@twine-s.com>2017-12-28 15:16:27 +0200
commitc056f991c0168f6449fac16c3b0cb165518c5e01 (patch)
treee5c69bb1f3e03029991efe15e930af80ff6712db /Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization
parent15799210aab388996f86808e000940093306ca41 (diff)
parent2d3f4bfd4b265888933ad8a7e21e4dd80aa1eda2 (diff)
downloadTango-c056f991c0168f6449fac16c3b0cb165518c5e01.tar.gz
Tango-c056f991c0168f6449fac16c3b0cb165518c5e01.zip
MERGE.
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization')
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/App.config30
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/AutoComplete/MachinesProvider.cs19
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/android-phone-color.pngbin0 -> 3254 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/arrow_right.pngbin0 -> 1094 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/machine-trans.pngbin0 -> 45618 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/remote-db.pngbin0 -> 159697 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/sqlite.pngbin0 -> 123916 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synch_big.pngbin0 -> 83487 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synchronization.jpgbin0 -> 41826 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/NavigationView.cs16
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/SyncNavigationManager.cs17
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/AssemblyInfo.cs18
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.Designer.cs62
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.resx117
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.Designer.cs30
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.settings7
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/SynchronizationModule.cs46
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Tango.MachineStudio.Synchronization.csproj255
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModelLocator.cs72
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/DirectSynchronizationViewVM.cs328
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/LocalSynchronizationViewVM.cs363
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MainViewVM.cs61
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MenuViewVM.cs31
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/RemoteSynchronizationViewVM.cs372
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml204
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml164
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml43
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml.cs46
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml83
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml172
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/packages.config17
35 files changed, 2685 insertions, 0 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/App.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/App.config
new file mode 100644
index 000000000..158702ed3
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/App.config
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <configSections>
+ <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+ <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </configSections>
+ <entityFramework>
+ <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
+ <providers>
+ <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+ <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
+ </providers>
+ </entityFramework>
+
+ <runtime>
+
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+
+ <dependentAssembly>
+
+ <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
+
+ <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
+
+ </dependentAssembly>
+
+ </assemblyBinding>
+
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/AutoComplete/MachinesProvider.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/AutoComplete/MachinesProvider.cs
new file mode 100644
index 000000000..887cb842d
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/AutoComplete/MachinesProvider.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.AutoComplete.Editors;
+using Tango.DAL.Observables;
+
+namespace Tango.MachineStudio.Synchronization.AutoComplete
+{
+ public class MachinesProvider : ISuggestionProvider
+ {
+ public IEnumerable GetSuggestions(string filter)
+ {
+ return ObservablesEntitiesAdapter.Instance.Machines.Where(x => x.SerialNumber.StartsWith(filter, StringComparison.CurrentCultureIgnoreCase)).ToList();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/android-phone-color.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/android-phone-color.png
new file mode 100644
index 000000000..46453bf83
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/android-phone-color.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/arrow_right.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/arrow_right.png
new file mode 100644
index 000000000..5b7f0736b
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/arrow_right.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/machine-trans.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/machine-trans.png
new file mode 100644
index 000000000..a7cf65852
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/machine-trans.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/remote-db.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/remote-db.png
new file mode 100644
index 000000000..844695629
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/remote-db.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/sqlite.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/sqlite.png
new file mode 100644
index 000000000..46cecd740
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/sqlite.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synch_big.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synch_big.png
new file mode 100644
index 000000000..ff6476f44
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synch_big.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synchronization.jpg b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synchronization.jpg
new file mode 100644
index 000000000..801bbce48
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Images/synchronization.jpg
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/NavigationView.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/NavigationView.cs
new file mode 100644
index 000000000..d4212475c
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/NavigationView.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.MachineStudio.Synchronization.Navigation
+{
+ public enum NavigationView
+ {
+ MenuView,
+ LocalSynchronizationView,
+ RemoteSynchronizationView,
+ DirectSynchronizationView,
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/SyncNavigationManager.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/SyncNavigationManager.cs
new file mode 100644
index 000000000..847fa2456
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Navigation/SyncNavigationManager.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.MachineStudio.Synchronization.Views;
+
+namespace Tango.MachineStudio.Synchronization.Navigation
+{
+ public class SyncNavigationManager
+ {
+ public void NavigateTo(NavigationView view)
+ {
+ MainView.Instance.TransitionControl.AutoNavigate(view.ToString());
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..d0a85a97c
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+[assembly: AssemblyTitle("Tango - Machine Studio Synchronization Module")]
+
+[assembly: ComVisible(false)]
+
+[assembly:ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..81d350bfd
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.Designer.cs
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.MachineStudio.Synchronization.Properties {
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if ((resourceMan == null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.MachineStudio.Synchronization.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.resx b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..2c61b78ac
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.MachineStudio.Synchronization.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.settings b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.settings
new file mode 100644
index 000000000..033d7a5e9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/SynchronizationModule.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/SynchronizationModule.cs
new file mode 100644
index 000000000..039b9faf6
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/SynchronizationModule.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media.Imaging;
+using Tango.DAL.Observables;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Synchronization.Views;
+using Tango.SharedUI.Helpers;
+
+namespace Tango.MachineStudio.Synchronization
+{
+ public class SynchronizationModule : IStudioModule
+ {
+ private bool _isInitialized;
+
+ public string Name => "Synchronization";
+
+ public string Description => "Perform local to local or remote to local database synchronization.";
+
+ public BitmapSource Image => ResourceHelper.GetImageFromResources("Images/synchronization.jpg");
+
+ public FrameworkElement MainView => new MainView();
+
+ public bool IsInitialized => _isInitialized;
+
+ public Permissions Permission => Permissions.RunSynchronizationModule;
+
+ public void Dispose()
+ {
+ //Dispose...
+ }
+
+ public void Initialize()
+ {
+ if (!_isInitialized)
+ {
+ //Initialize..
+
+ _isInitialized = true;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Tango.MachineStudio.Synchronization.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Tango.MachineStudio.Synchronization.csproj
new file mode 100644
index 000000000..3c03f1e48
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Tango.MachineStudio.Synchronization.csproj
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{12D0C43C-391F-4C74-92AB-82E9A9BEEB9B}</ProjectGuid>
+ <OutputType>library</OutputType>
+ <RootNamespace>Tango.MachineStudio.Synchronization</RootNamespace>
+ <AssemblyName>Tango.MachineStudio.Synchronization</AssemblyName>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\Build\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+ </Reference>
+ <Reference Include="FontAwesome.WPF, Version=4.7.0.37774, Culture=neutral, PublicKeyToken=0758b07a11a4f466, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath>
+ </Reference>
+ <Reference Include="GalaSoft.MvvmLight, Version=5.3.0.19026, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
+ </Reference>
+ <Reference Include="GalaSoft.MvvmLight.Extras, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=669f0b5e8f868abf, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Extras.dll</HintPath>
+ </Reference>
+ <Reference Include="GalaSoft.MvvmLight.Platform, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=5f873c45e98af8a1, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
+ <Reference Include="MahApps.Metro, Version=1.5.0.23, Culture=neutral, PublicKeyToken=f4fb5a3c4d1e5b4f, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll</HintPath>
+ </Reference>
+ <Reference Include="MaterialDesignColors, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MaterialDesignColors.1.1.2\lib\net45\MaterialDesignColors.dll</HintPath>
+ </Reference>
+ <Reference Include="MaterialDesignThemes.Wpf, Version=2.3.1.953, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MaterialDesignThemes.2.3.1.953\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Reactive.Core, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.Interfaces, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.Linq, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\System.Reactive.Linq.3.1.1\lib\net46\System.Reactive.Linq.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.PlatformServices, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\System.Reactive.PlatformServices.3.1.1\lib\net46\System.Reactive.PlatformServices.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Reactive.Windows.Threading, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Windows" />
+ <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AutoComplete\MachinesProvider.cs" />
+ <Compile Include="Navigation\NavigationView.cs" />
+ <Compile Include="Navigation\SyncNavigationManager.cs" />
+ <Compile Include="ViewModelLocator.cs" />
+ <Compile Include="ViewModels\DirectSynchronizationViewVM.cs" />
+ <Compile Include="ViewModels\LocalSynchronizationViewVM.cs" />
+ <Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="ViewModels\MenuViewVM.cs" />
+ <Compile Include="ViewModels\RemoteSynchronizationViewVM.cs" />
+ <Compile Include="Views\DirectSynchronizationView.xaml.cs">
+ <DependentUpon>DirectSynchronizationView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\RemoteSynchronizationView.xaml.cs">
+ <DependentUpon>RemoteSynchronizationView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\LocalSynchronizationView.xaml.cs">
+ <DependentUpon>LocalSynchronizationView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\MainView.xaml.cs">
+ <DependentUpon>MainView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\MenuView.xaml.cs">
+ <DependentUpon>MenuView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="..\..\..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="SynchronizationModule.cs" />
+ <Page Include="Views\DirectSynchronizationView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\RemoteSynchronizationView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Views\LocalSynchronizationView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\MainView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\MenuView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <Content Include="..\..\..\..\DB\Tango.db">
+ <Link>Tango.db</Link>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <None Include="App.config" />
+ <None Include="packages.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj">
+ <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project>
+ <Name>Tango.AutoComplete</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.DAL.Local\Tango.DAL.Local.csproj">
+ <Project>{0e0eef3e-8f4e-4f23-9d19-479fd8d76c12}</Project>
+ <Name>Tango.DAL.Local</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.DAL.Observables\Tango.DAL.Observables.csproj">
+ <Project>{0ecd6da8-7aa6-48d9-8b65-279d176ad9af}</Project>
+ <Name>Tango.DAL.Observables</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.DAL.Remote\Tango.DAL.Remote.csproj">
+ <Project>{38197109-8610-4d3f-92b9-16d48df94d7c}</Project>
+ <Name>Tango.DAL.Remote</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Integration\Tango.Integration.csproj">
+ <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project>
+ <Name>Tango.Integration</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
+ <Name>Tango.Logging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.PMR\Tango.PMR.csproj">
+ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project>
+ <Name>Tango.PMR</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Settings\Tango.Settings.csproj">
+ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project>
+ <Name>Tango.Settings</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.SharedUI\Tango.SharedUI.csproj">
+ <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project>
+ <Name>Tango.SharedUI</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Synchronization\Tango.Synchronization.csproj">
+ <Project>{7ada4e86-cad7-4968-a210-3a8a9e5153ab}</Project>
+ <Name>Tango.Synchronization</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Transport\Tango.Transport.csproj">
+ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project>
+ <Name>Tango.Transport</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.MachineStudio.Common\Tango.MachineStudio.Common.csproj">
+ <Project>{cb0b0aa2-bb24-4bca-a720-45e397684e12}</Project>
+ <Name>Tango.MachineStudio.Common</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\synchronization.jpg" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\android-phone-color.png" />
+ <Resource Include="Images\arrow_right.png" />
+ <Resource Include="Images\remote-db.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\sqlite.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\synch_big.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\machine-trans.png" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModelLocator.cs
new file mode 100644
index 000000000..090a323a2
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModelLocator.cs
@@ -0,0 +1,72 @@
+using GalaSoft.MvvmLight;
+using GalaSoft.MvvmLight.Ioc;
+using Microsoft.Practices.ServiceLocation;
+using Tango.MachineStudio.Synchronization.Navigation;
+using Tango.MachineStudio.Synchronization.ViewModels;
+
+namespace Tango.MachineStudio.Synchronization
+{
+ /// <summary>
+ /// This class contains static references to all the view models in the
+ /// application and provides an entry point for the bindings.
+ /// </summary>
+ public static class ViewModelLocator
+ {
+ /// <summary>
+ /// Initializes a new instance of the ViewModelLocator class.
+ /// </summary>
+ static ViewModelLocator()
+ {
+ ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
+ SimpleIoc.Default.Register<MainViewVM>();
+ SimpleIoc.Default.Register<MenuViewVM>();
+ SimpleIoc.Default.Register<LocalSynchronizationViewVM>();
+ SimpleIoc.Default.Register<RemoteSynchronizationViewVM>();
+ SimpleIoc.Default.Register<DirectSynchronizationViewVM>();
+
+ SimpleIoc.Default.Unregister<SyncNavigationManager>();
+
+ SimpleIoc.Default.Register<SyncNavigationManager, SyncNavigationManager>();
+ }
+
+ public static MainViewVM MainViewVM
+ {
+ get
+ {
+ return ServiceLocator.Current.GetInstance<MainViewVM>();
+ }
+ }
+
+ public static MenuViewVM MenuViewVM
+ {
+ get
+ {
+ return ServiceLocator.Current.GetInstance<MenuViewVM>();
+ }
+ }
+
+ public static LocalSynchronizationViewVM LocalSynchronizationViewVM
+ {
+ get
+ {
+ return ServiceLocator.Current.GetInstance<LocalSynchronizationViewVM>();
+ }
+ }
+
+ public static RemoteSynchronizationViewVM RemoteSynchronizationViewVM
+ {
+ get
+ {
+ return ServiceLocator.Current.GetInstance<RemoteSynchronizationViewVM>();
+ }
+ }
+
+ public static DirectSynchronizationViewVM DirectSynchronizationViewVM
+ {
+ get
+ {
+ return ServiceLocator.Current.GetInstance<DirectSynchronizationViewVM>();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/DirectSynchronizationViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/DirectSynchronizationViewVM.cs
new file mode 100644
index 000000000..3f8772f0e
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/DirectSynchronizationViewVM.cs
@@ -0,0 +1,328 @@
+using Google.Protobuf;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Entity.Validation;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.Core.Helpers;
+using Tango.DAL.Observables;
+using Tango.Integration.Services;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Common.StudioApplication;
+using Tango.MachineStudio.Synchronization.Navigation;
+using Tango.PMR.Integration;
+using Tango.SharedUI;
+using Tango.Synchronization;
+using Tango.Synchronization.Local;
+using Tango.Synchronization.Remote;
+
+namespace Tango.MachineStudio.Synchronization.ViewModels
+{
+ public class DirectSynchronizationViewVM : ViewModel
+ {
+ private SyncNavigationManager _navigation;
+ private String _slaveDBFile;
+ private String _masterDBFile;
+ private LocalDBComparer _comparer;
+ private INotificationProvider _notification;
+ private String _comparedSerialNumber;
+
+ public IStudioApplicationManager ApplicationManager { get; set; }
+
+ public DirectSynchronizationViewVM(IStudioApplicationManager applicationManager, SyncNavigationManager navigation, INotificationProvider notification)
+ {
+ ApplicationManager = applicationManager;
+
+ _navigation = navigation;
+ _notification = notification;
+
+ BackCommand = new RelayCommand(() => _navigation.NavigateTo(NavigationView.MenuView));
+
+ Differences = new ObservableCollection<Diff>();
+
+ CompareCommand = new RelayCommand(Compare, (x) => !IsWorking && SelectedMachine != null);
+ CommitAllCommand = new RelayCommand(Synchronize, (x) => Differences.Count > 0 && !IsWorking && SelectedMachine != null);
+ }
+
+ #region Commands
+
+ /// <summary>
+ /// Gets or sets the back command.
+ /// </summary>
+ public RelayCommand BackCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the browse master database command.
+ /// </summary>
+ public RelayCommand BrowseMasterDBCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the browse slave database command.
+ /// </summary>
+ public RelayCommand BrowseSlaveDBCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the compare command.
+ /// </summary>
+ public RelayCommand CompareCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the commit command.
+ /// </summary>
+ public RelayCommand CommitCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the commit all command.
+ /// </summary>
+ public RelayCommand CommitAllCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the clean command.
+ /// </summary>
+ public RelayCommand CleanCommand { get; set; }
+
+ #endregion
+
+ #region Properties
+
+ private bool _isWorking;
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is working.
+ /// </summary>
+ public bool IsWorking
+ {
+ get { return _isWorking; }
+ set { _isWorking = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isClearMachine;
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is clear machine.
+ /// </summary>
+ public bool IsClearMachine
+ {
+ get { return _isClearMachine; }
+ set
+ {
+ _isClearMachine = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private ObservableCollection<Diff> _differences;
+ /// <summary>
+ /// Gets or sets the differences.
+ /// </summary>
+ public ObservableCollection<Diff> Differences
+ {
+ get { return _differences; }
+ set { _differences = value; RaisePropertyChanged(nameof(Differences)); }
+ }
+
+ private Diff _selectedDifference;
+ /// <summary>
+ /// Gets or sets the selected difference.
+ /// </summary>
+ public Diff SelectedDifference
+ {
+ get { return _selectedDifference; }
+ set { _selectedDifference = value; RaisePropertyChanged(nameof(SelectedDifference)); InvalidateRelayCommands(); }
+ }
+
+ private Machine _selectedMachine;
+ /// <summary>
+ /// Gets or sets the selected machine.
+ /// </summary>
+ public Machine SelectedMachine
+ {
+ get { return _selectedMachine; }
+ set { _selectedMachine = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void Compare()
+ {
+ if (SelectedMachine.SerialNumber != ApplicationManager.ConnectedMachine.SerialNumber)
+ {
+ if (!_notification.ShowQuestion("The selected machine serial number does not match the connected machine. Are you sure you want to continue?"))
+ {
+ return;
+ }
+ }
+
+ Task.Factory.StartNew(async () =>
+ {
+ using (_notification.PushTaskItem("Downloading machine database..."))
+ {
+ try
+ {
+ IsWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+
+ ApplicationManager.ConnectedMachine.UseKeepAlive = false;
+
+ var response = await ApplicationManager.ConnectedMachine.SendRequest<DirectSynchronizationRequest, DirectSynchronizationResponse>(new DirectSynchronizationRequest(), TimeSpan.FromSeconds(60));
+
+ using (_notification.PushTaskItem("Generating temporary files..."))
+ {
+ String tempFolder = PathHelper.GetTempFolderPath();
+
+ //File path for the reflected remote data base SQLite.
+ _masterDBFile = Path.Combine(tempFolder, "Remote.db");
+ //File path for the received machine SQLite db.
+ _slaveDBFile = Path.Combine(tempFolder, "Local.db");
+
+ //Save the machine db to file.
+ File.WriteAllBytes(_slaveDBFile, response.Message.LocalDB.ToByteArray());
+
+ //Copy the SQLite db template.
+ File.Copy(Path.Combine(PathHelper.GetStartupPath(), "Tango.db"), _masterDBFile);
+
+ //Synchronize the SQL Server db with the new SQLite template. (Overwrite basically)
+ RemoteDBSynchronizer.Synchronize(_masterDBFile, SelectedMachine.SerialNumber, true);
+
+ _comparedSerialNumber = SelectedMachine.SerialNumber;
+
+ using (_notification.PushTaskItem("Comparing database..."))
+ {
+ _comparer = new LocalDBComparer(new SQLiteDataBase(_masterDBFile), new SQLiteDataBase(_slaveDBFile));
+
+ var diffs = _comparer.Compare();
+ Differences = new ObservableCollection<Diff>(diffs);
+
+ if (diffs.Where(x => x.Action != DiffAction.ReplaceTableDataInSlave).Count() > 0)
+ {
+ ShowInfo("Found " + Differences.Where(x => x.Action != DiffAction.ReplaceTableDataInSlave).Count() + " differences.");
+ }
+ else
+ {
+ ShowInfo("The machine database is synchronized.");
+ }
+ }
+ }
+ }
+ catch (DbEntityValidationException ex)
+ {
+ String message = "The following validation errors occurred." + Environment.NewLine + Environment.NewLine;
+
+ foreach (var error in ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).ToList())
+ {
+ message += error.ErrorMessage + Environment.NewLine;
+ }
+
+ ShowError(message);
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ IsWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+ ApplicationManager.ConnectedMachine.UseKeepAlive = true;
+ }
+ }
+ });
+ }
+
+ private void Synchronize()
+ {
+ if (IsClearMachine)
+ {
+ if (!_notification.ShowQuestion("This will erase and override the existing machine database. Do you want to proceed?"))
+ {
+ return;
+ }
+ }
+
+ if (SelectedMachine.SerialNumber != _comparedSerialNumber)
+ {
+ _notification.ShowError("You have selected a different machine serial number after comparing. Please compare again if you wish to synchronize a different machine.");
+ return;
+ }
+
+ Task.Factory.StartNew(async () =>
+ {
+ using (_notification.PushTaskItem("Synchronizing..."))
+ {
+ try
+ {
+ ApplicationManager.ConnectedMachine.UseKeepAlive = false;
+
+ IsWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+
+ for (int i = 0; i < Differences.Count; i++)
+ {
+ var diff = Differences[i];
+
+ diff.Commit();
+ InvokeUINow(() => Differences.Remove(diff));
+ i--;
+ }
+
+ _comparer.Dispose();
+
+ byte[] remoteDbBytes = IsClearMachine ? File.ReadAllBytes(_masterDBFile) : File.ReadAllBytes(_slaveDBFile);
+
+ var response = await ApplicationManager.ConnectedMachine.SendRequest<OverrideDataBaseRequest, OverrideDataBaseResponse>(new OverrideDataBaseRequest()
+ {
+ RemoteDB = ByteString.CopyFrom(remoteDbBytes)
+ }, TimeSpan.FromSeconds(30));
+
+ if (!response.Message.Successful)
+ {
+ ShowError("The remote machine has reported some error while trying to override the database.");
+ }
+ else
+ {
+ //Synchronize the SQL Server db with the synchronized master DB.
+ RemoteDBSynchronizer.Synchronize(_masterDBFile, _comparedSerialNumber, false);
+
+ PathHelper.TryDeleteFile(_slaveDBFile);
+ PathHelper.TryDeleteFile(_masterDBFile);
+ _slaveDBFile = null;
+ _masterDBFile = null;
+ InvalidateRelayCommands();
+ }
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ IsWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+ ApplicationManager.ConnectedMachine.UseKeepAlive = true;
+ }
+ }
+ });
+ }
+
+ private void ShowError(String message)
+ {
+ InvokeUINow(() => _notification.ShowError(message));
+ }
+
+ private void ShowInfo(String message)
+ {
+ InvokeUINow(() => _notification.ShowInfo(message));
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/LocalSynchronizationViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/LocalSynchronizationViewVM.cs
new file mode 100644
index 000000000..9c805cca4
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/LocalSynchronizationViewVM.cs
@@ -0,0 +1,363 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.Logging;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Synchronization.Navigation;
+using Tango.MachineStudio.Synchronization.Properties;
+using Tango.Settings;
+using Tango.SharedUI;
+using Tango.Synchronization;
+using Tango.Synchronization.Local;
+
+namespace Tango.MachineStudio.Synchronization.ViewModels
+{
+ public class LocalSynchronizationViewVM : ViewModel
+ {
+ private SyncNavigationManager _navigation;
+ private String _masterDBFile;
+ private String _slaveDBFile;
+ private LocalDBComparer _comparer;
+ private INotificationProvider _notification;
+ private bool _isWorking;
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LocalSynchronizationViewVM"/> class.
+ /// </summary>
+ /// <param name="navigation">The navigation.</param>
+ /// <param name="notification">The notification.</param>
+ public LocalSynchronizationViewVM(SyncNavigationManager navigation, INotificationProvider notification)
+ {
+ _navigation = navigation;
+ _notification = notification;
+
+ BackCommand = new RelayCommand(() => _navigation.NavigateTo(NavigationView.MenuView));
+
+ Differences = new ObservableCollection<Diff>();
+
+ BrowseMasterDBCommand = new RelayCommand(BrowseMasterDB, (x) => !_isWorking);
+ BrowseSlaveDBCommand = new RelayCommand(BrowseSlaveDB, (x) => !_isWorking);
+ CompareCommand = new RelayCommand(Compare, (x) => MasterDBFile != null && SlaveDBFile != null && !_isWorking);
+ CommitCommand = new RelayCommand(Commit, (x) => SelectedDifference != null && !_isWorking);
+ CommitAllCommand = new RelayCommand(CommitAll, (x) => Differences.Count > 0 && !_isWorking);
+ CleanCommand = new RelayCommand(CleanSlave, (x) => !_isWorking && SlaveDBFile != null);
+
+ if (File.Exists(SettingsManager.Default.MachineStudio.SynchronizationModule.LocalMasterDBFile))
+ {
+ MasterDBFile = SettingsManager.Default.MachineStudio.SynchronizationModule.LocalMasterDBFile;
+ MasterDBName = Path.GetFileName(MasterDBFile);
+ }
+
+ if (File.Exists(SettingsManager.Default.MachineStudio.SynchronizationModule.LocalSlaveDBFile))
+ {
+ SlaveDBFile = SettingsManager.Default.MachineStudio.SynchronizationModule.LocalSlaveDBFile;
+ SlaveDBName = Path.GetFileName(SlaveDBFile);
+ }
+ }
+
+ #endregion
+
+ #region Commands
+
+ /// <summary>
+ /// Gets or sets the back command.
+ /// </summary>
+ public RelayCommand BackCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the browse master database command.
+ /// </summary>
+ public RelayCommand BrowseMasterDBCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the browse slave database command.
+ /// </summary>
+ public RelayCommand BrowseSlaveDBCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the compare command.
+ /// </summary>
+ public RelayCommand CompareCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the commit command.
+ /// </summary>
+ public RelayCommand CommitCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the commit all command.
+ /// </summary>
+ public RelayCommand CommitAllCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the clean command.
+ /// </summary>
+ public RelayCommand CleanCommand { get; set; }
+ #endregion
+
+ #region Properties
+
+ private ObservableCollection<Diff> _differences;
+ /// <summary>
+ /// Gets or sets the differences.
+ /// </summary>
+ public ObservableCollection<Diff> Differences
+ {
+ get { return _differences; }
+ set { _differences = value; RaisePropertyChanged(nameof(Differences)); }
+ }
+
+ private Diff _selectedDifference;
+ /// <summary>
+ /// Gets or sets the selected difference.
+ /// </summary>
+ public Diff SelectedDifference
+ {
+ get { return _selectedDifference; }
+ set { _selectedDifference = value; RaisePropertyChanged(nameof(SelectedDifference)); InvalidateRelayCommands(); }
+ }
+
+ private String _masterDBName;
+ /// <summary>
+ /// Gets or sets the name of the master database.
+ /// </summary>
+ public String MasterDBName
+ {
+ get { return _masterDBName; }
+ set { _masterDBName = value; RaisePropertyChanged(nameof(MasterDBName)); }
+ }
+
+ private String _slaveDBName;
+ /// <summary>
+ /// Gets or sets the name of the slave database.
+ /// </summary>
+ public String SlaveDBName
+ {
+ get { return _slaveDBName; }
+ set { _slaveDBName = value; RaisePropertyChanged(nameof(SlaveDBName)); }
+ }
+
+ /// <summary>
+ /// Gets or sets the slave database file.
+ /// </summary>
+ public String SlaveDBFile
+ {
+ get { return _slaveDBFile; }
+ set { _slaveDBFile = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the master database file.
+ /// </summary>
+ public String MasterDBFile
+ {
+ get { return _masterDBFile; }
+ set { _masterDBFile = value; RaisePropertyChangedAuto(); }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private async void CleanSlave()
+ {
+ if (_notification.ShowQuestion("Are you sure you want to erase all data on slave database?"))
+ {
+ using (_notification.PushTaskItem("Clearing database..."))
+ {
+ try
+ {
+ _isWorking = true;
+ await Task.Factory.StartNew(() =>
+ {
+ SQLiteDataBase localDB = new SQLiteDataBase(SlaveDBFile);
+ localDB.LoadTables();
+ localDB.ClearDataBase();
+ try
+ {
+ localDB.Dispose();
+ }
+ catch { }
+ });
+
+ Differences.Clear();
+ }
+ catch (Exception ex)
+ {
+ ShowError(LogManager.Log(ex).Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ InvalidateRelayCommands();
+ SelectedDifference = null;
+ }
+ }
+ }
+ }
+
+ private void Compare()
+ {
+ _comparer = new LocalDBComparer(new SQLiteDataBase(MasterDBFile), new SQLiteDataBase(SlaveDBFile));
+
+ Task.Factory.StartNew(() =>
+ {
+ using (_notification.PushTaskItem("Comparing Databases..."))
+ {
+ try
+ {
+ _isWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+ var diffs = _comparer.Compare();
+ Differences = new ObservableCollection<Diff>(diffs);
+
+ if (diffs.Where(x => x.Action != DiffAction.ReplaceTableDataInSlave).Count() > 0)
+ {
+ ShowInfo("Found " + Differences.Where(x => x.Action != DiffAction.ReplaceTableDataInSlave).Count() + " differences.");
+ }
+ else
+ {
+ ShowInfo("The master and slave databases are synchronized.");
+ }
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+
+ SettingsManager.Default.MachineStudio.SynchronizationModule.LocalMasterDBFile = MasterDBFile;
+ SettingsManager.Default.MachineStudio.SynchronizationModule.LocalSlaveDBFile = SlaveDBFile;
+ SettingsManager.SaveDefaultSettings();
+ }
+ }
+ });
+ }
+
+ private void Commit()
+ {
+ Task.Factory.StartNew(() =>
+ {
+ using (_notification.PushTaskItem("Committing difference..."))
+ {
+ try
+ {
+ _isWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+ SelectedDifference.Commit();
+
+ InvokeUINow(() => Differences.Remove(SelectedDifference));
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+ }
+ }
+ });
+ }
+
+ private void CommitAll()
+ {
+ Task.Factory.StartNew(() =>
+ {
+ using (_notification.PushTaskItem("Committing all differences..."))
+ {
+ try
+ {
+ _isWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+
+ for (int i = 0; i < Differences.Count; i++)
+ {
+ var diff = Differences[i];
+ using (_notification.PushTaskItem("Committing difference " + (Differences.IndexOf(diff) + 1) + "..."))
+ {
+ diff.Commit();
+ InvokeUINow(() => Differences.Remove(diff));
+ i--;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+ }
+ }
+ });
+ }
+
+ private void BrowseSlaveDB()
+ {
+ String file = BrowseForFilePath();
+ if (file != null)
+ {
+ SlaveDBFile = file;
+ SlaveDBName = Path.GetFileName(file);
+ InvalidateRelayCommands();
+ }
+ }
+
+ private void BrowseMasterDB()
+ {
+ String file = BrowseForFilePath();
+ if (file != null)
+ {
+ MasterDBFile = file;
+ MasterDBName = Path.GetFileName(file);
+ InvalidateRelayCommands();
+ }
+ }
+
+ private String BrowseForFilePath()
+ {
+ OpenFileDialog dlg = new OpenFileDialog();
+ dlg.Title = "Select SQLite Database File";
+ dlg.Filter = "SQLite Database|*.db";
+ if (dlg.ShowDialog().Value)
+ {
+ return dlg.FileName;
+ }
+ return null;
+ }
+
+ private void ShowError(String message)
+ {
+ InvokeUINow(() => _notification.ShowError(message));
+ }
+
+ private void ShowInfo(String message)
+ {
+ InvokeUINow(() => _notification.ShowInfo(message));
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MainViewVM.cs
new file mode 100644
index 000000000..c392aee1a
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MainViewVM.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Logging;
+using Tango.SharedUI;
+
+namespace Tango.MachineStudio.Synchronization.ViewModels
+{
+ public class MainViewVM : ViewModel
+ {
+ public MainViewVM()
+ {
+ MainViewLogger logger = new MainViewLogger();
+ logger.NewLog += (output) =>
+ {
+ Log += output + Environment.NewLine;
+ };
+
+ LogManager.RegisterLogger(logger);
+ }
+
+ private String _log;
+ /// <summary>
+ /// Gets or sets the current application log text.
+ /// </summary>
+ public String Log
+ {
+ get { return _log; }
+ set { _log = value; RaisePropertyChanged(nameof(Log)); }
+ }
+
+ #region Custom Logger
+
+ public class MainViewLogger : ILogger
+ {
+ public bool Enabled { get; set; }
+ public bool Immediate { get; set; }
+ public event Action<String> NewLog;
+
+ public MainViewLogger()
+ {
+ Enabled = true;
+ Immediate = true;
+ }
+
+ public void OnError(LogItemBase output)
+ {
+ NewLog?.Invoke(output.TimeStamp.ToTimeString() + ": " + output.GetMessage());
+ }
+
+ public void OnTrace(LogItemBase output)
+ {
+ NewLog?.Invoke(output.TimeStamp.ToTimeString() + ": " + output.GetMessage());
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MenuViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MenuViewVM.cs
new file mode 100644
index 000000000..0fe510f36
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/MenuViewVM.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.MachineStudio.Synchronization.Navigation;
+using Tango.SharedUI;
+
+namespace Tango.MachineStudio.Synchronization.ViewModels
+{
+ public class MenuViewVM : ViewModel
+ {
+ private SyncNavigationManager _navigation;
+
+ public MenuViewVM(SyncNavigationManager navigation)
+ {
+ _navigation = navigation;
+
+ StartLocalSyncCommand = new RelayCommand(() => { _navigation.NavigateTo(NavigationView.LocalSynchronizationView); });
+ StartRemoteSyncCommand = new RelayCommand(() => { _navigation.NavigateTo(NavigationView.RemoteSynchronizationView); });
+ StartDirectRemoteSyncCommand = new RelayCommand(() => { _navigation.NavigateTo(NavigationView.DirectSynchronizationView); });
+ }
+
+ public RelayCommand StartLocalSyncCommand { get; set; }
+
+ public RelayCommand StartRemoteSyncCommand { get; set; }
+
+ public RelayCommand StartDirectRemoteSyncCommand { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/RemoteSynchronizationViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/RemoteSynchronizationViewVM.cs
new file mode 100644
index 000000000..e14b0ffb9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/ViewModels/RemoteSynchronizationViewVM.cs
@@ -0,0 +1,372 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Entity.Validation;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.DAL.Local.DB;
+using Tango.DAL.Observables;
+using Tango.DAL.Remote.DB;
+using Tango.Logging;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Common.StudioApplication;
+using Tango.MachineStudio.Synchronization.Navigation;
+using Tango.Settings;
+using Tango.SharedUI;
+using Tango.Synchronization;
+using Tango.Synchronization.Local;
+using Tango.Synchronization.Remote;
+
+namespace Tango.MachineStudio.Synchronization.ViewModels
+{
+ public class RemoteSynchronizationViewVM : ViewModel, IShutdownRequestBlocker
+ {
+ private SyncNavigationManager _navigation;
+ private String _slaveDBFile;
+ private INotificationProvider _notification;
+ private bool _isWorking;
+ private RemoteDBComparer _comparer;
+ private RemoteDB _remoteDB;
+ private LocalDB _localDB;
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LocalSynchronizationViewVM"/> class.
+ /// </summary>
+ /// <param name="navigation">The navigation.</param>
+ /// <param name="notification">The notification.</param>
+ public RemoteSynchronizationViewVM(SyncNavigationManager navigation, INotificationProvider notification)
+ {
+ _navigation = navigation;
+ _notification = notification;
+
+ BackCommand = new RelayCommand(() => _navigation.NavigateTo(NavigationView.MenuView));
+
+ Differences = new ObservableCollection<Diff>();
+
+ BrowseSlaveDBCommand = new RelayCommand(BrowseSlaveDB, (x) => !_isWorking);
+ CompareCommand = new RelayCommand(Compare, (x) => SlaveDBFile != null && !_isWorking && SelectedMachine != null);
+ CommitCommand = new RelayCommand(Commit, (x) => SelectedDifference != null && !_isWorking && SelectedMachine != null);
+ CommitAllCommand = new RelayCommand(CommitAll, (x) => Differences.Count > 0 && !_isWorking && SelectedMachine != null);
+ CleanCommand = new RelayCommand(CleanSlave, (x) => !_isWorking && SlaveDBFile != null);
+
+ if (File.Exists(SettingsManager.Default.MachineStudio.SynchronizationModule.RemoteSQLiteFile))
+ {
+ SlaveDBFile = SettingsManager.Default.MachineStudio.SynchronizationModule.RemoteSQLiteFile;
+ SlaveDBName = Path.GetFileName(SlaveDBFile);
+ }
+ }
+
+ #endregion
+
+ #region Commands
+
+ /// <summary>
+ /// Gets or sets the back command.
+ /// </summary>
+ public RelayCommand BackCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the browse master database command.
+ /// </summary>
+ public RelayCommand BrowseMasterDBCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the browse slave database command.
+ /// </summary>
+ public RelayCommand BrowseSlaveDBCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the compare command.
+ /// </summary>
+ public RelayCommand CompareCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the commit command.
+ /// </summary>
+ public RelayCommand CommitCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the commit all command.
+ /// </summary>
+ public RelayCommand CommitAllCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the clean command.
+ /// </summary>
+ public RelayCommand CleanCommand { get; set; }
+
+ #endregion
+
+ #region Properties
+
+ private ObservableCollection<Diff> _differences;
+ /// <summary>
+ /// Gets or sets the differences.
+ /// </summary>
+ public ObservableCollection<Diff> Differences
+ {
+ get { return _differences; }
+ set { _differences = value; RaisePropertyChanged(nameof(Differences)); }
+ }
+
+ private Diff _selectedDifference;
+ /// <summary>
+ /// Gets or sets the selected difference.
+ /// </summary>
+ public Diff SelectedDifference
+ {
+ get { return _selectedDifference; }
+ set { _selectedDifference = value; RaisePropertyChanged(nameof(SelectedDifference)); InvalidateRelayCommands(); }
+ }
+
+ private String _slaveDBName;
+ /// <summary>
+ /// Gets or sets the name of the slave database.
+ /// </summary>
+ public String SlaveDBName
+ {
+ get { return _slaveDBName; }
+ set { _slaveDBName = value; RaisePropertyChanged(nameof(SlaveDBName)); }
+ }
+
+ private Machine _selectedMachine;
+ /// <summary>
+ /// Gets or sets the selected machine.
+ /// </summary>
+ public Machine SelectedMachine
+ {
+ get { return _selectedMachine; }
+ set { _selectedMachine = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the slave database file.
+ /// </summary>
+ public String SlaveDBFile
+ {
+ get { return _slaveDBFile; }
+ set { _slaveDBFile = value; RaisePropertyChangedAuto(); }
+ }
+ #endregion
+
+ #region Private Methods
+
+ private async void CleanSlave()
+ {
+ if (_notification.ShowQuestion("Are you sure you want to erase all data on slave database?"))
+ {
+ using (_notification.PushTaskItem("Clearing database..."))
+ {
+ try
+ {
+ _isWorking = true;
+ await Task.Factory.StartNew(() =>
+ {
+ SQLiteDataBase localDB = new SQLiteDataBase(SlaveDBFile);
+ localDB.LoadTables();
+ localDB.ClearDataBase();
+ try
+ {
+ localDB.Dispose();
+ }
+ catch{ }
+ });
+
+ Differences.Clear();
+ }
+ catch (Exception ex)
+ {
+ ShowError(LogManager.Log(ex).Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ InvalidateRelayCommands();
+ SelectedDifference = null;
+ }
+ }
+ }
+ }
+
+ private void Compare()
+ {
+ Task.Factory.StartNew(() =>
+ {
+ using (_notification.PushTaskItem("Comparing Databases..."))
+ {
+ try
+ {
+ if (_comparer != null)
+ {
+ _comparer.Dispose();
+ }
+
+ _remoteDB = RemoteDB.CreateDefault();
+ _localDB = new LocalDB(SlaveDBFile);
+ _comparer = new RemoteDBComparer(_remoteDB, _localDB, SelectedMachine.SerialNumber);
+ _isWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+ var diffs = _comparer.Compare();
+ Differences = new ObservableCollection<Diff>(diffs);
+
+ if (diffs.Where(x => x.Action != DiffAction.ReplaceTableDataInSlave).Count() > 0)
+ {
+ ShowInfo("Found " + Differences.Where(x => x.Action != DiffAction.ReplaceTableDataInSlave).Count() + " differences.");
+ }
+ else
+ {
+ ShowInfo("The master and slave databases are synchronized.");
+ }
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+
+ SettingsManager.Default.MachineStudio.SynchronizationModule.RemoteSQLiteFile = SlaveDBFile;
+ SettingsManager.SaveDefaultSettings();
+ }
+ }
+ });
+ }
+
+ private void Commit()
+ {
+ Task.Factory.StartNew(() =>
+ {
+ using (_notification.PushTaskItem("Committing difference..."))
+ {
+ try
+ {
+ _isWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+ SelectedDifference.Commit();
+ _remoteDB.SaveChanges();
+ _localDB.SaveChanges();
+
+ InvokeUINow(() => Differences.Remove(SelectedDifference));
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+ }
+ }
+ });
+ }
+
+ private void CommitAll()
+ {
+ Task.Factory.StartNew(() =>
+ {
+ using (_notification.PushTaskItem("Committing all differences..."))
+ {
+ try
+ {
+ _isWorking = true;
+ InvalidateRelayCommands();
+ Thread.Sleep(1500);
+
+ for (int i = 0; i < Differences.Count; i++)
+ {
+ var diff = Differences[i];
+ using (_notification.PushTaskItem("Committing difference " + (Differences.IndexOf(diff) + 1) + "..."))
+ {
+ diff.Commit();
+ InvokeUINow(() => Differences.Remove(diff));
+ i--;
+ }
+ }
+
+ _remoteDB.SaveChanges();
+ _localDB.SaveChanges();
+ }
+ catch (DbEntityValidationException ex)
+ {
+ String message = "The following validation errors occurred while trying to update the database." + Environment.NewLine + Environment.NewLine;
+
+ foreach (var error in ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).ToList())
+ {
+ message += error.ErrorMessage + Environment.NewLine;
+ }
+
+ ShowError(message);
+ }
+ catch (Exception ex)
+ {
+ ShowError(ex.Message);
+ }
+ finally
+ {
+ _isWorking = false;
+ SelectedDifference = null;
+ InvalidateRelayCommands();
+ }
+ }
+ });
+ }
+
+ private void BrowseSlaveDB()
+ {
+ String file = BrowseForFilePath();
+ if (file != null)
+ {
+ SlaveDBFile = file;
+ SlaveDBName = Path.GetFileName(file);
+ InvalidateRelayCommands();
+ }
+ }
+
+ private String BrowseForFilePath()
+ {
+ OpenFileDialog dlg = new OpenFileDialog();
+ dlg.Title = "Select SQLite Database File";
+ dlg.Filter = "SQLite Database|*.db";
+ if (dlg.ShowDialog().Value)
+ {
+ return dlg.FileName;
+ }
+ return null;
+ }
+
+ private void ShowError(String message)
+ {
+ InvokeUINow(() => _notification.ShowError(message));
+ }
+
+ private void ShowInfo(String message)
+ {
+ InvokeUINow(() => _notification.ShowInfo(message));
+ }
+
+ public Task<bool> OnShutdownRequest()
+ {
+ if (_comparer != null)
+ {
+ _comparer.Dispose();
+ }
+ return Task.FromResult(true);
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml
new file mode 100644
index 000000000..ba0530ca6
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml
@@ -0,0 +1,204 @@
+<UserControl x:Class="Tango.MachineStudio.Synchronization.Views.DirectSynchronizationView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:fa="http://schemas.fontawesome.io/icons/"
+ xmlns:synchronization="clr-namespace:Tango.Synchronization;assembly=Tango.Synchronization"
+ xmlns:providers="clr-namespace:Tango.MachineStudio.Synchronization.AutoComplete"
+ xmlns:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Synchronization"
+ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Synchronization.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" DataContext="{x:Static global:ViewModelLocator.DirectSynchronizationViewVM}">
+
+ <UserControl.Resources>
+ <converters:BooleanToVisibilityInverseConverter x:Key="BooleanToVisibilityInverseConverter"></converters:BooleanToVisibilityInverseConverter>
+ <converters:BooleanInverseConverter x:Key="BooleanInverseConverter"></converters:BooleanInverseConverter>
+
+ <providers:MachinesProvider x:Key="MachinesProvider"></providers:MachinesProvider>
+
+ <VisualBrush x:Key="badgeBackground">
+ <VisualBrush.Visual>
+ <Border>
+ <Path Stretch="Fill" RenderTransformOrigin="0.5,0.5">
+ <Path.RenderTransform>
+ <ScaleTransform ScaleX="-1"></ScaleTransform>
+ </Path.RenderTransform>
+ <Path.Fill>
+ <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+ <GradientStop Color="#EEEEEE" Offset="0.4" />
+ <GradientStop Color="White" Offset="1"/>
+ </LinearGradientBrush>
+ </Path.Fill>
+ <Path.Data>
+ <PathGeometry Figures="M 53.868 43.913 H 19.511 c -0.444 0 -0.875 -0.151 -1.221 -0.428 L 0.734 29.439 c -0.978 -0.783 -0.978 -2.271 0 -3.053 L 18.29 12.341 c 0.347 -0.277 0.777 -0.428 1.221 -0.428 h 34.356 c 1.081 0 1.958 0.877 1.958 1.958 v 28.084 c 0 1.081 -0.876 1.958 -1.957 1.958 z" FillRule="NonZero"/>
+ </Path.Data>
+ </Path>
+ </Border>
+ </VisualBrush.Visual>
+ </VisualBrush>
+ </UserControl.Resources>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="100" />
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <Grid>
+ <StackPanel Orientation="Horizontal" Margin="20">
+ <Button Style="{StaticResource MaterialDesignFlatButton}" Padding="0" Margin="0 5 0 0" VerticalAlignment="Center" Command="{Binding BackCommand}">
+ <materialDesign:PackIcon Kind="ArrowLeft" Foreground="#303030" ToolTip="Back" VerticalAlignment="Center" Width="40" Height="40"></materialDesign:PackIcon>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" FontSize="30">Direct Database Synchronization</TextBlock>
+ </StackPanel>
+ </Grid>
+
+ <Grid Margin="20" Grid.Row="1">
+ <GroupBox Header="Compare &amp; Synchronize">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="57*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition MaxWidth="250" />
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="1*"/>
+ </Grid.RowDefinitions>
+
+ <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">
+ <Image Source="../Images/remote-db.png" Width="100" Margin="10" Opacity="0.8" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant"></Image>
+ <TextBlock Background="{StaticResource badgeBackground}" Padding="5" Width="200" FontSize="14" HorizontalAlignment="Left">Remote Database</TextBlock>
+ <StackPanel Orientation="Horizontal" Margin="0 5 0 0">
+ <fa:ImageAwesome Icon="Key" Width="16" Height="16"></fa:ImageAwesome>
+ <autoComplete:AutoCompleteTextBox Margin="5 0 0 0" IsEnabled="{Binding IsWorking,Converter={StaticResource BooleanInverseConverter}}" Width="170" materialDesign:HintAssist.Hint="Enter machine serial number" DisplayMember="SerialNumber" Provider="{StaticResource ResourceKey=MachinesProvider}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
+ <autoComplete:AutoCompleteTextBox.ItemTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding SerialNumber}"></TextBlock>
+ </DataTemplate>
+ </autoComplete:AutoCompleteTextBox.ItemTemplate>
+ <autoComplete:AutoCompleteTextBox.LoadingContent>
+ <TextBlock Text="Loading..." Margin="5" FontSize="14" />
+ </autoComplete:AutoCompleteTextBox.LoadingContent>
+ </autoComplete:AutoCompleteTextBox>
+ </StackPanel>
+ </StackPanel>
+
+ <StackPanel Margin="20 0 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Row="1" >
+ <Image Source="../Images/machine-trans.png" RenderOptions.BitmapScalingMode="Fant" Width="110"></Image>
+ <TextBlock Margin="0 20 0 0">
+ <Run FontWeight="Bold">IP Address:</Run>
+ <Run Text="{Binding ApplicationManager.ConnectedMachine.IPAddress,Mode=OneWay}"></Run>
+ </TextBlock>
+ <TextBlock Margin="0 5 0 0">
+ <Run FontWeight="Bold">Serial Number:</Run>
+ <Run Text="{Binding ApplicationManager.ConnectedMachine.SerialNumber,Mode=OneWay}"></Run>
+ </TextBlock>
+ <TextBlock Margin="0 5 0 0">
+ <Run FontWeight="Bold">Organization:</Run>
+ <Run Text="{Binding ApplicationManager.ConnectedMachine.Organization,Mode=OneWay}"></Run>
+ </TextBlock>
+ </StackPanel>
+
+ </Grid>
+
+ <Button Margin="20 10" Grid.Row="1" Width="200" Height="40" HorizontalAlignment="Left" Command="{Binding CompareCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMPARE</TextBlock>
+ <fa:ImageAwesome Icon="LongArrowRight" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+
+ <Grid Grid.Column="1">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="625*"/>
+ <ColumnDefinition Width="347*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="20"/>
+ <RowDefinition Height="205*"/>
+ </Grid.RowDefinitions>
+ <TextBlock Margin="10 5 0 0" FontSize="14">Differences</TextBlock>
+ <ListBox Margin="10" Background="#F1F1F1" Grid.Row="1" ItemsSource="{Binding Differences}" SelectedItem="{Binding SelectedDifference,Mode=TwoWay}">
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Border Padding="10">
+ <StackPanel Orientation="Horizontal">
+ <fa:ImageAwesome Icon="Cog" Width="20" Height="20" Foreground="Gray"></fa:ImageAwesome>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" Text="{Binding Description}">
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Setter Property="Foreground" Value="Red"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Action}" Value="ReplaceTableDataInSlave">
+ <Setter Property="Foreground" Value="#404040"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Bottom" Grid.Column="1">SQL Command</TextBlock>
+ <TextBox Grid.Column="1" Margin="10" Style="{x:Null}" BorderThickness="0" Foreground="Gray" FontSize="14" Text="{Binding SelectedDifference.Command,Mode=OneWay}" IsReadOnly="True" Background="#F1F1F1" Padding="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" Grid.Row="1"></TextBox>
+ </Grid>
+
+ <Grid Grid.Row="1" Grid.Column="1">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
+ <StackPanel VerticalAlignment="Center" Orientation="Horizontal" Margin="0 0 20 0">
+ <TextBlock>Clear Machine Before Synchronization</TextBlock>
+ <ToggleButton Margin="10 0 0 0" IsChecked="{Binding IsClearMachine}" Foreground="Red" Style="{StaticResource MaterialDesignSwitchToggleButton}" ></ToggleButton>
+ </StackPanel>
+ <Button Margin="10 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Right" Command="{Binding CommitAllCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">SYNCHRONIZE</TextBlock>
+ <fa:ImageAwesome Icon="SortAmountAsc" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </GroupBox>
+ </Grid>
+
+ <Grid Grid.Row="1" Visibility="{Binding ApplicationManager.IsMachineConnected,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
+ <Grid.Background>
+ <SolidColorBrush Color="White" Opacity="0.8"></SolidColorBrush>
+ </Grid.Background>
+
+ <TextBlock Foreground="Silver" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40">
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Style.Triggers>
+ <EventTrigger RoutedEvent="Loaded">
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="00:00:01" RepeatBehavior="Forever">
+ <LinearDoubleKeyFrame Value="0" KeyTime="00:00:00"></LinearDoubleKeyFrame>
+ <LinearDoubleKeyFrame Value="1" KeyTime="00:00:0.5"></LinearDoubleKeyFrame>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ No Machine Connection
+ </TextBlock>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml.cs
new file mode 100644
index 000000000..5a7c12646
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/DirectSynchronizationView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Synchronization.Views
+{
+ /// <summary>
+ /// Interaction logic for DirectSynchronizationView.xaml
+ /// </summary>
+ public partial class DirectSynchronizationView : UserControl
+ {
+ public DirectSynchronizationView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml
new file mode 100644
index 000000000..e5a4aac5a
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml
@@ -0,0 +1,164 @@
+<UserControl x:Class="Tango.MachineStudio.Synchronization.Views.LocalSynchronizationView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:synchronization="clr-namespace:Tango.Synchronization;assembly=Tango.Synchronization"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Synchronization"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Synchronization.Views"
+ xmlns:fa="http://schemas.fontawesome.io/icons/"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" DataContext="{x:Static global:ViewModelLocator.LocalSynchronizationViewVM}">
+
+ <UserControl.Resources>
+ <VisualBrush x:Key="badgeBackground">
+ <VisualBrush.Visual>
+ <Border>
+ <Path Stretch="Fill" RenderTransformOrigin="0.5,0.5">
+ <Path.RenderTransform>
+ <ScaleTransform ScaleX="-1"></ScaleTransform>
+ </Path.RenderTransform>
+ <Path.Fill>
+ <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+ <GradientStop Color="#EEEEEE" Offset="0.4" />
+ <GradientStop Color="White" Offset="1"/>
+ </LinearGradientBrush>
+ </Path.Fill>
+ <Path.Data>
+ <PathGeometry Figures="M 53.868 43.913 H 19.511 c -0.444 0 -0.875 -0.151 -1.221 -0.428 L 0.734 29.439 c -0.978 -0.783 -0.978 -2.271 0 -3.053 L 18.29 12.341 c 0.347 -0.277 0.777 -0.428 1.221 -0.428 h 34.356 c 1.081 0 1.958 0.877 1.958 1.958 v 28.084 c 0 1.081 -0.876 1.958 -1.957 1.958 z" FillRule="NonZero"/>
+ </Path.Data>
+ </Path>
+ </Border>
+ </VisualBrush.Visual>
+ </VisualBrush>
+ </UserControl.Resources>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="100"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Grid>
+ <StackPanel Orientation="Horizontal" Margin="20">
+ <Button Style="{StaticResource MaterialDesignFlatButton}" Padding="0" Margin="0 5 0 0" VerticalAlignment="Center" Command="{Binding BackCommand}">
+ <materialDesign:PackIcon Kind="ArrowLeft" Foreground="#303030" ToolTip="Back" VerticalAlignment="Center" Width="40" Height="40"></materialDesign:PackIcon>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" FontSize="30">Local Database Synchronization</TextBlock>
+ </StackPanel>
+ </Grid>
+ <Grid Grid.Row="1">
+ <Grid Margin="20">
+ <GroupBox Header="Compare &amp; Synchronize">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="57*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition MaxWidth="250" />
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition/>
+ <RowDefinition/>
+ </Grid.RowDefinitions>
+
+ <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">
+ <Image Source="../Images/sqlite.png" Width="100" Margin="10" Opacity="0.8" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant"></Image>
+ <TextBlock Background="{StaticResource badgeBackground}" Padding="5" Width="200" FontSize="14" HorizontalAlignment="Left">Master Database</TextBlock>
+ <StackPanel Orientation="Horizontal" Margin="0 5 0 0">
+ <TextBox IsReadOnly="True" Width="130" BorderBrush="#4E4E4E" Text="{Binding MasterDBName}" ToolTip="{Binding MasterDBFile}"></TextBox>
+ <Button Margin="5 0 0 0" Cursor="Hand" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding BrowseMasterDBCommand}" ToolTip="Browse for master database file">
+ <fa:ImageAwesome Icon="FolderOpen" Width="24" Foreground="Gray"></fa:ImageAwesome>
+ </Button>
+ </StackPanel>
+ </StackPanel>
+
+ <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="1" Margin="20 0 0 0">
+ <Image Source="../Images/sqlite.png" Width="80" Margin="10" Opacity="0.8" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant"></Image>
+ <TextBlock Background="{StaticResource badgeBackground}" Padding="5" Width="200" FontSize="14" HorizontalAlignment="Left">Slave Database</TextBlock>
+ <StackPanel Orientation="Horizontal" Margin="0 5 0 0">
+ <TextBox IsReadOnly="True" Width="130" BorderBrush="#4E4E4E" Text="{Binding SlaveDBName}" ToolTip="{Binding SlaveDBFile}"></TextBox>
+ <Button Margin="5 0 0 0" Cursor="Hand" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding BrowseSlaveDBCommand}" ToolTip="Browse for slave database file">
+ <fa:ImageAwesome Icon="FolderOpen" Width="24" Foreground="Gray"></fa:ImageAwesome>
+ </Button>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+
+ <Button Margin="20 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Left" Command="{Binding CompareCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMPARE</TextBlock>
+ <fa:ImageAwesome Icon="LongArrowRight" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+
+ <Grid Grid.Column="1">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="671*"/>
+ <ColumnDefinition Width="301*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="20"/>
+ <RowDefinition Height="205*"/>
+ </Grid.RowDefinitions>
+ <TextBlock Margin="10 5 0 0" FontSize="14">Differences</TextBlock>
+ <ListBox Margin="10" Background="#F1F1F1" Grid.Row="1" ItemsSource="{Binding Differences}" SelectedItem="{Binding SelectedDifference,Mode=TwoWay}">
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Border Padding="10">
+ <StackPanel Orientation="Horizontal">
+ <fa:ImageAwesome Icon="Cog" Width="20" Height="20" Foreground="Gray"></fa:ImageAwesome>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" Text="{Binding Description}">
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Setter Property="Foreground" Value="Red"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Action}" Value="ReplaceTableDataInSlave">
+ <Setter Property="Foreground" Value="#404040"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+
+ <TextBlock Grid.Column="1" Margin="10 0 0 0" VerticalAlignment="Bottom">SQL Command</TextBlock>
+ <TextBox Grid.Column="1" Margin="10" Style="{x:Null}" BorderThickness="0" Foreground="Gray" FontSize="14" Text="{Binding SelectedDifference.Command,Mode=OneWay}" IsReadOnly="True" Background="#F1F1F1" Padding="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" Grid.Row="1"></TextBox>
+ </Grid>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Right" Grid.Column="1">
+ <Button Margin="10 10" Width="160" Height="40" Background="#FF4F4F" BorderBrush="#FF4F4F" Command="{Binding CleanCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">CLEAN SLAVE</TextBlock>
+ <fa:ImageAwesome Icon="TrashOutline" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ <Button Margin="10 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Right" Command="{Binding CommitCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMMIT</TextBlock>
+ <fa:ImageAwesome Icon="Bolt" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ <Button Margin="10 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Right" Command="{Binding CommitAllCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMMIT ALL</TextBlock>
+ <fa:ImageAwesome Icon="SortAmountAsc" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ </StackPanel>
+
+ </Grid>
+ </GroupBox>
+ </Grid>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml.cs
new file mode 100644
index 000000000..f6c70143d
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/LocalSynchronizationView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Synchronization.Views
+{
+ /// <summary>
+ /// Interaction logic for LocalSynchronizationView.xaml
+ /// </summary>
+ public partial class LocalSynchronizationView : UserControl
+ {
+ public LocalSynchronizationView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml
new file mode 100644
index 000000000..664dac229
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml
@@ -0,0 +1,43 @@
+<UserControl x:Class="Tango.MachineStudio.Synchronization.Views.MainView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Synchronization.Views"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Synchronization"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" Background="White" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="200"/>
+ </Grid.RowDefinitions>
+
+ <Image Source="../Images/synch_big.png" Opacity="0.2" Margin="-100"></Image>
+
+ <controls:MultiTransitionControl x:Name="TransitionControl" x:FieldModifier="public" AlwaysFade="True" TransitionType="Zoom">
+ <controls:MultiTransitionControl.Controls>
+ <ContentControl Tag="MenuView">
+ <local:MenuView></local:MenuView>
+ </ContentControl>
+ <ContentControl Tag="LocalSynchronizationView">
+ <local:LocalSynchronizationView></local:LocalSynchronizationView>
+ </ContentControl>
+ <ContentControl Tag="RemoteSynchronizationView">
+ <local:RemoteSynchronizationView></local:RemoteSynchronizationView>
+ </ContentControl>
+ <ContentControl Tag="DirectSynchronizationView">
+ <local:DirectSynchronizationView></local:DirectSynchronizationView>
+ </ContentControl>
+ </controls:MultiTransitionControl.Controls>
+ </controls:MultiTransitionControl>
+
+ <Grid Grid.Row="1">
+ <TextBox x:Name="txtLog" TextChanged="txtLog_TextChanged" Text="{Binding Log}" Background="{StaticResource AccentColorBrush}" Opacity="0.8" Foreground="White" FontSize="11" Padding="5" Style="{x:Null}" BorderThickness="1" IsReadOnly="True" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap">
+
+ </TextBox>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml.cs
new file mode 100644
index 000000000..31d50dedb
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MainView.xaml.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Synchronization.Views
+{
+ /// <summary>
+ /// Interaction logic for MainView.xaml
+ /// </summary>
+ public partial class MainView : UserControl
+ {
+ public static MainView Instance;
+
+ public MainView()
+ {
+ InitializeComponent();
+ Instance = this;
+ }
+
+ private void txtLog_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ Task.Factory.StartNew(() =>
+ {
+ Thread.Sleep(50);
+
+ this.Dispatcher.Invoke(() =>
+ {
+ txtLog.SelectionStart = txtLog.Text.Length;
+ txtLog.ScrollToEnd();
+ });
+ });
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml
new file mode 100644
index 000000000..67501743b
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml
@@ -0,0 +1,83 @@
+<UserControl x:Class="Tango.MachineStudio.Synchronization.Views.MenuView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Synchronization.Views"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Synchronization"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" DataContext="{x:Static global:ViewModelLocator.MenuViewVM}">
+ <Grid>
+ <Grid>
+ <UniformGrid Columns="3">
+ <Grid VerticalAlignment="Center">
+ <StackPanel>
+ <StackPanel HorizontalAlignment="Center" Margin="0 0 0 30">
+ <TextBlock TextAlignment="Center" FontSize="25">Local Synchronization</TextBlock>
+ <TextBlock TextAlignment="Center" FontSize="14" Foreground="#303030">Synchronize two SQLite local database files.</TextBlock>
+ </StackPanel>
+ <Viewbox RenderOptions.BitmapScalingMode="Fant" Width="400">
+ <Grid Width="450">
+ <StackPanel>
+ <StackPanel Orientation="Horizontal">
+ <Image Source="../Images/sqlite.png" Width="160"></Image>
+ <Image Source="../Images/arrow_right.png" Width="100" RenderTransformOrigin="0.5,0.5"></Image>
+ <Image Source="../Images/sqlite.png" Width="130"></Image>
+ </StackPanel>
+
+ <Button Command="{Binding StartLocalSyncCommand}" Height="80" Margin="0 20 0 0" HorizontalAlignment="Center" Padding="10" FontSize="20" Width="200">START</Button>
+ </StackPanel>
+ </Grid>
+ </Viewbox>
+ </StackPanel>
+ </Grid>
+
+ <Grid VerticalAlignment="Center">
+ <StackPanel>
+ <StackPanel HorizontalAlignment="Center" Margin="0 0 0 30">
+ <TextBlock TextAlignment="Center" FontSize="25">Direct Remote Synchronization</TextBlock>
+ <TextBlock TextAlignment="Center" FontSize="14" Foreground="#303030">Connect and synchronized a Tango machine over the network.</TextBlock>
+ </StackPanel>
+ <Viewbox RenderOptions.BitmapScalingMode="Fant" Width="400">
+ <Grid Width="450">
+ <StackPanel>
+ <StackPanel Orientation="Horizontal">
+ <Image Source="../Images/remote-db.png" Width="200"></Image>
+ <Image Source="../Images/arrow_right.png" Width="100"></Image>
+ <Image Source="../Images/machine-trans.png" Width="120"></Image>
+ </StackPanel>
+
+ <Button Command="{Binding StartDirectRemoteSyncCommand}" Height="80" Margin="0 20 0 0" HorizontalAlignment="Center" Padding="10" FontSize="20" Width="200">START</Button>
+ </StackPanel>
+ </Grid>
+ </Viewbox>
+ </StackPanel>
+ </Grid>
+
+ <Grid VerticalAlignment="Center">
+ <StackPanel>
+ <StackPanel HorizontalAlignment="Center" Margin="0 0 0 30">
+ <TextBlock TextAlignment="Center" FontSize="25">Semi Remote Synchronization</TextBlock>
+ <TextBlock TextAlignment="Center" FontSize="14" Foreground="#303030">Synchronize local SQLite database file with the remote Twine database.</TextBlock>
+ </StackPanel>
+ <Viewbox RenderOptions.BitmapScalingMode="Fant" Width="400">
+ <Grid Width="450">
+ <StackPanel>
+ <StackPanel Orientation="Horizontal">
+ <Image Source="../Images/remote-db.png" Width="200"></Image>
+ <Image Source="../Images/arrow_right.png" Width="100"></Image>
+ <Image Source="../Images/sqlite.png" Width="120"></Image>
+ </StackPanel>
+
+ <Button Command="{Binding StartRemoteSyncCommand}" Height="80" Margin="0 20 0 0" HorizontalAlignment="Center" Padding="10" FontSize="20" Width="200">START</Button>
+ </StackPanel>
+ </Grid>
+ </Viewbox>
+ </StackPanel>
+ </Grid>
+
+ </UniformGrid>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml.cs
new file mode 100644
index 000000000..eb4c17ca0
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/MenuView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Synchronization.Views
+{
+ /// <summary>
+ /// Interaction logic for MenuView.xaml
+ /// </summary>
+ public partial class MenuView : UserControl
+ {
+ public MenuView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml
new file mode 100644
index 000000000..9bb995bd8
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml
@@ -0,0 +1,172 @@
+<UserControl x:Class="Tango.MachineStudio.Synchronization.Views.RemoteSynchronizationView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:providers="clr-namespace:Tango.MachineStudio.Synchronization.AutoComplete"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:synchronization="clr-namespace:Tango.Synchronization;assembly=Tango.Synchronization"
+ xmlns:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Synchronization"
+
+ xmlns:local="clr-namespace:Tango.MachineStudio.Synchronization.Views"
+ xmlns:fa="http://schemas.fontawesome.io/icons/"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" Background="White" DataContext="{x:Static global:ViewModelLocator.RemoteSynchronizationViewVM}">
+ <UserControl.Resources>
+
+ <providers:MachinesProvider x:Key="MachinesProvider"></providers:MachinesProvider>
+
+ <VisualBrush x:Key="badgeBackground">
+ <VisualBrush.Visual>
+ <Border>
+ <Path Stretch="Fill" RenderTransformOrigin="0.5,0.5">
+ <Path.RenderTransform>
+ <ScaleTransform ScaleX="-1"></ScaleTransform>
+ </Path.RenderTransform>
+ <Path.Fill>
+ <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
+ <GradientStop Color="#EEEEEE" Offset="0.4" />
+ <GradientStop Color="White" Offset="1"/>
+ </LinearGradientBrush>
+ </Path.Fill>
+ <Path.Data>
+ <PathGeometry Figures="M 53.868 43.913 H 19.511 c -0.444 0 -0.875 -0.151 -1.221 -0.428 L 0.734 29.439 c -0.978 -0.783 -0.978 -2.271 0 -3.053 L 18.29 12.341 c 0.347 -0.277 0.777 -0.428 1.221 -0.428 h 34.356 c 1.081 0 1.958 0.877 1.958 1.958 v 28.084 c 0 1.081 -0.876 1.958 -1.957 1.958 z" FillRule="NonZero"/>
+ </Path.Data>
+ </Path>
+ </Border>
+ </VisualBrush.Visual>
+ </VisualBrush>
+ </UserControl.Resources>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="100"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Grid>
+ <StackPanel Orientation="Horizontal" Margin="20">
+ <Button Style="{StaticResource MaterialDesignFlatButton}" Padding="0" Margin="0 5 0 0" VerticalAlignment="Center" Command="{Binding BackCommand}">
+ <materialDesign:PackIcon Kind="ArrowLeft" Foreground="#303030" ToolTip="Back" VerticalAlignment="Center" Width="40" Height="40"></materialDesign:PackIcon>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" FontSize="30">Local Database Synchronization</TextBlock>
+ </StackPanel>
+ </Grid>
+ <Grid Grid.Row="1">
+ <Grid Margin="20">
+ <GroupBox Header="Compare &amp; Synchronize">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="57*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition MaxWidth="250" />
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition/>
+ <RowDefinition/>
+ </Grid.RowDefinitions>
+
+ <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">
+ <Image Source="../Images/remote-db.png" Width="100" Margin="10" Opacity="0.8" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant"></Image>
+ <TextBlock Background="{StaticResource badgeBackground}" Padding="5" Width="200" FontSize="14" HorizontalAlignment="Left">Remote Database</TextBlock>
+ <StackPanel Orientation="Horizontal" Margin="0 5 0 0">
+ <fa:ImageAwesome Icon="Key" Width="16" Height="16"></fa:ImageAwesome>
+ <autoComplete:AutoCompleteTextBox Margin="5 0 0 0" Width="170" materialDesign:HintAssist.Hint="Enter machine serial number" DisplayMember="SerialNumber" Provider="{StaticResource ResourceKey=MachinesProvider}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
+ <autoComplete:AutoCompleteTextBox.ItemTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding SerialNumber}"></TextBlock>
+ </DataTemplate>
+ </autoComplete:AutoCompleteTextBox.ItemTemplate>
+ <autoComplete:AutoCompleteTextBox.LoadingContent>
+ <TextBlock Text="Loading..." Margin="5" FontSize="14" />
+ </autoComplete:AutoCompleteTextBox.LoadingContent>
+ </autoComplete:AutoCompleteTextBox>
+ </StackPanel>
+ </StackPanel>
+
+ <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="1" Margin="20 0 0 0">
+ <Image Source="../Images/sqlite.png" Width="80" Margin="10" Opacity="0.8" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant"></Image>
+ <TextBlock Background="{StaticResource badgeBackground}" Padding="5" Width="200" FontSize="14" HorizontalAlignment="Left">SQLite Database</TextBlock>
+ <StackPanel Orientation="Horizontal" Margin="0 5 0 0">
+ <TextBox IsReadOnly="True" Width="130" BorderBrush="#4E4E4E" Text="{Binding SlaveDBName}" ToolTip="{Binding SlaveDBFile}"></TextBox>
+ <Button Margin="5 0 0 0" Cursor="Hand" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding BrowseSlaveDBCommand}" ToolTip="Browse for slave database file">
+ <fa:ImageAwesome Icon="FolderOpen" Width="24" Foreground="Gray"></fa:ImageAwesome>
+ </Button>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+
+ <Button Margin="20 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Left" Command="{Binding CompareCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMPARE</TextBlock>
+ <fa:ImageAwesome Icon="LongArrowRight" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+
+ <Grid Grid.Column="1">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="20"/>
+ <RowDefinition Height="205*"/>
+ </Grid.RowDefinitions>
+ <TextBlock Margin="10 5 0 0" FontSize="14">Differences</TextBlock>
+ <ListBox Margin="10" Background="#F1F1F1" Grid.Row="1" ItemsSource="{Binding Differences}" SelectedItem="{Binding SelectedDifference,Mode=TwoWay}">
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Border Padding="10">
+ <StackPanel Orientation="Horizontal">
+ <fa:ImageAwesome Icon="Cog" Width="20" Height="20" Foreground="Gray"></fa:ImageAwesome>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" Text="{Binding Description}">
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Setter Property="Foreground" Value="Red"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Action}" Value="ReplaceTableDataInSlave">
+ <Setter Property="Foreground" Value="#404040"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+ </Grid>
+
+ <Grid Grid.Row="1" Grid.Column="1">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
+ <Button Margin="10 10" Grid.Row="1" Width="240" Height="40" Background="#FF4F4F" BorderBrush="#FF4F4F" HorizontalAlignment="Right" Command="{Binding CleanCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">CLEAN SQLITE DATABASE</TextBlock>
+ <fa:ImageAwesome Icon="TrashOutline" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ <Button Margin="10 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Right" Command="{Binding CommitCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMMIT</TextBlock>
+ <fa:ImageAwesome Icon="Bolt" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ <Button Margin="10 10" Grid.Row="1" Width="160" Height="40" HorizontalAlignment="Right" Command="{Binding CommitAllCommand}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">COMMIT ALL</TextBlock>
+ <fa:ImageAwesome Icon="SortAmountAsc" VerticalAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=Foreground}" Width="16"></fa:ImageAwesome>
+ </StackPanel>
+ </Button>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </GroupBox>
+ </Grid>
+
+
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml.cs
new file mode 100644
index 000000000..cee8e20d1
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/Views/RemoteSynchronizationView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Synchronization.Views
+{
+ /// <summary>
+ /// Interaction logic for LocalSynchronizationView.xaml
+ /// </summary>
+ public partial class RemoteSynchronizationView : UserControl
+ {
+ public RemoteSynchronizationView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/packages.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/packages.config
new file mode 100644
index 000000000..1fa8e3268
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Synchronization/packages.config
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="CommonServiceLocator" version="1.3" targetFramework="net46" />
+ <package id="EntityFramework" version="6.0.0" targetFramework="net46" />
+ <package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net46" />
+ <package id="Google.Protobuf" version="3.4.1" targetFramework="net46" />
+ <package id="MahApps.Metro" version="1.5.0" targetFramework="net46" />
+ <package id="MaterialDesignColors" version="1.1.2" targetFramework="net46" />
+ <package id="MaterialDesignThemes" version="2.3.1.953" targetFramework="net46" />
+ <package id="MvvmLightLibs" version="5.3.0.0" targetFramework="net46" />
+ <package id="System.Reactive" version="3.1.1" targetFramework="net46" />
+ <package id="System.Reactive.Core" version="3.1.1" targetFramework="net46" />
+ <package id="System.Reactive.Interfaces" version="3.1.1" targetFramework="net46" />
+ <package id="System.Reactive.Linq" version="3.1.1" targetFramework="net46" />
+ <package id="System.Reactive.PlatformServices" version="3.1.1" targetFramework="net46" />
+ <package id="System.Reactive.Windows.Threading" version="3.1.1" targetFramework="net46" />
+</packages> \ No newline at end of file