public void SaveNow()
{
if (_domForCurrentPage != null)
{
try
{
_webSocketServer.Send("saving", "");
// CleanHtml already requires that we are on UI thread. But it's worth asserting here too in case that changes.
// If we weren't sure of that we would need locking for access to _tasksToDoAfterSaving and _inProcessOfSaving,
// and would need to be careful about whether any delayed tasks needed to be on the UI thread.
if (_view.InvokeRequired)
{
NonFatalProblem.Report(ModalIf.Beta, PassiveIf.Beta, "SaveNow called on wrong thread", null);
_view.Invoke((Action)(SaveNow));
return;
}
CheckForBL2364("beginning SaveNow");
_inProcessOfSaving = true;
_tasksToDoAfterSaving.Clear();
_view.CleanHtmlAndCopyToPageDom();
SavePageFrameState();
//BL-1064 (and several other reports) were about not being able to save a page. The problem appears to be that
//this old code:
// CurrentBook.SavePage(_domForCurrentPage);
//would some times ask book X to save a page from book Y.
//We could never reproduce it at will, so this is to help with that...
if(this._pageSelection.CurrentSelection.Book != _currentlyDisplayedBook)
{
Debug.Fail("This is the BL-1064 Situation");
Logger.WriteEvent("Warning: SaveNow() with a page that is not the current book. That should be ok, but it is the BL-1064 situation (though we now work around it).");
}
//but meanwhile, the page knows its book, so we can see if it looks like a valid book and give a helpful
//error if, for example, it was deleted:
try
{
if (!_pageSelection.CurrentSelection.Book.CanUpdate)
{
Logger.WriteEvent("Error: SaveNow() found that this book had CanUpdate=='false'");
Logger.WriteEvent("Book path was {0}",_pageSelection.CurrentSelection.Book.FolderPath);
throw new ApplicationException("Bloom tried to save a page to a book that was not in a position to be updated.");
}
}
catch (ObjectDisposedException err) // in case even calling CanUpdate gave an error
{
Logger.WriteEvent("Error: SaveNow() found that this book was disposed.");
throw err;
}
catch(Exception err) // in case even calling CanUpdate gave an error
{
Logger.WriteEvent("Error: SaveNow():CanUpdate threw an exception");
throw err;
}
CheckForBL2364("save");
//OK, looks safe, time to save.
_pageSelection.CurrentSelection.Book.SavePage(_domForCurrentPage);
CheckForBL2364("finished save");
}
finally
{
_inProcessOfSaving = false;
}
while (_tasksToDoAfterSaving.Count > 0)
{
var task = _tasksToDoAfterSaving[0];
_tasksToDoAfterSaving.RemoveAt(0);
task();
}
}
}
private void OnShowBookMetadataEditor() { try { if (!_model.CanEditCopyrightAndLicense) { MessageBox.Show(LocalizationManager.GetString("EditTab.CannotChangeCopyright", "Sorry, the copyright and license for this book cannot be changed.")); return; } _model.SaveNow(); //in case we were in this dialog already and made changes, which haven't found their way out to the Book yet Metadata metadata = _model.CurrentBook.GetLicenseMetadata(); if (metadata.License is NullLicense && string.IsNullOrWhiteSpace(metadata.CopyrightNotice)) { //looks like the first time. Nudge them with a nice default license. metadata.License = new CreativeCommonsLicense(true, true, CreativeCommonsLicense.DerivativeRules.Derivatives); } Logger.WriteEvent("Showing Metadata Editor Dialog"); using (var dlg = new Palaso.UI.WindowsForms.ClearShare.WinFormsUI.MetadataEditorDialog(metadata)) { dlg.ShowCreator = false; if (DialogResult.OK == dlg.ShowDialog()) { string imagePath = _model.CurrentBook.FolderPath.CombineForPath("license.png"); if (File.Exists(imagePath)) { File.Delete(imagePath); } Image licenseImage = dlg.Metadata.License.GetImage(); if (licenseImage != null) { licenseImage.Save(imagePath); } else if (File.Exists(imagePath)) { File.Delete(imagePath); } // Both LicenseNotes and Copyright By could have user-entered html characters that need escaping. var copyright = dlg.Metadata.CopyrightNotice; dlg.Metadata.CopyrightNotice = copyright; //NB: we are mapping "RightsStatement" (which comes from XMP-dc:Rights) to "LicenseNotes" in the html. //note that the only way currently to recognize a custom license is that RightsStatement is non-empty while description is empty var rights = dlg.Metadata.License.RightsStatement; dlg.Metadata.License.RightsStatement = rights; string description = dlg.Metadata.License.GetDescription("en") == null ? string.Empty : dlg.Metadata.License.GetDescription("en").Replace("'", "\\'"); string licenseImageName = licenseImage == null? string.Empty: "license.png"; string result = string.Format( "{{ copyright: '{0}', licenseImage: '{1}', licenseUrl: '{2}', licenseNotes: '{3}', licenseDescription: '{4}' }}", MakeJavaScriptContent(dlg.Metadata.CopyrightNotice), licenseImageName, dlg.Metadata.License.Url, MakeJavaScriptContent(rights), description); _browser1.RunJavaScript("if (calledByCSharp) { calledByCSharp.setCopyrightAndLicense(" + result + "); }"); //ok, so the the dom for *that page* is updated, but if the page doesn't display some of those values, they won't get //back to the data div in the actual html file even when the page is read and saved, because individual pages don't //have the data div. _model.CurrentBook.UpdateLicenseMetdata(dlg.Metadata); _model.SaveNow(); _model.RefreshDisplayOfCurrentPage(); //the cleanup() that is part of Save removes qtips, so let' redraw everything } } Logger.WriteMinorEvent("Emerged from Metadata Editor Dialog"); } catch (Exception error) { #if DEBUG throw; #endif Palaso.Reporting.ErrorReport.NotifyUserOfProblem(error, "There was a problem recording your changes to the copyright and license."); } }