33 Commits

Author SHA1 Message Date
Abdel
05d6580ba6 Merge pull request #56 from JDM170/fixes
Update
2025-06-18 13:47:15 -04:00
a60ae3c5a2 Update
* Updated DisplaySaveDialog
* Fixed a bug in SaveContactsHandler, when an exception was thrown when canceling file saving
* The window title displays "New file" instead of empty when creating a new file
* Commented out the code that saves a website with the "work" type (the program does not work with this type of website)
* Explicitly specified data types for some variables
* Minor code formatting

Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-06-18 20:45:44 +07:00
abdelkader
9c66157599 fixed test 2025-06-12 13:28:37 -04:00
Abdel
a67e88bb22 Merge pull request #53 from JDM170/update_readme
Update README
2025-06-10 13:23:33 -04:00
7d029293b0 Update README.md
Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-06-05 17:39:00 +07:00
abdelkader
c9b324a8c6 Merge branch 'master' of https://github.com/abdelkader/vCardEditor 2025-06-04 22:29:47 -04:00
Abdel
8457b57dae Merge pull request #52 from JDM170/fix_dialogs
Dialog fixes
2025-06-04 22:28:50 -04:00
Abdel
1b4d8373f2 Merge pull request #51 from JDM170/code_fixes
Corrections and additions in code
2025-06-04 22:27:54 -04:00
abdelkader
9c562b3f7e added test 2025-06-04 22:19:22 -04:00
a37ceee7f2 Update
* Aligning buttons on the About dialog and removing an extra line in tableLayoutPanel
* Removed unnecessary cancel button

Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-06-04 18:41:58 +07:00
8392f0c273 Update
* Added question when deleting data from the Extras tab
* ReplaceControls function merged with RemoveControl in ExtendedPanel
* Fixed strange logic of working with AskMessage
* Removed extra lines and spaces (again:D)

Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-06-04 17:16:26 +07:00
abdelkader
76398ae2c4 Added test and refactored the localization 2025-06-03 22:09:37 -04:00
abdelkader
dc47c59dc9 i18n draft 2025-06-02 21:37:39 -04:00
Abdel
1272d93ae9 Merge pull request #50 from JDM170/delete_bug_2
Fixed bug when deleting a number or site was not saved (separate signal)
2025-06-02 15:19:58 -04:00
892bf14a25 Fixed bug when deleting a number or site was not saved (separate signal)
Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-05-31 20:26:43 +07:00
abdelkader
0f8a6387e9 Merge branch 'master' of https://github.com/abdelkader/vCardEditor 2025-05-30 14:24:15 -04:00
abdelkader
313d70ae05 fixed merge 2025-05-30 14:23:51 -04:00
Abdel
5d8fd20541 Merge pull request #46 from JDM170/issue_40
Added a dialog box with a question about deleting contacts
2025-05-30 14:17:58 -04:00
26dfe4c357 Update
* Fixed indents, removed extra lines and spaces
* Partially removed var statement declaration (proper variable declaration)
* Sorted and removed unnecessary usings
* Correction of typos

Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-05-31 00:09:41 +07:00
75f6c55cbc Added a dialog box with a question about deleting contacts
Closes abdelkader/vCardEditor#40

Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-05-30 12:15:40 +07:00
abdelkader
a7c66075a1 changed version number 2025-05-29 08:51:27 -04:00
Abdel
c4a29b678f Merge pull request #45 from JDM170/fix_indexoutofrange_exception
Fixed IndexOutOfRange exception when trying to search
2025-05-29 08:47:20 -04:00
14efe79576 Fixed IndexOutOfRange exception when trying to search
Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
2025-05-29 10:37:40 +07:00
Abdel
66a77f3b98 Merge pull request #42 from JDM170/fix_work_number
Fixed adding a work number via extended panel
2025-05-28 15:12:09 -04:00
5f33b3adaf fixed adding a work number via extended panel 2024-07-30 15:22:20 +07:00
abdelkader
90dce429bd bug fixed 2024-04-04 12:45:14 -04:00
abdelkader
b17fce8dde 2nd draft for loading folder 2024-04-04 12:42:08 -04:00
abdelkader
afe52e2b18 draft for opening multiple vcard files 2024-04-02 22:45:32 -04:00
abdelkader
c89d9a197c fixed bug 2024-04-02 13:14:58 -04:00
abdelkader
6b57814c5b added a test for SaveSplittedFile 2024-04-02 12:45:31 -04:00
abdelkader
2023043889 draft for saving split files 2024-04-02 12:31:33 -04:00
abdelkader
4401f13fb4 allow to create a empty vcard file 2024-03-30 19:12:35 -04:00
Abdel
c9b9dfb623 Update Releases.txt 2024-03-28 18:53:42 -04:00
45 changed files with 1373 additions and 527 deletions

View File

@@ -1,30 +1,23 @@
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/B0B2KV8WP)
<a href="https://github.com/abdelkader/vCardEditor/releases/latest/download/vCardEditor.exe"><img src="https://camo.githubusercontent.com/d83fa798b621f1e112646fcc4aa74fff1ff6a8b22f5fc1da5ed8f79ddb4a51cb/68747470733a2f2f62616467656e2e6e65742f6769746875622f72656c656173652f4e61657265656e2f5374726170646f776e2e6a73" alt="Latest release" data-canonical-src="https://badgen.net/github/release/Naereen/Strapdown.js" style="max-width: 100%;"></a>
<a href="https://github.com/abdelkader/vCardEditor/releases/latest/download/vCardEditor.exe"><img src="https://badgen.net/github/release/Naereen/Strapdown.js" alt="Latest release" style="max-width: 100%;"></a>
## vCard Editor
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**.
<p align="center"><img src="https://user-images.githubusercontent.com/169070/236289228-106c1489-e01d-400c-968e-92d3e2be74ab.png" width="800"></p>
## ✅ Features
- [x] No need to install anything. Just head to the release section and download the last release version.
- [x] Add/Export images
## 📚 Tech Stack
- 🧰 [Wonderful library of parsing and generating vcf format](https://github.com/drlongnecker/Thought.vCards)
- 📖 [MVP pattern from this example](https://github.com/lennykean/NoteCards)
- 🧰 [SortableBindingList](http://timvw.be/2008/08/02/presenting-the-sortablebindinglistt-take-two/)
- 🧰 [Custom TabControl](https://github.com/r-aghaei/TabControlWithCloseButtonAndAddButton)
- 🧰 [QRCoder](https://github.com/codebude/QRCoder)
- 🧰 [Wonderful library of parsing and generating vcf format](https://github.com/drlongnecker/Thought.vCards)
- 📖 [MVP pattern from this example](https://github.com/lennykean/NoteCards)
- 🧰 [SortableBindingList](http://timvw.be/2008/08/02/presenting-the-sortablebindinglistt-take-two/)
- 🧰 [Custom TabControl](https://github.com/r-aghaei/TabControlWithCloseButtonAndAddButton)
- 🧰 [QRCoder](https://github.com/codebude/QRCoder)
## 📑 Release notes
Check release text file for history.
@@ -32,8 +25,4 @@ Check release text file for history.
## 👷 Contributing and help
Contributions are always welcome! Check ths projet or ths issue page for ideas.
- 📝 [**Report a bug**](https://github.com/abdelkader/vCardEditor/issues)
- 🙋‍♀️ [**Request a feature**](https://github.com/abdelkader/vCardEditor/discussions)
- 🙋‍ [**Request a feature**](https://github.com/abdelkader/vCardEditor/discussions)

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace vCardEditor
{
public interface ILocalizationProvider
{
string this[string key] { get; }
void SetLanguage(string langCode);
string CurrentLanguage { get; }
IReadOnlyDictionary<string, string> CurrentMessages { get; }
IEnumerable<string> AvailableLanguages { get; }
IEnumerable<string> AvailableLanguageNames { get; }
}
}

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.Linq;
using vCardEditor.Libs.TinyJson;
namespace vCardEditor
{
public class JsonLocalizationProvider : ILocalizationProvider
{
private readonly LocalizationFile _localization;
private string _currentLanguage;
public JsonLocalizationProvider(LocalizationFile localization, string defaultLanguage = "en")
{
_localization = localization;
_currentLanguage = defaultLanguage;
}
public void SetLanguage(string langCode)
{
if (_localization.languages.ContainsKey(langCode))
_currentLanguage = langCode;
}
public string this[string key]
{
get
{
if (_localization.languages.TryGetValue(_currentLanguage, out LanguageData lang))
{
if (lang.messages.TryGetValue(key, out string value))
return value;
}
if (_localization.languages.TryGetValue("en", out LanguageData fallbackLang))
{
if (fallbackLang.messages.TryGetValue(key, out string fallbackMsg))
return fallbackMsg;
}
return $"!{key}!";
}
}
public IReadOnlyDictionary<string, string> CurrentMessages =>
_localization.languages.TryGetValue(_currentLanguage, out LanguageData lang)
? lang.messages
: new Dictionary<string, string>();
public IEnumerable<string> AvailableLanguages => _localization.languages.Keys;
public IEnumerable<string> AvailableLanguageNames => _localization.languages?.Values != null
? _localization.languages.Values.Select(l => l?.name).Where(n => !string.IsNullOrEmpty(n))
: new List<string>();
public string CurrentLanguage => _currentLanguage;
}
}

View File

@@ -0,0 +1,7 @@
namespace vCardEditor.Libs.TinyJson
{
public interface IParser
{
T Deserialize<T>(string json);
}
}

View File

@@ -0,0 +1,377 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
namespace TinyJson
{
// Really simple JSON parser in ~300 lines
// - Attempts to parse JSON files with minimal GC allocation
// - Nice and simple "[1,2,3]".FromJson<List<int>>() API
// - Classes and structs can be parsed too!
// class Foo { public int Value; }
// "{\"Value\":10}".FromJson<Foo>()
// - Can parse JSON without type information into Dictionary<string,object> and List<object> e.g.
// "[1,2,3]".FromJson<object>().GetType() == typeof(List<object>)
// "{\"Value\":10}".FromJson<object>().GetType() == typeof(Dictionary<string,object>)
// - No JIT Emit support to support AOT compilation on iOS
// - Attempts are made to NOT throw an exception if the JSON is corrupted or invalid: returns null instead.
// - Only public fields and property setters on classes/structs will be written to
//
// Limitations:
// - No JIT Emit support to parse structures quickly
// - Limited to parsing <2GB JSON files (due to int.MaxValue)
// - Parsing of abstract classes or interfaces is NOT supported and will throw an exception.
public static class JSONParser
{
[ThreadStatic] static Stack<List<string>> splitArrayPool;
[ThreadStatic] static StringBuilder stringBuilder;
[ThreadStatic] static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfoCache;
[ThreadStatic] static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyInfoCache;
public static T FromJson<T>(this string json)
{
// Initialize, if needed, the ThreadStatic variables
if (propertyInfoCache == null) propertyInfoCache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
if (fieldInfoCache == null) fieldInfoCache = new Dictionary<Type, Dictionary<string, FieldInfo>>();
if (stringBuilder == null) stringBuilder = new StringBuilder();
if (splitArrayPool == null) splitArrayPool = new Stack<List<string>>();
//Remove all whitespace not within strings to make parsing simpler
stringBuilder.Length = 0;
for (int i = 0; i < json.Length; i++)
{
char c = json[i];
if (c == '"')
{
i = AppendUntilStringEnd(true, i, json);
continue;
}
if (char.IsWhiteSpace(c))
continue;
stringBuilder.Append(c);
}
//Parse the thing!
return (T)ParseValue(typeof(T), stringBuilder.ToString());
}
static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
{
stringBuilder.Append(json[startIdx]);
for (int i = startIdx + 1; i < json.Length; i++)
{
if (json[i] == '\\')
{
if (appendEscapeCharacter)
stringBuilder.Append(json[i]);
stringBuilder.Append(json[i + 1]);
i++;//Skip next character as it is escaped
}
else if (json[i] == '"')
{
stringBuilder.Append(json[i]);
return i;
}
else
stringBuilder.Append(json[i]);
}
return json.Length - 1;
}
//Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings
static List<string> Split(string json)
{
List<string> splitArray = splitArrayPool.Count > 0 ? splitArrayPool.Pop() : new List<string>();
splitArray.Clear();
if (json.Length == 2)
return splitArray;
int parseDepth = 0;
stringBuilder.Length = 0;
for (int i = 1; i < json.Length - 1; i++)
{
switch (json[i])
{
case '[':
case '{':
parseDepth++;
break;
case ']':
case '}':
parseDepth--;
break;
case '"':
i = AppendUntilStringEnd(true, i, json);
continue;
case ',':
case ':':
if (parseDepth == 0)
{
splitArray.Add(stringBuilder.ToString());
stringBuilder.Length = 0;
continue;
}
break;
}
stringBuilder.Append(json[i]);
}
splitArray.Add(stringBuilder.ToString());
return splitArray;
}
internal static object ParseValue(Type type, string json)
{
if (type == typeof(string))
{
if (json.Length <= 2)
return string.Empty;
StringBuilder parseStringBuilder = new StringBuilder(json.Length);
for (int i = 1; i < json.Length - 1; ++i)
{
if (json[i] == '\\' && i + 1 < json.Length - 1)
{
int j = "\"\\nrtbf/".IndexOf(json[i + 1]);
if (j >= 0)
{
parseStringBuilder.Append("\"\\\n\r\t\b\f/"[j]);
++i;
continue;
}
if (json[i + 1] == 'u' && i + 5 < json.Length - 1)
{
UInt32 c = 0;
if (UInt32.TryParse(json.Substring(i + 2, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out c))
{
parseStringBuilder.Append((char)c);
i += 5;
continue;
}
}
}
parseStringBuilder.Append(json[i]);
}
return parseStringBuilder.ToString();
}
if (type.IsPrimitive)
{
var result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture);
return result;
}
if (type == typeof(decimal))
{
decimal result;
decimal.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
return result;
}
if (type == typeof(DateTime))
{
DateTime result;
DateTime.TryParse(json.Replace("\"",""), System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out result);
return result;
}
if (json == "null")
{
return null;
}
if (type.IsEnum)
{
if (json[0] == '"')
json = json.Substring(1, json.Length - 2);
try
{
return Enum.Parse(type, json, false);
}
catch
{
return 0;
}
}
if (type.IsArray)
{
Type arrayType = type.GetElementType();
if (json[0] != '[' || json[json.Length - 1] != ']')
return null;
List<string> elems = Split(json);
Array newArray = Array.CreateInstance(arrayType, elems.Count);
for (int i = 0; i < elems.Count; i++)
newArray.SetValue(ParseValue(arrayType, elems[i]), i);
splitArrayPool.Push(elems);
return newArray;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
Type listType = type.GetGenericArguments()[0];
if (json[0] != '[' || json[json.Length - 1] != ']')
return null;
List<string> elems = Split(json);
var list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count });
for (int i = 0; i < elems.Count; i++)
list.Add(ParseValue(listType, elems[i]));
splitArrayPool.Push(elems);
return list;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
Type keyType, valueType;
{
Type[] args = type.GetGenericArguments();
keyType = args[0];
valueType = args[1];
}
//Refuse to parse dictionary keys that aren't of type string
if (keyType != typeof(string))
return null;
//Must be a valid dictionary element
if (json[0] != '{' || json[json.Length - 1] != '}')
return null;
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
return null;
var dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 });
for (int i = 0; i < elems.Count; i += 2)
{
if (elems[i].Length <= 2)
continue;
string keyValue = elems[i].Substring(1, elems[i].Length - 2);
object val = ParseValue(valueType, elems[i + 1]);
dictionary[keyValue] = val;
}
return dictionary;
}
if (type == typeof(object))
{
return ParseAnonymousValue(json);
}
if (json[0] == '{' && json[json.Length - 1] == '}')
{
return ParseObject(type, json);
}
return null;
}
static object ParseAnonymousValue(string json)
{
if (json.Length == 0)
return null;
if (json[0] == '{' && json[json.Length - 1] == '}')
{
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
return null;
var dict = new Dictionary<string, object>(elems.Count / 2);
for (int i = 0; i < elems.Count; i += 2)
dict[elems[i].Substring(1, elems[i].Length - 2)] = ParseAnonymousValue(elems[i + 1]);
return dict;
}
if (json[0] == '[' && json[json.Length - 1] == ']')
{
List<string> items = Split(json);
var finalList = new List<object>(items.Count);
for (int i = 0; i < items.Count; i++)
finalList.Add(ParseAnonymousValue(items[i]));
return finalList;
}
if (json[0] == '"' && json[json.Length - 1] == '"')
{
string str = json.Substring(1, json.Length - 2);
return str.Replace("\\", string.Empty);
}
if (char.IsDigit(json[0]) || json[0] == '-')
{
if (json.Contains("."))
{
double result;
double.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
return result;
}
else
{
int result;
int.TryParse(json, out result);
return result;
}
}
if (json == "true")
return true;
if (json == "false")
return false;
// handles json == "null" as well as invalid JSON
return null;
}
static Dictionary<string, T> CreateMemberNameDictionary<T>(T[] members) where T : MemberInfo
{
Dictionary<string, T> nameToMember = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < members.Length; i++)
{
T member = members[i];
if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true))
continue;
string name = member.Name;
if (member.IsDefined(typeof(DataMemberAttribute), true))
{
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true);
if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
name = dataMemberAttribute.Name;
}
nameToMember.Add(name, member);
}
return nameToMember;
}
static object ParseObject(Type type, string json)
{
object instance = FormatterServices.GetUninitializedObject(type);
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
return instance;
Dictionary<string, FieldInfo> nameToField;
Dictionary<string, PropertyInfo> nameToProperty;
if (!fieldInfoCache.TryGetValue(type, out nameToField))
{
nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
fieldInfoCache.Add(type, nameToField);
}
if (!propertyInfoCache.TryGetValue(type, out nameToProperty))
{
nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
propertyInfoCache.Add(type, nameToProperty);
}
for (int i = 0; i < elems.Count; i += 2)
{
if (elems[i].Length <= 2)
continue;
string key = elems[i].Substring(1, elems[i].Length - 2);
string value = elems[i + 1];
FieldInfo fieldInfo;
PropertyInfo propertyInfo;
if (nameToField.TryGetValue(key, out fieldInfo))
fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value));
else if (nameToProperty.TryGetValue(key, out propertyInfo))
propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null);
}
return instance;
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace vCardEditor.Libs.TinyJson
{
public class LocalizationFile
{
public string version;
public Dictionary<string, LanguageData> languages = new Dictionary<string, LanguageData>();
}
public class LanguageData
{
public string name;
public Dictionary<string, string> messages = new Dictionary<string, string>();
}
}

View File

@@ -0,0 +1,30 @@
using vCardEditor.Repository;
namespace vCardEditor.Libs.TinyJson
{
public class LocalizationLoader
{
private readonly IParser _parser;
private readonly IFileHandler _fileHandler;
public LocalizationLoader(IParser parser, IFileHandler fileHandler)
{
_parser = parser;
_fileHandler = fileHandler;
}
public LocalizationFile LoadEmbedded(string EmbeddedResourceName = "vCardEditor.i18n.lang.json")
{
string json = _fileHandler.LoadJsonFromAssembly(EmbeddedResourceName);
return Deserialize(json);
}
private LocalizationFile Deserialize(string json)
{
var result = _parser.Deserialize<LocalizationFile>(json);
return result ?? new LocalizationFile();
}
}
}

View File

@@ -0,0 +1,12 @@
using TinyJson;
namespace vCardEditor.Libs.TinyJson
{
public class TinyJsonParser : IParser
{
public T Deserialize<T>(string json)
{
return JSONParser.FromJson<T>(json);
}
}
}

View File

@@ -15,6 +15,7 @@ namespace VCFEditor.Model
NotifyPropertyChanged("Name");
}
}
[DisplayName("F.Name")]
public string FamilyName
{
@@ -27,12 +28,10 @@ namespace VCFEditor.Model
get {
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
return card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber;
return string.Empty;
}
}
[Browsable(false)]
public vCard card { get; set; }
@@ -44,7 +43,9 @@ namespace VCFEditor.Model
[Browsable(false)]
public bool isDeleted { get; set; }
[Browsable(false)]
public string path { get; set; }
public Contact()
{
@@ -53,6 +54,18 @@ namespace VCFEditor.Model
isDirty = false;
}
public Contact(vCard card)
{
this.card = card;
isSelected = false;
isDirty = false;
}
public Contact(string path) : this()
{
this.path = path;
}
private void NotifyPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace vCardEditor.Model
{
@@ -16,10 +15,9 @@ namespace vCardEditor.Model
get { return _size; }
set { _size = value; }
}
public FixedList() : this(5)
{
}
public FixedList() { }
public FixedList(int size)
{
this._size = size;

View File

@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Thought.vCards;
using VCFEditor.View;
using vCardEditor;
using vCardEditor.Model;
using vCardEditor.Repository;
using vCardEditor.View.Customs;
using VCFEditor.Repository;
using vCardEditor.Repository;
using vCardEditor.Model;
using System.Linq;
using System.Collections.Generic;
using VCFEditor.View;
namespace VCFEditor.Presenter
{
@@ -14,16 +15,17 @@ namespace VCFEditor.Presenter
{
private readonly IMainView _view;
private readonly IContactRepository _repository;
private readonly ILocalizationProvider _localization;
public MainPresenter(IMainView view, IContactRepository repository)
public MainPresenter(IMainView view, IContactRepository repository, ILocalizationProvider localization )
{
_view = view;
_repository = repository;
_localization = localization;
_view.LoadForm += LoadFormHandler;
_view.AddContact += AddContactHandler;
_view.NewFileOpened += NewFileOpenedHandler;
_view.NewFileOpened += OpenNewFileHandler;
_view.SaveContactsSelected += SaveContactsHandler;
_view.ChangeContactsSelected += ChangeContactSelectedHandler;
_view.DeleteContact += DeleteContactHandler;
@@ -42,7 +44,68 @@ namespace VCFEditor.Presenter
_view.CountImagesEvent += _view_CountImages;
_view.ClearImagesEvent += _view_ClearImages;
_view.BatchExportImagesEvent += _view_BatchExportImagesEvent;
_view.SplitFileEvent += SaveSplittedFileHandler;
_view.OpenFolderEvent += OpenNewFolderHandler;
_view.CardInfoRemoved += CardInfoRemovedHandler;
}
private void OpenNewFolderHandler(object sender, EventArg<string> e)
{
BeforeOpeningNewFileHandler();
string path = e.Data;
if (string.IsNullOrEmpty(path))
path = _view.DisplayOpenFolderDialog();
if (!string.IsNullOrEmpty(path))
{
bool Loaded =_repository.LoadMultipleFilesContact(path);
if (!Loaded)
{
_view.DisplayMessage("No file loaded!", "Error");
return;
}
AddPathToMostRecentUsedFiles(path);
_view.DisplayContacts(_repository.Contacts);
}
}
public void OpenNewFileHandler(object sender, EventArg<string> e)
{
BeforeOpeningNewFileHandler();
string path = e.Data;
if (string.IsNullOrEmpty(path))
path = _view.DisplayOpenFileDialog("vCard Files|*.vcf");
if (!string.IsNullOrEmpty(path))
{
string ext = _repository.GetExtension(path);
if (!string.Equals(ext, ".vcf", StringComparison.OrdinalIgnoreCase))
{
_view.DisplayMessage("Only vcf extension accepted!", "Error");
return;
}
if (!_repository.LoadContacts(path))
_view.DisplayMessage("File seems missing or corrupted!", "Error");
else
{
_view.DisplayContacts(_repository.Contacts);
AddPathToMostRecentUsedFiles(path);
}
}
}
private void AddPathToMostRecentUsedFiles(string path)
{
FixedList MostRecentUsedFiles = ConfigRepository.Instance.Paths;
if (!MostRecentUsedFiles.Contains(path))
{
MostRecentUsedFiles.Enqueue(path);
_view.UpdateMRUMenu(MostRecentUsedFiles);
}
}
private void _view_BatchExportImagesEvent(object sender, EventArgs e)
@@ -57,7 +120,6 @@ namespace VCFEditor.Presenter
{
count++;
SaveCardPhoto(_repository.Contacts[i].card, i);
}
}
@@ -86,7 +148,6 @@ namespace VCFEditor.Presenter
}
}
if (count > 0)
_view.DisplayMessage($"{count} contact(s) processed!", "Photo Count");
else
@@ -98,7 +159,7 @@ namespace VCFEditor.Presenter
if (_repository.Contacts == null)
return;
var count = _repository.Contacts.Count(x => x.card.Photos.Count > 0);
int count = _repository.Contacts.Count(x => x.card.Photos.Count > 0);
if (count > 0)
_view.DisplayMessage($"{count} contact(s) containing a picture = ", "Photo Count");
else
@@ -122,19 +183,20 @@ namespace VCFEditor.Presenter
_view.SendTextToClipBoard(SerializedCard);
_view.DisplayMessage("vCard copied to clipboard!", "Information");
}
private void LoadFormHandler(object sender, EventArg<FormState> e)
{
_view.LoadIntialState(ConfigRepository.Instance.FormState);
var paths = Environment.GetCommandLineArgs();
_view.LoadAvailablesLangs(_localization.AvailableLanguages);
_view.LoadLocalizedUI(_localization.CurrentMessages);
string[] paths = Environment.GetCommandLineArgs();
if (paths.Length > 1)
{
var evt = new EventArg<string>(paths[1]);
NewFileOpenedHandler(sender, evt);
OpenNewFileHandler(sender, evt);
}
}
private void AddressRemovedHandler(object sender, EventArg<int> e)
{
var contact = _repository.Contacts[_view.SelectedContactIndex];
@@ -148,7 +210,7 @@ namespace VCFEditor.Presenter
var contact = _repository.Contacts[_view.SelectedContactIndex];
_repository.SetDirtyFlag(_view.SelectedContactIndex);
contact.card.DeliveryAddresses.Add(new vCardDeliveryAddress( e.Data));
contact.card.DeliveryAddresses.Add(new vCardDeliveryAddress(e.Data));
}
private void AddressModifiedHandler(object sender, EventArg<List<vCardDeliveryAddressTypes>> e)
@@ -159,13 +221,13 @@ namespace VCFEditor.Presenter
contact.card.DeliveryAddresses.Clear();
contact.card.DeliveryAddresses.Add(new vCardDeliveryAddress(e.Data));
}
private void ExportImageHandler(object sender, EventArgs e)
{
if (_view.SelectedContactIndex > -1)
{
//TODO: image can be url, or file location.
var card = _repository.Contacts[_view.SelectedContactIndex].card;
vCard card = _repository.Contacts[_view.SelectedContactIndex].card;
SaveCardPhoto(card, _view.SelectedContactIndex, true);
}
}
@@ -173,12 +235,11 @@ namespace VCFEditor.Presenter
private void SaveCardPhoto(vCard card, int index, bool askUser = false)
{
//TODO: Save every image for a vCard.
var image = card.Photos.FirstOrDefault();
vCardPhoto image = card.Photos.FirstOrDefault();
if (image != null)
{
var newPath = _repository.GenerateFileName(_repository.fileName, index, image.Extension);
string newPath = _repository.GenerateFileName(_repository.fileName, index, image.Extension);
//string ImagePath = string.Empty;
//if (askUser)
@@ -190,10 +251,9 @@ namespace VCFEditor.Presenter
private void ExportQRHandler(object sender, EventArgs e)
{
if (_view.SelectedContactIndex > -1)
{
var card = _repository.Contacts[_view.SelectedContactIndex].card;
vCard card = _repository.Contacts[_view.SelectedContactIndex].card;
string content = _repository.GenerateStringFromVCard(card);
_view.DisplayQRCode(content);
@@ -202,29 +262,28 @@ namespace VCFEditor.Presenter
private void ModifyImageHandler(object sender, EventArg<string> e)
{
if (!string.IsNullOrEmpty(e.Data) )
if (!string.IsNullOrEmpty(e.Data))
{
vCardPhoto photo = new vCardPhoto(e.Data);
_repository.ModifyImage(_view.SelectedContactIndex, photo);
}
else
_repository.ModifyImage(_view.SelectedContactIndex, null);
}
void CloseFormHandler(object sender, EventArg<bool> e)
{
if (_repository.dirty && _view.AskMessage("Exit without saving?", "Exit"))
if (_repository.dirty && !_view.AskMessage("Exit without saving?", "Exit"))
e.Data = true;
if (!e.Data)
{
var state = _view.GetFormState();
FormState state = _view.GetFormState();
ConfigRepository.Instance.FormState = state;
ConfigRepository.Instance.SaveConfig();
}
}
public void BeforeLeavingContactHandler(object sender, EventArg<vCard> e)
{
_repository.SaveDirtyVCard(_view.SelectedContactIndex, e.Data);
@@ -232,10 +291,14 @@ namespace VCFEditor.Presenter
public void TextBoxValueChangedHandler(object sender, EventArgs e)
{
var tb = sender as StateTextBox;
StateTextBox tb = sender as StateTextBox;
if (tb != null && tb.oldText != tb.Text)
_repository.SetDirtyFlag(_view.SelectedContactIndex);
}
public void CardInfoRemovedHandler(object sender, EventArgs e)
{
_repository.SetDirtyFlag(_view.SelectedContactIndex);
}
public void FilterTextChangedHandler(object sender, EventArg<string> e)
@@ -247,6 +310,7 @@ namespace VCFEditor.Presenter
private void AddContactHandler(object sender, EventArgs e)
{
_repository.AddEmptyContact();
_view.DisplayContacts(_repository.Contacts);
}
private void DeleteContactHandler(object sender, EventArgs e)
@@ -256,56 +320,38 @@ namespace VCFEditor.Presenter
private void SaveContactsHandler(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(_repository.fileName))
_repository.SaveContactsToFile(_repository.fileName);
string filename = _repository.fileName ?? _view.DisplaySaveDialog();
if (string.IsNullOrWhiteSpace(filename))
return;
_repository.SaveContactsToFile(filename);
}
private void SaveSplittedFileHandler(object sender, EventArgs e)
{
if (_repository.Contacts == null || _repository.Contacts.Count == 0)
return;
string Path = _view.DisplayOpenFolderDialog();
if (!string.IsNullOrEmpty(Path))
{
int count = _repository.SaveSplittedFiles(Path);
_view.DisplayMessage(string.Format("{0} contact(s) processed!", count), "Information");
}
}
private void BeforeOpeningNewFileHandler()
{
if (_repository.Contacts != null && _repository.dirty)
{
if (!_view.AskMessage("Save current file before?", "Load"))
_repository.SaveContactsToFile(_repository.fileName);
if (_view.AskMessage("Save current file before?", "Load"))
SaveContactsHandler(null, null);
//_repository.SaveContactsToFile(_repository.fileName);
}
}
public void NewFileOpenedHandler(object sender, EventArg<string> e)
{
BeforeOpeningNewFileHandler();
string path = e.Data;
if (string.IsNullOrEmpty(path))
path = _view.DisplayOpenDialog("vCard Files|*.vcf");
if (!string.IsNullOrEmpty(path))
{
string ext = _repository.GetExtension(path);
if (!string.Equals(ext, ".vcf", StringComparison.OrdinalIgnoreCase))
{
_view.DisplayMessage("Only vcf extension accepted!", "Error");
return;
}
FixedList MostRecentUsedFiles = ConfigRepository.Instance.Paths;
if (!MostRecentUsedFiles.Contains(path))
{
MostRecentUsedFiles.Enqueue(path);
_view.UpdateMRUMenu(MostRecentUsedFiles);
}
if (!_repository.LoadContacts(path))
_view.DisplayMessage("File seems missing or corrupted!", "Error");
else
_view.DisplayContacts(_repository.Contacts);
}
}
public void ChangeContactSelectedHandler(object sender, EventArgs e)
{
if (_view.SelectedContactIndex > -1)
{
vCard card = _repository.Contacts[_view.SelectedContactIndex].card;
@@ -317,8 +363,6 @@ namespace VCFEditor.Presenter
}
else
_view.ClearContactDetail();
}
}
}

View File

@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using vCardEditor.Libs.TinyJson;
using vCardEditor.Repository;
using vCardEditor.View;
using VCFEditor.Presenter;
using VCFEditor;
using VCFEditor.Repository;
using vCardEditor.Repository;
namespace vCardEditor
{
@@ -20,10 +18,14 @@ namespace vCardEditor
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
FileHandler fileHandler = new FileHandler();
var fileHandler = new FileHandler();
var mainForm = new MainForm();
new MainPresenter(mainForm, new ContactRepository(fileHandler));
var embeddedlang = new LocalizationLoader(new TinyJsonParser(), fileHandler).LoadEmbedded();
MainForm mainForm = new MainForm();
new MainPresenter(mainForm,
new ContactRepository(fileHandler),
new JsonLocalizationProvider(embeddedlang));
Application.Run(mainForm);
}

View File

@@ -32,4 +32,4 @@ using System.Runtime.InteropServices;
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
// en utilisant '*', comme indiqué ci-dessous :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.5.7")]
[assembly: AssemblyVersion("0.5.8")]

View File

@@ -1,4 +1,15 @@
0.5.5
0.5.8
Merged PR #42, #45
0.5.7
added a feature to batch export/clear/count images.
Fix bug when opening files by menu.
some buttons click were not working properly.
0.5.6
Not released!
0.5.5
redisgn the extra tab
Fix some bugs
@@ -31,4 +42,4 @@
Replaced Moq with nsubstitute (Test mocking library).
0.1
Intial release
Intial release

View File

@@ -17,6 +17,7 @@ namespace vCardEditor.Repository
private const int MAX_RECENT_FILES = 5;
private static ConfigRepository instance = null;
[XmlIgnore]
public static ConfigRepository Instance
{
@@ -31,6 +32,7 @@ namespace vCardEditor.Repository
[Description("Overwrite the file when saving")]
public bool Overwrite { get; set; }
[Description("Maximum entries for MRU ")]
public int Maximum { get; set; }
@@ -45,14 +47,12 @@ namespace vCardEditor.Repository
private ConfigRepository() { }
/// <summary>
/// save config file
/// </summary>
public void SaveConfig()
{
var ns = new XmlSerializerNamespaces();
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer xsSubmit = new XmlSerializer(typeof(ConfigRepository));
@@ -82,7 +82,6 @@ namespace vCardEditor.Repository
configData = (ConfigRepository)deserializer.Deserialize(reader);
configData.Paths.Size = configData.Maximum;
}
}
catch (Exception)
{
@@ -94,10 +93,7 @@ namespace vCardEditor.Repository
};
}
return configData;
}
}
}

View File

@@ -3,9 +3,9 @@ using System.IO;
using System.Linq;
using System.Text;
using Thought.vCards;
using VCFEditor.Model;
using vCardEditor.Repository;
using vCardEditor.View;
using VCFEditor.Model;
namespace VCFEditor.Repository
{
@@ -13,16 +13,13 @@ namespace VCFEditor.Repository
{
public string fileName { get; set; }
private IFileHandler _fileHandler;
/// <summary>
/// Formatted name.
/// </summary>
public const string KeyName = "FN";
/// <summary>
/// Keep a copy of contact list when filtering
/// </summary>
private SortableBindingList<Contact> OriginalContactList = null;
private SortableBindingList<Contact> _contacts;
public SortableBindingList<Contact> Contacts
{
get
@@ -43,23 +40,45 @@ namespace VCFEditor.Repository
get { return (_contacts != null && _contacts.Any(x => x.isDirty)) || _dirty; }
set { _dirty = true; }
}
public ContactRepository(IFileHandler fileHandler)
{
_fileHandler = fileHandler;
}
public bool LoadMultipleFilesContact(string path)
{
Contacts.Clear();
string[] filePaths = _fileHandler.GetFiles(path, "*.vcf");
if (filePaths.Count() == 0)
return false;
foreach (string item in filePaths)
{
var result = LoadContactFromFile(item);
Contacts.AddRange(result);
OriginalContactList = Contacts;
}
return true;
}
public bool LoadContacts(string fileName)
{
Contacts.Clear();
this.fileName = fileName;
Contacts = LoadContactFromFile(fileName);
OriginalContactList = Contacts;
return true;
}
public SortableBindingList<Contact> LoadContactFromFile(string fileName)
{
if (!_fileHandler.FileExist(fileName))
{
OriginalContactList = null;
return false;
}
return null;
SortableBindingList<Contact> ListOfContacts = new SortableBindingList<Contact>();
string[] lines = _fileHandler.ReadAllLines(fileName);
StringBuilder RawContent = new StringBuilder();
@@ -72,24 +91,18 @@ namespace VCFEditor.Repository
{
if (string.Equals(lines[i].TrimEnd(), "END:VCARD", StringComparison.OrdinalIgnoreCase))
{
contact = new Contact
{
card = ParseRawContent(RawContent)
};
Contacts.Add(contact);
contact = new Contact(ParseRawContent(RawContent));
ListOfContacts.Add(contact);
RawContent.Length = 0;
}
}
catch (Exception)
{
OriginalContactList = null;
return false;
return null;
}
}
OriginalContactList = Contacts;
return true;
return ListOfContacts;
}
private vCard ParseRawContent(StringBuilder rawContent)
@@ -104,11 +117,7 @@ namespace VCFEditor.Repository
public void AddEmptyContact()
{
if (_contacts != null && _contacts.Count > 0)
{
Contact contact = new Contact();
Contacts.Add(contact);
}
Contacts.Add(new Contact() { isDirty = true });
}
public void SaveContactsToFile(string fileName)
@@ -126,7 +135,7 @@ namespace VCFEditor.Repository
StringBuilder sb = new StringBuilder();
foreach (var entry in Contacts)
foreach (Contact entry in Contacts)
{
//Do not save the deleted ones!
if (!entry.isDeleted)
@@ -137,7 +146,6 @@ namespace VCFEditor.Repository
//Clean the flag for every contact, even the deleted ones.
entry.isDirty = false;
}
_dirty = false;
_fileHandler.WriteAllText(fileName, sb.ToString());
@@ -169,12 +177,9 @@ namespace VCFEditor.Repository
_dirty = true;
_contacts.RemoveAt(i);
}
}
}
}
public SortableBindingList<Contact> FilterContacts(string filter)
{
@@ -184,7 +189,6 @@ namespace VCFEditor.Repository
return Contacts;
}
public void SetDirtyFlag(int index)
{
if (index > -1)
@@ -215,25 +219,23 @@ namespace VCFEditor.Repository
private void SaveExtraPhones(vCard newCard, vCard card)
{
card.Phones.Clear();
foreach (var item in newCard.Phones)
foreach (vCardPhone item in newCard.Phones)
card.Phones.Add(new vCardPhone(item.FullNumber, item.PhoneType));
}
private void SaveExtraField(vCard newCard, vCard card)
{
card.Notes.Clear();
foreach (var item in newCard.Notes)
foreach (vCardNote item in newCard.Notes)
card.Notes.Add(new vCardNote(item.Text));
card.Organization = newCard.Organization;
}
private void SaveAddresses(vCard NewCard, vCard card)
{
foreach (var item in NewCard.DeliveryAddresses)
foreach (vCardDeliveryAddress item in NewCard.DeliveryAddresses)
{
var adr = card.DeliveryAddresses.Where(x => x.AddressType.FirstOrDefault() == item.AddressType.FirstOrDefault()).FirstOrDefault();
vCardDeliveryAddress adr = card.DeliveryAddresses.Where(x => x.AddressType.FirstOrDefault() == item.AddressType.FirstOrDefault()).FirstOrDefault();
if (adr != null)
{
adr.City = item.City;
@@ -247,7 +249,6 @@ namespace VCFEditor.Repository
else
card.DeliveryAddresses.Add(new vCardDeliveryAddress(item.Street, item.City, item.Region, item.Country,
item.PostalCode, item.AddressType.FirstOrDefault()));
}
}
@@ -265,10 +266,8 @@ namespace VCFEditor.Repository
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Home) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Home).FullNumber = string.Empty;
}
//Cellular
if (NewCard.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
{
@@ -281,7 +280,6 @@ namespace VCFEditor.Repository
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Cellular).FullNumber = string.Empty;
}
//Work
@@ -296,7 +294,6 @@ namespace VCFEditor.Repository
{
if (card.Phones.GetFirstChoice(vCardPhoneTypes.Work) != null)
card.Phones.GetFirstChoice(vCardPhoneTypes.Work).FullNumber = string.Empty;
}
}
@@ -316,14 +313,12 @@ namespace VCFEditor.Repository
{
if (card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet) != null)
card.EmailAddresses.GetFirstChoice(vCardEmailAddressType.Internet).Address = string.Empty;
}
}
private void SaveWebUrl(vCard NewCard, vCard card)
{
//Personal
if (NewCard.Websites.GetFirstChoice(vCardWebsiteTypes.Personal) != null)
{
if (card.Websites.GetFirstChoice(vCardWebsiteTypes.Personal) != null)
@@ -335,23 +330,21 @@ namespace VCFEditor.Repository
{
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;
}
//Work
//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;
//}
}
public string GenerateStringFromVCard(vCard card)
@@ -392,8 +385,45 @@ namespace VCFEditor.Repository
public string GenerateFileName(string fileName, int index, string extension)
{
string result = Path.Combine(Path.GetDirectoryName(fileName), index.ToString() + "." + extension);
return result;
return _fileHandler.GetFileNameWithExtension(fileName, index, extension);
}
public int SaveSplittedFiles(string FolderPath)
{
//Do not save the deleted ones!
var contactsToSave = Contacts.Where(x => !x.isDeleted).ToList();
int count;
for (count = 0; count < contactsToSave.Count(); count++)
{
Contact entry = contactsToSave[count];
string SerializedCard = GenerateStringFromVCard(entry.card);
//Check if filename for the card is empty, and generate one if empty
if (string.IsNullOrEmpty(entry.path))
entry.path = GenerateFileName(FolderPath, entry.FamilyName, count);
_fileHandler.WriteAllText(entry.path, SerializedCard);
//Clean the flag for every contact, even the deleted ones.
entry.isDirty = false;
}
//Clean the global flag for the entire vCard Catalog.
_dirty = false;
//return number of contacts processed!
return count;
}
private string GenerateFileName(string FolderPath, string familyName, int index)
{
string FinalPath;
if (string.IsNullOrEmpty(familyName))
FinalPath = _fileHandler.GetVcfFileName(FolderPath, index.ToString());
else
FinalPath = _fileHandler.GetVcfFileName(FolderPath, familyName);
return FinalPath;
}
}
}

View File

@@ -1,5 +1,5 @@
using System.IO;
using System.Reflection;
namespace vCardEditor.Repository
{
@@ -22,7 +22,8 @@ namespace vCardEditor.Repository
public void MoveFile(string newFilename, string oldFilename)
{
File.Move(newFilename, oldFilename);
if (File.Exists(newFilename))
File.Move(newFilename, oldFilename);
}
public string[] ReadAllLines(string filename)
@@ -37,11 +38,41 @@ namespace vCardEditor.Repository
public void WriteBytesToFile(string imageFile, byte[] image)
{
using (var ms = new MemoryStream(image))
using (MemoryStream ms = new MemoryStream(image))
{
using (var fs = new FileStream(imageFile, FileMode.Create))
using (FileStream fs = new FileStream(imageFile, FileMode.Create))
ms.WriteTo(fs);
}
}
public string GetVcfFileName(string folderPath, string filename)
{
return Path.Combine(folderPath, filename + ".vcf");
}
public string GetFileNameWithExtension(string fileName, int index, string extension)
{
return Path.Combine(Path.GetDirectoryName(fileName), index.ToString() + "." + extension);
}
public string[] GetFiles(string path, string ext)
{
return Directory.GetFiles(path, ext, SearchOption.TopDirectoryOnly);
}
public string LoadJsonFromAssembly(string EmbeddedResourceName)
{
string json;
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(EmbeddedResourceName))
{
if (stream == null)
throw new FileNotFoundException($"Embedded resource '{EmbeddedResourceName}' not found.");
using (StreamReader reader = new StreamReader(stream))
json = reader.ReadToEnd();
}
return json;
}
}
}

View File

@@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thought.vCards;
using VCFEditor.Model;
using System.ComponentModel;
using vCardEditor.View;
namespace VCFEditor.Repository
@@ -15,6 +11,7 @@ namespace VCFEditor.Repository
string fileName { get; set; }
SortableBindingList<Contact> Contacts { get; set; }
bool LoadContacts(string fileName);
bool LoadMultipleFilesContact(string path);
SortableBindingList<Contact> FilterContacts(string p);
void SaveContactsToFile(string fileName);
void DeleteContact();
@@ -28,5 +25,7 @@ namespace VCFEditor.Repository
string GenerateStringFromVCard(vCard card);
string GenerateFileName(string fileName, int index, string extension);
int SaveSplittedFiles(string Path);
}
}

View File

@@ -1,4 +1,6 @@
namespace vCardEditor.Repository
using System.IO;
namespace vCardEditor.Repository
{
public interface IFileHandler
{
@@ -9,5 +11,9 @@
string GetExtension(string path);
string ChangeExtension(string path, string extension);
void WriteBytesToFile(string imageFile, byte[] image);
string GetVcfFileName(string folderPath, string familyName);
string GetFileNameWithExtension(string fileName, int index, string extension);
string LoadJsonFromAssembly(string EmbeddedResourceName);
string[] GetFiles(string path, string ext);
}
}

View File

@@ -46,7 +46,7 @@
this.tableLayoutPanel.ColumnCount = 3;
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 32.31441F));
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67.68559F));
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 119F));
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 90F));
this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0);
this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0);
this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1);
@@ -56,33 +56,30 @@
this.tableLayoutPanel.Controls.Add(this.okButton, 2, 5);
this.tableLayoutPanel.Controls.Add(this.updateButton, 1, 5);
this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel.Location = new System.Drawing.Point(12, 11);
this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4);
this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9);
this.tableLayoutPanel.Name = "tableLayoutPanel";
this.tableLayoutPanel.RowCount = 7;
this.tableLayoutPanel.RowCount = 6;
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 47.93651F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.69841F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 8F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel.Size = new System.Drawing.Size(556, 326);
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 16F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 16F));
this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 16F));
this.tableLayoutPanel.Size = new System.Drawing.Size(417, 265);
this.tableLayoutPanel.TabIndex = 0;
//
// logoPictureBox
//
this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image")));
this.logoPictureBox.Location = new System.Drawing.Point(4, 4);
this.logoPictureBox.Margin = new System.Windows.Forms.Padding(4);
this.logoPictureBox.Location = new System.Drawing.Point(3, 3);
this.logoPictureBox.Name = "logoPictureBox";
this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6);
this.logoPictureBox.Size = new System.Drawing.Size(133, 121);
this.logoPictureBox.Size = new System.Drawing.Size(99, 98);
this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.logoPictureBox.TabIndex = 12;
this.logoPictureBox.TabStop = false;
@@ -91,11 +88,11 @@
//
this.tableLayoutPanel.SetColumnSpan(this.labelProductName, 2);
this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelProductName.Location = new System.Drawing.Point(149, 0);
this.labelProductName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
this.labelProductName.MaximumSize = new System.Drawing.Size(0, 21);
this.labelProductName.Location = new System.Drawing.Point(111, 0);
this.labelProductName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17);
this.labelProductName.Name = "labelProductName";
this.labelProductName.Size = new System.Drawing.Size(403, 21);
this.labelProductName.Size = new System.Drawing.Size(303, 17);
this.labelProductName.TabIndex = 19;
this.labelProductName.Text = "Nom du produit";
this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@@ -104,11 +101,11 @@
//
this.tableLayoutPanel.SetColumnSpan(this.labelVersion, 2);
this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelVersion.Location = new System.Drawing.Point(149, 31);
this.labelVersion.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
this.labelVersion.MaximumSize = new System.Drawing.Size(0, 21);
this.labelVersion.Location = new System.Drawing.Point(111, 26);
this.labelVersion.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17);
this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(403, 21);
this.labelVersion.Size = new System.Drawing.Size(303, 17);
this.labelVersion.TabIndex = 0;
this.labelVersion.Text = "Version";
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@@ -117,11 +114,11 @@
//
this.tableLayoutPanel.SetColumnSpan(this.labelCopyright, 2);
this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelCopyright.Location = new System.Drawing.Point(149, 62);
this.labelCopyright.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 21);
this.labelCopyright.Location = new System.Drawing.Point(111, 52);
this.labelCopyright.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17);
this.labelCopyright.Name = "labelCopyright";
this.labelCopyright.Size = new System.Drawing.Size(403, 21);
this.labelCopyright.Size = new System.Drawing.Size(303, 17);
this.labelCopyright.TabIndex = 21;
this.labelCopyright.Text = "Copyright";
this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@@ -130,11 +127,11 @@
//
this.tableLayoutPanel.SetColumnSpan(this.labelCompanyName, 2);
this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelCompanyName.Location = new System.Drawing.Point(149, 93);
this.labelCompanyName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 21);
this.labelCompanyName.Location = new System.Drawing.Point(111, 78);
this.labelCompanyName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 17);
this.labelCompanyName.Name = "labelCompanyName";
this.labelCompanyName.Size = new System.Drawing.Size(403, 21);
this.labelCompanyName.Size = new System.Drawing.Size(303, 17);
this.labelCompanyName.TabIndex = 22;
this.labelCompanyName.Text = "Nom de la société";
this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@@ -143,34 +140,34 @@
//
this.tableLayoutPanel.SetColumnSpan(this.textBoxDescription, 2);
this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBoxDescription.Location = new System.Drawing.Point(149, 128);
this.textBoxDescription.Margin = new System.Windows.Forms.Padding(8, 4, 4, 4);
this.textBoxDescription.Location = new System.Drawing.Point(111, 107);
this.textBoxDescription.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.textBoxDescription.Multiline = true;
this.textBoxDescription.Name = "textBoxDescription";
this.textBoxDescription.ReadOnly = true;
this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxDescription.Size = new System.Drawing.Size(403, 143);
this.textBoxDescription.Size = new System.Drawing.Size(303, 120);
this.textBoxDescription.TabIndex = 23;
this.textBoxDescription.TabStop = false;
this.textBoxDescription.Text = "Description";
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.okButton.Location = new System.Drawing.Point(442, 282);
this.okButton.Margin = new System.Windows.Forms.Padding(4);
this.okButton.Location = new System.Drawing.Point(332, 235);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(110, 29);
this.okButton.Size = new System.Drawing.Size(82, 24);
this.okButton.TabIndex = 24;
this.okButton.Text = "&OK";
//
// updateButton
//
this.updateButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.updateButton.Location = new System.Drawing.Point(312, 283);
this.updateButton.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.updateButton.Location = new System.Drawing.Point(233, 235);
this.updateButton.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.updateButton.Name = "updateButton";
this.updateButton.Size = new System.Drawing.Size(121, 29);
this.updateButton.Size = new System.Drawing.Size(91, 24);
this.updateButton.TabIndex = 25;
this.updateButton.Text = "Check update...";
this.updateButton.Click += new System.EventHandler(this.updateButton_Click);
@@ -178,16 +175,15 @@
// AboutDialog
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(580, 348);
this.ClientSize = new System.Drawing.Size(435, 283);
this.Controls.Add(this.tableLayoutPanel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Margin = new System.Windows.Forms.Padding(4);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AboutDialog";
this.Padding = new System.Windows.Forms.Padding(12, 11, 12, 11);
this.Padding = new System.Windows.Forms.Padding(9, 9, 9, 9);
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

View File

@@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
using vCardEditor.Repository;
@@ -40,7 +35,7 @@ namespace vCardEditor.View
return titleAttribute.Title;
}
}
return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
return Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
}
}
@@ -109,10 +104,10 @@ namespace vCardEditor.View
{
try
{
using (var client = new WebClient())
using (WebClient client = new WebClient())
{
string result = await client.DownloadStringTaskAsync(ConfigRepository.Instance.VersionUrl);
using (var reader = new StringReader(result))
using (StringReader reader = new StringReader(result))
{
string InternetVersion = reader.ReadLine();
string AssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
@@ -126,11 +121,11 @@ namespace vCardEditor.View
}
}
}
catch (WebException )
catch (WebException)
{
MessageBox.Show("Could not download version information from GitHub.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception )
catch (Exception)
{
MessageBox.Show("Error processing version information.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

View File

@@ -30,48 +30,33 @@
{
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.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnClose.Location = new System.Drawing.Point(337, 427);
this.btnClose.Margin = new System.Windows.Forms.Padding(4);
this.btnClose.Location = new System.Drawing.Point(253, 347);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(100, 28);
this.btnClose.Size = new System.Drawing.Size(75, 23);
this.btnClose.TabIndex = 0;
this.btnClose.Text = "Close";
this.btnClose.UseVisualStyleBackColor = true;
//
// pgConfig
//
this.pgConfig.Location = new System.Drawing.Point(16, 15);
this.pgConfig.Margin = new System.Windows.Forms.Padding(4);
this.pgConfig.Location = new System.Drawing.Point(12, 12);
this.pgConfig.Name = "pgConfig";
this.pgConfig.Size = new System.Drawing.Size(421, 405);
this.pgConfig.Size = new System.Drawing.Size(316, 329);
this.pgConfig.TabIndex = 1;
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(229, 427);
this.btnCancel.Margin = new System.Windows.Forms.Padding(4);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(100, 28);
this.btnCancel.TabIndex = 0;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// ConfigDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(449, 470);
this.ClientSize = new System.Drawing.Size(337, 382);
this.Controls.Add(this.pgConfig);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnClose);
this.Margin = new System.Windows.Forms.Padding(4);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "ConfigDialog";
this.Text = "Configuration Dialog";
this.ResumeLayout(false);
@@ -82,6 +67,5 @@
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.PropertyGrid pgConfig;
private System.Windows.Forms.Button btnCancel;
}
}

View File

@@ -1,7 +1,5 @@
using System;
using System.Windows.Forms;
using System.Windows.Forms;
using vCardEditor.Repository;
using vCardEditor.Model;
namespace vCardEditor.View
{

View File

@@ -26,9 +26,7 @@ namespace vCardEditor.View.Customs
Addresses = addressCollection;
_checkBoxes = Controls.OfType<CheckBox>().ToList();
foreach (var item in addressCollection)
foreach (vCardDeliveryAddressTypes item in addressCollection)
{
switch (item.ToString())
{
@@ -53,9 +51,7 @@ namespace vCardEditor.View.Customs
case "International":
cbInternational.Checked = true;
break;
}
}
}
@@ -71,13 +67,11 @@ namespace vCardEditor.View.Customs
}
Addresses.Clear();
foreach (var item in checkedItems)
foreach (CheckBox item in checkedItems)
{
var enumType = (vCardDeliveryAddressTypes)Enum.Parse(typeof(vCardDeliveryAddressTypes), item.Text, true);
vCardDeliveryAddressTypes enumType = (vCardDeliveryAddressTypes)Enum.Parse(typeof(vCardDeliveryAddressTypes), item.Text, true);
Addresses.Add(enumType);
}
}
}
}

View File

@@ -8,8 +8,8 @@ namespace vCardEditor.View.Customs
public partial class AddressBox : UserControl
{
public event EventHandler TextChangedEvent;
public List<vCardDeliveryAddressTypes> AddressType { get; set; }
public AddressBox(string street, string city, string region, string country, string postalCode,
string extendedAddress, string postOfficeBox, List<vCardDeliveryAddressTypes> addressType)
@@ -46,7 +46,7 @@ namespace vCardEditor.View.Customs
public vCardDeliveryAddress getDeliveryAddress()
{
var deliveryAddress = new vCardDeliveryAddress
vCardDeliveryAddress deliveryAddress = new vCardDeliveryAddress
{
City = CityValue.Text,
Country = CountryValue.Text,
@@ -57,9 +57,7 @@ namespace vCardEditor.View.Customs
PostOfficeBox = POBoxValue.Text,
AddressType = AddressType
};
return deliveryAddress;
}
}
}

View File

@@ -26,7 +26,6 @@ namespace vCardEditor.View.Customs
Selecting += tbcAddress_Selecting;
HandleCreated += tbcAddress_HandleCreated;
MouseDoubleClick += AddressTabControl_MouseDoubleClick;
}
public void getDeliveryAddress(vCard card)
@@ -51,9 +50,9 @@ namespace vCardEditor.View.Customs
{
if (GetTabRect(i).Contains(e.Location))
{
var AddressBox = TabPages[i].Controls[0] as AddressBox;
AddressBox AddressBox = TabPages[i].Controls[0] as AddressBox;
var diag = new AddAddressDialog(AddressBox.AddressType);
AddAddressDialog diag = new AddAddressDialog(AddressBox.AddressType);
if (diag.ShowDialog() == DialogResult.OK)
{
@@ -66,10 +65,8 @@ namespace vCardEditor.View.Customs
break;
}
}
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private const int TCM_SETMINTABWIDTH = 0x1300 + 49;
@@ -78,20 +75,18 @@ namespace vCardEditor.View.Customs
SendMessage(Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
}
private void tbcAddress_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPageIndex == TabCount - 1)
e.Cancel = true;
}
private void tbcAddress_MouseDown(object sender, MouseEventArgs e)
{
var lastIndex = TabCount - 1;
int lastIndex = TabCount - 1;
if (GetTabRect(lastIndex).Contains(e.Location))
{
var diag = new AddAddressDialog();
AddAddressDialog diag = new AddAddressDialog();
if (diag.ShowDialog() == DialogResult.OK)
{
vCardDeliveryAddress da = new vCardDeliveryAddress();
@@ -100,16 +95,15 @@ namespace vCardEditor.View.Customs
AddTab?.Invoke(sender, new EventArg<List<vCardDeliveryAddressTypes>>(diag.Addresses));
SelectedIndex = TabCount - 2;
}
}
else
{
for (var i = 0; i < TabPages.Count; i++)
for (int i = 0; i < TabPages.Count; i++)
{
var tabRect = GetTabRect(i);
Rectangle tabRect = GetTabRect(i);
tabRect.Inflate(-2, -2);
var closeImage = Properties.Resources.Close;
var imageRect = new Rectangle(
Bitmap closeImage = Properties.Resources.Close;
Rectangle imageRect = new Rectangle(
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2,
closeImage.Width, closeImage.Height);
@@ -122,12 +116,9 @@ namespace vCardEditor.View.Customs
SelectedIndex = 0;
RemoveTab?.Invoke(sender, new EventArg<int>(i));
}
return;
}
}
}
}
@@ -136,19 +127,19 @@ namespace vCardEditor.View.Customs
if (e.Index > TabCount - 1)
return;
var tabRect = GetTabRect(e.Index);
Rectangle tabRect = GetTabRect(e.Index);
tabRect.Inflate(-2, -2);
if (e.Index == TabCount - 1)
{
var addImage = Properties.Resources.Add;
Bitmap addImage = Properties.Resources.Add;
e.Graphics.DrawImage(addImage,
tabRect.Left + (tabRect.Width - addImage.Width) / 2,
tabRect.Top + (tabRect.Height - addImage.Height) / 2);
}
else
{
var closeImage = Properties.Resources.Close;
Bitmap closeImage = Properties.Resources.Close;
e.Graphics.DrawImage(closeImage,
(tabRect.Right - closeImage.Width),
tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
@@ -172,8 +163,6 @@ namespace vCardEditor.View.Customs
TextBrush.Dispose();
}
}
public void SetAddresses(vCard card)
@@ -184,7 +173,7 @@ namespace vCardEditor.View.Customs
private void AddTabForEveryAddress(vCard card)
{
foreach (var item in card.DeliveryAddresses)
foreach (vCardDeliveryAddress item in card.DeliveryAddresses)
AddtabForAddress(item);
SelectedIndex = 0;
}
@@ -193,36 +182,32 @@ namespace vCardEditor.View.Customs
{
string title = GetTabTitle(da.AddressType);
var page = new TabPage($" {title} ");
TabPage page = new TabPage($" {title} ");
TabPages.Insert(TabCount - 1, page);
var ab = new AddressBox(da.Street, da.City, da.Region, da.Country,
AddressBox ab = new AddressBox(da.Street, da.City, da.Region, da.Country,
da.PostalCode, da.ExtendedAddress, da.PostOfficeBox, da.AddressType);
ab.TextChangedEvent += (s, e) => TextChangedEvent?.Invoke(s, e);
ab.Dock = DockStyle.Fill;
page.Controls.Add(ab);
page.ToolTipText = string.Join(",", da.AddressType.ConvertAll(f => f.ToString()));
}
private string GetTabTitle(List<vCardDeliveryAddressTypes> addressTypes)
{
var title = string.Empty;
string title = string.Empty;
if (addressTypes.Count > 0)
{
title = addressTypes[0].ToString();
if (addressTypes.Count > 1)
title += "...";
}
return title;
}
private void ClearTabs()
{
//Remove every tab (except "+"). We don't call Clear() as it doesn't free memory.
while (TabCount > 1)
TabPages[0].Dispose();

View File

@@ -18,7 +18,7 @@ namespace vCardEditor.View.Customs
_checkBoxes = Controls.OfType<CheckBox>().ToList();
Columns = columns;
foreach (var item in columns)
foreach (Column item in columns)
{
switch (item)
{
@@ -36,13 +36,9 @@ namespace vCardEditor.View.Customs
private void btnOK_Click(object sender, EventArgs e)
{
Columns.Clear();
var total = _checkBoxes
.Where(checkBox => checkBox.Checked);
foreach (var item in total)
foreach (CheckBox item in _checkBoxes.Where(checkBox => checkBox.Checked))
{
var enumType = (Column)Enum.Parse(typeof(Column), item.Text, true);
Column enumType = (Column)Enum.Parse(typeof(Column), item.Text, true);
Columns.Add(enumType);
}
}

View File

@@ -1,7 +1,7 @@

namespace vCardEditor.View.Customs
{
partial class CustumInputDialog
partial class CustomInputDialog
{
/// <summary>
/// Required designer variable.

View File

@@ -2,9 +2,9 @@
namespace vCardEditor.View.Customs
{
public partial class CustumInputDialog : Form
public partial class CustomInputDialog : Form
{
public CustumInputDialog()
public CustomInputDialog()
{
InitializeComponent();
}
@@ -15,7 +15,5 @@ namespace vCardEditor.View.Customs
{
input = tbInput.Text;
}
}
}

View File

@@ -6,20 +6,19 @@ using Thought.vCards;
namespace vCardEditor.View.Customs
{
public partial class ExtendedPanel : UserControl
{
public ExtendedPanel()
{
InitializeComponent();
miCell.Click += MenuItemClickHandlers;
miCell.Tag = new vCardPhone(string.Empty, vCardPhoneTypes.Cellular);
miCell.Click += MenuItemClickHandlers;
miHome.Tag = new vCardPhone(string.Empty, vCardPhoneTypes.Home);
miHome.Click += MenuItemClickHandlers;
miWork.Tag = new vCardPhone(string.Empty, vCardPhoneTypes.Home);
miWork.Tag = new vCardPhone(string.Empty, vCardPhoneTypes.Work);
miWork.Click += MenuItemClickHandlers;
miEmail.Tag = new vCardEmailAddress(string.Empty, vCardEmailAddressType.Internet);
@@ -35,9 +34,10 @@ namespace vCardEditor.View.Customs
//{
// AddControl(custom.input, string.Empty);
//}
}
public event EventHandler ContentTextChanged;
public event EventHandler CardInfoRemoved;
public string Caption
{
@@ -46,14 +46,14 @@ namespace vCardEditor.View.Customs
}
public PanelType panelType { get; set; }
private void MenuItemClickHandlers(object sender, EventArgs e)
{
var tag = (sender as ToolStripMenuItem).Tag;
object tag = (sender as ToolStripMenuItem).Tag;
if (tag != null && tag is vCardRoot)
AddControl(tag as vCardRoot);
}
private void btnAddExtraText_Click(object sender, EventArgs e)
{
Button btnSender = (Button)sender;
@@ -71,35 +71,31 @@ namespace vCardEditor.View.Customs
default:
break;
}
}
public void AddControl(vCardRoot card)
{
Point pt = GetCoordinatesForNewControl();
RemovableTextBox ctl = new RemovableTextBox(card);
ctl.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Left;
ctl.Location = pt;
ctl.Width = PanelContent.Width - 20; //TODO : Calculte the right size of the scrollbar!
RemovableTextBox ctl = new RemovableTextBox(card)
{
Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Left,
Location = pt,
Width = PanelContent.Width - 20 //TODO : Calculte the right size of the scrollbar!
};
ctl.BoutonRemoveClicked += RemoveControl;
ctl.ButtonRemoveClicked += RemoveControl;
ctl.ContentTextChanged += (s, e) => ContentTextChanged?.Invoke(s, e);
PanelContent.Controls.Add(ctl);
}
public List<vCardRoot> GetExtraFields()
{
List<vCardRoot> result = new List<vCardRoot>();
foreach (var item in PanelContent.Controls)
foreach (Control item in PanelContent.Controls)
{
var ctl = item as RemovableTextBox;
result.Add(ctl.Tag as vCardRoot);
result.Add((item as RemovableTextBox).Tag as vCardRoot);
}
return result;
@@ -113,40 +109,28 @@ namespace vCardEditor.View.Customs
private void RemoveControl(object sender, EventArgs e)
{
var par = (sender as Control).Parent;
PanelContent.Controls.Remove(par);
ReplaceControls();
}
private void ReplaceControls()
{
for (int i = 0; i < PanelContent.Controls.Count; i++)
if (MessageBox.Show("Are you sure?", "Question", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
var ctl = PanelContent.Controls[i];
ctl.Location = new Point(5, (i * 30) + 10);
PanelContent.Controls.Remove((sender as Control).Parent);
for (int i = 0; i < PanelContent.Controls.Count; i++)
{
PanelContent.Controls[i].Location = new Point(5, (i * 30) + 10);
}
CardInfoRemoved?.Invoke(sender, e);
}
}
private Point GetCoordinatesForNewControl()
{
Point pt;
if (PanelContent.Controls.Count > 0)
{
var LastControl = PanelContent.Controls[PanelContent.Controls.Count - 1];
pt = LastControl.Location;
pt = PanelContent.Controls[PanelContent.Controls.Count - 1].Location;
pt.Y += 30;
}
else
pt = new Point(5, 10);
return pt;
}
}
}

View File

@@ -6,12 +6,13 @@ namespace vCardEditor.View.Customs
{
public partial class RemovableTextBox : UserControl
{
public event EventHandler BoutonRemoveClicked;
public event EventHandler ButtonRemoveClicked;
public event EventHandler ContentTextChanged;
public RemovableTextBox()
{
InitializeComponent();
btnRemove.Click += (s, e) => BoutonRemoveClicked?.Invoke(s, e);
btnRemove.Click += (s, e) => ButtonRemoveClicked?.Invoke(s, e);
// Bubble up to set the dirty flag from the parent.
ContentTextBox.LostFocus += (s, e) => ContentTextChanged?.Invoke(s, e);
ContentTextBox.Validated += (s, e) => ContentTextChanged?.Invoke(s, e);
@@ -22,7 +23,7 @@ namespace vCardEditor.View.Customs
private void ContentTextBox_Validated(object sender, EventArgs e)
{
var card = this.Tag as vCardRoot;
vCardRoot card = this.Tag as vCardRoot;
card.ChangeContent(Content);
}
@@ -33,7 +34,6 @@ namespace vCardEditor.View.Customs
Content = cardType.ToString();
}
public string Title
{
get { return TitleLabel.Text; }
@@ -45,6 +45,5 @@ namespace vCardEditor.View.Customs
get { return ContentTextBox.Text; }
set { ContentTextBox.Text = value; }
}
}
}

View File

@@ -30,14 +30,18 @@ namespace VCFEditor.View
event EventHandler CountImagesEvent;
event EventHandler ClearImagesEvent;
event EventHandler BatchExportImagesEvent;
event EventHandler<EventArg<string>> OpenFolderEvent;
event EventHandler SplitFileEvent;
event EventHandler CardInfoRemoved;
int SelectedContactIndex { get; }
void DisplayContacts(SortableBindingList<Contact> contacts);
void DisplayContactDetail(vCard card, string FileName);
void ClearContactDetail();
bool AskMessage(string msg, string caption);
void DisplayMessage(string msg, string caption);
string DisplayOpenDialog(string filter);
string DisplaySaveDialog(string filename);
string DisplayOpenFileDialog(string filter);
string DisplaySaveDialog();
void UpdateMRUMenu(FixedList MRUList);
void SendTextToClipBoard(string text);
@@ -48,5 +52,8 @@ namespace VCFEditor.View
void DisplayQRCode(string content);
void ClearImageFromForm();
string DisplayOpenFolderDialog();
void LoadLocalizedUI(IReadOnlyDictionary<string, string> currentMessages);
void LoadAvailablesLangs(IEnumerable<string> availableLanguages);
}
}

View File

@@ -32,7 +32,7 @@ namespace vCardEditor.View
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.miSave = new System.Windows.Forms.ToolStripMenuItem();
@@ -56,8 +56,8 @@ namespace vCardEditor.View
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.tbsNew = new System.Windows.Forms.ToolStripButton();
this.tbsOpen = new System.Windows.Forms.ToolStripButton();
this.tbsSave = new System.Windows.Forms.ToolStripButton();
this.tbsOpen = new System.Windows.Forms.ToolStripSplitButton();
this.openFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.tbsDelete = new System.Windows.Forms.ToolStripButton();
this.tbsQR = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
@@ -104,6 +104,8 @@ namespace vCardEditor.View
this.menuExtraField = new System.Windows.Forms.ContextMenuStrip(this.components);
this.miNote = new System.Windows.Forms.ToolStripMenuItem();
this.miOrg = new System.Windows.Forms.ToolStripMenuItem();
this.tbsSave = new System.Windows.Forms.ToolStripSplitButton();
this.splitToFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.gbNameList.SuspendLayout();
@@ -248,27 +250,27 @@ namespace vCardEditor.View
this.clearToolStripMenuItem,
this.countToolStripMenuItem});
this.imagesToolStripMenuItem.Name = "imagesToolStripMenuItem";
this.imagesToolStripMenuItem.Size = new System.Drawing.Size(224, 26);
this.imagesToolStripMenuItem.Size = new System.Drawing.Size(140, 26);
this.imagesToolStripMenuItem.Text = "Images";
//
// exportToolStripMenuItem
//
this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
this.exportToolStripMenuItem.Size = new System.Drawing.Size(224, 26);
this.exportToolStripMenuItem.Size = new System.Drawing.Size(135, 26);
this.exportToolStripMenuItem.Text = "Export";
this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click);
//
// clearToolStripMenuItem
//
this.clearToolStripMenuItem.Name = "clearToolStripMenuItem";
this.clearToolStripMenuItem.Size = new System.Drawing.Size(224, 26);
this.clearToolStripMenuItem.Size = new System.Drawing.Size(135, 26);
this.clearToolStripMenuItem.Text = "Clear";
this.clearToolStripMenuItem.Click += new System.EventHandler(this.clearToolStripMenuItem_Click);
//
// countToolStripMenuItem
//
this.countToolStripMenuItem.Name = "countToolStripMenuItem";
this.countToolStripMenuItem.Size = new System.Drawing.Size(224, 26);
this.countToolStripMenuItem.Size = new System.Drawing.Size(135, 26);
this.countToolStripMenuItem.Text = "Count";
this.countToolStripMenuItem.Click += new System.EventHandler(this.countToolStripMenuItem_Click);
//
@@ -330,22 +332,21 @@ namespace vCardEditor.View
// tbsOpen
//
this.tbsOpen.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsOpen.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openFolderToolStripMenuItem});
this.tbsOpen.Image = ((System.Drawing.Image)(resources.GetObject("tbsOpen.Image")));
this.tbsOpen.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsOpen.Name = "tbsOpen";
this.tbsOpen.Size = new System.Drawing.Size(29, 24);
this.tbsOpen.Size = new System.Drawing.Size(39, 24);
this.tbsOpen.Text = "&Open";
this.tbsOpen.Click += new System.EventHandler(this.tbsOpen_Click);
this.tbsOpen.ButtonClick += new System.EventHandler(this.tbsOpen_Click);
//
// tbsSave
// openFolderToolStripMenuItem
//
this.tbsSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsSave.Image = ((System.Drawing.Image)(resources.GetObject("tbsSave.Image")));
this.tbsSave.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsSave.Name = "tbsSave";
this.tbsSave.Size = new System.Drawing.Size(29, 24);
this.tbsSave.Text = "&Save";
this.tbsSave.Click += new System.EventHandler(this.tbsSave_Click);
this.openFolderToolStripMenuItem.Name = "openFolderToolStripMenuItem";
this.openFolderToolStripMenuItem.Size = new System.Drawing.Size(174, 26);
this.openFolderToolStripMenuItem.Text = "Open Folder";
this.openFolderToolStripMenuItem.Click += new System.EventHandler(this.openFolderToolStripMenuItem_Click);
//
// tbsDelete
//
@@ -412,8 +413,8 @@ namespace vCardEditor.View
this.dgContacts.AllowUserToAddRows = false;
this.dgContacts.AllowUserToDeleteRows = false;
this.dgContacts.AllowUserToResizeRows = false;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.dgContacts.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
dataGridViewCellStyle2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.dgContacts.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle2;
this.dgContacts.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)));
@@ -861,6 +862,25 @@ namespace vCardEditor.View
this.miOrg.Text = "Organisation";
this.miOrg.Click += new System.EventHandler(this.miOrg_Click);
//
// tbsSave
//
this.tbsSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.tbsSave.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.splitToFilesToolStripMenuItem});
this.tbsSave.Image = ((System.Drawing.Image)(resources.GetObject("tbsSave.Image")));
this.tbsSave.ImageTransparentColor = System.Drawing.Color.Magenta;
this.tbsSave.Name = "tbsSave";
this.tbsSave.Size = new System.Drawing.Size(39, 24);
this.tbsSave.Text = "&Save";
this.tbsSave.ButtonClick += new System.EventHandler(this.tbsSave_Click);
//
// splitToFilesToolStripMenuItem
//
this.splitToFilesToolStripMenuItem.Name = "splitToFilesToolStripMenuItem";
this.splitToFilesToolStripMenuItem.Size = new System.Drawing.Size(224, 26);
this.splitToFilesToolStripMenuItem.Text = "Split to files";
this.splitToFilesToolStripMenuItem.Click += new System.EventHandler(this.splitToFilesToolStripMenuItem_Click);
//
// MainForm
//
this.AllowDrop = true;
@@ -919,8 +939,6 @@ namespace vCardEditor.View
private System.Windows.Forms.ToolStripMenuItem miAbout;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton tbsOpen;
private System.Windows.Forms.ToolStripButton tbsSave;
private System.Windows.Forms.ToolStripButton tbsDelete;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripButton tbsAbout;
@@ -981,5 +999,9 @@ namespace vCardEditor.View
private System.Windows.Forms.ToolStripMenuItem miOrg;
private ExtendedPanel extendedPanelWeb;
private ExtendedPanel extendedPanelPhones;
private System.Windows.Forms.ToolStripSplitButton tbsOpen;
private System.Windows.Forms.ToolStripMenuItem openFolderToolStripMenuItem;
private System.Windows.Forms.ToolStripSplitButton tbsSave;
private System.Windows.Forms.ToolStripMenuItem splitToFilesToolStripMenuItem;
}
}

View File

@@ -1,16 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using VCFEditor.View;
using VCFEditor.Model;
using Thought.vCards;
using vCardEditor.Repository;
using vCardEditor.Model;
using System.Drawing;
using System.Collections.Generic;
using vCardEditor.Repository;
using vCardEditor.View.Customs;
using vCardEditor.View.UIToolbox;
using VCFEditor.Model;
using VCFEditor.View;
namespace vCardEditor.View
{
@@ -37,8 +37,9 @@ namespace vCardEditor.View
public event EventHandler CountImagesEvent;
public event EventHandler ClearImagesEvent;
public event EventHandler BatchExportImagesEvent;
public event EventHandler<EventArg<string>> OpenFolderEvent;
public event EventHandler SplitFileEvent;
public event EventHandler CardInfoRemoved;
ComponentResourceManager resources;
@@ -53,25 +54,26 @@ namespace vCardEditor.View
else
return -1;
}
}
public MainForm()
{
InitializeComponent();
resources = new ComponentResourceManager(typeof(MainForm));
tbcAddress.AddTab += (sender, e) => AddressAdded?.Invoke(sender, e);
tbcAddress.RemoveTab += (sender, e) => AddressRemoved?.Invoke(sender, e);
tbcAddress.ModifyTab += (sender, e) => AddressModified?.Invoke(sender, e);
tbcAddress.TextChangedEvent += (sender, e) => TextBoxValueChanged?.Invoke(sender, e);
btnClearFilter.Click += (sender, e) => textBoxFilter.Clear();
extendedPanelPhones.ContentTextChanged += (sender, e) => TextBoxValueChanged?.Invoke(sender, e);
extendedPanelWeb.ContentTextChanged += (sender, e) => TextBoxValueChanged?.Invoke(sender, e);
BuildMRUMenu();
extendedPanelPhones.CardInfoRemoved += (sender, e) => CardInfoRemoved?.Invoke(sender, e);
extendedPanelWeb.CardInfoRemoved += (sender, e) => CardInfoRemoved?.Invoke(sender, e);
BuildMRUMenu();
}
private void tbsOpen_Click(object sender, EventArgs e)
@@ -79,7 +81,6 @@ namespace vCardEditor.View
OpenFile(sender, string.Empty);
}
private void OpenFile(object sender, string filename)
{
var evt = new EventArg<string>(filename);
@@ -92,13 +93,16 @@ namespace vCardEditor.View
public void DisplayContacts(SortableBindingList<Contact> contacts)
{
bsContacts.DataSource = null;
if (contacts != null)
bsContacts.DataSource = contacts;
}
private void tbsSave_Click(object sender, EventArgs e)
{
if (dgContacts.RowCount == 0)
return;
if (SaveContactsSelected != null)
{
//make sure the last changes in the textboxes is saved.
@@ -109,7 +113,6 @@ namespace vCardEditor.View
SaveContactsSelected(sender, e);
}
}
private void tbsNew_Click(object sender, EventArgs e)
@@ -122,12 +125,10 @@ namespace vCardEditor.View
if (dgContacts.CurrentCell == null)
return;
//Weired, the selection is fired multiple times...
int RowIndex = dgContacts.CurrentCell.RowIndex;
if (LastRowIndex != RowIndex)
{
if (ChangeContactsSelected != null && dgContacts.CurrentCell != null)
{
vCard data = GetvCardFromWindow();
@@ -147,13 +148,12 @@ namespace vCardEditor.View
public void DisplayContactDetail(vCard card, string FileName)
{
if (card == null)
throw new ArgumentException("vCard must be valid!");
ClearContactDetail();
Text = string.Format("{0} - vCard Editor", FileName);
Text = string.Format("{0} - vCard Editor", FileName ?? "New file");
tcMainTab.Enabled = true;
gbNameList.Enabled = true;
@@ -169,50 +169,46 @@ namespace vCardEditor.View
SetExtraInfos(card);
SetExtraTabFields(card);
}
private void SetExtraInfos(vCard card)
{
foreach (var item in card.EmailAddresses)
extendedPanelWeb.AddControl(item);
foreach (var item in card.Websites)
extendedPanelWeb.AddControl(item);
foreach (var item in card.Phones)
foreach (vCardPhone item in card.Phones)
extendedPanelPhones.AddControl(item);
foreach (vCardEmailAddress item in card.EmailAddresses)
extendedPanelWeb.AddControl(item);
foreach (vCardWebsite item in card.Websites)
extendedPanelWeb.AddControl(item);
}
private void SetExtraTabFields(vCard card)
{
foreach (var note in card.Notes)
foreach (vCardNote note in card.Notes)
AddExtraTextGroup(vCardPropeties.NOTE, note.Text);
if (!string.IsNullOrEmpty(card.Organization))
{
AddExtraTextGroup(vCardPropeties.ORG, card.Organization);
}
}
public void AddExtraTextGroup(vCardPropeties type, string content)
{
ExtraTextGroup etg = new ExtraTextGroup();
etg.Content = content;
etg.Caption = type.ToString() + " :";
etg.CardProp = type;
ExtraTextGroup etg = new ExtraTextGroup
{
Content = content,
Caption = type.ToString() + ":",
CardProp = type,
Dock = DockStyle.Top
};
etg.TextChangedEvent += (sender, e) => TextBoxValueChanged?.Invoke(sender, e);
etg.ControlDeleted += (sender, e) =>
{
var send = sender as Control;
panelTabExtra.Controls.Remove(send.Parent);
if (AskMessage("Are you sure?", "Question"))
panelTabExtra.Controls.Remove((sender as Control).Parent);
};
etg.Dock = DockStyle.Top;
panelTabExtra.Controls.Add(etg);
}
@@ -248,7 +244,7 @@ namespace vCardEditor.View
{
if (photos.Any())
{
var photo = photos[0];
vCardPhoto photo = photos[0];
try
{
// Get the bytes of the photo if it has not already been loaded.
@@ -265,8 +261,8 @@ namespace vCardEditor.View
}
else
PhotoBox.Image = (Image)resources.GetObject("PhotoBox.Image");
}
private void SetAddressesValues(vCard card)
{
tbcAddress.SetAddresses(card);
@@ -299,32 +295,29 @@ namespace vCardEditor.View
textBoxFilter.Focus();
}
private vCard GetvCardFromWindow()
{
vCard card = new vCard
{
Title = FormattedTitleValue.Text,
FormattedName = FormattedNameValue.Text,
GivenName = firstNameValue.Text,
AdditionalNames = middleNameValue.Text,
FamilyName = lastNameValue.Text,
};
tbcAddress.getDeliveryAddress(card);
getExtraPhones(card);
getExtraWeb(card);
getExtraData(card);
return card;
}
private void getExtraPhones(vCard card)
{
card.Phones.Clear();
foreach (var item in extendedPanelPhones.GetExtraFields())
foreach (vCardRoot item in extendedPanelPhones.GetExtraFields())
{
if (item is vCardPhone)
{
@@ -332,40 +325,34 @@ namespace vCardEditor.View
card.Phones.Add(phone);
}
}
}
private void getExtraWeb(vCard card)
{
card.Websites.Clear();
card.EmailAddresses.Clear();
foreach (var item in extendedPanelWeb.GetExtraFields())
foreach (vCardRoot item in extendedPanelWeb.GetExtraFields())
{
switch (item)
{
case vCardEmailAddress email:
card.EmailAddresses.Add(email);
break;
case vCardWebsite website:
card.Websites.Add(website);
break;
default:
break;
}
}
}
private void getExtraData(vCard card)
{
foreach (var item in panelTabExtra.Controls)
foreach (object item in panelTabExtra.Controls)
{
var tbc = item as ExtraTextGroup;
ExtraTextGroup tbc = item as ExtraTextGroup;
switch (tbc.CardProp)
{
case vCardPropeties.NOTE:
@@ -391,12 +378,12 @@ namespace vCardEditor.View
Close();
}
private void MainForm_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
private void MainForm_DragDrop(object sender, DragEventArgs e)
{
string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false);
@@ -409,13 +396,11 @@ namespace vCardEditor.View
OpenFile(sender, FileList[0]);
}
private void BuildMRUMenu()
{
//TODO: Open File or Folder.
recentFilesMenuItem.DropDownItemClicked += (s, e) => OpenFile(s, e.ClickedItem.Text);
UpdateMRUMenu(ConfigRepository.Instance.Paths);
}
public void UpdateMRUMenu(FixedList MostRecentFilesList)
@@ -426,7 +411,6 @@ namespace vCardEditor.View
recentFilesMenuItem.DropDownItems.Clear();
for (int i = 0; i < MostRecentFilesList._innerList.Count; i++)
recentFilesMenuItem.DropDownItems.Add(MostRecentFilesList[i]);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
@@ -435,19 +419,12 @@ namespace vCardEditor.View
CloseForm?.Invoke(sender, evt);
e.Cancel = evt.Data;
}
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;
return window == DialogResult.Yes;
}
private void miConfig_Click(object sender, EventArgs e)
@@ -459,7 +436,8 @@ namespace vCardEditor.View
{
MessageBox.Show(msg, caption);
}
public string DisplayOpenDialog(string filter = "")
public string DisplayOpenFileDialog(string filter = "")
{
string filename = string.Empty;
openFileDialog.Filter = filter;
@@ -471,25 +449,29 @@ namespace vCardEditor.View
return filename;
}
public string DisplaySaveDialog(string filename)
public string DisplaySaveDialog()
{
var saveFileDialog = new SaveFileDialog
SaveFileDialog saveFileDialog = new SaveFileDialog
{
FileName = filename
Title = "Save vCard file",
Filter = "Virtual Contact File|*.vcf"
};
string filename = null;
DialogResult result = saveFileDialog.ShowDialog();
if (result == DialogResult.OK)
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
filename = saveFileDialog.FileName;
Text = string.Format("{0} - vCard Editor", filename);
}
return filename;
}
private void PhotoBox_Click(object sender, EventArgs e)
{
if (ModifyImage != null)
{
var fileName = DisplayOpenDialog();
string fileName = DisplayOpenFileDialog();
if (!string.IsNullOrEmpty(fileName))
{
try
@@ -502,11 +484,8 @@ namespace vCardEditor.View
{
MessageBox.Show($"Invalid file! : {fileName}");
}
}
}
}
public void ClearImageFromForm()
@@ -536,26 +515,23 @@ namespace vCardEditor.View
Clipboard.SetText(text);
}
private void dgContacts_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
{
if (e.RowIndex == -1)
{
e.ContextMenuStrip = contextMenuStrip1;
}
}
private void modifiyColumnsToolStripMenuItem_Click(object sender, EventArgs e)
{
List<Column> Columns = GetListColumnsForDataGrid();
var dialog = new ColumnsDialog(Columns);
ColumnsDialog dialog = new ColumnsDialog(Columns);
if (dialog.ShowDialog() == DialogResult.OK)
{
ToggleAllColumnsToInvisible();
ToggleOnlySelected(dialog.Columns);
}
}
@@ -566,19 +542,17 @@ namespace vCardEditor.View
{
if (dgContacts.Columns[i].Visible)
{
var name = dgContacts.Columns[i].Name;
var enumType = (Column)Enum.Parse(typeof(Column), name, true);
string name = dgContacts.Columns[i].Name;
Column enumType = (Column)Enum.Parse(typeof(Column), name, true);
Columns.Add(enumType);
}
}
return Columns;
}
private void ToggleOnlySelected(List<Column> columns)
{
foreach (var item in columns)
foreach (Column item in columns)
{
switch (item)
{
@@ -602,7 +576,6 @@ namespace vCardEditor.View
public FormState GetFormState()
{
return new FormState
{
Columns = GetListColumnsForDataGrid(),
@@ -618,7 +591,6 @@ namespace vCardEditor.View
{
var evt = new EventArg<FormState>(new FormState());
LoadForm?.Invoke(sender, evt);
}
public void LoadIntialState(FormState state)
@@ -634,6 +606,7 @@ namespace vCardEditor.View
}
}
}
private void tbsQR_Click(object sender, EventArgs e)
{
ExportQR?.Invoke(sender, e);
@@ -645,7 +618,6 @@ namespace vCardEditor.View
qr.ShowDialog();
}
private void addNotesToolStripMenuItem_Click(object sender, EventArgs e)
{
var evt = new EventArg<vCardPropeties>(vCardPropeties.NOTE);
@@ -666,7 +638,6 @@ namespace vCardEditor.View
menuExtraField.Show(ptLowerLeft);
}
private void miNote_Click(object sender, EventArgs e)
{
var evt = new EventArg<vCardPropeties>(vCardPropeties.NOTE);
@@ -703,5 +674,37 @@ namespace vCardEditor.View
{
BatchExportImagesEvent?.Invoke(sender, e);
}
private void openFolderToolStripMenuItem_Click(object sender, EventArgs e)
{
var evt = new EventArg<string>(string.Empty);
OpenFolderEvent?.Invoke(sender, evt);
}
private void splitToFilesToolStripMenuItem_Click(object sender, EventArgs e)
{
SplitFileEvent?.Invoke(sender, e);
}
public string DisplayOpenFolderDialog()
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
return dialog.SelectedPath;
return string.Empty;
}
public void LoadLocalizedUI(IReadOnlyDictionary<string, string> currentMessages)
{
//this.fileToolStripMenuItem.Text = currentMessages["MSG_002"];
}
public void LoadAvailablesLangs(IEnumerable<string> availableLanguages)
{
foreach (string lang in availableLanguages)
{
}
}
}
}

View File

@@ -29,8 +29,6 @@ namespace vCardEditor.View
pictureBoxQRCode.BackgroundImage = qrCode.GetGraphic(20, Color.Black, Color.White, null, 1);
pictureBoxQRCode.Size = new Size(pictureBoxQRCode.Width, pictureBoxQRCode.Height);
pictureBoxQRCode.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
@@ -61,30 +59,27 @@ namespace vCardEditor.View
}
else
{
using (FileStream fs = (System.IO.FileStream)saveFileDialog1.OpenFile())
using (FileStream fs = (FileStream)saveFileDialog1.OpenFile())
{
ImageFormat imageFormat = null;
switch (saveFileDialog1.FilterIndex)
{
case 1:
imageFormat = ImageFormat.Bmp;
break;
case 2:
imageFormat = ImageFormat.Png;
break;
case 3:
imageFormat = ImageFormat.Jpeg;
break;
case 4:
imageFormat = ImageFormat.Gif;
break;
default:
throw new NotSupportedException("File extension is not supported");
}
pictureBoxQRCode.BackgroundImage.Save(fs, imageFormat);
ImageFormat imageFormat = null;
switch (saveFileDialog1.FilterIndex)
{
case 1:
imageFormat = ImageFormat.Bmp;
break;
case 2:
imageFormat = ImageFormat.Png;
break;
case 3:
imageFormat = ImageFormat.Jpeg;
break;
case 4:
imageFormat = ImageFormat.Gif;
break;
default:
throw new NotSupportedException("File extension is not supported");
}
pictureBoxQRCode.BackgroundImage.Save(fs, imageFormat);
}
}
}

View File

@@ -95,5 +95,33 @@ namespace vCardEditor.View
return -1;
}
//https://stackoverflow.com/questions/43331145/how-can-i-improve-performance-of-an-addrange-method-on-a-custom-bindinglist
public void AddRange(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException(nameof(collection));
// Remember the current setting for RaiseListChangedEvents
// (if it was already deactivated, we shouldn't activate it after adding!).
bool oldRaiseEventsValue = RaiseListChangedEvents;
try
{
RaiseListChangedEvents = false;
foreach (var value in collection)
Add(value);
}
// Restore the old setting for RaiseListChangedEvents (even if there was an exception),
// and fire the ListChanged-event once (if RaiseListChangedEvents is activated).
finally
{
RaiseListChangedEvents = oldRaiseEventsValue;
if (RaiseListChangedEvents)
ResetBindings();
}
}
}
}

View File

@@ -0,0 +1,19 @@
{
"version": "1.0",
"languages": {
"en": {
"name": "English",
"messages": {
"MSG_001": "Save current file before?",
"MSG_002": "File"
}
},
"fr": {
"name": "Français",
"messages": {
"MSG_001": "Sauvegarder le fichier en cours",
"MSG_002": "Fichier"
}
}
}
}

View File

@@ -57,6 +57,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
@@ -66,6 +67,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ILocalizationProvider.cs" />
<Compile Include="JsonLocalizationProvider.cs" />
<Compile Include="Libs\QRCoder\AbstractQRCode.cs" />
<Compile Include="Libs\QRCoder\ArtQRCode.cs" />
<Compile Include="Libs\QRCoder\ASCIIQRCode.cs" />
@@ -83,6 +86,11 @@
<Compile Include="Libs\QRCoder\QRCodeData.cs" />
<Compile Include="Libs\QRCoder\QRCodeGenerator.cs" />
<Compile Include="Libs\QRCoder\SvgQRCode.cs" />
<Compile Include="Libs\TinyJson\IParser.cs" />
<Compile Include="Libs\TinyJson\JSONParser.cs" />
<Compile Include="Libs\TinyJson\LocalizationFile.cs" />
<Compile Include="Libs\TinyJson\LocalizationLoader.cs" />
<Compile Include="Libs\TinyJson\TinyJsonParser.cs" />
<Compile Include="Model\vCardPropeties.cs" />
<Compile Include="Model\Column.cs" />
<Compile Include="Model\FixedList.cs" />
@@ -176,11 +184,11 @@
<Compile Include="View\Customs\ColumnsDialog.Designer.cs">
<DependentUpon>ColumnsDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\Customs\CustumInputDialog.cs">
<Compile Include="View\Customs\CustomInputDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\Customs\CustumInputDialog.Designer.cs">
<DependentUpon>CustumInputDialog.cs</DependentUpon>
<Compile Include="View\Customs\CustomInputDialog.Designer.cs">
<DependentUpon>CustomInputDialog.cs</DependentUpon>
</Compile>
<Compile Include="View\Customs\ExtendedPanel.cs">
<SubType>UserControl</SubType>
@@ -244,8 +252,8 @@
<EmbeddedResource Include="View\Customs\ColumnsDialog.resx">
<DependentUpon>ColumnsDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\Customs\CustumInputDialog.resx">
<DependentUpon>CustumInputDialog.cs</DependentUpon>
<EmbeddedResource Include="View\Customs\CustomInputDialog.resx">
<DependentUpon>CustomInputDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="View\Customs\ExtendedPanel.resx">
<DependentUpon>ExtendedPanel.cs</DependentUpon>
@@ -263,6 +271,7 @@
<DependentUpon>QRDialog.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.config" />
<EmbeddedResource Include="i18n\lang.json" />
<None Include="Libs\QRCoder\Assets\nuget-readme.md" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>

View File

@@ -178,8 +178,7 @@ namespace vCardEditor_Test
repo.AddEmptyContact();
Assert.IsTrue(repo.Contacts.Count == 0);
Assert.IsTrue(repo.Contacts.Count == 1);
}
}
}

View File

@@ -0,0 +1,69 @@
namespace vCardEditor_Test
{
public class JsonEntries
{
public static string[] JsonEmtpy
{
get
{
return "".Split('\n');
}
}
public static string[] JsonIncorrect
{
get
{
return "abcdef".Split('\n');
}
}
public static string JsonValid
{
get
{
return @"{
""version"": ""1.0"",
""languages"": {
""en"": {
""name"": ""English"",
""messages"": {
""MSG_001"": ""Save current file before?"",
""MSG_002"": ""File""
}
},
""fr"": {
""name"": ""Français"",
""messages"": {
""MSG_001"": ""Sauvegarder le fichier en cours"",
""MSG_002"": ""Fichier""
}
}
}
}";
}
}
public static string InvalidJsonValid
{
get
{
return @"{
""version"": ""1.0"",
""languages"": {
""en"": {
""name"": ""English"",
""messages"": {
""MSG_001"": ""Save current file before?"",
""MSG_002"": ""File""
_002"": ""Fichier""
}
}
}
}";
}
}
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using System;
using vCardEditor.Libs.TinyJson;
using vCardEditor.Repository;
namespace vCardEditor_Test
{
[TestClass]
public class JsonLocalizationProviderTest
{
[TestMethod]
public void CorrectJsonLoaded_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.LoadJsonFromAssembly(Arg.Any<string>()).Returns(JsonEntries.JsonValid);
var JsonParser = new TinyJsonParser();
var embeddedlang = new LocalizationLoader(JsonParser, fileHandler).LoadEmbedded();
Assert.IsTrue(embeddedlang.version == "1.0", "Json version incorrect");
Assert.IsTrue(embeddedlang.languages.Count == 2, "Number of json entries invalid");
}
}
}

View File

@@ -0,0 +1,38 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using vCardEditor.Libs.TinyJson;
using vCardEditor.Repository;
namespace vCardEditor_Test
{
[TestClass]
public class LocalizationLoaderTest
{
[TestMethod]
public void CorrectJsonLoaded_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.LoadJsonFromAssembly(Arg.Any<string>()).Returns(JsonEntries.JsonValid);
var JsonParser = new TinyJsonParser();
var embeddedlang = new LocalizationLoader(JsonParser, fileHandler).LoadEmbedded();
Assert.IsTrue(embeddedlang.version == "1.0", "Json version incorrect");
Assert.IsTrue(embeddedlang.languages.Count == 2, "Number of json entries invalid");
}
[TestMethod]
public void IncorrectJsonLoaded_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.LoadJsonFromAssembly(Arg.Any<string>()).Returns(JsonEntries.InvalidJsonValid);
var JsonParser = new TinyJsonParser();
var embeddedlang = new LocalizationLoader(JsonParser, fileHandler).LoadEmbedded();
Assert.IsTrue(embeddedlang.version == "1.0", "Json version incorrect");
}
}
}

View File

@@ -10,6 +10,7 @@ using System;
using AutoFixture;
using Thought.vCards;
using System.Collections.Generic;
using vCardEditor;
namespace vCardEditor_Test
{
@@ -24,7 +25,8 @@ namespace vCardEditor_Test
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfOneEntry);
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.aaa"));
view.Received().DisplayMessage(Arg.Any<string>(), Arg.Any<string>());
@@ -42,8 +44,10 @@ namespace vCardEditor_Test
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.vcf"));
view.Received().DisplayContacts(Arg.Is<SortableBindingList<Contact>>(x=>x.Count == 1));
@@ -64,10 +68,12 @@ namespace vCardEditor_Test
var view = Substitute.For<IMainView>();
view.AskMessage(Arg.Any<string>(), Arg.Any<string>()).Returns(true);
var presenter = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename.vcf"));
repo.Contacts[1].isDirty = true;
fileHandler.FileExist(Arg.Any<string>()).Returns(false);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("filename2.vcf"));
view.Received().AskMessage(Arg.Any<string>(), Arg.Any<string>());
@@ -84,7 +90,9 @@ namespace vCardEditor_Test
var view = Substitute.For<IMainView>();
var presenter = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
view.SaveContactsSelected += Raise.Event();
@@ -105,7 +113,9 @@ namespace vCardEditor_Test
var view = Substitute.For<IMainView>();
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
view.SaveContactsSelected += Raise.Event();
@@ -123,8 +133,10 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.GetExtension(Arg.Any<string>()).Returns(".vcf");
var view = Substitute.For<IMainView>();
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.NewFileOpened += Raise.EventWith(new EventArg<string>("aaa.vcf"));
//Mouse click on second row.
@@ -148,7 +160,10 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
repo.LoadContacts("aaa.vcf");
view.CopyTextToClipboardEvent += Raise.Event();
@@ -167,7 +182,9 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
var contact = repo.LoadContacts("aaa.vcf");
view.AddressRemoved += Raise.EventWith(new EventArg<int>(0));
@@ -186,7 +203,9 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
var contact = repo.LoadContacts("aaa.vcf");
var fixture = new Fixture { RepeatCount = 2 };
@@ -210,7 +229,9 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
var contact = repo.LoadContacts("aaa.vcf");
var fixture = new Fixture { RepeatCount = 2 };
@@ -232,7 +253,8 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
_ = repo.LoadContacts("aaa.vcf");
view.ExportImage += Raise.Event();
@@ -250,7 +272,8 @@ namespace vCardEditor_Test
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
view.SelectedContactIndex.Returns(0);
_ = new MainPresenter(view, repo);
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
var contact = repo.LoadContacts("aaa.vcf");
view.ModifyImage += Raise.EventWith(new EventArg<string>(""));
@@ -259,6 +282,44 @@ namespace vCardEditor_Test
Assert.IsTrue(repo.Contacts[0].isDirty);
}
[TestMethod]
public void AddContact_ShouldCreateEmtptyContactFile_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
var repo = Substitute.For<ContactRepository>(fileHandler);
var view = Substitute.For<IMainView>();
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.AddContact += Raise.Event();
view.Received().DisplayContacts(Arg.Any<SortableBindingList<Contact>>());
Assert.IsTrue(repo.Contacts.Count == 1);
}
[TestMethod]
public void SaveSplittedFile_ShouldCall3TimesFileSaving_Test()
{
var fileHandler = Substitute.For<IFileHandler>();
fileHandler.ReadAllLines(Arg.Any<string>()).Returns(Entries.vcfFourEntry);
fileHandler.FileExist(Arg.Any<string>()).Returns(true);
var repo = Substitute.For<ContactRepository>(fileHandler);
repo.LoadContacts("aaa.vcf");
repo.Contacts[3].isDeleted = true;
var view = Substitute.For<IMainView>();
view.DisplayOpenFolderDialog().Returns("aaa");
var localization = Substitute.For<ILocalizationProvider>();
_ = new MainPresenter(view, repo, localization);
view.SplitFileEvent += Raise.Event();
//Should save only 3 files.
fileHandler.Received(3).WriteAllText(Arg.Any<string>(), Arg.Any<string>());
}
}
}

View File

@@ -77,10 +77,13 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ContactRepositoryTest.cs" />
<Compile Include="JsonEntries.cs" />
<Compile Include="Entries.cs" />
<Compile Include="FixedListTest.cs" />
<Compile Include="JsonLocalizationProviderTest.cs" />
<Compile Include="MainPresenterTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="LocalizationLoaderTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\vCardEditor\vCardEditor.csproj">