← Back to team overview

zim-wiki team mailing list archive

Re: Evernote/Footnote-like UI change?

 

OK, I've made a very quick and dirty prototype as a plugin. It shows
all child and grand child pages inline with the parent page below the
text. To try it, drop the attached file in the zim/plugins/ folder
(/usr/lib/python2.7/site-packages/zim/plugins or similar folder when
installed).

Consider it a mock-up and let me know what to change - bonus points
for modifying it in gimp/photoshop/paint to come up with a better look
;)

Please note:
0/ this plugin is experimental -- don't even think about using it for
real at this moment
1/ after you disable the plugin again restart zim to get rid of the new view
2/ inline notes are only read-only for now
3/ inline notes are clipped to 300 px (not sure if this is needed or not)
4/ indenting for sub-sub-pages not really visible - need to enhance that
5/ no rounded corners - needs some cruft to make it look nice ;)
6/ no guarantees about scalability and load time at this state

One question I already have is whether it is a good idea or not to
have a single scroll bar for both the parent page text and the child
page listing. Alternatively these could be in separate panes, so the
text remains in the same place while scrolling through the child
pages.

Another question is how to handle folding of sub-pages. I now show all
sub-sub-pages in the tree. But I also could hide them until you click
"show".

Enjoy!

Jaap
# -*- coding: utf-8 -*-

# Copyright 2012 Jaap Karssenberg <jaap.karssenberg@xxxxxxxxx>

import gtk

from zim.plugins import PluginClass
from zim.notebook import Path

from zim.gui.widgets import encode_markup_text, Button
from zim.gui.pageview import PageView


class ChildViewPlugin(PluginClass):

	plugin_info = {
		'name': _('Child View'), # T: plugin name
		'description': _('''\
This plugin adds a list of child pages below the page view.

EXPERIMANTAL PLUGIN - don't even condsider using it for real use,
it's just a mock up for brainstorming a new feature.

NOTE: After disabeling this plugin you need to restart zim to change back
to standard view

'''), # T: plugin description
		'author': 'Jaap Karssenberg',
	}

	plugin_preferences = (
		# key, type, label, default
		#('floating', 'bool', _('Show ToC as floating widget instead of in sidepane'), False),
	)

	def __init__(self, ui):
		PluginClass.__init__(self, ui)
		self.widget = None

	def finalize_ui(self, ui):
		if ui.ui_type == 'gtk':
			self.widget = ChildView(ui)
			ui.mainwindow.add(self.widget)
			self.widget.show_all()

	def disconnect(self):
		PluginClass.disconnect(self)


class ChildViewBase():

	def _get_children(self):
		return [c for c in self.vbox.get_children() if isinstance(c, ChildWidget)]


	def load_children(self):
		children = self.ui.notebook.index.list_pages(self.path)
		for path in children:
			#~ print '!!! WALK', child
			child = ChildWidget(self.ui, path)
			child.show_all()
			self.vbox.pack_start(child)
	
	def clear_children(self):
		for child in self._get_children():
			self.vbox.remove(child)

	def on_show_all(self, button):
		active = button.get_active()
		for child in self._get_children():
			loaded = bool(child.pageview)
			child.tbutton.set_active(active)

			if active and not loaded:
				# loading is slow, show and hide is fast
				while gtk.events_pending():
					gtk.main_iteration(block=False)


class ChildView(gtk.ScrolledWindow, ChildViewBase):

	# TODO button collapse / expand all
	# TODO think about keyboard navigation

	def __init__(self, ui):
		gtk.ScrolledWindow.__init__(self)
		self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self.ui = ui

		self.vbox = gtk.VBox()
		self.add_with_viewport(self.vbox)

		# reparent pageview widget - HACK no official API
		pageview = ui.mainwindow.pageview
		pageview.reparent(self.vbox)

		# disable scrolling for pageview
		swindow = pageview.view.get_parent()
		swindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)

		# add toolbar
		hbox = gtk.HBox()
		self.vbox.add(hbox)

		tbutton = gtk.ToggleButton(_('Show All'))
		tbutton.connect('toggled', self.on_show_all)
		hbox.pack_end(tbutton, False)

		# initiate children
		if ui.page:
			self.path = ui.page
			self.load_children()
		else:
			self.path = None
		ui.connect('open-page', self.on_open_page)

	def on_open_page(self, ui, page, *a):
		self.path = page
		self.clear_children()
		self.load_children()


class ChildWidget(gtk.VBox, ChildViewBase):
	
	def __init__(self, ui, path):
		gtk.VBox.__init__(self)
		self.set_border_width(3)
		self.ui = ui
		self.path = path
		self.pageview = None

		# Head line
		self.head = gtk.HBox(spacing=12)
		self.add(self.head)

		# Vbox for sub-pages
		self.vbox = gtk.VBox()
		self.vbox.set_border_width(12) # FIXME can we set only left and right ?
		self.pack_end(self.vbox)
		#self.vbox.set_no_show_all(True)
		self.load_children()
		if not self._get_children():
			self.vbox.set_no_show_all(True)

		# Show the page name
		label = gtk.Label()
		label.set_markup('<b>+' + encode_markup_text(path.basename) + '</b>')
		self.head.pack_start(label, False) 

		# Add some buttons
		self.tbutton = gtk.ToggleButton(_('Show'))
		self.tbutton.connect('toggled', self.on_show)
		self.head.pack_end(self.tbutton, False)

		self.gbutton = Button(_('Open'), 'gtk-go-forward')
		self.gbutton.connect('clicked', lambda o: self.ui.open_page(self.path))
		self.head.pack_end(self.gbutton, False)

		# Show tags
		tags = []
		for tag in self.ui.notebook.index.list_tags(self.path):
			tags.append('@' + tag.name)
		label = gtk.Label()
		label.set_markup('<span color="#ce5c00">' + encode_markup_text(' '.join(tags)) + '</span>')
		self.head.pack_end(label, False)

		# TODO date / other info ?

		#   this will make a real tree with more indenting for every level
		# TODO rounded corners ;)

	def on_show(self, button):
		if button.get_active():
			#loaded = bool(self.pageview)
			self.show_pageview()
			#if not loaded:
			#	self.load_children()
			#self.vbox.set_no_show_all(False)
			#self.vbox.show()
		else:
			self.hide_pageview()
			#self.vbox.hide()
			#self.vbox.set_no_show_all(True)

	def show_pageview(self):
		if not self.pageview:
			pageview = PageView(self.ui, secondary=True)
			swindow = pageview.view.get_parent()
			swindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)

			w, h = self.size_request()
			swindow.set_size_request(w, 200) # fixed height, matched width
			#swindow.set_size_request(w, -1) # full height, matched width	
			# TODO make sure this resized on window resize
			
			page = self.ui.notebook.get_page(self.path)
			pageview.set_page(page)

			self.pageview = pageview
			self.add(pageview)

		self.pageview.set_no_show_all(False)
		self.pageview.show_all()

	def hide_pageview(self):
		if self.pageview:
			self.pageview.hide()
			self.pageview.set_no_show_all(True)


Follow ups

References