Created
February 3, 2016 11:44
-
-
Save tung/19cf304700c4c1f85e81 to your computer and use it in GitHub Desktop.
Tomboy-like recent note list for Gnote Unity launcher icon right-click menu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# | |
# gnote-unity.py3 | |
# | |
# Shows a Tomboy-like list of recent notes when the Gnote launcher is right-clicked. | |
# Clicking on a note opens it. | |
# Notes are sorted by last modification time and update dynamically. | |
# | |
# To use, just run this at login time, e.g. set under Startup Applications. | |
# | |
from gi.repository import Unity, GObject, Dbusmenu | |
from datetime import datetime | |
from dateutil.tz import tzlocal, tzutc | |
import glob, os | |
g_gnote_path = '/usr/bin/gnote' | |
g_gnote_home = os.getenv('HOME') + '/.local/share/gnote' | |
g_note_list = None | |
g_note_list_max = 8 | |
g_gnote_home_mtime = None | |
g_launcher = Unity.LauncherEntry.get_for_desktop_id("gnote.desktop") | |
g_qlist = None | |
g_qlist_items = [] | |
class Note: | |
def __init__(self, filename, title, date): | |
self.filename = filename | |
self.title = title | |
self.date = date | |
def get_tag(tag_name, line): | |
open_tag = '<' + tag_name + '>' | |
close_tag = '</' + tag_name + '>' | |
start = line.find(open_tag) | |
if start != -1: | |
tag_content = line[start + len(open_tag):] | |
end = tag_content.find(close_tag) | |
if end != -1: | |
tag_content = tag_content[:end] | |
return tag_content | |
return None | |
def insert_recent_note(nlist, nlist_max, entry): | |
if entry.title == 'New Note Template' or entry.title == 'Using Links in Gnote': | |
return | |
insert_pos = None | |
for pos in range(0, len(nlist)): | |
if entry.date > nlist[pos].date: | |
insert_pos = pos | |
break | |
if insert_pos == None: | |
if len(nlist) < nlist_max: | |
nlist.append(entry) | |
else: | |
nlist.insert(insert_pos, entry) | |
if len(nlist) > nlist_max: | |
del nlist[nlist_max] | |
def find_recent_notes(): | |
global g_gnote_home_mtime | |
global g_note_list | |
global g_gnote_home | |
global g_note_list_max | |
# Only update note list if the directory was modified since last time. | |
check_path_stat = os.stat(g_gnote_home) | |
check_path_mtime = datetime.fromtimestamp(check_path_stat.st_mtime, tzlocal()) | |
if g_gnote_home_mtime != None and check_path_mtime <= g_gnote_home_mtime: | |
return | |
g_gnote_home_mtime = check_path_mtime | |
# Check all the notes for updates. | |
g_note_list = [] | |
for filename in glob.iglob(g_gnote_home + '/*.note'): | |
# Short-circuit if the file modified time is older than all the list notes. | |
filestat = os.stat(filename) | |
mtime = datetime.fromtimestamp(filestat.st_mtime, tzlocal()) | |
if len(g_note_list) >= g_note_list_max and mtime < g_note_list[-1].date: | |
continue | |
# Parse the note and maybe insert it. | |
title = None | |
last_change_date = None | |
with open(filename, encoding='utf-8') as note_file: | |
for note_line in note_file: | |
if not title: | |
title = get_tag('title', note_line) | |
if not last_change_date: | |
last_change_date_str = get_tag('last-change-date', note_line) | |
if last_change_date_str: | |
# Gnote stores times in UTC | |
last_change_date = datetime.strptime(last_change_date_str, '%Y-%m-%dT%H:%M:%S.%fZ') | |
last_change_date = last_change_date.replace(tzinfo=tzutc()) | |
if title and last_change_date: | |
entry = Note(filename, title, last_change_date) | |
insert_recent_note(g_note_list, g_note_list_max, entry) | |
break | |
def open_note(a, b): | |
global g_gnote_path | |
note_title = a.property_get(Dbusmenu.MENUITEM_PROP_LABEL) | |
if os.fork() == 0: | |
os.execl(g_gnote_path, g_gnote_path, '--open-note', note_title) | |
exit(1) | |
def init_quicklist(): | |
global g_note_list_max | |
global g_launcher | |
global g_qlist | |
global g_qlist_items | |
g_qlist = Dbusmenu.Menuitem.new() | |
for i in range(g_note_list_max): | |
item = Dbusmenu.Menuitem.new() | |
item.connect('item-activated', open_note) | |
g_qlist.child_append(item) | |
g_qlist_items.append(item) | |
g_launcher.set_property('quicklist', g_qlist) | |
def update_quicklist(): | |
global g_note_list | |
global g_note_list_max | |
global g_qlist_items | |
find_recent_notes() | |
for i in range(len(g_note_list)): | |
g_qlist_items[i].property_set(Dbusmenu.MENUITEM_PROP_LABEL, g_note_list[i].title) | |
g_qlist_items[i].property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True) | |
if len(g_note_list) < g_note_list_max: | |
for i in range(len(g_note_list), g_note_list_max): | |
g_qlist_items[i].property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, False) | |
return True | |
if __name__ == '__main__': | |
init_quicklist() | |
update_quicklist() | |
GObject.timeout_add_seconds(5, update_quicklist) | |
GObject.MainLoop().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment