public void merge(string other_file) {
// create a backup, just in case something could go wrong
save_to(file_name_ + ".backup." + DateTime.Now.Ticks);
// set_aliases is_merged!
++ignore_change_;
var merge_from = adjust_guids_before_merge( load_settings_file(this, other_file));
// first, merge lines
foreach ( var new_line in merge_from.Item1)
if ( !lines_.ContainsKey(new_line.Key))
lines_.Add(new_line.Key, new_line.Value);
// now, merge notes
// Step 0: mark all new notes as merged
foreach (var new_note in merge_from.Item2)
if (new_note.the_note != null)
new_note.the_note.is_merged = true;
// Step 1: insert notes to what we already have here
// (replies to existing notes, and notes on lines that already have notes)
List<note_item> still_to_add = new List<note_item>();
foreach (var new_note in merge_from.Item2) {
var found_line = notes_sorted_by_line_index_.FirstOrDefault(x => x.line_id == new_note.line_id);
if (found_line == null) {
// it's a completely new line - we'll add it later
if ( new_note.the_note != null)
add_color_for_author(new_note.the_note.author_name, new_note.the_note.author_color);
still_to_add.Add(new_note);
continue;
}
if (!new_note.is_note_header) {
var found = notes_sorted_by_line_index_.FindIndex(x => x.note_id == new_note.note_id);
if (found != -1) {
// in this case, look at last_edited -> if bigger than ours, take that (someone else updated the entry after us)
Debug.Assert(notes_sorted_by_line_index_[found].line_id == new_note.line_id);
Debug.Assert(notes_sorted_by_line_index_[found].reply_id == new_note.reply_id);
if (new_note.utc_last_edited > notes_sorted_by_line_index_[found].utc_last_edited)
notes_sorted_by_line_index_[found] = new_note;
} else {
// it's a new note, just add it
// the way we keep the sorted lines (sorted by line index), we should never encounter a line with a reply pointing to an inexisting line
Debug.Assert(lines_.ContainsKey(new_note.line_id));
add_color_for_author(new_note.the_note.author_name, new_note.the_note.author_color);
add_note(lines_[new_note.line_id], new_note.the_note, new_note.note_id, new_note.reply_id, new_note.deleted, new_note.utc_last_edited);
}
} else {
// it's a note header - we already have it
}
}
// Step 2: insert notes to completely new lines
List<note_item> copy = notes_sorted_by_line_index_.ToList();
foreach (var n in still_to_add) {
var idx = copy.FindIndex(x => lines_[x.line_id].idx > lines_[n.line_id].idx);
if ( idx >= 0)
copy.Insert(idx, n);
else
copy.Add(n);
}
notes_sorted_by_line_index_ = copy;
dirty_ = false;
--ignore_change_;
// the reason we readd everything - the merged notes would end up being appended to the end, no matter what line they were appended to
// we want to show them sorted by line
readd_everything();
notesCtrl.Refresh();
save();
}