Last active
May 18, 2017 12:15
-
-
Save jaap-karssenberg/9c8789adb53b369838f838c38c3c02dd to your computer and use it in GitHub Desktop.
Archive plugin for zim desktop wiki
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
# -*- coding: utf-8 -*- | |
# Copyright 2015 Jaap Karssenberg <jaap.karssenberg@gmail.com> | |
# TODO - "copy to archive" next to "move to archive" | |
# TODO - hook into search dialog - hide archive + show button with "show X archived pages" | |
# TODO - hook into auto-completion - put archive lower in the list | |
# To install this plugin: | |
# 1. in zim go to the preferences dialog, plugins tab | |
# 2. click "open plugin folder" | |
# this should open ~/.local/share/zim/plugins or similar | |
# 3. copy this file to the folder presented | |
# 4. restart zim (quit and then start again, don't just close the window) | |
# 5. go back to the plugins tab, plugin should now show up | |
from __future__ import with_statement | |
import gobject | |
import gtk | |
import re | |
import datetime | |
import logging | |
from zim.plugins import PluginClass, extends, WindowExtension | |
from zim.actions import action | |
from zim.notebook import Path | |
from zim.gui.widgets import ui_environment, Dialog, Button, \ | |
WindowSidePaneWidget, LEFT_PANE, TOP, WIDGET_POSITIONS, \ | |
BrowserTreeView, ScrolledWindow | |
logger = logging.getLogger('zim.plugins.archive') | |
class ArchivePlugin(PluginClass): | |
plugin_info = { | |
'name': _('Archive'), # T: plugin name | |
'description': _('''\ | |
This plugin uses a section of the notebook as an archive. | |
This archive section is used to get pages out of the way from the | |
active notebook structere. | |
'''), | |
# T: plugin description | |
'author': 'Jaap Karssenberg', | |
'help': 'Plugins:Archive', | |
} | |
plugin_preferences = ( | |
# key, type, label, default | |
('namespace', 'namespace', _('Section'), Path(':Archive')), # T: input label | |
#~ ('embedded', 'bool', _('Show calendar in sidepane instead of as dialog'), False), # T: preferences option | |
#~ ('pane', 'choice', _('Position in the window'), (LEFT_PANE, TOP), WIDGET_POSITIONS), # T: preferences option | |
) | |
# TODO disable pane setting if not embedded | |
def __init__(self, config=None): | |
PluginClass.__init__(self, config) | |
#~ self.preferences.connect('changed', self.on_preferences_changed) | |
#~ self.on_preferences_changed(self.preferences) | |
#~ def on_preferences_changed(self, preferences): | |
#~ if preferences['embedded']: | |
#~ self.set_extension_class('MainWindow', MainWindowExtensionEmbedded) | |
#~ else: | |
#~ self.set_extension_class('MainWindow', MainWindowExtensionDialog) | |
def archive_page(self, notebook, page): | |
postfix = datetime.date.today().strftime("_%Y%m%d") | |
section = self.preferences['namespace'] | |
newpage = notebook.get_page(section + (page.name + postfix)) | |
if newpage.exists(): | |
i = 1 | |
postfix = postfix + '_(%i)' % i | |
newpage = notebook.get_page(section + (page.name + postfix)) | |
while new_page.exists(): | |
i += 1 | |
postfix = postfix + '_(%i)' % i | |
newpage = notebook.get_page(Path(page.name + postfix)) | |
notebook.move_page(page, newpage) | |
def list_archived_versions(self, notebook, page): | |
# Find all pages in archive that look like page + postfix | |
# Find all pages in archive that look like page where parent | |
# has a postfix | |
# Yield pages and archive dates | |
def _versions(trunk, remainder): | |
basename = remainder.pop(0) | |
pattern = re.compile(re.escape(basename) + r'[ _](\d{8})([ _]\(\d+\))?$') | |
for path in notebook.index.list_pages(trunk): | |
match = pattern.search(path.basename) | |
if match: # branch with archive date | |
date = match.group(1) | |
if remainder: | |
child = path + remainder | |
if notebook.get_page(child).exists(): | |
yield child, date | |
else: | |
yield path, date | |
elif path.basename == basename: | |
if remainder: # follow trunk | |
for r in _versions(path, remainder): | |
yield r | |
else: | |
pass # empty parent of archived pages | |
section = self.preferences['namespace'] | |
for path, date in _versions(section, page.parts): | |
yield path, date | |
@extends('MainWindow') | |
class MainWindowExtensionDialog(WindowExtension): | |
'''Extension used to add calendar dialog to mainwindow''' | |
uimanager_xml = ''' | |
<ui> | |
<menubar name='menubar'> | |
<menu action='file_menu'> | |
<placeholder name='page_modification_actions'> | |
<menuitem action='archive_page'/> | |
</placeholder> | |
</menu> | |
<menu action='view_menu'> | |
<placeholder name='plugin_items'> | |
<menuitem action='show_archived_versions'/> | |
</placeholder> | |
</menu> | |
</menubar> | |
</ui> | |
''' | |
@action(_('_Archive Page')) # T: menu item | |
def archive_page(self): | |
self.window.ui.save_page() # XXX | |
notebook = self.window.ui.notebook # XXX | |
page = self.window.pageview.get_page() | |
self.plugin.archive_page(notebook, page) | |
@action(_('_Archived Versions...'), tooltip=_('Show Archived Versions...')) # T: menu item | |
def show_archived_versions(self): | |
notebook = self.window.ui.notebook # XXX | |
page = self.window.pageview.get_page() | |
opener = self.window.get_resource_opener() | |
dialog = ArchivedVersionsDialog(self.window, self.plugin, notebook, page, opener) | |
dialog.present() | |
#~ @extends('SearchDialog') | |
#~ class SearchDialogExtension(WindowExtension): | |
#~ def __init__(self, plugin, window): | |
#~ WindowExtension.__init__(self, plugin, window) | |
# Install filter + button | |
#~ def teardown(self): | |
# REmove filter + button | |
class ArchivedVersionsDialog(Dialog): | |
# TODO "open" button that opens current selected version | |
def __init__(self, parent, plugin, notebook, page, opener): | |
Dialog.__init__(self, parent, _('Archived Pages'), # T: dialog title | |
defaultwindowsize=(400, 300), | |
buttons=gtk.BUTTONS_CLOSE, | |
) | |
label = gtk.Label(_('Archived versions of: <b>%s</b>') % page.name) # T: label, "%s" is the full page name | |
label.set_use_markup(True) | |
self.vbox.pack_start(label, False) | |
model = gtk.ListStore(str, str) # date, page | |
for path, date in plugin.list_archived_versions(notebook, page): | |
# TODO - get ctime and mtime for page | |
# TODO - get more user readable rendering of date - same as in "recent pages" dialog | |
date = "%s-%s-%s" % (date[0:4], date[4:6] ,date[6:8]) # year, month, day | |
model.append((date, path.name)) | |
model.set_sort_column_id(0, gtk.SORT_DESCENDING) | |
treeview = BrowserTreeView() | |
self.vbox.add(ScrolledWindow(treeview)) | |
cell_renderer = gtk.CellRendererText() | |
for name, i in ( | |
(_('Date'), 0), # T: Column header archive dialog | |
(_('Page'), 1), # T: Column header archive dialog | |
): | |
column = gtk.TreeViewColumn(name, cell_renderer, text=i) | |
column.set_sort_column_id(i) | |
treeview.append_column(column) | |
treeview.set_model(model) | |
def on_open_page(view, path, col): | |
page = Path( view.get_model()[path][1].decode('utf-8') ) | |
opener.open_page(page) | |
treeview.connect('row-activated', on_open_page) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment