Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/bookview.py
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@member.fsf.org>2009-03-02 06:03:47 (GMT)
committer Walter Bender <walter@walter-laptop.(none)>2009-03-02 14:45:14 (GMT)
commit0b218d3045918e3c32985ced34eb70aa2764e387 (patch)
tree4462b4356a28ea7f5367a45225d379228f0ed16d /bookview.py
parentedb525a310c2c165de2ee26c1885cb676f867287 (diff)
Move sugar-free components to infoslicer/ core-library directory
Diffstat (limited to 'bookview.py')
-rw-r--r--bookview.py269
1 files changed, 269 insertions, 0 deletions
diff --git a/bookview.py b/bookview.py
new file mode 100644
index 0000000..fc9af86
--- /dev/null
+++ b/bookview.py
@@ -0,0 +1,269 @@
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os
+import gtk
+import logging
+import gobject
+from gettext import gettext as _
+
+from sugar.graphics.toolbutton import ToolButton
+from sugar.activity.activity import get_bundle_path, get_activity_root
+from sugar.graphics.style import *
+
+from toolbar import WidgetItem, ButtonItem
+
+logger = logging.getLogger('infoslicer')
+
+PUBLISH = 0
+TITLE = 1
+
+class BookView(gtk.VBox):
+ def sync(self):
+ if not self._changing:
+ return
+ gobject.source_remove(self._changing)
+ index, column = self.tree.get_cursor()
+ self._cursor_changed(index)
+
+ def __init__(self, book, name, tooltip, custom):
+ gtk.VBox.__init__(self)
+ self.book = book
+ self._changing = None
+ self._check = None
+
+ title = gtk.Toolbar()
+
+ # title checkbox
+
+ if custom:
+ self._check = gtk.CheckButton()
+ self._check.props.can_focus = False
+ self._check.props.tooltip_text = \
+ _('Articles are ready to be published')
+ self._check.connect('toggled', self._check_toggled_cb)
+ check_box = gtk.HBox()
+ check_box.set_size_request(50, -1)
+ check_box.pack_start(self._check, True, False)
+ title.insert(WidgetItem(check_box), -1)
+ else:
+ title.insert(WidgetItem(gtk.Label(' ')), -1)
+
+ # title caption
+
+ caption_label = gtk.Label(name)
+ caption_label.props.tooltip_text = tooltip
+ caption_label.modify_fg(gtk.STATE_NORMAL, COLOR_WHITE.get_gdk_color())
+ caption_box = gtk.HBox()
+ caption_box.pack_start(caption_label, False)
+ caption = gtk.EventBox()
+ caption.add(caption_box)
+ caption.modify_bg(gtk.STATE_NORMAL, COLOR_TOOLBAR_GREY.get_gdk_color())
+ title.insert(WidgetItem(caption), -1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_expand(True)
+ title.insert(separator, -1)
+
+ # create article button
+
+ if custom:
+ create = ButtonItem('add',
+ label=_('Create'),
+ tooltip_text=_('Create new article'))
+ create.connect('clicked', self._create_cb)
+ title.insert(create, -1)
+ else:
+ logger.debug('BookView(%s): listen for new articles' % name)
+ self.book.connect('article-added', self._article_added_cb)
+
+ # delete article button
+
+ delete = ButtonItem('edit-delete',
+ label=_('Delete'),
+ tooltip_text=_('Delete current article'))
+ delete.connect('clicked', self._delete_cb)
+ title.insert(delete, -1)
+
+ # move buttons
+
+ downward = ButtonItem('down',
+ label=_('Move downward'),
+ tooltip_text=_('Move article downward'))
+ downward.connect('clicked', self._swap_cb, +1)
+ title.insert(downward, -1)
+ upward = ButtonItem('up',
+ label=_('Move upward'),
+ tooltip_text=_('Move article upward'))
+ upward.connect('clicked', self._swap_cb, -1)
+ title.insert(upward, -1)
+
+ # tree
+
+ self.store = gtk.ListStore(bool, str)
+ self.tree = gtk.TreeView(self.store)
+ self.tree.props.headers_visible = False
+ self.tree.connect('cursor-changed', self._cursor_changed_cb)
+
+ cell = gtk.CellRendererToggle()
+ cell.connect('toggled', self._cell_toggled_cb)
+ cell.props.activatable = True
+
+ column = self.tree.insert_column_with_attributes(0, '', cell, active=0)
+ column.props.sizing = gtk.TREE_VIEW_COLUMN_FIXED
+ column.props.fixed_width = 50
+ column.props.visible = custom
+
+ cell = gtk.CellRendererText()
+ cell.connect('edited', self._cell_edited_cb)
+ cell.props.editable = True
+ self.tree.insert_column_with_attributes(1, '', cell, text=1)
+
+ for i in self.book.index:
+ self.store.append((i['ready'], i['title']))
+
+ # scrolled tree
+
+ tree_scroll = gtk.ScrolledWindow()
+ tree_scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ tree_scroll.add(self.tree)
+
+ self.pack_start(title, False)
+ self.pack_start(tree_scroll)
+
+ if len(self.store):
+ self.tree.set_cursor(0, self.tree.get_column(1), False)
+ if custom:
+ self._update_check(self.store[0][PUBLISH])
+
+ self.show_all()
+
+ def _article_added_cb(self, book, article):
+ logger.debug('_article_added_cb: new article %s' % article)
+
+ self.book.props.article = article
+ self.store.append((False, article))
+ self.tree.set_cursor(len(self.store)-1, self.tree.get_column(1), False)
+
+ def _create_cb(self, widget):
+ def find_name(list, prefix, uniq):
+ name = uniq == 0 and prefix or ('%s %d' % (prefix, uniq))
+ if not [i for i in list if i[TITLE] == name]:
+ return name
+ return find_name(list, prefix, uniq+1)
+
+ if self._changing:
+ gobject.source_remove(self._changing)
+ self._changing = None
+
+ name = find_name(self.store, _('New article'), 0)
+ self.book.props.article = name
+ self.store.append((False, name))
+ self.tree.set_cursor(len(self.store)-1, self.tree.get_column(1), True)
+ self._update_check(self.store[-1][PUBLISH])
+
+ def _delete_cb(self, widget):
+ index, column = self.tree.get_cursor()
+ if not index:
+ return
+ index = index[0]
+
+ if self._changing:
+ gobject.source_remove(self._changing)
+ self._changing = None
+
+ self.book.remove(self.store[index][TITLE])
+ self.store.remove(self.tree.props.model.get_iter(index))
+
+ if len(self.store):
+ if index >= len(self.store):
+ index -= 1
+ self.tree.set_cursor(index, self.tree.get_column(1), False)
+ self._update_check(self.store[index][PUBLISH])
+
+ def _swap_cb(self, widget, delta):
+ old_index, column = self.tree.get_cursor()
+ if not old_index:
+ return
+
+ old_index = old_index[0]
+ new_index = old_index + delta
+
+ if new_index < 0:
+ new_index = len(self.store)-1
+ elif new_index >= len(self.store):
+ new_index = 0
+
+ self.book.index[old_index], self.book.index[new_index] = \
+ self.book.index[new_index], self.book.index[old_index]
+ self.store.swap(self.tree.props.model.get_iter(old_index),
+ self.tree.props.model.get_iter(new_index))
+
+ def _check_toggled_cb(self, widget):
+ for i, entry in enumerate(self.store):
+ entry[PUBLISH] = widget.props.active
+ self.book.index[i]['ready'] = widget.props.active
+ self._check.props.inconsistent = False
+
+ def _update_check(self, value):
+ if not self._check:
+ return
+
+ for i in self.store:
+ if i[PUBLISH] != value:
+ self._check.props.inconsistent = True
+ return
+ self._check.props.inconsistent = False
+ self._check.props.active = value
+
+ def _cell_toggled_cb(self, cell, index):
+ value = not self.store[index][PUBLISH]
+ self.store[index][PUBLISH] = value
+ self.book.index[int(index)]['ready'] = value
+ self._update_check(value)
+
+ def _cursor_changed_cb(self, widget):
+ if self._changing:
+ gobject.source_remove(self._changing)
+
+ index, column = self.tree.get_cursor()
+
+ if index != None:
+ self._changing = gobject.timeout_add(500, self._cursor_changed,
+ index)
+
+ def _cursor_changed(self, index):
+ self.book.props.article = self.store[index][TITLE]
+ self._changing = None
+ return False
+
+ def _cell_edited_cb(self, cell, index, newtext):
+ logger.debug('_cell_edited_cb(%s, %s)' % (index, newtext))
+
+ # Disallowed chars are < > and &
+ if newtext == "" or newtext.isspace() or '&' in newtext \
+ or '<' in newtext or '>' in newtext:
+ return
+
+ # If there is already an article with the new name in the theme,
+ # then we ignore the name change and highlight the existing article
+ overides = [i for i, row in enumerate(self.store)
+ if row[TITLE] == newtext]
+ if overides:
+ self.tree.set_cursor(overides[0], self.tree.get_column(1), False)
+ return
+
+ self.book.props.article.article_title = newtext
+ self.store[index][TITLE] = newtext