From 0f63bf837f3b4728791231f54a9345e88d3653ad Mon Sep 17 00:00:00 2001 From: RKrom Date: Tue, 29 Jul 2014 15:34:19 +0200 Subject: [PATCH] OneNote: changed the behavior for the default destination, we create a new page in the unfiled section. Also changed the names of the destination, included the Notebook & Section --- .../Destinations/OneNoteDestination.cs | 28 +-- .../OfficeExport/OneNoteExporter.cs | 171 +++++++++++++++--- .../OfficeInterop/OneNoteInterop.cs | 45 ++++- 3 files changed, 202 insertions(+), 42 deletions(-) diff --git a/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs b/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs index 1b692183a..8b2f96ffe 100644 --- a/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs +++ b/GreenshotOfficePlugin/Destinations/OneNoteDestination.cs @@ -69,7 +69,7 @@ namespace GreenshotOfficePlugin { if (page == null) { return "Microsoft OneNote"; } else { - return page.PageName; + return page.DisplayName; } } } @@ -110,20 +110,20 @@ namespace GreenshotOfficePlugin { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description); - if (page != null) { - // No page selected, take the current - List pages = OneNoteExporter.GetPages(); - if(pages == null || pages.Count == 0) { - return exportInformation; + if (page == null) { + try { + exportInformation.ExportMade = OneNoteExporter.ExportToNewPage(surface); + } catch(Exception ex) { + exportInformation.ErrorMessage = ex.Message; + LOG.Error(ex); + } + } else { + try { + exportInformation.ExportMade = OneNoteExporter.ExportToPage(surface, page); + } catch(Exception ex) { + exportInformation.ErrorMessage = ex.Message; + LOG.Error(ex); } - page = pages[0]; - } - try { - OneNoteExporter.ExportToPage(surface, page); - exportInformation.ExportMade = true; - } catch (Exception ex) { - exportInformation.ErrorMessage = ex.Message; - LOG.Error(ex); } return exportInformation; } diff --git a/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs b/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs index e96955f8f..717680538 100644 --- a/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs +++ b/GreenshotOfficePlugin/OfficeExport/OneNoteExporter.cs @@ -18,25 +18,16 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -using System; -using System.Collections.Generic; -using System.Text; -using Greenshot.Interop; -using System.Reflection; -using System.Xml; -using System.IO; -using System.Drawing; -using System.Drawing.Imaging; using Greenshot.Plugin; using GreenshotPlugin.Core; +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; namespace Greenshot.Interop.Office { - public class OneNotePage { - public string PageName { get; set; } - public string PageID { get; set; } - public bool IsCurrentlyViewed { get; set; } - } + public class OneNoteExporter { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OneNoteExporter)); private const string XML_IMAGE_CONTENT = "{0}"; @@ -44,23 +35,129 @@ namespace Greenshot.Interop.Office { private const string ONENOTE_NAMESPACE_2007 = "http://schemas.microsoft.com/office/onenote/2007/onenote"; private const string ONENOTE_NAMESPACE_2010 = "http://schemas.microsoft.com/office/onenote/2010/onenote"; - public static void ExportToPage(ISurface surfaceToUpload, OneNotePage page) { + /// + /// Create a new page in the "unfiled notes section", with the title of the capture, and export the capture there. + /// + /// ISurface + /// bool true if export worked + public static bool ExportToNewPage(ISurface surfaceToUpload) { + using(IOneNoteApplication oneNoteApplication = COMWrapper.GetOrCreateInstance()) { + OneNotePage newPage = new OneNotePage(); + string unfiledNotesSectionID = GetSectionID(oneNoteApplication, SpecialLocation.slUnfiledNotesSection); + if(unfiledNotesSectionID != null) { + string pageId = ""; + oneNoteApplication.CreateNewPage(unfiledNotesSectionID, out pageId, NewPageStyle.npsDefault); + newPage.ID = pageId; + // Set the new name, this is automatically done in the export to page + newPage.Name = surfaceToUpload.CaptureDetails.Title; + return ExportToPage(oneNoteApplication, surfaceToUpload, newPage); + } + } + return false; + } + + /// + /// Can be used to change the title of a page + /// + /// + /// + /// + private static void UpdatePageTitle(IOneNoteApplication oneNoteApplication, string pageId, string title) { + try { + string pageXML = ""; + oneNoteApplication.GetPageContent(pageId, out pageXML, PageInfo.piAll, XMLSchema.xsCurrent); + XmlDocument doc = new XmlDocument(); + doc.LoadXml(pageXML); + XmlNamespaceManager namespaceManager = new XmlNamespaceManager(doc.NameTable); + namespaceManager.AddNamespace("one", ONENOTE_NAMESPACE_2010); + + doc.SelectSingleNode("//one:T", namespaceManager).InnerText = title; + // Update the page + oneNoteApplication.UpdatePageContent(doc.OuterXml, DateTime.MinValue, XMLSchema.xs2010, true); + + } catch(Exception ex) { + LOG.Warn("Couldn't set page title.", ex); + } + } + + /// + /// Export the capture to the specified page + /// + /// ISurface + /// OneNotePage + /// bool true if everything worked + public static bool ExportToPage(ISurface surfaceToUpload, OneNotePage page) { + using(IOneNoteApplication oneNoteApplication = COMWrapper.GetOrCreateInstance()) { + return ExportToPage(oneNoteApplication, surfaceToUpload, page); + } + } + + /// + /// Export the capture to the specified page + /// + /// IOneNoteApplication + /// ISurface + /// OneNotePage + /// bool true if everything worked + private static bool ExportToPage(IOneNoteApplication oneNoteApplication, ISurface surfaceToUpload, OneNotePage page) { + if(oneNoteApplication == null) { + return false; + } using (MemoryStream pngStream = new MemoryStream()) { SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings); string base64String = Convert.ToBase64String(pngStream.GetBuffer()); string imageXmlStr = string.Format(XML_IMAGE_CONTENT, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height); - string pageChangesXml = string.Format(XML_OUTLINE, new object[] { imageXmlStr, page.PageID, ONENOTE_NAMESPACE_2010, page.PageName }); - using (IOneNoteApplication oneNoteApplication = COMWrapper.GetOrCreateInstance()) { - LOG.InfoFormat("Sending XML: {0}", pageChangesXml); - oneNoteApplication.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false); - try { - oneNoteApplication.NavigateTo(page.PageID, null, false); - } catch(Exception ex) { - LOG.Warn("Unable to navigate to the target page", ex); + string pageChangesXml = string.Format(XML_OUTLINE, new object[] { imageXmlStr, page.ID, ONENOTE_NAMESPACE_2010, page.Name }); + LOG.InfoFormat("Sending XML: {0}", pageChangesXml); + oneNoteApplication.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false); + try { + oneNoteApplication.NavigateTo(page.ID, null, false); + } catch(Exception ex) { + LOG.Warn("Unable to navigate to the target page", ex); + } + return true; + } + } + + /// + /// Retrieve the Section ID for the specified special location + /// + /// + /// SpecialLocation + /// string with section ID + private static string GetSectionID(IOneNoteApplication oneNoteApplication, SpecialLocation specialLocation) { + if(oneNoteApplication == null) { + return null; + } + string unfiledNotesPath = ""; + oneNoteApplication.GetSpecialLocation(specialLocation, out unfiledNotesPath); + + string notebookXml = ""; + oneNoteApplication.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010); + if(!string.IsNullOrEmpty(notebookXml)) { + LOG.Debug(notebookXml); + StringReader reader = null; + try { + reader = new StringReader(notebookXml); + using(XmlTextReader xmlReader = new XmlTextReader(reader)) { + while(xmlReader.Read()) { + if("one:Section".Equals(xmlReader.Name)) { + string id = xmlReader.GetAttribute("ID"); + string path = xmlReader.GetAttribute("path"); + if(unfiledNotesPath.Equals(path)) { + return id; + } + } + } + } + } finally { + if(reader != null) { + reader.Dispose(); } } } + return null; } /// @@ -81,16 +178,36 @@ namespace Greenshot.Interop.Office { reader = new StringReader(notebookXml); using (XmlTextReader xmlReader = new XmlTextReader(reader)) { reader = null; + OneNoteSection currentSection = null; + OneNoteNotebook currentNotebook = null; while (xmlReader.Read()) { + if("one:Notebook".Equals(xmlReader.Name)) { + string id = xmlReader.GetAttribute("ID"); + if(id != null && (currentNotebook == null || !id.Equals(currentNotebook.ID))) { + currentNotebook = new OneNoteNotebook(); + currentNotebook.ID = xmlReader.GetAttribute("ID"); + currentNotebook.Name = xmlReader.GetAttribute("name"); + } + } + if("one:Section".Equals(xmlReader.Name)) { + string id = xmlReader.GetAttribute("ID"); + if(id != null && (currentSection == null || !id.Equals(currentSection.ID))) { + currentSection = new OneNoteSection(); + currentSection.ID = xmlReader.GetAttribute("ID"); + currentSection.Name = xmlReader.GetAttribute("name"); + currentSection.Parent = currentNotebook; + } + } if ("one:Page".Equals(xmlReader.Name)) { // Skip deleted items if("true".Equals(xmlReader.GetAttribute("isInRecycleBin"))) { continue; } OneNotePage page = new OneNotePage(); - page.PageName = xmlReader.GetAttribute("name"); - page.PageID = xmlReader.GetAttribute("ID"); - if(page.PageID == null || page.PageName == null) { + page.Parent = currentSection; + page.Name = xmlReader.GetAttribute("name"); + page.ID = xmlReader.GetAttribute("ID"); + if(page.ID == null || page.Name == null) { continue; } page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed")); @@ -113,7 +230,7 @@ namespace Greenshot.Interop.Office { if(p1.IsCurrentlyViewed || p2.IsCurrentlyViewed) { return p2.IsCurrentlyViewed.CompareTo(p1.IsCurrentlyViewed); } - return p1.PageName.CompareTo(p2.PageName); + return p1.DisplayName.CompareTo(p2.DisplayName); }); return pages; } diff --git a/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs b/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs index 7a7a49095..27604290a 100644 --- a/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs +++ b/GreenshotOfficePlugin/OfficeInterop/OneNoteInterop.cs @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + using System; namespace Greenshot.Interop.Office { @@ -27,13 +28,15 @@ namespace Greenshot.Interop.Office { [ComProgId("OneNote.Application")] public interface IOneNoteApplication : ICommon { /// - /// Make sure that the notebookXml is of type string, e.g. "", otherwise a type error occurs. + /// Make sure that the out variables are filled with a string, e.g. "", otherwise a type error occurs. /// For more info on the methods: http://msdn.microsoft.com/en-us/library/gg649853.aspx /// void GetHierarchy(string startNode, HierarchyScope scope, out string notebookXml, XMLSchema schema); + void GetSpecialLocation(SpecialLocation specialLocation, out string specialLocationPath); void UpdatePageContent(string pageChangesXml, DateTime dateExpectedLastModified, XMLSchema schema, bool force); void GetPageContent(string pageId, out string pageXml, PageInfo pageInfoToExport, XMLSchema schema); void NavigateTo(string hierarchyObjectID, string objectId, bool newWindow); + void CreateNewPage(string sectionID, out string pageID, NewPageStyle newPageStyle); } public enum PageInfo { @@ -57,4 +60,44 @@ namespace Greenshot.Interop.Office { xs2010 = 1, xsCurrent= xs2010 } + + public enum SpecialLocation : int { + slBackupFolder = 0, + slUnfiledNotesSection = 1, + slDefaultNotebookFolder = 2 + } + + public enum NewPageStyle { + npsDefault = 0, + npsBlankPageWithTitle = 1, + npsBlankPageNoTitle = 2 + } + + public class OneNotePage { + public OneNoteSection Parent { get; set; } + public string Name { get; set; } + public string ID { get; set; } + public bool IsCurrentlyViewed { get; set; } + public string DisplayName { + get { + OneNoteNotebook notebook = Parent.Parent; + if(string.IsNullOrEmpty(notebook.Name)) { + return string.Format("{0} / {1}", Parent.Name, Name); + } else { + return string.Format("{0} / {1} / {2}", Parent.Parent.Name, Parent.Name, Name); + } + } + } + } + + public class OneNoteSection { + public OneNoteNotebook Parent { get; set; } + public string Name { get; set; } + public string ID { get; set; } + } + + public class OneNoteNotebook { + public string Name { get; set; } + public string ID { get; set; } + } }