117
117
// Set up TreeViewColumns
118
118
Gtk.TreeViewColumn column = new Gtk.TreeViewColumn (
119
Catalog.GetString ("Note Title"),
120
new Gtk.CellRendererText (), "text", 0);
119
Catalog.GetString ("Note Title"),
120
new Gtk.CellRendererText (), "text", 0);
121
121
column.SortColumnId = 0;
122
122
column.Resizable = true;
123
123
treeView.AppendColumn (column);
125
125
column = new Gtk.TreeViewColumn (
126
Catalog.GetString ("Status"),
127
new Gtk.CellRendererText (), "text", 1);
126
Catalog.GetString ("Status"),
127
new Gtk.CellRendererText (), "text", 1);
128
128
column.SortColumnId = 1;
129
129
column.Resizable = true;
130
130
treeView.AppendColumn (column);
176
176
// TODO: Store GUID hidden in model; use instead of title
177
177
Gtk.TreeIter iter;
178
if (!model.GetIter (out iter, args.Path))
178
if (!model.GetIter (out iter, args.Path))
181
181
string noteTitle = (string) model.GetValue (iter, 0 /* note title */);
183
Note note = Tomboy.DefaultNoteManager.Find (noteTitle);
183
Note note = Tomboy.DefaultNoteManager.Find (noteTitle);
184
184
if (note != null)
185
185
note.Window.Present ();
188
188
public string HeaderText
191
191
headerLabel.Markup = string.Format (
192
"<span size=\"large\" weight=\"bold\">{0}</span>",
192
"<span size=\"large\" weight=\"bold\">{0}</span>",
197
197
public string MessageText
199
set { messageLabel.Text = value; }
200
messageLabel.Text = value;
202
204
public string ProgressText
204
get { return progressLabel.Text; }
207
return progressLabel.Text;
206
210
progressLabel.Markup =
207
string.Format ("<span style=\"italic\">{0}</span>",
211
string.Format ("<span style=\"italic\">{0}</span>",
212
216
public void AddUpdateItem (string title, string status)
214
218
model.AppendValues (title, status);
372
376
Exception mainThreadException = null;
373
377
Gtk.Application.Invoke (delegate {
375
SyncTitleConflictDialog conflictDlg =
379
SyncTitleConflictDialog conflictDlg =
376
380
new SyncTitleConflictDialog (localConflictNote, noteUpdateTitles);
377
Gtk.ResponseType reponse = Gtk.ResponseType.Ok;
379
bool noteSyncBitsMatch =
380
SyncManager.SynchronizedNoteXmlMatches (localConflictNote.GetCompleteNoteXml (),
381
remoteNote.XmlContent);
383
// If the synchronized note content is in conflict
384
// and there is no saved conflict handling behavior, show the dialog
385
if (!noteSyncBitsMatch && savedBehavior == 0)
386
reponse = (Gtk.ResponseType) conflictDlg.Run ();
389
if (reponse == Gtk.ResponseType.Cancel)
390
resolution = SyncTitleConflictResolution.Cancel;
392
if (noteSyncBitsMatch)
393
resolution = SyncTitleConflictResolution.OverwriteExisting;
394
else if (savedBehavior == 0)
395
resolution = conflictDlg.Resolution;
397
resolution = savedBehavior;
399
switch (resolution) {
400
case SyncTitleConflictResolution.OverwriteExisting:
401
if (conflictDlg.AlwaysPerformThisAction)
402
savedBehavior = resolution;
403
// No need to delete if sync will overwrite
404
if (localConflictNote.Id != remoteNote.UUID)
405
manager.Delete (localConflictNote);
407
case SyncTitleConflictResolution.RenameExistingAndUpdate:
408
if (conflictDlg.AlwaysPerformThisAction)
409
savedBehavior = resolution;
410
RenameNote (localConflictNote, conflictDlg.RenamedTitle, true);
412
case SyncTitleConflictResolution.RenameExistingNoUpdate:
413
if (conflictDlg.AlwaysPerformThisAction)
414
savedBehavior = resolution;
415
RenameNote (localConflictNote, conflictDlg.RenamedTitle, false);
381
Gtk.ResponseType reponse = Gtk.ResponseType.Ok;
383
bool noteSyncBitsMatch =
384
SyncManager.SynchronizedNoteXmlMatches (localConflictNote.GetCompleteNoteXml (),
385
remoteNote.XmlContent);
387
// If the synchronized note content is in conflict
388
// and there is no saved conflict handling behavior, show the dialog
389
if (!noteSyncBitsMatch && savedBehavior == 0)
390
reponse = (Gtk.ResponseType) conflictDlg.Run ();
393
if (reponse == Gtk.ResponseType.Cancel)
394
resolution = SyncTitleConflictResolution.Cancel;
396
if (noteSyncBitsMatch)
397
resolution = SyncTitleConflictResolution.OverwriteExisting;
398
else if (savedBehavior == 0)
399
resolution = conflictDlg.Resolution;
401
resolution = savedBehavior;
403
switch (resolution) {
404
case SyncTitleConflictResolution.OverwriteExisting:
405
if (conflictDlg.AlwaysPerformThisAction)
406
savedBehavior = resolution;
407
// No need to delete if sync will overwrite
408
if (localConflictNote.Id != remoteNote.UUID)
409
manager.Delete (localConflictNote);
411
case SyncTitleConflictResolution.RenameExistingAndUpdate:
412
if (conflictDlg.AlwaysPerformThisAction)
413
savedBehavior = resolution;
414
RenameNote (localConflictNote, conflictDlg.RenamedTitle, true);
416
case SyncTitleConflictResolution.RenameExistingNoUpdate:
417
if (conflictDlg.AlwaysPerformThisAction)
418
savedBehavior = resolution;
419
RenameNote (localConflictNote, conflictDlg.RenamedTitle, false);
420
Preferences.Set (Preferences.SYNC_CONFIGURED_CONFLICT_BEHAVIOR,
421
(int) savedBehavior); // TODO: Clean up
424
conflictDlg.Destroy ();
426
// Let the SyncManager continue
427
SyncManager.ResolveConflict (/*localConflictNote, */resolution);
424
Preferences.Set (Preferences.SYNC_CONFIGURED_CONFLICT_BEHAVIOR,
425
(int) savedBehavior); // TODO: Clean up
428
conflictDlg.Destroy ();
430
// Let the SyncManager continue
431
SyncManager.ResolveConflict (/*localConflictNote, */resolution);
428
432
} catch (Exception e) {
429
433
mainThreadException = e;
453
457
note.Save (); // Write to file
454
458
bool noteOpen = note.IsOpened;
455
459
string newContent = //note.XmlContent;
456
NoteArchiver.Instance.GetRenamedNoteXml (note.XmlContent, oldTitle, newTitle);
460
NoteArchiver.Instance.GetRenamedNoteXml (note.XmlContent, oldTitle, newTitle);
457
461
string newCompleteContent = //note.GetCompleteNoteXml ();
458
NoteArchiver.Instance.GetRenamedNoteXml (note.GetCompleteNoteXml (), oldTitle, newTitle);
462
NoteArchiver.Instance.GetRenamedNoteXml (note.GetCompleteNoteXml (), oldTitle, newTitle);
459
463
//Logger.Debug ("RenameNote: newContent: " + newContent);
460
464
//Logger.Debug ("RenameNote: newCompleteContent: " + newCompleteContent);
462
466
// We delete and recreate the note to simplify content conflict handling
463
467
Tomboy.DefaultNoteManager.Delete (note);
465
469
// Create note with old XmlContent just in case GetCompleteNoteXml failed
466
470
Logger.Debug ("RenameNote: about to create " + newTitle);
467
471
Note renamedNote = Tomboy.DefaultNoteManager.Create (newTitle, newContent);
468
472
if (newCompleteContent != null) {// TODO: Anything to do if it is null?
470
474
renamedNote.LoadForeignNoteXml (newCompleteContent);
471
} catch {} // TODO: Handle exception in case that newCompleteContent is invalid XML
475
} catch {} // TODO: Handle exception in case that newCompleteContent is invalid XML
474
478
renamedNote.Window.Present ();
476
#endregion // Private Methods
480
#endregion // Private Methods
483
487
private Note existingNote;
484
488
private IList<string> noteUpdateTitles;
486
490
private Gtk.Button continueButton;
488
492
private Gtk.Entry renameEntry;
489
493
private Gtk.CheckButton renameUpdateCheck;
490
494
private Gtk.RadioButton renameRadio;
491
495
private Gtk.RadioButton deleteExistingRadio;
492
496
private Gtk.CheckButton alwaysDoThisCheck;
494
498
private Gtk.Label headerLabel;
495
499
private Gtk.Label messageLabel;
497
public SyncTitleConflictDialog (Note existingNote, IList<string> noteUpdateTitles) :
498
base (Catalog.GetString ("Note Conflict"), null, Gtk.DialogFlags.Modal)
501
public SyncTitleConflictDialog (Note existingNote, IList<string> noteUpdateTitles) :
502
base (Catalog.GetString ("Note Conflict"), null, Gtk.DialogFlags.Modal)
500
504
this.existingNote = existingNote;
501
505
this.noteUpdateTitles = noteUpdateTitles;
503
507
// Suggest renaming note by appending " (old)" to the existing title
504
508
string suggestedRenameBase = existingNote.Title + Catalog.GetString (" (old)");
505
509
string suggestedRename = suggestedRenameBase;
506
510
for (int i = 1; !IsNoteTitleAvailable (suggestedRename); i++)
507
511
suggestedRename = suggestedRenameBase + " " + i.ToString();
509
513
VBox outerVBox = new VBox (false, 12);
510
514
outerVBox.BorderWidth = 12;
511
515
outerVBox.Spacing = 8;
513
517
HBox hbox = new HBox (false, 8);
514
518
Image image = new Image (GuiUtils.GetIcon (Gtk.Stock.DialogWarning, 48)); // TODO: Is this the right icon?
516
520
hbox.PackStart (image, false, false, 0);
518
522
VBox vbox = new VBox (false, 8);
520
524
headerLabel = new Label ();
521
525
headerLabel.UseMarkup = true;
522
526
headerLabel.Xalign = 0;
523
527
headerLabel.UseUnderline = false;
524
528
headerLabel.Show ();
525
529
vbox.PackStart (headerLabel, false, false, 0);
527
531
messageLabel = new Label ();
528
532
messageLabel.Xalign = 0;
529
533
messageLabel.UseUnderline = false;
531
535
messageLabel.Wrap = true;
532
536
messageLabel.Show ();
533
537
vbox.PackStart (messageLabel, false, false, 0);
536
540
hbox.PackStart (vbox, true, true, 0);
539
543
outerVBox.PackStart (hbox);
540
544
VBox.PackStart (outerVBox);
542
546
Gtk.HBox renameHBox = new Gtk.HBox ();
543
547
renameRadio = new Gtk.RadioButton (Catalog.GetString ("Rename local note:"));
544
548
renameRadio.Toggled += radio_Toggled;
545
549
Gtk.VBox renameOptionsVBox = new Gtk.VBox ();
547
551
renameEntry = new Gtk.Entry (suggestedRename);
548
552
renameEntry.Changed += renameEntry_Changed;
549
553
renameUpdateCheck = new Gtk.CheckButton (Catalog.GetString ("Update links in referencing notes"));
552
556
renameHBox.PackStart (renameRadio);
553
557
renameHBox.PackStart (renameOptionsVBox);
554
558
VBox.PackStart (renameHBox);
556
560
deleteExistingRadio = new Gtk.RadioButton (renameRadio, Catalog.GetString ("Overwrite local note"));
557
561
deleteExistingRadio.Toggled += radio_Toggled;
558
562
VBox.PackStart (deleteExistingRadio);
560
564
alwaysDoThisCheck = new Gtk.CheckButton (Catalog.GetString ("Always perform this action"));
561
565
VBox.PackStart (alwaysDoThisCheck);
563
567
continueButton = (Gtk.Button) AddButton (Gtk.Stock.GoForward, Gtk.ResponseType.Accept);
565
569
// Set initial dialog text
566
570
HeaderText = Catalog.GetString ("Note conflict detected");
567
571
MessageText = string.Format (Catalog.GetString ("The server version of \"{0}\" conflicts with your local note."
568
+ " What do you want to do with your local note?"),
572
+ " What do you want to do with your local note?"),
569
573
existingNote.Title);
574
578
private void renameEntry_Changed (object sender, System.EventArgs e)
576
580
if (renameRadio.Active &&
577
!IsNoteTitleAvailable (RenamedTitle))
581
!IsNoteTitleAvailable (RenamedTitle))
578
582
continueButton.Sensitive = false;
580
584
continueButton.Sensitive = true;
583
587
private bool IsNoteTitleAvailable (string renamedTitle)
585
589
return !noteUpdateTitles.Contains (renamedTitle) &&
586
existingNote.Manager.Find (renamedTitle) == null;
590
existingNote.Manager.Find (renamedTitle) == null;
589
593
// Handler for each radio button's Toggled event
590
594
private void radio_Toggled (object sender, System.EventArgs e)
596
600
renameEntry.Sensitive = renameRadio.Active;
597
601
renameUpdateCheck.Sensitive = renameRadio.Active;
600
604
public string HeaderText
603
607
headerLabel.Markup = string.Format (
604
"<span size=\"large\" weight=\"bold\">{0}</span>",
608
"<span size=\"large\" weight=\"bold\">{0}</span>",
609
613
public string MessageText
611
set { messageLabel.Text = value; }
616
messageLabel.Text = value;
614
620
public string RenamedTitle
616
get { return renameEntry.Text; }
623
return renameEntry.Text;
619
627
public bool AlwaysPerformThisAction
621
get { return alwaysDoThisCheck.Active; }
630
return alwaysDoThisCheck.Active;
624
634
public SyncTitleConflictResolution Resolution
628
638
if (renameRadio.Active) {
629
639
if (renameUpdateCheck.Active)
630
return SyncTitleConflictResolution.RenameExistingAndUpdate;
640
return SyncTitleConflictResolution.RenameExistingAndUpdate;
632
642
return SyncTitleConflictResolution.RenameExistingNoUpdate;