Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/createcardpanel.py
diff options
context:
space:
mode:
Diffstat (limited to 'createcardpanel.py')
-rw-r--r--createcardpanel.py436
1 files changed, 252 insertions, 184 deletions
diff --git a/createcardpanel.py b/createcardpanel.py
index 5fc1366..5671cd8 100644
--- a/createcardpanel.py
+++ b/createcardpanel.py
@@ -20,6 +20,7 @@
import gtk
from os import environ
from os.path import join, dirname, basename
+import hippo
import shutil
import tempfile
@@ -31,49 +32,70 @@ from xml.dom.minidom import parse
from sugar.graphics.objectchooser import ObjectChooser
from sugar import mime
from sugar.graphics import style
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.icon import Icon
+from sugar.graphics.palette import Palette
+from port.widgets import ToggleToolButton
+from port.widgets import CanvasRoundBox, ToolComboBox
+from port import chooser
import theme
+import speak.espeak
+import speak.widgets
+import speak.face
_logger = logging.getLogger('memorize-activity')
class CreateCardPanel(gtk.EventBox):
-
__gsignals__ = {
- 'add-pair': (SIGNAL_RUN_FIRST, None, 6 * [TYPE_PYOBJECT]),
- 'update-pair': (SIGNAL_RUN_FIRST, None, 6 * [TYPE_PYOBJECT]),
+ 'add-pair': (SIGNAL_RUN_FIRST, None, 8 * [TYPE_PYOBJECT]),
+ 'update-pair': (SIGNAL_RUN_FIRST, None, 8 * [TYPE_PYOBJECT]),
}
-
+
def __init__(self):
+ def make_label(icon_name, label):
+ label_box = gtk.HBox()
+ icon = Icon(
+ icon_name=icon_name,
+ icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR)
+ label_box.pack_start(icon, False)
+ label = gtk.Label(label)
+ label.modify_fg(gtk.STATE_NORMAL,
+ style.COLOR_TOOLBAR_GREY.get_gdk_color())
+ label_box.pack_start(label)
+ label_box.show_all()
+ return label_box
+
gtk.EventBox.__init__(self)
-
+
self.equal_pairs = False
self._updatebutton_sensitive = False
self._card1_has_sound = False
self._card2_has_sound = False
-
- # Set the add new pair buttom
- add_icon = join(dirname(__file__), 'images', 'pair-add.svg')
- add_image = gtk.Image()
- add_image.set_from_file(add_icon)
- self._addbutton = gtk.Button(' ' + _('Add as new pair'))
- self._addbutton.set_image(add_image)
- self._addbutton.connect('pressed', self.emit_add_pair)
- self._addbutton.set_size_request(
- theme.PAIR_SIZE + theme.PAD*4, -1)
- self._addbutton.set_sensitive(False)
- # Set update selected pair buttom
- update_icon = join(dirname(__file__), 'images', 'pair-update.svg')
- update_image = gtk.Image()
- update_image.set_from_file(update_icon)
- self._updatebutton = gtk.Button(' ' + _('Update selected pair'))
- self._updatebutton.set_image(update_image)
- self._updatebutton.connect('pressed', self.emit_update_pair)
- self._updatebutton.set_size_request(
- theme.PAIR_SIZE + theme.PAD*4, -1)
- self._updatebutton.set_sensitive(False)
+ # save buttons
+
+ buttons_bar = gtk.HBox()
+ buttons_bar.props.border_width = 10
+
+ self._addbutton = ToolButton(
+ tooltip=_('Add as new pair'),
+ sensitive=False)
+ self._addbutton.set_icon_widget(
+ make_label('pair-add', ' ' + _('Add')))
+ self._addbutton.connect('clicked', self.emit_add_pair)
+ buttons_bar.pack_start(self._addbutton, False)
+
+ self._updatebutton = ToolButton(
+ tooltip=_('Update selected pair'),
+ sensitive=False)
+ self._updatebutton.set_icon_widget(
+ make_label('pair-update', ' ' + _('Update')))
+ self._updatebutton.connect('clicked', self.emit_update_pair)
+ buttons_bar.pack_start(self._updatebutton, False)
# Set card editors
+
self.cardeditor1 = CardEditor()
self.cardeditor2 = CardEditor()
self.clean(None)
@@ -83,20 +105,20 @@ class CreateCardPanel(gtk.EventBox):
self.cardeditor2.connect('has-picture', self.receive_picture_signals)
self.cardeditor1.connect('has-sound', self.receive_sound_signals)
self.cardeditor2.connect('has-sound', self.receive_sound_signals)
-
- # Create table and add components to the table
- self.table = gtk.Table()
- self.table.set_homogeneous(False)
- self.table.set_col_spacings(theme.PAD)
- self.table.set_row_spacings(theme.PAD)
- self.table.set_border_width(theme.PAD)
- self.table.attach(self.cardeditor1, 0, 1, 0, 1, yoptions=gtk.SHRINK)
- self.table.attach(self.cardeditor2, 1, 2, 0, 1, yoptions=gtk.SHRINK)
- self.table.attach(self._addbutton, 0, 1, 1, 2, yoptions=gtk.SHRINK)
- self.table.attach(self._updatebutton, 1, 2, 1, 2, yoptions=gtk.SHRINK)
- self.add(self.table)
+
+ # edit panel
+
+ self.card_box = gtk.HBox()
+ self.card_box.pack_start(self.cardeditor1)
+ self.card_box.pack_start(self.cardeditor2)
+
+ box = gtk.VBox()
+ box.pack_start(self.card_box, False)
+ box.pack_start(buttons_bar, False)
+ self.add(box)
+
self.show_all()
-
+
def emit_add_pair(self, widget):
self._addbutton.set_sensitive(False)
if self.equal_pairs:
@@ -104,15 +126,18 @@ class CreateCardPanel(gtk.EventBox):
self.cardeditor1.get_text(),
self.cardeditor1.get_pixbuf(),
self.cardeditor1.get_pixbuf(),
- self.cardeditor1.get_snd(), self.cardeditor1.get_snd())
+ self.cardeditor1.get_snd(), self.cardeditor1.get_snd(),
+ self.cardeditor1.get_speak(), self.cardeditor1.get_speak()
+ )
else:
self.emit('add-pair', self.cardeditor1.get_text(),
self.cardeditor2.get_text(),
self.cardeditor1.get_pixbuf(),
self.cardeditor2.get_pixbuf(),
- self.cardeditor1.get_snd(), self.cardeditor2.get_snd())
+ self.cardeditor1.get_snd(), self.cardeditor2.get_snd(),
+ self.cardeditor1.get_speak(), self.cardeditor2.get_speak()
+ )
self.clean(None)
-
def emit_update_pair(self, widget):
self._addbutton.set_sensitive(False)
@@ -121,17 +146,21 @@ class CreateCardPanel(gtk.EventBox):
self.cardeditor1.get_text(),
self.cardeditor1.get_pixbuf(),
self.cardeditor1.get_pixbuf(),
- self.cardeditor1.get_snd(), self.cardeditor1.get_snd())
+ self.cardeditor1.get_snd(), self.cardeditor1.get_snd(),
+ self.cardeditor1.get_speak(), self.cardeditor1.get_speak()
+ )
else:
self.emit('update-pair', self.cardeditor1.get_text(),
self.cardeditor2.get_text(),
self.cardeditor1.get_pixbuf(),
self.cardeditor2.get_pixbuf(),
- self.cardeditor1.get_snd(), self.cardeditor2.get_snd())
+ self.cardeditor1.get_snd(), self.cardeditor2.get_snd(),
+ self.cardeditor1.get_speak(), self.cardeditor2.get_speak()
+ )
self.clean(None)
-
+
def pair_selected(self, widget, selected, newtext1, newtext2, aimg, bimg,
- asnd, bsnd):
+ asnd, bsnd, aspeak, bspeak):
if selected:
self.cardeditor1.set_text(newtext1)
self.cardeditor2.set_text(newtext2)
@@ -139,6 +168,8 @@ class CreateCardPanel(gtk.EventBox):
self.cardeditor2.set_pixbuf(bimg)
self.cardeditor1.set_snd(asnd)
self.cardeditor2.set_snd(bsnd)
+ self.cardeditor1.set_speak(aspeak)
+ self.cardeditor2.set_speak(bspeak)
self._addbutton.set_sensitive(True)
self._updatebutton.set_sensitive(selected)
self._updatebutton_sensitive = selected
@@ -146,16 +177,14 @@ class CreateCardPanel(gtk.EventBox):
def change_equal_pairs(self, widget, state):
self.equal_pairs = state
self.clean(None)
+
if self.equal_pairs:
- self.table.remove(self.cardeditor1)
- self.table.remove(self.cardeditor2)
- self.table.attach(self.cardeditor1, 0, 2, 0, 1,
- gtk.SHRINK, gtk.SHRINK)
+ if self.cardeditor2.parent:
+ self.card_box.remove(self.cardeditor2)
else:
- self.table.remove(self.cardeditor1)
- self.table.attach(self.cardeditor1, 0, 1, 0, 1, yoptions=gtk.SHRINK)
- self.table.attach(self.cardeditor2, 1, 2, 0, 1, yoptions=gtk.SHRINK)
-
+ if not self.cardeditor2.parent:
+ self.card_box.pack_start(self.cardeditor2)
+
def clean(self, widget):
self.cardeditor1.clean()
self.cardeditor2.clean()
@@ -164,28 +193,28 @@ class CreateCardPanel(gtk.EventBox):
self._card2_has_text = False
self._card1_has_picture = False
self._card2_has_picture = False
-
+
def receive_text_signals(self, widget, has_text):
if widget == self.cardeditor1:
self._card1_has_text = has_text
if widget == self.cardeditor2:
self._card2_has_text = has_text
self._update_buttom_status()
-
+
def receive_picture_signals(self, widget, has_picture):
if widget == self.cardeditor1:
self._card1_has_picture = has_picture
if widget == self.cardeditor2:
self._card2_has_picture = has_picture
self._update_buttom_status()
-
+
def receive_sound_signals(self, widget, has_sound):
if widget == self.cardeditor1:
self._card1_has_sound = has_sound
if widget == self.cardeditor2:
self._card2_has_sound = has_sound
self._update_buttom_status()
-
+
def _update_buttom_status(self):
if not self.equal_pairs:
if (self._card1_has_text or self._card1_has_picture or self._card1_has_sound) and (self._card2_has_text or self._card2_has_picture or self._card2_has_sound):
@@ -201,48 +230,31 @@ class CreateCardPanel(gtk.EventBox):
else:
self._addbutton.set_sensitive(False)
self._updatebutton.set_sensitive(False)
-
+
class CardEditor(gtk.EventBox):
-
+
__gsignals__ = {
- 'has-text': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
- 'has-picture': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
- 'has-sound': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'has-text': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'has-picture': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'has-sound': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
}
-
+
def __init__(self):
gtk.EventBox.__init__(self)
+ self.snd = None
+
tmp_root = join(environ['SUGAR_ACTIVITY_ROOT'], 'instance')
self.temp_folder = tempfile.mkdtemp(dir=tmp_root)
-
- table = gtk.Table()
+
+ box = gtk.VBox()
+ box.props.spacing = theme.PAD
+ box.props.border_width = theme.PAD
+
self.previewlabel = gtk.Label(_('Preview:'))
self.previewlabel.set_alignment(0, 1)
- self.textlabel = gtk.Label(_('Text:'))
- self.textlabel.set_alignment(0, 1)
-
- picture_icon = join(dirname(__file__), 'images', 'import_picture.svg')
- picture_image = gtk.Image()
- picture_image.set_from_file(picture_icon)
- self.browsepicture = gtk.Button()
- self.browsepicture.set_image(picture_image)
- self.browsepicture.connect('button-press-event', self._import_image)
-
- sound_icon = join(dirname(__file__), 'images', 'import_sound.svg')
- sound_image = gtk.Image()
- sound_image.set_from_file(sound_icon)
- self.browsesound = gtk.Button()
- self.browsesound.set_image(sound_image)
- self.browsesound.connect('button-press-event', self._import_audio)
- self.snd = None
- self.textentry = gtk.Entry()
- self.textentry.connect('changed', self.update_text)
-
- table.set_homogeneous(False)
- table.set_col_spacings(theme.PAD)
- table.set_row_spacings(theme.PAD)
- table.set_border_width(theme.PAD)
+ box.pack_start(self.previewlabel, False)
+
self.card = svgcard.SvgCard(-1,
{ 'front_text' : { 'card_text' : '',
'text_color' : '#ffffff' },
@@ -251,28 +263,62 @@ class CardEditor(gtk.EventBox):
'opacity' : '1' } },
None, theme.PAIR_SIZE, 1, '#c0c0c0')
self.card.flip()
-
- table.attach(self.previewlabel, 0, 2, 0, 1, yoptions=gtk.SHRINK)
- table.attach(self.card, 0, 2, 1, 2, gtk.SHRINK, gtk.SHRINK,
- theme.PAD)
- #Text label and entry
- table.attach(self.textlabel, 0, 1, 2, 3, yoptions=gtk.SHRINK)
- table.attach(self.textentry, 0, 2, 3, 4, yoptions=gtk.SHRINK)
- self.textentry.set_size_request(0, -1)
- #Picture label and entry
- table.attach(self.browsepicture, 0, 1, 4, 5, yoptions=gtk.SHRINK)
- #Sound label and entry
- table.attach(self.browsesound, 1, 2, 4, 5, yoptions=gtk.SHRINK)
-
- self.add(table)
-
+ card_align = gtk.Alignment(.5, .5, 0, 0)
+ card_align.add(self.card)
+ box.pack_start(card_align, False)
+
+ textlabel = gtk.Label(_('Text:'))
+ textlabel.set_alignment(0, 1)
+ box.pack_start(textlabel, False)
+
+ self.textentry = gtk.Entry()
+ self.textentry.connect('changed', self.update_text)
+ box.pack_start(self.textentry, False)
+
+ toolbar = gtk.HBox()
+
+ browsepicture = ToolButton(
+ icon_name='import_picture',
+ tooltip=_('Insert picture'))
+ toolbar.pack_start(browsepicture, False)
+
+ browsesound = ToolButton(
+ icon_name='import_sound',
+ tooltip=_('Insert sound'))
+ toolbar.pack_start(browsesound, False)
+
+ browsepicture.connect('clicked', self._load_image)
+ browsesound.connect('clicked', self._load_audio)
+
+ if speak.espeak.supported:
+ self.usespeak = ToggleToolButton(
+ named_icon='speak',
+ palette=SpeakPalette(self))
+ toolbar.pack_start(self.usespeak, False)
+ self.usespeak.connect('toggled', self._usespeak_cb)
+ else:
+ self.usespeak = None
+
+ toolbar_box = CanvasRoundBox(
+ radius=8,
+ border=2,
+ border_color=style.COLOR_BUTTON_GREY.get_int(),
+ background_color=style.COLOR_PANEL_GREY.get_int())
+ toolbar_box.append(hippo.CanvasWidget(widget=toolbar),
+ hippo.PACK_EXPAND)
+ toolbar_canvas = hippo.Canvas()
+ toolbar_canvas.set_root(toolbar_box)
+ box.pack_start(toolbar_canvas, False)
+
+ self.add(box)
+
def update_text(self, entry):
self.card.change_text(entry.get_text())
if len(entry.get_text()) == 0:
self.emit('has-text', False)
else:
self.emit('has-text', True)
-
+
def get_text(self):
return self.textentry.get_text()
@@ -280,91 +326,90 @@ class CardEditor(gtk.EventBox):
if newtext == None:
newtext = ''
self.textentry.set_text(newtext)
-
+
+ def get_speak(self):
+ if self.usespeak is None:
+ return None
+ if self.usespeak.props.active:
+ return self.usespeak.palette.face.status.voice.friendlyname
+
+ def set_speak(self, value):
+ if self.usespeak is None:
+ return
+ if value is None:
+ self.usespeak.props.active = False
+ else:
+ try:
+ self.usespeak.handler_block_by_func(self._usespeak_cb)
+ self.usespeak.props.active = True
+ finally:
+ self.usespeak.handler_unblock_by_func(self._usespeak_cb)
+ self.usespeak.palette.voices.resume(value)
+
def get_pixbuf(self):
return self.card.get_pixbuf()
-
+
def set_pixbuf(self, pixbuf):
self.card.set_pixbuf(pixbuf)
-
- def _import_image(self, widget, event):
- if hasattr(mime, 'GENERIC_TYPE_IMAGE'):
- filter = { 'what_filter': mime.GENERIC_TYPE_IMAGE }
- else:
- filter = { }
-
- chooser = ObjectChooser(_('Choose image'), None,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- **filter)
- try:
- result = chooser.run()
- if result == gtk.RESPONSE_ACCEPT:
- _logger.debug('ObjectChooser: %r' % chooser.get_selected_object())
- jobject = chooser.get_selected_object()
- if jobject and jobject.file_path:
- self._load_image(jobject.file_path)
- finally:
- chooser.destroy()
- del chooser
-
- def _load_image(self, index):
- pixbuf_t = gtk.gdk.pixbuf_new_from_file_at_size(
- index, theme.PAIR_SIZE - theme.PAD*2, theme.PAIR_SIZE - theme.PAD*2)
- if pixbuf_t.get_width() > pixbuf_t.get_height():
- size = pixbuf_t.get_width()
- else:
- size = pixbuf_t.get_height()
- pixbuf_z = gtk.gdk.pixbuf_new_from_file_at_size(
- 'images/white.png', size, size)
- pixbuf_t.composite(pixbuf_z, 0, 0, pixbuf_t.get_width(),
- pixbuf_t.get_height(), 0, 0, 1, 1,
- gtk.gdk.INTERP_BILINEAR, 255)
- self.card.set_pixbuf(pixbuf_z)
- _logger.error('Picture Loaded: '+index)
- self.emit('has-picture', True)
- del pixbuf_t
- del pixbuf_z
-
- def _import_audio(self, widget, event):
- if hasattr(mime, 'GENERIC_TYPE_AUDIO'):
- filter = { 'what_filter': mime.GENERIC_TYPE_AUDIO }
- else:
- filter = { }
-
- chooser = ObjectChooser(_('Choose audio'), None,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- **filter)
- jobject = ''
- try:
- result = chooser.run()
- if result == gtk.RESPONSE_ACCEPT:
- _logger.debug('ObjectChooser: %r' % chooser.get_selected_object())
- jobject = chooser.get_selected_object()
- if not jobject or not jobject.file_path:
- return
- finally:
- chooser.destroy()
- del chooser
-
- if jobject and jobject.file_path:
- self._load_audio(jobject.file_path)
-
- def _load_audio(self, index):
- dst = join(self.temp_folder, basename(index))
- shutil.copy(index, dst)
- self.set_snd(dst)
- icon_theme = gtk.icon_theme_get_default()
- pixbuf_t = icon_theme.load_icon("audio-x-generic",
- style.XLARGE_ICON_SIZE, 0)
- self.card.set_pixbuf(pixbuf_t)
- self.emit('has-sound', True)
- _logger.debug('Audio Loaded: '+dst)
-
+
+ def _load_image(self, widget):
+ def load(index):
+ self.set_speak(None)
+
+ pixbuf_t = gtk.gdk.pixbuf_new_from_file_at_size(
+ index, theme.PAIR_SIZE - theme.PAD*2,
+ theme.PAIR_SIZE - theme.PAD*2)
+ size = max(pixbuf_t.get_width(), pixbuf_t.get_height())
+ pixbuf_z = gtk.gdk.pixbuf_new_from_file_at_size(
+ 'images/white.png', size, size)
+ pixbuf_t.composite(pixbuf_z, 0, 0, pixbuf_t.get_width(),
+ pixbuf_t.get_height(), 0, 0, 1, 1,
+ gtk.gdk.INTERP_BILINEAR, 255)
+ self.card.set_pixbuf(pixbuf_z)
+ _logger.debug('Picture Loaded: '+index)
+ self.emit('has-picture', True)
+ del pixbuf_t
+ del pixbuf_z
+
+ chooser.pick(what=chooser.IMAGE,
+ cb=lambda jobject: load(jobject.file_path))
+
+ def _load_audio(self, widget):
+ def load(index):
+ self.set_speak(None)
+
+ dst = join(self.temp_folder, basename(index))
+ shutil.copy(index, dst)
+ self.set_snd(dst)
+ icon_theme = gtk.icon_theme_get_default()
+ pixbuf_t = icon_theme.load_icon("audio-x-generic",
+ style.XLARGE_ICON_SIZE, 0)
+ self.card.set_pixbuf(pixbuf_t)
+ self.emit('has-sound', True)
+ _logger.debug('Audio Loaded: '+dst)
+
+ chooser.pick(what=chooser.AUDIO,
+ cb=lambda jobject: load(jobject.file_path))
+
+ def _usespeak_cb(self, button):
+ self.card.change_speak(button.props.active)
+
+ if not button.props.active:
+ self.usespeak.palette.face.shut_up()
+ return
+
+ self.snd = None
+ self.card.set_pixbuf(None)
+ self.emit('has-sound', False)
+ self.emit('has-picture', False)
+
+ button.palette.face.say(self.get_text())
+
def set_snd(self, snd):
self.snd = snd
-
+
def get_snd(self):
- return self.snd
+ return self.snd
def clean(self):
self.textentry.set_text('')
@@ -373,3 +418,26 @@ class CardEditor(gtk.EventBox):
self.emit('has-text', False)
self.emit('has-picture', False)
self.emit('has-sound', False)
+ if self.usespeak is not None:
+ self.usespeak.props.active = False
+ self.usespeak.palette.face.shut_up()
+
+class SpeakPalette(Palette):
+ def __init__(self, editor):
+ Palette.__init__(self, _('Pronounce text while fliping tile'))
+
+ self.face = speak.face.View()
+
+ toolbar = gtk.HBox()
+ toolbar.modify_bg(gtk.STATE_NORMAL, style.COLOR_BLACK.get_gdk_color())
+
+ usespeak_play = ToolButton(icon_name='media-playback-start')
+ usespeak_play.connect('clicked', lambda button:
+ self.face.say(editor.get_text()))
+ toolbar.pack_start(usespeak_play, False)
+
+ self.voices = speak.widgets.Voices(self.face)
+ toolbar.pack_start(ToolComboBox(self.voices))
+
+ toolbar.show_all()
+ self.set_content(toolbar)