After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 356871 - export all notes or specific notebooks to html
export all notes or specific notebooks to html
Status: RESOLVED FIXED
Product: tomboy
Classification: Applications
Component: General
unspecified
Other All
: Normal enhancement
: 1.4.0
Assigned To: Tomboy Maintainers
Tomboy Maintainers
sandy[affects-ui]
: 518098 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2006-09-20 09:44 UTC by Jose Alberto
Modified: 2011-06-16 21:50 UTC
See Also:
GNOME target: ---
GNOME version: Unversioned Enhancement


Attachments
export all to html (2.97 KB, patch)
2006-10-21 03:14 UTC, James Williams
rejected Details | Review
Modifies addin to allow exporting all notes or selected notebooks (19.26 KB, patch)
2011-01-07 19:22 UTC, Robert Nordan
none Details | Review
Graphic representation of proposed system (45.71 KB, image/png)
2011-05-02 20:27 UTC, Robert Nordan
  Details
Fix for #356871, allows exporting notebooks or all notes to html (18.77 KB, patch)
2011-05-12 20:43 UTC, Robert Nordan
needs-work Details | Review
Fix for Bug 356871 - Allows mass export of HTML, v2 (20.18 KB, patch)
2011-06-15 11:23 UTC, Robert Nordan
committed Details | Review

Description Jose Alberto 2006-09-20 09:44:56 UTC
the same plugin used to xport a note to html can be used to xport ALL notes or a selection of notes so you can mantain an "web todo" in your server
Comment 1 James Williams 2006-10-21 03:14:45 UTC
Created attachment 75115 [details] [review]
export all to html

This patch adds another checkbox to allow the user to export all notes to html. The export linked button has been hardcoded to have no effect when exporting all, to avoid notes being written more than once.
Comment 2 Wouter Bolsterlee (uws) 2007-02-25 15:23:23 UTC
While I agree that the functionality is useful, the UI needs some loving instead of just adding another checkbox...
Comment 3 Boyd Timothy 2008-02-26 19:16:27 UTC
Setting the default assignee and QA Contact to "tomboy-maint@gnome.bugs".
Comment 4 David Tulloh 2008-12-01 00:26:37 UTC
This is a duplicate of #518098
http://bugzilla.gnome.org/show_bug.cgi?id=518098
Comment 5 Wouter Bolsterlee (uws) 2008-12-01 11:56:06 UTC
*** Bug 518098 has been marked as a duplicate of this bug. ***
Comment 6 Wouter Bolsterlee (uws) 2008-12-01 11:56:30 UTC
Thanks for noticing. It's the other way around though ;)
Comment 7 Sandy Armstrong 2008-12-01 19:53:07 UTC
Expanding bug to include the idea of exporting individual notebooks (bug 518098), and confirming.
Comment 8 Robert Nordan 2011-01-07 19:22:51 UTC
Created attachment 177775 [details] [review]
Modifies addin to allow exporting all notes or selected notebooks

I've created a patch to address this bug, which extends the addin to allow exporting of notebooks or all notes from the Search All Notes window in addition to the original functionality. The patch isolates the logic for exporting a single note and provides methods for exporting notebooks etc by calling the single note export for every note. As such it should be fairly easy to modify the plugin for other export types.

Tested on Linux and Windows, should be cross-platform safe.
Comment 9 Robert Nordan 2011-01-07 19:25:58 UTC
Forgot to mention, it depends on the patch submitted in https://bugzilla.gnome.org/show_bug.cgi?id=638588 in order to work.
Comment 10 Robert Nordan 2011-04-09 20:11:37 UTC
Looking back at this patch (something I did during the christmas holidays to have something to tinker with) I can see that it's quite a big code drop with some weaknesses. Going forward I'd like to redo this one like this:

Create an abstract "export all" add-in (with exception classes for various export problems) in Tomboy that contains all the needed functionality for exporting notebooks and All Notes, and subclass it to add the single note export method for HTML. That way we can easily create export add-ins for other formats as well, and any external add-in developers (like me!) can easily make an exporter for their favourite format.

I recently discovered the Application Add-in class which obviously is much better suited for export all than the method I used changing the export HTML Note add-in, but I need to figure out how to use it best in conjuction with a single Note add-in. So some exploratory work needs to be done here.

You'd need a global menu entry for "export all to HTML" and "export notebook to HTML", would it be smartest to make a Tools->Export menu with these actions listed so that one later could add more Export to **** actions?
Comment 11 Jared Jennings 2011-04-17 02:34:34 UTC
Is this something then that you are working to create or is it something that requires more discussion?
Comment 12 Robert Nordan 2011-04-17 09:20:02 UTC
I'm working on it bit by bit. I've gotten as far as porting my previous work to a system with an ExportAllApplicationAddin that is inherited by ExportAllToHTMLApplicationAddin (for notebook exports), and a separate ExportToHTMLNoteAddin (for single note export). (These two addin classes are still loaded from the same DLL and appear to the user as one addin.) Still need to redo it so there's proper exception throwing & handling. The main issue now is avoiding duplicating the single note export code between the ExportAll and ExportNote addins.

Does anyone know if there is a way you can find registered (and activated) note addins so that you can call methods on them? (Some sort of Note.activeAddins type thing?) My thinkign is that it would be cleanest if you could call the single note export in the NoteAddin from the ApplicationAddin.
Comment 13 Robert Nordan 2011-05-02 20:27:28 UTC
Created attachment 187083 [details]
Graphic representation of proposed system

This is the set-up I've landed on. The right side is unchanged from the way the add-in works now, and the left side is the new work I've been doing. When you subclass the ExportAllApplicationAddin all you have to do is implement two methods, one for naming the type of export (so that menus get the correct name) and one for how to export a single note. (The obvious way, which has been implemented here, is to have a reference to an instance of the ExportNoteAddin and call its note export method.)

Right now I have the system working, and the next step is to add proper error handling and bash some more sense into the dialogs. All notes are exported to a chosen folder as individual HTML files and notebooks are represented as subfolders. Adding new "export all" add-ins for plain text or whatever else floats your boat should be pretty trivial once this system is in place.

It'll be a pretty significant code drop when it's done, with new files added and therefore changes in the makefiles and the MonoDevelop Solution. Is there anything special I should be aware of in a situation like this?
Comment 14 Robert Nordan 2011-05-12 20:43:26 UTC
Created attachment 187739 [details] [review]
Fix for #356871, allows exporting notebooks or all notes to html

Here is my proposed patch. (Currently there's a problem because I can't apply it when I try, posting to see if Sandy can... There's no reason it shouldn't work!)
Comment 15 Robert Nordan 2011-05-12 21:09:15 UTC
Update: The patch works, Sandy tested it and I can make it work now too after creating yet another new clone of the Tomboy git to test. (Something must have gotten corrupted in the one I tested against.)

Please enjoy! The patch modifies the makefiles to make it build on *nix systems, but the csproj's are unmodified because I didn't dare mess with them. (So Windows compiling is a more open question, someone needs to advise on that.)

From here you can get my proof of concept: https://gitorious.org/tomboy-plaintext-export-addin/tomboy-plaintext-export-addin/trees/master 
This is a plaintext exporter that slots in easily beside the html exporter and shares the code for exporting all/notebooks.
Comment 16 Aaron D Borden 2011-06-11 02:23:30 UTC
Sweet patch, I'm looking at in now. Found a bug, you'll have to encode the note titles so they are file safe (and this would be platform dependant). For example I have a note "New </note> N" and the addin fails half way because it's treating the '/' as a path separator.
Comment 17 Aaron D Borden 2011-06-11 05:38:04 UTC
Review of attachment 187739 [details] [review]:

Great patch! Have some comments, minor design related. Overall I like the approach, thanks a lot!

::: Tomboy/Addins/ExportToHtml/ExportToHtmlApplicationAddin.cs
@@ +12,3 @@
+	{
+
+		ExportToHtmlNoteAddin exporter = new ExportToHtmlNoteAddin ();

The exporter code should probably be moved into the ApplicationAddin from the NoteAddin... it doesn't really matter though, I wouldn't hold the commit for that.

@@ +30,3 @@
+		{
+			Logger.Debug (Catalog.GetString("Exporting Note '{0}' to '{1}'..."),
+			              note.Title, output_path);

Log messages don't need to be translated.

::: Tomboy/ExportAllApplicationAddin.cs
@@ +24,3 @@
+		/// The full name to be used in the menu. Can include spaces, should use Catalog.GetString.
+		/// </summary>
+		protected string export_type_full_name;

export_type_pretty_name

@@ +37,3 @@
+		{
+			// Gets names from subclass.
+			setNames ();

This should be capitalized.

@@ +88,3 @@
+				                </menubar>
+				                </ui>
+				                ".Replace ("HTML", export_file_suffix)	//quick hack to make it work.

Please use String.Format () and then you can swap HTML with {0}. I think that gets rid of the hack :)

@@ +105,3 @@
+		/// (export_type_full_name).
+		/// </summary>
+		protected abstract void setNames ();

SetNames ()

@@ +133,3 @@
+		/// </summary>
+		/// <param name="sender">
+		void ExportAllButtonClicked (object sender, EventArgs args)

This should be called "ExportAllNotes" and the ExportAllNotesButtonClicked should just wrap this.

@@ +135,3 @@
+		void ExportAllButtonClicked (object sender, EventArgs args)
+		{
+			Logger.Info (Catalog.GetString ("Activated export all to " + export_file_suffix));

Log messages don't need to be translated.

@@ +139,3 @@
+			//Opens the folder selection dialog
+			ExportMultipleDialog dialog =
+			    new ExportMultipleDialog ("All Notes " + export_file_suffix +" Export", export_file_suffix);

Use the export_file_full_name for the ExportMultipleDialogs since it looks better.

@@ +141,3 @@
+			    new ExportMultipleDialog ("All Notes " + export_file_suffix +" Export", export_file_suffix);
+			int response = dialog.Run ();
+			Logger.Debug(Catalog.GetString("Clicked ok or cancel"));

Log messages don't need to be translated.

@@ +143,3 @@
+			Logger.Debug(Catalog.GetString("Clicked ok or cancel"));
+			string output_folder = dialog.Filename;
+			Logger.Debug(Catalog.GetString("Tried to get filename"));

Log messages don't need to be translated.

@@ +150,3 @@
+
+			try {
+				Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);

Log messages don't need to be translated.

@@ +151,3 @@
+			try {
+				Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);
+				System.IO.Directory.CreateDirectory(output_folder);

I believe this will throw an exception if it already exists... but I can't test it on linux because the Gtk dialog won't let me choose the existing folder... might not be the same on another OS.

Spacing between method name and (

@@ +163,3 @@
+						continue;
+
+					notebook = new Notebook (tag);

You can just use NotebookManager.GetNotebookFromTag (Tag) and just check that notebook != null.

@@ +166,3 @@
+					Logger.Debug ("Exporting notebook " + notebook.Name);
+					notebook_folder = output_folder + System.IO.Path.DirectorySeparatorChar
+					                  + notebook.NormalizedName;

I think some encoding is needed to that the folder is a valid foldername depending on the OS. NormalizedName doesn't do much.

@@ +173,3 @@
+
+				//Finally we have to export all unfiled notes.
+				Logger.Debug (Catalog.GetString ("Exporting Unfiled Notes"));

Log messages don't need to be translated.

@@ +176,3 @@
+				ExportUnfiledNotes (output_folder);
+
+			} catch (UnauthorizedAccessException ex) {

We should log an debug message with the exception message.

@@ +180,3 @@
+				                 Catalog.GetString ("Access denied."));
+				return;
+			} catch (DirectoryNotFoundException ex) {

We should log an debug message with the exception message.

@@ +185,3 @@
+				return;
+			} catch (Exception ex) {
+				Logger.Error (Catalog.GetString ("Could not export: {0}"), ex);

Log messages don't need to be translated.

@@ +186,3 @@
+			} catch (Exception ex) {
+				Logger.Error (Catalog.GetString ("Could not export: {0}"), ex);
+				ShowErrorDialog (output_folder, dialog, ex.Message);

Let's use a prettier message that can be translated, in this case "Unknown error." or similar.

@@ +193,3 @@
+			dialog.SavePreferences ();
+			dialog.Destroy ();
+			dialog = null;

These should be in a finally clause, no?

@@ +207,3 @@
+			string output_folder = null;
+			ExportMultipleDialog dialog = null;
+			Logger.Info (Catalog.GetString ("Activated export notebook to " + export_file_suffix));

Log messages don't need to be translated.

@@ +214,3 @@
+				//Handling the two special notebooks
+				string notebook_name = notebook.NormalizedName;
+				if (notebook_name == "___NotebookManager___AllNotes__Notebook___") {

Blah, this is no good but just leave it. I have a patch that exposes the special notebooks as fields of the NotebookManager. Once that is pushed we can fix this.

@@ +215,3 @@
+				string notebook_name = notebook.NormalizedName;
+				if (notebook_name == "___NotebookManager___AllNotes__Notebook___") {
+					Logger.Info (Catalog.GetString ("This notebook includes all notes, activating Export All"));

Log messages don't need to be translated.

@@ +216,3 @@
+				if (notebook_name == "___NotebookManager___AllNotes__Notebook___") {
+					Logger.Info (Catalog.GetString ("This notebook includes all notes, activating Export All"));
+					ExportAllButtonClicked (sender, args);

Call the "ExportAllNotes" method. ExportAllButtonClicked is a signal handler and doesn't make sense here.

@@ +220,3 @@
+				} else if (notebook_name == "___NotebookManager___UnfiledNotes__Notebook___") {
+					dialog = new ExportMultipleDialog (Catalog.GetString ("Unfiled Notes"), export_file_suffix);
+					int response = dialog.Run();

Spacing between method and (

@@ +227,3 @@
+					}
+
+					Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);

Log messages don't need to be translated.

@@ +228,3 @@
+
+					Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);
+					System.IO.Directory.CreateDirectory(output_folder);

Spacing between method and (

@@ +229,3 @@
+					Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);
+					System.IO.Directory.CreateDirectory(output_folder);
+					ExportUnfiledNotes(output_folder);

Spacing between method and (

@@ +233,3 @@
+					//Ordinary notebooks
+					dialog = new ExportMultipleDialog (notebook_name, export_file_suffix);
+					int response = dialog.Run();

Spacing between method and (

@@ +240,3 @@
+					}
+
+					Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);

Log messages don't need to be translated.

@@ +241,3 @@
+
+					Logger.Debug (Catalog.GetString ("Creating an export folder in: ") + output_folder);
+					System.IO.Directory.CreateDirectory(output_folder);

Spacing between method and (

@@ +244,3 @@
+					ExportNotebook (notebook, output_folder);
+				}
+			} catch (UnauthorizedAccessException ex) {

We should log an debug message with the exception message.

@@ +248,3 @@
+				                 Catalog.GetString ("Access denied."));
+				return;
+			} catch (DirectoryNotFoundException ex) {

We should log an debug message with the exception message.

@@ +253,3 @@
+				return;
+			} catch (Exception ex) {
+				Logger.Error (Catalog.GetString ("Could not export: {0}"), ex);

Log messages don't need to be translated.

@@ +254,3 @@
+			} catch (Exception ex) {
+				Logger.Error (Catalog.GetString ("Could not export: {0}"), ex);
+				ShowErrorDialog (output_folder, dialog, ex.Message);

Use "Unknown error" or similar.

@@ +261,3 @@
+			dialog.SavePreferences ();
+			dialog.Destroy ();
+			dialog = null;

finally

@@ +283,3 @@
+
+				if (save) {
+					ExportSingleNote(note, output_folder + note.Title + "." + export_file_suffix);

You should only have to pass output_folder to ExportSingleNote. Since the sublcass implements it and it already had the note.Title and export_file_suffix, these bits are unnecessary. Plus maybe someone wants to dream up an exporter that doesn't export to files with the title as the filename... Maybe they want to export by tags or something crazy.

@@ +292,3 @@
+		/// Finds all notes without a notebook tag and exports them to the specified folder.
+		/// </summary>
+		public void ExportUnfiledNotes (string output_folder)

This method and the above one are very similar. Let's create one method ExportNotes that takes a list of notes and the output_folder. That way we can condense the two. For notebook, you just pass the Notesbook's Tag.Notes and for Unfiled Notes you would have to build the list yourself.

This would also give more flexibility to the subclass to come up with their own list of notes to export however they want.

@@ +306,3 @@
+						|| tag.Name.StartsWith (Tag.SYSTEM_TAG_PREFIX + Notebook.NotebookTagPrefix))
+						save = false;
+				}

Use NotebookManager.GetNotebookFromNote (note). If it is null, then proceed, otherwise skip it.

@@ +308,3 @@
+				}
+
+				if (save) {

You also need to check for template notes here.

@@ +317,3 @@
+		/// <summary>
+		/// Exports a single Note to *** in a specified location.
+		/// </summary>

Please give a little more description to the output_path parameter :)
Comment 18 Robert Nordan 2011-06-15 11:23:29 UTC
Created attachment 189971 [details] [review]
Fix for Bug 356871 - Allows mass export of HTML, v2

This is a new version of the patch, with all the changes you suggested except for two:  

Q: The exporter code should probably be moved into the ApplicationAddin from the NoteAddin... it doesn't really matter though, I wouldn't hold the commit for that.
A: I felt that reducing the code duplication and executable size slightly was better than the very slight increase in memory usage we get from doing it this way. Since creating a new object that way never actually calls the add-in initializers we won't get any wacky side effects from using that one method on the add-in object. 

Q: I believe this will throw an exception if it already exists... but I can't test it on linux because the Gtk dialog won't let me choose the existing folder... might not be the same on another OS.
A: I tested and it simply silently moves on, so no problem there.

The only really new functionality is functions that check paths and especially note titles to make sure they don't screw up the export. (Like a note with / or \ in the title might.)

The remaining issue is changing the csprojs so that it can build on Windows. Somebody needs to demonstrate how that's done, because when I try to commit my  csproj saved in MonoDevelop the diff is huge and every library reference etc. is changed from a clean version neutral one to a complex one with versions etc. In other words, very messy and probably not something you want in the git tree.
Comment 19 Aaron D Borden 2011-06-15 23:48:01 UTC
(In reply to comment #18)
> The remaining issue is changing the csprojs so that it can build on Windows.
> Somebody needs to demonstrate how that's done, because when I try to commit my 
> csproj saved in MonoDevelop the diff is huge and every library reference etc.
> is changed from a clean version neutral one to a complex one with versions etc.
> In other words, very messy and probably not something you want in the git tree.

Don't worry about the csprojs. We don't have a policy on how to handle it, so the de facto is to let the windows guys handle it. But when I do edit csprojs or the mdp I'll make the changes by hand to avoid that stuff.
Comment 20 Aaron D Borden 2011-06-15 23:49:11 UTC
Comment on attachment 189971 [details] [review]
Fix for Bug 356871 - Allows mass export of HTML, v2

Looks good, do you have commit access?
Comment 21 Robert Nordan 2011-06-16 06:51:29 UTC
Nope, feel free to commit for me. ;-)
Comment 22 Aaron D Borden 2011-06-16 21:48:31 UTC
Comment on attachment 189971 [details] [review]
Fix for Bug 356871 - Allows mass export of HTML, v2

commit 405cc4e74824235128e2770cbcabd6ba48e1ae00

thanks!
Comment 23 Aaron D Borden 2011-06-16 21:50:26 UTC
Thanks, this fix will appear in Tomboy 1.7.1