From af8c24470530d09e93dab30923f98119713fa2b3 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Mon, 15 Oct 2012 17:54:10 +0000 Subject: removing gtk2 code from repository --- diff --git a/gtk2/StoryActivity.py b/gtk2/StoryActivity.py deleted file mode 100644 index ef5e37d..0000000 --- a/gtk2/StoryActivity.py +++ /dev/null @@ -1,404 +0,0 @@ -#Copyright (c) 2012 Walter Bender - -# 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 3 of the License, or -# (at your option) any later version. -# -# You should have received a copy of the GNU General Public License -# along with this library; if not, write to the Free Software -# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - - -import gtk -import gobject -import subprocess -import cairo -import os -import time - -from sugar.activity import activity -from sugar import profile -from sugar.datastore import datastore -try: - from sugar.graphics.toolbarbox import ToolbarBox - _have_toolbox = True -except ImportError: - _have_toolbox = False - -if _have_toolbox: - from sugar.activity.widgets import ActivityToolbarButton - from sugar.activity.widgets import StopButton - -from sugar.graphics.alert import Alert - -from toolbar_utils import button_factory, label_factory, separator_factory -from utils import json_load, json_dump, play_audio_from_file -from grecord import Grecord - -import telepathy -import dbus -from dbus.service import signal -from dbus.gobject_service import ExportedGObject -from sugar.presence import presenceservice -from sugar.presence.tubeconn import TubeConnection - -from gettext import gettext as _ - -from game import Game - -import logging -_logger = logging.getLogger('story-activity') - - -SERVICE = 'org.sugarlabs.StoryActivity' -IFACE = SERVICE - - -class StoryActivity(activity.Activity): - """ Storytelling game """ - - def __init__(self, handle): - """ Initialize the toolbars and the game board """ - try: - super(StoryActivity, self).__init__(handle) - except dbus.exceptions.DBusException, e: - _logger.error(str(e)) - - self.path = activity.get_bundle_path() - - self.nick = profile.get_nick_name() - if profile.get_color() is not None: - self.colors = profile.get_color().to_string().split(',') - else: - self.colors = ['#A0FFA0', '#FF8080'] - - self._recording = False - self._grecord = None - self._alert = None - - self._setup_toolbars(_have_toolbox) - self._setup_dispatch_table() - - # Create a canvas - canvas = gtk.DrawingArea() - canvas.set_size_request(gtk.gdk.screen_width(), \ - gtk.gdk.screen_height()) - self.set_canvas(canvas) - canvas.show() - self.show_all() - - self._game = Game(canvas, parent=self, path=self.path, - colors=self.colors) - self._setup_presence_service() - - if 'dotlist' in self.metadata: - self._restore() - else: - self._game.new_game() - - def _setup_toolbars(self, have_toolbox): - """ Setup the toolbars. """ - - self.max_participants = 9 - - if have_toolbox: - toolbox = ToolbarBox() - - # Activity toolbar - activity_button = ActivityToolbarButton(self) - - toolbox.toolbar.insert(activity_button, 0) - activity_button.show() - - self.set_toolbar_box(toolbox) - toolbox.show() - self.toolbar = toolbox.toolbar - - else: - # Use pre-0.86 toolbar design - games_toolbar = gtk.Toolbar() - toolbox = activity.ActivityToolbox(self) - self.set_toolbox(toolbox) - toolbox.add_toolbar(_('Game'), games_toolbar) - toolbox.show() - toolbox.set_current_toolbar(1) - self.toolbar = games_toolbar - - self._new_game_button_h = button_factory( - 'view-refresh', self.toolbar, self._new_game_cb, - tooltip=_('Load new images.')) - - separator_factory(self.toolbar) - - self.save_as_image = button_factory( - 'image-saveoff', self.toolbar, self._do_save_as_image_cb, - tooltip=_('Save as image')) - - separator_factory(self.toolbar) - - self._record_button = button_factory( - 'media-record', self.toolbar, - self._record_cb, tooltip=_('Start recording')) - - self._playback_button = button_factory( - 'media-playback-start-insensitive', self.toolbar, - self._playback_recording_cb, tooltip=_('Nothing to play')) - - if _have_toolbox: - separator_factory(toolbox.toolbar, True, False) - - if _have_toolbox: - stop_button = StopButton(self) - stop_button.props.accelerator = 'q' - toolbox.toolbar.insert(stop_button, -1) - stop_button.show() - - def _new_game_cb(self, button=None): - ''' Start a new game. ''' - self._game.new_game() - - def write_file(self, file_path): - """ Write the grid status to the Journal """ - dot_list = self._game.save_game() - self.metadata['dotlist'] = '' - for dot in dot_list: - self.metadata['dotlist'] += str(dot) - if dot_list.index(dot) < len(dot_list) - 1: - self.metadata['dotlist'] += ' ' - - def _restore(self): - """ Restore the game state from metadata """ - dot_list = [] - dots = self.metadata['dotlist'].split() - for dot in dots: - dot_list.append(int(dot)) - self._game.restore_game(dot_list) - - def _do_save_as_image_cb(self, button=None): - """ Grab the current canvas and save it to the Journal. """ - self._notify_successful_save(title=_('Save as image')) - file_path = os.path.join(activity.get_activity_root(), - 'instance', 'story.png') - png_surface = self._game.export() - png_surface.write_to_png(file_path) - - dsobject = datastore.create() - dsobject.metadata['title'] = "%s %s" % \ - (self.metadata['title'], _("image")) - dsobject.metadata['icon-color'] = profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'image/png' - dsobject.set_file_path(file_path) - datastore.write(dsobject) - dsobject.destroy() - os.remove(file_path) - if self._alert is not None: - self.remove_alert(self._alert) - self._alert = None - - def _record_cb(self, button=None): - ''' Start/stop audio recording ''' - if self._grecord is None: - _logger.debug('setting up grecord') - self._grecord = Grecord(self) - if self._recording: # Was recording, so stop (and save?) - _logger.debug('recording...True. Preparing to save.') - self._grecord.stop_recording_audio() - self._recording = False - self._record_button.set_icon('media-record') - self._record_button.set_tooltip(_('Start recording')) - self._playback_button.set_icon('media-playback-start') - self._playback_button.set_tooltip(_('Play recording')) - self._notify_successful_save(title=_('Save recording')) - gobject.timeout_add(100, self._wait_for_transcoding_to_finish) - else: # Wasn't recording, so start - _logger.debug('recording...False. Start recording.') - self._grecord.record_audio() - self._recording = True - self._record_button.set_icon('media-recording') - self._record_button.set_tooltip(_('Stop recording')) - - def _wait_for_transcoding_to_finish(self, button=None): - while not self._grecord.transcoding_complete(): - time.sleep(1) - if self._alert is not None: - self.remove_alert(self._alert) - self._alert = None - self._save_recording() - - def _playback_recording_cb(self, button=None): - ''' Play back current recording ''' - _logger.debug('Playback current recording from output.ogg...') - play_audio_from_file(os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg')) - return - - def _save_recording(self): - if os.path.exists(os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg')): - _logger.debug('Saving recording to Journal...') - dsobject = datastore.create() - dsobject.metadata['title'] = _('audio note for %s') % \ - (self.metadata['title']) - dsobject.metadata['icon-color'] = profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'audio/ogg' - _logger.debug('setting file path to %s' % ( - os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg'))) - dsobject.set_file_path(os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg')) - datastore.write(dsobject) - dsobject.destroy() - # Always save an image with the recording. - self._do_save_as_image_cb() - else: - _logger.debug('Nothing to save...') - return - - def _notify_successful_save(self, title='', msg=''): - ''' Notify user when saves are completed ''' - self._alert = Alert() - self._alert.props.title = title - self._alert.props.msg = msg - self.add_alert(self._alert) - self._alert.show() - - # Collaboration-related methods - - def _setup_presence_service(self): - """ Setup the Presence Service. """ - self.pservice = presenceservice.get_instance() - self.initiating = None # sharing (True) or joining (False) - - owner = self.pservice.get_owner() - self.owner = owner - self._share = "" - self.connect('shared', self._shared_cb) - self.connect('joined', self._joined_cb) - - def _shared_cb(self, activity): - """ Either set up initial share...""" - self._new_tube_common(True) - - def _joined_cb(self, activity): - """ ...or join an exisiting share. """ - self._new_tube_common(False) - - def _new_tube_common(self, sharer): - """ Joining and sharing are mostly the same... """ - if self._shared_activity is None: - _logger.debug("Error: Failed to share or join activity ... \ - _shared_activity is null in _shared_cb()") - return - - self.initiating = sharer - self.waiting_for_hand = not sharer - - self.conn = self._shared_activity.telepathy_conn - self.tubes_chan = self._shared_activity.telepathy_tubes_chan - self.text_chan = self._shared_activity.telepathy_text_chan - - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( - 'NewTube', self._new_tube_cb) - - if sharer: - _logger.debug('This is my activity: making a tube...') - id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( - SERVICE, {}) - else: - _logger.debug('I am joining an activity: waiting for a tube...') - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( - reply_handler=self._list_tubes_reply_cb, - error_handler=self._list_tubes_error_cb) - self._game.set_sharing(True) - - def _list_tubes_reply_cb(self, tubes): - """ Reply to a list request. """ - for tube_info in tubes: - self._new_tube_cb(*tube_info) - - def _list_tubes_error_cb(self, e): - """ Log errors. """ - _logger.debug('Error: ListTubes() failed: %s' % (e)) - - def _new_tube_cb(self, id, initiator, type, service, params, state): - """ Create a new tube. """ - _logger.debug('New tube: ID=%d initator=%d type=%d service=%s \ -params=%r state=%d' % (id, initiator, type, service, params, state)) - - if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): - if state == telepathy.TUBE_STATE_LOCAL_PENDING: - self.tubes_chan[ \ - telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) - - tube_conn = TubeConnection(self.conn, - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, \ - group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) - - self.chattube = ChatTube(tube_conn, self.initiating, \ - self.event_received_cb) - - def _setup_dispatch_table(self): - ''' Associate tokens with commands. ''' - self._processing_methods = { - 'n': [self._receive_new_game, 'get a new game grid'], - 'p': [self._receive_dot_click, 'get a dot click'], - } - - def event_received_cb(self, event_message): - ''' Data from a tube has arrived. ''' - if len(event_message) == 0: - return - try: - command, payload = event_message.split('|', 2) - except ValueError: - _logger.debug('Could not split event message %s' % (event_message)) - return - self._processing_methods[command][0](payload) - - def send_new_game(self): - ''' Send a new grid to all players ''' - self.send_event('n|%s' % (json_dump(self._game.save_game()))) - - def _receive_new_game(self, payload): - ''' Sharer can start a new game. ''' - dot_list = json_load(payload) - self._game.restore_game(dot_list) - - def send_dot_click(self, dot, color): - ''' Send a dot click to all the players ''' - self.send_event('p|%s' % (json_dump([dot, color]))) - - def _receive_dot_click(self, payload): - ''' When a dot is clicked, everyone should change its color. ''' - (dot, color) = json_load(payload) - self._game.remote_button_press(dot, color) - - def send_event(self, entry): - """ Send event through the tube. """ - if hasattr(self, 'chattube') and self.chattube is not None: - self.chattube.SendText(entry) - - -class ChatTube(ExportedGObject): - """ Class for setting up tube for sharing """ - - def __init__(self, tube, is_initiator, stack_received_cb): - super(ChatTube, self).__init__(tube, PATH) - self.tube = tube - self.is_initiator = is_initiator # Are we sharing or joining activity? - self.stack_received_cb = stack_received_cb - self.stack = '' - - self.tube.add_signal_receiver(self.send_stack_cb, 'SendText', IFACE, - path=PATH, sender_keyword='sender') - - def send_stack_cb(self, text, sender=None): - if sender == self.tube.get_unique_name(): - return - self.stack = text - self.stack_received_cb(text) - - @signal(dbus_interface=IFACE, signature='s') - def SendText(self, text): - self.stack = text diff --git a/gtk2/game.py b/gtk2/game.py deleted file mode 100644 index c1bc398..0000000 --- a/gtk2/game.py +++ /dev/null @@ -1,265 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) 2012 Walter Bender - -# 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 3 of the License, or -# (at your option) any later version. -# -# You should have received a copy of the GNU General Public License -# along with this library; if not, write to the Free Software -# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - - -import gtk -import gobject -import cairo -import os -import glob -from random import uniform - -from gettext import gettext as _ - -import logging -_logger = logging.getLogger('search-activity') - -try: - from sugar.graphics import style - GRID_CELL_SIZE = style.GRID_CELL_SIZE -except ImportError: - GRID_CELL_SIZE = 0 - -from sprites import Sprites, Sprite - - -DOT_SIZE = 40 -COLORS = ['#000000', '#a00000', '#907000', '#009000', '#0000ff', '#9000a0'] - - -class Game(): - - def __init__(self, canvas, parent=None, path=None, - colors=['#A0FFA0', '#FF8080']): - self._canvas = canvas - self._parent = parent - self._parent.show_all() - self._path = path - - self._colors = ['#FFFFFF'] - self._colors.append(colors[0]) - self._colors.append(colors[1]) - - self._canvas.set_flags(gtk.CAN_FOCUS) - self._canvas.connect("expose-event", self._expose_cb) - - self._width = gtk.gdk.screen_width() - self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5) - self._scale = self._height / (3 * DOT_SIZE * 1.2) - self._scale /= 1.5 - self._dot_size = int(DOT_SIZE * self._scale) - self._space = int(self._dot_size / 5.) - self.we_are_sharing = False - - self._start_time = 0 - self._timeout_id = None - - # Find the image files - self._PATHS = glob.glob(os.path.join(self._path, 'images', '*.svg')) - - # Generate the sprites we'll need... - self._sprites = Sprites(self._canvas) - self._dots = [] - yoffset = self._space * 2 # int(self._space / 2.) - for y in range(3): - for x in range(3): - xoffset = int((self._width - 3 * self._dot_size - \ - 2 * self._space) / 2.) - self._dots.append( - Sprite(self._sprites, - xoffset + x * (self._dot_size + self._space), - y * (self._dot_size + self._space) + yoffset, - self._new_dot_surface(color=self._colors[0]))) - self._dots[-1].type = -1 # No image - self._dots[-1].set_label_attributes(72) - - def _all_clear(self): - ''' Things to reinitialize when starting up a new game. ''' - if self._timeout_id is not None: - gobject.source_remove(self._timeout_id) - - for dot in self._dots: - if dot.type != -1: - dot.type = -1 - dot.set_shape(self._new_dot_surface( - self._colors[abs(dot.type)])) - dot.set_label('?') - self._dance_counter = 0 - self._dance_step() - - def _dance_step(self): - ''' Short animation before loading new game ''' - for dot in self._dots: - dot.set_shape(self._new_dot_surface( - self._colors[int(uniform(0, 3))])) - self._dance_counter += 1 - if self._dance_counter < 10: - self._timeout_id = gobject.timeout_add(500, self._dance_step) - else: - self._new_game() - - def new_game(self): - ''' Start a new game. ''' - self._all_clear() - - def _new_game(self): - ''' Select pictures at random ''' - for i in range(3 * 3): - self._dots[i].set_label('') - self._dots[i].type = int(uniform(0, len(self._PATHS))) - _logger.debug(self._dots[i].type) - self._dots[i].set_shape(self._new_dot_surface( - image=self._dots[i].type)) - - if self.we_are_sharing: - _logger.debug('sending a new game') - self._parent.send_new_game() - - def restore_game(self, dot_list): - ''' Restore a game from the Journal or share ''' - for i, dot in enumerate(dot_list): - self._dots[i].type = dot - self._dots[i].set_shape(self._new_dot_surface( - image=self._dots[i].type)) - - def save_game(self): - ''' Return dot list for saving to Journal or - sharing ''' - dot_list = [] - for dot in self._dots: - dot_list.append(dot.type) - return dot_list - - def set_sharing(self, share=True): - _logger.debug('enabling sharing') - self.we_are_sharing = share - - def _grid_to_dot(self, pos): - ''' calculate the dot index from a column and row in the grid ''' - return pos[0] + pos[1] * 3 - - def _dot_to_grid(self, dot): - ''' calculate the grid column and row for a dot ''' - return [dot % 3, int(dot / 3)] - - def _expose_cb(self, win, event): - self.do_expose_event(event) - - def do_expose_event(self, event): - ''' Handle the expose-event by drawing ''' - # Restrict Cairo to the exposed area - cr = self._canvas.window.cairo_create() - cr.rectangle(event.area.x, event.area.y, - event.area.width, event.area.height) - cr.clip() - # Refresh sprite list - self._sprites.redraw_sprites(cr=cr) - - def _destroy_cb(self, win, event): - gtk.main_quit() - - def export(self): - ''' Write dot to cairo surface. ''' - w = h = int(4 * self._space + 3 * self._dot_size) - png_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h) - cr = cairo.Context(png_surface) - cr.set_source_rgb(192, 192, 192) - cr.rectangle(0, 0, w, h) - cr.fill() - for i in range(9): - y = self._space + int(i / 3.) * (self._dot_size + self._space) - x = self._space + (i % 3) * (self._dot_size + self._space) - cr.save() - cr = gtk.gdk.CairoContext(cr) - cr.set_source_surface(self._dots[i].cached_surfaces[0], x, y) - cr.rectangle(x, y, self._dot_size, self._dot_size) - cr.fill() - cr.restore() - return png_surface - - def _new_dot_surface(self, color='#000000', image=None): - ''' generate a dot of a color color ''' - self._dot_cache = {} - if image is not None: - color = COLORS[int(uniform(0, 6))] - fd = open(os.path.join(self._path, self._PATHS[image]), 'r') - svg_string = '' - for line in fd: - svg_string += line.replace('#000000', color) - fd.close() - pixbuf = svg_str_to_pixbuf(svg_string, w=self._dot_size, - h = self._dot_size) - ''' - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( - os.path.join(self._path, self._PATHS[image]), - self._dot_size, self._dot_size) - ''' - else: - if color in self._dot_cache: - return self._dot_cache[color] - self._stroke = color - self._fill = color - self._svg_width = self._dot_size - self._svg_height = self._dot_size - - i = self._colors.index(color) - pixbuf = svg_str_to_pixbuf( - self._header() + \ - self._circle(self._dot_size / 2., self._dot_size / 2., - self._dot_size / 2.) + \ - self._footer()) - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, - self._svg_width, self._svg_height) - context = cairo.Context(surface) - context = gtk.gdk.CairoContext(context) - context.set_source_pixbuf(pixbuf, 0, 0) - context.rectangle(0, 0, self._svg_width, self._svg_height) - context.fill() - if image is None: - self._dot_cache[color] = surface - return surface - - def _header(self): - return '\n' - - def _rect(self, w, h, x, y): - svg_string = ' \n' - - def _footer(self): - return '\n' - - -def svg_str_to_pixbuf(svg_string, w=None, h=None): - ''' Load pixbuf from SVG string ''' - pl = gtk.gdk.PixbufLoader('svg') - if w is not None: - pl.set_size(w, h) - pl.write(svg_string) - pl.close() - return pl.get_pixbuf() diff --git a/gtk2/grecord.py b/gtk2/grecord.py deleted file mode 100644 index 02fcbd3..0000000 --- a/gtk2/grecord.py +++ /dev/null @@ -1,244 +0,0 @@ -#Copyright (c) 2008, Media Modifications Ltd. -#Copyright (c) 2011-12, Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import os -import time - -import gtk -import gst - -import logging -_logger = logging.getLogger("portfolio-activity") - -import gobject -gobject.threads_init() - - -class Grecord: - - def __init__(self, parent): - self._activity = parent - self._eos_cb = None - - self._can_limit_framerate = False - self._playing = False - - self._audio_transcode_handler = None - self._transcode_id = None - - self._pipeline = gst.Pipeline("Record") - self._create_audiobin() - - bus = self._pipeline.get_bus() - bus.add_signal_watch() - bus.connect('message', self._bus_message_handler) - - def _create_audiobin(self): - src = gst.element_factory_make("alsasrc", "absrc") - - # attempt to use direct access to the 0,0 device, solving some A/V - # sync issues - src.set_property("device", "plughw:0,0") - hwdev_available = src.set_state(gst.STATE_PAUSED) != \ - gst.STATE_CHANGE_FAILURE - src.set_state(gst.STATE_NULL) - if not hwdev_available: - src.set_property("device", "default") - - srccaps = gst.Caps("audio/x-raw-int,rate=16000,channels=1,depth=16") - - # Guarantee perfect stream, important for A/V sync - rate = gst.element_factory_make("audiorate") - - # Without a buffer here, gstreamer struggles at the start of the - # recording and then the A/V sync is bad for the whole video - # (possibly a gstreamer/ALSA bug -- even if it gets caught up, it - # should be able to resync without problem). - queue = gst.element_factory_make("queue", "audioqueue") - queue.set_property("leaky", True) # prefer fresh data - queue.set_property("max-size-time", 5000000000) # 5 seconds - queue.set_property("max-size-buffers", 500) - queue.connect("overrun", self._log_queue_overrun) - - enc = gst.element_factory_make("wavenc", "abenc") - - sink = gst.element_factory_make("filesink", "absink") - sink.set_property("location", - os.path.join(self._activity.get_activity_root(), - 'instance', 'output.wav')) - - self._audiobin = gst.Bin("audiobin") - self._audiobin.add(src, rate, queue, enc, sink) - - src.link(rate, srccaps) - gst.element_link_many(rate, queue, enc, sink) - - def _log_queue_overrun(self, queue): - cbuffers = queue.get_property("current-level-buffers") - cbytes = queue.get_property("current-level-bytes") - ctime = queue.get_property("current-level-time") - - def play(self): - if self._get_state() == gst.STATE_PLAYING: - return - - self._pipeline.set_state(gst.STATE_PLAYING) - self._playing = True - - def pause(self): - self._pipeline.set_state(gst.STATE_PAUSED) - self._playing = False - - def stop(self): - self._pipeline.set_state(gst.STATE_NULL) - self._playing = False - - def is_playing(self): - return self._playing - - def _get_state(self): - return self._pipeline.get_state()[1] - - def stop_recording_audio(self): - # We should be able to simply pause and remove the audiobin, but - # this seems to cause a gstreamer segfault. So we stop the whole - # pipeline while manipulating it. - # http://dev.laptop.org/ticket/10183 - self._pipeline.set_state(gst.STATE_NULL) - self._pipeline.remove(self._audiobin) - self.play() - - audio_path = os.path.join(self._activity.get_activity_root(), - 'instance', 'output.wav') - if not os.path.exists(audio_path) or os.path.getsize(audio_path) <= 0: - # FIXME: inform model of failure? - _logger.error('output.wav does not exist or is empty') - return - - line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! \ -wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! \ -vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! \ -filesink name=audioFilesink' - self._audioline = gst.parse_launch(line) - - vorbis_enc = self._audioline.get_by_name('audioVorbisenc') - - audioFilesink = self._audioline.get_by_name('audioFilesink') - audioOggFilepath = os.path.join(self._activity.get_activity_root(), - 'instance', 'output.ogg') - audioFilesink.set_property("location", audioOggFilepath) - - audioBus = self._audioline.get_bus() - audioBus.add_signal_watch() - self._audio_transcode_handler = audioBus.connect( - 'message', self._onMuxedAudioMessageCb, self._audioline) - self._transcode_id = gobject.timeout_add(200, self._transcodeUpdateCb, - self._audioline) - self._audiopos = 0 - self._audioline.set_state(gst.STATE_PLAYING) - - def transcoding_complete(self): - # The EOS message is sometimes either not sent or not received. - # So if the position in the stream is not advancing, assume EOS. - if self._transcode_id is None: - _logger.debug('EOS.... transcoding finished') - return True - else: - position, duration = self._query_position(self._audioline) - # _logger.debug('position: %s, duration: %s' % (str(position), - # str(duration))) - if position == duration: - _logger.debug('We are done, even though we did not see EOS') - self._clean_up_transcoding_pipeline(self._audioline) - return True - elif position == self._audiopos: - _logger.debug('No progess, so assume we are done') - self._clean_up_transcoding_pipeline(self._audioline) - return True - self._audiopos = position - return False - - def blockedCb(self, x, y, z): - pass - - def record_audio(self): - # We should be able to add the audiobin on the fly, but unfortunately - # this results in several seconds of silence being added at the start - # of the recording. So we stop the whole pipeline while adjusting it. - # SL#2040 - self._pipeline.set_state(gst.STATE_NULL) - self._pipeline.add(self._audiobin) - self.play() - - def _transcodeUpdateCb(self, pipe): - position, duration = self._query_position(pipe) - if position != gst.CLOCK_TIME_NONE: - value = position * 100.0 / duration - value = value / 100.0 - return True - - def _query_position(self, pipe): - try: - position, format = pipe.query_position(gst.FORMAT_TIME) - except: - position = gst.CLOCK_TIME_NONE - - try: - duration, format = pipe.query_duration(gst.FORMAT_TIME) - except: - duration = gst.CLOCK_TIME_NONE - - return (position, duration) - - def _onMuxedAudioMessageCb(self, bus, message, pipe): - # _logger.debug(message.type) - if message.type != gst.MESSAGE_EOS: - return True - self._clean_up_transcoding_pipeline(pipe) - return False - - def _clean_up_transcoding_pipeline(self, pipe): - gobject.source_remove(self._audio_transcode_handler) - self._audio_transcode_handler = None - gobject.source_remove(self._transcode_id) - self._transcode_id = None - pipe.set_state(gst.STATE_NULL) - pipe.get_bus().remove_signal_watch() - pipe.get_bus().disable_sync_message_emission() - - wavFilepath = os.path.join(self._activity.get_activity_root(), - 'instance', 'output.wav') - os.remove(wavFilepath) - return - - def _bus_message_handler(self, bus, message): - t = message.type - if t == gst.MESSAGE_EOS: - if self._eos_cb: - cb = self._eos_cb - self._eos_cb = None - cb() - elif t == gst.MESSAGE_ERROR: - # TODO: if we come out of suspend/resume with errors, then - # get us back up and running... TODO: handle "No space - # left on the resource.gstfilesink.c" err, debug = - # message.parse_error() - pass diff --git a/gtk2/setup.py b/gtk2/setup.py deleted file mode 100644 index e5026ee..0000000 --- a/gtk2/setup.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if len(sys.argv) > 1 and '--no-sugar' == sys.argv[1]: - # Remove the argument from the stack so we don't cause problems - # for distutils - sys.argv.pop(1) - - import glob, os.path, string - from distutils.core import setup - - DATA_FILES = [ - ('icons', glob.glob('icons/*')), - ('images', glob.glob('images/*')), - ('/usr/share/applications', ['turtleart.desktop']) - ] - - setup (name = 'Turtle Art', - description = "A LOGO-like tool for teaching programming", - author = "Walter Bender", - author_email = "walter.bender@gmail.com", - version = '0.9.4', - packages = ['TurtleArt'], - scripts = ['turtleart'], - data_files = DATA_FILES, - ) -else: - from sugar.activity import bundlebuilder - - if __name__ == "__main__": - bundlebuilder.start() diff --git a/gtk2/sprites.py b/gtk2/sprites.py deleted file mode 100644 index 2b8bb55..0000000 --- a/gtk2/sprites.py +++ /dev/null @@ -1,459 +0,0 @@ -# -*- coding: utf-8 -*- - -#Copyright (c) 2007-8, Playful Invention Company. -#Copyright (c) 2008-11 Walter Bender - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -''' - -sprites.py is a simple sprites library for managing graphics objects, -'sprites', on a gtk.DrawingArea. It manages multiple sprites with -methods such as move, hide, set_layer, etc. - -There are two classes: - -class Sprites maintains a collection of sprites -class Sprite manages individual sprites within the collection. - -Example usage: - # Import the classes into your program. - from sprites import Sprites Sprite - - # Create a new sprite collection associated with your widget - self.sprite_list = Sprites(widget) - - # Create a "pixbuf" (in this example, from SVG). - my_pixbuf = svg_str_to_pixbuf("...some svg code...") - - # Create a sprite at position x1, y1. - my_sprite = sprites.Sprite(self.sprite_list, x1, y1, my_pixbuf) - - # Move the sprite to a new position. - my_sprite.move((x1+dx, y1+dy)) - - # Create another "pixbuf". - your_pixbuf = svg_str_to_pixbuf("...some svg code...") - - # Create a sprite at position x2, y2. - your_sprite = sprites.Sprite(self.sprite_list, x2, y2, my_pixbuf) - - # Assign the sprites to layers. - # In this example, your_sprite will be on top of my_sprite. - my_sprite.set_layer(100) - your_sprite.set_layer(200) - - # Now put my_sprite on top of your_sprite. - my_sprite.set_layer(300) - - cr = self.window.cairo_create() - # In your activity's do_expose_event, put in a call to redraw_sprites - self.sprites.redraw_sprites(event.area, cairo_context) - -# method for converting SVG to a gtk pixbuf -def svg_str_to_pixbuf(svg_string): - pl = gtk.gdk.PixbufLoader('svg') - pl.write(svg_string) - pl.close() - pixbuf = pl.get_pixbuf() - return pixbuf - -''' - -import pygtk -pygtk.require('2.0') -import gtk -import pango -import pangocairo -import cairo - -class Sprites: - ''' A class for the list of sprites and everything they share in common ''' - - def __init__(self, widget): - ''' Initialize an empty array of sprites ''' - self.widget = widget - self.list = [] - self.cr = None - - def set_cairo_context(self, cr): - ''' Cairo context may be set or reset after __init__ ''' - self.cr = cr - - def get_sprite(self, i): - ''' Return a sprint from the array ''' - if i < 0 or i > len(self.list) - 1: - return(None) - else: - return(self.list[i]) - - def length_of_list(self): - ''' How many sprites are there? ''' - return(len(self.list)) - - def append_to_list(self, spr): - ''' Append a new sprite to the end of the list. ''' - self.list.append(spr) - - def insert_in_list(self, spr, i): - ''' Insert a sprite at position i. ''' - if i < 0: - self.list.insert(0, spr) - elif i > len(self.list) - 1: - self.list.append(spr) - else: - self.list.insert(i, spr) - - def remove_from_list(self, spr): - ''' Remove a sprite from the list. ''' - if spr in self.list: - self.list.remove(spr) - - def find_sprite(self, pos, inverse=False): - ''' Search based on (x, y) position. Return the 'top/first' one. ''' - list = self.list[:] - if not inverse: - list.reverse() - for spr in list: - if spr.hit(pos): - return spr - return None - - def redraw_sprites(self, area=None, cr=None): - ''' Redraw the sprites that intersect area. ''' - # I think I need to do this to save Cairo some work - if cr is None: - cr = self.cr - else: - self.cr = cr - if cr is None: - print 'sprites.redraw_sprites: no Cairo context' - return - for spr in self.list: - if area == None: - spr.draw(cr=cr) - else: - intersection = spr.rect.intersect(area) - if intersection.width > 0 or intersection.height > 0: - spr.draw(cr=cr) - - -class Sprite: - ''' A class for the individual sprites ''' - - def __init__(self, sprites, x, y, image): - ''' Initialize an individual sprite ''' - self._sprites = sprites - self.save_xy = (x, y) # remember initial (x, y) position - self.rect = gtk.gdk.Rectangle(int(x), int(y), 0, 0) - self._scale = [12] - self._rescale = [True] - self._horiz_align = ["center"] - self._vert_align = ["middle"] - self._fd = None - self._bold = False - self._italic = False - self._color = None - self._margins = [0, 0, 0, 0] - self.layer = 100 - self.labels = [] - self.cached_surfaces = [] - self._dx = [] # image offsets - self._dy = [] - self.type = None - self.set_image(image) - self._sprites.append_to_list(self) - - def set_image(self, image, i=0, dx=0, dy=0): - ''' Add an image to the sprite. ''' - while len(self.cached_surfaces) < i + 1: - self.cached_surfaces.append(None) - self._dx.append(0) - self._dy.append(0) - self._dx[i] = dx - self._dy[i] = dy - if isinstance(image, gtk.gdk.Pixbuf) or \ - isinstance(image, cairo.ImageSurface): - w = image.get_width() - h = image.get_height() - else: - w, h = image.get_size() - if i == 0: # Always reset width and height when base image changes. - self.rect.width = w + dx - self.rect.height = h + dy - else: - if w + dx > self.rect.width: - self.rect.width = w + dx - if h + dy > self.rect.height: - self.rect.height = h + dy - if isinstance(image, cairo.ImageSurface): - self.cached_surfaces[i] = image - else: # Convert to Cairo surface - surface = cairo.ImageSurface( - cairo.FORMAT_ARGB32, self.rect.width, self.rect.height) - context = cairo.Context(surface) - context = gtk.gdk.CairoContext(context) - context.set_source_pixbuf(image, 0, 0) - context.rectangle(0, 0, self.rect.width, self.rect.height) - context.fill() - self.cached_surfaces[i] = surface - - def move(self, pos): - ''' Move to new (x, y) position ''' - self.inval() - self.rect.x, self.rect.y = int(pos[0]), int(pos[1]) - self.inval() - - def move_relative(self, pos): - ''' Move to new (x+dx, y+dy) position ''' - self.inval() - self.rect.x += int(pos[0]) - self.rect.y += int(pos[1]) - self.inval() - - def get_xy(self): - ''' Return current (x, y) position ''' - return (self.rect.x, self.rect.y) - - def get_dimensions(self): - ''' Return current size ''' - return (self.rect.width, self.rect.height) - - def get_layer(self): - ''' Return current layer ''' - return self.layer - - def set_shape(self, image, i=0): - ''' Set the current image associated with the sprite ''' - self.inval() - self.set_image(image, i) - self.inval() - - def set_layer(self, layer=None): - ''' Set the layer for a sprite ''' - self._sprites.remove_from_list(self) - if layer is not None: - self.layer = layer - for i in range(self._sprites.length_of_list()): - if layer < self._sprites.get_sprite(i).layer: - self._sprites.insert_in_list(self, i) - self.inval() - return - self._sprites.append_to_list(self) - self.inval() - - def set_label(self, new_label, i=0): - ''' Set the label drawn on the sprite ''' - self._extend_labels_array(i) - if type(new_label) is str or type(new_label) is unicode: - # pango doesn't like nulls - self.labels[i] = new_label.replace("\0", " ") - else: - self.labels[i] = str(new_label) - self.inval() - - def set_margins(self, l=0, t=0, r=0, b=0): - ''' Set the margins for drawing the label ''' - self._margins = [l, t, r, b] - - def _extend_labels_array(self, i): - ''' Append to the labels attribute list ''' - if self._fd is None: - self.set_font('Sans') - if self._color is None: - self._color = (0., 0., 0.) - while len(self.labels) < i + 1: - self.labels.append(" ") - self._scale.append(self._scale[0]) - self._rescale.append(self._rescale[0]) - self._horiz_align.append(self._horiz_align[0]) - self._vert_align.append(self._vert_align[0]) - - def set_font(self, font): - ''' Set the font for a label ''' - self._fd = pango.FontDescription(font) - - def set_label_color(self, rgb): - ''' Set the font color for a label ''' - COLORTABLE = {'black': '#000000', 'white': '#FFFFFF', - 'red': '#FF0000', 'yellow': '#FFFF00', - 'green': '#00FF00', 'cyan': '#00FFFF', - 'blue': '#0000FF', 'purple': '#FF00FF', - 'gray': '#808080'} - if rgb.lower() in COLORTABLE: - rgb = COLORTABLE[rgb.lower()] - # Convert from '#RRGGBB' to floats - self._color = (int('0x' + rgb[1:3], 16) / 256., - int('0x' + rgb[3:5], 16) / 256., - int('0x' + rgb[5:7], 16) / 256.) - return - - def set_label_attributes(self, scale, rescale=True, horiz_align="center", - vert_align="middle", i=0): - ''' Set the various label attributes ''' - self._extend_labels_array(i) - self._scale[i] = scale - self._rescale[i] = rescale - self._horiz_align[i] = horiz_align - self._vert_align[i] = vert_align - - def hide(self): - ''' Hide a sprite ''' - self.inval() - self._sprites.remove_from_list(self) - - def restore(self): - ''' Restore a hidden sprite ''' - self.set_layer() - - def inval(self): - ''' Invalidate a region for gtk ''' - self._sprites.widget.queue_draw_area(self.rect.x, - self.rect.y, - self.rect.width, - self.rect.height) - - def draw(self, cr=None): - ''' Draw the sprite (and label) ''' - if cr is None: - print 'sprite.draw: no Cairo context.' - return - for i, surface in enumerate(self.cached_surfaces): - cr.set_source_surface(surface, - self.rect.x + self._dx[i], - self.rect.y + self._dy[i]) - cr.rectangle(self.rect.x + self._dx[i], - self.rect.y + self._dy[i], - self.rect.width, - self.rect.height) - cr.fill() - if len(self.labels) > 0: - self.draw_label(cr) - - def hit(self, pos): - ''' Is (x, y) on top of the sprite? ''' - x, y = pos - if x < self.rect.x: - return False - if x > self.rect.x + self.rect.width: - return False - if y < self.rect.y: - return False - if y > self.rect.y + self.rect.height: - return False - return True - - def draw_label(self, cr): - ''' Draw the label based on its attributes ''' - # Create a pangocairo context - cr = pangocairo.CairoContext(cr) - my_width = self.rect.width - self._margins[0] - self._margins[2] - if my_width < 0: - my_width = 0 - my_height = self.rect.height - self._margins[1] - self._margins[3] - for i in range(len(self.labels)): - pl = cr.create_layout() - pl.set_text(str(self.labels[i])) - self._fd.set_size(int(self._scale[i] * pango.SCALE)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - if w > my_width: - if self._rescale[i]: - self._fd.set_size( - int(self._scale[i] * pango.SCALE * my_width / w)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - else: - j = len(self.labels[i]) - 1 - while(w > my_width and j > 0): - pl.set_text( - "…" + self.labels[i][len(self.labels[i]) - j:]) - self._fd.set_size(int(self._scale[i] * pango.SCALE)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - j -= 1 - if self._horiz_align[i] == "center": - x = int(self.rect.x + self._margins[0] + (my_width - w) / 2) - elif self._horiz_align[i] == 'left': - x = int(self.rect.x + self._margins[0]) - else: # right - x = int(self.rect.x + self.rect.width - w - self._margins[2]) - h = pl.get_size()[1] / pango.SCALE - if self._vert_align[i] == "middle": - y = int(self.rect.y + self._margins[1] + (my_height - h) / 2) - elif self._vert_align[i] == "top": - y = int(self.rect.y + self._margins[1]) - else: # bottom - y = int(self.rect.y + self.rect.height - h - self._margins[3]) - cr.save() - cr.translate(x, y) - cr.set_source_rgb(self._color[0], self._color[1], self._color[2]) - cr.update_layout(pl) - cr.show_layout(pl) - cr.restore() - - def label_width(self): - ''' Calculate the width of a label ''' - cr = pangocairo.CairoContext(self._sprites.cr) - if cr is not None: - max = 0 - for i in range(len(self.labels)): - pl = cr.create_layout() - pl.set_text(self.labels[i]) - self._fd.set_size(int(self._scale[i] * pango.SCALE)) - pl.set_font_description(self._fd) - w = pl.get_size()[0] / pango.SCALE - if w > max: - max = w - return max - else: - return self.rect.width - - def label_safe_width(self): - ''' Return maximum width for a label ''' - return self.rect.width - self._margins[0] - self._margins[2] - - def label_safe_height(self): - ''' Return maximum height for a label ''' - return self.rect.height - self._margins[1] - self._margins[3] - - def label_left_top(self): - ''' Return the upper-left corner of the label safe zone ''' - return(self._margins[0], self._margins[1]) - - def get_pixel(self, pos, i=0): - ''' Return the pixel at (x, y) ''' - x = int(pos[0] - self.rect.x) - y = int(pos[1] - self.rect.y) - if x < 0 or x > (self.rect.width - 1) or \ - y < 0 or y > (self.rect.height - 1): - return(-1, -1, -1, -1) - - # create a new 1x1 cairo surface - cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1); - cr = cairo.Context(cs) - cr.set_source_surface(self.cached_surfaces[i], -x, -y) - cr.rectangle(0,0,1,1) - cr.set_operator(cairo.OPERATOR_SOURCE) - cr.fill() - cs.flush() # ensure all writing is done - # Read the pixel - pixels = cs.get_data() - return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0) - diff --git a/gtk2/toolbar_utils.py b/gtk2/toolbar_utils.py deleted file mode 100644 index 94e6883..0000000 --- a/gtk2/toolbar_utils.py +++ /dev/null @@ -1,164 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2011, Walter Bender - -# 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 3 of the License, or -# (at your option) any later version. -# -# You should have received a copy of the GNU General Public License -# along with this library; if not, write to the Free Software -# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - - -import gtk - -from sugar.graphics.radiotoolbutton import RadioToolButton -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.combobox import ComboBox -from sugar.graphics.toolcombobox import ToolComboBox - - -def combo_factory(combo_array, toolbar, callback, cb_arg=None, - tooltip=None, default=None): - '''Factory for making a toolbar combo box''' - combo = ComboBox() - if tooltip is not None and hasattr(combo, 'set_tooltip_text'): - combo.set_tooltip_text(tooltip) - if cb_arg is not None: - combo.connect('changed', callback, cb_arg) - else: - combo.connect('changed', callback) - for i, selection in enumerate(combo_array): - combo.append_item(i, selection, None) - combo.show() - toolitem = gtk.ToolItem() - toolitem.add(combo) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - if default is not None: - combo.set_active(combo_array.index(default)) - return combo - - -def entry_factory(default_string, toolbar, tooltip=None, max=3): - ''' Factory for adding a text box to a toolbar ''' - entry = gtk.Entry() - entry.set_text(default_string) - if tooltip is not None and hasattr(entry, 'set_tooltip_text'): - entry.set_tooltip_text(tooltip) - entry.set_width_chars(max) - entry.show() - toolitem = gtk.ToolItem() - toolitem.add(entry) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - return entry - - -def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None, - accelerator=None): - '''Factory for making tooplbar buttons''' - button = ToolButton(icon_name) - if tooltip is not None: - button.set_tooltip(tooltip) - button.props.sensitive = True - if accelerator is not None: - button.props.accelerator = accelerator - if cb_arg is not None: - button.connect('clicked', callback, cb_arg) - else: - button.connect('clicked', callback) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(button, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(button, -1) - button.show() - return button - - -def radio_factory(name, toolbar, callback, cb_arg=None, tooltip=None, - group=None): - ''' Add a radio button to a toolbar ''' - button = RadioToolButton(group=group) - button.set_named_icon(name) - if callback is not None: - if cb_arg is None: - button.connect('clicked', callback) - else: - button.connect('clicked', callback, cb_arg) - if hasattr(toolbar, 'insert'): # Add button to the main toolbar... - toolbar.insert(button, -1) - else: # ...or a secondary toolbar. - toolbar.props.page.insert(button, -1) - button.show() - if tooltip is not None: - button.set_tooltip(tooltip) - return button - - -def label_factory(toolbar, label_text, width=None): - ''' Factory for adding a label to a toolbar ''' - label = gtk.Label(label_text) - label.set_line_wrap(True) - if width is not None: - label.set_size_request(width, -1) # doesn't work on XOs - label.show() - toolitem = gtk.ToolItem() - toolitem.add(label) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - return label - - -def separator_factory(toolbar, expand=False, visible=True): - ''' add a separator to a toolbar ''' - separator = gtk.SeparatorToolItem() - separator.props.draw = visible - separator.set_expand(expand) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(separator, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(separator, -1) - separator.show() - - -def image_factory(image, toolbar, tooltip=None): - ''' Add an image to the toolbar ''' - img = gtk.Image() - img.set_from_pixbuf(image) - img_tool = gtk.ToolItem() - img_tool.add(img) - if tooltip is not None: - img.set_tooltip_text(tooltip) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(img_tool, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(img_tool, -1) - img_tool.show() - return img - - -def spin_factory(default, min, max, callback, toolbar): - spin_adj = gtk.Adjustment(default, min, max, 1, 32, 0) - spin = gtk.SpinButton(spin_adj, 0, 0) - spin_id = spin.connect('value-changed', callback) - spin.set_numeric(True) - spin.show() - toolitem = gtk.ToolItem() - toolitem.add(spin) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - return spin diff --git a/gtk2/toolbar_utils.py~ b/gtk2/toolbar_utils.py~ deleted file mode 100644 index ef2382d..0000000 --- a/gtk2/toolbar_utils.py~ +++ /dev/null @@ -1,165 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2011, Walter Bender -# Port To GTK3: -# Ignacio Rodriguez -# 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 3 of the License, or -# (at your option) any later version. -# -# You should have received a copy of the GNU General Public License -# along with this library; if not, write to the Free Software -# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - - -from gi.repository import Gtk - -from sugar3.graphics.radiotoolbutton import RadioToolButton -from sugar3.graphics.toolbutton import ToolButton -from sugar3.graphics.combobox import ComboBox -from sugar3.graphics.toolcombobox import ToolComboBox - - -def combo_factory(combo_array, toolbar, callback, cb_arg=None, - tooltip=None, default=None): - '''Factory for making a toolbar combo box''' - combo = ComboBox() - if tooltip is not None and hasattr(combo, 'set_tooltip_text'): - combo.set_tooltip_text(tooltip) - if cb_arg is not None: - combo.connect('changed', callback, cb_arg) - else: - combo.connect('changed', callback) - for i, selection in enumerate(combo_array): - combo.append_item(i, selection, None) - combo.show() - toolitem = Gtk.ToolItem() - toolitem.add(combo) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - if default is not None: - combo.set_active(combo_array.index(default)) - return combo - - -def entry_factory(default_string, toolbar, tooltip=None, max=3): - ''' Factory for adding a text box to a toolbar ''' - entry = Gtk.Entry() - entry.set_text(default_string) - if tooltip is not None and hasattr(entry, 'set_tooltip_text'): - entry.set_tooltip_text(tooltip) - entry.set_width_chars(max) - entry.show() - toolitem = Gtk.ToolItem() - toolitem.add(entry) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - return entry - - -def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None, - accelerator=None): - '''Factory for making tooplbar buttons''' - button = ToolButton(icon_name) - if tooltip is not None: - button.set_tooltip(tooltip) - button.props.sensitive = True - if accelerator is not None: - button.props.accelerator = accelerator - if cb_arg is not None: - button.connect('clicked', callback, cb_arg) - else: - button.connect('clicked', callback) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(button, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(button, -1) - button.show() - return button - - -def radio_factory(name, toolbar, callback, cb_arg=None, tooltip=None, - group=None): - ''' Add a radio button to a toolbar ''' - button = RadioToolButton(group=group) - button.set_named_icon(name) - if callback is not None: - if cb_arg is None: - button.connect('clicked', callback) - else: - button.connect('clicked', callback, cb_arg) - if hasattr(toolbar, 'insert'): # Add button to the main toolbar... - toolbar.insert(button, -1) - else: # ...or a secondary toolbar. - toolbar.props.page.insert(button, -1) - button.show() - if tooltip is not None: - button.set_tooltip(tooltip) - return button - - -def label_factory(toolbar, label_text, width=None): - ''' Factory for adding a label to a toolbar ''' - label = Gtk.Label(label_text) - label.set_line_wrap(True) - if width is not None: - label.set_size_request(width, -1) # doesn't work on XOs - label.show() - toolitem = Gtk.ToolItem() - toolitem.add(label) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - return label - - -def separator_factory(toolbar, expand=False, visible=True): - ''' add a separator to a toolbar ''' - separator = Gtk.SeparatorToolItem() - separator.props.draw = visible - separator.set_expand(expand) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(separator, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(separator, -1) - separator.show() - - -def image_factory(image, toolbar, tooltip=None): - ''' Add an image to the toolbar ''' - img = Gtk.Image() - img.set_from_pixbuf(image) - img_tool = Gtk.ToolItem() - img_tool.add(img) - if tooltip is not None: - img.set_tooltip_text(tooltip) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(img_tool, -1) - else: # or a secondary toolbar - toolbar.props.page.insert(img_tool, -1) - img_tool.show() - return img - - -def spin_factory(default, min, max, callback, toolbar): - spin_adj = Gtk.Adjustment(default, min, max, 1, 32, 0) - spin = Gtk.SpinButton(spin_adj, 0, 0) - spin_id = spin.connect('value-changed', callback) - spin.set_numeric(True) - spin.show() - toolitem = Gtk.ToolItem() - toolitem.add(spin) - if hasattr(toolbar, 'insert'): # the main toolbar - toolbar.insert(toolitem, -1) - else: - toolbar.props.page.insert(toolitem, -1) - toolitem.show() - return spin diff --git a/gtk2/utils.py b/gtk2/utils.py deleted file mode 100644 index 230ab45..0000000 --- a/gtk2/utils.py +++ /dev/null @@ -1,61 +0,0 @@ -#Copyright (c) 2011 Walter Bender - -# 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 3 of the License, or -# (at your option) any later version. -# -# You should have received a copy of the GNU General Public License -# along with this library; if not, write to the Free Software -# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - -import subprocess -from StringIO import StringIO -try: - OLD_SUGAR_SYSTEM = False - import json - json.dumps - from json import load as jload - from json import dump as jdump -except (ImportError, AttributeError): - try: - import simplejson as json - from simplejson import load as jload - from simplejson import dump as jdump - except: - OLD_SUGAR_SYSTEM = True - - -def json_load(text): - """ Load JSON data using what ever resources are available. """ - if OLD_SUGAR_SYSTEM is True: - listdata = json.read(text) - else: - # strip out leading and trailing whitespace, nulls, and newlines - io = StringIO(text) - try: - listdata = jload(io) - except ValueError: - # assume that text is ascii list - listdata = text.split() - for i, value in enumerate(listdata): - listdata[i] = int(value) - return listdata - - -def json_dump(data): - """ Save data using available JSON tools. """ - if OLD_SUGAR_SYSTEM is True: - return json.write(data) - else: - _io = StringIO() - jdump(data, _io) - return _io.getvalue() - - -def play_audio_from_file(file_path): - """ Audio media """ - command_line = ['gst-launch', 'filesrc', 'location=' + file_path, - '! oggdemux', '! vorbisdec', '! audioconvert', - '! alsasink'] - subprocess.call(command_line) -- cgit v0.9.1