15 Commits
0.2 ... v0.31

Author SHA1 Message Date
abdelkader
91fb7ca500 #11 corrected 2022-05-22 20:14:58 -04:00
Abdel
5c42100019 Update README.md
add contribution section
2022-02-08 10:47:32 -05:00
abdelkader
28fe4f116d handle first & lastname 2022-01-26 09:31:36 -05:00
Abdel
79412f3484 Update README.md
new readme file
2022-01-26 09:27:58 -05:00
Abdel
126fc13afd Update README.md
updated readme with a new screenshot
2022-01-26 09:27:35 -05:00
abdelkader
cb013a36f6 close #8; incremental name when backup file 2022-01-05 13:20:56 -05:00
abdelkader
a95dcafb29 Corrected some tests 2021-02-06 21:04:42 -05:00
abdelkader
a18a253696 bug fixed when deleting more than one contact
More MVP..remove winform from presenter
2021-02-06 20:40:29 -05:00
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
24 changed files with 1722 additions and 503 deletions

1
.gitignore vendored
View File

@@ -215,3 +215,4 @@ FakesAssemblies/
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
/contacts

View File

@@ -1,13 +1,40 @@
# vCard Editor
A Simple vcf file Editor.
![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/
Also, the MVP pattern from this example :
https://github.com/lennykean/NoteCards
A Simple vcf file Editor. You can export easily edit (modify, delete) entries of a vcf file with this simple tool.
The software is still in **early stage**.
## Installation
No need to install anything. Just head to the release section and download the last release version.
## Screenshots
![App Screenshot](https://user-images.githubusercontent.com/474542/151180600-cf169628-0761-49a9-a63d-05f751c6a9bb.png)
## Acknowledgements
- [Wonderful library of parsing and generating vcf format](https://github.com/drlongnecker/Thought.vCards)
- [MVP pattern from this example](https://github.com/lennykean/NoteCards)
## Release notes
#### 0.3
- Added address section.
- refactoring and bugs fixed
#### 0.2
- Updated the vCard library to https://github.com/acastroy/Thought.vCards
- Replaced Moq with nsubstitute (Test mocking library).
## Contributing
Contributions are always welcome!

View File

@@ -1,54 +1,54 @@
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)]
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
}
}
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

@@ -5,7 +5,6 @@ using Thought.vCards;
using VCFEditor.View;
using vCardEditor.View;
using VCFEditor.Repository;
using System.Windows.Forms;
using vCardEditor.Repository;
using vCardEditor.Model;
@@ -22,8 +21,8 @@ namespace VCFEditor.Presenter
_view = view;
_repository = repository;
//hook event from the view to event handler present in this presenter.
_view.NewFileOpened += NewFileOpened;
_view.BeforeOpeningNewFile += BeforeOpeningNewFile;
_view.SaveContactsSelected += SaveContacts;
_view.ChangeContactsSelected += ChangeContactSelected;
_view.DeleteContact += DeleteContact;
@@ -33,11 +32,12 @@ namespace VCFEditor.Presenter
_view.CloseForm += CloseForm;
}
void CloseForm(object sender, FormClosingEventArgs e)
void CloseForm(object sender, EventArg<bool> e)
{
if (_repository.dirty && _view.AskMessage("Exit before saving", "Exit"))
e.Cancel = true;
if (_repository.dirty && _view.AskMessage("Exit before saving?", "Exit"))
e.Data = true;
}
public void BeforeLeavingContact(object sender, EventArg<vCard> e)
{
@@ -74,20 +74,41 @@ namespace VCFEditor.Presenter
}
private void BeforeOpeningNewFile(object sender, EventArgs e)
{
if (_repository.Contacts != null && _repository.dirty)
{
if (!_view.AskMessage("Save current file before?", "Load"))
_repository.SaveContacts(_repository.fileName);
}
}
public void NewFileOpened(object sender, EventArg<string> e)
{
BeforeOpeningNewFile(sender, e);
string path = e.Data;
if (string.IsNullOrEmpty(path))
path = _view.DisplayOpenDialog();
if (!string.IsNullOrEmpty(path))
{
FixedList MRUList = ConfigRepository.Instance.Paths;
string ext = System.IO.Path.GetExtension(path);
if (ext != ".vcf")
{
_view.DisplayMessage("Only vcf extension accepted!", "Error");
return;
}
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);
}
@@ -95,6 +116,7 @@ namespace VCFEditor.Presenter
}
public void ChangeContactSelected(object sender, EventArgs e)
{
if (_view.SelectedContactIndex > -1)

View File

@@ -23,7 +23,7 @@ namespace vCardEditor
var fileHandler = new FileHandler();
var mainForm = new MainForm();
var presenter = new MainPresenter(mainForm, new ContactRepository(fileHandler));
new MainPresenter(mainForm, new ContactRepository(fileHandler));
Application.Run(mainForm);
}

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,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é.
@@ -12,7 +12,7 @@ namespace vCardEditor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
[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())));

View File

@@ -6,6 +6,7 @@ using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.Repository;
using System.Collections.Generic;
namespace VCFEditor.Repository
{
@@ -46,12 +47,7 @@ namespace VCFEditor.Repository
{
_fileHandler = fileHandler;
}
/// <summary>
/// Load the contacts from filename.
/// 1- Parse the file
/// 2-
/// </summary>
/// <param name="path"></param>
public BindingList<Contact> LoadContacts(string fileName)
{
this.fileName = fileName;
@@ -59,14 +55,15 @@ namespace VCFEditor.Repository
StringBuilder RawContent = new StringBuilder();
Contact contact = new Contact();
string[] lines = _fileHandler.ReadAllLines(fileName);
//TODO: Clean end of line from spaces..
//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")
if (lines[i].TrimEnd() == "END:VCARD")
{
contact.card = ParseRawContent(RawContent);
Contacts.Add(contact);
@@ -77,6 +74,7 @@ namespace VCFEditor.Repository
}
OriginalContactList = Contacts;
_dirty = false;
return Contacts;
}
@@ -92,7 +90,10 @@ namespace VCFEditor.Repository
//Take a copy...
if (!ConfigRepository.Instance.OverWrite)
File.Move(fileName, fileName + ".old");
{
string backupName = GetBackupName();
_fileHandler.MoveFile(fileName, backupName);
}
StringBuilder sb = new StringBuilder();
//Do not save the deleted ones...
@@ -104,6 +105,22 @@ namespace VCFEditor.Repository
_fileHandler.WriteAllText(fileName, sb.ToString());
_dirty = false;
}
private string GetBackupName()
{
int count = 0;
string backupName = fileName + ".old" + count.ToString();
while (_fileHandler.FileExist(backupName))
{
count++;
backupName = fileName + ".old" + count.ToString();
}
return backupName;
}
@@ -115,13 +132,14 @@ namespace VCFEditor.Repository
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;
_dirty = true;
}
}
@@ -185,44 +203,123 @@ namespace VCFEditor.Repository
public void SaveDirtyVCard(int index, vCard NewCard)
{
if (index > -1 && _contacts[index].isDirty)
if (index > -1 && index < _contacts.Count-1 && _contacts[index].isDirty)
{
vCard card = _contacts[index].card;
card.Title = NewCard.Title;
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;
SavePhone(NewCard, card);
SaveEmail(NewCard, card);
SaveWebUrl(NewCard, card);
_contacts[index].isDirty = false;
_dirty = 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)
{
//Inernet
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.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address,
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>

View File

@@ -8,6 +8,16 @@ namespace vCardEditor.Repository
{
public class FileHandler : IFileHandler
{
public bool FileExist(string filename)
{
return File.Exists(filename);
}
public void MoveFile(string newFilename, string oldFilename)
{
File.Move(newFilename, oldFilename);
}
public string[] ReadAllLines(string filename)
{
return File.ReadAllLines(filename);

View File

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

View File

@@ -7,6 +7,8 @@ namespace vCardEditor.Repository
{
public interface IFileHandler
{
void MoveFile(string newFilename, string oldFilename);
bool FileExist(string filename);
string[] ReadAllLines(string filename);
void WriteAllText(string fileName, string contents);
}

View File

@@ -16,7 +16,7 @@ namespace VCFEditor.View
public class EventArg<T> : EventArgs
{
// Property variable
private readonly T p_EventData;
private T p_EventData;
// Constructor
public EventArg(T data)
@@ -28,6 +28,7 @@ namespace VCFEditor.View
public T Data
{
get { return p_EventData; }
set { p_EventData = value;}
}
}
}

View File

@@ -12,19 +12,22 @@ namespace VCFEditor.View
{
#region All events
event EventHandler DeleteContact;
event EventHandler BeforeOpeningNewFile;
event EventHandler SaveContactsSelected;
event EventHandler<EventArg<string>> NewFileOpened;
event EventHandler ChangeContactsSelected;
event EventHandler<EventArg<vCard>> BeforeLeavingContact;
event EventHandler<EventArg<string>> FilterTextChanged;
event EventHandler TextBoxValueChanged;
event EventHandler<FormClosingEventArgs> CloseForm;
event EventHandler<EventArg<bool>> CloseForm;
#endregion
int SelectedContactIndex { get; }
void DisplayContacts(BindingList<Contact> contacts);
void DisplayContactDetail(vCard card, string FileName);
bool AskMessage(string msg, string caption);
void DisplayMessage(string msg, string caption);
string DisplayOpenDialog();
void UpdateMRUMenu(FixedList MRUList);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@ using VCFEditor.Model;
using Thought.vCards;
using vCardEditor.Repository;
using vCardEditor.Model;
using System.Drawing;
namespace vCardEditor.View
{
@@ -15,13 +16,14 @@ namespace vCardEditor.View
{
#region event list
public event EventHandler SaveContactsSelected;
public event EventHandler BeforeOpeningNewFile;
public event EventHandler DeleteContact;
public event EventHandler<EventArg<string>> NewFileOpened;
public event EventHandler ChangeContactsSelected;
public event EventHandler<EventArg<vCard>> BeforeLeavingContact;
public event EventHandler<EventArg<string>> FilterTextChanged;
public event EventHandler TextBoxValueChanged;
public event EventHandler<FormClosingEventArgs> CloseForm;
public event EventHandler<EventArg<bool>> CloseForm;
#endregion
ComponentResourceManager resources;
@@ -46,17 +48,14 @@ namespace vCardEditor.View
}
private void tbsOpen_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog.ShowDialog();
if (result == DialogResult.OK)
OpenNewFile(sender, openFileDialog.FileName);
if (NewFileOpened != null)
NewFileOpened(sender, new EventArg<string>(string.Empty));
}
public void DisplayContacts(BindingList<Contact> contacts)
{
if (contacts != null)
@@ -91,55 +90,28 @@ namespace vCardEditor.View
public void DisplayContactDetail(vCard card, string FileName)
{
if (card == null)
throw new ArgumentException("card");
throw new ArgumentException("card must be valid!");
//set the title with the filename.
this.Text = string.Format("{0} - vCard Editor", FileName);
gbContactDetail.Enabled = true;
gbNameList.Enabled = true;
//Formatted Name
SetSummaryValue(firstNameValue, card.GivenName);
SetSummaryValue(lastNameValue, card.FamilyName);
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)
{
var photo = card.Photos[0];
try
{
// Get the bytes of the photo if it has
// not already been loaded.
if (!photo.IsLoaded)
photo.Fetch();
PhotoBox.Image = photo.GetBitmap();
}
catch
{
//Empty image icon instead.
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
}
}
else
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
SetAddressesValues(card.DeliveryAddresses);
SetPhotoValue(card.Photos);
}
#region helper methods to populate textboxes.
private void SetSummaryValue(StateTextBox valueLabel, string value)
{
if (valueLabel == null)
@@ -171,6 +143,94 @@ namespace vCardEditor.View
if (webSite != null)
SetSummaryValue(valueLabel, webSite.Url.ToString());
}
void SetPhotoValue(vCardPhotoCollection photos)
{
if (photos.Any())
{
var photo = photos[0];
try
{
// Get the bytes of the photo if it has
// not already been loaded.
if (!photo.IsLoaded)
photo.Fetch();
PhotoBox.Image = photo.GetBitmap();
}
catch
{
//Empty image icon instead.
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
}
}
else
PhotoBox.Image = ((System.Drawing.Image)(resources.GetObject("PhotoBox.Image")));
}
private void SetAddressesValues(vCardDeliveryAddressCollection addresses)
{
ClearAddressTextFields();
if (addresses.Any())
{
var HomeAddress = addresses.Where(x => x.IsHome).FirstOrDefault();
if (HomeAddress != null)
{
HomeAddressValue.Text = HomeAddress.Street;
HomeCityValue.Text = HomeAddress.City;
HomeZipValue.Text = HomeAddress.PostalCode;
HomeStateValue.Text = HomeAddress.Region;
HomeCountryValue.Text = HomeAddress.Country;
}
var WorkAddress = addresses.Where(x => x.IsWork).FirstOrDefault();
if (WorkAddress != null)
{
WorkAddressValue.Text = WorkAddress.Street;
WorkCityValue.Text = WorkAddress.City;
WorkZipValue.Text = WorkAddress.PostalCode;
WorkStateValue.Text = WorkAddress.Region;
WorkCountryValue.Text = WorkAddress.Country;
}
var PostalAddress = addresses.Where(x => x.IsPostal).FirstOrDefault();
if (PostalAddress != null)
{
PostalAddressValue.Text = PostalAddress.Street;
PostalAddressValue.Text = PostalAddress.Street;
PostalCityValue.Text = PostalAddress.City;
PostalZipValue.Text = PostalAddress.PostalCode;
PostalStateValue.Text = PostalAddress.Region;
PostalCountryValue.Text = PostalAddress.Country;
}
}
}
private void ClearAddressTextFields()
{
HomeAddressValue.Clear();
HomePOBoxValue.Clear();
HomeCityValue.Clear();
HomeZipValue.Clear();
HomeStateValue.Clear();
HomeCountryValue.Clear();
WorkAddressValue.Clear();
WorkPOBoxValue.Clear();
WorkCityValue.Clear();
WorkZipValue.Clear();
WorkStateValue.Clear();
WorkCountryValue.Clear();
PostalAddressValue.Clear();
PostalPOBoxValue.Clear();
PostalCityValue.Clear();
PostalZipValue.Clear();
PostalStateValue.Clear();
PostalCountryValue.Clear();
}
#endregion
private void tbsDelete_Click(object sender, EventArgs e)
@@ -213,26 +273,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,34 +323,17 @@ namespace vCardEditor.View
return;
}
OpenNewFile(sender, FileList[0]);
NewFileOpened(sender, new EventArg<string>(FileList[0]));
}
#endregion
/// <summary>
/// Open vcf file.
/// </summary>
/// <param name="sender"></param>
/// <param name="file"></param>
private void OpenNewFile(object sender, string file)
{
string ext = System.IO.Path.GetExtension(file);
//TODO: Should parse invalid content file...
if (ext != ".vcf")
{
MessageBox.Show("Only vcf extension accepted!");
return;
}
if (NewFileOpened != null)
NewFileOpened(sender, new EventArg<string>(file));
}
private void BuildMRUMenu()
{
recentFilesMenuItem.DropDownItemClicked += (s, e) => OpenNewFile(s, e.ClickedItem.Text);
recentFilesMenuItem.DropDownItemClicked += (s, e) => NewFileOpened(s, new EventArg<string>(e.ClickedItem.Text));
//Update the MRU Menu entries..
UpdateMRUMenu(ConfigRepository.Instance.Paths);
@@ -314,18 +353,15 @@ namespace vCardEditor.View
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
var evt = new EventArg<bool>(false);
if (CloseForm != null)
CloseForm(sender, e);
CloseForm(sender,evt);
e.Cancel = evt.Data;
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
@@ -338,12 +374,35 @@ namespace vCardEditor.View
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();
}
public void DisplayMessage(string msg, string caption)
{
MessageBox.Show(msg, caption);
}
public string DisplayOpenDialog()
{
string filename = string.Empty;
DialogResult result = openFileDialog.ShowDialog();
if (result == DialogResult.OK)
filename = openFileDialog.FileName;
return filename;
}
private void rbChangeAddress(object sender, EventArgs e)
{
}
}
}

View File

@@ -112,15 +112,15 @@
<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>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.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>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="miOpen.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -139,16 +139,16 @@
</data>
<data name="miQuit.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAH9SURBVDhPpZLdS1NhHMcfCMFuvOj9wrQ5S5a62TKdKSZpu5CVowbzjc1srZh6nDp3EF8YQ8XI
G0EEQWqCaHgT1kCJ5aYDmQt1IAYhSN11lX/Ct9+ziXrmEQS/8DkP/J7n++FwnsPOnR+iFmfloCIN39ga
NSDkfbKXcoHpOTTWEWoim7hBXDxVEHXfQ8h1H3+/iAh/6AieJjCMXgKbZCcl7912LDs1+DXyCP+C7zDR
rAnSWCoYZzPxspwg4ipAQFDjp1eHP76XeFN0hR86Egyydl4cjg0mBMmsdWrwrTUf255i/PbZpIJeJvJD
3i0PXNEOOCOt6NsQ4Y0NQFh/C9ZFgrAzH4uOXMT6C7E72SgVUNmzOQD90mOU+otQtVQOQ0AP84oRQtSe
EKy05cFvV2GjR4udMZPsGzSEzKgJVMMSroV9zRov98e6E4Jlx118fpWDiEuDCXc9ROsz2W/gXG9JFJIZ
6bJh3pKN1fY8zAkVaK4ukQqO3wIVKPxxCFu03cZsnQLfHSqsiqV4/eDySQH9B1VDafKCr01K+EwZ4KKA
oIVDl3SNBwJ+jlZJOS7g+fg8fXvBooDfpkJbyVU+5WUVoSQyCC5JIeQFU8b0rE+1mfsLViU6y67xaSVR
Tjwk7hCpRDyyAp7pFzeN83W30FNxnU/NxFNCwfeORyoA+w+MrWMTrGDAJwAAAABJRU5ErkJggg==
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAf1JREFUOE+l
kt1LU2Ecxx8IwW686P3CtDlLlrrZMp0pJmm7kJWjBvONzWytmHqcOncQXxhDxcgbQQRBaoJoeBPWQInl
pgOZC3UgBiFI3XWVf8K337OJeuYRBL/wOQ/8nuf74XCew86dH6IWZ+WgIg3f2Bo1IOR9spdygek5NNYR
aiKbuEFcPFUQdd9DyHUff7+ICH/oCJ4mMIxeAptkJyXv3XYsOzX4NfII/4LvMNGsCdJYKhhnM/GynCDi
KkBAUOOnV4c/vpd4U3SFHzoSDLJ2XhyODSYEyax1avCtNR/bnmL89tmkgl4m8kPeLQ9c0Q44I63o2xDh
jQ1AWH8L1kWCsDMfi45cxPoLsTvZKBVQ2bM5AP3SY5T6i1C1VA5DQA/zihFC1J4QrLTlwW9XYaNHi50x
k+wbNITMqAlUwxKuhX3NGi/3x7oTgmXHXXx+lYOIS4MJdz1E6zPZb+Bcb0kUkhnpsmHeko3V9jzMCRVo
ri6RCo7fAhUo/HEIW7TdxmydAt8dKqyKpXj94PJJAf0HVUNp8oKvTUr4TBngooCghUOXdI0HAn6OVkk5
LuD5+Dx9e8GigN+mQlvJVT7lZRWhJDIILkkh5AVTxvSsT7WZ+wtWJTrLrvFpJVFOPCTuEKlEPLICnukX
N43zdbfQU3GdT83EU0LB945HKgD7D4ytYxOsYMAnAAAAAElFTkSuQmCC
</value>
</data>
<data name="miAbout.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -166,10 +166,10 @@
E9ew//AVxE8OItv/9O/Cf0ck8gud2vKswuxNZgAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>132, 17</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>248, 17</value>
</metadata>
<data name="tbsOpen.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -238,60 +238,60 @@
E9ew//AVxE8OItv/9O/Cf0ck8gud2vKswuxNZgAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>353, 17</value>
</metadata>
<data name="PhotoBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAACHUExURf///y4uLi8vLykpKUBAQEVFRUtLS0REREpKSj09PUFBQd/f3ygoKDk5OU5OTiAgIAAA
ADQ0NBwcHBkZGff39+zs7BMTE9nZ2QkJCWlpaebm5qenp/Pz88LCws/Pz4eHh3h4eFhYWJKSkp+fn8XF
xWdnZ6+vr3BwcH5+frm5uY2NjV5eXqGhob8kg48AAARnSURBVGhD7ZiLkqI6EEAHoqNAmPAGdXzg23H/
//u2u9OiIM4Okq3aW9dTNVVj0vQh5EHI24sXL178T/nMZ8dyOCyP+zzhIvOk85WrIkKNjttPLjbMaSdj
JYQFCKFi67DlCpMkK6VQYRPwj1RyyXXm8MpCkCIkyCSC85SrDeGVMUq0Q4Oi7JBygBGSHVgwt19BJis+
cIQRVgW1xPedChLZVrHmEAPMC5JA8oHLDNCEnmDBQb1JS6lbMnBHoyExGqEIW6TOpibqXtloAQkIxgSa
QAQeW5w4rCfpRJFFS94JEmmPWplZDrbxxUKOD4BM7LGFmd5ZgwaemG4KShDdIPSE2S8O7EUyFrpfbiQI
ekYujANZmhgEXgGNubdUHugdE0vBqeBHdqfR3eP7RqbOV0T9f9sxGuqeEfRONuPQPhykw8+sVQO9o44c
2ofSujyzOw0ParHj0D6Mw+ucaQIaeGpWyaF9GJDmMv1r4NQBjf3BoX1wQ+waXMs4+ZWLxkRrPvihtaI1
Zw7tw9n+XuM61oRD+3AQ9NBaPfg+GDhGdjhrxW+aVvCtE+85tA/z7I8aE4uNR6154MGXtW+ZWDo/h+Hg
YXPAMrDN7AaWEjWtHtp5qA0H9mMrHPK0AY3xQzMv6ekZJqjb6sH9mj0xtMHdwBpd7QPrDEBj4m2DLFx4
sbWJoNDxxx6H9eZLwI6zFXinmRkASOqH7R7HCUcGP0L38QONrwxtbQn4IsTPgQZQpJZGv6jTiXXngQJh
aP9ckZ9hGDSRE2Oj7IL3gc+thjL9hYtMDzGMtythfDT6fVtxKi2LPg1h32xZ5zkXGyedHcaWBOz31f4v
naUQn/l8ttnMtvnflLz45/C+nYXbWf+lIJnOV34w4F9tJHYQhMtFr5m6WLpZpmTwzWr/KxBSZXE5e3rh
Sb9CcEgplPMwx8KSApBRvHtyg5NOMkoBxIcH0zE9RxwiI/s5zzG4WIQs2l9f6argCCDKnhkL86sFPa3H
c8fiJkZkz3y1jRVdq8+D0XP33JIlWjCAQsDTfcu2j/FCnYM82a7xTPJzXFkAiFFl1+GWTKBvOQGC9yo3
06qHkuk6whvhagRvpWtzFo6+Uzx6xsNtutlsuJ7naZKk+Xw9omF4iaCYb0bkI2YZ3eg1B3rwyP59cjjs
xgKP8Wsa8kiR8/U/IznGtxp9r4CUSkWRUjzAbiIwRoii2+7QG6haispzSz2CYjoefy9i2UgCPxsiLOFK
An8rq9Mu9FRAFr5cg0luPfT7LkQEnYb0umjm0J5KpH9xFYPV3U4KYUVsZqG8CCsArrmARUGnmePgCHig
ucI1DBVlXU4KE9UcAQjluYGLK7As7nJMlAaoqSeiggZcReiSqMsq7QW6AziDhkpqcAVDReqdU/yEPOBp
QZd2Qbmc4icsuDWdgW0Dp/gJT2ss9d1mq8k2wM8L2NPAmqv/HnCpwkgi6vLQtsHNJLyi6nBpDdXlsDjJ
vTbyOlxa5+ld4YsXL178Z3h7+w1PM1gbWuVRlwAAAABJRU5ErkJggg==
iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAAABGdBTUEAALGPC/xhBQAAAIdQTFRF////
Li4uLy8vKSkpQEBARUVFS0tLRERESkpKPT09QUFB39/fKCgoOTk5Tk5OICAgAAAANDQ0HBwcGRkZ9/f3
7OzsExMT2dnZCQkJaWlp5ubmp6en8/PzwsLCz8/Ph4eHeHh4WFhYkpKSn5+fxcXFZ2dnr6+vcHBwfn5+
ubm5jY2NXl5eoaGhvySDjwAABGdJREFUaEPtmIuSojoQQAeio0CY8AZ1fODbcf//+7a706Igzg6Srdpb
11M1VWPS9CHkQcjbixcvXvxP+cxnx3I4LI/7POEi86TzlasiQo2O208uNsxpJ2MlhAUIoWLrsOUKkyQr
pVBhE/CPVHLJdebwykKQIiTIJILzlKsN4ZUxSrRDg6LskHKAEZIdWDC3X0EmKz5whBFWBbXE950KEtlW
seYQA8wLkkDygcsM0ISeYMFBvUlLqVsycEejITEaoQhbpM6mJupe2WgBCQjGBJpABB5bnDisJ+lEkUVL
3gkSaY9amVkOtvHFQo4PgEzssYWZ3lmDBp6YbgpKEN0g9ITZLw7sRTIWul9uJAh6Ri6MA1maGAReAY25
t1Qe6B0TS8Gp4Ed2p9Hd4/tGps5XRP1/2zEa6p4R9E4249A+HKTDz6xVA72jjhzah9K6PLM7DQ9qsePQ
PozD65xpAhp4albJoX0YkOYy/Wvg1AGN/cGhfXBD7Bpcyzj5lYvGRGs++KG1ojVnDu3D2f5e4zrWhEP7
cBD00Fo9+D4YOEZ2OGvFb5pW8K0T7zm0D/PsjxoTi41HrXngwZe1b5lYOj+H4eBhc8AysM3sBpYSNa0e
2nmoDQf2Yysc8rQBjfFDMy/p6RkmqNvqwf2aPTG0wd3AGl3tA+sMQGPibYMsXHixtYmg0PHHHof15kvA
jrMVeKeZGQBI6oftHscJRwY/QvfxA42vDG1tCfgixM+BBlCklka/qNOJdeeBAmFo/1yRn2EYNJETY6Ps
gveBz62GMv2Fi0wPMYy3K2F8NPp9W3EqLYs+DWHfbFnnORcbJ50dxpYE7PfV/i+dpRCf+Xy22cy2+d+U
vPjn8L6dhdtZ/6Ugmc5XfjDgX20kdhCEy0WvmbpYulmmZPDNav8rEFJlcTl7euFJv0JwSCmU8zDHwpIC
kFG8e3KDk04ySgHEhwfTMT1HHCIj+znPMbhYhCzaX1/pquAIIMqeGQvzqwU9rcdzx+ImRmTPfLWNFV2r
z4PRc/fckiVaMIBCwNN9y7aP8UKdgzzZrvFM8nNcWQCIUWXX4ZZMoG85AYL3KjfTqoeS6TrCG+FqBG+l
a3MWjr5TPHrGw2262Wy4nudpkqT5fD2iYXiJoJhvRuQjZhnd6DUHevDI/n1yOOzGAo/xaxrySJHz9T8j
Oca3Gn2vgJRKRZFSPMBuIjBGiKLb7tAbqFqKynNLPYJiOh5/L2LZSAI/GyIs4UoCfyur0y70VEAWvlyD
SW499PsuRASdhvS6aObQnkqkf3EVg9XdTgphRWxmobwIKwCuuYBFQaeZ4+AIeKC5wjUMFWVdTgoT1RwB
COW5gYsrsCzuckyUBqipJ6KCBlxF6JKoyyrtBboDOIOGSmpwBUNF6p1T/IQ84GlBl3ZBuZziJyy4NZ2B
bQOn+AlPayz13WaryTbAzwvY08Caq/8ecKnCSCLq8tC2wc0kvKLqcGkN1eWwOMm9NvI6XFrn6V3hixcv
XvxneHv7DU8zWBta5VGXAAAAAElFTkSuQmCC
</value>
</data>
<metadata name="bsContacts.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="bsContacts.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>486, 17</value>
</metadata>
<data name="btnClearFilter.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADrwAAA68AZW8ckkAAAJ4SURBVDhPbZNfSFNxFMdPrdYf18TKNEEo//XUTEqb9kcC
NXqTRASH5Z9AVvjQpkv7Y2qUZOq0qHSrUFrDxiJS6GEg6EPP5SDouYcC96DTuT8O+XbO3TWSduDDOfd7
zvdw7+/eS//GGNFpB9GEZFX6G6yfYEZeER1Tpa0xTtQ6oUvBj24bJMu12hJz/4f8HPgtN/7rKbFpXhwf
xsb8DALOEbgzD0GMgjf3CCIzbmzMTSPgsG9dophT9mLxWT/iHifWXw8h/t6BsOcNvHk5CuEpJ+Lul1h3
Digzi6P9EI+TqE6ee+G3pRWx4R7E7L2IDXYjNnSfF41i7e2YgtSiKT2Z4fqn+arcxTyNErV5M9Kx0m5G
tNuKaK8tQd8tRB90JZBatJ4OnrEos+KxE12Rp9g1SPTcm34AK+ZGRKzXEbG1Jcdqxi9TDWRWPOzVyoJt
zJ4nRC/c+3QI1NcibG5JSsBUiwmtFn1EXeJRvewkMvI612xRIcI2C0KNDQg11G+FtXBnO2YNx8Hz/HJU
s3w0fBiT3+tqEbl3B2vXWrBaXZ0U6UXu3sbsqZNygJPKByeF31iKUFMTVi/XYKXyYoKKKqZShWtVD9Wb
eLYZ/rIzyhI5CddCbgGCxnMIlp5HsKyc4Ww8i4XcPAWpFU16MsPXc4ez8JSogx4SlQ8RffySkYVlQzGW
C0s4l+Bb9lE8IvosSC1aolcMX9pBsMdVQZQqx6Ax8Q8yQDTl06dhKd+Ar5nZeEw0bSW6JEgt2lKBAT79
fvCsm316ZrsskNAwqdJ4t2Mn+JV+6iSqUnWN1KJ5tLuTmjdDhJRmoiLOMiDmzZBaf5PoAmcdo5qJ/gBC
SbPSrCTkJAAAAABJRU5ErkJggg==
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAnhJREFUOE9tk19IU3EUx0+t1h/XxMo0QSj/9dRMSpv2RwI1epNEBIfln0BW+NCm
S/tjapRk6rSodKtQWsPGIlLoYSDoQ8/lIOi5hwL3oNO5Pw75ds7dNZJ24MM593vO93Dv795L/8YY0WkH
0YRkVfobrJ9gRl4RHVOlrTFO1DqhS8GPbhsky7XaEnP/h/wc+C03/uspsWleHB/GxvwMAs4RuDMPQYyC
N/cIIjNubMxNI+Cwb12imFP2YvFZP+IeJ9ZfDyH+3oGw5w28eTkK4Skn4u6XWHcOKDOLo/0Qj5OoTp57
4belFbHhHsTsvYgNdiM2dJ8XjWLt7ZiC1KIpPZnh+qf5qtzFPI0StXkz0rHSbka024pory1B3y1EH3Ql
kFq0ng6esSiz4rETXZGn2DVI9NybfgAr5kZErNcRsbUlx2rGL1MNZFY87NXKgm3MnidEL9z7dAjU1yJs
bklKwFSLCa0WfURd4lG97CQy8jrXbFEhwjYLQo0NCDXUb4W1cGc7Zg3HwfP8clSzfDR8GJPf62oRuXcH
a9dasFpdnRTpRe7exuypk3KAk8oHJ4XfWIpQUxNWL9dgpfJigooqplKFa1UP1Zt4thn+sjPKEjkJ10Ju
AYLGcwiWnkewrJzhbDyLhdw8BakVTXoyw9dzh7PwlKiDHhKVDxF9/JKRhWVDMZYLSziX4Fv2UTwi+ixI
LVqiVwxf2kGwx1VBlCrHoDHxDzJANOXTp2Ep34Cvmdl4TDRtJbokSC3aUoEBPv1+8KybfXpmuyyQ0DCp
0ni3Yyf4lX7qJKpSdY3Uonm0u5OaN0OElGaiIs4yIObNkFp/k+gCZx2jmon+AEJJs9KsJOQkAAAAAElF
TkSuQmCC
</value>
</data>
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="Column1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Column2.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="Column2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

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>

View File

@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>vCardEditor</RootNamespace>
<AssemblyName>vCardEditor</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -24,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>
@@ -33,6 +34,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>assests\vCard.ico</ApplicationIcon>
@@ -147,6 +149,7 @@
<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');
}
}
}
}

Binary file not shown.

View File

@@ -5,114 +5,136 @@ 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
[TestMethod]
public void NewFileOpened_OpenInvalidExtension_Test()
{
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');
}
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"));
view.Received().DisplayMessage(Arg.Any<string>(), Arg.Any<string>());
}
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()
public void NewFileOpened_OpenNewFile_Test()
{
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.vcf"));
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 NewFileOpened_OpenNewOneWhileAnotherOneIsDirty_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.AskMessage(Arg.Any<string>(), Arg.Any<string>()).Returns(true);
var presenter = new MainPresenter(view, repo);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
repo.Contacts[1].isDirty = true;
view.NewFileOpened += Raise.EventWith(new EventArg<string>("bbb.vcf"));
view.Received().AskMessage(Arg.Any<string>(), Arg.Any<string>());
}
[TestMethod]
public void SaveFile_FirstTime()
{
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.vcf"));
view.SaveContactsSelected += Raise.Event();
fileHandler.Received().MoveFile("aaa.vcf", "aaa.vcf.old0");
}
[TestMethod]
public void SaveFile_ExistAlready()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfThreeEntry);
fileHandler.FileExist("aaa.vcf.old0").Returns(true);
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.vcf"));
view.SaveContactsSelected += Raise.Event();
fileHandler.Received().MoveFile("aaa.vcf", "aaa.vcf.old1");
}
[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.vcf"));
//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,13 +33,21 @@
<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">
<HintPath>Lib\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>
@@ -45,6 +55,10 @@
<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" />
@@ -55,6 +69,8 @@
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="ContactRepositoryTest.cs" />
<Compile Include="Entries.cs" />
<Compile Include="FixedListTest.cs" />
<Compile Include="MainPresenterTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -65,8 +81,9 @@
<Name>vCardEditor</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="Lib\" />
<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.