22 Commits
v0.12 ... 0.3

Author SHA1 Message Date
abdelkader
ddde4b0d2c Fixed minor bugs 2021-01-31 18:08:36 -05:00
abdelkader
2d864d7c00 Fix bug #4
Rearranged the main view
2021-01-31 10:37:07 -05:00
Abdel
fe018dd2e7 Update README.md 2020-12-28 21:41:55 +00:00
Abdel
ade032cdf2 Update README.md 2020-12-28 18:05:56 +00:00
abdelkader
0693da5bb4 Removed the ref for the moq lib 2020-12-28 09:16:30 -05:00
abdelkader
b3cee3a9d2 Replaced Moq with Nsubstitute 2020-12-28 09:06:45 -05:00
abdelkader
3f66b15e0b Updgrade .net to 4.5 2020-12-27 20:08:42 -05:00
abdelkader
90eb345ddb Update the Thought.vCards package 2020-12-27 15:21:18 -05:00
abdelkader
fe2d1adec2 Remove contact items even when list is filtered 2016-10-27 20:29:27 -04:00
abdelkader
485309c570 Ask to save before leaving when contact is deleted 2016-10-24 20:39:45 -04:00
Abdel
1efb72a332 FixedList to maintain MRU. Added simple config dialog 2015-09-22 22:17:14 -04:00
Abdel
3a6803bceb added some asset 2015-09-20 23:33:43 -04:00
Abdel
18fdf6c440 added comment, and removed unused interface 2015-09-20 23:06:07 -04:00
Abdel
b77cf21ca4 Merge branch 'configFile' 2015-09-20 22:20:37 -04:00
Abdel
47f87bc482 refactoring 2015-09-20 22:19:20 -04:00
Abdel
208a2b49a3 Complete rewrite of the config process 2015-09-20 19:37:39 -04:00
Abdel
57e4ff9729 draft of config file and MRU menu 2015-09-19 22:59:26 -04:00
Abdel
005710d1de forget StateTextBox for some textbox 2015-09-19 22:00:36 -04:00
Abdel
23f05e3431 fixed a filter issue, and added a closing message 2015-09-19 21:46:03 -04:00
Abdel
5b8627126f Added filename in title., and fixed filtering 2015-09-16 20:15:51 -04:00
Abdel
f801cae11e Update README.md 2015-09-15 19:39:45 -04:00
Abdel
25a560eac9 Target the .net 3.5 (Present on windows 7) 2015-09-14 20:45:02 -04:00
44 changed files with 7992 additions and 2963 deletions

View File

@@ -1,13 +1,20 @@
# vCard Editor
A Simple vcf file Editor.
![vcard](https://cloud.githubusercontent.com/assets/169070/9863134/7451d17a-5b0b-11e5-80d6-56d7a70fd5e2.jpg)
![vcard editor](https://cloud.githubusercontent.com/assets/169070/9892920/6fb417f0-5be1-11e5-981e-e9c6f9b6f86d.jpg)
- You can export easily edit (modify, delete) entries of a vcf file with this simple tool.
Thanks for Thought.vCards for his wonderful library of parsing and generating vcf format.
http://www.thoughtproject.com/Libraries/vCard/
https://github.com/drlongnecker/Thought.vCards
Also, the MVP pattern from this example :
Also, I used the MVP pattern from this example :
https://github.com/lennykean/NoteCards
Relase note:
*0.2*
- Updated the vCard library to https://github.com/acastroy/Thought.vCards
- Replaced Moq with nsubstitute (Test mocking library).

View File

@@ -1,56 +1,54 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
namespace VCFEditor.Model
{
/// <summary>
///
/// </summary>
public class Contact : INotifyPropertyChanged
{
[DisplayName(" ")]
public bool isSelected { get; set; }
[DisplayName("Name")]
public string Name
{
get { return card.FormattedName; }
set
{
card.FormattedName = value;
this.NotifyPropertyChanged("Name");
}
}
[Browsable(false)]
public vCard card { get; set; }
[Browsable(false)]
public bool isDirty { get; set; }
public Contact()
{
card = new vCard();
isSelected = false;
isDirty = false;
}
#region property change event
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
using System.ComponentModel;
using Thought.vCards;
namespace VCFEditor.Model
{
/// <summary>
///
/// </summary>
public class Contact : INotifyPropertyChanged
{
[DisplayName(" ")]
public bool isSelected { get; set; }
[DisplayName("Name")]
public string Name
{
get { return card.FormattedName; }
set
{
card.FormattedName = value;
this.NotifyPropertyChanged("Name");
}
}
[Browsable(false)]
public vCard card { get; set; }
[Browsable(false)]
public bool isDirty { get; set; }
[Browsable(false)]
public bool isDeleted { get; set; }
public Contact()
{
card = new vCard();
isSelected = false;
isDirty = false;
}
#region property change event
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace vCardEditor.Model
{
[Serializable]
public class FixedList
{
public List<string> _innerList { get; set; }
private int _size;
public int Size
{
get { return _size; }
set { _size = value; }
}
public FixedList() : this(5)
{
}
public FixedList(int size)
{
this._size = size;
this._innerList = new List<string>(size);
}
public void Enqueue(string elem)
{
_innerList.Insert(_innerList.Count, elem);
if (_innerList.Count > _size)
_innerList.RemoveAt(0);
}
public string this[int index]
{
get { return _innerList[index]; }
set { _innerList[index] = value; }
}
public bool Contains(string elem)
{
return _innerList.Any(x => string.Compare(x, elem, StringComparison.OrdinalIgnoreCase) == 0);
}
public bool IsEmpty()
{
return (this._innerList.Count == 0);
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace vCardEditor.Model
{
public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
}

View File

@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using VCFEditor.View;
using System.ComponentModel;
using System.IO;
using vCardEditor.View;
using VCFEditor.Repository;
using System.Windows.Forms;
using vCardEditor.Repository;
using vCardEditor.Model;
namespace VCFEditor.Presenter
@@ -32,14 +30,22 @@ namespace VCFEditor.Presenter
_view.FilterTextChanged += FilterTextChanged;
_view.TextBoxValueChanged += TextBoxValueChanged;
_view.BeforeLeavingContact += BeforeLeavingContact;
_view.CloseForm += CloseForm;
}
void CloseForm(object sender, FormClosingEventArgs e)
{
if (_repository.dirty && _view.AskMessage("Exit before saving", "Exit"))
e.Cancel = true;
}
public void BeforeLeavingContact(object sender, EventArg<vCard> e)
{
if (_view.SelectedContactIndex > -1)
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
{
if (_repository.dirty)
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
}
}
public void TextBoxValueChanged(object sender, EventArgs e)
@@ -73,9 +79,20 @@ namespace VCFEditor.Presenter
string path = e.Data;
if (!string.IsNullOrEmpty(path))
{
FixedList MRUList = ConfigRepository.Instance.Paths;
if (!MRUList.Contains(path))
{
MRUList.Enqueue(path);
// ConfigRepository.Instance.Paths.Clear();
_view.UpdateMRUMenu(MRUList);
}
_repository.LoadContacts(path);
_view.DisplayContacts(_repository.Contacts);
}
}
public void ChangeContactSelected(object sender, EventArgs e)
@@ -86,7 +103,10 @@ namespace VCFEditor.Presenter
vCard card = _repository.Contacts[index].card;
if (card != null)
_view.DisplayContactDetail(card);
{
_repository.Contacts[index].isDirty = false;
_view.DisplayContactDetail(card, _repository.fileName);
}
}
}

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.34209
// Version du runtime :4.0.30319.42000
//
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.

View File

@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
namespace vCardEditor.Properties
{
namespace vCardEditor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.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
{
public static Settings Default {
get {
return defaultInstance;
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel;
using vCardEditor.Model;
using System.Runtime.Serialization;
namespace vCardEditor.Repository
{
[XmlRoot("Config")]
[Serializable]
public class ConfigRepository
{
private static string ConfigFileName
{
get { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.xml"); }
}
private static ConfigRepository instance = null;
[XmlIgnore]
public static ConfigRepository Instance
{
get
{
if (instance == null)
instance = LoadConfig();
return instance;
}
}
[Description("Overwrite the file when saving")]
public bool OverWrite { get; set; }
[Description("Maximum entries for MRU ")]
public int Maximum { get; set; }
[Browsable(false)]
public FixedList Paths { get; set;}
private ConfigRepository() { }
/// <summary>
/// save config file
/// </summary>
public void SaveConfig()
{
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer xsSubmit = new XmlSerializer(typeof(ConfigRepository));
using (StringWriter sww = new StringWriter())
using (TextWriter writer = new StreamWriter(ConfigFileName))
{
xsSubmit.Serialize(writer, instance, ns);
}
}
/// <summary>
/// Load config file.
/// </summary>
/// <returns></returns>
private static ConfigRepository LoadConfig()
{
ConfigRepository obj;
try
{
if (!File.Exists(ConfigFileName))
throw new Exception();
XmlSerializer deserializer = new XmlSerializer(typeof(ConfigRepository));
using (TextReader reader = new StreamReader(ConfigFileName))
{
obj = (ConfigRepository)deserializer.Deserialize(reader);
obj.Paths.Size = obj.Maximum;
}
}
catch (Exception)
{
obj = new ConfigRepository();
obj.Paths = new FixedList(5);
}
return obj;
}
}
}

View File

@@ -1,223 +1,330 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.Repository;
namespace VCFEditor.Repository
{
public class ContactRepository : IContactRepository
{
public string fileName { get; set; }
private IFileHandler _fileHandler;
#region Contact Info
/// <summary>
/// Formatted name.
/// </summary>
public const string KeyName = "FN";
/// <summary>
/// Contact List
/// </summary>
private BindingList<Contact> _contacts;
public BindingList<Contact> Contacts
{
get
{
if (_contacts == null)
_contacts = new BindingList<Contact>();
return _contacts;
}
set
{
_contacts = value;
}
}
#endregion
public ContactRepository(IFileHandler fileHandler)
{
_fileHandler = fileHandler;
}
/// <summary>
/// Load contacts.
/// 1- Parse the file
/// 2-
/// </summary>
/// <param name="path"></param>
public BindingList<Contact> LoadContacts(string fileName)
{
this.fileName = fileName;
StringBuilder RawContent = new StringBuilder();
Contact contact = new Contact();
string[] lines = _fileHandler.ReadAllLines(fileName);
//Prevent from adding contacts to existings ones.
Contacts.Clear();
for (int i = 0; i < lines.Length; i++)
{
RawContent.AppendLine(lines[i]);
if (lines[i] == "END:VCARD")
{
contact.card = ParseRawContent(RawContent);
Contacts.Add(contact);
contact = new Contact();
RawContent.Clear();
}
}
return Contacts;
}
/// <summary>
/// Save the contact to the file.
/// </summary>
/// <param name="path">Path to the new file, else if null, we overwrite the same file</param>
public void SaveContacts(string fileName)
{
//overwrite the same file, else save as another file.
if (string.IsNullOrEmpty(fileName))
fileName = this.fileName;
StringBuilder sb = new StringBuilder();
foreach (var entry in Contacts)
sb.Append(generateRawContent(entry.card));
_fileHandler.WriteAllText(fileName, sb.ToString());
}
/// <summary>
/// Delete contacted that are selected.
/// </summary>
public void DeleteContact()
{
if (_contacts != null && _contacts.Count > 0)
{
//loop from the back to prevent index mangling...
for (int i = _contacts.Count - 1; i > -1; i--)
{
if (_contacts[i].isSelected)
_contacts.RemoveAt(i);
}
}
}
/// <summary>
/// Use the lib to parse a vcard chunk.
/// </summary>
/// <param name="rawContent"></param>
/// <returns></returns>
private vCard ParseRawContent(StringBuilder rawContent)
{
vCard card = null;
using (MemoryStream s = GenerateStreamFromString(rawContent.ToString()))
using (TextReader streamReader = new StreamReader(s, Encoding.UTF8))
{
card = new vCard(streamReader);
}
return card;
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
public List<Contact> FilterContacts(string filter)
{
List<Contact> Filtered = new List<Contact>(Contacts);
Filtered.RemoveAll(i => !(i.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0));
return Filtered;
}
/// <summary>
/// Save modified card info in the raw content.
/// </summary>
/// <param name="card"></param>
/// <param name="index"></param>
public void SaveDirtyFlag(int index)
{
if (index > -1)
_contacts[index].isDirty = true;
}
public void SaveDirtyVCard(int index, vCard NewCard)
{
if (index > -1 && _contacts[index].isDirty)
{
vCard card = _contacts[index].card;
card.FormattedName = NewCard.FormattedName;
//HomePhone
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Home) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber = NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber;
else
{
if (NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home) != null
&& !string.IsNullOrEmpty(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber))
card.Phones.Add(new vCardPhone(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber, vCardPhoneTypes.Home));
}
//Cellular
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber = NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber;
else
{
if (NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null
&& !string.IsNullOrEmpty(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber))
card.Phones.Add(new vCardPhone(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber, vCardPhoneTypes.Cellular));
}
if (card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet) != null)
card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address = NewCard.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address;
if (card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal) != null)
card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal).Url = NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Personal).Url;
_contacts[index].isDirty = false;
}
}
/// <summary>
/// Generate a VCard class from a string.
/// </summary>
/// <param name="card"></param>
/// <returns></returns>
private string generateRawContent(vCard card)
{
vCardStandardWriter writer = new vCardStandardWriter();
TextWriter tw = new StringWriter();
writer.Write(card, tw);
return tw.ToString();
}
}
}
using System;
using System.IO;
using System.Linq;
using System.Text;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.Repository;
using System.Collections.Generic;
namespace VCFEditor.Repository
{
public class ContactRepository : IContactRepository
{
public string fileName { get; set; }
private IFileHandler _fileHandler;
#region Contact Info
/// <summary>
/// Formatted name.
/// </summary>
public const string KeyName = "FN";
/// <summary>
/// Keep a copy of contact list when filtering
/// </summary>
private BindingList<Contact> OriginalContactList = null;
/// <summary>
/// Contact List
/// </summary>
private BindingList<Contact> _contacts;
public BindingList<Contact> Contacts
{
get
{
if (_contacts == null)
_contacts = new BindingList<Contact>();
return _contacts;
}
set
{
_contacts = value;
}
}
#endregion
public ContactRepository(IFileHandler fileHandler)
{
_fileHandler = fileHandler;
}
public BindingList<Contact> LoadContacts(string fileName)
{
this.fileName = fileName;
StringBuilder RawContent = new StringBuilder();
Contact contact = new Contact();
string[] lines = _fileHandler.ReadAllLines(fileName);
//Prevent from adding contacts to existings ones.
Contacts.Clear();
for (int i = 0; i < lines.Length; i++)
{
RawContent.AppendLine(lines[i]);
if (lines[i] == "END:VCARD")
{
contact.card = ParseRawContent(RawContent);
Contacts.Add(contact);
contact = new Contact();
RawContent.Length = 0;
}
}
OriginalContactList = Contacts;
_dirty = false;
return Contacts;
}
/// <summary>
/// Save the contact to the file.
/// </summary>
/// <param name="path">Path to the new file, else if null, we overwrite the same file</param>
public void SaveContacts(string fileName)
{
//overwrite the same file, else save as another file.
if (string.IsNullOrEmpty(fileName))
fileName = this.fileName;
//Take a copy...
if (!ConfigRepository.Instance.OverWrite)
File.Move(fileName, fileName + ".old");
StringBuilder sb = new StringBuilder();
//Do not save the deleted ones...
foreach (var entry in Contacts)
{
if (!entry.isDeleted)
sb.Append(generateRawContent(entry.card));
}
_fileHandler.WriteAllText(fileName, sb.ToString());
_dirty = false;
}
/// <summary>
/// Delete contacted that are selected.
/// </summary>
public void DeleteContact()
{
if (_contacts != null && _contacts.Count > 0)
{
//loop from the back to prevent index mangling...
for (int i = _contacts.Count - 1; i > -1; i--)
{
if (_contacts[i].isSelected)
{
_contacts[i].isDeleted = true;
_contacts.RemoveAt(i);
_dirty = true;
}
}
}
}
/// <summary>
/// Use the lib to parse a vcard chunk.
/// </summary>
/// <param name="rawContent"></param>
/// <returns></returns>
private vCard ParseRawContent(StringBuilder rawContent)
{
vCard card = null;
using (MemoryStream s = GenerateStreamFromString(rawContent.ToString()))
using (TextReader streamReader = new StreamReader(s, Encoding.UTF8))
{
card = new vCard(streamReader);
}
return card;
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
public BindingList<Contact> FilterContacts(string filter)
{
var list = OriginalContactList.Where(i => (i.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) &&
!i.isDeleted);
Contacts = new BindingList<Contact>(list.ToList());
return Contacts;
}
/// <summary>
/// Save modified card info in the raw content.
/// </summary>
/// <param name="card"></param>
/// <param name="index"></param>
public void SaveDirtyFlag(int index)
{
if (index > -1)
_contacts[index].isDirty = true;
}
public void SaveDirtyVCard(int index, vCard NewCard)
{
if (index > -1 && _contacts[index].isDirty)
{
vCard card = _contacts[index].card;
card.Title = NewCard.Title;
card.FormattedName = NewCard.FormattedName;
SavePhone(NewCard, card);
SaveEmail(NewCard, card);
SaveWebUrl(NewCard, card);
_contacts[index].isDirty = false;
_dirty = true;
}
}
private void SavePhone(vCard NewCard, vCard card)
{
//HomePhone
if (NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home) != null)
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Home) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber = NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber;
else
card.Phones.Add(new vCardPhone(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber, vCardPhoneTypes.Home));
}
else
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Home) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber = string.Empty;
}
//Cellular
if (NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber = NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber;
else
card.Phones.Add(new vCardPhone(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber, vCardPhoneTypes.Cellular));
}
else
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber = string.Empty;
}
//Work
if (NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Work) != null)
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Work) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Work).FullNumber = NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Work).FullNumber;
else
card.Phones.Add(new vCardPhone(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Work).FullNumber, vCardPhoneTypes.Work));
}
else
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Work) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Work).FullNumber = string.Empty;
}
}
private void SaveEmail(vCard NewCard, vCard card)
{
//Work
if (NewCard.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet) != null)
{
if (card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet) != null)
card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address
= NewCard.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address;
else
card.EmailAddresses.Add(new vCardEmailAddress(NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Work).FullNumber,
vCardEmailAddressType.Internet));
}
else
{
if (card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet) != null)
card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address = string.Empty;
}
}
private void SaveWebUrl(vCard NewCard, vCard card)
{
if (NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Personal) != null)
{
if (card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal) != null)
card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal).Url = NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Personal).Url;
else
card.Websites.Add(new vCardWebsite(NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Personal).Url, vCardWebsiteTypes.Personal));
}
else
{
if (card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal) != null)
card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal).Url = string.Empty;
}
if (NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Work) != null)
{
if (card.Websites.GetFirstChoice(vCardWebsiteTypes.Work) != null)
card.Websites.GetFirstChoice(vCardWebsiteTypes.Work).Url = NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Work).Url;
else
card.Websites.Add(new vCardWebsite(NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Work).Url, vCardWebsiteTypes.Work));
}
else
{
if (card.Websites.GetFirstChoice(vCardWebsiteTypes.Work) != null)
card.Websites.GetFirstChoice(vCardWebsiteTypes.Work).Url = string.Empty;
}
}
/// <summary>
/// Generate a VCard class from a string.
/// </summary>
/// <param name="card"></param>
/// <returns></returns>
private string generateRawContent(vCard card)
{
vCardStandardWriter writer = new vCardStandardWriter();
TextWriter tw = new StringWriter();
writer.Write(card, tw);
return tw.ToString();
}
/// <summary>
/// Check if some iem in the contact list is modified
/// </summary>
/// <returns>true for dirty</returns>
private bool _dirty;
public bool dirty
{
get { return _dirty || (_contacts != null && _contacts.Any(x => x.isDirty)); }
set { _dirty = value; }
}
}
}

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
@@ -12,13 +11,15 @@ namespace VCFEditor.Repository
public interface IContactRepository
{
string fileName { get; set; }
BindingList<Contact> Contacts { get; set; }
BindingList<Contact> Contacts { get; set; }
bool dirty { get; set; }
BindingList<Contact> LoadContacts(string fileName);
void SaveContacts(string fileName);
void DeleteContact();
List<Contact> FilterContacts(string p);
BindingList<Contact> FilterContacts(string p);
void SaveDirtyFlag(int index);
void SaveDirtyVCard(int index, vCard card);
void SaveDirtyVCard(int index, vCard card);
}
}

View File

@@ -39,7 +39,7 @@ namespace Thought.vCards {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Thought.vCards.WarningMessages", typeof(WarningMessages).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("vCardEditor.Thought.vCards.WarningMessages", typeof(WarningMessages).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@@ -72,6 +72,8 @@ namespace Thought.vCards
private vCardPhotoCollection photos;
private vCardSourceCollection sources;
private vCardWebsiteCollection websites;
private vCardIMPPCollection ims;
private vCardSocialProfileCollection sps;
/// <summary>
/// Initializes a new instance of the <see cref="vCard"/> class.
@@ -111,6 +113,8 @@ namespace Thought.vCards
this.photos = new vCardPhotoCollection();
this.sources = new vCardSourceCollection();
this.websites = new vCardWebsiteCollection();
this.ims = new vCardIMPPCollection();
this.sps = new vCardSocialProfileCollection();
}
@@ -147,32 +151,9 @@ namespace Thought.vCards
vCardReader reader = new vCardStandardReader();
reader.ReadInto(this, streamReader);
}
//String example = "BEGIN:VCARD\nVERSION:3.0\nN:;Saad;;;\nFN:Saad\nTEL;TYPE=CELL:418-271-3874\nTEL;TYPE=HOME:418-524-7721\nEND:VCARD";
// using (MemoryStream s = GenerateStreamFromString(example))
//{
// vCardReader reader = new vCardStandardReader();
// TextReader streamReader = new StreamReader(s, Encoding.Default);
// reader.ReadInto(this, streamReader);
//}
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public MemoryStream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
/// <summary>
/// The security access classification of the vCard owner (e.g. private).
@@ -764,5 +745,21 @@ namespace Thought.vCards
}
}
/// <summary>
/// IMPP Collection
/// </summary>
public vCardIMPPCollection IMs
{
get { return this.ims; }
}
/// <summary>
/// SocialProfile collection for the vCard in the X-SOCIALPROFILE property
/// </summary>
public vCardSocialProfileCollection SocialProfiles
{
get { return this.sps; }
}
}
}

View File

@@ -6,6 +6,7 @@
* ======================================================================= */
using System;
using System.Collections.Generic;
namespace Thought.vCards
{
@@ -18,7 +19,7 @@ namespace Thought.vCards
public class vCardDeliveryAddress
{
private vCardDeliveryAddressTypes addressType;
private List<vCardDeliveryAddressTypes> addressType;
private string city;
private string country;
private string postalCode;
@@ -36,13 +37,14 @@ namespace Thought.vCards
this.postalCode = string.Empty;
this.region = string.Empty;
this.street = string.Empty;
this.addressType = new List<vCardDeliveryAddressTypes>();
}
/// <summary>
/// The type of postal address.
/// </summary>
public vCardDeliveryAddressTypes AddressType
public List<vCardDeliveryAddressTypes> AddressType
{
get
{
@@ -94,21 +96,7 @@ namespace Thought.vCards
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Domestic) ==
vCardDeliveryAddressTypes.Domestic;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Domestic;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Domestic;
}
return (addressType.Contains(vCardDeliveryAddressTypes.Domestic));
}
}
@@ -120,20 +108,7 @@ namespace Thought.vCards
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Home) ==
vCardDeliveryAddressTypes.Home;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Home;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Home;
}
return (addressType.Contains(vCardDeliveryAddressTypes.Home));
}
}
@@ -145,19 +120,7 @@ namespace Thought.vCards
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.International) ==
vCardDeliveryAddressTypes.International;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.International;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.International;
}
return (addressType.Contains(vCardDeliveryAddressTypes.International));
}
}
@@ -169,19 +132,7 @@ namespace Thought.vCards
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Parcel) ==
vCardDeliveryAddressTypes.Parcel;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Parcel;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Parcel;
}
return (addressType.Contains(vCardDeliveryAddressTypes.Parcel));
}
}
@@ -193,19 +144,7 @@ namespace Thought.vCards
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Postal) ==
vCardDeliveryAddressTypes.Postal;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Postal;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Postal;
}
return (addressType.Contains(vCardDeliveryAddressTypes.Postal));
}
}
@@ -217,19 +156,18 @@ namespace Thought.vCards
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Work) ==
vCardDeliveryAddressTypes.Work;
return (addressType.Contains(vCardDeliveryAddressTypes.Work));
}
set
}
/// <summary>
/// Indicates a preferred address
/// </summary>
public bool IsPreferred
{
get
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Work;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Work;
}
return (addressType.Contains(vCardDeliveryAddressTypes.Preferred));
}
}

View File

@@ -13,7 +13,6 @@ namespace Thought.vCards
/// <summary>
/// The type of a delivery address.
/// </summary>
[Flags]
public enum vCardDeliveryAddressTypes
{
@@ -50,7 +49,12 @@ namespace Thought.vCards
/// <summary>
/// A work delivery address.
/// </summary>
Work
Work,
/// <summary>
/// you can mark an address as Preferred type="pref"
/// </summary>
Preferred
}
}

View File

@@ -6,6 +6,7 @@
* ======================================================================= */
using System;
using System.Collections.Generic;
namespace Thought.vCards
{
@@ -18,7 +19,7 @@ namespace Thought.vCards
public class vCardDeliveryLabel
{
private vCardDeliveryAddressTypes addressType;
private List<vCardDeliveryAddressTypes> addressType;
private string text;
@@ -27,6 +28,7 @@ namespace Thought.vCards
/// </summary>
public vCardDeliveryLabel()
{
this.addressType = new List<vCardDeliveryAddressTypes>();
}
@@ -42,170 +44,107 @@ namespace Thought.vCards
public vCardDeliveryLabel(string text)
{
this.text = text == null ? string.Empty : text;
this.addressType = new List<vCardDeliveryAddressTypes>();
}
/// <summary>
/// The type of delivery address for the label.
/// </summary>
public vCardDeliveryAddressTypes AddressType
{
get
{
return this.addressType;
}
set
{
this.addressType = value;
}
}
/// <summary>
/// The type of postal address.
/// </summary>
public List<vCardDeliveryAddressTypes> AddressType
{
get
{
return this.addressType;
}
set
{
this.addressType = value;
}
}
/// <summary>
/// Indicates a domestic delivery address.
/// </summary>
public bool IsDomestic
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Domestic) ==
vCardDeliveryAddressTypes.Domestic;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Domestic;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Domestic;
}
}
}
/// <summary>
/// Indicates a domestic delivery address.
/// </summary>
public bool IsDomestic
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.Domestic));
}
}
/// <summary>
/// Indicates a home address.
/// </summary>
public bool IsHome
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Home) ==
vCardDeliveryAddressTypes.Home;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Home;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Home;
}
}
}
/// <summary>
/// Indicates a home address.
/// </summary>
public bool IsHome
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.Home));
}
}
/// <summary>
/// Indicates an international address.
/// </summary>
public bool IsInternational
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.International) ==
vCardDeliveryAddressTypes.International;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.International;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.International;
}
}
}
/// <summary>
/// Indicates an international address.
/// </summary>
public bool IsInternational
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.International));
}
}
/// <summary>
/// Indicates a parcel delivery address.
/// </summary>
public bool IsParcel
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Parcel) ==
vCardDeliveryAddressTypes.Parcel;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Parcel;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Parcel;
}
}
}
/// <summary>
/// Indicates a parcel delivery address.
/// </summary>
public bool IsParcel
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.Parcel));
}
}
/// <summary>
/// Indicates a postal address.
/// </summary>
public bool IsPostal
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Postal) ==
vCardDeliveryAddressTypes.Postal;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Postal;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Postal;
}
}
}
/// <summary>
/// Indicates a postal address.
/// </summary>
public bool IsPostal
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.Postal));
}
}
/// <summary>
/// Indicates a work address.
/// </summary>
public bool IsWork
{
get
{
return (this.addressType & vCardDeliveryAddressTypes.Work) ==
vCardDeliveryAddressTypes.Work;
}
set
{
if (value)
{
this.addressType |= vCardDeliveryAddressTypes.Work;
}
else
{
this.addressType &= ~vCardDeliveryAddressTypes.Work;
}
}
}
/// <summary>
/// Indicates a work address.
/// </summary>
public bool IsWork
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.Work));
}
}
/// <summary>
/// Indicates a preferred address
/// </summary>
public bool IsPreferred
{
get
{
return (addressType.Contains(vCardDeliveryAddressTypes.Preferred));
}
}
/// <summary>

View File

@@ -26,9 +26,10 @@ namespace Thought.vCards
private string address;
private vCardEmailAddressType emailType;
private ItemType itemType;
private bool isPreferred;
/// <summary>
/// Creates a new <see cref="vCardEmailAddress"/>.
/// </summary>
@@ -36,6 +37,7 @@ namespace Thought.vCards
{
this.address = string.Empty;
this.emailType = vCardEmailAddressType.Internet;
this.itemType = ItemType.UNSPECIFIED;
}
@@ -45,29 +47,19 @@ namespace Thought.vCards
/// <param name="address">
/// The Internet email address.
/// </param>
public vCardEmailAddress(string address)
/// <param name="emailType">type of address, usually Internet. Internet is the default.</param>
/// <param name="itemType">HOME,WORK, unspecified</param>
public vCardEmailAddress(string address, vCardEmailAddressType emailType = vCardEmailAddressType.Internet, ItemType itemType = ItemType.UNSPECIFIED)
{
this.address = address == null ? string.Empty : address;
this.emailType = vCardEmailAddressType.Internet;
}
/// <summary>
/// Creates a new <see cref="vCardEmailAddress"/> of the specified type.
/// </summary>
/// <param name="address">
/// The email address.
/// </param>
/// <param name="emailType">
/// The type of email address.
/// </param>
public vCardEmailAddress(string address, vCardEmailAddressType emailType)
{
this.address = address;
this.emailType = emailType;
this.itemType = itemType;
}
/// <summary>
/// The email address.
/// </summary>
@@ -118,6 +110,16 @@ namespace Thought.vCards
}
}
/// <summary>
/// ItemType for this element (HOME,WORK,etc)
/// </summary>
public ItemType ItemType {
get { return this.itemType; }
set { this.itemType = value; }
}
/// <summary>
/// Builds a string that represents the email address.

View File

@@ -94,4 +94,24 @@ namespace Thought.vCards
}
/// <summary>
/// Identifies the HOME,WORK,ETC typing of an element
/// </summary>
public enum ItemType
{
/// <summary>
/// default - unknown
/// </summary>
UNSPECIFIED =0,
/// <summary>
/// work
/// </summary>
WORK = 1,
/// <summary>
/// home
/// </summary>
HOME =2,
}
}

View File

@@ -0,0 +1,319 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace Thought.vCards
{
/// <summary>
/// IM info <see cref="vCard"/>.
/// </summary>
[Serializable]
public class vCardIMPP
{
private string handle;
private ItemType itemType;
private IMServiceType serviceType;
/// <summary>
/// Creates a new <see cref="vCardIMPP"/> object.
/// </summary>
public vCardIMPP()
{
this.serviceType = IMServiceType.Unspecified;
}
/// <summary>
/// Creates a new <see cref="vCardIMPP"/> object with the specified handle.
/// </summary>
/// <param name="handle">the im handle</param>
/// <param name="serviceType">skype, aim, etc</param>
/// <param name="itemType">the type of IM, defaults to Unspecified</param>
public vCardIMPP(string handle, IMServiceType serviceType, ItemType itemType = ItemType.UNSPECIFIED)
{
this.handle = handle;
this.itemType = itemType;
this.serviceType = serviceType;
}
/// <summary>
/// The full IM handle.
/// </summary>
public string Handle
{
get
{
return this.handle ?? string.Empty;
}
set
{
this.handle = value;
}
}
/// <summary>
/// the IMServiceType AIM, googletalk, etc
/// </summary>
public IMServiceType ServiceType
{
get { return serviceType; }
set { serviceType = value; }
}
/// <summary>
/// The IM ItemType. home work, unspecified
/// </summary>
public ItemType ItemType
{
get
{
return this.itemType;
}
set
{
this.itemType = value;
}
}
/// <summary>
/// is PREF set on this IMPP item
/// </summary>
public bool IsPreferred { get; set; }
}
/// <summary>
/// simple enum for various types of IM services
/// </summary>
public enum IMServiceType
{
/// <summary>
/// unspecified
/// </summary>
Unspecified = 0,
/// <summary>
/// for Skype
/// </summary>
Skype,
/// <summary>
/// aim
/// </summary>
AIM,
/// <summary>
/// gtalk
/// </summary>
GoogleTalk,
/// <summary>
/// msn
/// </summary>
MSN,
/// <summary>
/// yahoo
/// </summary>
Yahoo,
/// <summary>
/// facebook
/// </summary>
Facebook,
/// <summary>
/// jabber
/// </summary>
Jabber,
/// <summary>
/// icq
/// </summary>
ICQ,
/// <summary>
/// qq
/// </summary>
QQ,
/// <summary>
/// gadu gadu
/// </summary>
GaduGadu
}
/// <summary>
/// simple class to generate the strings for given IMServiceType
/// </summary>
public static class IMTypeUtils
{
private static Dictionary<IMServiceType, string> lookup;
static IMTypeUtils()
{
lookup = new Dictionary<IMServiceType, string>();
lookup.Add(IMServiceType.AIM, "AIM:aim");
lookup.Add(IMServiceType.Facebook, "Facebook:xmpp");
lookup.Add(IMServiceType.GoogleTalk, "GoogleTalk:xmpp");
lookup.Add(IMServiceType.ICQ, "ICQ:aim");
lookup.Add(IMServiceType.Jabber, "Jabber:xmpp");
lookup.Add(IMServiceType.MSN, "MSN:msnim");
lookup.Add(IMServiceType.QQ, "QQ:x-apple");
lookup.Add(IMServiceType.Skype, "Skype:skype");
lookup.Add(IMServiceType.Yahoo, "Yahoo:ymsgr");
lookup.Add(IMServiceType.GaduGadu, "GaduGadu:x-apple");
}
/// <summary>
/// will return the property meta info to be written for a given IM serviceType
/// </summary>
///
/// <param name="serviceType">IMServiceType to get the subproperty info for </param>
/// <returns>for example GoogleTalk:xmpp, or for yahoo Yahoo:ymsgr</returns>
public static string GetIMTypePropertyFull(IMServiceType serviceType)
{
if (lookup.ContainsKey(serviceType))
{
return lookup[serviceType];
}
return null;
}
/// <summary>
/// returns the xmpp or aim or ymsgr portion of the lookup for AIM:aim, Yahoo:ysmgr, etc
/// </summary>
/// <param name="serviceType">IMServiceType to fetch the lookup for</param>
/// <returns>xmpp or msnim</returns>
public static string GetIMTypePropertySuffix(IMServiceType serviceType)
{
string suffix = null;
if (lookup.ContainsKey(serviceType))
{
string full = lookup[serviceType];
suffix = full.Substring(full.IndexOf(":") + 1);
}
return suffix;
}
/// <summary>
/// this method will return the first part of the AIM:aim , or MSN:msnim string used for writing out the property subproperty info for IMPP values
/// </summary>
/// <param name="serviceType">the IM service type to fetch from the dictionary</param>
/// <returns>AIM or QQ or Yahoo, the first string component for the lookup of serviceTypes</returns>
public static string GetIMTypePropertyPrefix(IMServiceType serviceType)
{
string prefix = null;
if (lookup.ContainsKey(serviceType))
{
string full = lookup[serviceType];
prefix = full.Substring(0, full.IndexOf(":"));
}
return prefix;
}
/// <summary>
/// the handle is coming back with the msnim:handle, so we want to return the pure handle minus the msnim:
/// </summary>
/// <param name="serviceType"></param>
/// <param name="handle"></param>
/// <returns></returns>
public static string StripHandlePrefix(IMServiceType serviceType, string handle)
{
string property = GetIMTypePropertyFull(serviceType);
if (property != null)
{
string prefix = property.Substring(property.IndexOf(":") + 1);
int prefixLength = prefix.Length + 1;
if (handle.StartsWith(prefix))
{
handle = handle.Substring(handle.IndexOf(prefix + ":") + prefixLength);
}
}
return handle;
}
/// <summary>
/// for parsing the
/// </summary>
/// <param name="imType"></param>
/// <returns></returns>
public static IMServiceType? GetIMServiceType(string imType)
{
IMServiceType? serviceType = null;
switch (imType.ToLowerInvariant())
{
case "aim":
serviceType = IMServiceType.AIM;
break;
case "facebook":
serviceType = IMServiceType.Facebook;
break;
case "googletalk":
case "google":
serviceType = IMServiceType.GoogleTalk;
break;
case "icq":
serviceType = IMServiceType.ICQ;
break;
case "jabber":
case "xmpp":
serviceType = IMServiceType.Jabber;
break;
case "msn":
serviceType = IMServiceType.MSN;
break;
case "qq":
serviceType = IMServiceType.QQ;
break;
case "skype":
serviceType = IMServiceType.Skype;
break;
case "yahoo":
case "ymsgr":
serviceType = IMServiceType.Yahoo;
break;
case "gadugadu":
case "gadu":
serviceType = IMServiceType.GaduGadu;
break;
}
return serviceType;
}
}
}

View File

@@ -0,0 +1,21 @@

/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardIMPP"/> objects.
/// </summary>
public class vCardIMPPCollection : Collection<vCardIMPP>
{
}
}

View File

@@ -143,6 +143,52 @@ namespace Thought.vCards
}
}
/// <summary>
/// Indicates an iphone
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsiPhone
{
get
{
return (this.phoneType & vCardPhoneTypes.IPhone) == vCardPhoneTypes.IPhone;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.IPhone;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.IPhone;
}
}
}
/// <summary>
/// Indicates a main number
/// </summary>
/// <seealso cref="vCardPhoneTypes"/>
public bool IsMain
{
get
{
return (this.phoneType & vCardPhoneTypes.Main) == vCardPhoneTypes.Main;
}
set
{
if (value)
{
this.phoneType = this.phoneType | vCardPhoneTypes.Main;
}
else
{
this.phoneType = this.phoneType & ~vCardPhoneTypes.Main;
}
}
}
/// <summary>
/// Indicates a fax number.

View File

@@ -107,7 +107,18 @@ namespace Thought.vCards
/// <summary>
/// Indicates a work and voice number.
/// </summary>
WorkVoice = Work + Voice
WorkVoice = Work + Voice,
/// <summary>
/// to handle iPhone type in NAB for phone
/// </summary>
IPhone = 8192,
/// <summary>
/// to handle Main type for NAB
/// </summary>
Main = 16384
}
}

View File

@@ -49,6 +49,10 @@ namespace Thought.vCards
private Uri url;
private string encodedData;
/// <summary>
/// Loads a photograph from an array of bytes.
/// </summary>
@@ -97,6 +101,27 @@ namespace Thought.vCards
}
/// <summary>
/// Creates a new vCard photo from already encoded data.
/// </summary>
/// <param name="data">
/// The base64 encoded string of the image.
/// </param>
/// <param name="isEncoded">
/// Boolean true if is encoded.
/// </param>
public vCardPhoto(string data, bool isEncoded)
{
if (string.IsNullOrEmpty(data))
{
throw new ArgumentNullException("data");
}
this.encodedData = data;
}
/// <summary>
/// Creates a new vCard photo from an existing Bitmap object.
@@ -198,8 +223,19 @@ namespace Thought.vCards
/// </remarks>
public Bitmap GetBitmap()
{
MemoryStream stream = new MemoryStream(this.data);
return new Bitmap(stream);
if (HasEncodedData)
{
var bytes = Convert.FromBase64String(this.EncodedData);
MemoryStream stream = new MemoryStream(bytes);
return new Bitmap(stream);
}
else
{
MemoryStream stream = new MemoryStream(this.data);
return new Bitmap(stream);
}
}
@@ -233,6 +269,28 @@ namespace Thought.vCards
}
}
/// <summary>
/// property used to check if the data is already encoded in base64
/// </summary>
public bool HasEncodedData
{
get
{
return this.encodedData != null;
}
}
/// <summary>
/// get base64 encoded data
/// </summary>
public string EncodedData
{
get
{
return this.encodedData;
}
}
/// <summary>
/// The URL of the image.

View File

@@ -0,0 +1,206 @@
/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace Thought.vCards
{
/// <summary>
/// IM info <see cref="vCard"/>.
/// </summary>
[Serializable]
public class vCardSocialProfile
{
private string username;
private SocialProfileServiceType serviceType;
private string fullProfileUrl;
/// <summary>
/// Creates a new <see cref="vCardIMPP"/> object.
/// </summary>
public vCardSocialProfile()
{
this.serviceType = SocialProfileServiceType.Unspecified;
}
/// <summary>
/// Creates a new <see cref="vCardIMPP"/> object with the specified handle.
/// </summary>
/// <param name="username">the social profile username handle</param>
/// <param name="serviceType">Facebook, Twitter, Flickr, etc</param>
/// <param name="fullProfileUrl">the full url for the profile => http://twitter.com/username </param>
public vCardSocialProfile(string username, SocialProfileServiceType serviceType, string fullProfileUrl)
{
this.username = username;
this.serviceType = serviceType;
this.fullProfileUrl = fullProfileUrl;
}
/// <summary>
/// the full profile url of the socialProfile (http://twitter.com/username)
/// </summary>
public string ProfileUrl
{
get
{
return this.fullProfileUrl ?? string.Empty;
}
set
{
this.fullProfileUrl = value;
}
}
/// <summary>
/// The username on the socialProfile
/// </summary>
public string Username
{
get
{
return this.username ?? string.Empty;
}
set
{
this.username = value;
}
}
/// <summary>
/// the IMServiceType AIM, googletalk, etc
/// </summary>
public SocialProfileServiceType ServiceType
{
get { return serviceType; }
set { serviceType = value; }
}
}
/// <summary>
/// simple enum for various types of SocialProfile services
/// </summary>
public enum SocialProfileServiceType
{
/// <summary>
/// unspecified
/// </summary>
Unspecified = 0,
/// <summary>
/// Facebook
/// </summary>
Facebook,
/// <summary>
/// LinkedIn
/// </summary>
LinkedIn,
/// <summary>
/// Twitter
/// </summary>
Twitter,
/// <summary>
/// Flickr
/// </summary>
Flickr,
/// <summary>
/// Myspace
/// </summary>
Myspace
}
/// <summary>
/// utisl to handle string to enum conversion in one spot for SocialProfile types
/// </summary>
public static class SocialProfileTypeUtils
{
/// <summary>
/// for parsing the type string
/// </summary>
/// <param name="profileType"></param>
/// <returns>nullable ServiceType for matching string of serviceType</returns>
public static SocialProfileServiceType? GetSocialProfileServiceType(string profileType)
{
SocialProfileServiceType? serviceType = null;
switch (profileType.ToLowerInvariant())
{
case "facebook":
serviceType = SocialProfileServiceType.Facebook;
break;
case "flickr":
serviceType = SocialProfileServiceType.Flickr;
break;
case "linkedin":
serviceType = SocialProfileServiceType.LinkedIn;
break;
case "myspace":
serviceType = SocialProfileServiceType.Myspace;
break;
case "twitter":
serviceType = SocialProfileServiceType.Twitter;
break;
}
return serviceType;
}
/// <summary>
/// for returning the socialProfile type string that will be used in the type=twitter for reading socialProfile vCard data
/// </summary>
/// <param name="serviceType">the SocialProfile Type to get the lowercase string for to include in the type value</param>
/// <returns>facebook,twitter,etc</returns>
public static string GetSocialProfileServicePropertyType(SocialProfileServiceType serviceType)
{
string profileType = null;
switch (serviceType)
{
case SocialProfileServiceType.Facebook :
profileType = "facebook";
break;
case SocialProfileServiceType.Flickr:
profileType = "flickr";
break;
case SocialProfileServiceType.LinkedIn:
profileType = "linkedin";
break;
case SocialProfileServiceType.Myspace:
profileType = "myspace";
break;
case SocialProfileServiceType.Twitter:
profileType = "twitter";
break;
}
return profileType;
}
}
}

View File

@@ -0,0 +1,21 @@

/* =======================================================================
* vCard Library for .NET
* Copyright (c) 2007-2009 David Pinch; http://wwww.thoughtproject.com
* See LICENSE.TXT for licensing information.
* ======================================================================= */
using System;
using System.Collections.ObjectModel;
namespace Thought.vCards
{
/// <summary>
/// A collection of <see cref="vCardSocialProfile"/> objects.
/// </summary>
public class vCardSocialProfileCollection : Collection<vCardSocialProfile>
{
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@ namespace Thought.vCards
private bool embedLocalImages;
private vCardStandardWriterOptions options;
private string productId;
private const string TYPE = "TYPE";
/// <summary>
/// The characters that are escaped per the original
@@ -156,7 +156,7 @@ namespace Thought.vCards
// See section 2.1.1 of RFC 2426.
properties.Add(new vCardProperty("BEGIN", "VCARD"));
properties.Add(new vCardProperty("VERSION", "3.0"));
BuildProperties_NAME(
properties,
card);
@@ -197,6 +197,8 @@ namespace Thought.vCards
properties,
card);
BuildProperties_IMPP(properties, card);
BuildProperties_KEY(
properties,
card);
@@ -257,6 +259,8 @@ namespace Thought.vCards
properties,
card);
BuildProperties_XSOCIALPROFILE(properties, card);
BuildProperties_X_WAB_GENDER(
properties,
card);
@@ -309,7 +313,7 @@ namespace Thought.vCards
values.Add(string.Empty);
values.Add(string.Empty);
values.Add(address.Street);
values.Add(!string.IsNullOrEmpty(address.Street) ? address.Street.Replace("\r\n", "\n") : string.Empty);
values.Add(address.City);
values.Add(address.Region);
values.Add(address.PostalCode);
@@ -319,22 +323,27 @@ namespace Thought.vCards
new vCardProperty("ADR", values);
if (address.IsDomestic)
property.Subproperties.Add("DOM");
property.Subproperties.Add(TYPE, "DOM");
if (address.IsInternational)
property.Subproperties.Add("INTL");
property.Subproperties.Add(TYPE, "INTL");
if (address.IsParcel)
property.Subproperties.Add("PARCEL");
property.Subproperties.Add(TYPE, "PARCEL");
if (address.IsPostal)
property.Subproperties.Add("POSTAL");
property.Subproperties.Add(TYPE, "POSTAL");
if (address.IsHome)
property.Subproperties.Add("HOME");
property.Subproperties.Add(TYPE, "HOME");
if (address.IsWork)
property.Subproperties.Add("WORK");
property.Subproperties.Add(TYPE, "WORK");
if (address.IsPreferred)
{
property.Subproperties.Add(TYPE, "PREF");
}
properties.Add(property);
@@ -359,16 +368,16 @@ namespace Thought.vCards
// The BDAY property indicates the birthdate
// of the person. The output format here is based on
// Microsoft Outlook, which writes the date as YYYMMDD.
// FIXES DateFormat with ToString
if (card.BirthDate.HasValue)
{
vCardProperty property =
new vCardProperty("BDAY", card.BirthDate.Value);
new vCardProperty("BDAY", card.BirthDate.Value.ToString("yyyy-MM-dd"));
properties.Add(property);
}
}
#endregion
@@ -467,66 +476,83 @@ namespace Thought.vCards
if (emailAddress.IsPreferred)
{
property.Subproperties.Add("PREF");
property.Subproperties.Add(TYPE, "PREF");
}
switch (emailAddress.EmailType)
{
case vCardEmailAddressType.Internet:
property.Subproperties.Add("INTERNET");
property.Subproperties.Add(TYPE, "INTERNET");
break;
case vCardEmailAddressType.AOL:
property.Subproperties.Add("AOL");
property.Subproperties.Add(TYPE, "AOL");
break;
case vCardEmailAddressType.AppleLink:
property.Subproperties.Add("AppleLink");
property.Subproperties.Add(TYPE, "AppleLink");
break;
case vCardEmailAddressType.AttMail:
property.Subproperties.Add("ATTMail");
property.Subproperties.Add(TYPE, "ATTMail");
break;
case vCardEmailAddressType.CompuServe:
property.Subproperties.Add("CIS");
property.Subproperties.Add(TYPE, "CIS");
break;
case vCardEmailAddressType.eWorld:
property.Subproperties.Add("eWorld");
property.Subproperties.Add(TYPE, "eWorld");
break;
case vCardEmailAddressType.IBMMail:
property.Subproperties.Add("IBMMail");
property.Subproperties.Add(TYPE, "IBMMail");
break;
case vCardEmailAddressType.MCIMail:
property.Subproperties.Add("MCIMail");
property.Subproperties.Add(TYPE, "MCIMail");
break;
case vCardEmailAddressType.PowerShare:
property.Subproperties.Add("POWERSHARE");
property.Subproperties.Add(TYPE, "POWERSHARE");
break;
case vCardEmailAddressType.Prodigy:
property.Subproperties.Add("PRODIGY");
property.Subproperties.Add(TYPE, "PRODIGY");
break;
case vCardEmailAddressType.Telex:
property.Subproperties.Add("TLX");
property.Subproperties.Add(TYPE, "TLX");
break;
case vCardEmailAddressType.X400:
property.Subproperties.Add("X400");
property.Subproperties.Add(TYPE, "X400");
break;
default:
property.Subproperties.Add("INTERNET");
property.Subproperties.Add(TYPE, "INTERNET");
break;
}
switch (emailAddress.ItemType)
{
case ItemType.UNSPECIFIED:
//do nothing
break;
case ItemType.HOME:
property.Subproperties.Add(TYPE, ItemType.HOME.ToString());
break;
case ItemType.WORK:
property.Subproperties.Add(TYPE, ItemType.WORK.ToString());
break;
default:
break;
}
properties.Add(property);
}
@@ -588,14 +614,76 @@ namespace Thought.vCards
}
#endregion
#endregion
#region [ BuildProperties_KEY ]
/// <summary>
/// Builds KEY properties.
/// </summary>
private void BuildProperties_KEY(
private void BuildProperties_IMPP(vCardPropertyCollection properties, vCard card)
{
// adding support for IMPP (IM handles) in the vCard
//iOS outputs this => IMPP;X-SERVICE-TYPE=Skype;type=HOME;type=pref:skype:skypeusernameee
foreach (var im in card.IMs)
{
vCardProperty property = new vCardProperty();
property.Name = "IMPP";
string prefix = IMTypeUtils.GetIMTypePropertyPrefix(im.ServiceType);
string suffix = IMTypeUtils.GetIMTypePropertySuffix(im.ServiceType);
if (!string.IsNullOrEmpty(prefix) && !string.IsNullOrEmpty(suffix))
{
property.Subproperties.Add("X-SERVICE-TYPE", prefix);
property.Value = string.Concat(suffix, ":", im.Handle);
}
else
{
property.Value = im.Handle;
}
if (im.IsPreferred)
{
property.Subproperties.Add(TYPE, "PREF");
}
switch (im.ItemType)
{
case ItemType.HOME:
property.Subproperties.Add(TYPE, ItemType.HOME.ToString());
break;
case ItemType.WORK:
property.Subproperties.Add(TYPE, ItemType.WORK.ToString());
break;
case ItemType.UNSPECIFIED:
default:
property.Subproperties.Add(TYPE, "OTHER");
break;
}
properties.Add(property);
if (im.ServiceType == IMServiceType.AIM)
{
var propertyXAim = new vCardProperty("X-AIM", im.Handle);
properties.Add(propertyXAim);
}
}
}
#region [ BuildProperties_KEY ]
/// <summary>
/// Builds KEY properties.
/// </summary>
private void BuildProperties_KEY(
vCardPropertyCollection properties,
vCard card)
{
@@ -609,7 +697,7 @@ namespace Thought.vCards
property.Name = "KEY";
property.Value = certificate.Data;
property.Subproperties.Add(certificate.KeyType);
property.Subproperties.Add(TYPE, certificate.KeyType);
properties.Add(property);
@@ -635,26 +723,23 @@ namespace Thought.vCards
vCardProperty property = new vCardProperty("LABEL", label.Text);
if (label.IsDomestic)
property.Subproperties.Add("DOM");
property.Subproperties.Add(TYPE, "DOM");
if (label.IsInternational)
property.Subproperties.Add("INTL");
property.Subproperties.Add(TYPE, "INTL");
if (label.IsParcel)
property.Subproperties.Add("PARCEL");
property.Subproperties.Add(TYPE, "PARCEL");
if (label.IsPostal)
property.Subproperties.Add("POSTAL");
property.Subproperties.Add(TYPE, "POSTAL");
if (label.IsHome)
property.Subproperties.Add("HOME");
property.Subproperties.Add(TYPE, "HOME");
if (label.IsWork)
property.Subproperties.Add("WORK");
property.Subproperties.Add(TYPE, "WORK");
// Give a hint to use QUOTED-PRINTABLE.
property.Subproperties.Add("ENCODING", "QUOTED-PRINTABLE");
properties.Add(property);
@@ -803,14 +888,13 @@ namespace Thought.vCards
vCardProperty property = new vCardProperty();
property.Name = "NOTE";
property.Value = note.Text;
property.Value = note.Text.Replace("\r\n", "\n");
if (!string.IsNullOrEmpty(note.Language))
{
property.Subproperties.Add("language", note.Language);
}
property.Subproperties.Add("ENCODING", "QUOTED-PRINTABLE");
properties.Add(property);
}
@@ -839,8 +923,20 @@ namespace Thought.vCards
if (!string.IsNullOrEmpty(card.Organization))
{
vCardProperty property =
new vCardProperty("ORG", card.Organization);
vCardProperty property;
// Add department also
if (!string.IsNullOrEmpty(card.Department))
{
vCardValueCollection values = new vCardValueCollection(';');
values.Add(card.Organization);
values.Add(card.Department);
property = new vCardProperty("ORG", values);
}
else
{
property = new vCardProperty("ORG", card.Organization);
}
properties.Add(property);
@@ -860,80 +956,89 @@ namespace Thought.vCards
foreach (vCardPhoto photo in card.Photos)
{
if (photo.Url == null)
if (photo.Url == null)
{
// This photo does not have a URL associated
// with it. Therefore a property can be
// generated only if the image data is loaded.
// Otherwise there is not enough information.
vCardProperty property = null;
if (photo.IsLoaded)
{
property = new vCardProperty("PHOTO", photo.GetBytes());
}
else if (photo.HasEncodedData)
{
property = new vCardProperty("PHOTO", photo.EncodedData);
}
if (property != null)
{
property.Subproperties.Add("TYPE", "JPEG");
properties.Add(property);
}
}
else
{
// This photo has a URL associated with it. The
// PHOTO property can either be linked as an image
// or embedded, if desired.
bool doEmbedded =
photo.Url.IsFile ? this.embedLocalImages : this.embedInternetImages;
if (doEmbedded)
{
// This photo does not have a URL associated
// with it. Therefore a property can be
// generated only if the image data is loaded.
// Otherwise there is not enough information.
// According to the settings of the card writer,
// this linked image should be embedded into the
// vCard data. Attempt to fetch the data.
if (photo.IsLoaded)
{
try
{
photo.Fetch();
}
catch
{
properties.Add(
new vCardProperty("PHOTO", photo.GetBytes()));
// An error was encountered. The image can
// still be written as a link, however.
}
doEmbedded = false;
}
}
// At this point, doEmbedded is true only if (a) the
// writer was configured to embed the image, and (b)
// the image was successfully downloaded.
if (doEmbedded)
{
properties.Add(
new vCardProperty("PHOTO", photo.GetBytes()));
}
else
{
// This photo has a URL associated with it. The
// PHOTO property can either be linked as an image
// or embedded, if desired.
vCardProperty uriPhotoProperty =
new vCardProperty("PHOTO");
bool doEmbedded =
photo.Url.IsFile ? this.embedLocalImages : this.embedInternetImages;
// Set the VALUE property to indicate that
// the data for the photo is a URI.
if (doEmbedded)
{
// According to the settings of the card writer,
// this linked image should be embedded into the
// vCard data. Attempt to fetch the data.
try
{
photo.Fetch();
}
catch
{
// An error was encountered. The image can
// still be written as a link, however.
doEmbedded = false;
}
}
// At this point, doEmbedded is true only if (a) the
// writer was configured to embed the image, and (b)
// the image was successfully downloaded.
if (doEmbedded)
{
properties.Add(
new vCardProperty("PHOTO", photo.GetBytes()));
}
else
{
vCardProperty uriPhotoProperty =
new vCardProperty("PHOTO");
// Set the VALUE property to indicate that
// the data for the photo is a URI.
uriPhotoProperty.Subproperties.Add("VALUE", "URI");
uriPhotoProperty.Value = photo.Url.ToString();
properties.Add(uriPhotoProperty);
}
uriPhotoProperty.Subproperties.Add("VALUE", "URI");
uriPhotoProperty.Value = photo.Url.ToString();
properties.Add(uriPhotoProperty);
}
}
}
}
@@ -975,7 +1080,7 @@ namespace Thought.vCards
{
vCardProperty property =
new vCardProperty("REV", card.RevisionDate.Value.ToString());
new vCardProperty("REV", card.RevisionDate.Value.ToString("s") + "Z");
properties.Add(property);
@@ -1072,43 +1177,64 @@ namespace Thought.vCards
property.Name = "TEL";
if (phone.IsBBS)
property.Subproperties.Add("BBS");
property.Subproperties.Add(TYPE, "BBS");
if (phone.IsCar)
property.Subproperties.Add("CAR");
property.Subproperties.Add(TYPE, "CAR");
if (phone.IsCellular)
property.Subproperties.Add("CELL");
property.Subproperties.Add(TYPE, "CELL");
if (phone.IsFax)
property.Subproperties.Add("FAX");
{
if (!phone.IsHome && !phone.IsWork)
{
property.Subproperties.Add(TYPE, "OTHER");
}
property.Subproperties.Add(TYPE, "FAX");
}
if (phone.IsHome)
property.Subproperties.Add("HOME");
property.Subproperties.Add(TYPE, "HOME");
if (phone.IsISDN)
property.Subproperties.Add("ISDN");
property.Subproperties.Add(TYPE, "ISDN");
if (phone.IsMessagingService)
property.Subproperties.Add("MSG");
property.Subproperties.Add(TYPE, "MSG");
if (phone.IsModem)
property.Subproperties.Add("MODEM");
property.Subproperties.Add(TYPE, "MODEM");
if (phone.IsPager)
property.Subproperties.Add("PAGER");
property.Subproperties.Add(TYPE, "PAGER");
if (phone.IsPreferred)
property.Subproperties.Add("PREF");
property.Subproperties.Add(TYPE, "PREF");
if (phone.IsVideo)
property.Subproperties.Add("VIDEO");
property.Subproperties.Add(TYPE, "VIDEO");
if (phone.IsVoice)
property.Subproperties.Add("VOICE");
{
if (!phone.IsHome && !phone.IsWork)
{
property.Subproperties.Add(TYPE, "OTHER");
}
property.Subproperties.Add(TYPE, "VOICE");
}
if (phone.IsWork)
property.Subproperties.Add("WORK");
property.Subproperties.Add(TYPE, "WORK");
if (phone.IsiPhone)
{
property.Subproperties.Add(TYPE, "IPHONE");
}
if (phone.IsMain)
{
property.Subproperties.Add(TYPE, "MAIN");
}
property.Value = phone.FullNumber;
properties.Add(property);
@@ -1195,7 +1321,10 @@ namespace Thought.vCards
new vCardProperty("URL", webSite.Url.ToString());
if (webSite.IsWorkSite)
property.Subproperties.Add("WORK");
property.Subproperties.Add(TYPE, "WORK");
// Add Subproperty for HOME aswell
if (webSite.IsPersonalSite)
property.Subproperties.Add(TYPE, "HOME");
properties.Add(property);
}
@@ -1206,6 +1335,32 @@ namespace Thought.vCards
#endregion
private void BuildProperties_XSOCIALPROFILE(vCardPropertyCollection properties, vCard card)
{
// adding support for X-SOCIALPROFILE) in the vCard
foreach (var sp in card.SocialProfiles)
{
vCardProperty property = new vCardProperty();
property.Name = "X-SOCIALPROFILE";
string propertyType = SocialProfileTypeUtils.GetSocialProfileServicePropertyType(sp.ServiceType);
property.Subproperties.Add("TYPE", propertyType);
property.Subproperties.Add("X-USER", sp.Username);
property.Value = sp.ProfileUrl;
properties.Add(property);
}
}
#region [ BuildProperties_X_WAB_GENDER ]
private void BuildProperties_X_WAB_GENDER(
@@ -1502,10 +1657,16 @@ namespace Thought.vCards
// A byte array should be encoded in BASE64 format.
builder.Append(";ENCODING=BASE64:");
builder.Append(";ENCODING=b:");
builder.Append(EncodeBase64((byte[])property.Value));
}
else if (property.Name.Equals("PHOTO", StringComparison.OrdinalIgnoreCase) && valueType == typeof(string))
{
//already base64 encoded
builder.Append(";ENCODING=b:");
builder.Append(property.Value);
}
else if (valueType == typeof(vCardValueCollection))
{

View File

@@ -0,0 +1,83 @@
namespace vCardEditor.View
{
partial class ConfigDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnClose = new System.Windows.Forms.Button();
this.pgConfig = new System.Windows.Forms.PropertyGrid();
this.btnCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnClose
//
this.btnClose.Location = new System.Drawing.Point(253, 347);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(75, 23);
this.btnClose.TabIndex = 0;
this.btnClose.Text = "Close";
this.btnClose.UseVisualStyleBackColor = true;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// pgConfig
//
this.pgConfig.Location = new System.Drawing.Point(12, 12);
this.pgConfig.Name = "pgConfig";
this.pgConfig.Size = new System.Drawing.Size(316, 329);
this.pgConfig.TabIndex = 1;
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(172, 347);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 0;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// ConfigDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(337, 382);
this.Controls.Add(this.pgConfig);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnClose);
this.Name = "ConfigDialog";
this.Text = "ConfigDialog";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.PropertyGrid pgConfig;
private System.Windows.Forms.Button btnCancel;
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Windows.Forms;
using vCardEditor.Repository;
using vCardEditor.Model;
namespace vCardEditor.View
{
public partial class ConfigDialog : Form
{
public ConfigDialog()
{
InitializeComponent();
ConfigRepository conf = ConfigRepository.Instance;//.Clone();
pgConfig.SelectedObject = conf;
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
}
}

View File

@@ -0,0 +1,120 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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>

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VCFEditor.View
{

View File

@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using System.Windows.Forms;
using vCardEditor.Model;
namespace VCFEditor.View
{
@@ -19,13 +18,13 @@ namespace VCFEditor.View
event EventHandler<EventArg<vCard>> BeforeLeavingContact;
event EventHandler<EventArg<string>> FilterTextChanged;
event EventHandler TextBoxValueChanged;
event EventHandler<FormClosingEventArgs> CloseForm;
#endregion
int SelectedContactIndex { get; }
void DisplayContacts(BindingList<Contact> contacts);
void DisplayContacts(List<Contact> contacts);
void DisplayContactDetail(vCard card);
void DisplayContactDetail(vCard card, string FileName);
bool AskMessage(string msg, string caption);
void UpdateMRUMenu(FixedList MRUList);
}
}

View File

@@ -35,6 +35,8 @@
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.miOpen = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.miConfig = new System.Windows.Forms.ToolStripMenuItem();
this.recentFilesMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.miQuit = new System.Windows.Forms.ToolStripMenuItem();
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.miAbout = new System.Windows.Forms.ToolStripMenuItem();
@@ -46,33 +48,41 @@
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.tbsAbout = new System.Windows.Forms.ToolStripButton();
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.FormattedNameLabel = new System.Windows.Forms.Label();
this.HomePhoneLabel = new System.Windows.Forms.Label();
this.FormattedNameValue = new System.Windows.Forms.TextBox();
this.CellularPhoneLabel = new System.Windows.Forms.Label();
this.PersonalWebSiteLabel = new System.Windows.Forms.Label();
this.WorkPhoneLabel = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.EmailAddressValue = new vCardEditor.View.StateTextBox();
this.EmailAddressLabel = new System.Windows.Forms.Label();
this.WorkPhoneValue = new vCardEditor.View.StateTextBox();
this.PersonalWebSiteValue = new vCardEditor.View.StateTextBox();
this.PhotoBox = new System.Windows.Forms.PictureBox();
this.CellularPhoneValue = new vCardEditor.View.StateTextBox();
this.HomePhoneValue = new vCardEditor.View.StateTextBox();
this.bsContacts = new System.Windows.Forms.BindingSource(this.components);
this.gbContactDetail = new System.Windows.Forms.GroupBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.FormattedNameLabel = new System.Windows.Forms.Label();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.EmailAddressLabel = new System.Windows.Forms.Label();
this.PersonalWebSiteLabel = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.PhotoBox = new System.Windows.Forms.PictureBox();
this.bsContacts = new System.Windows.Forms.BindingSource(this.components);
this.gbNameList = new System.Windows.Forms.GroupBox();
this.btnClearFilter = new System.Windows.Forms.Button();
this.textBoxFilter = new System.Windows.Forms.TextBox();
this.dgContacts = new System.Windows.Forms.DataGridView();
this.Column1 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.FormattedTitleLabel = new System.Windows.Forms.Label();
this.FormattedTitleValue = new vCardEditor.View.StateTextBox();
this.FormattedNameValue = new vCardEditor.View.StateTextBox();
this.EmailAddressValue = new vCardEditor.View.StateTextBox();
this.PersonalWebSiteValue = new vCardEditor.View.StateTextBox();
this.HomePhoneValue = new vCardEditor.View.StateTextBox();
this.WorkPhoneValue = new vCardEditor.View.StateTextBox();
this.CellularPhoneValue = new vCardEditor.View.StateTextBox();
this.menuStrip1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.gbContactDetail.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.PhotoBox)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.bsContacts)).BeginInit();
this.groupBox2.SuspendLayout();
this.gbNameList.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgContacts)).BeginInit();
this.SuspendLayout();
//
@@ -92,6 +102,8 @@
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miOpen,
this.toolStripMenuItem1,
this.miConfig,
this.recentFilesMenuItem,
this.miQuit});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
@@ -99,20 +111,36 @@
//
// miOpen
//
this.miOpen.Image = ((System.Drawing.Image)(resources.GetObject("miOpen.Image")));
this.miOpen.ImageTransparentColor = System.Drawing.Color.Fuchsia;
this.miOpen.Name = "miOpen";
this.miOpen.Size = new System.Drawing.Size(103, 22);
this.miOpen.Size = new System.Drawing.Size(130, 22);
this.miOpen.Text = "&Open";
this.miOpen.Click += new System.EventHandler(this.tbsOpen_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(100, 6);
this.toolStripMenuItem1.Size = new System.Drawing.Size(127, 6);
//
// miConfig
//
this.miConfig.Name = "miConfig";
this.miConfig.Size = new System.Drawing.Size(130, 22);
this.miConfig.Text = "Preference";
this.miConfig.Click += new System.EventHandler(this.miConfig_Click);
//
// recentFilesMenuItem
//
this.recentFilesMenuItem.Name = "recentFilesMenuItem";
this.recentFilesMenuItem.Size = new System.Drawing.Size(130, 22);
this.recentFilesMenuItem.Text = "Recent";
//
// miQuit
//
this.miQuit.Image = ((System.Drawing.Image)(resources.GetObject("miQuit.Image")));
this.miQuit.Name = "miQuit";
this.miQuit.Size = new System.Drawing.Size(103, 22);
this.miQuit.Size = new System.Drawing.Size(130, 22);
this.miQuit.Text = "&Quit";
this.miQuit.Click += new System.EventHandler(this.miQuit_Click);
//
@@ -126,8 +154,10 @@
//
// miAbout
//
this.miAbout.Image = ((System.Drawing.Image)(resources.GetObject("miAbout.Image")));
this.miAbout.ImageTransparentColor = System.Drawing.Color.Fuchsia;
this.miAbout.Name = "miAbout";
this.miAbout.Size = new System.Drawing.Size(152, 22);
this.miAbout.Size = new System.Drawing.Size(107, 22);
this.miAbout.Text = "&About";
this.miAbout.Click += new System.EventHandler(this.tbsAbout_Click);
//
@@ -150,7 +180,7 @@
this.toolStrip1.Location = new System.Drawing.Point(0, 24);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(808, 25);
this.toolStrip1.TabIndex = 2;
this.toolStrip1.TabIndex = 1;
this.toolStrip1.Text = "toolStrip1";
//
// tbsOpen
@@ -200,130 +230,120 @@
//
// openFileDialog
//
this.openFileDialog.FileName = "openFileDialog1";
//
// FormattedNameLabel
//
this.FormattedNameLabel.Location = new System.Drawing.Point(15, 25);
this.FormattedNameLabel.Name = "FormattedNameLabel";
this.FormattedNameLabel.Size = new System.Drawing.Size(102, 19);
this.FormattedNameLabel.TabIndex = 42;
this.FormattedNameLabel.Text = "Name:";
this.FormattedNameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.openFileDialog.Filter = "vCard Files|*.vcf";
this.openFileDialog.Title = "Open vCard File";
//
// HomePhoneLabel
//
this.HomePhoneLabel.Location = new System.Drawing.Point(34, 50);
this.HomePhoneLabel.Location = new System.Drawing.Point(25, 21);
this.HomePhoneLabel.Name = "HomePhoneLabel";
this.HomePhoneLabel.Size = new System.Drawing.Size(83, 19);
this.HomePhoneLabel.TabIndex = 43;
this.HomePhoneLabel.TabIndex = 0;
this.HomePhoneLabel.Text = "Home Phone:";
this.HomePhoneLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// FormattedNameValue
//
this.FormattedNameValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.FormattedNameValue.Location = new System.Drawing.Point(123, 24);
this.FormattedNameValue.Name = "FormattedNameValue";
this.FormattedNameValue.Size = new System.Drawing.Size(272, 20);
this.FormattedNameValue.TabIndex = 44;
this.FormattedNameValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.FormattedNameValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// CellularPhoneLabel
//
this.CellularPhoneLabel.Location = new System.Drawing.Point(25, 75);
this.CellularPhoneLabel.Location = new System.Drawing.Point(16, 46);
this.CellularPhoneLabel.Name = "CellularPhoneLabel";
this.CellularPhoneLabel.Size = new System.Drawing.Size(92, 19);
this.CellularPhoneLabel.TabIndex = 46;
this.CellularPhoneLabel.TabIndex = 2;
this.CellularPhoneLabel.Text = "Mobile:";
this.CellularPhoneLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// PersonalWebSiteLabel
//
this.PersonalWebSiteLabel.Location = new System.Drawing.Point(34, 150);
this.PersonalWebSiteLabel.Name = "PersonalWebSiteLabel";
this.PersonalWebSiteLabel.Size = new System.Drawing.Size(83, 19);
this.PersonalWebSiteLabel.TabIndex = 54;
this.PersonalWebSiteLabel.Text = "Personal Web Page:";
this.PersonalWebSiteLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// WorkPhoneLabel
//
this.WorkPhoneLabel.Location = new System.Drawing.Point(25, 125);
this.WorkPhoneLabel.Location = new System.Drawing.Point(16, 75);
this.WorkPhoneLabel.Name = "WorkPhoneLabel";
this.WorkPhoneLabel.Size = new System.Drawing.Size(92, 19);
this.WorkPhoneLabel.TabIndex = 55;
this.WorkPhoneLabel.Text = "Business Phone:";
this.WorkPhoneLabel.TabIndex = 4;
this.WorkPhoneLabel.Text = "Work Phone:";
this.WorkPhoneLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// groupBox1
// gbContactDetail
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.gbContactDetail.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.EmailAddressValue);
this.groupBox1.Controls.Add(this.EmailAddressLabel);
this.groupBox1.Controls.Add(this.WorkPhoneValue);
this.groupBox1.Controls.Add(this.PersonalWebSiteValue);
this.groupBox1.Controls.Add(this.WorkPhoneLabel);
this.groupBox1.Controls.Add(this.PersonalWebSiteLabel);
this.groupBox1.Controls.Add(this.PhotoBox);
this.groupBox1.Controls.Add(this.CellularPhoneValue);
this.groupBox1.Controls.Add(this.CellularPhoneLabel);
this.groupBox1.Controls.Add(this.HomePhoneValue);
this.groupBox1.Controls.Add(this.FormattedNameValue);
this.groupBox1.Controls.Add(this.HomePhoneLabel);
this.groupBox1.Controls.Add(this.FormattedNameLabel);
this.groupBox1.Location = new System.Drawing.Point(250, 52);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(546, 378);
this.groupBox1.TabIndex = 4;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Contact Detail :";
this.gbContactDetail.Controls.Add(this.groupBox3);
this.gbContactDetail.Controls.Add(this.groupBox2);
this.gbContactDetail.Controls.Add(this.groupBox1);
this.gbContactDetail.Controls.Add(this.PhotoBox);
this.gbContactDetail.Enabled = false;
this.gbContactDetail.Location = new System.Drawing.Point(250, 52);
this.gbContactDetail.Name = "gbContactDetail";
this.gbContactDetail.Size = new System.Drawing.Size(546, 378);
this.gbContactDetail.TabIndex = 3;
this.gbContactDetail.TabStop = false;
this.gbContactDetail.Text = "Contact Detail :";
//
// EmailAddressValue
// groupBox3
//
this.EmailAddressValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.EmailAddressValue.Location = new System.Drawing.Point(123, 99);
this.EmailAddressValue.Name = "EmailAddressValue";
this.EmailAddressValue.Size = new System.Drawing.Size(272, 20);
this.EmailAddressValue.TabIndex = 59;
this.EmailAddressValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.EmailAddressValue.Validated += new System.EventHandler(this.Value_TextChanged);
this.groupBox3.Controls.Add(this.FormattedTitleValue);
this.groupBox3.Controls.Add(this.FormattedTitleLabel);
this.groupBox3.Controls.Add(this.FormattedNameValue);
this.groupBox3.Controls.Add(this.FormattedNameLabel);
this.groupBox3.Location = new System.Drawing.Point(18, 14);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(377, 134);
this.groupBox3.TabIndex = 0;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Name";
//
// FormattedNameLabel
//
this.FormattedNameLabel.Location = new System.Drawing.Point(52, 44);
this.FormattedNameLabel.Name = "FormattedNameLabel";
this.FormattedNameLabel.Size = new System.Drawing.Size(56, 19);
this.FormattedNameLabel.TabIndex = 0;
this.FormattedNameLabel.Text = "Name:";
this.FormattedNameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.EmailAddressLabel);
this.groupBox2.Controls.Add(this.EmailAddressValue);
this.groupBox2.Controls.Add(this.PersonalWebSiteLabel);
this.groupBox2.Controls.Add(this.PersonalWebSiteValue);
this.groupBox2.Location = new System.Drawing.Point(18, 274);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(377, 89);
this.groupBox2.TabIndex = 2;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Web : ";
//
// EmailAddressLabel
//
this.EmailAddressLabel.Location = new System.Drawing.Point(-7, 100);
this.EmailAddressLabel.Location = new System.Drawing.Point(19, 29);
this.EmailAddressLabel.Name = "EmailAddressLabel";
this.EmailAddressLabel.Size = new System.Drawing.Size(124, 19);
this.EmailAddressLabel.TabIndex = 58;
this.EmailAddressLabel.Size = new System.Drawing.Size(89, 19);
this.EmailAddressLabel.TabIndex = 0;
this.EmailAddressLabel.Text = "Email Address:";
this.EmailAddressLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// WorkPhoneValue
// PersonalWebSiteLabel
//
this.WorkPhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.WorkPhoneValue.Location = new System.Drawing.Point(123, 124);
this.WorkPhoneValue.Name = "WorkPhoneValue";
this.WorkPhoneValue.Size = new System.Drawing.Size(272, 20);
this.WorkPhoneValue.TabIndex = 57;
this.WorkPhoneValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.WorkPhoneValue.Validated += new System.EventHandler(this.Value_TextChanged);
this.PersonalWebSiteLabel.Location = new System.Drawing.Point(25, 56);
this.PersonalWebSiteLabel.Name = "PersonalWebSiteLabel";
this.PersonalWebSiteLabel.Size = new System.Drawing.Size(83, 19);
this.PersonalWebSiteLabel.TabIndex = 2;
this.PersonalWebSiteLabel.Text = "Personal Web Page:";
this.PersonalWebSiteLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// PersonalWebSiteValue
// groupBox1
//
this.PersonalWebSiteValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PersonalWebSiteValue.Location = new System.Drawing.Point(123, 149);
this.PersonalWebSiteValue.Name = "PersonalWebSiteValue";
this.PersonalWebSiteValue.Size = new System.Drawing.Size(272, 20);
this.PersonalWebSiteValue.TabIndex = 56;
this.PersonalWebSiteValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.PersonalWebSiteValue.Validated += new System.EventHandler(this.Value_TextChanged);
this.groupBox1.Controls.Add(this.WorkPhoneLabel);
this.groupBox1.Controls.Add(this.HomePhoneLabel);
this.groupBox1.Controls.Add(this.HomePhoneValue);
this.groupBox1.Controls.Add(this.WorkPhoneValue);
this.groupBox1.Controls.Add(this.CellularPhoneLabel);
this.groupBox1.Controls.Add(this.CellularPhoneValue);
this.groupBox1.Location = new System.Drawing.Point(18, 160);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(377, 105);
this.groupBox1.TabIndex = 1;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Phones : ";
//
// PhotoBox
//
@@ -331,46 +351,25 @@
this.PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
this.PhotoBox.Location = new System.Drawing.Point(412, 25);
this.PhotoBox.Name = "PhotoBox";
this.PhotoBox.Size = new System.Drawing.Size(128, 144);
this.PhotoBox.Size = new System.Drawing.Size(128, 123);
this.PhotoBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.PhotoBox.TabIndex = 53;
this.PhotoBox.TabStop = false;
//
// CellularPhoneValue
// gbNameList
//
this.CellularPhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CellularPhoneValue.Location = new System.Drawing.Point(123, 74);
this.CellularPhoneValue.Name = "CellularPhoneValue";
this.CellularPhoneValue.Size = new System.Drawing.Size(272, 20);
this.CellularPhoneValue.TabIndex = 47;
this.CellularPhoneValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.CellularPhoneValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// HomePhoneValue
//
this.HomePhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.HomePhoneValue.Location = new System.Drawing.Point(123, 49);
this.HomePhoneValue.Name = "HomePhoneValue";
this.HomePhoneValue.Size = new System.Drawing.Size(272, 20);
this.HomePhoneValue.TabIndex = 45;
this.HomePhoneValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.HomePhoneValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// groupBox2
//
this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.gbNameList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.groupBox2.Controls.Add(this.btnClearFilter);
this.groupBox2.Controls.Add(this.textBoxFilter);
this.groupBox2.Controls.Add(this.dgContacts);
this.groupBox2.Location = new System.Drawing.Point(13, 52);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(231, 378);
this.groupBox2.TabIndex = 5;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Name List :";
this.gbNameList.Controls.Add(this.btnClearFilter);
this.gbNameList.Controls.Add(this.textBoxFilter);
this.gbNameList.Controls.Add(this.dgContacts);
this.gbNameList.Enabled = false;
this.gbNameList.Location = new System.Drawing.Point(13, 52);
this.gbNameList.Name = "gbNameList";
this.gbNameList.Size = new System.Drawing.Size(231, 378);
this.gbNameList.TabIndex = 2;
this.gbNameList.TabStop = false;
this.gbNameList.Text = "Name List :";
//
// btnClearFilter
//
@@ -378,7 +377,7 @@
this.btnClearFilter.Location = new System.Drawing.Point(201, 14);
this.btnClearFilter.Name = "btnClearFilter";
this.btnClearFilter.Size = new System.Drawing.Size(28, 22);
this.btnClearFilter.TabIndex = 8;
this.btnClearFilter.TabIndex = 1;
this.btnClearFilter.UseVisualStyleBackColor = true;
this.btnClearFilter.Click += new System.EventHandler(this.btnClearFilter_Click);
//
@@ -387,7 +386,7 @@
this.textBoxFilter.Location = new System.Drawing.Point(3, 15);
this.textBoxFilter.Name = "textBoxFilter";
this.textBoxFilter.Size = new System.Drawing.Size(193, 20);
this.textBoxFilter.TabIndex = 7;
this.textBoxFilter.TabIndex = 0;
this.textBoxFilter.TextChanged += new System.EventHandler(this.textBoxFilter_TextChanged);
//
// dgContacts
@@ -413,7 +412,7 @@
this.dgContacts.RowHeadersVisible = false;
this.dgContacts.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgContacts.Size = new System.Drawing.Size(225, 334);
this.dgContacts.TabIndex = 6;
this.dgContacts.TabIndex = 2;
this.dgContacts.RowLeave += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgContacts_RowLeave);
this.dgContacts.SelectionChanged += new System.EventHandler(this.dgContacts_SelectionChanged);
//
@@ -432,32 +431,133 @@
this.Column2.Name = "Column2";
this.Column2.ReadOnly = true;
//
// FormattedTitleLabel
//
this.FormattedTitleLabel.Location = new System.Drawing.Point(49, 16);
this.FormattedTitleLabel.Name = "FormattedTitleLabel";
this.FormattedTitleLabel.Size = new System.Drawing.Size(59, 19);
this.FormattedTitleValue.oldText = null;
this.FormattedTitleLabel.TabIndex = 2;
this.FormattedTitleLabel.Text = "Title:";
this.FormattedTitleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// FormattedTitleValue
//
this.FormattedTitleValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.FormattedTitleValue.Location = new System.Drawing.Point(114, 16);
this.FormattedTitleValue.Name = "FormattedTitleValue";
this.FormattedTitleValue.oldText = null;
this.FormattedTitleValue.Size = new System.Drawing.Size(225, 20);
this.FormattedTitleValue.TabIndex = 3;
this.FormattedTitleValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.FormattedTitleValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// FormattedNameValue
//
this.FormattedNameValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.FormattedNameValue.Location = new System.Drawing.Point(114, 44);
this.FormattedNameValue.Name = "FormattedNameValue";
this.FormattedNameValue.oldText = null;
this.FormattedNameValue.Size = new System.Drawing.Size(225, 20);
this.FormattedNameValue.TabIndex = 1;
this.FormattedNameValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.FormattedNameValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// EmailAddressValue
//
this.EmailAddressValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.EmailAddressValue.Location = new System.Drawing.Point(114, 28);
this.EmailAddressValue.Name = "EmailAddressValue";
this.EmailAddressValue.oldText = null;
this.EmailAddressValue.Size = new System.Drawing.Size(225, 20);
this.EmailAddressValue.TabIndex = 1;
this.EmailAddressValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.EmailAddressValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// PersonalWebSiteValue
//
this.PersonalWebSiteValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PersonalWebSiteValue.Location = new System.Drawing.Point(114, 54);
this.PersonalWebSiteValue.Name = "PersonalWebSiteValue";
this.PersonalWebSiteValue.oldText = null;
this.PersonalWebSiteValue.Size = new System.Drawing.Size(225, 20);
this.PersonalWebSiteValue.TabIndex = 3;
this.PersonalWebSiteValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.PersonalWebSiteValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// HomePhoneValue
//
this.HomePhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.HomePhoneValue.Location = new System.Drawing.Point(114, 20);
this.HomePhoneValue.Name = "HomePhoneValue";
this.HomePhoneValue.oldText = null;
this.HomePhoneValue.Size = new System.Drawing.Size(225, 20);
this.HomePhoneValue.TabIndex = 1;
this.HomePhoneValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.HomePhoneValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// WorkPhoneValue
//
this.WorkPhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.WorkPhoneValue.Location = new System.Drawing.Point(114, 74);
this.WorkPhoneValue.Name = "WorkPhoneValue";
this.WorkPhoneValue.oldText = null;
this.WorkPhoneValue.Size = new System.Drawing.Size(225, 20);
this.WorkPhoneValue.TabIndex = 5;
this.WorkPhoneValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.WorkPhoneValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// CellularPhoneValue
//
this.CellularPhoneValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CellularPhoneValue.Location = new System.Drawing.Point(114, 45);
this.CellularPhoneValue.Name = "CellularPhoneValue";
this.CellularPhoneValue.oldText = null;
this.CellularPhoneValue.Size = new System.Drawing.Size(225, 20);
this.CellularPhoneValue.TabIndex = 3;
this.CellularPhoneValue.LostFocus += new System.EventHandler(this.Value_TextChanged);
this.CellularPhoneValue.Validated += new System.EventHandler(this.Value_TextChanged);
//
// MainForm
//
this.AllowDrop = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(808, 455);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.gbNameList);
this.Controls.Add(this.gbContactDetail);
this.Controls.Add(this.toolStrip1);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.menuStrip1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MainMenuStrip = this.menuStrip1;
this.Name = "MainForm";
this.Text = "vCard Editor";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainForm_DragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.MainForm_DragEnter);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.gbContactDetail.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.PhotoBox)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.bsContacts)).EndInit();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.gbNameList.ResumeLayout(false);
this.gbNameList.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgContacts)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -482,25 +582,32 @@
private System.Windows.Forms.ToolStripButton tbsAbout;
private System.Windows.Forms.OpenFileDialog openFileDialog;
private System.Windows.Forms.BindingSource bsContacts;
internal System.Windows.Forms.Label FormattedNameLabel;
internal System.Windows.Forms.Label HomePhoneLabel;
internal System.Windows.Forms.TextBox FormattedNameValue;
internal StateTextBox HomePhoneValue;
internal System.Windows.Forms.Label CellularPhoneLabel;
internal StateTextBox CellularPhoneValue;
internal System.Windows.Forms.Label PersonalWebSiteLabel;
internal System.Windows.Forms.Label WorkPhoneLabel;
internal StateTextBox PersonalWebSiteValue;
internal StateTextBox WorkPhoneValue;
private System.Windows.Forms.GroupBox groupBox1;
internal StateTextBox EmailAddressValue;
internal System.Windows.Forms.Label EmailAddressLabel;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.GroupBox gbContactDetail;
private System.Windows.Forms.GroupBox gbNameList;
private System.Windows.Forms.TextBox textBoxFilter;
private System.Windows.Forms.DataGridView dgContacts;
private System.Windows.Forms.DataGridViewCheckBoxColumn Column1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
private System.Windows.Forms.Button btnClearFilter;
internal System.Windows.Forms.PictureBox PhotoBox;
private System.Windows.Forms.ToolStripMenuItem recentFilesMenuItem;
private System.Windows.Forms.ToolStripMenuItem miConfig;
private System.Windows.Forms.GroupBox groupBox2;
internal System.Windows.Forms.Label EmailAddressLabel;
internal StateTextBox EmailAddressValue;
internal System.Windows.Forms.Label PersonalWebSiteLabel;
internal StateTextBox PersonalWebSiteValue;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox groupBox3;
internal StateTextBox FormattedNameValue;
internal System.Windows.Forms.Label FormattedNameLabel;
internal StateTextBox FormattedTitleValue;
internal System.Windows.Forms.Label FormattedTitleLabel;
}
}

View File

@@ -1,20 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VCFEditor.View;
using VCFEditor.Model;
using Thought.vCards;
using System.IO;
using vCardEditor.Repository;
using vCardEditor.Model;
namespace vCardEditor.View
{
public partial class MainForm : Form, IMainView
{
#region event list
public event EventHandler SaveContactsSelected;
public event EventHandler DeleteContact;
public event EventHandler<EventArg<string>> NewFileOpened;
@@ -22,7 +21,8 @@ namespace vCardEditor.View
public event EventHandler<EventArg<vCard>> BeforeLeavingContact;
public event EventHandler<EventArg<string>> FilterTextChanged;
public event EventHandler TextBoxValueChanged;
public event EventHandler<FormClosingEventArgs> CloseForm;
#endregion
ComponentResourceManager resources;
public int SelectedContactIndex
@@ -41,8 +41,14 @@ namespace vCardEditor.View
{
InitializeComponent();
resources = new ComponentResourceManager(typeof(MainForm));
BuildMRUMenu();
}
private void tbsOpen_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog.ShowDialog();
@@ -58,13 +64,6 @@ namespace vCardEditor.View
}
public void DisplayContacts(List<Contact> contacts)
{
if (contacts != null)
this.bsContacts.DataSource = contacts;
}
private void tbsSave_Click(object sender, EventArgs e)
{
if (SaveContactsSelected != null)
@@ -89,28 +88,25 @@ namespace vCardEditor.View
TextBoxValueChanged(sender, e);
}
public void DisplayContactDetail(vCard card)
public void DisplayContactDetail(vCard card, string FileName)
{
if (card == null)
throw new ArgumentException("card");
throw new ArgumentException("card must be valid!");
this.Text = string.Format("{0} - vCard Editor", FileName);
gbContactDetail.Enabled = true;
gbNameList.Enabled = true;
//Formatted Name
SetSummaryValue(FormattedTitleValue, card.Title);
SetSummaryValue(FormattedNameValue, card.FormattedName);
//Home Phone
SetSummaryValue(HomePhoneValue, card.Phones.GetFirstChoice(vCardPhoneTypes.Home));
//Cellular Phone
SetSummaryValue(CellularPhoneValue, card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular));
//Email Address
SetSummaryValue(WorkPhoneValue, card.Phones.GetFirstChoice(vCardPhoneTypes.Work));
SetSummaryValue(EmailAddressValue, card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet));
// Personal Home Page
SetSummaryValue(PersonalWebSiteValue, card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal));
if (card.Photos.Count > 0)
if (card.Photos.Any())
{
var photo = card.Photos[0];
try
@@ -132,25 +128,26 @@ namespace vCardEditor.View
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
}
#region helper methods to populate textboxes.
private void SetSummaryValue(TextBox valueLabel, string value)
private void SetSummaryValue(StateTextBox valueLabel, string value)
{
if (valueLabel == null)
throw new ArgumentNullException("valueLabel");
//Clear textbox if value is empty!
valueLabel.Text = value;
valueLabel.oldText = value;
}
private void SetSummaryValue(TextBox valueLabel, vCardEmailAddress email)
private void SetSummaryValue(StateTextBox valueLabel, vCardEmailAddress email)
{
valueLabel.Text = string.Empty;
if (email != null)
SetSummaryValue(valueLabel, email.Address);
}
private void SetSummaryValue(TextBox valueLabel, vCardPhone phone)
private void SetSummaryValue(StateTextBox valueLabel, vCardPhone phone)
{
valueLabel.Text = string.Empty;
if (phone != null)
@@ -158,14 +155,14 @@ namespace vCardEditor.View
}
private void SetSummaryValue(TextBox valueLabel, vCardWebsite webSite)
private void SetSummaryValue(StateTextBox valueLabel, vCardWebsite webSite)
{
valueLabel.Text = string.Empty;
if (webSite != null)
SetSummaryValue(valueLabel, webSite.Url.ToString());
}
#endregion
private void tbsDelete_Click(object sender, EventArgs e)
{
if (DeleteContact != null)
@@ -185,6 +182,11 @@ namespace vCardEditor.View
private void textBoxFilter_TextChanged(object sender, EventArgs e)
{
//Save before leaving contact.
if (BeforeLeavingContact != null)
BeforeLeavingContact(sender, new EventArg<vCard>(getvCard()));
//filter.
if (FilterTextChanged != null)
FilterTextChanged(sender, new EventArg<string>(textBoxFilter.Text));
}
@@ -201,26 +203,22 @@ namespace vCardEditor.View
private vCard getvCard()
{
vCard card = new vCard();
card.Title = this.FormattedTitleValue.Text;
card.FormattedName = this.FormattedNameValue.Text;
if (!string.IsNullOrEmpty(HomePhoneValue.Text))
{
card.Phones.Add(
new vCardPhone(HomePhoneValue.Text, vCardPhoneTypes.Home));
}
card.Phones.Add(new vCardPhone(HomePhoneValue.Text, vCardPhoneTypes.Home));
if (!string.IsNullOrEmpty(CellularPhoneValue.Text))
{
card.Phones.Add(
new vCardPhone(CellularPhoneValue.Text, vCardPhoneTypes.Cellular));
}
card.Phones.Add(new vCardPhone(CellularPhoneValue.Text, vCardPhoneTypes.Cellular));
if (!string.IsNullOrEmpty(WorkPhoneValue.Text))
card.Phones.Add(new vCardPhone(WorkPhoneValue.Text, vCardPhoneTypes.Work));
if (!string.IsNullOrEmpty(this.EmailAddressValue.Text))
{
card.EmailAddresses.Add(
new vCardEmailAddress(this.EmailAddressValue.Text));
}
card.EmailAddresses.Add(new vCardEmailAddress(this.EmailAddressValue.Text));
if (!string.IsNullOrEmpty(this.PersonalWebSiteValue.Text))
card.Websites.Add(new vCardWebsite(this.PersonalWebSiteValue.Text));
return card;
}
@@ -267,7 +265,7 @@ namespace vCardEditor.View
/// <param name="file"></param>
private void OpenNewFile(object sender, string file)
{
string ext = Path.GetExtension(file);
string ext = System.IO.Path.GetExtension(file);
//TODO: Should parse invalid content file...
if (ext != ".vcf")
{
@@ -279,11 +277,64 @@ namespace vCardEditor.View
NewFileOpened(sender, new EventArg<string>(file));
}
private void BuildMRUMenu()
{
recentFilesMenuItem.DropDownItemClicked += (s, e) => OpenNewFile(s, e.ClickedItem.Text);
//Update the MRU Menu entries..
UpdateMRUMenu(ConfigRepository.Instance.Paths);
}
public void UpdateMRUMenu(FixedList MRUList)
{
//No need to go further if no menu entry to load!
if (MRUList == null || MRUList.IsEmpty())
return;
recentFilesMenuItem.DropDownItems.Clear();
for (int i = 0; i < MRUList._innerList.Count; i++)
recentFilesMenuItem.DropDownItems.Add(MRUList[i]);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (CloseForm != null)
CloseForm(sender, e);
ConfigRepository.Instance.SaveConfig();
}
/// <summary>
/// Ask user a question
/// </summary>
/// <param name="msg">question</param>
/// <param name="caption">caption</param>
/// <returns>true for yes, false for no</returns>
public bool AskMessage(string msg, string caption)
{
bool result = true; // true == yes
DialogResult window = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo);
if (window != DialogResult.No)
result = false;
return result;
}
/// <summary>
/// Load the config dialog
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void miConfig_Click(object sender, EventArgs e)
{
ConfigDialog dialog = new ConfigDialog();
dialog.ShowDialog();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace vCardEditor.View
{
public class StateTextBox : TextBox
{
private string _oldText;
public string oldText
{
get { return _oldText; }
}
public string oldText { get; set; }
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
_oldText = this.Text;
oldText = this.Text;
}
}

3
vCardEditor/app.config Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

View File

@@ -10,12 +10,13 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>vCardEditor</RootNamespace>
<AssemblyName>vCardEditor</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
@@ -23,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
@@ -32,6 +34,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>assests\vCard.ico</ApplicationIcon>
@@ -41,7 +44,6 @@
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
@@ -49,6 +51,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Model\FixedList.cs" />
<Compile Include="Model\ObjectCopier.cs" />
<Compile Include="Repository\ConfigRepository.cs" />
<Compile Include="Repository\ContactRepository.cs" />
<Compile Include="Repository\FileHandler.cs" />
<Compile Include="Repository\IContactRepository.cs" />
@@ -74,6 +79,8 @@
<Compile Include="Thought.vCards\vCardException.cs" />
<Compile Include="Thought.vCards\vCardFormat.cs" />
<Compile Include="Thought.vCards\vCardGender.cs" />
<Compile Include="Thought.vCards\vCardIMPP.cs" />
<Compile Include="Thought.vCards\vCardIMPPCollection.cs" />
<Compile Include="Thought.vCards\vCardNote.cs" />
<Compile Include="Thought.vCards\vCardNoteCollection.cs" />
<Compile Include="Thought.vCards\vCardPhone.cs" />
@@ -84,6 +91,8 @@
<Compile Include="Thought.vCards\vCardProperty.cs" />
<Compile Include="Thought.vCards\vCardPropertyCollection.cs" />
<Compile Include="Thought.vCards\vCardReader.cs" />
<Compile Include="Thought.vCards\vCardSocialProfile.cs" />
<Compile Include="Thought.vCards\vCardSocialProfileCollection.cs" />
<Compile Include="Thought.vCards\vCardSource.cs" />
<Compile Include="Thought.vCards\vCardSourceCollection.cs" />
<Compile Include="Thought.vCards\vCardStandardReader.cs" />
@@ -103,6 +112,12 @@
<Compile Include="View\AboutDialog.Designer.cs">
<DependentUpon>AboutDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\ConfigDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\ConfigDialog.Designer.cs">
<DependentUpon>ConfigDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\EventArgs.cs" />
<Compile Include="View\IMainView.cs" />
<Compile Include="View\MainForm.cs">
@@ -128,9 +143,13 @@
<EmbeddedResource Include="View\AboutDialog.resx">
<DependentUpon>AboutDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\ConfigDialog.resx">
<DependentUpon>ConfigDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

View File

@@ -0,0 +1,114 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thought.vCards;
using vCardEditor.Repository;
using VCFEditor.Repository;
namespace vCardEditor_Test
{
[TestClass]
public class ContactRepositoryTest
{
[TestMethod]
public void NewFileOpened_Utf8Entry_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfUtf8Entry);
var repo = Substitute.For<ContactRepository>(fileHandler);
Assert.AreEqual(repo.LoadContacts("name")[0].Name, "Oum Alaâ");
}
[TestMethod]
public void NewFileOpened_SaveDirtyCellPhone_NotNullWithNotNull_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.Contacts[0].isDirty=true;
string phone = "0011223344";
var newCard = new vCard();
newCard.Phones.Add(new vCardPhone(phone, vCardPhoneTypes.Cellular));
repo.SaveDirtyVCard(0, newCard);
var card = repo.Contacts[0].card;
Assert.AreEqual(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber, phone);
}
[TestMethod]
public void NewFileOpened_SaveDirtyCellPhone_NotNullWithNull_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.Contacts[0].isDirty = true;
repo.SaveDirtyVCard(0, new vCard());
var card = repo.Contacts[0].card;
Assert.AreEqual(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber, string.Empty);
}
[TestMethod]
public void NewFileOpened_SaveDirtyCellPhone_NullWithNotNull_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.Contacts[2].isDirty = true;
string phone = "0011223344";
var newCard = new vCard();
newCard.Phones.Add(new vCardPhone(phone, vCardPhoneTypes.Cellular));
repo.SaveDirtyVCard(2, newCard);
var card = repo.Contacts[2].card;
Assert.AreEqual(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber, phone);
}
[TestMethod]
public void NewFileOpened_SaveDirtyCellPhone_NullWithNull_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.Contacts[3].isDirty = true;
repo.SaveDirtyVCard(3, new vCard());
var card = repo.Contacts[2].card;
Assert.IsNull(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular));
}
[TestMethod]
public void NewFileOpened_v21_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfWikiv21);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("name");
repo.Contacts[0].isDirty = true;
repo.SaveDirtyVCard(0, new vCard());
//var card = repo.Contacts[2].card;
//Assert.IsNull(card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular));
}
}
}

135
vCardEditor_Test/Entries.cs Normal file
View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace vCardEditor_Test
{
public class Entries
{
public static string[] vcfOneEntry
{
get
{
string s = @"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"LABEL;QUOTED-PRINTABLE;WORK;PREF:Rue Th. Decuyper 6A=Bruxelles 1200=Belgique\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfThreeEntry
{
get
{
string s = "BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont2\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont3\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfFourEntry
{
get
{
string s = "BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean1\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont2\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont3\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont4\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfUtf8Entry
{
get
{
string s = "BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=41=6C=61=C3=A2;=4F=75=6D;;;\n" +
"FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=4F=75=6D=20=41=6C=61=C3=A2\n" +
"END:VCARD";
return s.Split('\n');
}
}
public static string[] vcfWikiv21
{
get
{
string s = "BEGIN:VCARD" +
"VERSION:2.1\n" +
"N:Gump;Forrest;;Mr.\n" +
"FN:Forrest Gump\n" +
"ORG:Bubba Gump Shrimp Co.\n" +
"TITLE:Shrimp Man\n" +
"PHOTO;GIF:http://www.example.com/dir_photos/my_photo.gif\n" +
"TEL;WORK;VOICE:(111) 555-1212\n" +
"TEL;HOME;VOICE:(404) 555-1212\n" +
"ADR;WORK;PREF:;;100 Waters Edge;Baytown;LA;30314;United States of America\n" +
"LABEL;WORK;PREF;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:100 Waters Edge=0D=\n" +
" =0ABaytown\\, LA 30314=0D=0AUnited States of America\n" +
"ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America\n" +
"LABEL;HOME;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:42 Plantation St.=0D=0A=\n" +
" Baytown, LA 30314=0D=0AUnited States of America\n" +
"EMAIL:forrestgump@example.com\n" +
"REV:20080424T195243Z\n" +
"END:VCARD";
return s.Split('\n');
}
}
}
}

View File

@@ -0,0 +1,67 @@
using vCardEditor.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace vCardEditor_Test
{
/// <summary>
///Classe de test pour FixedListTest, destinée à contenir tous
///les tests unitaires FixedListTest
///</summary>
[TestClass()]
public class FixedListTest
{
/// <summary>
///Test pour enqueue
///</summary>
[TestMethod()]
public void enqueue_one_element_test()
{
int size = 1;
FixedList target = new FixedList(size);
string elem = "test";
target.Enqueue(elem);
Assert.IsTrue( target.Size == 1);
Assert.IsTrue(target[0] == "test");
}
/// <summary>
///Test pour enqueue
///</summary>
[TestMethod()]
public void enqueue_two_elements_test()
{
int size = 1;
FixedList target = new FixedList(size);
target.Enqueue("elem1");
target.Enqueue("elem2");
Assert.IsTrue(target.Size == 1);
Assert.IsTrue(target[0] == "elem2");
Assert.IsTrue(target.Size == 1);
}
[TestMethod()]
public void enqueue_three_elements_test()
{
int size = 3;
FixedList target = new FixedList(size);
target.Enqueue("elem1"); // this one should be remove !
target.Enqueue("elem2");
target.Enqueue("elem3");
target.Enqueue("elem4");
Assert.IsTrue(target.Size == 3);
Assert.IsTrue(target[0] == "elem2");
Assert.IsTrue(target[1] == "elem3");
Assert.IsTrue(target.Size == 3);
}
}
}

View File

@@ -5,114 +5,62 @@ using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VCFEditor;
using VCFEditor.View;
using Moq;
using VCFEditor.Presenter;
using VCFEditor.Model;
using System.ComponentModel;
using VCFEditor.Repository;
using vCardEditor.Repository;
using NSubstitute;
namespace vCardEditor_Test
{
/// <summary>
///
/// </summary>
[TestClass]
public class MainPresenterTest
{
#region vCard Entries
public string[] vcfOneEntry
{
get
{
string s = @"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"LABEL;QUOTED-PRINTABLE;WORK;PREF:Rue Th. Decuyper 6A=Bruxelles 1200=Belgique\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD";
return s.Split('\n');
}
}
public string[] vcfThreeEntry
{
get
{
string s = "BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont1\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD\n" +
"BEGIN:VCARD\n" +
"VERSION:2.1\n" +
"FN:Jean Dupont3\n" +
"N:Dupont;Jean\n" +
"ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper\n" +
"TEL;CELL:+1234 56789\n" +
"EMAIL;INTERNET:jean.dupont@example.com\n" +
"END:VCARD";
return s.Split('\n');
}
}
#endregion
[TestMethod]
public void NewFileOpenedTest()
{
var handler = new Mock<IFileHandler>();
var repo = new Mock<ContactRepository>(handler.Object);
var view = new Mock<IMainView>();
handler.Setup(x => x.ReadAllLines("filename"))
.Returns(vcfOneEntry);
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa"));
var presenter = new MainPresenter(view.Object, repo.Object);
view.Raise(m => m.NewFileOpened += null, new EventArg<string>("filename"));
view.Received().DisplayContacts(Arg.Is<BindingList<Contact>>(x=>x.Count == 1));
view.Received().DisplayContacts(Arg.Is<BindingList<Contact>>(x => x[0].card.FormattedName == "Jean Dupont1"));
view.Verify(m => m.DisplayContacts(It.Is<BindingList<Contact>>(x => x.Count == 1)));
view.Verify(m => m.DisplayContacts(It.Is<BindingList<Contact>>(x => x[0].card.FormattedName == "Jean Dupont1")));
}
[TestMethod]
public void DeleteTest()
{
var handler = new Mock<IFileHandler>();
var repo = new Mock<ContactRepository>(handler.Object);
var view = new Mock<IMainView>();
handler.Setup(x => x.ReadAllLines("filename"))
.Returns(vcfThreeEntry);
var presenter = new MainPresenter(view.Object, repo.Object);
view.Raise(m => m.NewFileOpened += null, new EventArg<string>("filename"));
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa"));
//Mouse click on second row.
repo.Object.Contacts[1].isSelected = true;
repo.Contacts[1].isSelected = true;
//Delete the second one.
view.Raise(m => m.DeleteContact += null, null, null);
Assert.AreEqual(repo.Object.Contacts.Count, 2);
Assert.AreEqual(repo.Object.Contacts[1].card.FormattedName, "Jean Dupont3");
view.DeleteContact += Raise.Event();
Assert.AreEqual(repo.Contacts.Count, 2);
Assert.AreEqual(repo.Contacts[1].card.FormattedName, "Jean Dupont3");
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="4.2.0" targetFramework="net45" />
<package id="NSubstitute" version="3.1.0" targetFramework="net45" />
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net45" />
</packages>

View File

@@ -11,9 +11,10 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>vCardEditor_Test</RootNamespace>
<AssemblyName>vCardEditor_Test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -23,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -31,17 +33,35 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.2.0\lib\net45\Castle.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>bin\Debug\Moq.dll</HintPath>
<Reference Include="NSubstitute, Version=3.1.0.0, Culture=neutral, PublicKeyToken=92dd2e9066daa5ca, processorArchitecture=MSIL">
<HintPath>..\packages\NSubstitute.3.1.0\lib\net45\NSubstitute.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
@@ -49,6 +69,9 @@
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="ContactRepositoryTest.cs" />
<Compile Include="Entries.cs" />
<Compile Include="FixedListTest.cs" />
<Compile Include="MainPresenterTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@@ -58,6 +81,10 @@
<Name>vCardEditor</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.