Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Widgets.py
diff options
context:
space:
mode:
Diffstat (limited to 'Widgets.py')
-rw-r--r--Widgets.py423
1 files changed, 423 insertions, 0 deletions
diff --git a/Widgets.py b/Widgets.py
new file mode 100644
index 0000000..fb87cbf
--- /dev/null
+++ b/Widgets.py
@@ -0,0 +1,423 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# 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 commands
+
+import gi
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import Pango
+from gi.repository import GdkPixbuf
+from gi.repository import GObject
+
+from face import Face
+
+BASE = os.path.dirname(__file__)
+
+PITCH_MAX = 200
+RATE_MAX = 200
+
+def get_voices():
+ """Devuelve un diccionario del tipo: {"portugal": "pt-pt", . . .}"""
+
+ ret = commands.getoutput('espeak --voices')
+
+ voces = []
+ for linea in ret .split("\n"):
+ voz = linea.split(" ")
+
+ vv = []
+ for valor in voz:
+ if valor: vv.append(valor)
+
+ voces.append(vv)
+
+ voces = voces[1:]
+
+ voices = {}
+ for voz in voces:
+ if voz[2] != "M":
+ voices[voz[2]] = voz[1]
+ else:
+ voices[voz[3]] = voz[1]
+
+ return voices
+
+def get_separador(draw = False, ancho = 0, expand = False):
+ """ Devuelve un separador generico."""
+
+ separador = Gtk.SeparatorToolItem()
+ separador.props.draw = draw
+ separador.set_size_request(ancho, -1)
+ separador.set_expand(expand)
+ return separador
+
+def get_boton(archivo, flip = False, color = Gdk.Color(65000, 65000, 65000)):
+ """ Devuelve un toolbarbutton generico."""
+
+ boton = Gtk.ToolButton()
+ imagen = Gtk.Image()
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(archivo, 32, 32)
+ if flip: pixbuf = pixbuf.flip(True)
+ imagen.set_from_pixbuf(pixbuf)
+ imagen.modify_bg(0, color)
+ boton.set_icon_widget(imagen)
+ imagen.show()
+ boton.show()
+ return boton
+
+class Speaking(Gtk.Box):
+ """Cara con Entrada de texto."""
+
+ __gsignals__ = {"speak":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_STRING, ))}
+
+ def __init__(self):
+
+ Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
+
+ self.entrycombo = None
+ self.entry = None
+ self.face = None
+
+ self.entrycombo = Gtk.ComboBoxText.new_with_entry()
+
+ self.entry = self.entrycombo.get_child()
+ self.entry.can_activate_accel(True)
+
+ font = Pango.FontDescription('sans bold 24')
+ self.entry.modify_font(font)
+
+ self.face = Face()
+
+ self.pack_start(self.face, True, True, 0)
+ self.pack_start(self.entrycombo, False, True, 0)
+
+ self.show_all()
+
+ self.entrycombo.connect("changed", self._combo_changed_cb)
+
+ self.entry.connect('activate', self._entry_activate_cb)
+ self.entry.connect("key-press-event", self._entry_key_press_cb)
+ self.entry.connect("move-cursor", self._cursor_moved_cb)
+ self.entry.connect("changed", self._cursor_moved_cb)
+
+ def _cursor_moved_cb(self, entry):
+ """Mira lo que el usuario escribe."""
+
+ index = entry.get_property('cursor_position')
+ layout = entry.get_layout()
+ pos = layout.get_cursor_pos(index)
+ x = pos[0].x / Pango.SCALE - entry.get_property('scroll_offset')
+ y = entry.get_allocation().y
+ self.face.look_at(pos=(x, y))
+
+ def _combo_changed_cb(self, combo):
+ if not self.entry.is_focus():
+ self.entry.grab_focus()
+ self.entry.select_region(0, -1)
+
+ def look_at(self, pos):
+ """Le dice a la cara hacia donde mirar."""
+
+ self.face.look_at(pos)
+
+ def _entry_activate_cb(self, entry):
+ """Cuando el usuario presiona enter en
+ la entrada de texto."""
+
+ text = entry.get_text()
+
+ if text:
+ self.emit('speak', text)
+
+ history = self.entrycombo.get_model()
+ if len(history) == 0 or history[-1][0] != text:
+ self.entrycombo.append_text(text)
+ while len(history) > 20:
+ self.entrycombo.remove_text(0)
+ self.entrycombo.set_active(len(history) - 1)
+ entry.select_region(0, -1)
+
+ def _entry_key_press_cb(self, combo, event):
+ """Para navegar el historial de entradas
+ en la entrada de texto, con el teclado."""
+
+ keyname = Gdk.keyval_name(event.keyval)
+ index = self.entrycombo.get_active()
+
+ if keyname == "Up":
+ if index > 0: index -= 1
+ self.entrycombo.set_active(index)
+ self.entry.select_region(0, -1)
+ return True
+
+ elif keyname == "Down":
+ if index < len(self.entrycombo.get_model()) - 1: index += 1
+ self.entrycombo.set_active(index)
+ self.entry.select_region(0, -1)
+ return True
+
+ return False
+
+
+class Toolbar(Gtk.Toolbar):
+ """Toolbar Principal."""
+
+ __gsignals__ = {"switch-voice":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_STRING, )),
+ "switch-desktop":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_STRING, )),
+ "switch-toolbar":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_STRING, ))}
+
+ def __init__(self):
+
+ Gtk.Toolbar.__init__(self)
+ self.modify_bg(0, Gdk.Color(0, 0, 0))
+
+ self.voices = get_voices()
+
+ self.insert(get_separador(draw = False, ancho = 32, expand = False), -1)
+
+ archivo = os.path.join(BASE, "icons", "face.svg")
+ boton = get_boton(archivo, flip = False, color = Gdk.Color(0, 0, 0))
+ self.insert(boton, -1)
+
+ archivo = os.path.join(BASE, "icons", "mode-type.svg")
+ boton = get_boton(archivo, flip = False, color = Gdk.Color(0, 0, 0))
+ self.insert(boton, -1)
+ #boton.connect("clicked", self.emit_switch_desktop, "speaking")
+
+ archivo = os.path.join(BASE, "icons", "mode-robot.svg")
+ boton = get_boton(archivo, flip = False, color = Gdk.Color(0, 0, 0))
+ self.insert(boton, -1)
+ #boton.connect("clicked", self.emit_switch_desktop, "robot")
+
+ archivo = os.path.join(BASE, "icons", "mode-chat.svg")
+ boton = get_boton(archivo, flip = False, color = Gdk.Color(0, 0, 0))
+ self.insert(boton, -1)
+ #boton.connect("clicked", self.emit_switch_desktop, "chat")
+
+ item = Gtk.ToolItem()
+ combo = Gtk.ComboBoxText()
+ voces = self.voices.keys()
+ for key in sorted(voces):
+ combo.append_text(key)
+ combo.set_active(0)
+ combo.connect('changed', self.emit_switch_voice)
+ item.add(combo)
+ self.insert(item, -1)
+
+ archivo = os.path.join(BASE, "icons", "voice.svg")
+ boton = get_boton(archivo, flip = False, color = Gdk.Color(0, 0, 0))
+ self.insert(boton, -1)
+ boton.connect("clicked", self.emit_switch_toolbar, "pitch-rate")
+
+ archivo = os.path.join(BASE, "icons", "face.svg")
+ boton = get_boton(archivo, flip = False, color = Gdk.Color(0, 0, 0))
+ self.insert(boton, -1)
+ boton.connect("clicked", self.emit_switch_toolbar, "face")
+
+ self.show_all()
+
+ def emit_switch_desktop(self, widget, value):
+ """Cambiar entre chat, speaking y robot."""
+
+ self.emit("switch-desktop", value)
+
+ def emit_switch_toolbar(self, widget, value):
+ """Para que se muestre la toolbar pitch-rate o face."""
+
+ self.emit("switch-toolbar", value)
+
+ def emit_switch_voice(self, widget):
+ """Cuando cambia el lenguaje."""
+
+ self.emit("switch-voice", self.voices[widget.get_active_text()])
+
+class ToolbarPitchRate(Gtk.Toolbar):
+ """Toolbar con opciones pitch y rate."""
+
+ __gsignals__ = {"pitch":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_INT, )),
+ "rate":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_INT, ))}
+
+ def __init__(self):
+
+ Gtk.Toolbar.__init__(self)
+ self.modify_bg(0, Gdk.Color(0, 0, 0))
+
+ self.pitch = 0
+ self.rate = 0
+
+ self.insert(get_separador(draw = False, ancho = 32, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ label = Gtk.Label("Pitch:")
+ label.modify_fg(0, Gdk.Color(65000, 65000, 65000))
+ item.add(label)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ pitchadj = Gtk.Adjustment(self.pitch, 0,
+ PITCH_MAX, 1, PITCH_MAX / 10, 0)
+ pitchbar = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL)
+ pitchbar.set_adjustment(pitchadj)
+ pitchbar = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL)
+ pitchbar.set_adjustment(pitchadj)
+ pitchbar.set_draw_value(False)
+ pitchbar.set_size_request(240, 15)
+ item.add(pitchbar)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ label = Gtk.Label("Rate:")
+ label.modify_fg(0, Gdk.Color(65000, 65000, 65000))
+ item.add(label)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ rateadj = Gtk.Adjustment(self.rate, 0,
+ RATE_MAX, 1, RATE_MAX / 10, 0)
+ ratebar = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL)
+ ratebar.set_adjustment(rateadj)
+ ratebar.set_draw_value(False)
+ ratebar.set_size_request(240, 15)
+ item.add(ratebar)
+ self.insert(item, -1)
+
+ self.show_all()
+
+ pitchadj.connect("value_changed", self.pitch_adjusted)
+ rateadj.connect("value_changed", self.rate_adjusted)
+
+ def pitch_adjusted(self, widget):
+ """Cuando cambia pitch."""
+
+ self.pitch = int(widget.get_value())
+ self.emit('pitch', self.pitch)
+ #self.face.say_notification(_("pitch adjusted"))
+
+ def rate_adjusted(self, widget):
+ """Cuando cambia rate."""
+
+ self.rate = int(widget.get_value())
+ self.emit('rate', self.rate)
+ #self.face.say_notification(_("rate adjusted"))
+
+class ToolbarFace(Gtk.Toolbar):
+ """Toolbar con opciones para la cara."""
+
+ __gsignals__ = {"number-eyes":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_INT, )),
+ "switch-type-mouth":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_STRING, )),
+ "switch-type-eyes":(GObject.SIGNAL_RUN_FIRST,
+ GObject.TYPE_NONE, (GObject.TYPE_STRING, ))}
+
+ def __init__(self):
+
+ Gtk.Toolbar.__init__(self)
+ self.modify_bg(0, Gdk.Color(0, 0, 0))
+
+ self.insert(get_separador(draw = False, ancho = 32, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ label = Gtk.Label("Mouth:")
+ label.modify_fg(0, Gdk.Color(65000, 65000, 65000))
+ item.add(label)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ combo = Gtk.ComboBoxText()
+ combo.append_text("Simple")
+ combo.append_text("Waveform")
+ combo.append_text("Frequency")
+ combo.set_active(0)
+ combo.connect('changed', self.emit_switch_type_mouth)
+ item.add(combo)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ label = Gtk.Label("Eyes:")
+ label.modify_fg(0, Gdk.Color(65000, 65000, 65000))
+ item.add(label)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ combo = Gtk.ComboBoxText()
+ combo.append_text("Round")
+ combo.append_text("Glasses")
+ combo.set_active(0)
+ combo.connect('changed', self.emit_switch_type_eyes)
+ item.add(combo)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ label = Gtk.Label("Eyes number:")
+ label.modify_fg(0, Gdk.Color(65000, 65000, 65000))
+ item.add(label)
+ self.insert(item, -1)
+
+ self.insert(get_separador(draw = False, ancho = 5, expand = False), -1)
+
+ item = Gtk.ToolItem()
+ numeyesadj = Gtk.Adjustment(2, 1, 5, 1, 1, 0)
+ numeyesbar = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL)
+ numeyesbar.set_adjustment(numeyesadj)
+ numeyesbar.set_draw_value(False)
+ numeyesbar.set_size_request(240, 15)
+ item.add(numeyesbar)
+ self.insert(item, -1)
+
+ self.show_all()
+
+ numeyesadj.connect("value_changed", self.eyes_changed_number)
+
+ def emit_switch_type_mouth(self, widget):
+ """Cuando cambia el tipo de boca."""
+
+ self.emit("switch-type-mouth", widget.get_active_text())
+
+ def emit_switch_type_eyes(self, widget):
+ """Cuando cambia el tipo de ojos."""
+
+ self.emit("switch-type-eyes", widget.get_active_text())
+
+ def eyes_changed_number(self, widget):
+ """Cuando se cambia la cantidad de ojos."""
+
+ self.emit('number-eyes', int(widget.get_value()))
+ #self.face.say_notification(_("eyes changed"))
+ \ No newline at end of file