diff --git a/JigsawPuzzleActivity.py b/JigsawPuzzleActivity.py index ee2a2e3..b538bc4 100644 --- a/JigsawPuzzleActivity.py +++ b/JigsawPuzzleActivity.py @@ -19,30 +19,39 @@ # # init gthreads before using abiword -import gobject -gobject.threads_init() +import gi +gi.require_version('Pango', '1.0') +gi.require_version('Gtk', '3.0') +from gi.repository import GObject + +from sugar3.activity.activity import Activity, get_bundle_path +from sugar3.graphics.toolbarbox import ToolbarBox +from sugar3.activity.widgets import ActivityButton +from sugar3.activity.widgets import TitleEntry +from sugar3.activity.widgets import StopButton +from sugar3.activity.widgets import ShareButton +from sugar3.activity.widgets import DescriptionItem -from sugar.activity.activity import Activity, ActivityToolbox, get_bundle_path from gettext import gettext as _ import logging, os, sys import time import zlib -from cStringIO import StringIO +from io import StringIO from mamamedia_modules import json from JigsawPuzzleUI import JigsawPuzzleUI -from mamamedia_modules import TubeHelper +# from mamamedia_modules import TubeHelper from mamamedia_modules import GAME_IDLE, GAME_STARTED, GAME_FINISHED, GAME_QUIT logger = logging.getLogger('jigsawpuzzle-activity') -from dbus.service import method, signal -from dbus.gobject_service import ExportedGObject +# from dbus.service import method, signal +# from dbus.gi_service import ExportedGObject SERVICE = "org.worldwideworkshop.olpc.JigsawPuzzle.Tube" IFACE = SERVICE PATH = "/org/worldwideworkshop/olpc/JigsawPuzzle/Tube" - +''' class GameTube (ExportedGObject): """ Manage the communication between cooperating activities """ def __init__(self, tube, is_initiator, activity): @@ -79,30 +88,37 @@ def Hello(self): """Request that this player's Welcome method is called to bring it up to date with the game state. """ + pass @signal(dbus_interface=IFACE, signature='s') def GameUpdate(self, game_state): """ When an image is chosen by the initiator, this method gets called.""" + pass @signal(dbus_interface=IFACE, signature='su') def StatusUpdate (self, status, ellapsed_time): """ signal a reshufle, possibly with a new image """ - + pass + @signal(dbus_interface=IFACE, signature='') def RequestImage (self): """ Request that the game image be sent to us. """ + pass @signal(dbus_interface=IFACE, signature='i') def PiecePicked (self, index): """ Signals a piece picked in the correct board position """ + pass @signal(dbus_interface=IFACE, signature='i') def PiecePlaced (self, index): """ Signals a piece placed in the correct board position """ + pass @signal(dbus_interface=IFACE, signature='i(dd)') def PieceDropped (self, index, position): """ Signals a piece that has been moved around and dropped """ + pass ############### # Callbacks @@ -220,8 +236,9 @@ def ImageDetailsSync (self, state): self.activity.ui._thaw(state) self.activity.ui._send_status_update() +''' -class JigsawPuzzleActivity(Activity, TubeHelper): +class JigsawPuzzleActivity(Activity): def __init__(self, handle): Activity.__init__(self, handle) logger.debug('Starting Jigsaw Puzzle activity... %s' % str(get_bundle_path())) @@ -229,24 +246,49 @@ def __init__(self, handle): self.connect('destroy', self._destroy_cb) - toolbox = ActivityToolbox(self) - self.set_toolbox(toolbox) - toolbox.show() - - # Toolbar title size hack - title_widget = toolbox._activity_toolbar.title - title_widget.set_size_request(title_widget.get_layout().get_pixel_size()[0] + 30, -1) - self.ui = JigsawPuzzleUI(self) self.set_canvas(self.ui) - + self.build_toolbar() self.show_all() - - TubeHelper.__init__(self, tube_class=GameTube, service=SERVICE) - + + # TubeHelper.__init__(self, tube_class=GameTube, service=SERVICE) + + def build_toolbar(self): + # toolbar with the new toolbar redesign + toolbar_box = ToolbarBox() + + activity_button = ActivityButton(self) + toolbar_box.toolbar.insert(activity_button, 0) + activity_button.show() + + title_entry = TitleEntry(self) + toolbar_box.toolbar.insert(title_entry, -1) + title_entry.show() + + description_item = DescriptionItem(self) + toolbar_box.toolbar.insert(description_item, -1) + description_item.show() + + share_button = ShareButton(self) + toolbar_box.toolbar.insert(share_button, -1) + share_button.show() + + separator = Gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + toolbar_box.toolbar.insert(separator, -1) + separator.show() + + stop_button = StopButton(self) + toolbar_box.toolbar.insert(stop_button, -1) + stop_button.show() + + self.set_toolbar_box(toolbar_box) + toolbar_box.show() + def _destroy_cb(self, data=None): return True - + ''' def new_tube_cb (self): self.ui.set_contest_mode(True) @@ -263,7 +305,8 @@ def buddy_joined_cb (self, buddy): def buddy_left_cb (self, buddy): nick = self.ui.buddy_panel.remove_player(buddy) self.ui.set_message(_("Buddy '%s' left the game!") % (nick), frommesh=True) - + ''' + def read_file(self, file_path): f = open(file_path, 'r') try: diff --git a/JigsawPuzzleUI.py b/JigsawPuzzleUI.py index 899a8bc..0502a51 100644 --- a/JigsawPuzzleUI.py +++ b/JigsawPuzzleUI.py @@ -18,9 +18,7 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk, gobject, pango +from gi.repository import Gtk, GObject, Pango, Gdk import os from mamamedia_modules import BorderFrame, BORDER_ALL_BUT_BOTTOM, BORDER_ALL_BUT_LEFT @@ -48,37 +46,37 @@ COLOR_FRAME_CONTROLS = "#FFFF00" COLOR_BG_CONTROLS = "#66CC00" COLOR_FG_BUTTONS = ( - (gtk.STATE_NORMAL,"#CCFF99"), - (gtk.STATE_ACTIVE,"#CCFF99"), - (gtk.STATE_PRELIGHT,"#CCFF99"), - (gtk.STATE_SELECTED,"#CCFF99"), - (gtk.STATE_INSENSITIVE,"#CCFF99"), + (Gtk.StateType.NORMAL,"#CCFF99"), + (Gtk.StateType.ACTIVE,"#CCFF99"), + (Gtk.StateType.PRELIGHT,"#CCFF99"), + (Gtk.StateType.SELECTED,"#CCFF99"), + (Gtk.StateType.INSENSITIVE,"#CCFF99"), ) COLOR_BG_BUTTONS = ( - (gtk.STATE_NORMAL,"#027F01"), - (gtk.STATE_ACTIVE,"#014D01"), - (gtk.STATE_PRELIGHT,"#016D01"), - (gtk.STATE_SELECTED,"#027F01"), - (gtk.STATE_INSENSITIVE,"#CCCCCC"), + (Gtk.StateType.NORMAL,"#027F01"), + (Gtk.StateType.ACTIVE,"#014D01"), + (Gtk.StateType.PRELIGHT,"#016D01"), + (Gtk.StateType.SELECTED,"#027F01"), + (Gtk.StateType.INSENSITIVE,"#CCCCCC"), ) def prepare_btn(btn, w=-1, h=-1): for state, color in COLOR_BG_BUTTONS: - btn.modify_bg(state, gtk.gdk.color_parse(color)) + btn.modify_bg(state, Gdk.color_parse(color)) c = btn.get_child() if c is not None: for state, color in COLOR_FG_BUTTONS: - c.modify_fg(state, gtk.gdk.color_parse(color)) + c.modify_fg(state, Gdk.color_parse(color)) else: for state, color in COLOR_FG_BUTTONS: - btn.modify_fg(state, gtk.gdk.color_parse(color)) + btn.modify_fg(state, Gdk.color_parse(color)) if w>0 or h>0: btn.set_size_request(w, h) return btn class JigsawPuzzleUI (BorderFrame): - __gsignals__ = {'game-state-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (int,))} + __gsignals__ = {'game-state-changed' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (int,))} def __init__(self, parent): super(JigsawPuzzleUI, self).__init__(border_color=COLOR_FRAME_OUTER) @@ -95,7 +93,7 @@ def __init__(self, parent): self._readonly = False self._join_time = 0 - inner_table = gtk.Table(2,2,False) + inner_table = Gtk.Table(2,2,False) self.add(inner_table) self.game = JigsawPuzzleWidget() @@ -106,50 +104,50 @@ def __init__(self, parent): self.game.show() # panel is a holder for everything on the left side down to (not inclusive) the language dropdown - panel = gtk.VBox() + panel = Gtk.VBox() # Logo image - img_logo = gtk.Image() + img_logo = Gtk.Image() img_logo.set_from_file("icons/logo.png") img_logo.show() - panel.pack_start(img_logo, expand=False, fill=False) + panel.pack_start(self, img_logo, False, False) # Control panel has the image controls control_panel = BorderFrame(border=BORDER_ALL_BUT_BOTTOM, border_color=COLOR_FRAME_CONTROLS, bg_color=COLOR_BG_CONTROLS) - control_panel_box = gtk.VBox() + control_panel_box = Gtk.VBox() - scrolled = gtk.ScrolledWindow() - scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER - scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC + scrolled = Gtk.ScrolledWindow() + scrolled.props.hscrollbar_policy = Gtk.PolicyType.NEVER + scrolled.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC scrolled.show() scrolled.add_with_viewport(control_panel_box) - scrolled.child.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(COLOR_BG_CONTROLS)) + scrolled.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse(COLOR_BG_CONTROLS)) control_panel.add(scrolled) - spacer = gtk.Label() + spacer = Gtk.Label() spacer.set_size_request(-1, 5) - control_panel_box.pack_start(spacer, expand=False, fill=False) + control_panel_box.pack_start(spacer, False, False, 0) - btn_box = gtk.Table(2,5,False) + btn_box = Gtk.Table(2,5,False) btn_box.set_col_spacings(5) btn_box.set_row_spacings(5) - btn_box.attach(gtk.Label(), 0,1,0,2) + btn_box.attach(Gtk.Label(), 0,1,0,2) # Cut type buttons - self.btn_basic_cut = gtk.ToggleButton() - i = gtk.Image() + self.btn_basic_cut = Gtk.ToggleButton() + i = Gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join('icons', 'cut_basic.svg'))) self.btn_basic_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_basic_cut), 1,2,0,1,0,0) - self.btn_simple_cut = gtk.ToggleButton() - i = gtk.Image() + self.btn_simple_cut = Gtk.ToggleButton() + i = Gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join('icons', 'cut_simple.svg'))) self.btn_simple_cut.set_image(i) btn_box.attach(prepare_btn(self.btn_simple_cut), 2,3,0,1,0,0) - self.btn_classic_cut = gtk.ToggleButton() - i = gtk.Image() + self.btn_classic_cut = Gtk.ToggleButton() + i = Gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join('icons', 'cut_classic.svg'))) self.btn_classic_cut.set_image(i) # Link cutter buttons with cutter styles @@ -158,24 +156,24 @@ def __init__(self, parent): 'simple': self.btn_simple_cut, 'classic': self.btn_classic_cut, } - for k,v in self.btn_cut_mapping.items(): + for k,v in list(self.btn_cut_mapping.items()): v.connect("released", self.set_piece_cut, k) btn_box.attach(prepare_btn(self.btn_classic_cut), 3,4,0,1,0,0) # Difficulty level buttons - self.btn_easy_level = gtk.ToggleButton() - i = gtk.Image() + self.btn_easy_level = Gtk.ToggleButton() + i = Gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join('icons', 'level_easy.svg'))) self.btn_easy_level.set_active(True) self.btn_easy_level.set_image(i) btn_box.attach(prepare_btn(self.btn_easy_level), 1,2,1,2,0,0) - self.btn_normal_level = gtk.ToggleButton() - i = gtk.Image() + self.btn_normal_level = Gtk.ToggleButton() + i = Gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join('icons', 'level_normal.svg'))) self.btn_normal_level.set_image(i) btn_box.attach(prepare_btn(self.btn_normal_level), 2,3,1,2,0,0) - self.btn_hard_level = gtk.ToggleButton() - i = gtk.Image() + self.btn_hard_level = Gtk.ToggleButton() + i = Gtk.Image() i.set_from_pixbuf(utils.load_image(os.path.join('icons', 'level_hard.svg'))) self.btn_hard_level.set_image(i) # Link level buttons with levels @@ -184,13 +182,13 @@ def __init__(self, parent): 5: self.btn_normal_level, 8: self.btn_hard_level, } - for k,v in self.btn_level_mapping.items(): + for k,v in list(self.btn_level_mapping.items()): v.connect("released", self.set_level, k) btn_box.attach(prepare_btn(self.btn_hard_level), 3,4,1,2,0,0) - btn_box.attach(gtk.Label(), 4,5,0,2) - control_panel_box.pack_start(btn_box, expand=False) + btn_box.attach(Gtk.Label(), 4,5,0,2) + control_panel_box.pack_start(btn_box, False, False, 0) self.thumb = ImageSelectorWidget(frame_color=COLOR_FRAME_THUMB, prepare_btn_cb=prepare_btn, @@ -199,45 +197,45 @@ def __init__(self, parent): parent=self._parent) self.thumb.connect("category_press", self.do_select_category) self.thumb.connect("image_press", self.do_shuffle) - control_panel_box.pack_start(self.thumb, expand=False) + control_panel_box.pack_start(self.thumb, False, False, 0) - spacer = gtk.Label() + spacer = Gtk.Label() spacer.set_size_request(-1, 5) - control_panel_box.pack_start(spacer, expand=False, fill=False) + control_panel_box.pack_start(spacer, False, False, 0) # The game control buttons - btn_box = gtk.Table(3,4,False) + btn_box = Gtk.Table(3,4,False) btn_box.set_row_spacings(2) - btn_box.attach(gtk.Label(), 0,1,0,4) - btn_box.attach(gtk.Label(), 2,3,0,4) - self.btn_solve = prepare_btn(gtk.Button(" "), 200) + btn_box.attach(Gtk.Label(), 0,1,0,4) + btn_box.attach(Gtk.Label(), 2,3,0,4) + self.btn_solve = prepare_btn(Gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_solve, _("Solve")]) self.btn_solve.connect("clicked", self.do_solve) btn_box.attach(self.btn_solve, 1,2,0,1,0,0) - self.btn_shuffle = prepare_btn(gtk.Button(" "), 200) + self.btn_shuffle = prepare_btn(Gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_shuffle, _("Shuffle")]) self.btn_shuffle.connect("clicked", self.do_shuffle) btn_box.attach(self.btn_shuffle, 1,2,1,2,0,0) - self.btn_add = prepare_btn(gtk.Button(" "), 200) + self.btn_add = prepare_btn(Gtk.Button(" "), 200) self.labels_to_translate.append([self.btn_add, _("My Picture")]) self.btn_add.connect("clicked", self.do_add_image) btn_box.attach(self.btn_add, 1,2,2,3,0,0) - self.btn_hint = prepare_btn(gtk.ToggleButton(" "), 200) + self.btn_hint = prepare_btn(Gtk.ToggleButton(" "), 200) self.labels_to_translate.append([self.btn_hint, _("Board Hint")]) self.btn_hint.connect("clicked", self.do_show_hint) btn_box.attach(self.btn_hint, 1,2,3,4,0,0) - control_panel_box.pack_start(btn_box, False) + control_panel_box.pack_start(btn_box, False, False, 0) self.control_panel_box = control_panel_box # Control panel end - panel.pack_start(control_panel, expand=True, fill=True) + panel.pack_start(control_panel, True, True, 0) inner_table.attach(panel, 0,1,0,1,0) self.game_box = BorderFrame(border_color=COLOR_FRAME_GAME) self.game_box.add(self.game) - self.notebook = gtk.Notebook() + self.notebook = Gtk.Notebook() self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False @@ -251,29 +249,29 @@ def __init__(self, parent): lang_combo.install() lang_box = BorderFrame(bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) - hbox = gtk.HBox(False) - vbox = gtk.VBox(False) - vbox.pack_start(lang_combo, padding=8) - hbox.pack_start(vbox, padding=8) + hbox = Gtk.HBox(False) + vbox = Gtk.VBox(False) + vbox.pack_start(lang_combo,False, False,8) + hbox.pack_start(vbox,False, False, 8) lang_box.add(hbox) - inner_table.attach(lang_box, 0,1,1,2,gtk.FILL, gtk.FILL) + inner_table.attach(lang_box, 0,1,1,2,Gtk.FILL, Gtk.FILL) timer_box = BorderFrame(border=BORDER_ALL_BUT_LEFT, bg_color=COLOR_BG_CONTROLS, border_color=COLOR_FRAME_CONTROLS) - timer_hbox = gtk.HBox(False) + timer_hbox = Gtk.HBox(False) self.timer = TimerWidget(bg_color=COLOR_BG_BUTTONS[0][1], fg_color=COLOR_FG_BUTTONS[0][1], lbl_color=COLOR_BG_BUTTONS[1][1]) self.timer.set_sensitive(False) self.timer.set_border_width(3) self.labels_to_translate.append((self.timer, _("Time: "))) - timer_hbox.pack_start(self.timer, False, padding=8) + timer_hbox.pack_start(self.timer, False, False, 8) self.timer.connect('timer_toggle', self.timer_toggle_cb) - self.msg_label = gtk.Label() + self.msg_label = Gtk.Label() self.msg_label.show() - timer_hbox.pack_start(self.msg_label, True) + timer_hbox.pack_start(self.msg_label, True, False, 0) self.do_select_language(lang_combo) @@ -316,7 +314,7 @@ def set_readonly (self): self.set_button_translation(self.btn_shuffle, "Game Running") self.btn_shuffle.get_child().set_label(_("Game Running")) self.btn_shuffle.set_sensitive(False) - for b in self.btn_cut_mapping.values() + self.btn_level_mapping.values(): + for b in list(self.btn_cut_mapping.values()) + list(self.btn_level_mapping.values()): if not (b.get_active() and self.is_initiator()): b.set_sensitive(False) self._readonly = True @@ -360,7 +358,7 @@ def set_game_state (self, state, force=False): self._send_game_update() self._send_status_update() elif state[0] <= GAME_STARTED[0] and self._contest_mode and not self.is_initiator(): - c = gtk.gdk.Cursor(gtk.gdk.WATCH) + c = Gdk.Cursor(Gdk.WATCH) self.window.set_cursor(c) @@ -387,9 +385,9 @@ def do_select_category (self, o, *args): def _show_game (self, pixbuf=None, reshuffle=True): if not self.game.get_parent(): self.game_box.pop() - while gtk.events_pending(): - gtk.main_iteration(False) - c = gtk.gdk.Cursor(gtk.gdk.WATCH) + while Gtk.events_pending(): + Gtk.main_iteration(False) + c = Gdk.Cursor(Gdk.WATCH) self.window.set_cursor(c) if not self.game.prepare_image(pixbuf, reshuffle): self._shuffling = False @@ -429,13 +427,13 @@ def do_solve (self, o, *args): self.set_game_state(GAME_FINISHED) self.set_message(_("Puzzle Solved!")) self.control_panel_box.foreach(self.control_panel_box.remove) - lbl = gtk.Label(_("Press Stop on the Toolbar to Exit Activity!")) - lbl.modify_font(pango.FontDescription("bold 9")) + lbl = Gtk.Label(_("Press Stop on the Toolbar to Exit Activity!")) + lbl.modify_font(Pango.FontDescription("bold 9")) lbl.set_line_wrap(True) - lbl.set_justify(gtk.JUSTIFY_CENTER) + lbl.set_justify(Gtk.JUSTIFY_CENTER) lbl.set_size_request(200, -1) lbl.show() - self.control_panel_box.pack_start(lbl, True) + self.control_panel_box.pack_start(lbl, True, False, 0) def do_add_image (self, o, *args): @@ -466,7 +464,7 @@ def set_button_translation (self, btn, translation): def refresh_labels (self, first_time=False): self._parent.set_title(_("Jigsaw Puzzle Activity")) for lbl in self.labels_to_translate: - if isinstance(lbl[0], gtk.Button): + if isinstance(lbl[0], Gtk.Button): lbl[0].get_child().set_label(_(lbl[1])) else: lbl[0].set_label(_(lbl[1])) @@ -483,13 +481,13 @@ def set_piece_cut (self, btn, cutter, *args): def cutter_change_cb (self, o, cutter, tppl): # tppl = target pieces per line - for c,b in self.btn_cut_mapping.items(): + for c,b in list(self.btn_cut_mapping.items()): if c == cutter: b.set_sensitive(True) b.set_active(True) else: b.set_active(False) - for c,b in self.btn_level_mapping.items(): + for c,b in list(self.btn_level_mapping.items()): if c == tppl: b.set_sensitive(True) b.set_active(True) @@ -526,14 +524,14 @@ def _freeze (self, journal=True): def _thaw (self, data): self.timer.reset() for k in ('thumb', 'timer', 'game'): - if data.has_key(k): + if k in data: logging.debug('_thaw data for %s: %s' % (k, data)) getattr(self, k)._thaw(data[k]) - if data.has_key('game'):# and not data.has_key('thumb'): + if 'game' in data:# and not data.has_key('thumb'): self.thumb.load_pb(self.game.board.cutboard.pb) - if data.has_key('timer'): + if 'timer' in data: self._join_time = self.timer.ellapsed() - if data.has_key('game') and data['game']['piece_pos']: + if 'game' in data and data['game']['piece_pos']: self._show_game(reshuffle=False) @utils.trace diff --git a/JigsawPuzzleWidget.py b/JigsawPuzzleWidget.py index beef37b..4dc4e72 100644 --- a/JigsawPuzzleWidget.py +++ b/JigsawPuzzleWidget.py @@ -18,33 +18,32 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk, gobject, pango, cairo +from gi.repository import Gtk, GObject, Pango, Gdk +import cairo import random import os import logging -import md5 -from cStringIO import StringIO +from hashlib import md5 +from io import StringIO from mmm_modules import BorderFrame, utils MAGNET_POWER_PERCENT = 20 CUTTERS = {} def create_pixmap (w, h): - cm = gtk.gdk.colormap_get_system() - pm = gtk.gdk.Pixmap(None, w, h, cm.get_visual().depth) + cm = Gdk.colormap_get_system() + pm = Gdk.Pixmap(None, w, h, cm.get_visual().depth) gc = pm.new_gc() - gc.set_colormap(gtk.gdk.colormap_get_system()) + gc.set_colormap(Gdk.colormap_get_system()) color = cm.alloc_color('white') gc.set_foreground(color) pm.draw_rectangle(gc, True, 0, 0, w, h) return pm -class JigsawPiece (gtk.EventBox): - __gsignals__ = {'picked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'moved' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (int, int)), - 'dropped' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),} +class JigsawPiece (Gtk.EventBox): + __gsignals__ = {'picked' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()), + 'moved' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (int, int)), + 'dropped' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()),} def __init__ (self): super(JigsawPiece, self).__init__() @@ -53,14 +52,14 @@ def __init__ (self): self.root_coords = (0,0) self.last_coords = (0,0) self.shape = None - self.image = gtk.Image() - self.pb_wf = gtk.Image() + self.image = Gtk.Image() + self.pb_wf = Gtk.Image() self.placed = False self._prepare_ui() self._prepare_event_callbacks() def _prepare_ui (self): - self._c = gtk.Fixed() + self._c = Gtk.Fixed() self._c.show() self.add(self._c) self._c.put(self.image, 0, 0) @@ -248,7 +247,7 @@ def _prepare (self, cols, rows, cutter=None, hch=None, vch=None): self.pieces[c].append(self.cut(c,r)) def get_cutter (self): - for k,v in CUTTERS.items(): + for k,v in list(CUTTERS.items()): if isinstance(self.cutter, v): return k return None @@ -270,7 +269,7 @@ def refresh (self): self.cr.set_source_rgb(0,0,0) def get_hint (self): - pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, self.width, self.height) + pb = Gdk.Pixbuf(Gdk.COLORSPACE_RGB, True, 8, self.width, self.height) pb.get_from_drawable(self.hint_pm, self.pm.get_colormap(), 0, 0, 0, 0, self.width, self.height) return pb @@ -358,7 +357,7 @@ def cut (self, x, y): width = int(width) height = int(height) # Prepare the piece mask - mask = gtk.gdk.Pixmap(None, width+width_offset, height+height_offset, 1) + mask = Gdk.Pixmap(None, width+width_offset, height+height_offset, 1) mask_cr = mask.cairo_create() mask_cr.save() mask_cr.set_operator(cairo.OPERATOR_SOURCE) @@ -379,14 +378,14 @@ def cut (self, x, y): # The piece image self.refresh() - pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height) + pb = Gdk.Pixbuf(Gdk.COLORSPACE_RGB, True, 8, width, height) pb.get_from_drawable(self.pm, self.pm.get_colormap(), px, py, 0, 0, width, height) # The outlined image self.cr.move_to(px+offsets['left'], py+offsets['top']) self.path_for_piece(self.cr, x, y, width-width_offset, height-height_offset) self.cr.stroke() - pb_wf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height) + pb_wf = Gdk.Pixbuf(Gdk.COLORSPACE_RGB, True, 8, width, height) pb_wf.get_from_drawable(self.pm, self.pm.get_colormap(), px, py, 0, 0, width, height) return (pb, pb_wf, mask, px, py, width-width_offset, height-height_offset) @@ -423,12 +422,12 @@ def _freeze (self, img_cksum_only=False): def _thaw (self, data): if data is None: return - if data.has_key('pb') and data['pb'] is not None: + if 'pb' in data and data['pb'] is not None: fn = os.tempnam() f = file(fn, 'w+b') f.write(data['pb']) f.close() - i = gtk.Image() + i = Gtk.Image() i.set_from_file(fn) os.remove(fn) self.pb = i.get_pixbuf() @@ -443,17 +442,17 @@ def _thaw (self, data): class JigsawBoard (BorderFrame): """ Drop area for jigsaw pieces to be tested against. Maybe use this to do the piece cutting / hint ? """ - __gsignals__ = {'solved' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), + __gsignals__ = {'solved' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()), } def __init__ (self): super(JigsawBoard, self).__init__(border_color="#0000FF") #self.image = None - self.board = gtk.Fixed() + self.board = Gtk.Fixed() self.board.show() self.add(self.board) self.board_distribution = None self.target_pieces_per_line = 3 - self.hint_board_image = gtk.Image() + self.hint_board_image = Gtk.Image() self.cutboard = CutBoard() def get_cutter (self): @@ -529,7 +528,7 @@ def place_piece (self, piece): bx, by, mx, my = self.board_distribution[index] self.board.move(piece, bx, by) self.board_distribution[index] = None - if len(filter(None, self.board_distribution))==0: + if len([_f for _f in self.board_distribution if _f])==0: for p in self.board.get_children(): if isinstance(p, JigsawPiece): p.hide_wireframe() @@ -552,21 +551,21 @@ def _freeze (self, img_cksum_only=False): def _thaw (self, data): for k in ('target_pieces_per_line', ): - if data.has_key(k): + if k in data: setattr(self, k, data[k]) self.cutboard._thaw(data['cutboard']) -class JigsawPuzzleWidget (gtk.EventBox): +class JigsawPuzzleWidget (Gtk.EventBox): __gsignals__ = { - 'picked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (JigsawPiece,)), - 'dropped' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (JigsawPiece,bool)), - 'solved' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'cutter-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str, int)), + 'picked' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (JigsawPiece,)), + 'dropped' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (JigsawPiece,bool)), + 'solved' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()), + 'cutter-changed' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (str, int)), } def __init__ (self): super(JigsawPuzzleWidget, self).__init__() - self._container = gtk.Fixed() + self._container = Gtk.Fixed() self.add(self._container) self.board = JigsawBoard() self.board.connect('solved', self._solved_cb) @@ -615,7 +614,7 @@ def prepare_image (self, pixbuf=None, reshuffle=True): factor = min((float(w)*0.6)/pixbuf.get_width(), (float(h)*0.6)/pixbuf.get_height()) pixbuf = pixbuf.scale_simple(int(pixbuf.get_width() * factor), int(pixbuf.get_height()*factor), - gtk.gdk.INTERP_BILINEAR) + Gdk.INTERP_BILINEAR) if pixbuf is None: pixbuf = self.board.cutboard.pb if pixbuf is None: @@ -627,7 +626,7 @@ def prepare_image (self, pixbuf=None, reshuffle=True): self._container.remove(child) bx, by = self._container.child_get(self.board, 'x', 'y') bw, bh = self.board.inner.get_size_request() - br = gtk.gdk.Rectangle(bx,by,bw,bh) + br = Gdk.Rectangle(bx,by,bw,bh) for n, piece in enumerate(self.board.get_pieces(reshuffle)): if self.forced_location and len(self.forced_location)>n: if self.forced_location[n] is None: @@ -637,7 +636,7 @@ def prepare_image (self, pixbuf=None, reshuffle=True): self._container.put(piece, *self.forced_location[n]) else: pw,ph = piece.get_size_request() - r = gtk.gdk.Rectangle(bx,by,pw,ph) + r = Gdk.Rectangle(bx,by,pw,ph) r.x = int(random.random()*(w-pw)) r.y = int(random.random()*(h-ph)) if br.intersect(r).width > 0: @@ -649,8 +648,8 @@ def prepare_image (self, pixbuf=None, reshuffle=True): piece.connect('dropped', self._drop_cb) if self.forced_location and len(self.forced_location)>n and self.forced_location[n] is None: self.board.place_piece(piece) - while gtk.events_pending(): - gtk.main_iteration(False) + while Gtk.events_pending(): + Gtk.main_iteration(False) piece.get_position() self.forced_location = None self.running = True @@ -712,14 +711,14 @@ def _freeze (self, img_cksum_only=False): 'piece_pos': [x[1] for x in pieces]} def _thaw (self, data): - if data.has_key('board'): + if 'board' in data: self.board._thaw(data['board']) self.set_cutter(data.get('cutter', None)) self.set_target_pieces_per_line(data.get('target_pieces_per_line', None)) self.forced_location = data.get('piece_pos', None) if __name__ == '__main__': - w = gtk.Window() + w = Gtk.Window() j = JigsawPuzzleWidget() img = utils.load_image('test_image.gif') @@ -727,4 +726,4 @@ def _thaw (self, data): w.add(j) w.show_all() - gtk.main() + Gtk.main() diff --git a/activity/activity.info b/activity/activity.info index 0c66472..e73d4ba 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -1,7 +1,7 @@ [Activity] name = Jigsaw Puzzle bundle_id = org.worldwideworkshop.olpc.JigsawPuzzle -exec = sugar-activity JigsawPuzzleActivity.JigsawPuzzleActivity -s +exec = sugar-activity3 JigsawPuzzleActivity.JigsawPuzzleActivity icon = activity-jigsawpuzzle activity_version = 11 show_launcher = yes diff --git a/mamamedia_modules.py b/mamamedia_modules.py index 3b9fdc3..5141f21 100644 --- a/mamamedia_modules.py +++ b/mamamedia_modules.py @@ -23,8 +23,8 @@ cwd = os.path.split(__file__)[0] -import gtk -theme = gtk.icon_theme_get_default() +from gi.repository import Gtk +theme = Gtk.IconTheme.get_default() if os.path.exists(os.path.join(cwd, 'mmm_modules')): # We are self contained diff --git a/mmm_modules/__init__.py b/mmm_modules/__init__.py index 0b1a050..4cdf24d 100644 --- a/mmm_modules/__init__.py +++ b/mmm_modules/__init__.py @@ -1,8 +1,8 @@ -from borderframe import * -from timer import * -from image_category import * -from i18n import * -from buddy_panel import * -from tube_helper import * -import utils -import json +from .borderframe import * +from .timer import * +from .image_category import * +from .i18n import * +from .buddy_panel import * +from .tube_helper import * +from . import utils +from . import json diff --git a/mmm_modules/borderframe.py b/mmm_modules/borderframe.py index 14d55d1..2cfef7c 100644 --- a/mmm_modules/borderframe.py +++ b/mmm_modules/borderframe.py @@ -18,9 +18,7 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk, gobject, pango +from gi.repository import Gtk, GObject, Pango, Gdk BORDER_LEFT = 1 BORDER_RIGHT = 2 @@ -33,15 +31,15 @@ BORDER_ALL_BUT_TOP = BORDER_HORIZONTAL | BORDER_BOTTOM BORDER_ALL_BUT_LEFT = BORDER_VERTICAL | BORDER_RIGHT -class BorderFrame (gtk.EventBox): +class BorderFrame (Gtk.EventBox): def __init__ (self, border=BORDER_ALL, size=5, bg_color=None, border_color=None): - gtk.EventBox.__init__(self) + Gtk.EventBox.__init__(self) if border_color is not None: - self.set_border_color(gtk.gdk.color_parse(border_color)) - self.inner = gtk.EventBox() + self.set_border_color(Gdk.color_parse(border_color)) + self.inner = Gtk.EventBox() if bg_color is not None: - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bg_color)) - align = gtk.Alignment(1.0,1.0,1.0,1.0) + self.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse(bg_color)) + align = Gtk.Alignment.new(1.0,1.0,1.0,1.0) self.padding = [0,0,0,0] if (border & BORDER_TOP) != 0: self.padding[0] = size @@ -55,11 +53,11 @@ def __init__ (self, border=BORDER_ALL, size=5, bg_color=None, border_color=None) align.add(self.inner) align.show() self.inner.show() - gtk.EventBox.add(self, align) + Gtk.EventBox.add(self, align) self.stack = [] def set_border_color (self, color): - gtk.EventBox.modify_bg(self, gtk.STATE_NORMAL, color) + Gtk.EventBox.modify_bg(self, Gtk.StateType.NORMAL, color) def modify_bg (self, state, color): self.inner.modify_bg(state, color) @@ -67,7 +65,9 @@ def modify_bg (self, state, color): def add (self, widget): self.stack.append(widget) self.inner.add(widget) - self.inner.child.show_now() + # FIXME REVIEW NOTE : RECHECK + + self.inner.show_now() def push (self, widget): widget.set_size_request(*self.inner.child.get_size_request()) diff --git a/mmm_modules/buddy_panel.py b/mmm_modules/buddy_panel.py index 6f5e32e..f1b0bd8 100644 --- a/mmm_modules/buddy_panel.py +++ b/mmm_modules/buddy_panel.py @@ -18,56 +18,54 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk +from gi.repository import Gtk import logging -from tube_helper import GAME_IDLE, GAME_STARTED, GAME_FINISHED, GAME_QUIT +from .tube_helper import GAME_IDLE, GAME_STARTED, GAME_FINISHED, GAME_QUIT #from sugar.graphics.icon import CanvasIcon BUDDYMODE_CONTEST = 0 BUDDYMODE_COLLABORATION = 1 -class BuddyPanel (gtk.ScrolledWindow): +class BuddyPanel (Gtk.ScrolledWindow): def __init__ (self, mode=BUDDYMODE_CONTEST): super(BuddyPanel, self).__init__() - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.set_policy(Gtk.POLICY_AUTOMATIC, Gtk.POLICY_AUTOMATIC) - self.model = gtk.ListStore(str, str, str, str) - self.model.set_sort_column_id(0, gtk.SORT_ASCENDING) - self.treeview = gtk.TreeView() + self.model = Gtk.ListStore(str, str, str, str) + self.model.set_sort_column_id(0, Gtk.SORT_ASCENDING) + self.treeview = Gtk.TreeView() - #col = gtk.TreeViewColumn(_("Icon")) - #r = gtk.CellRendererText() + #col = Gtk.TreeViewColumn(_("Icon")) + #r = Gtk.CellRendererText() #col.pack_start(r, True) #col.set_attributes(r, stock_id=0) #self.treeview.append_column(col) - col = gtk.TreeViewColumn(_("Buddy")) - r = gtk.CellRendererText() + col = Gtk.TreeViewColumn(_("Buddy")) + r = Gtk.CellRendererText() col.pack_start(r, True) col.set_attributes(r, text=0) self.treeview.append_column(col) - col = gtk.TreeViewColumn(_("Status")) - r = gtk.CellRendererText() + col = Gtk.TreeViewColumn(_("Status")) + r = Gtk.CellRendererText() col.pack_start(r, True) col.set_attributes(r, text=1) self.treeview.append_column(col) col.set_visible(mode == BUDDYMODE_CONTEST) - col = gtk.TreeViewColumn(_("Play Time")) - r = gtk.CellRendererText() + col = Gtk.TreeViewColumn(_("Play Time")) + r = Gtk.CellRendererText() col.pack_start(r, True) col.set_attributes(r, text=2) self.treeview.append_column(col) col.set_visible(mode == BUDDYMODE_CONTEST) - col = gtk.TreeViewColumn(_("Joined at")) - r = gtk.CellRendererText() + col = Gtk.TreeViewColumn(_("Joined at")) + r = Gtk.CellRendererText() col.pack_start(r, True) col.set_attributes(r, text=3) self.treeview.append_column(col) diff --git a/mmm_modules/i18n.py b/mmm_modules/i18n.py index 454d871..0a0ec7c 100644 --- a/mmm_modules/i18n.py +++ b/mmm_modules/i18n.py @@ -25,7 +25,7 @@ import gettext import locale -import gtk, gobject +from gi.repository import Gtk, GObject _ = lambda x: x @@ -111,12 +111,12 @@ def list_available_translations (domain): pass return rv -class LanguageComboBox (gtk.ComboBox): +class LanguageComboBox (Gtk.ComboBox): def __init__ (self, domain): - liststore = gtk.ListStore(gobject.TYPE_STRING) - gtk.ComboBox.__init__(self, liststore) + liststore = Gtk.ListStore(GObject.TYPE_STRING) + Gtk.ComboBox.__init__(self, liststore) - self.cell = gtk.CellRendererText() + self.cell = Gtk.CellRendererText() self.pack_start(self.cell, True) self.add_attribute(self.cell, 'text', 0) @@ -156,8 +156,8 @@ def install (self, *args): ### def gather_other_translations (): from glob import glob - images = filter(lambda x: os.path.isdir(x), glob('images/*')) - images = map(lambda x: os.path.basename(x), images) + images = [x for x in glob('images/*') if os.path.isdir(x)] + images = [os.path.basename(x) for x in images] f = file('i18n_misc_strings.py', 'w') for e in images: f.write('_("%s")\n' % e) diff --git a/mmm_modules/image_category.py b/mmm_modules/image_category.py index 38e7cde..fb346f6 100644 --- a/mmm_modules/image_category.py +++ b/mmm_modules/image_category.py @@ -18,20 +18,19 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk, gobject + +from gi.repository import Gtk, GObject import os from glob import glob import logging -import md5 +from hashlib import md5 -from sugar import mime -from sugar.graphics.objectchooser import ObjectChooser +from sugar3 import mime +from sugar3.graphics.objectchooser import ObjectChooser -from borderframe import BorderFrame -from utils import load_image, resize_image, RESIZE_CUT +from .borderframe import BorderFrame +from .utils import load_image, resize_image, RESIZE_CUT cwd = os.path.normpath(os.path.join(os.path.split(__file__)[0], '..')) @@ -148,7 +147,7 @@ def _get_category_thumb (self): thumbs.extend(glob(os.path.join(self.path, "default_thumb.*"))) thumbs.extend(glob(os.path.join(mmmpath, "mmm_images","default_thumb.*"))) logging.debug(thumbs) - thumbs = filter(lambda x: os.path.exists(x), thumbs) + thumbs = [x for x in thumbs if os.path.exists(x)] thumbs.append(None) else: thumbs = [self.path] @@ -156,9 +155,9 @@ def _get_category_thumb (self): return load_image(thumbs[0], self.twidth, self.theight) -class ImageSelectorWidget (gtk.Table): - __gsignals__ = {'category_press' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'image_press' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),} +class ImageSelectorWidget (Gtk.Table): + __gsignals__ = {'category_press' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()), + 'image_press' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()),} def __init__ (self, width=IMAGE_SIZE, @@ -168,12 +167,12 @@ def __init__ (self, method=RESIZE_CUT, image_dir=None, parent=None): - gtk.Table.__init__(self, 2,5,False) + Gtk.Table.__init__(self, 2,5,False) self._parent = parent self._signals = [] self.width = width self.height = height - self.image = gtk.Image() + self.image = Gtk.Image() self.method = method #self.set_myownpath(MYOWNPIC_FOLDER) img_box = BorderFrame(border_color=frame_color) @@ -181,30 +180,30 @@ def __init__ (self, img_box.set_border_width(5) self._signals.append((img_box, img_box.connect('button_press_event', self.emit_image_pressed))) self.attach(img_box, 0,5,0,1,0,0) - self.attach(gtk.Label(), 0,1,1,2) - self.bl = gtk.Button() + self.attach(Gtk.Label(), 0,1,1,2) + self.bl = Gtk.Button() - il = gtk.Image() + il = Gtk.Image() il.set_from_pixbuf(load_image(os.path.join(iconpath, 'arrow_left.png'))) self.bl.set_image(il) self.bl.connect('clicked', self.previous) self.attach(prepare_btn_cb(self.bl), 1,2,1,2,0,0) - cteb = gtk.EventBox() - self.cat_thumb = gtk.Image() + cteb = Gtk.EventBox() + self.cat_thumb = Gtk.Image() self.cat_thumb.set_size_request(THUMB_SIZE, THUMB_SIZE) cteb.add(self.cat_thumb) self._signals.append((cteb, cteb.connect('button_press_event', self.emit_cat_pressed))) self.attach(cteb, 2,3,1,2,0,0,xpadding=10) - self.br = gtk.Button() - ir = gtk.Image() + self.br = Gtk.Button() + ir = Gtk.Image() ir.set_from_pixbuf(load_image(os.path.join(iconpath,'arrow_right.png'))) self.br.set_image(ir) - self.br.connect('clicked', self.next) + self.br.connect('clicked', self.__next__) self.attach(prepare_btn_cb(self.br), 3,4,1,2,0,0) - self.attach(gtk.Label(),4,5,1,2) + self.attach(Gtk.Label(),4,5,1,2) self.filename = None self.show_all() self.image.set_size_request(width, height) @@ -217,21 +216,21 @@ def add_image (self, *args):#widget=None, response=None, *args): if hasattr(mime, 'GENERIC_TYPE_IMAGE'): chooser = ObjectChooser(_('Choose image'), self._parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + Gtk.DIALOG_MODAL | Gtk.DIALOG_DESTROY_WITH_PARENT, what_filter=mime.GENERIC_TYPE_IMAGE) else: chooser = ObjectChooser(_('Choose image'), self._parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + Gtk.DIALOG_MODAL | Gtk.DIALOG_DESTROY_WITH_PARENT) try: result = chooser.run() - if result == gtk.RESPONSE_ACCEPT: + if result == Gtk.RESPONSE_ACCEPT: jobject = chooser.get_selected_object() if jobject and jobject.file_path: if self.load_image(str(jobject.file_path), True): pass else: - err = gtk.MessageDialog(self._parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, + err = Gtk.MessageDialog(self._parent, Gtk.DIALOG_MODAL, Gtk.MESSAGE_ERROR, Gtk.BUTTONS_OK, _("Not a valid image file")) err.run() err.destroy() @@ -244,12 +243,12 @@ def add_image (self, *args):#widget=None, response=None, *args): #print (widget,response,args) #if response is None: # # My Own Image selector - # imgfilter = gtk.FileFilter() + # imgfilter = Gtk.FileFilter() # imgfilter.set_name(_("Image Files")) # imgfilter.add_mime_type('image/*') - # fd = gtk.FileChooserDialog(title=_("Select Image File"), parent=None, - # action=gtk.FILE_CHOOSER_ACTION_OPEN, - # buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) + # fd = Gtk.FileChooserDialog(title=_("Select Image File"), parent=None, + # action=Gtk.FILE_CHOOSER_ACTION_OPEN, + # buttons=(Gtk.STOCK_CANCEL, Gtk.RESPONSE_REJECT,Gtk.STOCK_OK, Gtk.RESPONSE_ACCEPT)) # # fd.set_current_folder(os.path.expanduser("~/")) # fd.set_modal(True) @@ -258,12 +257,12 @@ def add_image (self, *args):#widget=None, response=None, *args): # fd.resize(800,600) # fd.show() #else: - # if response == gtk.RESPONSE_ACCEPT: + # if response == Gtk.RESPONSE_ACCEPT: # if self.load_image(widget.get_filename()): # pass # #self.do_shuffle() # else: - # err = gtk.MessageDialog(self._parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, + # err = Gtk.MessageDialog(self._parent, Gtk.DIALOG_MODAL, Gtk.MESSAGE_ERROR, Gtk.BUTTONS_OK, # _("Not a valid image file")) # err.run() # err.destroy() @@ -330,7 +329,7 @@ def get_filename (self): def get_image (self): return self.category.pb - def next (self, *args, **kwargs): + def __next__ (self, *args, **kwargs): pb = self.category.get_next_image() if pb is not None: self.image.set_from_pixbuf(pb) @@ -357,7 +356,7 @@ def set_image_dir (self, directory): self.image.set_from_pixbuf(self.category.get_image(filename)) else: if self.category.has_images(): - self.next() + next(self) def load_image(self, filename, fromJournal=False): """ Loads an image from the file """ @@ -374,7 +373,7 @@ def load_image(self, filename, fromJournal=False): # self.image.set_from_pixbuf(self.category.get_image(filename)) #else: self.category = CategoryDirectory(filename, self.width, self.height, method=self.method) - self.next() + next(self) self.cat_thumb.set_from_pixbuf(self.category.thumb) return self.image.get_pixbuf() is not None @@ -396,12 +395,12 @@ def _thaw (self, obj): self.set_image_dir(obj.get('image_dir', None)) self.image.set_from_pixbuf(self.category.get_image(obj.get('filename', None))) -class CategorySelector (gtk.ScrolledWindow): - __gsignals__ = {'selected' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,))} +class CategorySelector (Gtk.ScrolledWindow): + __gsignals__ = {'selected' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (str,))} def __init__ (self, title=None, selected_category_path=None, path=None, extra=()): - gtk.ScrolledWindow.__init__ (self) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + Gtk.ScrolledWindow.__init__ (self) + self.set_policy(Gtk.POLICY_AUTOMATIC, Gtk.POLICY_AUTOMATIC) if path is None: path = os.path.join(mmmpath, 'mmm_images') self.path = path @@ -409,10 +408,10 @@ def __init__ (self, title=None, selected_category_path=None, path=None, extra=() model, selected = self.get_model(path, selected_category_path, extra) self.ignore_first = selected is not None - self.treeview = gtk.TreeView() - col = gtk.TreeViewColumn(title) - r1 = gtk.CellRendererPixbuf() - r2 = gtk.CellRendererText() + self.treeview = Gtk.TreeView() + col = Gtk.TreeViewColumn(title) + r1 = Gtk.CellRendererPixbuf() + r2 = Gtk.CellRendererText() col.pack_start(r1, False) col.pack_start(r2, True) col.set_cell_data_func(r1, self.cell_pb) @@ -436,15 +435,15 @@ def cell_pb (self, tvcolumn, cell, model, it): def get_pb (self, path): thumbs = glob(os.path.join(path, "thumb.*")) thumbs.extend(glob(os.path.join(self.path, "default_thumb.*"))) - thumbs = filter(lambda x: os.path.exists(x), thumbs) + thumbs = [x for x in thumbs if os.path.exists(x)] thumbs.append(None) return load_image(thumbs[0], THUMB_SIZE, THUMB_SIZE) def get_model (self, path, selected_path, extra): # Each row is (path/dirname, pretty name, 0 based index) selected = None - store = gtk.ListStore(str, str, int) - store.set_sort_column_id(1, gtk.SORT_ASCENDING) + store = Gtk.ListStore(str, str, int) + store.set_sort_column_id(1, Gtk.SORT_ASCENDING) files = [os.path.join(path, x) for x in os.listdir(path) if not x.startswith('.')] files.extend(extra) for fullpath, prettyname in [(x, _(os.path.basename(x))) for x in files if os.path.isdir(x)]: diff --git a/mmm_modules/json.py b/mmm_modules/json.py index a28a13e..29f123e 100644 --- a/mmm_modules/json.py +++ b/mmm_modules/json.py @@ -30,7 +30,7 @@ def peek(self): return self.string[i] else: return None - def next(self): + def __next__(self): self.index += 1 if self.index < len(self.string): return self.string[self.index] @@ -58,7 +58,7 @@ def _read(self): self._eatWhitespace() peek = self._peek() if peek is None: - raise ReadException, "Nothing to read: '%s'" % self._generator.all() + raise ReadException("Nothing to read: '%s'" % self._generator.all()) if peek == '{': return self._readObject() elif peek == '[': @@ -77,7 +77,7 @@ def _read(self): self._readComment() return self._read() else: - raise ReadException, "Input is not valid JSON: '%s'" % self._generator.all() + raise ReadException("Input is not valid JSON: '%s'" % self._generator.all()) def _readTrue(self): self._assertNext('t', "true") @@ -103,7 +103,7 @@ def _readNull(self): def _assertNext(self, ch, target): if self._next() != ch: - raise ReadException, "Trying to read %s: '%s'" % (target, self._generator.all()) + raise ReadException("Trying to read %s: '%s'" % (target, self._generator.all())) def _readNumber(self): isfloat = False @@ -119,7 +119,7 @@ def _readNumber(self): else: return int(result) except ValueError: - raise ReadException, "Not a valid JSON number: '%s'" % result + raise ReadException("Not a valid JSON number: '%s'" % result) def _readString(self): result = "" @@ -132,20 +132,20 @@ def _readString(self): if ch in 'brnft': ch = self.escapes[ch] elif ch == "u": - ch4096 = self._next() - ch256 = self._next() - ch16 = self._next() - ch1 = self._next() - n = 4096 * self._hexDigitToInt(ch4096) - n += 256 * self._hexDigitToInt(ch256) - n += 16 * self._hexDigitToInt(ch16) - n += self._hexDigitToInt(ch1) - ch = unichr(n) + ch4096 = self._next() + ch256 = self._next() + ch16 = self._next() + ch1 = self._next() + n = 4096 * self._hexDigitToInt(ch4096) + n += 256 * self._hexDigitToInt(ch256) + n += 16 * self._hexDigitToInt(ch16) + n += self._hexDigitToInt(ch1) + ch = chr(n) elif ch not in '"/\\': - raise ReadException, "Not a valid escaped JSON character: '%s' in %s" % (ch, self._generator.all()) + raise ReadException("Not a valid escaped JSON character: '%s' in %s" % (ch, self._generator.all())) result = result + ch except StopIteration: - raise ReadException, "Not a valid JSON string: '%s'" % self._generator.all() + raise ReadException("Not a valid JSON string: '%s'" % self._generator.all()) assert self._next() == '"' return result @@ -155,8 +155,8 @@ def _hexDigitToInt(self, ch): except KeyError: try: result = int(ch) - except ValueError: - raise ReadException, "The character %s is not a hex digit." % ch + except ValueError: + raise ReadException("The character %s is not a hex digit." % ch) return result def _readComment(self): @@ -167,7 +167,7 @@ def _readComment(self): elif second == '*': self._readCStyleComment() else: - raise ReadException, "Not a valid JSON comment: %s" % self._generator.all() + raise ReadException("Not a valid JSON comment: %s" % self._generator.all()) def _readCStyleComment(self): try: @@ -176,10 +176,10 @@ def _readCStyleComment(self): ch = self._next() done = (ch == "*" and self._peek() == "/") if not done and ch == "/" and self._peek() == "*": - raise ReadException, "Not a valid JSON comment: %s, '/*' cannot be embedded in the comment." % self._generator.all() + raise ReadException("Not a valid JSON comment: %s, '/*' cannot be embedded in the comment." % self._generator.all()) self._next() except StopIteration: - raise ReadException, "Not a valid JSON comment: %s, expected */" % self._generator.all() + raise ReadException("Not a valid JSON comment: %s, expected */" % self._generator.all()) def _readDoubleSolidusComment(self): try: @@ -201,7 +201,7 @@ def _readArray(self): if not done: ch = self._next() if ch != ",": - raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch) + raise ReadException("Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch)) assert ']' == self._next() return result @@ -211,12 +211,12 @@ def _readObject(self): done = self._peek() == '}' while not done: key = self._read() - if type(key) is not types.StringType: - raise ReadException, "Not a valid JSON object key (should be a string): %s" % key + if type(key) is not bytes: + raise ReadException("Not a valid JSON object key (should be a string): %s" % key) self._eatWhitespace() ch = self._next() if ch != ":": - raise ReadException, "Not a valid JSON object: '%s' due to: '%s'" % (self._generator.all(), ch) + raise ReadException("Not a valid JSON object: '%s' due to: '%s'" % (self._generator.all(), ch)) self._eatWhitespace() val = self._read() result[key] = val @@ -225,8 +225,8 @@ def _readObject(self): if not done: ch = self._next() if ch != ",": - raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch) - assert self._next() == "}" + raise ReadException("Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch)) + assert self._next() == "}" return result def _eatWhitespace(self): @@ -242,7 +242,7 @@ def _peek(self): return self._generator.peek() def _next(self): - return self._generator.next() + return next(self._generator) class JsonWriter(object): @@ -257,10 +257,10 @@ def write(self, obj, escaped_forward_slash=False): def _write(self, obj): ty = type(obj) - if ty is types.DictType: + if ty is dict: n = len(obj) self._append("{") - for k, v in obj.items(): + for k, v in list(obj.items()): self._write(k) self._append(":") self._write(v) @@ -268,7 +268,7 @@ def _write(self, obj): if n > 0: self._append(",") self._append("}") - elif ty is types.ListType or ty is types.TupleType: + elif ty is list or ty is tuple: n = len(obj) self._append("[") for item in obj: @@ -277,22 +277,22 @@ def _write(self, obj): if n > 0: self._append(",") self._append("]") - elif ty is types.StringType or ty is types.UnicodeType: + elif ty is bytes or ty is str: self._append('"') - obj = obj.replace('\\', r'\\') + obj = obj.replace('\\', r'\\') if self._escaped_forward_slash: obj = obj.replace('/', r'\/') - obj = obj.replace('"', r'\"') - obj = obj.replace('\b', r'\b') - obj = obj.replace('\f', r'\f') - obj = obj.replace('\n', r'\n') - obj = obj.replace('\r', r'\r') - obj = obj.replace('\t', r'\t') + obj = obj.replace('"', r'\"') + obj = obj.replace('\b', r'\b') + obj = obj.replace('\f', r'\f') + obj = obj.replace('\n', r'\n') + obj = obj.replace('\r', r'\r') + obj = obj.replace('\t', r'\t') self._append(obj) self._append('"') - elif ty is types.IntType or ty is types.LongType: + elif ty is int or ty is int: self._append(str(obj)) - elif ty is types.FloatType: + elif ty is float: self._append("%f" % obj) elif obj is True: self._append("true") @@ -301,7 +301,7 @@ def _write(self, obj): elif obj is None: self._append("null") else: - raise WriteException, "Cannot write in JSON: %s" % repr(obj) + raise WriteException("Cannot write in JSON: %s" % repr(obj)) def write(obj, escaped_forward_slash=False): return JsonWriter().write(obj, escaped_forward_slash) diff --git a/mmm_modules/timer.py b/mmm_modules/timer.py index 92390e0..ff3ccb0 100644 --- a/mmm_modules/timer.py +++ b/mmm_modules/timer.py @@ -18,9 +18,7 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk, gobject, pango +from gi.repository import Gtk, GObject, Pango, Gdk import os from time import time @@ -40,25 +38,25 @@ mmmpath = cwd iconpath = os.path.join(mmmpath, 'icons') -from utils import load_image +from .utils import load_image -class TimerWidget (gtk.HBox): - __gsignals__ = {'timer_toggle' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (bool,)),} +class TimerWidget (Gtk.HBox): + __gsignals__ = {'timer_toggle' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (bool,)),} def __init__ (self, bg_color="#DD4040", fg_color="#4444FF", lbl_color="#DD4040", can_stop=True): - gtk.HBox.__init__(self) - self.counter = gtk.EventBox() - self.counter.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bg_color)) + Gtk.HBox.__init__(self) + self.counter = Gtk.EventBox() + self.counter.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse(bg_color)) self.counter.set_size_request(120, -1) - hb = gtk.HBox() + hb = Gtk.HBox() self.counter.add(hb) - self.lbl_time = gtk.Label() - self.lbl_time.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(lbl_color)) + self.lbl_time = Gtk.Label() + self.lbl_time.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse(lbl_color)) self.pack_start(self.lbl_time, False) - self.time_label = gtk.Label("--:--") - self.time_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(fg_color)) + self.time_label = Gtk.Label("--:--") + self.time_label.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse(fg_color)) hb.pack_start(self.time_label, False, False, 5) self.prepare_icons() - self.icon = gtk.Image() + self.icon = Gtk.Image() self.icon.set_from_pixbuf(self.icons[1]) hb.pack_end(self.icon, False, False, 5) self.pack_start(self.counter, False) @@ -102,7 +100,7 @@ def start (self): self.start_time = time() - self.start_time self.do_tick() if self.timer_id is None: - self.timer_id = gobject.timeout_add(1000, self.do_tick) + self.timer_id = GObject.timeout_add(1000, self.do_tick) self.emit('timer_toggle', True) def stop (self, finished=False): @@ -110,7 +108,7 @@ def stop (self, finished=False): return self.icon.set_from_pixbuf(self.icons[1]) if self.timer_id is not None: - gobject.source_remove(self.timer_id) + GObject.source_remove(self.timer_id) self.timer_id = None self.start_time = time() - self.start_time if not finished: diff --git a/mmm_modules/tube_helper.py b/mmm_modules/tube_helper.py index 8436cfc..e3c7b10 100644 --- a/mmm_modules/tube_helper.py +++ b/mmm_modules/tube_helper.py @@ -17,11 +17,11 @@ # If you find this activity useful or end up using parts of it in one of your # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # - -import telepathy +# FIXME Port to Collabwrapper +from gi.repository import TelepathyGLib as telepathy #import telepathy.client -from sugar.presence.tubeconn import TubeConnection -from sugar.presence import presenceservice +from sugar3.presence.tubeconn import TubeConnection +from sugar3.presence import presenceservice #import dbus import logging logger = logging.getLogger('tube_helper') diff --git a/mmm_modules/utils.py b/mmm_modules/utils.py index 1db4fca..dc2cef6 100644 --- a/mmm_modules/utils.py +++ b/mmm_modules/utils.py @@ -18,9 +18,7 @@ # own creations we would love to hear from you at info@WorldWideWorkshop.org ! # -import pygtk -pygtk.require('2.0') -import gtk +from gi.repository import Gtk, Gdk, GdkPixbuf import logging RESIZE_STRETCH = 1 @@ -62,7 +60,7 @@ def calculate_relative_size (orig_width, orig_height, width, height): return out_w, out_h def load_image (filename, width=-1, height=-1, method=RESIZE_CUT): - """ load an image from filename, returning it's gtk.gdk.PixBuf(). + """ load an image from filename, returning it's Gdk.PixBuf(). If any or all of width and height are given, scale the loaded image to fit the given size(s). If both width and height and requested scaling can be achieved in two flavours, as defined by the method argument: @@ -92,7 +90,7 @@ def load_image (filename, width=-1, height=-1, method=RESIZE_CUT): # slider.prepare_stringed(2,2) # return slider # - img = gtk.Image() + img = Gtk.Image() try: img.set_from_file(filename) pb = img.get_pixbuf() @@ -106,7 +104,7 @@ def resize_image (pb, width=-1, height=-1, method=RESIZE_CUT): logging.debug("utils: method=%i" % method) if method == RESIZE_STRETCH or width == -1 or height == -1: w,h = calculate_relative_size(pb.get_width(), pb.get_height(), width, height) - scaled_pb = pb.scale_simple(w,h, gtk.gdk.INTERP_BILINEAR) + scaled_pb = pb.scale_simple(w,h, GdkPixbuf.InterpType.BILINEAR) elif method == RESIZE_PAD: w,h = pb.get_width(), pb.get_height() hr = float(height)/h @@ -115,7 +113,7 @@ def resize_image (pb, width=-1, height=-1, method=RESIZE_CUT): w = w * factor h = h * factor logging.debug("RESIZE_PAD: %i,%i,%f" % (w,h,factor)) - scaled_pb = pb.scale_simple(int(w), int(h), gtk.gdk.INTERP_BILINEAR) + scaled_pb = pb.scale_simple(int(w), int(h), GdkPixbuf.InterpType.BILINEAR) else: # RESIZE_CUT / default w,h = pb.get_width(), pb.get_height() if width > w: @@ -151,16 +149,16 @@ def resize_image (pb, width=-1, height=-1, method=RESIZE_CUT): # w, h now have -1 for the side that should be relatively scaled, to keep the aspect ratio and # assuring that the image is at least as big as the request. w,h = calculate_relative_size(pb.get_width(), pb.get_height(), w,h) - scaled_pb = pb.scale_simple(w,h, gtk.gdk.INTERP_BILINEAR) + scaled_pb = pb.scale_simple(w,h, GdkPixbuf.InterpType.BILINEAR) # now we cut whatever is left to make the requested size - scaled_pb = scaled_pb.subpixbuf(abs((width-w)/2),abs((height-h)/2), width, height) + scaled_pb = scaled_pb.new_subpixbuf(abs((width-w)/2),abs((height-h)/2), width, height) return scaled_pb ### Helper decorators def trace (func): def wrapped (*args, **kwargs): - logging.debug("TRACE %s %s %s" % (func.func_name, args, kwargs)) + logging.debug("TRACE %s %s %s" % (func.__name__, args, kwargs)) return func(*args, **kwargs) return wrapped diff --git a/setup.py b/setup.py index 1a961a4..c2ed0b7 100755 --- a/setup.py +++ b/setup.py @@ -16,5 +16,5 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from sugar.activity import bundlebuilder +from sugar3.activity import bundlebuilder bundlebuilder.start()