Showing posts with label Tomboy. Show all posts
Showing posts with label Tomboy. Show all posts

08 February 2011

Export all Tomboy notes into HTML/XHTML

Just wrote Python script to export all the Tomboy notes into an HTML file. The following script connects Tomboy via DBus Interface, creates XHTML file and converts it to HTML by means of an XSL. Conversion powered by xsltproc utility.

tomboy2html.py

#!/usr/bin/python
# Copyright (C) 2011 - Ruslan Osmanov <rrosmanov@gmail.com>
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# See <http://www.gnu.org/licenses/>
# 
##
# @file tomboy2html.py
# @brief Export all Tomboy notes in XHTML/HTML file(s)
# @author Ruslan Osmanov
# @version 1.0
# @date 08.02.2011
# @details xsltproc utility required
# @copyright Copyright (C) 2011 - Ruslan Osmanov

import dbus, dbus.glib
try:
  import gobject
except ImportError:
  # gobject functions are moved to dbus.glib in this Python version
  pass
import os, sys, getopt
import re

def usage():
  print __file__ + " [OPTIONS]"
  print """Options:
-h, --help    Display help
-p, --prefix    Optional. Output filename prefix. Default: notes
-x, --xhtml   Optional. Generate XHTML file also. Default: off 
-s, --xsl   Optional. XSL for XML-HTML conversion. Default: tomboy-notes.xsl 
-d, --debug   Optional. Debug mode. Default: off 
"""

def main(argv):
  debug_mode = False
  prefix = 'notes'
  xhtml = False
  xsl_filename = os.path.dirname(__file__) + '/tomboy-notes.xsl'

  # Get CLI options
  try:
    opts, args = getopt.getopt(argv[1:], "s:p:xhd", 
        ("xsl=", "prefix=", "debug", "xhtml", "help"))

  except getopt.GetoptError:
    usage()
    sys.exit(2)

  # Save CLI options
  for o, a in opts:
    if o in ('-h', '--help'):
      usage();
      sys.exit();

    elif o in ('-x', '--xhtml'):
      xhtml = True

    elif o in ('-d', '--debug'):
      debug_mode = True

    elif o in ("-p", "--prefix"):
      prefix = os.path.expanduser(a)

    elif o in ("-s", "--xsl"):
      xsl_filename = os.path.expanduser(a)

  xhtml_filename = prefix + '.xhtml'
  html_filename = prefix + '.html'
  if False == os.path.exists(xsl_filename):
    print "XSL file '"+xsl_filename+"' doesn't exist"
    sys.exit(2)

  if debug_mode:
    print "xhtml =", xhtml_filename, "\nhtml =", html_filename
    print "\nxsl =", xsl_filename

  # Access the Tomboy remote control interface
  bus = dbus.SessionBus()
  obj = bus.get_object("org.gnome.Tomboy", "/org/gnome/Tomboy/RemoteControl")
  tomboy = dbus.Interface(obj, "org.gnome.Tomboy.RemoteControl")

  # Get note URIs
  all_notes = tomboy.ListAllNotes()

  # Write each note XML to the XHTML file
  f = open(xhtml_filename, "w")
  f.write('<?xml version="1.0" encoding="utf-8"?>' + 
      '<?xml-stylesheet type="text/xsl" href="' +xsl_filename+'"?>'
      '<notes>')
  for n in all_notes:
    if (debug_mode):
      print "NOTE '"+n+"'"
    xml = re.sub(r'<\?xml[^<]*\?>', '', tomboy.GetNoteCompleteXml(n))
    xml = re.sub(r'\&\#x?.*\;', '', xml)
    f.write(unicode(xml).encode("utf-8"))

  f.write('</notes>')
  f.close()

  # Generate HTML
  cmd = "xsltproc -o '%(html)s' '%(xsl)s' '%(xhtml)s'" % \
      {'html': html_filename.replace("'", "\\'"), 
          'xsl': xsl_filename, 
          'xhtml': xhtml_filename}
      if debug_mode:
        print cmd
  os.system(cmd)

  if xhtml == False:
    os.unlink(xhtml_filename)

if __name__ == "__main__":
    main(sys.argv)

tomboy-notes.xsl

<?xml version='1.0' encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tomboy="http://beatniksoftware.com/tomboy"
xmlns:notes="http://beatniksoftware.com/tomboy/notes"
xmlns:size="http://beatniksoftware.com/tomboy/size"
xmlns:link="http://beatniksoftware.com/tomboy/link"
version='1.0'>

<xsl:output method="html" indent="no" />
<xsl:preserve-space elements="*" />

<xsl:param name="font" />
<xsl:param name="export-linked" />
<xsl:param name="export-linked-all" />
<xsl:param name="root-note" />

<xsl:param name="newline" select="'&#xA;'" />

<xsl:template match="/">
<html>
<head>
    <title>Tomboy Notes Export</title>
    <style type="text/css">/*<![CDATA[*/
        body { <xsl:value-of select="$font" /> }
        h1 { 
            font-size: xx-large;
            font-weight: bold;
            border-bottom: 1px solid black; 
        }
        div.note {
            position: relative;
            display: block;
            padding: 5pt;
            margin: 5pt;
            white-space: -moz-pre-wrap; /* Mozilla */
            white-space: -pre-wrap; /* Opera 4 - 6 */
            white-space: -o-pre-wrap; /* Opera 7 */
            white-space: pre-wrap; /* CSS3 */
            word-wrap: break-word; /* IE 5.5+ */ 
        }
        table.note-info{
            margin: 20px 0 5px;
            font-size:xx-small;
            border-width: 0 1px 1px 0;
            border-style: solid;
        }
        table.note-info td{
            padding: 2px 5px;
            border-width: 1px 0 0 1px;
            border-style: solid;
        }
        /*//]]>*/
    </style>
</head>
<body>
    <xsl:for-each select="notes/tomboy:note">
    <div class="note">
        <xsl:apply-templates select="tomboy:text | tomboy:title"/>

        <table class="note-info" boder="0" cellpadding="0" cellspacing="0"
            summary="Note Info">
            <tr>
                <td>Last updated:</td>    
                <td><xsl:value-of select="tomboy:last-change-date" /></td>
            </tr>    
            <tr>
                <td>Tags:</td>    
                <td>
                    <xsl:for-each select="tomboy:tags">
                    <div><xsl:value-of select="tomboy:tag"/></div>    
                    </xsl:for-each>
                </td>
            </tr>    
        </table>
    </div>
    </xsl:for-each>
</body>
</html>
</xsl:template>



<xsl:template match="text()">
    
    <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="child::tomboy:text">
    <xsl:apply-templates select="node()"/>
</xsl:template>

<xsl:template match="tomboy:title">
    <h1><xsl:value-of select="text()"/></h1>
</xsl:template>
<xsl:template match="tomboy:bold">
    <strong><xsl:apply-templates select="node()"/></strong>
</xsl:template>
<xsl:template match="tomboy:italic">
    <i><xsl:apply-templates select="node()"/></i>
</xsl:template>
<xsl:template match="tomboy:monospace">
    <code><xsl:apply-templates select="node()"/></code>
</xsl:template>

<xsl:template match="tomboy:strikethrough">
<strike><xsl:apply-templates select="node()"/></strike>
</xsl:template>

<xsl:template match="tomboy:highlight">
<span style="background:yellow"><xsl:apply-templates select="node()"/></span>
</xsl:template>

<xsl:template match="tomboy:datetime">
<span style="font-style:italic;font-size:small;color:#888A85">
<xsl:apply-templates select="node()"/>
</span>
</xsl:template>

<xsl:template match="size:small">
<span style="font-size:small"><xsl:apply-templates select="node()"/></span>
</xsl:template>

<xsl:template match="size:large">
<span style="font-size:large"><xsl:apply-templates select="node()"/></span>
</xsl:template>

<xsl:template match="size:huge">
<span style="font-size:xx-large"><xsl:apply-templates select="node()"/></span>
</xsl:template>

<xsl:template match="link:broken">
<span style="color:#555753;text-decoration:underline">
<xsl:value-of select="node()"/>
</span>
</xsl:template>
<xsl:template match="link:internal">
<a style="color:#204A87" href="#{node()}">
<xsl:value-of select="node()"/>
</a>
</xsl:template>

<xsl:template match="link:url">
<a style="color:#3465A4" href="{node()}"><xsl:value-of select="node()"/></a>
</xsl:template>

<xsl:template match="tomboy:list">
<ul>
<xsl:apply-templates select="tomboy:list-item" />
</ul>
</xsl:template>

<xsl:template match="tomboy:list-item">
<li>
<xsl:if test="normalize-space(text()) = ''">
<xsl:attribute name="style">list-style-type: none</xsl:attribute>
</xsl:if>
<xsl:attribute name="dir">
<xsl:value-of select="@dir"/>
</xsl:attribute>
<xsl:apply-templates select="node()" />
</li>
</xsl:template>

<xsl:template match="//tomboy:x | //tomboy:y | //tomboy:width | //tomboy:height | //tomboy:cursor-position | //tomboy:create-date | tomboy:last-change-date | tomboy:open-on-startup | tomboy:last-metadata-change-date | tomboy:tags">
<xsl:comment>literal</xsl:comment>
</xsl:template>

</xsl:stylesheet>

Usage

I saved the files here in ~/scripts/python/tomboy2html/. Thus, to save all the Tomboy notes in all_notes.xhtml and all_notes.html, I can issue the following:
$ chmod +x ~/scripts/python/tomboy2html/tomboy2html.py
$ ~/scripts/python/tomboy2html/tomboy2html.py -p "all_notes" -x -s \
~/scripts/python/tomboy2html/tomboy-notes.xsl
It creates all_notes.xhtml and all_notes.html files in current directory.

Update 09 February 2011

Clone the Git repo:
$ git clone git://github.com/rosmanov/Tomboy2HTML.git

24 October 2010

Importing text files into Tomboy

Thanks to Scott Carpenter's post, I managed to write a Python script importing folder files into Tomboy.

The script creates note for each text file(".txt") using Tomboy DBus API. txt2tomboy.py:


import dbus, gobject, dbus.glib
import os

# get the d-bus session bus
bus = dbus.SessionBus()
# access the tomboy d-bus object
obj = bus.get_object("org.gnome.Tomboy", "/org/gnome/Tomboy/RemoteControl")
# access the tomboy remote control interface
tomboy = dbus.Interface(obj, "org.gnome.Tomboy.RemoteControl")

extAllowed = ['.txt']
srcDir = 'path/to/notes/'
path = os.path.expanduser(srcDir)

dirlist = os.listdir(path)
dirlist.sort()

for root, dirs, files in os.walk('/home/ruslan/now/'):
    for filename in files: 
        #print join(root, filename)
        if os.path.splitext(filename)[1] in extAllowed:
            print os.path.join(root, filename)
            f = open(os.path.join(root, filename))
            # d-bus complains if string params aren't valid UTF-8
            title = filename;

   # reset to start of file and read whole file
   f.seek(0)
   s = f.read();

   # creating named notes seems to prevent notes
   #   from showing up as "New Note NNN"
   note = tomboy.CreateNamedNote(title)

   # TODO: remove DisplayNote()/HideNote() in future versions
   # where the bug will hopefully be fixed.
   # Because of bug in Tomboy 1.8.0(at least I've noticed it in this version)
   # we have to workaround displaying the note before SetNoteContents :/
   tomboy.DisplayNote(note)
   tomboy.SetNoteContents(note, title + "\n\n" + s)
   tomboy.HideNote(note)

That's it. I'd just share what I've learnt

P.S. This is a start point in learning Python for me :)

UPDATE 25.10.2010 09:46 UTC+5

More flexible version:

#!/usr/bin/python
import dbus, gobject, dbus.glib
import os, sys, getopt

def usage():
    print __file__ + " [options]"
    print "Options:"
    print "-h --help        Display this help"
    print "-p --path        Path to source direcrory with text files"

def main(argv):
    path = './'                # source path 
    extAllowed = ['.txt']

    try:
        opts, args = getopt.getopt(argv[1:], "p:h", ("path="))

    except getopt.GetoptError:
        usage()
        sys.exit(2)

    for o, a in opts:
        if o in ('-h', '--help'):
            usage();
            sys.exit();

        elif o in ("-p", "--path"):
            path = os.path.expanduser(a)

    # get the d-bus session bus
    bus = dbus.SessionBus()
    # access the tomboy d-bus object
    obj = bus.get_object("org.gnome.Tomboy", "/org/gnome/Tomboy/RemoteControl")
    # access the tomboy remote control interface
    tomboy = dbus.Interface(obj, "org.gnome.Tomboy.RemoteControl")

    dirlist = os.listdir(path)
    dirlist.sort()

    for root, dirs, files in os.walk(path):
        for filename in files: 
            #print join(root, filename)
            if os.path.splitext(filename)[1] in extAllowed:
                print os.path.join(root, filename)
                f = open(os.path.join(root, filename))
                # d-bus complains if string params aren't valid UTF-8
                title = filename;

                # reset to start of file and read whole file
                f.seek(0)
                s = f.read();

                # creating named notes seems to prevent notes
                #   from showing up as "New Note NNN"
                note = tomboy.CreateNamedNote(title)
                # TODO: remove DisplayNote()/HideNote() in future versions
                # where the bug will hopefully be fixed.
                # Because of bug in Tomboy 1.8.0(at least I've noticed it in this version)
                # we have to workaround displaying the note before SetNoteContents :/
                tomboy.DisplayNote(note)
                tomboy.SetNoteContents(note, title + "\n\n" + s)
                tomboy.HideNote(note)

if __name__ == "__main__":
    main(sys.argv)

UPDATE Tue Jul 10 10:53:17 MSK 2012

The new Tomboy DBus API has a bug: SetNoteContents() doesn't work until the note isn't displayed. I've updated scripts with the following workaround:

tomboy.DisplayNote(note)
tomboy.SetNoteContents(note, title + "\n\n" + s)
tomboy.HideNote(note)
:/