Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SugarCeibalNotifica.py587
-rw-r--r--activity/activity.info2
2 files changed, 588 insertions, 1 deletions
diff --git a/SugarCeibalNotifica.py b/SugarCeibalNotifica.py
new file mode 100644
index 0000000..d961153
--- /dev/null
+++ b/SugarCeibalNotifica.py
@@ -0,0 +1,587 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Plan Ceibal - Uruguay
+# Flavio Danesse - fdanesse@activitycentral.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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import shelve
+import os
+import gtk
+import sys
+import gobject
+
+from ceibal.notifier.store import *
+
+from sugar.activity import activity
+from sugar.activity.widgets import StopButton
+
+BASE = os.path.dirname(__file__)
+
+pixbuf1 = gtk.gdk.pixbuf_new_from_file_at_size(
+ os.path.join(BASE, "Iconos", "ceibal-gris.png"), 32,32)
+
+pixbuf2 = gtk.gdk.pixbuf_new_from_file_at_size(
+ os.path.join(BASE, "Iconos", "ceibal.png"), 32,32)
+
+class CeibalNotifica(activity.Activity):
+
+ def __init__(self, handle):
+
+ activity.Activity.__init__(self, handle, False)
+
+ self.set_title("Ceibal Notifica")
+ self.set_border_width(2)
+
+ self.text_buffer = None
+ self.text_view = None
+ self.store = None
+ self.listore_model = None
+ self.modelsort = None
+ self.notify_store = None
+ self.info_toolbar = None
+ self.control_toolbar = None
+ self.filter = None
+
+ self.set_layout()
+ self.show_all()
+
+ self.connect("delete_event", self.delete_event)
+ self.notify_store.connect("show_notify", self.show_notify)
+ self.notify_store.connect("delete_notify", self.delete_notify)
+ self.notify_store.connect("marcar_notify", self.marcar_notify)
+ self.control_toolbar.connect("get_filter", self.get_filter)
+ self.control_toolbar.connect("make_filter", self.make_filter)
+ self.control_toolbar.connect("show_filter", self.show_filter)
+ self.control_toolbar.connect("exit", self.salir)
+
+ self.load_notify()
+ self.notify_store.columns_autosize()
+
+ def set_layout(self):
+
+ self.listore_model = ListoreModel()
+ self.modelsort = gtk.TreeModelSort(self.listore_model)
+ self.notify_store = Notify_Store(self.modelsort)
+ self.text_buffer = gtk.TextBuffer()
+
+ self.text_view = gtk.TextView(buffer=self.text_buffer)
+ self.text_view.set_editable(False)
+ self.text_view.set_wrap_mode(gtk.WRAP_WORD)
+ self.text_view.set_justification(gtk.JUSTIFY_FILL)
+ self.text_view.set_pixels_above_lines(5)
+ self.text_view.set_pixels_below_lines(15)
+ self.text_view.set_pixels_inside_wrap(5)
+ self.text_view.set_left_margin(10)
+ self.text_view.set_right_margin(10)
+
+ hpanel = gtk.HPaned()
+ self.store = Store()
+
+ scroll = gtk.ScrolledWindow()
+ scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scroll.add_with_viewport(self.notify_store)
+
+ hpanel.pack1(scroll, resize = False, shrink = True)
+
+ scroll = gtk.ScrolledWindow()
+ scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scroll.add_with_viewport(self.text_view)
+
+ hpanel.pack2(scroll, resize = False, shrink = True)
+
+ vbox = gtk.VBox()
+
+ self.info_toolbar = ToolbarInfo()
+ self.control_toolbar = ToolbarControl()
+
+ vbox.pack_start(self.control_toolbar, False, False, 0)
+ vbox.pack_start(hpanel, True, True, 0)
+ vbox.pack_start(self.info_toolbar, False, False, 0)
+
+ hpanel.show_all()
+ self.set_canvas(vbox)
+
+ def get_filter(self, widget, value):
+
+ filtro_nivel2 = self.store.db.get_categories(value=value)
+ widget.set_filter(filtro_nivel2)
+
+ def make_filter(self, widget, value):
+
+ self.filter = value
+ self.load_notify()
+ widget.make_filter(self.filter)
+
+ def show_notify(self, widget, text, info):
+
+ self.text_buffer.set_text(text)
+ self.info_toolbar.set_text(info)
+
+ def delete_notify(self, widget, path):
+
+ iter = widget.get_model().get_iter(path)
+ id_registro = int(widget.get_model().get_value(iter, 1))
+ self.store.db.remove_message(id_registro)
+ iter = self.listore_model.get_iter(path)
+ self.listore_model.remove(iter)
+ self.update_view()
+
+ def show_filter(self, widget):
+
+ if self.filter[0] == 'Ninguno' and self.filter[1] == 'Ninguno': return
+
+ valor = 0
+
+ if self.filter[0] == 'Prioridad': valor = 2
+ if self.filter[0] == 'Lanzamiento': valor = 5
+ if self.filter[0] == 'Expiración': valor = 6
+ if self.filter[0] == 'Tipo': valor = 7
+
+ iter = self.listore_model.get_iter_first()
+
+ while iter:
+ val = self.listore_model.get_value(iter, valor)
+ path = self.listore_model.get_path(iter)
+ iter = self.listore_model.iter_next(self.listore_model.get_iter(path))
+
+ if val != self.filter[1]:
+ self.listore_model.remove(self.listore_model.get_iter(path))
+
+ def marcar_notify(self, widget, path):
+
+ iter = widget.get_model().get_iter(path)
+ id_registro = int(widget.get_model().get_value(iter, 1))
+ marca = not self.store.db.is_fav(id_registro)
+ self.store.db.set_fav(id_registro, fav=marca)
+ iter = self.listore_model.get_iter(path)
+ fav = self.store.db.is_fav(id_registro)
+ self.listore_model.set_value(iter, 8, fav)
+ self.update_view()
+
+ def update_view(self):
+
+ path = self.notify_store.get_path_selected()
+
+ if path == None: path = 0
+
+ self.notify_store.treeselection.select_path(path)
+
+ try:
+ iter = self.listore_model.get_iter(path)
+
+ if self.listore_model.get_value(iter, 8):
+ self.listore_model.set_value(iter, 0, pixbuf2)
+
+ else:
+ self.listore_model.set_value(iter, 0, pixbuf1)
+
+ except:
+ self.text_buffer.set_text('')
+ self.info_toolbar.set_text('')
+
+ def load_notify(self):
+
+ notificaciones = self.store.db.get_messages([])
+ self.listore_model.clear()
+
+ for notif in notificaciones:
+ self.add_notify(notif)
+
+ def add_notify(self, notify):
+
+ mark = pixbuf1
+
+ if bool(notify['fav']): mark = pixbuf2
+
+ notify = [mark, notify['id'], notify['priority'], notify['title'], notify['text'],
+ notify['launched'], notify['expires'], notify['type'], bool(notify['fav'])]
+ io = self.modelsort.get_model().append(notify)
+ sel = self.notify_store.get_selection()
+ il = self.modelsort.convert_child_iter_to_iter(None, io)
+ sel.select_iter(il)
+
+ def delete_event(self, widget, event):
+
+ self.salir()
+
+ return False
+
+ def salir(self, widget=None):
+
+ sys.exit(0)
+
+class ListoreModel(gtk.ListStore):
+
+ def __init__(self):
+
+ gtk.ListStore.__init__(self, gtk.gdk.Pixbuf,
+ gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
+
+class Notify_Store(gtk.TreeView):
+
+ __gsignals__ = {
+ "show_notify": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, (gobject.TYPE_STRING,
+ gobject.TYPE_STRING)),
+ "delete_notify": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
+ "marcar_notify": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))}
+
+ def __init__(self, model):
+
+ gtk.TreeView.__init__(self, model)
+
+ self.set_property("rules-hint", True)
+ self.add_events(gtk.gdk.BUTTON2_MASK)
+
+ self.connect("button-press-event", self.handle_click)
+
+ self.set_headers_clickable(True)
+ self.set_columns()
+ self.show_all()
+
+ self.treeselection = self.get_selection()
+ self.treeselection.set_mode(gtk.SELECTION_SINGLE)
+ self.treeselection.set_select_function(
+ self.func_selections,
+ self.get_model(), True)
+
+ def set_columns(self):
+
+ self.append_column(self.make_column_mark('', 0, True))
+ self.append_column(self.make_column('id', 1, False))
+ self.append_column(self.make_column('Prioridad', 2, True))
+ self.append_column(self.make_column('Título', 3, True))
+ self.append_column(self.make_column('Notificación', 4, False))
+ self.append_column(self.make_column('Lanzamiento', 5, False))
+ self.append_column(self.make_column('Expira', 6, True))
+ self.append_column(self.make_column('Tipo', 7, True))
+ self.append_column(self.make_column('Favorito', 8, False))
+
+ def make_column_mark(self, text, index, visible):
+
+ render = gtk.CellRendererPixbuf()
+ column = gtk.TreeViewColumn(text, render, pixbuf = index)
+ column.set_property("visible", visible)
+ return column
+
+ def make_column(self, text, index, visible):
+
+ render = gtk.CellRendererText()
+ column = gtk.TreeViewColumn(text, render, text=index)
+ column.set_sort_column_id(index)
+ column.set_property('visible', visible)
+ return column
+
+ def func_selections(self, selection, model, path, is_selected, user_data):
+
+ iter = self.get_model().get_iter(path)
+ texto = self.get_model().get_value(iter, 4)
+ nid = self.get_model().get_value(iter, 1)
+ lanzamiento = self.get_model().get_value(iter, 5)
+ fav = self.get_model().get_value(iter, 8)
+
+ if fav:
+ fav = "Si"
+
+ else:
+ fav = "No"
+
+ info = "id: %s Lanzamiento: %s Favorito: %s" % (nid, lanzamiento, fav)
+ self.emit("show_notify", texto, info)
+
+ return True
+
+ def handle_click(self, widget, event):
+
+ boton = event.button
+ pos = (int(event.x), int(event.y))
+ tiempo = event.time
+
+ try:
+ path, col, x, y = widget.get_path_at_pos(pos[0], pos[1])
+
+ if boton == 1:
+ return
+
+ elif boton == 3:
+ self.get_menu(boton, pos, tiempo, path)
+ return
+
+ elif boton == 2:
+ return
+
+ except:
+ pass
+
+ def get_menu(self, boton, pos, tiempo, path):
+
+ menu = gtk.Menu()
+
+ eliminar = gtk.MenuItem("Eliminar Notificación.")
+ menu.append(eliminar)
+
+ eliminar.connect_object("activate", self.emit_delete_notify, path)
+ iter = self.get_model().get_iter(path)
+ fav = self.get_model().get_value(iter, 8)
+
+ marcar = gtk.MenuItem("Marcar Como Favorito.")
+
+ if fav: marcar = gtk.MenuItem("Desmarcar Como Favorito.")
+
+ menu.append(marcar)
+
+ marcar.connect_object("activate", self.emit_marcar_notify, path)
+ menu.show_all()
+
+ gtk.Menu.popup(menu, None, None, None, boton, tiempo)
+
+ def get_path_selected(self):
+
+ (model, iter) = self.get_selection().get_selected()
+ path = None
+
+ if iter:
+ treemodelrow = model[iter]
+ path = treemodelrow.path
+
+ return path
+
+ def emit_delete_notify(self, path):
+
+ self.emit("delete_notify", path)
+
+ def emit_marcar_notify(self, path):
+
+ self.emit("marcar_notify", path)
+
+class ToolbarInfo(gtk.Toolbar):
+
+ def __init__(self):
+
+ gtk.Toolbar.__init__(self)
+
+ self.modify_bg(gtk.STATE_NORMAL,
+ gtk.gdk.Color(0, 20000, 0, 1))
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(0, -1)
+ separator.set_expand(True)
+ self.insert(separator, -1)
+
+ item = gtk.ToolItem()
+ self.info_label = gtk.Label("")
+ self.info_label.modify_fg(gtk.STATE_NORMAL,
+ gtk.gdk.Color(65535, 65535, 65535,1))
+ self.info_label.show()
+ item.add(self.info_label)
+ self.insert(item, -1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(0, -1)
+ separator.set_expand(True)
+ self.insert(separator, -1)
+
+ def set_text(self, text=""):
+
+ self.info_label.set_text(text)
+
+class ToolbarControl(gtk.Toolbar):
+
+ __gsignals__ = {
+ "get_filter": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, (gobject.TYPE_STRING,)),
+ "make_filter": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
+ "show_filter": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, []),
+ "exit": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, [])}
+
+ def __init__(self):
+
+ gtk.Toolbar.__init__(self)
+
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0, 0, 1))
+ self.filter_combo1 = None
+ self.filter_combo2 = None
+
+ self.set_layout()
+ self.show_all()
+
+ self.filter_combo1.connect("change_selection", self.emit_get_filter)
+ self.filter_combo2.connect("change_selection", self.emit_make_filter)
+
+ def set_layout(self):
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(10, -1)
+ separator.set_expand(False)
+ self.insert(separator, -1)
+
+ item = gtk.ToolItem()
+ label = gtk.Label("Filtrar por:")
+ label.modify_fg(gtk.STATE_NORMAL,
+ gtk.gdk.Color(65535, 65535, 65535,1))
+ label.show()
+ item.add(label)
+ self.insert(item, -1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(10, -1)
+ separator.set_expand(False)
+ self.insert(separator, -1)
+
+ item = gtk.ToolItem()
+ self.filter_combo1 = Combo()
+ self.filter_combo1.set_items(["Tipo", "Prioridad",
+ "Lanzamiento", "Expiración"])
+ self.filter_combo1.show()
+ item.add(self.filter_combo1)
+ self.insert(item, -1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(10, -1)
+ separator.set_expand(False)
+ self.insert(separator, -1)
+
+ item = gtk.ToolItem()
+ label = gtk.Label("Seleccionar:")
+ label.modify_fg(gtk.STATE_NORMAL,
+ gtk.gdk.Color(65535, 65535, 65535,1))
+ label.show()
+ item.add(label)
+ self.insert(item, -1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(10, -1)
+ separator.set_expand(False)
+ self.insert(separator, -1)
+
+ item = gtk.ToolItem()
+ self.filter_combo2 = Combo()
+ self.filter_combo2.set_items([])
+ self.filter_combo2.get_model().clear()
+ self.filter_combo2.show()
+ item.add(self.filter_combo2)
+ self.insert(item, -1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(0, -1)
+ separator.set_expand(True)
+ self.insert(separator, -1)
+
+ stopbutton = gtk.ToolButton()
+ image = gtk.Image()
+ image.set_from_stock(gtk.STOCK_STOP, 32)
+ stopbutton.set_icon_widget(image)
+ image.show()
+ stopbutton.connect('clicked', self.emit_exit)
+ self.insert(stopbutton, -1)
+ stopbutton.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_size_request(10, -1)
+ separator.set_expand(False)
+ self.insert(separator, -1)
+
+ def emit_get_filter(self, widget, value):
+
+ self.emit("get_filter", value)
+
+ def emit_make_filter(self, widget, value):
+
+ val1 = self.filter_combo1.get_value_select()
+ self.emit("make_filter", [val1,value])
+
+ def set_filter(self, lista):
+
+ self.filter_combo2.set_items(lista)
+
+ def make_filter(self, filter):
+
+ if filter[0] == 'Ninguno':
+ self.filter_combo2.get_model().clear()
+
+ self.emit('show_filter')
+
+ def emit_exit(self, widget):
+
+ self.emit('exit')
+
+class Combo(gtk.ComboBox):
+
+ __gsignals__ = {
+ "change_selection": (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, (gobject.TYPE_STRING,))}
+
+ def __init__(self):
+
+ gtk.ComboBox.__init__(self, gtk.ListStore(str))
+
+ cell = gtk.CellRendererText()
+ self.pack_start(cell, True)
+ self.add_attribute(cell, 'text', 0)
+
+ self.show_all()
+
+ self.connect("changed", self.emit_selection)
+
+ def set_items(self, items):
+
+ self.get_model().clear()
+ self.append_text("Ninguno")
+
+ for item in items:
+ self.append_text(str(item))
+
+ self.set_active(0)
+
+ def emit_selection(self, widget):
+
+ indice = widget.get_active()
+
+ if indice < 0: return
+
+ iter = widget.get_model().get_iter(indice)
+ value = widget.get_model().get_value(iter, 0)
+
+ self.emit("change_selection", value)
+
+ def get_value_select(self):
+
+ indice = self.get_active()
+
+ if indice < 0: return None
+
+ iter = self.get_model().get_iter(indice)
+ value = self.get_model().get_value(iter, 0)
+
+ return value
+ \ No newline at end of file
diff --git a/activity/activity.info b/activity/activity.info
index 0f30591..1157ae8 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -2,7 +2,7 @@
name = CeibalNotifica
activity_version = 1
bundle_id = org.laptop.CeibalNotifica
-exec = sugar-activity CeibalNotifica.CeibalNotifica
+exec = sugar-activity SugarCeibalNotifica.CeibalNotifica
icon = ceibal-notifica
show_launcher = yes
license = GPLv3+