def build_toolbar(self): toolbar_box = ToolbarBox() view_toolbar = ViewToolbar() view_toolbar.connect('go-fullscreen', self.view_toolbar_go_fullscreen_cb) view_toolbar.show() view_toolbar_button = ToolbarButton( page=view_toolbar, icon_name='toolbar-view') toolbar_box.toolbar.insert(view_toolbar_button, -1) view_toolbar_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) stop_button.props.accelerator = '<Ctrl><Shift>Q' toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show()
def add_view(self, widget): if len(self._view_icons) >= 5: for x in self.activity._alerts: self.activity.remove_alert(x) alert = NotifyAlert(10) alert.props.title = _('Limit reached') alert.props.msg = _('You have reached the maximum limit of ' 'favorites views, please delete some before ' 'continuing.') self.activity.add_alert(alert) alert.connect('response', lambda x, y: self.activity.remove_alert(x)) return current = len(self._view_buttons) + 1 label = _('Favorites view %d') % current button = ToolbarButton(label=label, icon_name='view-radial') page = FavoritePage(button, self, 'view-radial', 'emblem-favorite', label) button.set_page(page) self._view_icons[button] = 'view-radial' self._favorite_icons[button] = 'emblem-favorite' self._view_buttons[button] = button if self.favorite_names_enabled: self._favorite_names[button] = label self.insert(button, -1) self.save_to_gconf() self.show_all()
def __init__(self, activity, **kwargs): toolbar = ActivityToolbar(activity, orientation_left=True) ToolbarButton.__init__(self, page=toolbar, **kwargs) icon = _create_activity_icon(activity.metadata) self.set_icon_widget(icon) icon.show()
def createPercussionToolbar(self, toolbar_box): self.beats_pm_button = IntensitySelector(range(2, 13), 4, imagefile('beat3.svg')) self.tempo_button = \ IntensitySelector(range(PLAYER_TEMPO_LOWER, PLAYER_TEMPO_UPPER + 1, PLAYER_TEMPO_STEP), PLAYER_TEMPO, imagefile('tempo5.png')) self.complexity_button = IntensitySelector(xfrange(0, 1, 0.1), self.regularity, imagefile('complex6.svg')) self._play_percussion_btn = ToolButton( icon_name='media-playback-start') self._play_percussion_btn.set_property('can-default', True) self._play_percussion_btn.show() self._play_percussion_btn.connect('clicked', self.handlePlayButton) beats_toolbar = ToolbarBox() beats_toolbar.toolbar.insert(self._play_percussion_btn, -1) self._what_drum_widget = Gtk.ToolItem() self._what_drum_search_button = FilterToolItem( _('Select Drum'), 'view-type', _('Jazz / Rock Kit'), self._what_drum_widget) self._what_drum_search_button.set_widget_icon( file_name=imagefile("drum1kit.svg")) self._what_drum_widget.show() beats_toolbar.toolbar.insert(self._what_drum_search_button, -1) self._what_drum_search_button.show() self._what_drum_search_button.set_is_important(True) beats_toolbar.toolbar.insert(Gtk.SeparatorToolItem(), -1) beats_toolbar.toolbar.insert(self.complexity_button, -1) beats_toolbar.toolbar.insert(self.beats_pm_button, -1) beats_toolbar.toolbar.insert(self.tempo_button, -1) beats_toolbar_button = ToolbarButton(icon_name='toolbar-drums', page=beats_toolbar) beats_toolbar_button.show() toolbar_box.toolbar.insert(beats_toolbar_button, 1) self.beats_pm_button.set_tooltip(_("Beats per bar")) self.beats_pm_button.show() self.beats_pm_button.connect('changed', self.beatSliderChange, True) self.tempo_button.connect('changed', self.tempoSliderChange, True) self.complexity_button.connect('changed', self.handleComplexityChange, True) self.complexity_button.set_tooltip(_("Beat complexity")) self.tempo_button.show() self.tempo_button.set_tooltip(_('Tempo')) self.complexity_button.show()
def __init__(self, activity, **kwargs): toolbar = ActivityToolbar(activity, orientation_left=True) toolbar.connect('enter-key-press', lambda widget: self.emit('clicked')) ToolbarButton.__init__(self, page=toolbar, **kwargs) icon = _create_activity_icon(activity.metadata) self.set_icon_widget(icon) icon.show()
def make_toolbar(self): # toolbar with the new toolbar redesign toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() toolbarview = Gtk.Toolbar() langtoolbar_button = ToolbarButton( label=_('View'), page=toolbarview, icon_name='settings') langtoolbar_button.show() toolbar_box.toolbar.insert(langtoolbar_button, -1) tool = ToolButton('en') tool.set_tooltip(_('English')) tool.connect('clicked', self.language_en) tool.show() toolbarview.insert(tool, -1) tool = ToolButton('es') tool.set_tooltip(_('Spanish')) tool.connect('clicked', self.language_es) tool.show() toolbarview.insert(tool, -1) tool = ToolButton('fr') tool.set_tooltip(_('French')) tool.connect('clicked', self.language_fr) tool.show() toolbarview.insert(tool, -1) tool = ToolButton('remote') tool.set_tooltip(_('Server settings')) tool.connect('clicked', self.settings) tool.show() toolbarview.insert(tool, -1) toolbarview.show() favorite_button = ToolButton(self.favorite_status) favorite_button.set_tooltip('Filter on favorite') favorite_button.connect('clicked', self.favorite) toolbar_box.toolbar.insert(favorite_button, -1) favorite_button.show() self.favorite_button = favorite_button 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 build_today_toolbar(self, toolbox): today_bar = Gtk.Toolbar() item1 = Gtk.ToolItem() self.label_today = Gtk.Label() self.label_today.set_text(_('Today:') + ' ' + _('Day') + ' ') item1.add(self.label_today) today_bar.insert(item1, -1) item2 = Gtk.ToolItem() self.day_today_spin = Gtk.SpinButton() self.day_today_spin.set_range(1, 31) self.day_today_spin.set_increments(1, 5) self.day_today_spin.props.value = self._today[0] self.day_today_spin.connect('notify::value', self.day_today_change) item2.add(self.day_today_spin) today_bar.insert(item2, -1) item3 = Gtk.ToolItem() self.label_today_month = Gtk.Label() self.label_today_month.set_text(' ' + _('Month') + ' ') item3.add(self.label_today_month) today_bar.insert(item3, -1) item4 = Gtk.ToolItem() self.month_today_spin = Gtk.SpinButton() self.month_today_spin.set_range(1, 12) self.month_today_spin.set_increments(1, 4) self.month_today_spin.props.value = self._today[1] self.month_today_spin.connect('notify::value', self.month_today_change) item4.add(self.month_today_spin) today_bar.insert(item4, -1) item5 = Gtk.ToolItem() self.label_today_year = Gtk.Label() self.label_today_year.set_text(' ' + _('Year') + ' ') item5.add(self.label_today_year) today_bar.insert(item5, -1) item6 = Gtk.ToolItem() self.year_today_spin = Gtk.SpinButton() self.year_today_spin.set_range(1900, self._now.year + 1) self.year_today_spin.set_increments(1, 10) self.year_today_spin.props.value = self._today[2] self.year_today_spin.connect('notify::value', self.year_today_change) item6.add(self.year_today_spin) today_bar.insert(item6, -1) today_bar.show_all() today_button = ToolbarButton(label=_('Today'), page=today_bar, icon_name='write-time') toolbox.toolbar.insert(today_button, -1) today_button.show()
def __init__(self, activity, shared=False, **kwargs): toolbar = ActivityToolbar(activity, orientation_left=True) if not shared: toolbar.share.props.visible = False ToolbarButton.__init__(self, page=toolbar, **kwargs) icon = _create_activity_icon(activity.metadata) self.set_icon_widget(icon) icon.show()
def make_toolbar(self): # toolbar with the new toolbar redesign toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() self.toolbarview = Gtk.Toolbar() langtoolbar_button = ToolbarButton( label=_('Filter'), page=self.toolbarview, icon_name='filter') langtoolbar_button.show() toolbar_box.toolbar.insert(langtoolbar_button, -1) self.toolbarview.show() box_search_item = Gtk.ToolItem() self.search_entry = Gtk.Entry() self.search_entry.connect('changed', self.text_filter) self.search_entry.set_size_request(300, -1) box_search_item.add(self.search_entry) self.search_entry.show() box_search_item.show() toolbar_box.toolbar.insert(box_search_item, -1) favorite_button = ToolButton(self.favorite_status) favorite_button.set_tooltip('Filter on favorite') favorite_button.connect('clicked', self.favorite) toolbar_box.toolbar.insert(favorite_button, -1) favorite_button.show() self.favorite_button = favorite_button library_button = ToolButton('library') library_button.set_tooltip('Show libraries') library_button.connect('clicked', self.library_clicked) toolbar_box.toolbar.insert(library_button, -1) library_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 _setup_toolbars(self): ''' Setup the toolbars.. ''' tools_toolbar = Gtk.Toolbar() numbers_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() self.activity_toolbar_button = ActivityToolbarButton(self) toolbox.toolbar.insert(self.activity_toolbar_button, 0) self.activity_toolbar_button.show() self.numbers_toolbar_button = ToolbarButton( page=numbers_toolbar, icon_name='number-tools') if MODE == 'number': numbers_toolbar.show() toolbox.toolbar.insert(self.numbers_toolbar_button, -1) self.numbers_toolbar_button.show() self.tools_toolbar_button = ToolbarButton( page=tools_toolbar, icon_name='view-source') self.button_pattern = button_factory( 'new-pattern-game', toolbox.toolbar, self._select_game_cb, cb_arg='pattern', tooltip=_('New game')) self._set_extras(toolbox.toolbar) self._sep.append(separator_factory(toolbox.toolbar, True, False)) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() button_factory('score-copy', self.activity_toolbar_button, self._write_scores_to_clipboard, tooltip=_('Export scores to clipboard')) self.set_toolbar_box(toolbox) toolbox.show() if MODE == 'word': self.words_tool_button = button_factory( 'word-tools', tools_toolbar, self._edit_words_cb, tooltip=_('Edit word lists.')) self.import_button = button_factory( 'image-tools', tools_toolbar, self.image_import_cb, tooltip=_('Import custom cards')) self.button_custom = button_factory( 'new-custom-game', tools_toolbar, self._select_game_cb, cb_arg='custom', tooltip=_('New custom game')) self.button_custom.set_sensitive(False) if MODE == 'number': self._setup_number_buttons(numbers_toolbar)
def _setup_toolbars(self): custom_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() self._toolbar = toolbox.toolbar self._activity_button = ActivityToolbarButton(self) self._activity_button.connect('clicked', self._update_graphics) self._toolbar.insert(self._activity_button, 0) self._activity_button.show() self._custom_toolbar_button = ToolbarButton( label=_('Custom'), page=custom_toolbar, icon_name='view-source') self._custom_toolbar_button.connect('clicked', self._update_graphics) custom_toolbar.show() self._toolbar.insert(self._custom_toolbar_button, -1) self._custom_toolbar_button.show() self._load_standard_buttons(self._toolbar) self._separator = Gtk.SeparatorToolItem() self._separator.props.draw = False self._separator.set_expand(True) self._toolbar.insert(self._separator, -1) self._separator.show() stop_button = StopButton(self) stop_button.props.accelerator = _('<Ctrl>Q') self._toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbox) toolbox.show() self._load_custom_buttons(custom_toolbar)
def __init__(self, handle): if not hasattr(self, 'confvars'): self.confvars = read_conf_from_info(get_bundle_path()) logging.error("Starting server database: %s port: %s" % (self.confvars['path'], self.confvars['port'])) os.chdir(os.environ['SUGAR_BUNDLE_PATH']) self.confvars['ip'] = '0.0.0.0' server.run_server(self.confvars) handle.uri = 'http://%s:%s%s' % ( self.confvars['ip'], self.confvars['port'], self.confvars['home_page']) webactivity.WebActivity.__init__(self, handle) if USE_GTK2: # Use xpcom to set a RAM cache limit. (Trac #7081.) from xpcom import components from xpcom.components import interfaces cls = components.classes['@mozilla.org/preferences-service;1'] pref_service = cls.getService(interfaces.nsIPrefService) branch = pref_service.getBranch("browser.cache.memory.") branch.setIntPref("capacity", "5000") # Use xpcom to turn off "offline mode" detection, which disables # access to localhost for no good reason. (Trac #6250.) ios_class = components.classes["@mozilla.org/network/io-service;1"] io_service = ios_class.getService(interfaces.nsIIOService2) io_service.manageOfflineStatus = False self.searchtoolbar = SearchToolbar(self) search_toolbar_button = ToolbarButton() search_toolbar_button.set_page(self.searchtoolbar) search_toolbar_button.props.icon_name = 'search-wiki' search_toolbar_button.props.label = _('Search') self.get_toolbar_box().toolbar.insert(search_toolbar_button, 1) search_toolbar_button.show() # Hide add-tabs button if hasattr(self._primary_toolbar, '_add_tab'): self._primary_toolbar._add_tab.hide() self.searchtoolbar.show()
def _set_toolbar(self): separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) stop = StopButton(self) # Buttons # self._photo = RadioToolButton() self._photo.props.icon_name = 'media-photo' self._photo.props.label = _('Photo') self._video = RadioToolButton() self._video.props.group = self._photo self._video.props.icon_name = 'media-video' self._video.props.label = _('Video') self._audio = RadioToolButton() self._audio.props.group = self._photo self._audio.props.icon_name = 'media-audio' self._audio.props.label = _('Audio') # End of Buttons # self._timer = TimerCombo() self._timer_2 = DurationCombo() #self._timer_2.combo.set_sensitive(False) self._preferencias = ToolbarButton() toolbar = Gtk.Toolbar() combo = QualityCombo() #combo.set_sensitive(False) self.calidad = ToolComboBox(combo=combo, label_text=_('Quality:')) self.calidad.show_all() toolbar.insert(self.calidad, -1) toolbar.show_all() self._preferencias.set_page(toolbar) self._preferencias.props.icon_name = 'preferences-system' self._preferencias.props.label = _('Preferences') self.toolbar.insert(self.activitybutton, -1) self.toolbar.insert(self._photo, -1) self.toolbar.insert(self._video, -1) self.toolbar.insert(self._audio, -1) self.toolbar.insert(Gtk.SeparatorToolItem(), -1) self.toolbar.insert(self._timer, -1) self.toolbar.insert(self._timer_2, -1) self.toolbar.insert(self._preferencias, -1) self.toolbar.insert(separator, -1) self.toolbar.insert(stop, -1) self.set_toolbar_box(self.toolbox)
def add_page(self, ebook_reader_tab_instance): # Add the "content" for the section. tab_name = ebook_reader_tab_instance.get_tab_label() tab_widget = ebook_reader_tab_instance.get_widget_to_attach_notebook_tab() tab_toolbar = ebook_reader_tab_instance.get_tab_toolbar() if tab_toolbar is not None: tab_widget.pack_start(tab_toolbar, False, False, 0) tab_widget.reorder_child(tab_toolbar, 0) self._tab_toolbars_list.append(tab_toolbar) self.notebook.add_page(tab_name, tab_widget) # Add the "(secondary) toolbar" for the section. icon_name = \ ebook_reader_tab_instance.get_tab_toolbar_icon_name() toolbar_button = ToolbarButton(page=None, icon_name=icon_name + '-select') self._toolbar_buttons_list.append(toolbar_button) toolbar_button.connect('clicked', self.load_corresponding_page, ebook_reader_tab_instance.get_pagenum()) ebook_reader_tab_instance.show() toolbar_button.set_tooltip(tab_name) self._toolbar_box._toolbar.insert(toolbar_button, -1) toolbar_button.show() self._toolbar_box.show_all()
def build_size_toolbar(self, toolbox): size_bar = Gtk.Toolbar() #Horizontal item1 = Gtk.ToolItem() label1 = Gtk.Label() label1.set_text(' %s ' % _('H')) item1.add(label1) size_bar.insert(item1, -1) item2 = Gtk.ToolItem() self.h_spin = Gtk.SpinButton() self.h_spin.set_range(2, 30) self.h_spin.set_increments(1, 2) self.h_spin.props.value = self.game_size[0] self.h_spin.connect('notify::value', self.h_spin_change) item2.add(self.h_spin) size_bar.insert(item2, -1) #Vertical item3 = Gtk.ToolItem() label2 = Gtk.Label() label2.set_text(' %s ' % _('V')) item3.add(label2) size_bar.insert(item3, -1) item4 = Gtk.ToolItem() self.v_spin = Gtk.SpinButton() self.v_spin.set_range(2, 20) self.v_spin.set_increments(1, 2) self.v_spin.props.value = self.game_size[1] self.v_spin.connect('notify::value', self.v_spin_change) item4.add(self.v_spin) size_bar.insert(item4, -1) size_bar.show_all() size_button = ToolbarButton(label=_('Board size'), page=size_bar, icon_name='preferences-system') toolbox.toolbar.insert(size_button, -1) size_button.show()
def load_views(self): client = GConf.Client.get_default() options = client.get(_FAVORITE_KEY) options2 = client.get(_VIEW_KEY) options3 = client.get(_FAVORITE_NAME_KEY) view_icons = [] favorites_icons = [] favorite_names = [] if options is not None and options2 is not None and \ options3 is not None: for gval in options.get_list(): favorites_icons.append(gval.get_string()) for gval in options2.get_list(): view_icons.append(gval.get_string()) for gval in options3.get_list(): favorite_names.append(gval.get_string()) current = 0 for view_icon in view_icons: if self.favorite_names_enabled: try: label = favorite_names[current] except IndexError: label = _('Favorites view %d') % (current + 1) else: label = _('Favorites view %d') % (current + 1) button = ToolbarButton(label=label, icon_name=view_icon) page = FavoritePage(button, self, view_icon, favorites_icons[current], label) button.set_page(page) self.insert(button, -1) self._view_icons[button] = view_icon self._favorite_icons[button] = favorites_icons[current] self._view_buttons[button] = button self._favorite_names[button] = label current += 1
def load_views(self): settings = Gio.Settings(_DESKTOP_CONF_DIR) data = settings.get_value('homeviews').unpack() current = 0 for view in data: label = _('Favorites view %d') % (current + 1) print view, data view_icon = view['view-icon'] favorite_icon = view['favorite-icon'] button = ToolbarButton(label=label, icon_name=view_icon) page = FavoritePage(button, self, view_icon, favorite_icon, label) button.set_page(page) self.insert(button, -1) self._view_icons[button] = view_icon self._favorite_icons[button] = favorite_icon self._view_buttons[button] = button self._favorite_names[button] = label current += 1
def setup_toolbar(self): '''Setup the top toolbar. Groupthink needs some work here.''' toolbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() self.set_toolbar_box(toolbox) toolbox.show() toolbar = toolbox.toolbar self.edit_toolbar = EditToolbar() edit_toolbar_button = ToolbarButton( page=self.edit_toolbar, icon_name='toolbar-edit') self.edit_toolbar.show() toolbar.insert(edit_toolbar_button, -1) edit_toolbar_button.show() self.edit_toolbar.undo.connect('clicked', self.undobutton_cb) self.edit_toolbar.redo.connect('clicked', self.redobutton_cb) self.edit_toolbar.copy.connect('clicked', self.copybutton_cb) self.edit_toolbar.paste.connect('clicked', self.pastebutton_cb) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show()
def __init__(self, cactivity): self._activity = cactivity self.is_active = False self.left = self._create_left_panel() self.right = self._create_right_panel() self.text_channel = None self.fixed = Gtk.Fixed() #self.button = BulletinButton() #self.button.connect("clicked", self._toggle) self.button = ToolbarButton() self.button.connect("clicked", self._toggle) self.button.props.icon_name = 'computer-xo' self.toolbar = BulletinToolbar() self.button.props.page = self.toolbar self.toolbar.toolitems.entry.connect('activate', self.entry_activate_cb) #self.share_button = ShareButton(self._activity) #self.share_button.private.props.active = False pserv = presenceservice.get_instance() self.owner = pserv.get_owner() # If any shared activity exists if self._activity.shared_activity: self._activity.connect('joined', self._joined_cb) # joining an activity if self._activity.get_shared(): # already joined the activity self._joined_cb(self._activity) else: if not self._activity.metadata or (self._activity.metadata.get('share-scope', activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE): self._alert(_('Off-line'), _('Share, or invite someone.')) self._activity.connect('shared', self._shared_cb)
def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = "media-playback-stop" self.stop_play_state = True self.stop_play = ToolButton("media-playback-stop") self.stop_play.set_tooltip(_("Stop")) self.stop_play.set_accelerator(_("<ctrl>space")) self.stop_play.connect("clicked", self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name("slow-walk-milton-raposo") slowest_button.set_tooltip(_("Run slower")) slowest_button.connect("clicked", self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name("walking") slow_button.set_tooltip(_("Run slow")) slow_button.connect("clicked", self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name("running") fast_button.set_tooltip("Run fast") fast_button.connect("clicked", self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all()
def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = 'media-playback-stop' self.stop_play_state = True self.stop_play = ToolButton('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play.set_accelerator(_('<ctrl>space')) self.stop_play.connect('clicked', self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name('slow-walk-milton-raposo') slowest_button.set_tooltip(_('Run slower')) slowest_button.connect('clicked', self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name('walking') slow_button.set_tooltip(_('Run slow')) slow_button.connect('clicked', self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name('running') fast_button.set_tooltip('Run fast') fast_button.connect('clicked', self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all()
def __init__(self, handle): # Initialize the parent Activity.__init__(self, handle) logger.debug('Initiating PlayGo') self.size = DEFAULT_SIZE self.komi = DEFAULT_KOMI # Set the activity toolbarbox toolbarbox = ToolbarBox() self.set_toolbar_box(toolbarbox) toolbarbox.toolbar.insert(ActivityToolbarButton(self), -1) toolbarbox.toolbar.insert(Gtk.SeparatorToolItem(), -1) self.gameToolbar = GameToolbar(self) self.gameToolbar.connect('game-restart', self.restart_game) self.gameToolbar.connect('game-board-size', self.board_size_change) self.gameToolbar.connect('ai-activated', self.ai_activated_cb) self.gameToolbar.connect('ai-deactivated', self.ai_deactivated_cb) toolbarbox.toolbar.insert(ToolbarButton(page=self.gameToolbar, icon_name='txt'), -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbarbox.toolbar.insert(separator, -1) toolbarbox.toolbar.insert(StopButton(self), -1) toolbarbox.show_all() toolbarbox.toolbar.show_all() self.gameToolbar.show_all() # Initialize the game self.game = GoGame(self.size) self.CurrentColor = 'B' self.PlayerColor = 'B' self.pass_count = 0 self.ai_activated = False self.set_up_ui() if not handle.object_id: self.infopanel.show(_('Welcome to PlayGo!')) else: self.show_score() self.lastX = -1 self.lastY = -1 # Set keypad actions self._key_actions = { 'KP_Up' : 'move_up', 'KP_Right' : 'move_right', 'KP_Down' : 'move_down', 'KP_Left' : 'move_left', 'KP_Home' : 'place_stone', 'KP_Next' : 'undo', 'KP_End' : 'pass' } ##self._key_grabber = KeyGrabber() ##self._key_grabber.connect('key-pressed', ## self._key_pressed_cb) # New KeyGrabber API change (ticket #7999) ##try: ## self._key_grabber.grab_keys(self._key_actions.keys()) ##except: ## for key in self._key_actions.keys(): ## self._key_grabber.grab(key) #Set up collaboration self.collaboration = CollaborationWrapper(self, self.buddy_joined, self.buddy_left, self.Play, self.game.undostack, self.bootstrap) self.connect('shared', self.collaboration._shared_cb) if self.get_shared_activity(): # We are joining the activity self.connect('joined', self.collaboration._joined_cb) if self.get_shared(): # We've already joined self.collaboration._joined_cb()
def __init__(self, handle): activity.Activity.__init__(self, handle) self._book_model = BookModel() self._actual_page = 1 # we do not have collaboration features # make the share option insensitive self.max_participants = 1 # get the language configured by the user # will be used to translate the names of the media files locale = os.environ.get('LANG', '') language_location = locale.split('.', 1)[0].lower() self._language = language_location.split('_')[0] if self._language == 'en': # we don't need translate the file names if langauage is 'en' self._language = None self._translations = None if self._language is not None: # read the translations file if available dict_path = os.path.join(activity.get_bundle_path(), 'data', "%s_dict.csv" % self._language) logging.debug('Looking for media translation dictionary %s', dict_path) if os.path.exists(dict_path): logging.debug('Loading translations') self._translations = {} with open(dict_path) as dict_file: for line in dict_file: words = line.split(',') self._translations[words[0]] = words[1].strip() toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) self._edit_toolbar = EditToolbar() edit_toolbar_button = ToolbarButton(page=self._edit_toolbar, icon_name='toolbar-edit') toolbar_box.toolbar.insert(edit_toolbar_button, 1) set_background_button = ToolButton('set-background') set_background_button.set_tooltip(_('Set the background')) set_background_button.connect('clicked', self.__set_background_clicked_cb) toolbar_box.toolbar.insert(set_background_button, -1) insert_picture_button = ToolButton('insert-picture') insert_picture_button.set_tooltip(_('Add a picture')) insert_picture_button.connect('clicked', self.__add_image_clicked_cb) toolbar_box.toolbar.insert(insert_picture_button, -1) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) self._duplicate_page_button = ToolButton() icon = Icon(icon_name='edit-duplicate', xo_color=profile.get_color()) self._duplicate_page_button.set_icon_widget(icon) self._duplicate_page_button.set_tooltip(_('Duplicate page')) self._duplicate_page_button.connect('clicked', self.__duplicate_page_clicked_cb) toolbar_box.toolbar.insert(self._duplicate_page_button, -1) self._add_page_button = ToolButton('list-add') self._add_page_button.set_tooltip(_('Add a page')) self._add_page_button.connect('clicked', self.__add_page_clicked_cb) toolbar_box.toolbar.insert(self._add_page_button, -1) self._remove_button = ToolButton('edit-delete') self._remove_button.set_tooltip(_('Remove an image or page')) self._remove_button.connect('clicked', self.__remove_clicked_cb) toolbar_box.toolbar.insert(self._remove_button, -1) self._prev_page_button = ToolButton('go-previous-paired') self._prev_page_button.set_tooltip(_('Previous page')) self._prev_page_button.connect('clicked', self.__prev_page_clicked_cb) toolbar_box.toolbar.insert(self._prev_page_button, -1) self._next_page_button = ToolButton('go-next-paired') self._next_page_button.set_tooltip(_('Next page')) self._next_page_button.connect('clicked', self.__next_page_clicked_cb) toolbar_box.toolbar.insert(self._next_page_button, -1) self._view_list_button = ToggleToolButton('view-list') self._view_list_button.set_tooltip(_('View pages')) self._view_list_button.connect('toggled', self.__view_list_toggled_cb) toolbar_box.toolbar.insert(self._view_list_button, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) stop_button = StopButton(self) toolbar_box.toolbar.insert(stop_button, -1) # add export buttons activity_toolbar = activity_button.props.page epub_button = ToolButton('save-as-epub') epub_button.set_tooltip(_('Save as EPUB book')) epub_button.connect('clicked', self.__save_ebook_clicked_cb) activity_toolbar.insert(epub_button, -1) epub_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() edition_canvas = self.create_edition_canvas() hbox = Gtk.HBox() self._preview_panel = PreviewPanel(self._book_model.get_pages()) self._preview_panel.connect('page-activated', self.__page_activated_cb) self._preview_panel.connect('page-moved', self.__page_moved_cb) hbox.pack_start(self._preview_panel, False, False, 0) hbox.pack_start(edition_canvas, True, True, 0) self.set_canvas(hbox) self.prepare_edit_toolbar() self._update_page_buttons() self.show_all() self._preview_panel.hide()
class Dimensions(activity.Activity): ''' Dimension matching game ''' def __init__(self, handle): ''' Initialize the Sugar activity ''' super(Dimensions, self).__init__(handle) self.ready_to_play = False self._prompt = '' self._read_journal_data() self._sep = [] self._setup_toolbars() canvas = self._setup_canvas() self._setup_presence_service() if not hasattr(self, '_saved_state'): self._saved_state = None self.vmw.new_game(self._saved_state, self._deck_index) self.ready_to_play = True ''' if self._saved_state == None: # Launch animated help self.vmw.help_animation() ''' if self._editing_word_list: self.vmw.editing_word_list = True self.vmw.edit_word_list() elif self._editing_custom_cards: self.vmw.editing_custom_cards = True self.vmw.edit_custom_card() Gdk.Screen.get_default().connect('size-changed', self._configure_cb) self._configure_cb(None) def _select_game_cb(self, button, card_type): ''' Choose which game we are playing. ''' if self.vmw.joiner(): # joiner cannot change level return self.vmw.card_type = card_type self._prompt = PROMPT_DICT[card_type] self._load_new_game(card_type) def _load_new_game(self, card_type=None): if not self.ready_to_play: return self._notify_new_game(self._prompt) # a brief pause to give alert time to load timeout = GObject.timeout_add(200, self._new_game, card_type) def _new_game(self, card_type): if card_type == 'custom' and self.vmw.custom_paths[0] is None: self.image_import_cb() else: self.tools_toolbar_button.set_expanded(False) self.vmw.new_game() def _robot_cb(self, button=None): ''' Toggle robot assist on/off ''' if self.vmw.robot: self.vmw.robot = False self.robot_button.set_tooltip(_('Play with the computer.')) self.robot_button.set_icon_name('robot-off') elif not self.vmw.editing_word_list: self.vmw.robot = True self.robot_button.set_tooltip(_('Stop playing with the computer.')) self.robot_button.set_icon_name('robot-on') def _level_cb(self, button, level): ''' Cycle between levels ''' if self.vmw.joiner(): # joiner cannot change level return self.vmw.level = level # self.level_label.set_text(self.calc_level_label(self.vmw.low_score, # self.vmw.level)) self._load_new_game() def calc_level_label(self, low_score, play_level): ''' Show the score. ''' if low_score[play_level] == -1: return LEVEL_LABELS[play_level] else: return '%s (%d:%02d)' % \ (LEVEL_LABELS[play_level], int(low_score[play_level] / 60), int(low_score[play_level] % 60)) def image_import_cb(self, button=None): ''' Import custom cards from the Journal ''' self.vmw.editing_custom_cards = True self.vmw.editing_word_list = False self.vmw.edit_custom_card() if self.vmw.robot: self._robot_cb(button) def _number_card_O_cb(self, button, numberO): ''' Choose between O-card list for numbers game. ''' if self.vmw.joiner(): # joiner cannot change decks return self.vmw.numberO = numberO self.vmw.card_type = 'number' self._load_new_game() def _number_card_C_cb(self, button, numberC): ''' Choose between C-card list for numbers game. ''' if self.vmw.joiner(): # joiner cannot change decks return self.vmw.numberC = numberC self.vmw.card_type = 'number' self._load_new_game() def _edit_words_cb(self, button): ''' Edit the word list. ''' self.vmw.editing_word_list = True self.vmw.editing_custom_cards = False self.vmw.edit_word_list() if self.vmw.robot: self._robot_cb(button) def _read_metadata(self, keyword, default_value): ''' If the keyword is found, return stored value ''' if keyword in self.metadata: return (self.metadata[keyword]) else: return (default_value) def _read_journal_data(self): ''' There may be data from a previous instance. ''' self._play_level = int(self._read_metadata('play_level', 1)) self._robot_time = int(self._read_metadata('robot_time', 60)) self._card_type = self._read_metadata('cardtype', 'word') self._low_score = [ int(self._read_metadata('low_score_beginner', -1)), int(self._read_metadata('low_score_intermediate', -1)), int(self._read_metadata('low_score_expert', -1)) ] self._all_scores = self._data_loader( self._read_metadata('all_scores', '[]')) self._numberO = int(self._read_metadata('numberO', PRODUCT)) self._numberC = int(self._read_metadata('numberC', HASH)) self._matches = int(self._read_metadata('matches', 0)) self._robot_matches = int(self._read_metadata('robot_matches', 0)) self._total_time = int(self._read_metadata('total_time', 0)) self._deck_index = int(self._read_metadata('deck_index', 0)) self._word_lists = [[ self._read_metadata('mouse', _('mouse')), self._read_metadata('cat', _('cat')), self._read_metadata('dog', _('dog')) ], [ self._read_metadata('cheese', _('cheese')), self._read_metadata('apple', _('apple')), self._read_metadata('bread', _('bread')) ], [ self._read_metadata('moon', _('moon')), self._read_metadata('sun', _('sun')), self._read_metadata('earth', _('earth')) ]] self._editing_word_list = bool( int(self._read_metadata('editing_word_list', 0))) self._editing_custom_cards = bool( int(self._read_metadata('editing_custom_cards', 0))) if self._card_type == 'custom': self._custom_object = self._read_metadata('custom_object', None) if self._custom_object == None: self._card_type = 'pattern' self._custom_jobject = [] for i in range(9): self._custom_jobject.append( self._read_metadata('custom_' + str(i), None)) def _write_scores_to_clipboard(self, button=None): ''' SimpleGraph will plot the cululative results ''' jscores = '' for i, s in enumerate(self.vmw.all_scores): jscores += '%s: %s\n' % (str(i + 1), s) Gtk.Clipboard().set_text(jscores) def _setup_toolbars(self): ''' Setup the toolbars.. ''' games_toolbar = Gtk.Toolbar() tools_toolbar = Gtk.Toolbar() numbers_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() self.activity_toolbar_button = ActivityToolbarButton(self) toolbox.toolbar.insert(self.activity_toolbar_button, 0) self.activity_toolbar_button.show() ''' self.numbers_toolbar_button = ToolbarButton( page=numbers_toolbar, icon_name='number-tools') numbers_toolbar.show() toolbox.toolbar.insert(self.numbers_toolbar_button, -1) self.numbers_toolbar_button.show() ''' self.tools_toolbar_button = ToolbarButton(page=tools_toolbar, icon_name='view-source') tools_toolbar.show() toolbox.toolbar.insert(self.tools_toolbar_button, -1) self.tools_toolbar_button.show() self.button_pattern = button_factory('new-word-game', toolbox.toolbar, self._select_game_cb, cb_arg='word', tooltip=PROMPT_DICT['word']) self._set_extras(toolbox.toolbar) self._sep.append(separator_factory(toolbox.toolbar, False, True)) help_button = HelpButton(self) toolbox.toolbar.insert(help_button, -1) help_button.show() self._setup_toolbar_help() self._sep.append(separator_factory(toolbox.toolbar, True, False)) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() export_scores = button_factory('score-copy', self.activity_toolbar_button, self._write_scores_to_clipboard, tooltip=_('Export scores to clipboard')) self.set_toolbar_box(toolbox) toolbox.show() ''' self.button_pattern = button_factory( 'new-pattern-game', games_toolbar, self._select_game_cb, cb_arg='pattern', tooltip=PROMPT_DICT['pattern']) self.button_number = button_factory( 'new-number-game', games_toolbar, self._select_game_cb, cb_arg='number', tooltip=PROMPT_DICT['number']) self.button_word = button_factory( 'new-word-game', games_toolbar, self._select_game_cb, cb_arg='word', tooltip=PROMPT_DICT['word']) self.button_custom = button_factory( 'no-custom-game', games_toolbar, self._select_game_cb, cb_arg='custom', tooltip=PROMPT_DICT['custom']) self._set_extras(games_toolbar) ''' self.words_tool_button = button_factory('word-tools', tools_toolbar, self._edit_words_cb, tooltip=_('Edit word lists.')) ''' self.import_button = button_factory( 'image-tools', tools_toolbar, self.image_import_cb, tooltip=_('Import custom cards')) self.button_custom = button_factory( 'no-custom-game', tools_toolbar, self._select_game_cb, cb_arg='custom', tooltip=PROMPT_DICT['custom']) self.product_button = radio_factory( 'product', numbers_toolbar, self._number_card_O_cb, cb_arg=PRODUCT, tooltip=_('product'), group=None) NUMBER_O_BUTTONS[PRODUCT] = self.product_button self.roman_button = radio_factory( 'roman', numbers_toolbar, self._number_card_O_cb, cb_arg=ROMAN, tooltip=_('Roman numerals'), group=self.product_button) NUMBER_O_BUTTONS[ROMAN] = self.roman_button self.word_button = radio_factory( 'word', numbers_toolbar, self._number_card_O_cb, cb_arg=WORD, tooltip=_('word'), group=self.product_button) NUMBER_O_BUTTONS[WORD] = self.word_button self.chinese_button = radio_factory( 'chinese', numbers_toolbar, self._number_card_O_cb, cb_arg=CHINESE, tooltip=_('Chinese'), group=self.product_button) NUMBER_O_BUTTONS[CHINESE] = self.chinese_button self.mayan_button = radio_factory( 'mayan', numbers_toolbar, self._number_card_O_cb, cb_arg=MAYAN, tooltip=_('Mayan'), group=self.product_button) NUMBER_O_BUTTONS[MAYAN] = self.mayan_button self.incan_button = radio_factory( 'incan', numbers_toolbar, self._number_card_O_cb, cb_arg=INCAN, tooltip=_('Quipu'), group=self.product_button) NUMBER_O_BUTTONS[INCAN] = self.incan_button separator_factory(numbers_toolbar, False, True) self.hash_button = radio_factory( 'hash', numbers_toolbar, self._number_card_C_cb, cb_arg=HASH, tooltip=_('hash marks'), group=None) NUMBER_C_BUTTONS[HASH] = self.hash_button self.dots_button = radio_factory( 'dots', numbers_toolbar, self._number_card_C_cb, cb_arg=DOTS, tooltip=_('dots in a circle'), group=self.hash_button) NUMBER_C_BUTTONS[DOTS] = self.dots_button self.star_button = radio_factory( 'star', numbers_toolbar, self._number_card_C_cb, cb_arg=STAR, tooltip=_('points on a star'), group=self.hash_button) NUMBER_C_BUTTONS[STAR] = self.star_button self.dice_button = radio_factory( 'dice', numbers_toolbar, self._number_card_C_cb, cb_arg=DICE, tooltip=_('dice'), group=self.hash_button) NUMBER_C_BUTTONS[DICE] = self.dice_button self.lines_button = radio_factory( 'lines', numbers_toolbar, self._number_card_C_cb, cb_arg=LINES, tooltip=_('dots in a line'), group=self.hash_button) NUMBER_C_BUTTONS[LINES] = self.lines_button ''' def _configure_cb(self, event): self._vbox.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self._vbox.show() self._canvas.set_size_request(int(Gdk.Screen.width()), int(Gdk.Screen.height())) self._canvas.show() if Gdk.Screen.width() < Gdk.Screen.height(): for sep in self._sep: sep.hide() else: for sep in self._sep: sep.show() def _robot_selection_cb(self, widget): if self._robot_palette: if not self._robot_palette.is_up(): self._robot_palette.popup(immediate=True, state=self._robot_palette.SECONDARY) else: self._robot_palette.popdown(immediate=True) return def _setup_robot_palette(self): self._robot_palette = self._robot_time_button.get_palette() for seconds in ROBOT_TIMER_VALUES: text = ROBOT_TIMER_LABELS[seconds] menu_item = MenuItem(icon_name='timer-%d' % (seconds), text_label=text) menu_item.connect('activate', self._robot_selected_cb, seconds) self._robot_palette.menu.append(menu_item) menu_item.show() def _robot_selected_cb(self, button, seconds): self.vmw.robot_time = seconds if hasattr(self, '_robot_time_button') and \ seconds in ROBOT_TIMER_VALUES: self._robot_time_button.set_icon_name('timer-%d' % seconds) def _set_extras(self, toolbar): self.robot_button = button_factory('robot-off', toolbar, self._robot_cb, tooltip=_('Play with the computer')) self._robot_time_button = button_factory('timer-60', toolbar, self._robot_selection_cb, tooltip=_('robot pause time')) self._setup_robot_palette() self._sep.append(separator_factory(toolbar, False, True)) self.beginner_button = radio_factory('beginner', toolbar, self._level_cb, cb_arg=BEGINNER, tooltip=_('beginner'), group=None) LEVEL_BUTTONS[BEGINNER] = self.beginner_button self.intermediate_button = radio_factory('intermediate', toolbar, self._level_cb, cb_arg=INTERMEDIATE, tooltip=_('intermediate'), group=self.beginner_button) LEVEL_BUTTONS[INTERMEDIATE] = self.intermediate_button self.expert_button = radio_factory('expert', toolbar, self._level_cb, cb_arg=EXPERT, tooltip=_('expert'), group=self.beginner_button) LEVEL_BUTTONS[EXPERT] = self.expert_button def _fixed_resize_cb(self, widget=None, rect=None): ''' If a toolbar opens or closes, we need to resize the vbox holding out scrolling window. ''' self._vbox.set_size_request(rect.width, rect.height) def _setup_canvas(self): ''' Create a canvas in a Gtk.Fixed ''' self.fixed = Gtk.Fixed() self.fixed.connect('size-allocate', self._fixed_resize_cb) self.fixed.show() self.set_canvas(self.fixed) self._vbox = Gtk.VBox(False, 0) self._vbox.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self.fixed.put(self._vbox, 0, 0) self._vbox.show() self._canvas = Gtk.DrawingArea() self._canvas.set_size_request(int(Gdk.Screen.width()), int(Gdk.Screen.height())) self._canvas.show() self.show_all() self._vbox.pack_end(self._canvas, True, True, 0) self._vbox.show() self.show_all() self.vmw = Game(self._canvas, self) self.vmw.level = self._play_level LEVEL_BUTTONS[self._play_level].set_active(True) self.vmw.card_type = self._card_type self.vmw.robot = False self.vmw.robot_time = self._robot_time self.vmw.low_score = self._low_score self.vmw.all_scores = self._all_scores self.vmw.numberO = self._numberO # NUMBER_O_BUTTONS[self._numberO].set_active(True) self.vmw.numberC = self._numberC # NUMBER_C_BUTTONS[self._numberC].set_active(True) self.vmw.matches = self._matches self.vmw.robot_matches = self._robot_matches self.vmw.total_time = self._total_time self.vmw.buddies = [] self.vmw.word_lists = self._word_lists self.vmw.editing_word_list = self._editing_word_list if hasattr(self, '_custom_object') and self._custom_object is not None: self.vmw._find_custom_paths(datastore.get(self._custom_object)) for i in range(9): if hasattr(self, '_custom_jobject') and \ self._custom_jobject[i] is not None: self.vmw.custom_paths[i] = datastore.get( self._custom_jobject[i]) return self._canvas def write_file(self, file_path): ''' Write data to the Journal. ''' if hasattr(self, 'vmw'): self.metadata['play_level'] = self.vmw.level self.metadata['low_score_beginner'] = int(self.vmw.low_score[0]) self.metadata['low_score_intermediate'] = int( self.vmw.low_score[1]) self.metadata['low_score_expert'] = int(self.vmw.low_score[2]) self.metadata['all_scores'] = \ self._data_dumper(self.vmw.all_scores) self.metadata['robot_time'] = self.vmw.robot_time self.metadata['numberO'] = self.vmw.numberO self.metadata['numberC'] = self.vmw.numberC self.metadata['cardtype'] = self.vmw.card_type self.metadata['matches'] = self.vmw.matches self.metadata['robot_matches'] = self.vmw.robot_matches self.metadata['total_time'] = int(self.vmw.total_time) self.metadata['deck_index'] = self.vmw.deck.index self.metadata['mouse'] = self.vmw.word_lists[0][0] self.metadata['cat'] = self.vmw.word_lists[0][1] self.metadata['dog'] = self.vmw.word_lists[0][2] self.metadata['cheese'] = self.vmw.word_lists[1][0] self.metadata['apple'] = self.vmw.word_lists[1][1] self.metadata['bread'] = self.vmw.word_lists[1][2] self.metadata['moon'] = self.vmw.word_lists[2][0] self.metadata['sun'] = self.vmw.word_lists[2][1] self.metadata['earth'] = self.vmw.word_lists[2][2] self.metadata['editing_word_list'] = self.vmw.editing_word_list self.metadata['mime_type'] = 'application/x-visualmatch' f = file(file_path, 'w') f.write(self._dump()) f.close() else: _logger.debug('Deferring saving to %s' % file_path) def _dump(self): ''' Dump game data to the journal.''' data = [] for i in self.vmw.grid.grid: if i is None or self.vmw.editing_word_list: data.append(None) else: data.append(i.index) for i in self.vmw.clicked: if i.spr is None or self.vmw.deck.spr_to_card(i.spr) is None or \ self.vmw.editing_word_list: data.append(None) else: data.append(self.vmw.deck.spr_to_card(i.spr).index) for i in self.vmw.deck.cards: if i is None or self.vmw.editing_word_list: data.append(None) else: data.append(i.index) for i in self.vmw.match_list: if self.vmw.deck.spr_to_card(i) is not None: data.append(self.vmw.deck.spr_to_card(i).index) for i in self.vmw.word_lists: for j in i: data.append(j) return self._data_dumper(data) def _data_dumper(self, data): io = StringIO() jdump(data, io) return io.getvalue() def read_file(self, file_path): ''' Read data from the Journal. ''' f = open(file_path, 'r') self._load(f.read()) f.close() def _load(self, data): ''' Load game data from the journal. ''' saved_state = self._data_loader(data) if len(saved_state) > 0: self._saved_state = saved_state def _data_loader(self, data): io = StringIO(data) return jload(io) def _notify_new_game(self, prompt): ''' Called from New Game button since loading a new game can be slooow!! ''' alert = NotifyAlert(3) alert.props.title = prompt alert.props.msg = _('A new game is loading.') def _notification_alert_response_cb(alert, response_id, self): self.remove_alert(alert) alert.connect('response', _notification_alert_response_cb, self) self.add_alert(alert) alert.show() def _new_help_box(self, name, button=None): help_box = Gtk.VBox() help_box.set_homogeneous(False) help_palettes[name] = help_box if button is not None: help_buttons[name] = button help_windows[name] = Gtk.ScrolledWindow() help_windows[name].set_size_request( int(Gdk.Screen.width() / 3), Gdk.Screen.height() - style.GRID_CELL_SIZE * 3) help_windows[name].set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) help_windows[name].add_with_viewport(help_palettes[name]) help_palettes[name].show() return help_box def _setup_toolbar_help(self): ''' Set up a help palette for the main toolbars ''' help_box = self._new_help_box('main-toolbar') add_section(help_box, _('Dimensions'), icon='activity-dimensions') add_paragraph(help_box, _('Tools'), icon='view-source') # add_paragraph(help_box, _('Game'), icon='new-pattern-game') # add_paragraph(help_box, PROMPT_DICT['number'], icon='new-number-game') add_paragraph(help_box, PROMPT_DICT['word'], icon='new-word-game') # add_paragraph(help_box, _('Numbers'), icon='number-tools') add_paragraph(help_box, _('Play with the computer'), icon='robot-off') add_paragraph(help_box, _('robot pause time'), icon='timer-60') add_paragraph(help_box, _('beginner'), icon='beginner') add_paragraph(help_box, _('intermediate'), icon='intermediate') add_paragraph(help_box, _('expert'), icon='expert') add_section(help_box, _('Dimensions'), icon='activity-dimensions') add_paragraph(help_box, _('Export scores to clipboard'), icon='score-copy') add_section(help_box, _('Tools'), icon='view-source') # add_section(help_box, _('Import image cards'), icon='image-tools') # add_paragraph(help_box, PROMPT_DICT['custom'], icon='new-custom-game') add_section(help_box, _('Edit word lists.'), icon='word-tools') ''' add_section(help_box, _('Numbers'), icon='number-tools') add_paragraph(help_box, _('product'), icon='product') add_paragraph(help_box, _('Roman numerals'), icon='roman') add_paragraph(help_box, _('word'), icon='word') add_paragraph(help_box, _('Chinese'), icon='chinese') add_paragraph(help_box, _('Mayan'), icon='mayan') add_paragraph(help_box, _('Quipu'), icon='incan') add_paragraph(help_box, _('hash marks'), icon='hash') add_paragraph(help_box, _('dots in a circle'), icon='dots') add_paragraph(help_box, _('points on a star'), icon='star') add_paragraph(help_box, _('dice'), icon='dice') add_paragraph(help_box, _('dots in a line'), icon='lines') ''' 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.vmw.buddies.append(self.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...''' if self._shared_activity is None: _logger.error('Failed to share or join activity ... \ _shared_activity is null in _shared_cb()') return self.initiating = True self.waiting_for_deck = False _logger.debug('I am sharing...') 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) _logger.debug('This is my activity: making a tube...') id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _joined_cb(self, activity): ''' ...or join an exisiting share. ''' if self._shared_activity is None: _logger.error('Failed to share or join activity ... \ _shared_activity is null in _shared_cb()') return self.initiating = False _logger.debug('I joined a shared activity.') 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) _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.waiting_for_deck = 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.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) if self.waiting_for_deck: self._send_event('j') def event_received_cb(self, text): ''' Data is passed as tuples: cmd:text ''' if text[0] == 'B': e, card_index = text.split(':') self.vmw.add_to_clicked( self.vmw.deck.index_to_card(int(card_index)).spr) elif text[0] == 'r': self.vmw.clean_up_match() elif text[0] == 'R': self.vmw.clean_up_no_match(None) elif text[0] == 'S': e, card_index = text.split(':') i = int(card_index) self.vmw.process_click(self.vmw.clicked[i].spr) self.vmw.process_selection(self.vmw.clicked[i].spr) elif text[0] == 'j': if self.initiating: # Only the sharer 'shares'. self._send_event('P:' + str(self.vmw.level)) self._send_event('X:' + str(self.vmw.deck.index)) self._send_event('M:' + str(self.vmw.matches)) self._send_event('C:' + self.vmw.card_type) self._send_event('D:' + str(self._dump())) elif text[0] == 'J': # Force a request for current state. self._send_event('j') self.waiting_for_deck = True elif text[0] == 'C': e, text = text.split(':') self.vmw.card_type = text elif text[0] == 'P': e, text = text.split(':') self.vmw.level = int(text) # self.level_label.set_text(self.calc_level_label( # self.vmw.low_score, self.vmw.level)) LEVEL_BUTTONS[self.vmw.level].set_active(True) elif text[0] == 'X': e, text = text.split(':') self.vmw.deck.index = int(text) elif text[0] == 'M': e, text = text.split(':') self.vmw.matches = int(text) elif text[0] == 'D': if self.waiting_for_deck: e, text = text.split(':') self._load(text) self.waiting_for_deck = False self.vmw.new_game(self._saved_state, self.vmw.deck.index) def _send_event(self, entry): ''' Send event through the tube. ''' if hasattr(self, 'chattube') and self.chattube is not None: self.chattube.SendText(entry)
def _setup_toolbars(self): """ Setup the toolbars.. """ project_toolbar = Gtk.Toolbar() custom_slide_toolbar = Gtk.Toolbar() custom_stator_toolbar = Gtk.Toolbar() edit_toolbar = Gtk.Toolbar() # no sharing self.max_participants = 1 toolbox = ToolbarBox() # Activity toolbar activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() project_toolbar_button = ToolbarButton(page=project_toolbar, icon_name='sliderule') project_toolbar.show() toolbox.toolbar.insert(project_toolbar_button, -1) project_toolbar_button.show() custom_slide_toolbar_button = ToolbarButton(page=custom_slide_toolbar, icon_name='custom-slide') custom_slide_toolbar.show() toolbox.toolbar.insert(custom_slide_toolbar_button, -1) custom_slide_toolbar_button.show() custom_stator_toolbar_button = ToolbarButton( page=custom_stator_toolbar, icon_name='custom-stator') custom_stator_toolbar.show() toolbox.toolbar.insert(custom_stator_toolbar_button, -1) custom_stator_toolbar_button.show() edit_toolbar_button = ToolbarButton(label=_('Edit'), page=edit_toolbar, icon_name='toolbar-edit') edit_toolbar_button.show() toolbox.toolbar.insert(edit_toolbar_button, -1) edit_toolbar_button.show() self.set_toolbar_box(toolbox) toolbox.show() toolbar = toolbox.toolbar # Add the buttons to the toolbars self._function_combo = combo_factory(FUNCTIONS, project_toolbar, self._function_combo_cb, default=FC_multiply, tooltip=_('select function')) self.top_button = button_factory('C', project_toolbar, self._dummy_cb, tooltip=_('active slide')) self._slide_combo = combo_factory(SLIDE_TABLE, project_toolbar, self._slide_combo_cb, default=C_slide, tooltip=_('select slide')) self.bottom_button = button_factory('D', project_toolbar, self._dummy_cb, tooltip=_('active stator')) self._stator_combo = combo_factory(STATOR_TABLE, project_toolbar, self._stator_combo_cb, default=D_slide, tooltip=_('select stator')) separator_factory(project_toolbar) self.realign_button = button_factory('realign', project_toolbar, self.realign_cb, tooltip=_('realign slides')) self._offset_function = [] self._calculate_function = [] self._label_function = [] self._domain_min = [] self._domain_max = [] self._step_size = [] self.custom = [] ENTRY = ['C', 'D'] ENTRY_TOOLBAR = [custom_slide_toolbar, custom_stator_toolbar] ENTRY_BUTTON = ['custom-slide', 'custom-stator'] ENTRY_TOOLTIP = [_('create custom slide'), _('create custom stator')] ENTRY_CALLBACK = [self._custom_slide_cb, self._custom_stator_cb] for i in range(2): self._offset_function.append( entry_factory(DEFINITIONS[ENTRY[i]][0], ENTRY_TOOLBAR[i], tooltip=_('position function'), max=10)) self._calculate_function.append( entry_factory(DEFINITIONS[ENTRY[i]][1], ENTRY_TOOLBAR[i], tooltip=_('result function'), max=10)) self._label_function.append( entry_factory(DEFINITIONS[ENTRY[i]][2], ENTRY_TOOLBAR[i], tooltip=_('label function'), max=10)) self._domain_min.append( entry_factory(DEFINITIONS[ENTRY[i]][3], ENTRY_TOOLBAR[i], tooltip=_('domain minimum'), max=4)) self._domain_max.append( entry_factory(DEFINITIONS[ENTRY[i]][4], ENTRY_TOOLBAR[i], tooltip=_('domain maximum'), max=4)) self._step_size.append( entry_factory(DEFINITIONS[ENTRY[i]][5], ENTRY_TOOLBAR[i], tooltip=_('step size'), max=4)) self.custom.append( button_factory(ENTRY_BUTTON[i], ENTRY_TOOLBAR[i], ENTRY_CALLBACK[i], tooltip=ENTRY_TOOLTIP[i])) copy = button_factory('edit-copy', edit_toolbar, self._copy_cb, tooltip=_('Copy'), accelerator='<Ctrl>c') paste = button_factory('edit-paste', edit_toolbar, self._paste_cb, tooltip=_('Paste'), accelerator='<Ctrl>v') separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() # workaround to #2050 edit_toolbar_button.set_expanded(True) # start with project toolbar enabled project_toolbar_button.set_expanded(True)
class MeasureActivity(activity.Activity): ''' Oscilloscope Sugar activity ''' def __init__(self, handle): ''' Init canvas, toolbars, etc. The toolbars are in sensor_toolbar.py and toolbar_side.py The audio controls are in audiograb.py The rendering happens in drawwaveform.py Logging is in journal.py ''' activity.Activity.__init__(self, handle) if Gst.version() == (1L, 0L, 10L, 0L): return self._incompatible() self._image_counter = 1 def mode_image(name): path = os.path.join(ICONS_DIR, name) return GdkPixbuf.Pixbuf.new_from_file_at_size(path, 45, 45) self.mode_images = {} self.mode_images['sound'] = mode_image('media-audio.svg') self.mode_images['resistance'] = mode_image('resistance.svg') self.mode_images['voltage'] = mode_image('voltage.svg') self.icon_colors = self.get_icon_colors_from_sugar() self.stroke_color, self.fill_color = self.icon_colors.split(',') self.nick = self.get_nick_from_sugar() self.CONTEXT = '' self.adjustmentf = None # Freq. slider control self.hw = _get_hardware_model() self.new_recording = False self.session_id = 0 self.read_metadata() self._active = True self._dsobject = None self.connect('notify::active', self._notify_active_cb) self.connect('destroy', self.on_quit) self.data_logger = DataLogger(self) self.wave = DrawWaveform(self) ag = audiograb.AudioGrab_Unknown ags = { 'XO-1': audiograb.AudioGrab_XO1, 'XO-1.5': audiograb.AudioGrab_XO15, 'XO-1.75': audiograb.AudioGrab_XO175, 'XO-4': audiograb.AudioGrab_XO4, 'NL3': audiograb.AudioGrab_NL3, } if self.hw in ags: ag = ags[self.hw] self.audiograb = ag(self.wave.new_buffer, self) # no sharing self.max_participants = 1 box3 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, homogeneous=False, spacing=0) box3.pack_start(self.wave, True, True, 0) # We need event boxes in order to set the background color. side_eventboxes = [] self.side_toolbars = [] for i in range(self.audiograb.channels): side_eventboxes.append(Gtk.EventBox()) side_eventboxes[i].modify_bg( Gtk.StateType.NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) self.side_toolbars.append(SideToolbar(self, channel=i)) side_eventboxes[i].add(self.side_toolbars[i].box1) box3.pack_start(side_eventboxes[i], False, True, 0) event_box = Gtk.EventBox() self.text_box = Gtk.Label() self.text_box.set_justify(Gtk.Justification.LEFT) rgba = Gdk.RGBA() rgba.red, rgba.green, rgba.blue, rgba.alpha = 1., 1., 1., 1. self.text_box.override_background_color(Gtk.StateFlags.NORMAL, rgba) event_box.add(self.text_box) event_box.modify_bg(Gtk.StateType.NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) box1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False, spacing=0) box1.pack_start(box3, True, True, 0) box1.pack_start(event_box, False, True, 0) self.set_canvas(box1) toolbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() self.sensor_toolbar = SensorToolbar(self, self.audiograb.channels) self.tuning_toolbar = TuningToolbar(self) self.new_instrument_toolbar = InstrumentToolbar(self) self._extras_toolbar = Gtk.Toolbar() self.control_toolbar = Gtk.Toolbar() sensor_button = ToolbarButton(label=_('Sensors'), page=self.sensor_toolbar, icon_name='sensor-tools') toolbox.toolbar.insert(sensor_button, -1) sensor_button.show() tuning_button = ToolbarButton( # TRANS: Tuning insruments label=_('Tuning'), page=self.tuning_toolbar, icon_name='tuning-tools') toolbox.toolbar.insert(tuning_button, -1) tuning_button.show() new_instrument_button = ToolbarButton(label=_('Add instrument'), page=self.new_instrument_toolbar, icon_name='view-source') toolbox.toolbar.insert(new_instrument_button, -1) new_instrument_button.show() self._extras_button = ToolbarButton(page=self._extras_toolbar, icon_name='domain-time') toolbox.toolbar.insert(self._extras_button, -1) self._extras_toolbar_item = Gtk.ToolItem() self._extras_toolbar.insert(self._extras_toolbar_item, -1) self._extras_button.hide() self.sensor_toolbar.show() self._extra_tools = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) # Set up Frequency-domain Button self.freq = ToolButton('domain-time') self.freq.set_tooltip(_('Time Base')) self.freq.connect('clicked', self.timefreq_control) self.freq.show() self._extra_tools.add(self.freq) self.sensor_toolbar.add_frequency_slider(self._extra_tools) self._extra_item = Gtk.ToolItem() self._extra_item.add(self._extra_tools) self._extra_tools.show() toolbox.toolbar.insert(self._extra_item, -1) self._extra_item.show() self._pause = ToolButton('media-playback-pause') self._pause.set_tooltip(_('Freeze the display')) self._pause.connect('clicked', self._pause_play_cb) self._pause.show() toolbox.toolbar.insert(self._pause, -1) self._capture = ToolButton('image-saveoff') self._capture.set_tooltip(_('Capture sample now')) self._capture.connect('clicked', self._capture_cb) self._capture.show() toolbox.toolbar.insert(self._capture, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbox.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.props.accelerator = _('<Ctrl>Q') toolbox.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbox) sensor_button.set_expanded(True) toolbox.show() self.sensor_toolbar.update_page_size() self.show_all() self._first = True # Always start in 'sound' mode. self.sensor_toolbar.set_mode('sound') self.sensor_toolbar.set_sound_context() self.sensor_toolbar.set_show_hide_windows() self.wave.set_active(True) self.wave.set_context_on() screen = Gdk.Screen.get_default() screen.connect('size-changed', self.__screen_size_changed_cb) self.__screen_size_changed_cb(None)
def _setup_toolbars(self): ''' Setup the toolbars. ''' self.max_participants = 1 # No sharing self._toolbox = ToolbarBox() self.activity_button = ActivityToolbarButton(self) self.activity_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.activity_button, 0) self.activity_button.show() self.set_toolbar_box(self._toolbox) self._toolbox.show() self.toolbar = self._toolbox.toolbar view_toolbar = Gtk.Toolbar() self.view_toolbar_button = ToolbarButton( page=view_toolbar, label=_('View'), icon_name='toolbar-view') self.view_toolbar_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.view_toolbar_button, 1) view_toolbar.show() self.view_toolbar_button.show() button = ToolButton('view-fullscreen') button.set_tooltip(_('Fullscreen')) button.props.accelerator = '<Alt>Return' view_toolbar.insert(button, -1) button.show() button.connect('clicked', self._fullscreen_cb) self._zoom_in = ToolButton('zoom-in') self._zoom_in.set_tooltip(_('Increase size')) view_toolbar.insert(self._zoom_in, -1) self._zoom_in.show() self._zoom_in.connect('clicked', self._zoom_in_cb) self._zoom_out = ToolButton('zoom-out') self._zoom_out.set_tooltip(_('Decrease size')) view_toolbar.insert(self._zoom_out, -1) self._zoom_out.show() self._zoom_out.connect('clicked', self._zoom_out_cb) self._zoom_eq = ToolButton('zoom-original') self._zoom_eq.set_tooltip(_('Restore original size')) view_toolbar.insert(self._zoom_eq, -1) self._zoom_eq.show() self._zoom_eq.connect('clicked', self._zoom_eq_cb) self._set_zoom_buttons_sensitivity() edit_toolbar = Gtk.Toolbar() self.edit_toolbar_button = ToolbarButton( page=edit_toolbar, label=_('Edit'), icon_name='toolbar-edit') self.edit_toolbar_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.edit_toolbar_button, 1) edit_toolbar.show() self.edit_toolbar_button.show() self._copy_button = ToolButton('edit-copy') self._copy_button.set_tooltip(_('Copy')) self._copy_button.props.accelerator = '<Ctrl>C' edit_toolbar.insert(self._copy_button, -1) self._copy_button.show() self._copy_button.connect('clicked', self._copy_cb) self._copy_button.set_sensitive(False) self._paste_button = ToolButton('edit-paste') self._paste_button.set_tooltip(_('Paste')) self._paste_button.props.accelerator = '<Ctrl>V' edit_toolbar.insert(self._paste_button, -1) self._paste_button.show() self._paste_button.connect('clicked', self._paste_cb) self._paste_button.set_sensitive(False) self._progress_toolbar = Gtk.Toolbar() self.progress_toolbar_button = ToolbarButton( page=self._progress_toolbar, label=_('Check progress'), icon_name='check-progress') self.progress_toolbar_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.progress_toolbar_button, -1) self._progress_toolbar.show() self.progress_toolbar_button.show() self._help_button = ToolButton('toolbar-help') self._help_button.set_tooltip(_('Help')) self._help_button.props.accelerator = '<Ctrl>H' self._toolbox.toolbar.insert(self._help_button, -1) self._help_button.show() self._help_button.connect('clicked', self._help_cb) self._help_button.set_sensitive(False) self._help_button.palette_invoker.props.lock_palette = True self.transfer_button = ToolButton('transfer') self.transfer_button.set_tooltip(_('Training data upload status')) self._toolbox.toolbar.insert(self.transfer_button, -1) self.transfer_button.connect('clicked', self._transfer_cb) self.transfer_button.hide() self.progress_label = Gtk.Label() self.progress_label.set_line_wrap(True) self.progress_label.set_size_request(300, -1) self.progress_label.set_use_markup(True) toolitem = Gtk.ToolItem() toolitem.add(self.progress_label) self.progress_label.show() self._toolbox.toolbar.insert(toolitem, -1) toolitem.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self._toolbox.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' self._toolbox.toolbar.insert(stop_button, -1) stop_button.show()
class LogActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self._autosearch_timer = None # Paths to watch: ~/.sugar/someuser/logs, /var/log paths = [] paths.append(env.get_profile_path('logs')) paths.append('/var/log') # Additional misc files. ext_files = [] ext_files.append(os.path.expanduser('~/.bash_history')) self.viewer = MultiLogView(paths, ext_files) self.set_canvas(self.viewer) self.viewer.grab_focus() self._build_toolbox() # Get Sugar's clipboard self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self.show() self._configure_cb(None) Gdk.Screen.get_default().connect('size-changed', self._configure_cb) def _build_toolbox(self): toolbar_box = ToolbarBox() self.max_participants = 1 activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page self._toolbar = toolbar_box.toolbar self._toolbar.insert(activity_button, -1) self._secondary_toolbar = Gtk.Toolbar() self._secondary_toolbar_button = ToolbarButton( page=self._secondary_toolbar, icon_name='system-search') self._secondary_toolbar.show() self._toolbar.insert(self._secondary_toolbar_button, -1) self._secondary_toolbar_button.hide() show_list = ToggleToolButton('view-list') show_list.set_active(True) show_list.set_tooltip(_('Show list of files')) show_list.connect('toggled', self._list_toggled_cb) self._toolbar.insert(show_list, -1) show_list.show() copy = CopyButton() copy.connect('clicked', self.__copy_clicked_cb) self._toolbar.insert(copy, -1) wrap_btn = ToggleToolButton("format-wrap") wrap_btn.set_tooltip(_('Word Wrap')) wrap_btn.connect('clicked', self._wrap_cb) self._toolbar.insert(wrap_btn, -1) self.search_entry = iconentry.IconEntry() self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1) self.search_entry.set_icon_from_name( iconentry.ICON_ENTRY_PRIMARY, 'entry-search') self.search_entry.add_clear_button() self.search_entry.connect('activate', self._search_entry_activate_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self._search_item = Gtk.ToolItem() self._search_item.add(self.search_entry) self._toolbar.insert(self._search_item, -1) self._search_prev = ToolButton('go-previous-paired') self._search_prev.set_tooltip(_('Previous')) self._search_prev.connect('clicked', self._search_prev_cb) self._toolbar.insert(self._search_prev, -1) self._search_next = ToolButton('go-next-paired') self._search_next.set_tooltip(_('Next')) self._search_next.connect('clicked', self._search_next_cb) self._toolbar.insert(self._search_next, -1) self._update_search_buttons() self.collector_palette = CollectorPalette(self) collector_btn = ToolButton('log-export') collector_btn.set_palette(self.collector_palette) collector_btn.connect('clicked', self._logviewer_cb) collector_btn.show() activity_toolbar.insert(collector_btn, -1) self._delete_btn = ToolButton('list-remove') self._delete_btn.set_tooltip(_('Delete Log File')) self._delete_btn.connect('clicked', self._delete_log_cb) self._toolbar.insert(self._delete_btn, -1) self._separator = Gtk.SeparatorToolItem() self._separator.set_expand(True) self._separator.set_draw(False) self._toolbar.insert(self._separator, -1) self._stop_btn = StopButton(self) self._toolbar.insert(self._stop_btn, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box) def _configure_cb(self, event=None): for control in [self._stop_btn, self._separator, self._delete_btn]: if control in self._toolbar: self._toolbar.remove(control) if Gdk.Screen.width() < Gdk.Screen.height(): self._secondary_toolbar_button.show() self._secondary_toolbar_button.set_expanded(True) self._remove_controls(self._toolbar) self._add_controls(self._secondary_toolbar) else: self._secondary_toolbar_button.set_expanded(False) self._secondary_toolbar_button.hide() self._remove_controls(self._secondary_toolbar) self._add_controls(self._toolbar) for control in [self._delete_btn, self._separator, self._stop_btn]: if control not in self._toolbar: self._toolbar.insert(control, -1) def _remove_controls(self, toolbar): for control in [self._search_item, self._search_prev, self._search_next]: if control in toolbar: toolbar.remove(control) def _add_controls(self, toolbar): for control in [self._search_item, self._search_prev, self._search_next]: if control not in toolbar: toolbar.insert(control, -1) control.show() def _list_toggled_cb(self, widget): if widget.get_active(): self.viewer.list_scroll.show() else: self.viewer.list_scroll.hide() def __copy_clicked_cb(self, button): if self.viewer.active_log: self.viewer.active_log.copy_clipboard(self.clipboard) def _wrap_cb(self, button): if button.get_active(): self.viewer._textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) else: self.viewer._textview.set_wrap_mode(Gtk.WrapMode.NONE) def _search_entry_activate_cb(self, entry): if self._autosearch_timer: GLib.source_remove(self._autosearch_timer) self.viewer.set_search_text(entry.props.text) self._update_search_buttons() def _search_entry_changed_cb(self, entry): if self._autosearch_timer: GLib.source_remove(self._autosearch_timer) self._autosearch_timer = GLib.timeout_add(_AUTOSEARCH_TIMEOUT, self.__autosearch_cb) def __autosearch_cb(self): self._autosearch_timer = None self.search_entry.activate() return False def _search_prev_cb(self, button): self.viewer.search_next('backward') self._update_search_buttons() def _search_next_cb(self, button): self.viewer.search_next('forward') self._update_search_buttons() def _update_search_buttons(self,): if len(self.viewer.search_text) == 0: self._search_prev.props.sensitive = False self._search_next.props.sensitive = False else: prev_result = self.viewer.get_next_result('backward') next_result = self.viewer.get_next_result('forward') self._search_prev.props.sensitive = prev_result is not None self._search_next.props.sensitive = next_result is not None def _delete_log_cb(self, widget): if self.viewer.active_log: logfile = self.viewer.active_log.logfile try: os.remove(logfile) except OSError, err: notify = NotifyAlert() notify.props.title = _('Error') notify.props.msg = _('%(error)s when deleting %(file)s') % \ {'error': err.strerror, 'file': logfile} notify.connect('response', _notify_response_cb, self) self.add_alert(notify)
class AbiWordActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) # abiword uses the current directory for all its file dialogs os.chdir(os.path.expanduser('~')) # create our main abiword canvas self.abiword_canvas = DocumentView() self._new_instance = True toolbar_box = ToolbarBox() self.activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(self.activity_button, -1) separator = Gtk.SeparatorToolItem() separator.show() self.activity_button.props.page.insert(separator, 2) ExportButtonFactory(self, self.abiword_canvas) self.activity_button.show() edit_toolbar = ToolbarButton() edit_toolbar.props.page = EditToolbar(self, toolbar_box) edit_toolbar.props.icon_name = 'toolbar-edit' edit_toolbar.props.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar, -1) view_toolbar = ToolbarButton() view_toolbar.props.page = ViewToolbar(self.abiword_canvas) view_toolbar.props.icon_name = 'toolbar-view' view_toolbar.props.label = _('View') toolbar_box.toolbar.insert(view_toolbar, -1) # due to http://bugzilla.abisource.com/show_bug.cgi?id=13585 if self.abiword_canvas.get_version() != '3.0': self.speech_toolbar_button = ToolbarButton(icon_name='speak') toolbar_box.toolbar.insert(self.speech_toolbar_button, -1) self._init_speech() separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) text_toolbar = ToolbarButton() text_toolbar.props.page = TextToolbar(self.abiword_canvas) text_toolbar.props.icon_name = 'format-text' text_toolbar.props.label = _('Text') toolbar_box.toolbar.insert(text_toolbar, -1) para_toolbar = ToolbarButton() para_toolbar.props.page = ParagraphToolbar(self.abiword_canvas) para_toolbar.props.icon_name = 'paragraph-bar' para_toolbar.props.label = _('Paragraph') toolbar_box.toolbar.insert(para_toolbar, -1) insert_toolbar = ToolbarButton() insert_toolbar.props.page = InsertToolbar(self.abiword_canvas) insert_toolbar.props.icon_name = 'insert-table' insert_toolbar.props.label = _('Table') toolbar_box.toolbar.insert(insert_toolbar, -1) image = ToolButton('insert-picture') image.set_tooltip(_('Insert Image')) self._image_id = image.connect('clicked', self._image_cb) toolbar_box.toolbar.insert(image, -1) palette = image.get_palette() content_box = Gtk.VBox() palette.set_content(content_box) image_floating_checkbutton = Gtk.CheckButton(_('Floating')) image_floating_checkbutton.connect( 'toggled', self._image_floating_checkbutton_toggled_cb) content_box.pack_start(image_floating_checkbutton, True, True, 0) content_box.show_all() self.floating_image = False separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) separator.show() toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box) # add a overlay to be able to show a icon while joining a shared doc overlay = Gtk.Overlay() overlay.add(self.abiword_canvas) overlay.show() self._connecting_box = ConnectingBox() overlay.add_overlay(self._connecting_box) self.set_canvas(overlay) # we want a nice border so we can select paragraphs easily self.abiword_canvas.set_show_margin(True) # Read default font face and size client = GConf.Client.get_default() self._default_font_face = client.get_string( '/desktop/sugar/activities/write/font_face') if not self._default_font_face: self._default_font_face = 'Sans' self._default_font_size = client.get_int( '/desktop/sugar/activities/write/font_size') if self._default_font_size == 0: self._default_font_size = 12 # activity sharing self.participants = {} self.joined = False self.connect('shared', self._shared_cb) if self.shared_activity: # we are joining the activity logger.error('We are joining an activity') # display a icon while joining self._connecting_box.show() # disable the abi widget self.abiword_canvas.set_sensitive(False) self._new_instance = False self.connect('joined', self._joined_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) if self.get_shared(): self._joined_cb(self) else: # we are creating the activity logger.error("We are creating an activity") self.abiword_canvas.zoom_width() self.abiword_canvas.show() self.connect_after('map-event', self.__map_activity_event_cb) self.abiword_canvas.connect('size-allocate', self.size_allocate_cb) def _init_speech(self): import speech from speechtoolbar import SpeechToolbar if speech.supported: self.speech_toolbar = SpeechToolbar(self) self.speech_toolbar_button.set_page(self.speech_toolbar) self.speech_toolbar_button.show() def size_allocate_cb(self, abi, alloc): GObject.idle_add(abi.queue_draw) def __map_activity_event_cb(self, event, activity): # set custom keybindings for Write # we do it later because have problems if done before - OLPC #11049 logger.error('Loading keybindings') keybindings_file = os.path.join(get_bundle_path(), 'keybindings.xml') self.abiword_canvas.invoke_ex( 'com.abisource.abiword.loadbindings.fromURI', keybindings_file, 0, 0) # set default font if self._new_instance: self.abiword_canvas.select_all() logging.error('Setting default font to %s %d in new documents', self._default_font_face, self._default_font_size) self.abiword_canvas.set_font_name(self._default_font_face) self.abiword_canvas.set_font_size(str(self._default_font_size)) self.abiword_canvas.moveto_bod() self.abiword_canvas.select_bod() if hasattr(self.abiword_canvas, 'toggle_rulers'): # this is not available yet on upstream abiword self.abiword_canvas.view_print_layout() self.abiword_canvas.toggle_rulers(False) self.abiword_canvas.grab_focus() def get_preview(self): if not hasattr(self.abiword_canvas, 'render_page_to_image'): return activity.Activity.get_preview(self) from gi.repository import GdkPixbuf pixbuf = self.abiword_canvas.render_page_to_image(1) pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225), GdkPixbuf.InterpType.BILINEAR) preview_data = [] def save_func(buf, lenght, data): data.append(buf) return True pixbuf.save_to_callbackv(save_func, preview_data, 'png', [], []) preview_data = ''.join(preview_data) return preview_data def _shared_cb(self, activity): logger.error('My Write activity was shared') self._sharing_setup() self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) channel = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES] logger.error('This is my activity: offering a tube...') id = channel.OfferDBusTube('com.abisource.abiword.abicollab', {}) logger.error('Tube address: %s', channel.GetDBusTubeAddress(id)) def _sharing_setup(self): logger.debug("_sharing_setup()") if self.shared_activity is None: logger.error('Failed to share or join activity') return 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.tube_id = None self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) def _list_tubes_reply_cb(self, tubes): for tube_info in tubes: self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): logger.error('ListTubes() failed: %s', e) def _joined_cb(self, activity): logger.error("_joined_cb()") if not self.shared_activity: self._enable_collaboration() return self.joined = True logger.error('Joined an existing Write session') self._sharing_setup() logger.error('This is not my 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._enable_collaboration() def _enable_collaboration(self): """ when communication established, hide the download icon and enable the abi widget """ self.abiword_canvas.zoom_width() self.abiword_canvas.set_sensitive(True) self._connecting_box.hide() def _new_tube_cb(self, id, initiator, type, service, params, state): logger.error('New tube: ID=%d initiator=%d type=%d service=%s ' 'params=%r state=%d', id, initiator, type, service, params, state) if self.tube_id is not None: # We are already using a tube return if type != telepathy.TUBE_TYPE_DBUS or \ service != "com.abisource.abiword.abicollab": return channel = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES] if state == telepathy.TUBE_STATE_LOCAL_PENDING: channel.AcceptDBusTube(id) # look for the initiator's D-Bus unique name initiator_dbus_name = None dbus_names = channel.GetDBusNames(id) for handle, name in dbus_names: if handle == initiator: logger.error('found initiator D-Bus name: %s', name) initiator_dbus_name = name break if initiator_dbus_name is None: logger.error('Unable to get the D-Bus name of the tube initiator') return cmd_prefix = 'com.abisource.abiword.abicollab.olpc.' # pass this tube to abicollab address = channel.GetDBusTubeAddress(id) if self.joined: logger.error('Passing tube address to abicollab (join): %s', address) self.abiword_canvas.invoke_ex(cmd_prefix + 'joinTube', address, 0, 0) # The intiator of the session has to be the first passed # to the Abicollab backend. logger.error('Adding the initiator to the session: %s', initiator_dbus_name) self.abiword_canvas.invoke_ex(cmd_prefix + 'buddyJoined', initiator_dbus_name, 0, 0) else: logger.error('Passing tube address to abicollab (offer): %s', address) self.abiword_canvas.invoke_ex(cmd_prefix + 'offerTube', address, 0, 0) self.tube_id = id channel.connect_to_signal('DBusNamesChanged', self._on_dbus_names_changed) self._on_dbus_names_changed(id, dbus_names, []) def _on_dbus_names_changed(self, tube_id, added, removed): """ We call com.abisource.abiword.abicollab.olpc.buddy{Joined,Left} according members of the D-Bus tube. That's why we don't add/remove buddies in _buddy_{joined,left}_cb. """ logger.error('_on_dbus_names_changed') # if tube_id == self.tube_id: cmd_prefix = 'com.abisource.abiword.abicollab.olpc' for handle, bus_name in added: logger.error('added handle: %s, with dbus_name: %s', handle, bus_name) self.abiword_canvas.invoke_ex(cmd_prefix + '.buddyJoined', bus_name, 0, 0) self.participants[handle] = bus_name def _on_members_changed(self, message, added, removed, local_pending, remote_pending, actor, reason): logger.error("_on_members_changed") for handle in removed: bus_name = self.participants.pop(handle, None) if bus_name is None: # FIXME: that shouldn't happen so probably hide another bug. # Should be investigated continue cmd_prefix = 'com.abisource.abiword.abicollab.olpc' logger.error('removed handle: %d, with dbus name: %s', handle, bus_name) self.abiword_canvas.invoke_ex(cmd_prefix + '.buddyLeft', bus_name, 0, 0) def _buddy_joined_cb(self, activity, buddy): logger.error('buddy joined with object path: %s', buddy.object_path()) def _buddy_left_cb(self, activity, buddy): logger.error('buddy left with object path: %s', buddy.object_path()) def read_file(self, file_path): logging.debug('AbiWordActivity.read_file: %s, mimetype: %s', file_path, self.metadata['mime_type']) if self._is_plain_text(self.metadata['mime_type']): self.abiword_canvas.load_file('file://' + file_path, 'text/plain') else: # we pass no mime/file type, let libabiword autodetect it, # so we can handle multiple file formats self.abiword_canvas.load_file('file://' + file_path, '') self.abiword_canvas.zoom_width() self._new_instance = False def write_file(self, file_path): logging.debug('AbiWordActivity.write_file: %s, mimetype: %s', file_path, self.metadata['mime_type']) # if we were editing a text file save as plain text if self._is_plain_text(self.metadata['mime_type']): logger.debug('Writing file as type source (text/plain)') self.abiword_canvas.save('file://' + file_path, 'text/plain', '') else: #if the file is new, save in .odt format if self.metadata['mime_type'] == '': self.metadata['mime_type'] = 'application/rtf' # Abiword can't save in .doc format, save in .rtf instead if self.metadata['mime_type'] == 'application/msword': self.metadata['mime_type'] = 'application/rtf' self.abiword_canvas.save('file://' + file_path, self.metadata['mime_type'], '') # due to http://bugzilla.abisource.com/show_bug.cgi?id=13585 if self.abiword_canvas.get_version() != '3.0': self.metadata['fulltext'] = self.abiword_canvas.get_content( 'text/plain', None)[:3000] def _is_plain_text(self, mime_type): # These types have 'text/plain' in their mime_parents but we need # use it like rich text if mime_type in ['application/rtf', 'text/rtf', 'text/html']: return False from sugar3 import mime mime_parents = mime.get_mime_parents(self.metadata['mime_type']) return self.metadata['mime_type'] in ['text/plain', 'text/csv'] or \ 'text/plain' in mime_parents def _image_floating_checkbutton_toggled_cb(self, checkbutton): self.floating_image = checkbutton.get_active() def _image_cb(self, button): try: chooser = ObjectChooser(self, what_filter='Image', filter_type=FILTER_TYPE_GENERIC_MIME, show_preview=True) except: # for compatibility with older versions chooser = ObjectChooser(self, what_filter='Image') try: result = chooser.run() if result == Gtk.ResponseType.ACCEPT: logging.debug('ObjectChooser: %r', chooser.get_selected_object()) jobject = chooser.get_selected_object() if jobject and jobject.file_path: self.abiword_canvas.insert_image(jobject.file_path, self.floating_image) finally: chooser.destroy() del chooser
def build_colors_toolbar(self, toolbox): colors_bar = Gtk.Toolbar() ###################################################################### # Point color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Player 1')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() color = Gdk.Color(red=65535, green=65535, blue=65535) _fill_color.set_color(color) _fill_color.connect('notify::color', self.color_player1_change) item.add(_fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ###################################################################### # Back color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Player 2')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() color = Gdk.Color(red=0, green=0, blue=0) _fill_color.set_color(color) _fill_color.connect('notify::color', self.color_player2_change) item.add(_fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ###################################################################### # Line color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Lines')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() _fill_color.connect('notify::color', self.color_line_change) item.add(_fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ###################################################################### # Line color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Background')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() color = Gdk.Color(red=0, green=25700, blue=0) _fill_color.set_color(color) _fill_color.connect('notify::color', self.color_back_change) item.add(_fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ###################################################################### # Line color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Board')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() color = Gdk.Color(red=0, green=0, blue=65535) _fill_color.set_color(color) _fill_color.connect('notify::color', self.color_board_change) item.add(_fill_color) colors_bar.insert(item, -1) ###################################################################### colors_bar.show_all() colors_button = ToolbarButton(label=_('Colors'), page=colors_bar, icon_name='toolbar-colors') toolbox.toolbar.insert(colors_button, -1) colors_button.show()
class WebActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) _logger.debug('Starting the web activity') session = WebKit.get_default_session() session.set_property('accept-language-auto', True) session.set_property('ssl-use-system-ca-file', True) session.set_property('ssl-strict', False) # By default, cookies are not stored persistently, we have to # add a cookie jar so that they get saved to disk. We use one # with a SQlite database: cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path, read_only=False) session.add_feature(cookie_jar) _seed_xs_cookie(cookie_jar) # FIXME # downloadmanager.remove_old_parts() self._force_close = False self._tabbed_view = TabbedView() self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._tray = HTray() self.set_tray(self._tray, Gtk.PositionType.BOTTOM) self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) self._view_toolbar = ViewToolbar(self) self._primary_toolbar.connect('add-link', self._link_add_button_cb) self._primary_toolbar.connect('go-home', self._go_home_button_cb) self._primary_toolbar.connect('go-library', self._go_library_button_cb) self._primary_toolbar.connect('set-home', self._set_home_button_cb) self._primary_toolbar.connect('reset-home', self._reset_home_button_cb) self._edit_toolbar_button = ToolbarButton( page=self._edit_toolbar, icon_name='toolbar-edit') self._primary_toolbar.toolbar.insert( self._edit_toolbar_button, 1) view_toolbar_button = ToolbarButton( page=self._view_toolbar, icon_name='toolbar-view') self._primary_toolbar.toolbar.insert( view_toolbar_button, 2) self._primary_toolbar.show_all() self.set_toolbar_box(self._primary_toolbar) self.set_canvas(self._tabbed_view) self._tabbed_view.show() self.model = Model() self.model.connect('add_link', self._add_link_model_cb) self.connect('key-press-event', self._key_press_cb) if handle.uri: self._tabbed_view.current_browser.load_uri(handle.uri) elif not self._jobject.file_path: # TODO: we need this hack until we extend the activity API for # opening URIs and default docs. self._tabbed_view.load_homepage() self.messenger = None self.connect('shared', self._shared_cb) # Get the Presence Service self.pservice = presenceservice.get_instance() try: name, path = self.pservice.get_preferred_connection() self.tp_conn_name = name self.tp_conn_path = path self.conn = telepathy.client.Connection(name, path) except TypeError: _logger.debug('Offline') self.initiating = None if self.get_shared_activity() is not None: _logger.debug('shared: %s', self.get_shared()) # We are joining the activity _logger.debug('Joined activity') self.connect('joined', self._joined_cb) if self.get_shared(): # We've already joined self._joined_cb() else: _logger.debug('Created activity') # README: this is a workaround to remove old temp file # http://bugs.sugarlabs.org/ticket/3973 self._cleanup_temp_files() def _cleanup_temp_files(self): """Removes temporary files generated by Download Manager that were cancelled by the user or failed for any reason. There is a bug in GLib that makes this to happen: https://bugzilla.gnome.org/show_bug.cgi?id=629301 """ try: uptime_proc = open('/proc/uptime', 'r').read() uptime = int(float(uptime_proc.split()[0])) except EnvironmentError: logging.warning('/proc/uptime could not be read') uptime = None temp_path = os.path.join(self.get_activity_root(), 'instance') now = int(time.time()) cutoff = now - 24 * 60 * 60 # yesterday if uptime is not None: boot_time = now - uptime cutoff = max(cutoff, boot_time) for f in os.listdir(temp_path): if f.startswith('.goutputstream-'): fpath = os.path.join(temp_path, f) mtime = int(os.path.getmtime(fpath)) if mtime < cutoff: logging.warning('Removing old temporary file: %s', fpath) try: os.remove(fpath) except EnvironmentError: logging.error('Temporary file could not be ' 'removed: %s', fpath) def _on_focus_url_entry(self, gobject): self._primary_toolbar.entry.grab_focus() def _shared_cb(self, activity_): _logger.debug('My activity was shared') self.initiating = True self._setup() _logger.debug('This is my activity: making a tube...') self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(SERVICE, {}) def _setup(self): if self.get_shared_activity() is None: _logger.debug('Failed to share or join activity') return bus_name, conn_path, channel_paths = \ self.get_shared_activity().get_channels() # Work out what our room is called and whether we have Tubes already room = None tubes_chan = None text_chan = None for channel_path in channel_paths: channel = telepathy.client.Channel(bus_name, channel_path) htype, handle = channel.GetHandle() if htype == telepathy.HANDLE_TYPE_ROOM: _logger.debug('Found our room: it has handle#%d "%s"', handle, self.conn.InspectHandles(htype, [handle])[0]) room = handle ctype = channel.GetChannelType() if ctype == telepathy.CHANNEL_TYPE_TUBES: _logger.debug('Found our Tubes channel at %s', channel_path) tubes_chan = channel elif ctype == telepathy.CHANNEL_TYPE_TEXT: _logger.debug('Found our Text channel at %s', channel_path) text_chan = channel if room is None: _logger.debug("Presence service didn't create a room") return if text_chan is None: _logger.debug("Presence service didn't create a text channel") return # Make sure we have a Tubes channel - PS doesn't yet provide one if tubes_chan is None: _logger.debug("Didn't find our Tubes channel, requesting one...") tubes_chan = self.conn.request_channel( telepathy.CHANNEL_TYPE_TUBES, telepathy.HANDLE_TYPE_ROOM, room, True) self.tubes_chan = tubes_chan self.text_chan = text_chan tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) def _list_tubes_reply_cb(self, tubes): for tube_info in tubes: self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): _logger.debug('ListTubes() failed: %s', e) def _joined_cb(self, activity_): if not self.get_shared_activity(): return _logger.debug('Joined an existing shared activity') self.initiating = False self._setup() _logger.debug('This is not my 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) def _new_tube_cb(self, identifier, initiator, type, service, params, state): _logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', identifier, 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( identifier) self.tube_conn = TubeConnection( self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], identifier, group_iface=self.text_chan[ telepathy.CHANNEL_INTERFACE_GROUP]) _logger.debug('Tube created') self.messenger = Messenger(self.tube_conn, self.initiating, self.model) def _get_data_from_file_path(self, file_path): fd = open(file_path, 'r') try: data = fd.read() finally: fd.close() return data def read_file(self, file_path): if self.metadata['mime_type'] == 'text/plain': data = self._get_data_from_file_path(file_path) self.model.deserialize(data) for link in self.model.data['shared_links']: _logger.debug('read: url=%s title=%s d=%s' % (link['url'], link['title'], link['color'])) self._add_link_totray(link['url'], base64.b64decode(link['thumb']), link['color'], link['title'], link['owner'], -1, link['hash'], link.get('notes')) logging.debug('########## reading %s', data) self._tabbed_view.set_history(self.model.data['history']) for number, tab in enumerate(self.model.data['currents']): tab_page = self._tabbed_view.get_nth_page(number) tab_page.browser.set_history_index(tab['history_index']) zoom_level = tab.get('zoom_level') if zoom_level is not None: tab_page.browser.set_zoom_level(zoom_level) tab_page.browser.grab_focus() self._tabbed_view.set_current_page(self.model.data['current_tab']) elif self.metadata['mime_type'] == 'text/uri-list': data = self._get_data_from_file_path(file_path) uris = mime.split_uri_list(data) if len(uris) == 1: self._tabbed_view.props.current_browser.load_uri(uris[0]) else: _logger.error('Open uri-list: Does not support' 'list of multiple uris by now.') else: file_uri = 'file://' + file_path self._tabbed_view.props.current_browser.load_uri(file_uri) self._tabbed_view.props.current_browser.grab_focus() def write_file(self, file_path): if not self.metadata['mime_type']: self.metadata['mime_type'] = 'text/plain' if self.metadata['mime_type'] == 'text/plain': browser = self._tabbed_view.current_browser if not self._jobject.metadata['title_set_by_user'] == '1': if browser.props.title is None: self.metadata['title'] = _('Untitled') else: self.metadata['title'] = browser.props.title self.model.data['history'] = self._tabbed_view.get_history() current_tab = self._tabbed_view.get_current_page() self.model.data['current_tab'] = current_tab self.model.data['currents'] = [] for n in range(0, self._tabbed_view.get_n_pages()): tab_page = self._tabbed_view.get_nth_page(n) n_browser = tab_page.browser if n_browser is not None: uri = n_browser.get_uri() history_index = n_browser.get_history_index() info = {'title': n_browser.props.title, 'url': uri, 'history_index': history_index, 'zoom_level': n_browser.get_zoom_level()} self.model.data['currents'].append(info) f = open(file_path, 'w') try: logging.debug('########## writing %s', self.model.serialize()) f.write(self.model.serialize()) finally: f.close() def _link_add_button_cb(self, button): self._add_link() def _go_home_button_cb(self, button): self._tabbed_view.load_homepage() def _go_library_button_cb(self, button): self._tabbed_view.load_homepage(ignore_gconf=True) def _set_home_button_cb(self, button): self._tabbed_view.set_homepage() self._alert(_('The initial page was configured')) def _reset_home_button_cb(self, button): self._tabbed_view.reset_homepage() self._alert(_('The default initial page was configured')) def _alert(self, title, text=None): alert = NotifyAlert(timeout=5) alert.props.title = title alert.props.msg = text self.add_alert(alert) alert.connect('response', self._alert_cancel_cb) alert.show() def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) def _key_press_cb(self, widget, event): key_name = Gdk.keyval_name(event.keyval) browser = self._tabbed_view.props.current_browser if event.get_state() & Gdk.ModifierType.CONTROL_MASK: if key_name == 'd': self._add_link() elif key_name == 'f': _logger.debug('keyboard: Find') self._edit_toolbar_button.set_expanded(True) self._edit_toolbar.search_entry.grab_focus() elif key_name == 'l': _logger.debug('keyboard: Focus url entry') self._primary_toolbar.entry.grab_focus() elif key_name == 'minus': _logger.debug('keyboard: Zoom out') browser.zoom_out() elif key_name in ['plus', 'equal']: _logger.debug('keyboard: Zoom in') browser.zoom_in() elif key_name == '0': _logger.debug('keyboard: Actual size') browser.set_zoom_level(ZOOM_ORIGINAL) elif key_name == 'Left': _logger.debug('keyboard: Go back') browser.go_back() elif key_name == 'Right': _logger.debug('keyboard: Go forward') browser.go_forward() elif key_name == 'r': _logger.debug('keyboard: Reload') browser.reload() elif Gdk.keyval_name(event.keyval) == "t": self._tabbed_view.add_tab() elif key_name == 'w': _logger.debug('keyboard: close tab') self._tabbed_view.close_tab() elif key_name == "Tab": _logger.debug('keyboard: next tab') current_index = self._tabbed_view.get_current_page() if current_index == self._tabbed_view.get_n_pages() - 1: self._tabbed_view.set_current_page(0) else: self._tabbed_view.set_current_page(current_index + 1) elif event.get_state() & Gdk.ModifierType.SHIFT_MASK: if key_name == "ISO_Left_Tab": _logger.debug('keyboard: previous tab') current_index = self._tabbed_view.get_current_page() last_index = self._tabbed_view.get_n_pages() if current_index == 0: self._tabbed_view.set_current_page(last_index - 1) else: self._tabbed_view.set_current_page(current_index - 1) else: return False return True elif key_name in ('KP_Up', 'KP_Down', 'KP_Left', 'KP_Right'): scrolled_window = browser.get_parent() if key_name in ('KP_Up', 'KP_Down'): adjustment = scrolled_window.get_vadjustment() elif key_name in ('KP_Left', 'KP_Right'): adjustment = scrolled_window.get_hadjustment() value = adjustment.get_value() step = adjustment.get_step_increment() if key_name in ('KP_Up', 'KP_Left'): adjustment.set_value(value - step) elif key_name in ('KP_Down', 'KP_Right'): adjustment.set_value(value + step) return True elif key_name == 'Escape': status = browser.get_load_status() loading = WebKit.LoadStatus.PROVISIONAL <= status \ < WebKit.LoadStatus.FINISHED if loading: _logger.debug('keyboard: Stop loading') browser.stop_loading() return False def _add_link(self): ''' take screenshot and add link info to the model ''' browser = self._tabbed_view.props.current_browser ui_uri = browser.get_uri() for link in self.model.data['shared_links']: if link['hash'] == sha1(ui_uri).hexdigest(): _logger.debug('_add_link: link exist already a=%s b=%s', link['hash'], sha1(ui_uri).hexdigest()) return buf = self._get_screenshot() timestamp = time.time() self.model.add_link(ui_uri, browser.props.title, buf, profile.get_nick_name(), profile.get_color().to_string(), timestamp) if self.messenger is not None: self.messenger._add_link(ui_uri, browser.props.title, profile.get_color().to_string(), profile.get_nick_name(), base64.b64encode(buf), timestamp) def _add_link_model_cb(self, model, index): ''' receive index of new link from the model ''' link = self.model.data['shared_links'][index] self._add_link_totray(link['url'], base64.b64decode(link['thumb']), link['color'], link['title'], link['owner'], index, link['hash'], link.get('notes')) def _add_link_totray(self, url, buf, color, title, owner, index, hash, notes=None): ''' add a link to the tray ''' item = LinkButton(buf, color, title, owner, hash, notes) item.connect('clicked', self._link_clicked_cb, url) item.connect('remove_link', self._link_removed_cb) item.notes_changed_signal.connect(self.__link_notes_changed) # use index to add to the tray self._tray.add_item(item, index) item.show() self._view_toolbar.traybutton.props.sensitive = True self._view_toolbar.traybutton.props.active = True self._view_toolbar.update_traybutton_tooltip() def _link_removed_cb(self, button, hash): ''' remove a link from tray and delete it in the model ''' self.model.remove_link(hash) self._tray.remove_item(button) if len(self._tray.get_children()) == 0: self._view_toolbar.traybutton.props.sensitive = False self._view_toolbar.traybutton.props.active = False self._view_toolbar.update_traybutton_tooltip() def __link_notes_changed(self, button, hash, notes): self.model.change_link_notes(hash, notes) def _link_clicked_cb(self, button, url): ''' an item of the link tray has been clicked ''' self._tabbed_view.props.current_browser.load_uri(url) def _get_screenshot(self): browser = self._tabbed_view.props.current_browser window = browser.get_window() width, height = window.get_width(), window.get_height() thumb_width, thumb_height = style.zoom(100), style.zoom(80) thumb_surface = Gdk.Window.create_similar_surface( window, cairo.CONTENT_COLOR, thumb_width, thumb_height) cairo_context = cairo.Context(thumb_surface) thumb_scale_w = thumb_width * 1.0 / width thumb_scale_h = thumb_height * 1.0 / height cairo_context.scale(thumb_scale_w, thumb_scale_h) Gdk.cairo_set_source_window(cairo_context, window, 0, 0) cairo_context.paint() thumb_str = StringIO.StringIO() thumb_surface.write_to_png(thumb_str) return thumb_str.getvalue() def can_close(self): if self._force_close: return True elif downloadmanager.can_quit(): return True else: alert = Alert() alert.props.title = ngettext('Download in progress', 'Downloads in progress', downloadmanager.num_downloads()) message = ngettext('Stopping now will erase your download', 'Stopping now will erase your downloads', downloadmanager.num_downloads()) alert.props.msg = message cancel_icon = Icon(icon_name='dialog-cancel') cancel_label = ngettext('Continue download', 'Continue downloads', downloadmanager.num_downloads()) alert.add_button(Gtk.ResponseType.CANCEL, cancel_label, cancel_icon) stop_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Stop'), stop_icon) stop_icon.show() self.add_alert(alert) alert.connect('response', self.__inprogress_response_cb) alert.show() self.present() return False def __inprogress_response_cb(self, alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.CANCEL: logging.debug('Keep on') elif response_id == Gtk.ResponseType.OK: logging.debug('Stop downloads and quit') self._force_close = True downloadmanager.remove_all_downloads() self.close() def __switch_page_cb(self, tabbed_view, page, page_num): browser = page._browser status = browser.get_load_status() if status in (WebKit.LoadStatus.COMMITTED, WebKit.LoadStatus.FIRST_VISUALLY_NON_EMPTY_LAYOUT): self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) elif status in (WebKit.LoadStatus.PROVISIONAL, WebKit.LoadStatus.FAILED, WebKit.LoadStatus.FINISHED): self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) def get_document_path(self, async_cb, async_err_cb): browser = self._tabbed_view.props.current_browser browser.get_source(async_cb, async_err_cb) def get_canvas(self): return self._tabbed_view
def __init__(self, handle): activity.Activity.__init__(self, handle) # HACK to avoid Escape key disable fullscreen mode on Terminal Activity # This is related with http://bugs.sugarlabs.org/ticket/440 self.disconnect_by_func(self._Window__key_press_cb) self.connect('key-press-event', self.__key_press_cb) self.max_participants = 1 self._theme_state = "light" toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() edit_toolbar = self._create_edit_toolbar() edit_toolbar_button = ToolbarButton( page=edit_toolbar, icon_name='toolbar-edit' ) edit_toolbar.show() toolbar_box.toolbar.insert(edit_toolbar_button, -1) edit_toolbar_button.show() view_toolbar = self._create_view_toolbar() view_toolbar_button = ToolbarButton( page=view_toolbar, icon_name='toolbar-view') view_toolbar.show() toolbar_box.toolbar.insert(view_toolbar_button, -1) view_toolbar_button.show() self._delete_tab_toolbar = None self._previous_tab_toolbar = None self._next_tab_toolbar = None helpbutton = self._create_help_button() toolbar_box.toolbar.insert(helpbutton, -1) helpbutton.show_all() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl><Shift>Q' toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show() self._notebook = BrowserNotebook() self._notebook.connect("tab-added", self.__open_tab_cb) self._notebook.set_property("tab-pos", Gtk.PositionType.TOP) self._notebook.set_scrollable(True) self._notebook.show() self.set_canvas(self._notebook) self._create_tab(None)
def __init__(self, handle): """Set up the Develop activity.""" self._dirty = False super(DevelopActivity, self).__init__(handle) self.max_participants = 1 self.current_theme = "light" logging.info(repr(handle.get_dict())) # Source buffer self.editor = sourceview_editor.GtkSourceview2Editor() self.editor.connect('tab-changed', self.__editor_tab_changed_cb) self.editor.connect('changed', self.__editor_changed_cb) # Show tabs after Welcome Page self.editor.set_show_tabs(False) toolbarbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbarbox.toolbar.insert(activity_button, 0) self.set_toolbar_box(toolbarbox) view_btn = ToolbarButton() view_toolbar = DevelopViewToolbar(self) view_btn.props.page = view_toolbar view_btn.props.icon_name = 'toolbar-view' view_btn.props.label = _('View') view_toolbar.connect('theme-changed', self.editor.theme_changed_cb) view_toolbar.connect('font-size-changed', self.editor.font_changed_cb) toolbarbox.toolbar.insert(view_btn, -1) self.view_toolbar = view_toolbar edit_btn = ToolbarButton() edit_btn.props.page = DevelopEditToolbar(self) edit_btn.props.icon_name = 'toolbar-edit' edit_btn.props.label = _('Edit') toolbarbox.toolbar.insert(edit_btn, -1) search_btn = ToolbarButton() search_btn.props.page = DevelopSearchToolbar(self) search_btn.props.icon_name = 'search' search_btn.props.label = _('Search') toolbarbox.toolbar.insert(search_btn, -1) toolbarbox.toolbar.insert(Gtk.SeparatorToolItem(), -1) show_files_btn = RadioToolButton() show_files_btn.props.icon_name = 'sources' show_files_btn.props.group = show_files_btn show_files_btn.set_active(True) show_files_btn.set_tooltip(_('Show source files')) toolbarbox.toolbar.insert(show_files_btn, -1) show_files_btn.connect('clicked', self._change_treenotebook_page, 0) show_symbols_btn = RadioToolButton() show_symbols_btn.props.icon_name = 'symbols' show_symbols_btn.props.group = show_files_btn show_symbols_btn.set_active(False) show_symbols_btn.set_tooltip(_('Show file symbols')) toolbarbox.toolbar.insert(show_symbols_btn, -1) show_symbols_btn.connect('clicked', self._explore_code) show_log_btn = RadioToolButton() show_log_btn.props.icon_name = 'logs' show_log_btn.props.group = show_files_btn show_log_btn.set_active(False) show_log_btn.set_tooltip(_('Show log files')) toolbarbox.toolbar.insert(show_log_btn, -1) show_log_btn.connect('clicked', self._change_treenotebook_page, 2) toolbarbox.toolbar.insert(Gtk.SeparatorToolItem(), -1) create_file_btn = ToolButton('text-x-generic') create_file_btn.set_tooltip(_('Create empty file')) toolbarbox.toolbar.insert(create_file_btn, -1) create_file_btn.show() create_file_btn.connect('clicked', self.__create_empty_file_cb) erase_btn = ToolButton('erase') erase_btn.set_tooltip(_('Remove file')) toolbarbox.toolbar.insert(erase_btn, -1) erase_btn.show() erase_btn.connect('clicked', self.__remove_file_cb) toolbarbox.toolbar.insert(Gtk.SeparatorToolItem(), -1) run_btn = ToolButton('activity-start') run_btn.set_tooltip(_('Run activity')) toolbarbox.toolbar.insert(run_btn, -1) run_btn.connect('clicked', self.__run_actvity_cb) separator = Gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(True) toolbarbox.toolbar.insert(separator, -1) stopbtn = StopButton(self) toolbarbox.toolbar.insert(stopbtn, -1) save_bundle_btn = ToolButton('save-as-bundle') save_bundle_btn.set_tooltip(_('Create bundle (.xo file)')) activity_button.get_page().insert(save_bundle_btn, -1) save_bundle_btn.connect('clicked', self.save_bundle) save_bundle_btn.show() toolbarbox.show_all() # Main layout. hbox = Gtk.HPaned() # The treeview and selected pane reflect each other. self.numb = False # Wait to save until first change, but save an unchanged # backup copy when that happens. self.save_unchanged = False # The sidebar sidebar = Gtk.VBox() self.treenotebook = notebook.Notebook(can_close_tabs=False) self.treenotebook.set_show_tabs(False) sidebar.pack_start(self.treenotebook, True, True, 0) self.activity_tree_view = FileViewer() self.treenotebook.add_page(_("Activity"), self.activity_tree_view) self.treenotebook.set_size_request(Gdk.Screen.width() / 5, -1) # Symbols tree self._symbolstree = SymbolsTree() self._symbolstree.connect('symbol-selected', self.editor.symbol_selected_cb) scrolled = Gtk.ScrolledWindow() scrolled.add(self._symbolstree) scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.treenotebook.add_page(_('Symbols Tree'), scrolled) hbox.pack1(sidebar, resize=True, shrink=False) # Show sidebar after welcome page ends # sidebar.show() self.sidebar = sidebar logging.info('finished check') self.editor.show() hbox.pack2(self.editor, resize=True, shrink=True) self.set_canvas(hbox) hbox.show() logging.critical('finished initialization') self.activity_dir = None self.show() if not handle.object_id or not self.metadata.get('source'): GObject.timeout_add(10, self._show_welcome)
def _setup_toolbars(self): ''' Setup the toolbars. ''' self.max_participants = 2 self.edit_toolbar = Gtk.Toolbar() self.view_toolbar = Gtk.Toolbar() self.adjust_toolbar = Gtk.Toolbar() self.custom_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() edit_toolbar_button = ToolbarButton(label=_("Edit"), page=self.edit_toolbar, icon_name='toolbar-edit') self.edit_toolbar.show() toolbox.toolbar.insert(edit_toolbar_button, -1) edit_toolbar_button.show() view_toolbar_button = ToolbarButton(label=_("View"), page=self.view_toolbar, icon_name='toolbar-view') self.view_toolbar.show() toolbox.toolbar.insert(view_toolbar_button, -1) view_toolbar_button.show() adjust_toolbar_button = ToolbarButton(label=_('Adjust'), page=self.adjust_toolbar, icon_name='preferences-system') self.adjust_toolbar.show() toolbox.toolbar.insert(adjust_toolbar_button, -1) adjust_toolbar_button.show() custom_toolbar_button = ToolbarButton(label=_("Custom"), page=self.custom_toolbar, icon_name='view-source') self.custom_toolbar.show() toolbox.toolbar.insert(custom_toolbar_button, -1) custom_toolbar_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.toolbar = toolbox.toolbar adjust_toolbar_button.set_expanded(True) button_factory('edit-copy', self.edit_toolbar, self._copy_cb, tooltip=_('Copy'), accelerator='<Ctrl>c') button_factory('edit-paste', self.edit_toolbar, self._paste_cb, tooltip=_('Paste'), accelerator='<Ctrl>v') button_factory('view-fullscreen', self.view_toolbar, self.do_fullscreen_cb, tooltip=_('Fullscreen'), accelerator='<Alt>Return') button_factory('media-playback-start', self.view_toolbar, self._play_history_cb, tooltip=_('Play game history')) self.history_button = button_factory('list-numbered', self.view_toolbar, self._show_history_cb, tooltip=_('Show game history')) separator_factory(self.view_toolbar, False, True) label_factory(self.view_toolbar, _('White: ')) self.white_entry = entry_factory('', self.view_toolbar, tooltip=_("White's move")) separator_factory(self.view_toolbar, False, False) label_factory(self.view_toolbar, _('Black: ')) self.black_entry = entry_factory('', self.view_toolbar, tooltip=_("Black's move")) separator_factory(self.view_toolbar, False, True) skin_button1 = radio_factory('white-knight', self.view_toolbar, self.do_default_skin_cb, tooltip=_('Default pieces'), group=None) skin_button2 = radio_factory('white-knight-sugar', self.view_toolbar, self.do_sugar_skin_cb, tooltip=_('Sugar-style pieces'), group=skin_button1) xocolors = XoColor(','.join(self.colors)) icon = Icon(icon_name='white-knight-sugar', xo_color=xocolors) icon.show() skin_button2.set_icon_widget(icon) self.skin_button3 = radio_factory('white-knight-custom', self.view_toolbar, self.do_custom_skin_cb, tooltip=_('Custom pieces'), group=skin_button1) skin_button1.set_active(True) self.play_white_button = radio_factory('white-rook', self.adjust_toolbar, self._play_white_cb, group=None, tooltip=_('Play White')) self.play_black_button = radio_factory('black-rook', self.adjust_toolbar, self._play_black_cb, group=self.play_white_button, tooltip=_('Play Black')) self.play_white_button.set_active(True) separator_factory(self.adjust_toolbar, False, True) self.easy_button = radio_factory('beginner', self.adjust_toolbar, self._easy_cb, group=None, tooltip=_('Beginner')) self.hard_button = radio_factory('expert', self.adjust_toolbar, self._hard_cb, group=self.easy_button, tooltip=_('Expert')) self.easy_button.set_active(True) separator_factory(self.adjust_toolbar, False, True) self.robot_button = radio_factory( 'robot', self.adjust_toolbar, self._robot_cb, group=None, tooltip=_('Play against the computer')) self.human_button = radio_factory('human', self.adjust_toolbar, self._human_cb, group=self.robot_button, tooltip=_('Play against a person')) separator_factory(self.adjust_toolbar, False, False) self.opponent = label_factory(self.adjust_toolbar, '') separator_factory(self.adjust_toolbar, False, True) self.timer_button = ToolButton('timer-0') self.timer_button.set_tooltip(_('Timer')) self.timer_button.connect('clicked', self._timer_button_cb) self.toolbar.insert(self.timer_button, -1) self._setup_timer_palette() self.timer_button.show() self.timer_button.set_sensitive(True) self.robot_button.set_active(True) button_factory('new-game', self.toolbar, self._new_gnuchess_cb, tooltip=_('New game')) button_factory('edit-undo', self.toolbar, self._undo_cb, tooltip=_('Undo')) button_factory('hint', self.toolbar, self._hint_cb, tooltip=_('Hint')) separator_factory(self.toolbar, False, False) self.status = label_factory(self.toolbar, '', width=150) self.status.set_label(_("It is White's move.")) separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() for piece in list(PIECES.keys()): for color in ['white', 'black']: button_factory('%s-%s' % (color, piece), self.custom_toolbar, self._reskin_cb, cb_arg='%s_%s' % (color, piece), tooltip=PIECES[piece][color])
class LogActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self._autosearch_timer = None # Paths to watch: ~/.sugar/someuser/logs, /var/log paths = [] paths.append(env.get_profile_path('logs')) paths.append('/var/log') # Additional misc files. ext_files = [] ext_files.append(os.path.expanduser('~/.bash_history')) self.viewer = MultiLogView(paths, ext_files) self.set_canvas(self.viewer) self.viewer.grab_focus() self._build_toolbox() # Get Sugar's clipboard self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self.show() self._configure_cb(None) Gdk.Screen.get_default().connect('size-changed', self._configure_cb) def _build_toolbox(self): toolbar_box = ToolbarBox() self.max_participants = 1 activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page self._toolbar = toolbar_box.toolbar self._toolbar.insert(activity_button, -1) self._secondary_toolbar = Gtk.Toolbar() self._secondary_toolbar_button = ToolbarButton( page=self._secondary_toolbar, icon_name='system-search') self._secondary_toolbar.show() self._toolbar.insert(self._secondary_toolbar_button, -1) self._secondary_toolbar_button.hide() show_list = ToggleToolButton('view-list') show_list.set_active(True) show_list.set_tooltip(_('Show list of files')) show_list.connect('toggled', self._list_toggled_cb) self._toolbar.insert(show_list, -1) show_list.show() copy = CopyButton() copy.connect('clicked', self.__copy_clicked_cb) self._toolbar.insert(copy, -1) wrap_btn = ToggleToolButton("format-wrap") wrap_btn.set_tooltip(_('Word Wrap')) wrap_btn.connect('clicked', self._wrap_cb) self._toolbar.insert(wrap_btn, -1) self.search_entry = iconentry.IconEntry() self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1) self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'entry-search') self.search_entry.add_clear_button() self.search_entry.connect('activate', self._search_entry_activate_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self._search_item = Gtk.ToolItem() self._search_item.add(self.search_entry) self._toolbar.insert(self._search_item, -1) self._search_prev = ToolButton('go-previous-paired') self._search_prev.set_tooltip(_('Previous')) self._search_prev.connect('clicked', self._search_prev_cb) self._toolbar.insert(self._search_prev, -1) self._search_next = ToolButton('go-next-paired') self._search_next.set_tooltip(_('Next')) self._search_next.connect('clicked', self._search_next_cb) self._toolbar.insert(self._search_next, -1) self._update_search_buttons() self.collector_palette = CollectorPalette(self) collector_btn = ToolButton('log-export') collector_btn.set_palette(self.collector_palette) collector_btn.connect('clicked', self._logviewer_cb) collector_btn.show() activity_toolbar.insert(collector_btn, -1) self._delete_btn = ToolButton('list-remove') self._delete_btn.set_tooltip(_('Delete Log File')) self._delete_btn.connect('clicked', self._delete_log_cb) self._toolbar.insert(self._delete_btn, -1) self._separator = Gtk.SeparatorToolItem() self._separator.set_expand(True) self._separator.set_draw(False) self._toolbar.insert(self._separator, -1) self._stop_btn = StopButton(self) self._toolbar.insert(self._stop_btn, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box) def _configure_cb(self, event=None): for control in [self._stop_btn, self._separator, self._delete_btn]: if control in self._toolbar: self._toolbar.remove(control) if Gdk.Screen.width() < Gdk.Screen.height(): self._secondary_toolbar_button.show() self._secondary_toolbar_button.set_expanded(True) self._remove_controls(self._toolbar) self._add_controls(self._secondary_toolbar) else: self._secondary_toolbar_button.set_expanded(False) self._secondary_toolbar_button.hide() self._remove_controls(self._secondary_toolbar) self._add_controls(self._toolbar) for control in [self._delete_btn, self._separator, self._stop_btn]: if control not in self._toolbar: self._toolbar.insert(control, -1) def _remove_controls(self, toolbar): for control in [ self._search_item, self._search_prev, self._search_next ]: if control in toolbar: toolbar.remove(control) def _add_controls(self, toolbar): for control in [ self._search_item, self._search_prev, self._search_next ]: if control not in toolbar: toolbar.insert(control, -1) control.show() def _list_toggled_cb(self, widget): if widget.get_active(): self.viewer.list_scroll.show() else: self.viewer.list_scroll.hide() def __copy_clicked_cb(self, button): if self.viewer.active_log: self.viewer.active_log.copy_clipboard(self.clipboard) def _wrap_cb(self, button): if button.get_active(): self.viewer._textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) else: self.viewer._textview.set_wrap_mode(Gtk.WrapMode.NONE) def _search_entry_activate_cb(self, entry): if self._autosearch_timer: GObject.source_remove(self._autosearch_timer) self.viewer.set_search_text(entry.props.text) self._update_search_buttons() def _search_entry_changed_cb(self, entry): if self._autosearch_timer: GObject.source_remove(self._autosearch_timer) self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT, self.__autosearch_cb) def __autosearch_cb(self): self._autosearch_timer = None self.search_entry.activate() return False def _search_prev_cb(self, button): self.viewer.search_next('backward') self._update_search_buttons() def _search_next_cb(self, button): self.viewer.search_next('forward') self._update_search_buttons() def _update_search_buttons(self, ): if len(self.viewer.search_text) == 0: self._search_prev.props.sensitive = False self._search_next.props.sensitive = False else: prev_result = self.viewer.get_next_result('backward') next_result = self.viewer.get_next_result('forward') self._search_prev.props.sensitive = prev_result is not None self._search_next.props.sensitive = next_result is not None def _delete_log_cb(self, widget): if self.viewer.active_log: logfile = self.viewer.active_log.logfile try: os.remove(logfile) except OSError as err: notify = NotifyAlert() notify.props.title = _('Error') notify.props.msg = _('%(error)s when deleting %(file)s') % \ {'error': err.strerror, 'file': logfile} notify.connect('response', _notify_response_cb, self) self.add_alert(notify) def _logviewer_cb(self, widget): self.collector_palette.popup(True)
def __init__(self, handle): """Set up the HelloWorld activity.""" activity.Activity.__init__(self, handle) self.connect('realize', self.__realize_cb) self.max_participants = 1 # No sharing self._font_name = None self._layout = LAYOUT_RANDOM self._xo_colors = (_rgb(profile.get_color().to_string().split(',')[0]), _rgb(profile.get_color().to_string().split(',')[1])) self._color_scheme = self._xo_colors self._repeat_tags = False self._toolbox = ToolbarBox() self.activity_button = ActivityToolbarButton(self) self._toolbox.toolbar.insert(self.activity_button, 0) self.activity_button.show() self.set_toolbar_box(self._toolbox) self._toolbox.show() self.toolbar = self._toolbox.toolbar self._edit_toolbar = EditToolbar() button = ToolbarButton() button.set_page(self._edit_toolbar) button.props.icon_name = 'toolbar-edit' button.props.label = _('Edit') self._toolbox.toolbar.insert(button, -1) button.show() self._edit_toolbar.show() self._undo_button = self._edit_toolbar.undo self._undo_button.set_sensitive(False) self._undo_button.connect('clicked', self._undo_cb) self._redo_button = self._edit_toolbar.redo self._redo_button.set_sensitive(False) self._redo_button.connect('clicked', self._redo_cb) # used to count number of times wordcloud is clicked self._count_wordcloud = 0 self._undo_clicked = False self._save_text = [] # used to save text for undo self._save_text_redo = [] # used to save text for redo self._copy_button = self._edit_toolbar.copy self._copy_button.set_sensitive(False) self._copy_button.connect('clicked', self._copy_cb) self._paste_button = self._edit_toolbar.paste self._paste_button.set_sensitive(False) self._paste_button.connect('clicked', self._paste_cb) go_button = ToolButton('generate-cloud') self._toolbox.toolbar.insert(go_button, -1) go_button.set_tooltip(_('Create the cloud')) go_button.show() go_button.connect('clicked', self._go_cb) self._text_item = TextItem(self) self._toolbox.toolbar.insert(self._text_item, -1) self._text_item.show() text = self._read_metadata('text') if text is not None: self._text_item.set_text(text) self._repeat_button = ToggleToolButton('repeat-cloud') self._toolbox.toolbar.insert(self._repeat_button, -1) self._repeat_button.set_tooltip(_('Repeat words')) self._repeat_button.show() self._repeat_button.connect('clicked', self._repeat_cb) self.font_palette_content, self.font_palette_dict = \ set_palette_list( self._setup_font_palette(), 3, 7, style.SMALL_ICON_SIZE + style.DEFAULT_SPACING + style.DEFAULT_PADDING, return_dict=True) self._font_button = FontToolItem(self) self.font_palette_content.show() self._toolbox.toolbar.insert(self._font_button, -1) self._font_button.show() self.color_palette_content, self.color_palette_dict = \ set_palette_list( self._setup_color_palette(), 3, 5, style.GRID_CELL_SIZE + style.DEFAULT_SPACING + style.DEFAULT_PADDING, return_dict=True) self._color_button = ColorToolItem(self) self.color_palette_content.show() self._toolbox.toolbar.insert(self._color_button, -1) self._color_button.show() self.layout_palette_content, self.layout_palette_dict = \ set_palette_list(self._setup_layout_palette(), 1, 5, style.GRID_CELL_SIZE + style.DEFAULT_SPACING + style.DEFAULT_PADDING, return_dict=True) self._layout_button = LayoutToolItem(self) self.layout_palette_content.show() self._toolbox.toolbar.insert(self._layout_button, -1) self._layout_button.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self._toolbox.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' self._toolbox.toolbar.insert(stop_button, -1) stop_button.show() self._show_image( os.path.join(activity.get_bundle_path(), 'WordCloud.png')) self._set_color('XO') self._set_font('Droid Sans') for layout in list(LAYOUT_SCHEMES.keys()): if LAYOUT_SCHEMES[layout] == self._layout: self._set_layout(layout) break
class JukeboxActivity(activity.Activity): __gsignals__ = { 'playlist-finished': (GObject.SignalFlags.RUN_FIRST, None, []), } def __init__(self, handle): activity.Activity.__init__(self, handle) self.player = None self._alert = None self._playlist_jobject = None self._on_unfullscreen_show_playlist = False self.set_title(_('Jukebox Activity')) self.max_participants = 1 toolbar_box = ToolbarBox() self._activity_toolbar_button = ActivityToolbarButton(self) activity_toolbar = self._activity_toolbar_button.page toolbar_box.toolbar.insert(self._activity_toolbar_button, 0) self.title_entry = activity_toolbar.title self._view_toolbar = ViewToolbar() self._view_toolbar.connect('go-fullscreen', self.__go_fullscreen_cb) self._view_toolbar.connect('toggle-playlist', self.__toggle_playlist_cb) view_toolbar_button = ToolbarButton( page=self._view_toolbar, icon_name='toolbar-view') self._view_toolbar.show() toolbar_box.toolbar.insert(view_toolbar_button, -1) view_toolbar_button.show() self._control_toolbar = Gtk.Toolbar() self._control_toolbar_button = ToolbarButton( page=self._control_toolbar, icon_name='media-playback-start') self._control_toolbar.show() toolbar_box.toolbar.insert(self._control_toolbar_button, -1) self._control_toolbar_button.hide() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() self.connect('key_press_event', self.__key_press_event_cb) self.connect('playlist-finished', self.__playlist_finished_cb) # We want to be notified when the activity gets the focus or # loses it. When it is not active, we don't need to keep # reproducing the video self.connect('notify::active', self.__notify_active_cb) self._video_canvas = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self._playlist_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.playlist_widget = PlayList() self.playlist_widget.connect('play-index', self.__play_index_cb) self.playlist_widget.connect('missing-tracks', self.__missing_tracks_cb) self.playlist_widget.set_size_request( Gdk.Screen.width() * PLAYLIST_WIDTH_PROP, 0) self.playlist_widget.show() self._playlist_box.pack_start(self.playlist_widget, expand=True, fill=True, padding=0) self._playlist_toolbar = Gtk.Toolbar() move_up = ToolButton("go-up") move_up.set_tooltip(_("Move up")) move_up.connect("clicked", self._move_up_cb) self._playlist_toolbar.insert(move_up, 0) move_down = ToolButton("go-down") move_down.set_tooltip(_("Move down")) move_down.connect("clicked", self._move_down_cb) self._playlist_toolbar.insert(move_down, 1) self._playlist_box.pack_end(self._playlist_toolbar, False, False, 0) self._video_canvas.pack_start(self._playlist_box, False, False, 0) # Create the player just once logging.debug('Instantiating GstPlayer') self.player = GstPlayer() self.player.connect('eos', self.__player_eos_cb) self.player.connect('error', self.__player_error_cb) self.player.connect('play', self.__player_play_cb) self.control = Controls(self, toolbar_box.toolbar, self._control_toolbar) self._separator = Gtk.SeparatorToolItem() self._separator.props.draw = False self._separator.set_expand(True) self._separator.show() toolbar_box.toolbar.insert(self._separator, -1) self._stop = StopButton(self) toolbar_box.toolbar.insert(self._stop, -1) self._empty_widget = Gtk.Label(label="") self._empty_widget.show() self.videowidget = VideoWidget() self.set_canvas(self._video_canvas) self._init_view_area() self.show_all() if len(self.playlist_widget) < 2: self._view_toolbar._show_playlist.props.active = False self._configure_cb() self.player.init_view_area(self.videowidget) self._volume_monitor = Gio.VolumeMonitor.get() self._volume_monitor.connect('mount-added', self.__mount_added_cb) self._volume_monitor.connect('mount-removed', self.__mount_removed_cb) if handle.object_id is None: # The activity was launched from scratch. We need to show # the Empty Widget self.playlist_widget.hide() emptypanel.show(self, 'activity-jukebox', _('No media'), _('Choose media files'), self.control.show_picker_cb) self.control.check_if_next_prev() Gdk.Screen.get_default().connect('size-changed', self._configure_cb) def _move_up_cb(self, button): self.playlist_widget.move_up() def _move_down_cb(self, button): self.playlist_widget.move_down() def _configure_cb(self, event=None): toolbar = self.get_toolbar_box().toolbar toolbar.remove(self._stop) toolbar.remove(self._separator) if Gdk.Screen.width() < Gdk.Screen.height(): self._control_toolbar_button.show() self._control_toolbar_button.set_expanded(True) self.control.update_layout(landscape=False) toolbar.insert(self._separator, -1) else: self._control_toolbar_button.set_expanded(False) self._control_toolbar_button.hide() self.control.update_layout(landscape=True) toolbar.insert(self._stop, -1) def __notify_active_cb(self, widget, event): """Sugar notify us that the activity is becoming active or inactive. When we are inactive, we stop the player if it is reproducing a video. """ logging.debug('JukeboxActivity notify::active signal received') if self.player.player.props.current_uri is not None and \ self.player.playing_video(): if not self.player.is_playing() and self.props.active: self.player.play() if self.player.is_playing() and not self.props.active: self.player.pause() def _init_view_area(self): """ Use a notebook with two pages, one empty an another with the videowidget """ self.view_area = Gtk.Notebook() self.view_area.set_show_tabs(False) self.view_area.append_page(self._empty_widget, None) self.view_area.append_page(self.videowidget, None) self._video_canvas.pack_end(self.view_area, expand=True, fill=True, padding=0) def _switch_canvas(self, show_video): """Show or hide the video visualization in the canvas. When hidden, the canvas is filled with an empty widget to ensure redrawing. """ if show_video: self.view_area.set_current_page(1) else: self.view_area.set_current_page(0) self._video_canvas.queue_draw() def __key_press_event_cb(self, widget, event): key = event.keyval ctrl = event.state & Gdk.ModifierType.CONTROL_MASK # while activity toolbar is visible, only escape key is taken if self._activity_toolbar_button.is_expanded(): if key == Gdk.KEY_Escape: self._activity_toolbar_button.set_expanded(False) return True return False # while title is focused, no shortcuts if self.title_entry.has_focus(): return False # Shortcut - Space does play or pause if key == Gdk.KEY_space: self.control.button.emit('clicked') return True # Shortcut - Up does previous playlist item if key == Gdk.KEY_Up: self.control.prev_button.emit('clicked') return True # Shortcut - Down does next playlist item if key == Gdk.KEY_Down: self.control.next_button.emit('clicked') return True # Shortcut - Escape does unfullscreen, then playlist hide if key == Gdk.KEY_Escape: if self.is_fullscreen(): # sugar3.graphics.Window.__key_press_cb will handle it return False if self._view_toolbar._show_playlist.props.active: self._view_toolbar._show_playlist.props.active = False return True # Shortcut - ctrl-f does fullscreen toggle # (fullscreen enable is handled by ToolButton accelerator) if ctrl and key == Gdk.KEY_f: if self.is_fullscreen(): self.unfullscreen() return True # Shortcut - ctrl-l does playlist toggle # (ToggleToolButton accelerator ineffective when ViewToolbar hidden) if ctrl and key == Gdk.KEY_l: togglebutton = self._view_toolbar._show_playlist togglebutton.props.active = not togglebutton.props.active return True return False def __playlist_finished_cb(self, widget): self._switch_canvas(show_video=False) self._view_toolbar._show_playlist.props.active = True self.unfullscreen() # Select the first stream to be played when Play button will # be pressed self.playlist_widget.set_current_playing(0) self.control.check_if_next_prev() def songchange(self, direction): current_playing = self.playlist_widget.get_current_playing() if direction == 'prev' and current_playing > 0: self.play_index(current_playing - 1) elif direction == 'next' and \ current_playing < len(self.playlist_widget._items) - 1: self.play_index(current_playing + 1) else: self.emit('playlist-finished') def play_index(self, index): # README: this line is no more necessary because of the # .playing_video() method # self._switch_canvas(show_video=True) self.playlist_widget.set_current_playing(index) path = self.playlist_widget._items[index]['path'] if self.playlist_widget.check_available_media(path): if self.playlist_widget.is_from_journal(path): path = self.playlist_widget.get_path_from_journal(path) self.control.check_if_next_prev() self.player.set_uri(path) self.player.play() else: self.songchange('next') def __play_index_cb(self, widget, index, path): # README: this line is no more necessary because of the # .playing_video() method # self._switch_canvas(show_video=True) self.playlist_widget.set_current_playing(index) if self.playlist_widget.is_from_journal(path): path = self.playlist_widget.get_path_from_journal(path) self.control.check_if_next_prev() self.player.set_uri(path) self.player.play() def __player_eos_cb(self, widget): self.songchange('next') def _show_error_alert(self, title, msg=None): self._alert = ErrorAlert() self._alert.props.title = title if msg is not None: self._alert.props.msg = msg self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show() def __mount_added_cb(self, volume_monitor, device): logging.debug('Mountpoint added. Checking...') self.remove_alert(self._alert) self.playlist_widget.update() def __mount_removed_cb(self, volume_monitor, device): logging.debug('Mountpoint removed. Checking...') self.remove_alert(self._alert) self.playlist_widget.update() def __missing_tracks_cb(self, widget, tracks): self._show_missing_tracks_alert(tracks) def _show_missing_tracks_alert(self, tracks): self._alert = Alert() title = _('%s tracks not found.') % len(tracks) self._alert.props.title = title icon = Icon(icon_name='dialog-cancel') self._alert.add_button(Gtk.ResponseType.CANCEL, _('Dismiss'), icon) icon.show() icon = Icon(icon_name='dialog-ok') self._alert.add_button(Gtk.ResponseType.APPLY, _('Details'), icon) icon.show() self.add_alert(self._alert) self._alert.connect( 'response', self.__missing_tracks_alert_response_cb, tracks) def __missing_tracks_alert_response_cb(self, alert, response_id, tracks): if response_id == Gtk.ResponseType.APPLY: vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) vbox.props.valign = Gtk.Align.CENTER label = Gtk.Label(label='') label.set_markup(_('<b>Missing tracks</b>')) vbox.pack_start(label, False, False, 15) for track in tracks: label = Gtk.Label(label=track['path']) vbox.add(label) _missing_tracks = Gtk.ScrolledWindow() _missing_tracks.add_with_viewport(vbox) _missing_tracks.show_all() self.view_area.append_page(_missing_tracks, None) self.view_area.set_current_page(2) self.remove_alert(alert) def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) def __player_play_cb(self, widget): self._switch_canvas(True) def __player_error_cb(self, widget, message, detail): self.player.stop() self.control.set_disabled() logging.error('ERROR MESSAGE: %s', message) logging.error('ERROR DETAIL: %s', detail) file_path = self.playlist_widget._items[ self.playlist_widget.get_current_playing()]['path'] mimetype = mime.get_for_file(file_path) title = _('Error') msg = _('This "%s" file can\'t be played') % mimetype self._switch_canvas(False) self._show_error_alert(title, msg) def can_close(self): # We need to put the Gst.State in NULL so gstreamer can # cleanup the pipeline self.player.stop() return True def read_file(self, file_path): """Load a file from the datastore on activity start.""" logging.debug('JukeboxActivity.read_file: %s', file_path) title = self.metadata['title'] self.playlist_widget.load_file(file_path, title) def write_file(self, file_path): def write_playlist_to_file(file_path): """Open the file at file_path and write the playlist. It is saved in audio/x-mpegurl format. """ list_file = open(file_path, 'w') for uri in self.playlist_widget._items: list_file.write('#EXTINF:%s\n' % uri['title']) list_file.write('%s\n' % uri['path']) list_file.close() if not self.metadata['mime_type']: self.metadata['mime_type'] = 'audio/x-mpegurl' if self.metadata['mime_type'] == 'audio/x-mpegurl': write_playlist_to_file(file_path) else: if self._playlist_jobject is None: self._playlist_jobject = \ self.playlist_widget.create_playlist_jobject() # Add the playlist to the playlist jobject description. # This is only done if the activity was not started from a # playlist or from scratch: description = '' for uri in self.playlist_widget._items: description += '%s\n' % uri['title'] self._playlist_jobject.metadata['description'] = description write_playlist_to_file(self._playlist_jobject.file_path) datastore.write(self._playlist_jobject) def unfullscreen(self): activity.Activity.unfullscreen(self) if self._on_unfullscreen_show_playlist: self._view_toolbar._show_playlist.props.active = True def __go_fullscreen_cb(self, toolbar): if self._view_toolbar._show_playlist.props.active: self._view_toolbar._show_playlist.props.active = False self._on_unfullscreen_show_playlist = True self.fullscreen() def __toggle_playlist_cb(self, toolbar): if self._view_toolbar._show_playlist.props.active: self._playlist_box.show_all() else: self._playlist_box.hide() self._video_canvas.queue_draw()
def __init__(self, activity): self._activity = activity ToolbarBox.__init__(self) activity_button = ActivityToolbarButton(self._activity) self.toolbar.insert(activity_button, -1) self._activity.set_toolbar_box(self) edit_toolbar = ToolbarButton() edit_toolbar.props.page = DrawEditToolbar(self._activity) edit_toolbar.props.icon_name = 'toolbar-edit' edit_toolbar.props.label = _('Edit') self.toolbar.insert(edit_toolbar, -1) self._fill_color_button = ButtonFillColor(activity) self._fill_color_button.set_title(_('Shapes properties')) item_fill_color = Gtk.ToolItem() item_fill_color.add(self._fill_color_button) self._fill_color_button.set_sensitive(False) self._activity.tool_group = None self.tools_builder = ToolsToolbarBuilder(self.toolbar, self._activity, self._fill_color_button) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.toolbar.insert(separator, -1) self.shapes_button = DrawToolButton('shapes', self._activity.tool_group, _('Shapes')) self.toolbar.insert(self.shapes_button, -1) self.shapes_builder = ShapesToolbarBuilder(self._activity, self.shapes_button, self._fill_color_button) self.initialize_brush_shape_tools() self.toolbar.insert(item_fill_color, -1) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.toolbar.insert(separator, -1) fonts_button = ToolbarButton() fonts_button.props.page = TextToolbar(self._activity) fonts_button.props.icon_name = 'format-text-size' fonts_button.props.label = _('Fonts') self.toolbar.insert(fonts_button, -1) image_button = ToolbarButton() image_button.props.page = ImageToolbar(self._activity) image_button.props.icon_name = 'picture' image_button.props.label = _('Image') self.toolbar.insert(image_button, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) self.toolbar.insert(separator, -1) separator.show() stop = StopButton(self._activity) self.toolbar.insert(stop, -1) # TODO: workaround # the BrushButton does not starts self.brush_button = self.tools_builder._stroke_color.color_button area = self._activity.area self.brush_button.set_brush_shape(area.tool['line shape']) self.brush_button.set_brush_size(area.tool['line size']) self.brush_button.set_stamp_size(area.tool['stamp size']) # init the color cairo_stroke_color = area.tool['cairo_stroke_color'] red = cairo_stroke_color[0] * 65535 green = cairo_stroke_color[1] * 65535 blue = cairo_stroke_color[2] * 65535 stroke_color = Gdk.Color(red, green, blue) self.brush_button.set_color(stroke_color) self.tools_builder.color_brush(stroke_color)
class TrainingActivity(activity.Activity): ''' A series of training exercises ''' transfer_started_signal = GObject.Signal('started', arg_types=([])) transfer_progressed_signal = GObject.Signal('progressed', arg_types=([])) transfer_completed_signal = GObject.Signal('completed', arg_types=([])) transfer_failed_signal = GObject.Signal('failed', arg_types=([])) def __init__(self, handle): ''' Initialize the toolbars and the game board ''' try: super(TrainingActivity, self).__init__(handle) except dbus.exceptions.DBusException as e: _logger.error(str(e)) self.connect('realize', self.__realize_cb) self.connect('started', self.__transfer_started_cb) self.connect('progressed', self.__transfer_progressed_cb) self.connect('completed', self.__transfer_completed_cb) self.connect('failed', self.__transfer_failed_cb) self.volume_monitor = Gio.VolumeMonitor.get() self.volume_monitor.connect('mount-added', self._mount_added_cb) self.volume_monitor.connect('mount-removed', self._mount_removed_cb) if hasattr(self, 'metadata') and 'font_size' in self.metadata: self.font_size = int(self.metadata['font_size']) else: self.font_size = 8 self.zoom_level = self.font_size / float(len(FONT_SIZES)) _logger.debug('zoom level is %f' % self.zoom_level) _check_gconf_settings() # For debugging purposes self._setup_toolbars() self.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) self.bundle_path = activity.get_bundle_path() self.volume_data = [] self.help_palette = None self.help_panel_visible = False self._copy_entry = None self._paste_entry = None self._webkit = None self._clipboard_text = '' self._fixed = None self._notify_transfer_status = False if self._load_extension() and self.check_volume_data(): self._launcher() def _launcher(self): get_power_manager().inhibit_suspend() # We are resuming the activity or we are launching a new instance? # * Is there a data file to sync on the USB key? # * Do we create a new data file on the USB key? path = self._check_for_USB_data() if path is None: self._launch_task_master() elif self._sync_data_from_USB(path): self._copy_data_from_USB() # Flash a welcome back screen. self._load_intro_graphics(file_name='welcome-back.html') GObject.timeout_add(1500, self._launch_task_master) def can_close(self): get_power_manager().restore_suspend() return True def busy_cursor(self): self._old_cursor = self.get_window().get_cursor() self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) def reset_cursor(self): if hasattr(self, '_old_cursor'): self.get_window().set_cursor(self._old_cursor) def check_volume_data(self): # Before we begin (and before each task), # we need to find any and all USB keys # and any and all training-data files on them. _logger.debug(utils.get_volume_paths()) self.volume_data = [] for path in utils.get_volume_paths(): os.path.basename(path) self.volume_data.append( {'basename': os.path.basename(path), 'files': utils.look_for_training_data(path), 'sugar_path': os.path.join(self.get_activity_root(), 'data'), 'usb_path': path}) _logger.debug(self.volume_data[-1]) # (1) We require a USB key if len(self.volume_data) == 0: _logger.error('NO USB KEY INSERTED') alert = ConfirmationAlert() alert.props.title = _('USB key required') alert.props.msg = _('You must insert a USB key before launching ' 'this activity.') alert.connect('response', self._remove_alert_cb) self.add_alert(alert) self._load_intro_graphics(file_name='insert-usb.html') return False # (2) Only one USB key if len(self.volume_data) > 1: _logger.error('MULTIPLE USB KEYS INSERTED') alert = ConfirmationAlert() alert.props.title = _('Multiple USB keys found') alert.props.msg = _('Only one USB key must be inserted while ' 'running this program.\nPlease remove any ' 'additional USB keys before launching ' 'this activity.') alert.connect('response', self._remove_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False volume = self.volume_data[0] # (3) At least 10MB of free space if utils.is_full(volume['usb_path'], required=_MINIMUM_SPACE): _logger.error('USB IS FULL') alert = ConfirmationAlert() alert.props.title = _('USB key is full') alert.props.msg = _('No room on USB') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False # (4) File is read/write if not utils.is_writeable(volume['usb_path']): _logger.error('CANNOT WRITE TO USB') alert = ConfirmationAlert() alert.props.title = _('Cannot write to USB') alert.props.msg = _('USB key seems to be read-only.') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False # (5) Only one set of training data per USB key # We expect UIDs to formated as XXXX-XXXX # We need to make sure we have proper UIDs associated with # the USBs and the files on them match the UID. # (a) If there are no files, we will assign the UID based on the # volume path; # (b) If there is one file with a valid UID, we use that UID; if len(volume['files']) == 0: volume['uid'] = 'training-data-%s' % \ utils.format_volume_name(volume['basename']) _logger.debug('No training data found. Using UID %s' % volume['uid']) return True elif len(volume['files']) == 1: volume['uid'] = 'training-data-%s' % volume['files'][0][-9:] _logger.debug('Training data found. Using UID %s' % volume['uid']) return True else: _logger.error('MULTIPLE TRAINING-DATA FILES FOUND') alert = ConfirmationAlert() alert.props.title = _('Multiple training-data files found.') alert.props.msg = _('There can only be one set of training ' 'data per USB key.') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False def _check_for_USB_data(self): usb_path = os.path.join(self.volume_data[0]['usb_path'], self.volume_data[0]['uid']) if os.path.exists(usb_path): return usb_path else: return None def _sync_data_from_USB(self, usb_data_path=None): # We need to sync up file on USB with file on disk, # but only if the email addresses match. Otherwise, # raise an error. if usb_data_path is not None: usb_data = {} if os.path.exists(usb_data_path): fd = open(usb_data_path, 'r') json_data = fd.read() fd.close() if len(json_data) > 0: try: usb_data = json.loads(json_data) except ValueError as e: _logger.error('Cannot load USB data: %s' % e) else: _logger.error('Cannot find USB data: %s' % usb_data_path) sugar_data_path = os.path.join( self.volume_data[0]['sugar_path'], self.volume_data[0]['uid']) sugar_data = {} if os.path.exists(sugar_data_path): fd = open(sugar_data_path, 'r') json_data = fd.read() fd.close() if len(json_data) > 0: try: sugar_data = json.loads(json_data) except ValueError as e: _logger.error('Cannot load Sugar data: %s' % e) else: _logger.error('Cannot find Sugar data: %s' % sugar_data_path) # First, check to make sure email_address matches if EMAIL_UID in usb_data: usb_email = usb_data[EMAIL_UID] else: usb_email = None if EMAIL_UID in sugar_data: sugar_email = sugar_data[EMAIL_UID] else: sugar_email = None if usb_email != sugar_email: if usb_email is None and sugar_email is not None: _logger.warning('Using email address from Sugar: %s' % sugar_email) usb_data[EMAIL_UID] = sugar_email elif usb_email is not None and sugar_email is None: _logger.warning('Using email address from USB: %s' % usb_email) sugar_data[EMAIL_UID] = usb_email elif usb_email is None and sugar_email is None: _logger.warning('No email address found') else: # FIX ME: We need to resolve this, but for right now, punt. alert = ConfirmationAlert() alert.props.title = _('Data mismatch') alert.props.msg = _('Are you %(usb)s or %(sugar)s?' % {'usb': usb_email, 'sugar': sugar_email}) alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False def count_completed(data): count = 0 for key in data: if isinstance(data[key], dict) and \ 'completed' in data[key] and \ data[key]['completed']: count += 1 return count # The database with the most completed tasks takes precedence. if count_completed(usb_data) >= count_completed(sugar_data): _logger.debug('data sync: USB data takes precedence') data_one = usb_data data_two = sugar_data else: _logger.debug('data sync: Sugar data takes precedence') data_one = sugar_data data_two = usb_data # Copy completed tasks from one to two for key in data_one: if isinstance(data_one[key], dict) and \ 'completed' in data_one[key] and \ data_one[key]['completed']: data_two[key] = data_one[key] # Copy completed tasks from two to one for key in data_two: if isinstance(data_two[key], dict) and \ 'completed' in data_two[key] and \ data_two[key]['completed']: data_one[key] = data_two[key] # Copy incompleted tasks from one to two for key in data_one: if isinstance(data_one[key], dict) and \ (not 'completed' in data_one[key] or not data_one[key]['completed']): data_two[key] = data_one[key] # Copy incompleted tasks from two to one for key in data_two: if isinstance(data_two[key], dict) and \ (not 'completed' in data_two[key] or not data_two[key]['completed']): data_one[key] = data_two[key] # Copy name, email_address, current_task... for key in data_one: if not isinstance(data_one[key], dict): data_two[key] = data_one[key] for key in data_two: if not isinstance(data_two[key], dict): data_one[key] = data_two[key] # Finally, write to the USB and ... json_data = json.dumps(data_one) fd = open(usb_data_path, 'w') fd.write(json_data) fd.close() # ...save a shadow copy in Sugar fd = open(sugar_data_path, 'w') fd.write(json_data) fd.close() return True else: _logger.error('No data to sync on USB') return False def _copy_data_from_USB(self): usb_path = self._check_for_USB_data() if usb_path is not None: try: subprocess.call(['cp', usb_path, self.volume_data[0]['sugar_path']]) except OSError as e: _logger.error('Could not copy %s to %s: %s' % ( usb_path, self.volume_data[0]['sugar_path'], e)) else: _logger.error('No data found on USB') def toolbar_expanded(self): if self.activity_button.is_expanded(): return True elif self.edit_toolbar_button.is_expanded(): return True elif self.view_toolbar_button.is_expanded(): return True elif hasattr(self, 'progress_toolbar_button') and \ self.progress_toolbar_button.is_expanded(): return True def _launch_task_master(self): # Most things need only be done once if self._fixed is None: self._fixed = Gtk.Fixed() self._fixed.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) # Offsets from the bottom of the screen dy1 = 3 * style.GRID_CELL_SIZE dy2 = 2 * style.GRID_CELL_SIZE self._progress_area = Gtk.Alignment.new(0.5, 0, 0, 0) self._progress_area.set_size_request(Gdk.Screen.width(), -1) self._fixed.put(self._progress_area, 0, Gdk.Screen.height() - dy2) self._progress_area.show() self._button_area = Gtk.Alignment.new(0.5, 0, 0, 0) self._button_area.set_size_request(Gdk.Screen.width(), -1) self._fixed.put(self._button_area, 0, Gdk.Screen.height() - dy1) self._button_area.show() self._scrolled_window = Gtk.ScrolledWindow() self._scrolled_window.set_size_request( Gdk.Screen.width(), Gdk.Screen.height() - dy1) self._set_scroll_policy() self._graphics_area = Gtk.Alignment.new(0.5, 0, 0, 0) self._scrolled_window.add_with_viewport(self._graphics_area) self._graphics_area.show() self._fixed.put(self._scrolled_window, 0, 0) self._scrolled_window.show() self._task_master = TaskMaster(self) self._task_master.show() # Now that we have the tasks, we can build the progress toolbar and # help panel. self._build_progress_toolbar() self._help_panel = HelpPanel(self._task_master) self.help_palette = self._help_button.get_palette() self.help_palette.set_content(self._help_panel) self._help_panel.show() self._help_button.set_sensitive(True) Gdk.Screen.get_default().connect('size-changed', self._configure_cb) self._toolbox.connect('hide', self._resize_hide_cb) self._toolbox.connect('show', self._resize_show_cb) self._task_master.set_events(Gdk.EventMask.KEY_PRESS_MASK) self._task_master.connect('key_press_event', self._task_master.keypress_cb) self._task_master.set_can_focus(True) self._task_master.grab_focus() self.set_canvas(self._fixed) self._fixed.show() self.completed = False self._update_completed_sections() self._check_connected_task_status() self._task_master.task_master() def load_graphics_area(self, widget): self._graphics_area.add(widget) def load_button_area(self, widget): self._button_area.add(widget) def load_progress_area(self, widget): self._progress_area.add(widget) def _load_intro_graphics(self, file_name='generic-problem.html', message=None): center_in_panel = Gtk.Alignment.new(0.5, 0, 0, 0) url = os.path.join(self.bundle_path, 'html-content', file_name) graphics = Graphics() if message is None: graphics.add_uri('file://' + url) else: graphics.add_uri('file://' + url + '?MSG=' + utils.get_safe_text(message)) graphics.set_zoom_level(0.667) center_in_panel.add(graphics) graphics.show() self.set_canvas(center_in_panel) center_in_panel.show() def _resize_hide_cb(self, widget): self._resize_canvas(widget, True) def _resize_show_cb(self, widget): self._resize_canvas(widget, False) def _configure_cb(self, event): self._fixed.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self._set_scroll_policy() self._resize_canvas(None) self._task_master.reload_graphics() def _resize_canvas(self, widget, fullscreen=False): # When a toolbar is expanded or collapsed, resize the canvas # to ensure that the progress bar is still visible. if hasattr(self, '_task_master'): if self.toolbar_expanded(): dy1 = 4 * style.GRID_CELL_SIZE dy2 = 3 * style.GRID_CELL_SIZE else: dy1 = 3 * style.GRID_CELL_SIZE dy2 = 2 * style.GRID_CELL_SIZE if fullscreen: dy1 -= 2 * style.GRID_CELL_SIZE dy2 -= 2 * style.GRID_CELL_SIZE self._scrolled_window.set_size_request( Gdk.Screen.width(), Gdk.Screen.height() - dy1) self._fixed.move(self._progress_area, 0, Gdk.Screen.height() - dy2) self._fixed.move(self._button_area, 0, Gdk.Screen.height() - dy1) self.help_panel_visible = False def get_activity_version(self): info_path = os.path.join(self.bundle_path, 'activity', 'activity.info') try: info_file = open(info_path, 'r') except Exception as e: _logger.error('Could not open %s: %s' % (info_path, e)) return 'unknown' cp = ConfigParser() cp.readfp(info_file) section = 'Activity' if cp.has_option(section, 'activity_version'): activity_version = cp.get(section, 'activity_version') else: activity_version = 'unknown' return activity_version def get_uid(self): if len(self.volume_data) == 1: return self.volume_data[0]['uid'] else: return 'unknown' def write_file(self, file_path): # Only write if we have a valid USB/data file to work with. if len(self.volume_data) == 1 and \ len(self.volume_data[0]['files']) == 1: self.metadata[TRAINING_DATA_UID] = self.volume_data[0]['uid'] # We may have failed before getting to init of taskmaster if hasattr(self, '_task_master'): self._task_master.write_task_data( 'current_task', self._task_master.current_task) self.update_activity_title() email = self._task_master.read_task_data(EMAIL_UID) if email is None: email = '' self.metadata[TRAINING_DATA_EMAIL] = email name = self._task_master.read_task_data(NAME_UID) if name is None: name = '' self.metadata[TRAINING_DATA_FULLNAME] = name self.metadata['font_size'] = str(self.font_size) def update_activity_title(self): name = self._task_master.read_task_data(NAME_UID) if name is not None: bundle_name = activity.get_bundle_name() self.metadata['title'] = _('%(name)s %(bundle)s Activity') % \ {'name': name, 'bundle': bundle_name} def _setup_toolbars(self): ''' Setup the toolbars. ''' self.max_participants = 1 # No sharing self._toolbox = ToolbarBox() self.activity_button = ActivityToolbarButton(self) self.activity_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.activity_button, 0) self.activity_button.show() self.set_toolbar_box(self._toolbox) self._toolbox.show() self.toolbar = self._toolbox.toolbar view_toolbar = Gtk.Toolbar() self.view_toolbar_button = ToolbarButton( page=view_toolbar, label=_('View'), icon_name='toolbar-view') self.view_toolbar_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.view_toolbar_button, 1) view_toolbar.show() self.view_toolbar_button.show() button = ToolButton('view-fullscreen') button.set_tooltip(_('Fullscreen')) button.props.accelerator = '<Alt>Return' view_toolbar.insert(button, -1) button.show() button.connect('clicked', self._fullscreen_cb) self._zoom_in = ToolButton('zoom-in') self._zoom_in.set_tooltip(_('Increase size')) view_toolbar.insert(self._zoom_in, -1) self._zoom_in.show() self._zoom_in.connect('clicked', self._zoom_in_cb) self._zoom_out = ToolButton('zoom-out') self._zoom_out.set_tooltip(_('Decrease size')) view_toolbar.insert(self._zoom_out, -1) self._zoom_out.show() self._zoom_out.connect('clicked', self._zoom_out_cb) self._zoom_eq = ToolButton('zoom-original') self._zoom_eq.set_tooltip(_('Restore original size')) view_toolbar.insert(self._zoom_eq, -1) self._zoom_eq.show() self._zoom_eq.connect('clicked', self._zoom_eq_cb) self._set_zoom_buttons_sensitivity() edit_toolbar = Gtk.Toolbar() self.edit_toolbar_button = ToolbarButton( page=edit_toolbar, label=_('Edit'), icon_name='toolbar-edit') self.edit_toolbar_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.edit_toolbar_button, 1) edit_toolbar.show() self.edit_toolbar_button.show() self._copy_button = ToolButton('edit-copy') self._copy_button.set_tooltip(_('Copy')) self._copy_button.props.accelerator = '<Ctrl>C' edit_toolbar.insert(self._copy_button, -1) self._copy_button.show() self._copy_button.connect('clicked', self._copy_cb) self._copy_button.set_sensitive(False) self._paste_button = ToolButton('edit-paste') self._paste_button.set_tooltip(_('Paste')) self._paste_button.props.accelerator = '<Ctrl>V' edit_toolbar.insert(self._paste_button, -1) self._paste_button.show() self._paste_button.connect('clicked', self._paste_cb) self._paste_button.set_sensitive(False) self._progress_toolbar = Gtk.Toolbar() self.progress_toolbar_button = ToolbarButton( page=self._progress_toolbar, label=_('Check progress'), icon_name='check-progress') self.progress_toolbar_button.connect('clicked', self._resize_canvas) self._toolbox.toolbar.insert(self.progress_toolbar_button, -1) self._progress_toolbar.show() self.progress_toolbar_button.show() self._help_button = ToolButton('toolbar-help') self._help_button.set_tooltip(_('Help')) self._help_button.props.accelerator = '<Ctrl>H' self._toolbox.toolbar.insert(self._help_button, -1) self._help_button.show() self._help_button.connect('clicked', self._help_cb) self._help_button.set_sensitive(False) self._help_button.palette_invoker.props.lock_palette = True self.transfer_button = ToolButton('transfer') self.transfer_button.set_tooltip(_('Training data upload status')) self._toolbox.toolbar.insert(self.transfer_button, -1) self.transfer_button.connect('clicked', self._transfer_cb) self.transfer_button.hide() self.progress_label = Gtk.Label() self.progress_label.set_line_wrap(True) self.progress_label.set_size_request(300, -1) self.progress_label.set_use_markup(True) toolitem = Gtk.ToolItem() toolitem.add(self.progress_label) self.progress_label.show() self._toolbox.toolbar.insert(toolitem, -1) toolitem.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self._toolbox.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' self._toolbox.toolbar.insert(stop_button, -1) stop_button.show() def _build_progress_toolbar(self): self._progress_buttons = [] progress = self._task_master.get_completed_sections() for section_index in range(self._task_master.get_number_of_sections()): icon = self._task_master.get_section_icon(section_index) if section_index in progress: icon = icon + '-white' else: icon = icon + '-grey' name = self._task_master.get_section_name(section_index) if section_index == 0: group = None else: group = self._progress_buttons[0] self._progress_buttons.append(RadioToolButton(group=group)) self._progress_buttons[-1].set_icon_name(icon) self._progress_buttons[-1].set_tooltip(name) self._progress_toolbar.insert(self._progress_buttons[-1], -1) self._progress_buttons[-1].show() self._progress_buttons[-1].connect( 'clicked', self._jump_to_section_cb, section_index) self._radio_buttons_live = False section_index, task_index = \ self._task_master.get_section_and_task_index() self._progress_buttons[section_index].set_active(True) self._radio_buttons_live = True def _check_connected_task_status(self): ''' We only want to turn on notifications if we expect connectivity ''' task = self._task_master.uid_to_task(GET_CONNECTED_TASK) self.set_notify_transfer_status(task.is_completed()) def _update_completed_sections(self): progress = self._task_master.get_completed_sections() for section in range(self._task_master.get_number_of_sections()): icon = self._task_master.get_section_icon(section) if section in progress: icon = icon + '-white' else: icon = icon + '-grey' self._progress_buttons[section].set_icon_name(icon) self._radio_buttons_live = False section_index, task_index = \ self._task_master.get_section_and_task_index() self._progress_buttons[section_index].set_active(True) self._radio_buttons_live = True def mark_section_as_complete(self, section): icon = self._task_master.get_section_icon(section) + '-white' self._progress_buttons[section].set_icon_name(icon) if section < self._task_master.get_number_of_sections() - 1: self._radio_buttons_live = False self._progress_buttons[section + 1].set_active(True) self._radio_buttons_live = True def set_notify_transfer_status(self, state): _logger.debug('Setting transfer status to %s' % (str(state))) self._notify_transfer_status = state def _update_transfer_button(self, icon_name, tooltip): self.transfer_button.set_icon_name(icon_name) self.transfer_button.set_tooltip(tooltip) if self._notify_transfer_status: self.transfer_button.show() else: self.transfer_button.hide() def _transfer_cb(self, button): ''' Hide the button to dismiss notification ''' self.transfer_button.set_tooltip(_('Training data upload status')) self.transfer_button.hide() def __transfer_started_cb(self, widget): self._update_transfer_button('transfer', _('Data transfer started')) def __transfer_progressed_cb(self, widget): self._update_transfer_button('transfer', _('Data transfer progressing')) def __transfer_completed_cb(self, widget): self._update_transfer_button('transfer-complete', _('Data transfer completed')) def __transfer_failed_cb(self, widget): self._update_transfer_button('transfer-failed', _('Data transfer failed')) def __realize_cb(self, window): self.window_xid = window.get_window().get_xid() def set_copy_widget(self, webkit=None, text_entry=None): # Each task is responsible for setting a widget for copy if webkit is not None: self._webkit = webkit else: self._webkit = None if text_entry is not None: self._copy_entry = text_entry else: self._copy_entry = None self._copy_button.set_sensitive(webkit is not None or text_entry is not None) def _copy_cb(self, button): if self._copy_entry is not None: self._copy_entry.copy_clipboard() elif self._webkit is not None: self._webkit.copy_clipboard() else: _logger.debug('No widget set for copy.') def set_paste_widget(self, text_entry=None): # Each task is responsible for setting a widget for paste if text_entry is not None: self._paste_entry = text_entry self._paste_button.set_sensitive(text_entry is not None) def _paste_cb(self, button): clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self.clipboard_text = clipboard.wait_for_text() if self._paste_entry is not None: self._paste_entry.paste_clipboard() else: _logger.debug('No widget set for paste (%s).' % self.clipboard_text) def _fullscreen_cb(self, button): ''' Hide the Sugar toolbars. ''' self.fullscreen() def _set_zoom_buttons_sensitivity(self): if self.font_size < len(FONT_SIZES) - 1: self._zoom_in.set_sensitive(True) else: self._zoom_in.set_sensitive(False) if self.font_size > 0: self._zoom_out.set_sensitive(True) else: self._zoom_out.set_sensitive(False) if hasattr(self, '_scrolled_window'): self._set_scroll_policy() def _set_scroll_policy(self): if Gdk.Screen.width() < Gdk.Screen.height() or self.zoom_level > 0.667: self._scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) else: self._scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) def _zoom_eq_cb(self, button): self.font_size = 8 self.zoom_level = 0.667 self._set_zoom_buttons_sensitivity() self._task_master.reload_graphics() def _zoom_in_cb(self, button): if self.font_size < len(FONT_SIZES) - 1: self.font_size += 1 self.zoom_level *= 1.1 self._set_zoom_buttons_sensitivity() self._task_master.reload_graphics() def _zoom_out_cb(self, button): if self.font_size > 0: self.font_size -= 1 self.zoom_level /= 1.1 self._set_zoom_buttons_sensitivity() self._task_master.reload_graphics() def _jump_to_section_cb(self, button, section_index): if self._radio_buttons_live: if self._task_master.requirements_are_met(section_index, 0): uid = self._task_master.section_and_task_to_uid(section_index) self._task_master.current_task = \ self._task_master.uid_to_task_number(uid) self._task_master.reload_graphics() else: section_index, task_index = \ self._task_master.get_section_and_task_index() self._progress_buttons[section_index].set_active(True) def _help_cb(self, button): # title, help_file = self._task_master.get_help_info() # _logger.debug('%s: %s' % (title, help_file)) # if not hasattr(self, 'window_xid'): # self.window_xid = self.get_window().get_xid() # if title is not None and help_file is not None: # self.viewhelp = ViewHelp(title, help_file, self.window_xid) # self.viewhelp.show() try: self._help_panel.set_connected( utils.nm_status() == 'network-wireless-connected') except Exception as e: _logger.error('Could not read NM status: %s' % (e)) self._help_panel.set_connected(False) if self.help_palette: # FIXME: is_up() is always returning False, so we # "debounce" using help_panel_visible. if not self.help_palette.is_up() and not self.help_panel_visible: self.help_palette.popup( immediate=True, state=self.help_palette.SECONDARY) self.help_panel_visible = True else: self.help_palette.popdown(immediate=True) self.help_panel_visible = False self._help_button.set_expanded(False) def add_badge(self, msg, icon="training-trophy", name="One Academy"): sugar_icons = os.path.join(os.path.expanduser('~'), '.icons') if not os.path.exists(sugar_icons): try: subprocess.call(['mkdir', sugar_icons]) except OSError as e: _logger.error('Could not mkdir %s, %s' % (sugar_icons, e)) badge = { 'icon': icon, 'from': name, 'message': msg } # Use icons from html-content directory since default colors are # intended for white background. icon_dir = os.path.join(self.bundle_path, 'html-content', 'images') icon_path = os.path.join(icon_dir, icon + '.svg') try: subprocess.call(['cp', icon_path, sugar_icons]) except OSError as e: _logger.error('Could not copy %s to %s, %s' % (icon_path, sugar_icons, e)) if 'comments' in self.metadata: comments = json.loads(self.metadata['comments']) comments.append(badge) self.metadata['comments'] = json.dumps(comments) else: self.metadata['comments'] = json.dumps([badge]) def _load_extension(self): if not WEBSERVICES_AVAILABLE: _logger.error('Webservices not available on this version of Sugar') self._webservice_alert(_('Sugar upgrade required.')) return False extensions_path = os.path.join(os.path.expanduser('~'), '.sugar', 'default', 'extensions') webservice_path = os.path.join(extensions_path, 'webservice') sugarservices_path = os.path.join(self.bundle_path, 'sugarservices') init_path = os.path.join(self.bundle_path, 'sugarservices', '__init__.py') if not os.path.exists(extensions_path): try: subprocess.call(['mkdir', extensions_path]) except OSError as e: _logger.error('Could not mkdir %s, %s' % (extensions_path, e)) self._webservice_alert(_('System error.')) return False if not os.path.exists(webservice_path): try: subprocess.call(['mkdir', webservice_path]) except OSError as e: _logger.error('Could not mkdir %s, %s' % (webservice_path, e)) self._webservice_alert(_('System error.')) return False try: subprocess.call(['cp', init_path, webservice_path]) except OSError as e: _logger.error('Could not cp %s to %s, %s' % (init_path, webservice_path, e)) self._webservice_alert(_('System error.')) return False install = False if not os.path.exists(os.path.join(webservice_path, 'sugarservices')): _logger.error('SugarServices webservice not found. Installing...') install = True elif utils.get_sugarservices_version() < \ _REQUIRED_SUGARSERVICES_VERSION: _logger.error('Found old SugarServices version. Installing...') install = True if install: try: subprocess.call(['cp', '-r', sugarservices_path, webservice_path]) except OSError as e: _logger.error('Could not copy %s to %s, %s' % (sugarservices_path, webservice_path, e)) self._webservice_alert(_('System error.')) return False alert = ConfirmationAlert() alert.props.title = _('Restart required') alert.props.msg = _('We needed to install some software on your ' 'system.\nSugar must be restarted before ' 'sugarservices can commence.') alert.connect('response', self._reboot_alert_cb) self.add_alert(alert) self._load_intro_graphics(file_name='restart.html') return not install def _webservice_alert(self, message): alert = ConfirmationAlert() alert.props.title = message alert.props.msg = _('We are unable to install some software on your ' 'system.\nSugar must be upgraded before this ' 'activity can be run.') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=message) def _remove_alert_cb(self, alert, response_id): self.remove_alert(alert) def _close_alert_cb(self, alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: self.close() def _reboot_alert_cb(self, alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: try: utils.reboot() except Exception as e: _logger.error('Cannot reboot: %s' % e) def _mount_added_cb(self, volume_monitor, device): _logger.error('mount added') if self.check_volume_data(): _logger.debug('launching') self._launcher() def _mount_removed_cb(self, volume_monitor, device): _logger.error('mount removed') if self.check_volume_data(): _logger.debug('launching') self._launcher()
class GmailActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) _logger.debug('Starting the web activity') session = WebKit.get_default_session() session.set_property('accept-language-auto', True) session.set_property('ssl-use-system-ca-file', True) session.set_property('ssl-strict', False) # By default, cookies are not stored persistently, we have to # add a cookie jar so that they get saved to disk. We use one # with a SQlite database: cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path, read_only=False) session.add_feature(cookie_jar) # FIXME # downloadmanager.remove_old_parts() self._force_close = False self._tabbed_view = TabbedView() self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._tray = HTray() self.set_tray(self._tray, Gtk.PositionType.BOTTOM) self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) self._view_toolbar = ViewToolbar(self) self._primary_toolbar.connect('add-link', self._link_add_button_cb) self._primary_toolbar.connect('go-home', self._go_home_button_cb) self._primary_toolbar.connect('go-library', self._go_library_button_cb) self._primary_toolbar.connect('reset-home', self._reset_home_button_cb) self._edit_toolbar_button = ToolbarButton(page=self._edit_toolbar, icon_name='toolbar-edit') self._primary_toolbar.toolbar.insert(self._edit_toolbar_button, 1) view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view') self._primary_toolbar.toolbar.insert(view_toolbar_button, 2) self._primary_toolbar.show_all() self.set_toolbar_box(self._primary_toolbar) self.set_canvas(self._tabbed_view) self._tabbed_view.show() self.model = Model() self.model.connect('add_link', self._add_link_model_cb) self.connect('key-press-event', self._key_press_cb) if handle.uri: self._tabbed_view.current_browser.load_uri(handle.uri) elif not self._jobject.file_path: # TODO: we need this hack until we extend the activity API for # opening URIs and default docs. self._tabbed_view.load_homepage() self.messenger = None self.connect('shared', self._shared_cb) # Get the Presence Service self.pservice = presenceservice.get_instance() try: name, path = self.pservice.get_preferred_connection() self.tp_conn_name = name self.tp_conn_path = path self.conn = telepathy.client.Connection(name, path) except TypeError: _logger.debug('Offline') self.initiating = None if self.get_shared_activity() is not None: _logger.debug('shared: %s', self.get_shared()) # We are joining the activity _logger.debug('Joined activity') self.connect('joined', self._joined_cb) if self.get_shared(): # We've already joined self._joined_cb() else: _logger.debug('Created activity') # README: this is a workaround to remove old temp file # http://bugs.sugarlabs.org/ticket/3973 self._cleanup_temp_files() def _cleanup_temp_files(self): """Removes temporary files generated by Download Manager that were cancelled by the user or failed for any reason. There is a bug in GLib that makes this to happen: https://bugzilla.gnome.org/show_bug.cgi?id=629301 """ try: uptime_proc = open('/proc/uptime', 'r').read() uptime = int(float(uptime_proc.split()[0])) except EnvironmentError: logging.warning('/proc/uptime could not be read') uptime = None temp_path = os.path.join(self.get_activity_root(), 'instance') now = int(time.time()) cutoff = now - 24 * 60 * 60 # yesterday if uptime is not None: boot_time = now - uptime cutoff = max(cutoff, boot_time) for f in os.listdir(temp_path): if f.startswith('.goutputstream-'): fpath = os.path.join(temp_path, f) mtime = int(os.path.getmtime(fpath)) if mtime < cutoff: logging.warning('Removing old temporary file: %s', fpath) try: os.remove(fpath) except EnvironmentError: logging.error( 'Temporary file could not be ' 'removed: %s', fpath) def _on_focus_url_entry(self, gobject): self._primary_toolbar.entry.grab_focus() def _shared_cb(self, activity_): _logger.debug('My activity was shared') self.initiating = True self._setup() _logger.debug('This is my activity: making a tube...') self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _setup(self): if self.get_shared_activity() is None: _logger.debug('Failed to share or join activity') return bus_name, conn_path, channel_paths = \ self.get_shared_activity().get_channels() # Work out what our room is called and whether we have Tubes already room = None tubes_chan = None text_chan = None for channel_path in channel_paths: channel = telepathy.client.Channel(bus_name, channel_path) htype, handle = channel.GetHandle() if htype == telepathy.HANDLE_TYPE_ROOM: _logger.debug('Found our room: it has handle#%d "%s"', handle, self.conn.InspectHandles(htype, [handle])[0]) room = handle ctype = channel.GetChannelType() if ctype == telepathy.CHANNEL_TYPE_TUBES: _logger.debug('Found our Tubes channel at %s', channel_path) tubes_chan = channel elif ctype == telepathy.CHANNEL_TYPE_TEXT: _logger.debug('Found our Text channel at %s', channel_path) text_chan = channel if room is None: _logger.debug("Presence service didn't create a room") return if text_chan is None: _logger.debug("Presence service didn't create a text channel") return # Make sure we have a Tubes channel - PS doesn't yet provide one if tubes_chan is None: _logger.debug("Didn't find our Tubes channel, requesting one...") tubes_chan = self.conn.request_channel( telepathy.CHANNEL_TYPE_TUBES, telepathy.HANDLE_TYPE_ROOM, room, True) self.tubes_chan = tubes_chan self.text_chan = text_chan tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) def _list_tubes_reply_cb(self, tubes): for tube_info in tubes: self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): _logger.debug('ListTubes() failed: %s', e) def _joined_cb(self, activity_): if not self.get_shared_activity(): return _logger.debug('Joined an existing shared activity') self.initiating = False self._setup() _logger.debug('This is not my 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) def _new_tube_cb(self, identifier, initiator, type, service, params, state): _logger.debug( 'New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', identifier, 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( identifier) self.tube_conn = TubeConnection( self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], identifier, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) _logger.debug('Tube created') self.messenger = Messenger(self.tube_conn, self.initiating, self.model) def _get_data_from_file_path(self, file_path): fd = open(file_path, 'r') try: data = fd.read() finally: fd.close() return data def read_file(self, file_path): if self.metadata['mime_type'] == 'text/plain': data = self._get_data_from_file_path(file_path) self.model.deserialize(data) for link in self.model.data['shared_links']: _logger.debug('read: url=%s title=%s d=%s' % (link['url'], link['title'], link['color'])) self._add_link_totray(link['url'], base64.b64decode(link['thumb']), link['color'], link['title'], link['owner'], -1, link['hash'], link['notes']) logging.debug('########## reading %s', data) self._tabbed_view.set_history(self.model.data['history']) for number, tab in enumerate(self.model.data['currents']): tab_page = self._tabbed_view.get_nth_page(number) tab_page.browser.set_history_index(tab['history_index']) zoom_level = tab.get('zoom_level') if zoom_level is not None: tab_page.browser.set_zoom_level(zoom_level) tab_page.browser.grab_focus() self._tabbed_view.set_current_page(self.model.data['current_tab']) elif self.metadata['mime_type'] == 'text/uri-list': data = self._get_data_from_file_path(file_path) uris = mime.split_uri_list(data) if len(uris) == 1: self._tabbed_view.props.current_browser.load_uri(uris[0]) else: _logger.error('Open uri-list: Does not support' 'list of multiple uris by now.') else: file_uri = 'file://' + file_path self._tabbed_view.props.current_browser.load_uri(file_uri) self._tabbed_view.props.current_browser.grab_focus() def write_file(self, file_path): if not self.metadata['mime_type']: self.metadata['mime_type'] = 'text/plain' if self.metadata['mime_type'] == 'text/plain': browser = self._tabbed_view.current_browser if not self._jobject.metadata['title_set_by_user'] == '1': if browser.props.title is None: self.metadata['title'] = _('Untitled') else: self.metadata['title'] = browser.props.title self.model.data['history'] = self._tabbed_view.get_history() current_tab = self._tabbed_view.get_current_page() self.model.data['current_tab'] = current_tab self.model.data['currents'] = [] for n in range(0, self._tabbed_view.get_n_pages()): tab_page = self._tabbed_view.get_nth_page(n) n_browser = tab_page.browser if n_browser is not None: uri = n_browser.get_uri() history_index = n_browser.get_history_index() info = { 'title': n_browser.props.title, 'url': uri, 'history_index': history_index, 'zoom_level': n_browser.get_zoom_level() } self.model.data['currents'].append(info) f = open(file_path, 'w') try: logging.debug('########## writing %s', self.model.serialize()) f.write(self.model.serialize()) finally: f.close() def _link_add_button_cb(self, button): self._add_link() def _go_home_button_cb(self, button): self._tabbed_view.load_homepage() def _go_library_button_cb(self, button): self._tabbed_view.load_homepage(ignore_gconf=True) def _reset_home_button_cb(self, button): self._tabbed_view.reset_homepage() self._alert(_('The default initial page was configured')) def _alert(self, title, text=None): alert = NotifyAlert(timeout=5) alert.props.title = title alert.props.msg = text self.add_alert(alert) alert.connect('response', self._alert_cancel_cb) alert.show() def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) def _key_press_cb(self, widget, event): key_name = Gdk.keyval_name(event.keyval) browser = self._tabbed_view.props.current_browser if event.get_state() & Gdk.ModifierType.CONTROL_MASK: if key_name == 'd': self._add_link() elif key_name == 'f': _logger.debug('keyboard: Find') self._edit_toolbar_button.set_expanded(True) self._edit_toolbar.search_entry.grab_focus() elif key_name == 'l': _logger.debug('keyboard: Focus url entry') self._primary_toolbar.entry.grab_focus() elif key_name == 'minus': _logger.debug('keyboard: Zoom out') browser.zoom_out() elif key_name in ['plus', 'equal']: _logger.debug('keyboard: Zoom in') browser.zoom_in() elif key_name == '0': _logger.debug('keyboard: Actual size') browser.set_zoom_level(ZOOM_ORIGINAL) elif key_name == 'Left': _logger.debug('keyboard: Go back') browser.go_back() elif key_name == 'Right': _logger.debug('keyboard: Go forward') browser.go_forward() elif key_name == 'r': _logger.debug('keyboard: Reload') browser.reload() elif Gdk.keyval_name(event.keyval) == "t": self._tabbed_view.add_tab() elif key_name == 'w': _logger.debug('keyboard: close tab') self._tabbed_view.close_tab() elif key_name == "Tab": _logger.debug('keyboard: next tab') current_index = self._tabbed_view.get_current_page() if current_index == self._tabbed_view.get_n_pages() - 1: self._tabbed_view.set_current_page(0) else: self._tabbed_view.set_current_page(current_index + 1) elif event.get_state() & Gdk.ModifierType.SHIFT_MASK: if key_name == "ISO_Left_Tab": _logger.debug('keyboard: previous tab') current_index = self._tabbed_view.get_current_page() last_index = self._tabbed_view.get_n_pages() if current_index == 0: self._tabbed_view.set_current_page(last_index - 1) else: self._tabbed_view.set_current_page(current_index - 1) else: return False return True elif key_name in ('KP_Up', 'KP_Down', 'KP_Left', 'KP_Right'): scrolled_window = browser.get_parent() if key_name in ('KP_Up', 'KP_Down'): adjustment = scrolled_window.get_vadjustment() elif key_name in ('KP_Left', 'KP_Right'): adjustment = scrolled_window.get_hadjustment() value = adjustment.get_value() step = adjustment.get_step_increment() if key_name in ('KP_Up', 'KP_Left'): adjustment.set_value(value - step) elif key_name in ('KP_Down', 'KP_Right'): adjustment.set_value(value + step) return True elif key_name == 'Escape': status = browser.get_load_status() loading = WebKit.LoadStatus.PROVISIONAL <= status \ < WebKit.LoadStatus.FINISHED if loading: _logger.debug('keyboard: Stop loading') browser.stop_loading() return False def _add_link(self): ''' take screenshot and add link info to the model ''' browser = self._tabbed_view.props.current_browser ui_uri = browser.get_uri() for link in self.model.data['shared_links']: if link['hash'] == sha1(ui_uri).hexdigest(): _logger.debug('_add_link: link exist already a=%s b=%s', link['hash'], sha1(ui_uri).hexdigest()) return buf = self._get_screenshot() timestamp = time.time() self.model.add_link(ui_uri, browser.props.title, buf, profile.get_nick_name(), profile.get_color().to_string(), timestamp) if self.messenger is not None: self.messenger._add_link(ui_uri, browser.props.title, profile.get_color().to_string(), profile.get_nick_name(), base64.b64encode(buf), timestamp) def _add_link_model_cb(self, model, index): ''' receive index of new link from the model ''' link = self.model.data['shared_links'][index] self._add_link_totray(link['url'], base64.b64decode(link['thumb']), link['color'], link['title'], link['owner'], index, link['hash'], link.get('notes')) def _add_link_totray(self, url, buf, color, title, owner, index, hash, notes=None): ''' add a link to the tray ''' item = LinkButton(buf, color, title, owner, hash, notes) item.connect('clicked', self._link_clicked_cb, url) item.connect('remove_link', self._link_removed_cb) item.notes_changed_signal.connect(self.__link_notes_changed) # use index to add to the tray self._tray.add_item(item, index) item.show() self._view_toolbar.traybutton.props.sensitive = True self._view_toolbar.traybutton.props.active = True self._view_toolbar.update_traybutton_tooltip() def _link_removed_cb(self, button, hash): ''' remove a link from tray and delete it in the model ''' self.model.remove_link(hash) self._tray.remove_item(button) if len(self._tray.get_children()) == 0: self._view_toolbar.traybutton.props.sensitive = False self._view_toolbar.traybutton.props.active = False self._view_toolbar.update_traybutton_tooltip() def __link_notes_changed(self, button, hash, notes): self.model.change_link_notes(hash, notes) def _link_clicked_cb(self, button, url): ''' an item of the link tray has been clicked ''' self._tabbed_view.props.current_browser.load_uri(url) def _get_screenshot(self): browser = self._tabbed_view.props.current_browser window = browser.get_window() width, height = window.get_width(), window.get_height() thumb_width, thumb_height = style.zoom(100), style.zoom(80) thumb_surface = Gdk.Window.create_similar_surface( window, cairo.CONTENT_COLOR, thumb_width, thumb_height) cairo_context = cairo.Context(thumb_surface) thumb_scale_w = thumb_width * 1.0 / width thumb_scale_h = thumb_height * 1.0 / height cairo_context.scale(thumb_scale_w, thumb_scale_h) Gdk.cairo_set_source_window(cairo_context, window, 0, 0) cairo_context.paint() thumb_str = StringIO.StringIO() thumb_surface.write_to_png(thumb_str) return thumb_str.getvalue() def can_close(self): if self._force_close: return True elif downloadmanager.can_quit(): return True else: alert = Alert() alert.props.title = ngettext('Download in progress', 'Downloads in progress', downloadmanager.num_downloads()) message = ngettext('Stopping now will erase your download', 'Stopping now will erase your downloads', downloadmanager.num_downloads()) alert.props.msg = message cancel_icon = Icon(icon_name='dialog-cancel') cancel_label = ngettext('Continue download', 'Continue downloads', downloadmanager.num_downloads()) alert.add_button(Gtk.ResponseType.CANCEL, cancel_label, cancel_icon) stop_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Stop'), stop_icon) stop_icon.show() self.add_alert(alert) alert.connect('response', self.__inprogress_response_cb) alert.show() self.present() return False def __inprogress_response_cb(self, alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.CANCEL: logging.debug('Keep on') elif response_id == Gtk.ResponseType.OK: logging.debug('Stop downloads and quit') self._force_close = True downloadmanager.remove_all_downloads() self.close() def __switch_page_cb(self, tabbed_view, page, page_num): browser = page._browser status = browser.get_load_status() if status in (WebKit.LoadStatus.COMMITTED, WebKit.LoadStatus.FIRST_VISUALLY_NON_EMPTY_LAYOUT): self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) elif status in (WebKit.LoadStatus.PROVISIONAL, WebKit.LoadStatus.FAILED, WebKit.LoadStatus.FINISHED): self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) def get_document_path(self, async_cb, async_err_cb): browser = self._tabbed_view.props.current_browser browser.get_source(async_cb, async_err_cb) def get_canvas(self): return self._tabbed_view
def _setup_toolbars(self): """ Setup the toolbars. """ self.max_participants = 4 yupana_toolbar = Gtk.Toolbar() self.custom_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() # Activity toolbar activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() yupana_toolbar_button = ToolbarButton(label=_("Mode"), page=yupana_toolbar, icon_name='preferences-system') yupana_toolbar.show() toolbox.toolbar.insert(yupana_toolbar_button, -1) yupana_toolbar_button.show() custom_toolbar_button = ToolbarButton(label=_("Custom"), page=self.custom_toolbar, icon_name='view-source') self.custom_toolbar.show() toolbox.toolbar.insert(custom_toolbar_button, -1) custom_toolbar_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.toolbar = toolbox.toolbar self._new_yupana_button = button_factory( 'edit-delete', self.toolbar, self._new_yupana_cb, tooltip=_('Clear the yupana.')) separator_factory(yupana_toolbar, False, True) self.ten_button = radio_factory('ten', yupana_toolbar, self._ten_cb, tooltip=_('decimal mode'), group=None) self.twenty_button = radio_factory('twenty', yupana_toolbar, self._twenty_cb, tooltip=_('base-twenty mode'), group=self.ten_button) self.factor_button = radio_factory('factor', yupana_toolbar, self._factor_cb, tooltip=_('prime-factor mode'), group=self.ten_button) self.fibonacci_button = radio_factory('fibonacci', yupana_toolbar, self._fibonacci_cb, tooltip=_('Fibonacci mode'), group=self.ten_button) self.custom_button = radio_factory('view-source', yupana_toolbar, self._custom_cb, tooltip=_('custom mode'), group=self.ten_button) separator_factory(self.toolbar, False, False) self.status = label_factory(self.toolbar, '', width=200) self.status.set_label(_('decimal mode')) separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show()
def __init__(self, handle): activity.Activity.__init__(self, handle) _logger.debug('Starting the web activity') session = WebKit.get_default_session() session.set_property('accept-language-auto', True) session.set_property('ssl-use-system-ca-file', True) session.set_property('ssl-strict', False) # By default, cookies are not stored persistently, we have to # add a cookie jar so that they get saved to disk. We use one # with a SQlite database: cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path, read_only=False) session.add_feature(cookie_jar) # FIXME # downloadmanager.remove_old_parts() self._force_close = False self._tabbed_view = TabbedView() self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._tray = HTray() self.set_tray(self._tray, Gtk.PositionType.BOTTOM) self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) self._view_toolbar = ViewToolbar(self) self._primary_toolbar.connect('add-link', self._link_add_button_cb) self._primary_toolbar.connect('go-home', self._go_home_button_cb) self._primary_toolbar.connect('go-library', self._go_library_button_cb) self._primary_toolbar.connect('reset-home', self._reset_home_button_cb) self._edit_toolbar_button = ToolbarButton(page=self._edit_toolbar, icon_name='toolbar-edit') self._primary_toolbar.toolbar.insert(self._edit_toolbar_button, 1) view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view') self._primary_toolbar.toolbar.insert(view_toolbar_button, 2) self._primary_toolbar.show_all() self.set_toolbar_box(self._primary_toolbar) self.set_canvas(self._tabbed_view) self._tabbed_view.show() self.model = Model() self.model.connect('add_link', self._add_link_model_cb) self.connect('key-press-event', self._key_press_cb) if handle.uri: self._tabbed_view.current_browser.load_uri(handle.uri) elif not self._jobject.file_path: # TODO: we need this hack until we extend the activity API for # opening URIs and default docs. self._tabbed_view.load_homepage() self.messenger = None self.connect('shared', self._shared_cb) # Get the Presence Service self.pservice = presenceservice.get_instance() try: name, path = self.pservice.get_preferred_connection() self.tp_conn_name = name self.tp_conn_path = path self.conn = telepathy.client.Connection(name, path) except TypeError: _logger.debug('Offline') self.initiating = None if self.get_shared_activity() is not None: _logger.debug('shared: %s', self.get_shared()) # We are joining the activity _logger.debug('Joined activity') self.connect('joined', self._joined_cb) if self.get_shared(): # We've already joined self._joined_cb() else: _logger.debug('Created activity') # README: this is a workaround to remove old temp file # http://bugs.sugarlabs.org/ticket/3973 self._cleanup_temp_files()
def _setup_toolbars(self): ''' Setup the toolbars.. ''' games_toolbar = Gtk.Toolbar() tools_toolbar = Gtk.Toolbar() numbers_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() self.activity_toolbar_button = ActivityToolbarButton(self) toolbox.toolbar.insert(self.activity_toolbar_button, 0) self.activity_toolbar_button.show() ''' self.numbers_toolbar_button = ToolbarButton( page=numbers_toolbar, icon_name='number-tools') numbers_toolbar.show() toolbox.toolbar.insert(self.numbers_toolbar_button, -1) self.numbers_toolbar_button.show() ''' self.tools_toolbar_button = ToolbarButton(page=tools_toolbar, icon_name='view-source') tools_toolbar.show() toolbox.toolbar.insert(self.tools_toolbar_button, -1) self.tools_toolbar_button.show() self.button_pattern = button_factory('new-word-game', toolbox.toolbar, self._select_game_cb, cb_arg='word', tooltip=PROMPT_DICT['word']) self._set_extras(toolbox.toolbar) self._sep.append(separator_factory(toolbox.toolbar, False, True)) help_button = HelpButton(self) toolbox.toolbar.insert(help_button, -1) help_button.show() self._setup_toolbar_help() self._sep.append(separator_factory(toolbox.toolbar, True, False)) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() export_scores = button_factory('score-copy', self.activity_toolbar_button, self._write_scores_to_clipboard, tooltip=_('Export scores to clipboard')) self.set_toolbar_box(toolbox) toolbox.show() ''' self.button_pattern = button_factory( 'new-pattern-game', games_toolbar, self._select_game_cb, cb_arg='pattern', tooltip=PROMPT_DICT['pattern']) self.button_number = button_factory( 'new-number-game', games_toolbar, self._select_game_cb, cb_arg='number', tooltip=PROMPT_DICT['number']) self.button_word = button_factory( 'new-word-game', games_toolbar, self._select_game_cb, cb_arg='word', tooltip=PROMPT_DICT['word']) self.button_custom = button_factory( 'no-custom-game', games_toolbar, self._select_game_cb, cb_arg='custom', tooltip=PROMPT_DICT['custom']) self._set_extras(games_toolbar) ''' self.words_tool_button = button_factory('word-tools', tools_toolbar, self._edit_words_cb, tooltip=_('Edit word lists.')) '''
class AbiWordActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) # abiword uses the current directory for all its file dialogs os.chdir(os.path.expanduser('~')) # create our main abiword canvas self.abiword_canvas = DocumentView() self._new_instance = True toolbar_box = ToolbarBox() self.activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(self.activity_button, -1) separator = Gtk.SeparatorToolItem() separator.show() self.activity_button.props.page.insert(separator, 2) ExportButtonFactory(self, self.abiword_canvas) self.activity_button.show() edit_toolbar = ToolbarButton() edit_toolbar.props.page = EditToolbar(self, toolbar_box) edit_toolbar.props.icon_name = 'toolbar-edit' edit_toolbar.props.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar, -1) view_toolbar = ToolbarButton() view_toolbar.props.page = ViewToolbar(self.abiword_canvas) view_toolbar.props.icon_name = 'toolbar-view' view_toolbar.props.label = _('View') toolbar_box.toolbar.insert(view_toolbar, -1) self.speech_toolbar_button = ToolbarButton(icon_name='speak') toolbar_box.toolbar.insert(self.speech_toolbar_button, -1) self.speech_toolbar = SpeechToolbar(self) self.speech_toolbar_button.set_page(self.speech_toolbar) self.speech_toolbar_button.show() separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) text_toolbar = ToolbarButton() text_toolbar.props.page = TextToolbar(self.abiword_canvas) text_toolbar.props.icon_name = 'format-text' text_toolbar.props.label = _('Text') toolbar_box.toolbar.insert(text_toolbar, -1) para_toolbar = ToolbarButton() para_toolbar.props.page = ParagraphToolbar(self.abiword_canvas) para_toolbar.props.icon_name = 'paragraph-bar' para_toolbar.props.label = _('Paragraph') toolbar_box.toolbar.insert(para_toolbar, -1) insert_toolbar = ToolbarButton() insert_toolbar.props.page = InsertToolbar(self.abiword_canvas) insert_toolbar.props.icon_name = 'insert-table' insert_toolbar.props.label = _('Table') toolbar_box.toolbar.insert(insert_toolbar, -1) image = ToolButton('insert-picture') image.set_tooltip(_('Insert Image')) self._image_id = image.connect('clicked', self.__image_cb) toolbar_box.toolbar.insert(image, -1) palette = image.get_palette() box = PaletteMenuBox() palette.set_content(box) box.show() menu_item = PaletteMenuItem(_('Floating')) menu_item.connect('activate', self.__image_cb, True) box.append_item(menu_item) menu_item.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) separator.show() toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box) # add a overlay to be able to show a icon while joining a shared doc overlay = Gtk.Overlay() overlay.add(self.abiword_canvas) overlay.show() self._connecting_box = ConnectingBox() overlay.add_overlay(self._connecting_box) self.set_canvas(overlay) # we want a nice border so we can select paragraphs easily self.abiword_canvas.set_show_margin(True) # Set default font face and size self._default_font_face = 'Sans' self._default_font_size = 12 # activity sharing self.participants = {} self.joined = False self.connect('shared', self._shared_cb) if self.shared_activity: # we are joining the activity logger.debug('We are joining an activity') # display a icon while joining self._connecting_box.show() # disable the abi widget self.abiword_canvas.set_sensitive(False) self._new_instance = False self.connect('joined', self._joined_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) if self.get_shared(): self._joined_cb(self) else: # we are creating the activity logger.debug("We are creating an activity") self.abiword_canvas.zoom_width() self.abiword_canvas.show() self.connect_after('map-event', self.__map_activity_event_cb) self.abiword_canvas.connect('size-allocate', self.size_allocate_cb) def size_allocate_cb(self, abi, alloc): GObject.idle_add(abi.queue_draw) def __map_activity_event_cb(self, event, activity): # set custom keybindings for Write # we do it later because have problems if done before - OLPC #11049 logger.debug('Loading keybindings') keybindings_file = os.path.join(get_bundle_path(), 'keybindings.xml') self.abiword_canvas.invoke_ex( 'com.abisource.abiword.loadbindings.fromURI', keybindings_file, 0, 0) # set default font if self._new_instance: self.abiword_canvas.select_all() logging.debug('Setting default font to %s %d in new documents', self._default_font_face, self._default_font_size) self.abiword_canvas.set_font_name(self._default_font_face) self.abiword_canvas.set_font_size(str(self._default_font_size)) self.abiword_canvas.moveto_bod() self.abiword_canvas.select_bod() if hasattr(self.abiword_canvas, 'toggle_rulers'): # this is not available yet on upstream abiword self.abiword_canvas.view_print_layout() self.abiword_canvas.toggle_rulers(False) self.abiword_canvas.grab_focus() def get_preview(self): if not hasattr(self.abiword_canvas, 'render_page_to_image'): return activity.Activity.get_preview(self) from gi.repository import GdkPixbuf pixbuf = self.abiword_canvas.render_page_to_image(1) pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225), GdkPixbuf.InterpType.BILINEAR) preview_data = [] def save_func(buf, length, data): data.append(buf) return True pixbuf.save_to_callbackv(save_func, preview_data, 'png', [], []) preview_data = b''.join(preview_data) return preview_data def _shared_cb(self, activity): logger.debug('My Write activity was shared') self._sharing_setup() self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) channel = self.tubes_chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES] logger.debug('This is my activity: offering a tube...') id = channel.OfferDBusTube('com.abisource.abiword.abicollab', {}) logger.debug('Tube address: %s', channel.GetDBusTubeAddress(id)) def _sharing_setup(self): logger.debug("_sharing_setup()") if self.shared_activity is None: logger.error('Failed to share or join activity') return 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.tube_id = None self.tubes_chan[ TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) def _list_tubes_reply_cb(self, tubes): for tube_info in tubes: self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): logger.error('ListTubes() failed: %s', e) def _joined_cb(self, activity): logger.debug("_joined_cb()") if not self.shared_activity: self._enable_collaboration() return self.joined = True logger.debug('Joined an existing Write session') self._sharing_setup() logger.debug('This is not my activity: waiting for a tube...') self.tubes_chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES].ListTubes( reply_handler=self._list_tubes_reply_cb, error_handler=self._list_tubes_error_cb) self._enable_collaboration() def _enable_collaboration(self): """ when communication established, hide the download icon and enable the abi widget """ self.abiword_canvas.zoom_width() self.abiword_canvas.set_sensitive(True) self._connecting_box.hide() def _new_tube_cb(self, id, initiator, type, service, params, state): logger.debug( 'New tube: ID=%d initiator=%d type=%d service=%s ' 'params=%r state=%d', id, initiator, type, service, params, state) if self.tube_id is not None: # We are already using a tube return if type != TelepathyGLib.TubeType.DBUS or \ service != "com.abisource.abiword.abicollab": return channel = self.tubes_chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES] if state == TelepathyGLib.TubeState.LOCAL_PENDING: channel.AcceptDBusTube(id) # look for the initiator's D-Bus unique name initiator_dbus_name = None dbus_names = channel.GetDBusNames(id) for handle, name in dbus_names: if handle == initiator: logger.debug('found initiator D-Bus name: %s', name) initiator_dbus_name = name break if initiator_dbus_name is None: logger.error('Unable to get the D-Bus name of the tube initiator') return cmd_prefix = 'com.abisource.abiword.abicollab.olpc.' # pass this tube to abicollab address = channel.GetDBusTubeAddress(id) if self.joined: logger.debug('Passing tube address to abicollab (join): %s', address) self.abiword_canvas.invoke_ex(cmd_prefix + 'joinTube', address, 0, 0) # The intiator of the session has to be the first passed # to the Abicollab backend. logger.debug('Adding the initiator to the session: %s', initiator_dbus_name) self.abiword_canvas.invoke_ex(cmd_prefix + 'buddyJoined', initiator_dbus_name, 0, 0) else: logger.debug('Passing tube address to abicollab (offer): %s', address) self.abiword_canvas.invoke_ex(cmd_prefix + 'offerTube', address, 0, 0) self.tube_id = id channel.connect_to_signal('DBusNamesChanged', self._on_dbus_names_changed) self._on_dbus_names_changed(id, dbus_names, []) def _on_dbus_names_changed(self, tube_id, added, removed): """ We call com.abisource.abiword.abicollab.olpc.buddy{Joined,Left} according members of the D-Bus tube. That's why we don't add/remove buddies in _buddy_{joined,left}_cb. """ logger.debug('_on_dbus_names_changed') # if tube_id == self.tube_id: cmd_prefix = 'com.abisource.abiword.abicollab.olpc' for handle, bus_name in added: logger.debug('added handle: %s, with dbus_name: %s', handle, bus_name) self.abiword_canvas.invoke_ex(cmd_prefix + '.buddyJoined', bus_name, 0, 0) self.participants[handle] = bus_name def _on_members_changed(self, message, added, removed, local_pending, remote_pending, actor, reason): logger.debug("_on_members_changed") for handle in removed: bus_name = self.participants.pop(handle, None) if bus_name is None: # FIXME: that shouldn't happen so probably hide another bug. # Should be investigated continue cmd_prefix = 'com.abisource.abiword.abicollab.olpc' logger.debug('removed handle: %d, with dbus name: %s', handle, bus_name) self.abiword_canvas.invoke_ex(cmd_prefix + '.buddyLeft', bus_name, 0, 0) def _buddy_joined_cb(self, activity, buddy): logger.debug('buddy joined with object path: %s', buddy.object_path()) def _buddy_left_cb(self, activity, buddy): logger.debug('buddy left with object path: %s', buddy.object_path()) def read_file(self, file_path): logging.debug('AbiWordActivity.read_file: %s, mimetype: %s', file_path, self.metadata['mime_type']) if self._is_plain_text(self.metadata['mime_type']): self.abiword_canvas.load_file('file://' + file_path, 'text/plain') else: # we pass no mime/file type, let libabiword autodetect it, # so we can handle multiple file formats self.abiword_canvas.load_file('file://' + file_path, '') self.abiword_canvas.zoom_width() self._new_instance = False def write_file(self, file_path): logging.debug('AbiWordActivity.write_file: %s, mimetype: %s', file_path, self.metadata['mime_type']) # if we were editing a text file save as plain text if self._is_plain_text(self.metadata['mime_type']): logger.debug('Writing file as type source (text/plain)') self.abiword_canvas.save('file://' + file_path, 'text/plain', '') else: # if the file is new, save in .odt format if self.metadata['mime_type'] == '': self.metadata['mime_type'] = 'application/rtf' # Abiword can't save in .doc format, save in .rtf instead if self.metadata['mime_type'] == 'application/msword': self.metadata['mime_type'] = 'application/rtf' self.abiword_canvas.save('file://' + file_path, self.metadata['mime_type'], '') self.metadata['fulltext'] = self.abiword_canvas.get_content( 'text/plain', None)[0][:3000] def _is_plain_text(self, mime_type): # These types have 'text/plain' in their mime_parents but we need # use it like rich text if mime_type in ['application/rtf', 'text/rtf', 'text/html']: return False from sugar3 import mime mime_parents = mime.get_mime_parents(self.metadata['mime_type']) return self.metadata['mime_type'] in ['text/plain', 'text/csv'] or \ 'text/plain' in mime_parents def __image_cb(self, button, floating=False): try: chooser = ObjectChooser(self, what_filter='Image', filter_type=FILTER_TYPE_GENERIC_MIME, show_preview=True) except: # for compatibility with older versions chooser = ObjectChooser(self, what_filter='Image') try: result = chooser.run() if result == Gtk.ResponseType.ACCEPT: logging.debug('ObjectChooser: %r', chooser.get_selected_object()) jobject = chooser.get_selected_object() if jobject and jobject.file_path: self.abiword_canvas.insert_image(jobject.file_path, floating) finally: chooser.destroy() del chooser
def build_colors_toolbar(self, toolbox): colors_bar = Gtk.Toolbar() ######################################################################## # Point color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Points')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() fill_color = ColorToolButton() fill_color.connect('notify::color', self.color_point_change) item.add(fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ######################################################################## # Back color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Background')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() c = Gdk.Color(red=21588, green=47546, blue=18504) _fill_color.set_color(c) _fill_color.connect('notify::color', self.color_back_change) item.add(_fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ######################################################################## # Line color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Lines')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() _fill_color.connect('notify::color', self.color_line_change) item.add(_fill_color) colors_bar.insert(item, -1) # Separator separator = Gtk.SeparatorToolItem() colors_bar.insert(separator, -1) separator.show() ######################################################################## # Owner color item = Gtk.ToolItem() label = Gtk.Label() label.set_text('%s ' % _('Owner')) item.add(label) colors_bar.insert(item, -1) # select color item = Gtk.ToolItem() _fill_color = ColorToolButton() c = Gdk.Color(red=65535, green=0, blue=0) _fill_color.set_color(c) _fill_color.connect('notify::color', self.color_owner_change) item.add(_fill_color) colors_bar.insert(item, -1) colors_bar.show_all() colors_button = ToolbarButton(label=_('Colors'), page=colors_bar, icon_name='toolbar-colors') toolbox.toolbar.insert(colors_button, -1) colors_button.show()
def __init__(self, handle): activity.Activity.__init__(self, handle) # abiword uses the current directory for all its file dialogs os.chdir(os.path.expanduser('~')) # create our main abiword canvas self.abiword_canvas = DocumentView() self._new_instance = True toolbar_box = ToolbarBox() self.activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(self.activity_button, -1) separator = Gtk.SeparatorToolItem() separator.show() self.activity_button.props.page.insert(separator, 2) ExportButtonFactory(self, self.abiword_canvas) self.activity_button.show() edit_toolbar = ToolbarButton() edit_toolbar.props.page = EditToolbar(self, toolbar_box) edit_toolbar.props.icon_name = 'toolbar-edit' edit_toolbar.props.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar, -1) view_toolbar = ToolbarButton() view_toolbar.props.page = ViewToolbar(self.abiword_canvas) view_toolbar.props.icon_name = 'toolbar-view' view_toolbar.props.label = _('View') toolbar_box.toolbar.insert(view_toolbar, -1) self.speech_toolbar_button = ToolbarButton(icon_name='speak') toolbar_box.toolbar.insert(self.speech_toolbar_button, -1) self.speech_toolbar = SpeechToolbar(self) self.speech_toolbar_button.set_page(self.speech_toolbar) self.speech_toolbar_button.show() separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) text_toolbar = ToolbarButton() text_toolbar.props.page = TextToolbar(self.abiword_canvas) text_toolbar.props.icon_name = 'format-text' text_toolbar.props.label = _('Text') toolbar_box.toolbar.insert(text_toolbar, -1) para_toolbar = ToolbarButton() para_toolbar.props.page = ParagraphToolbar(self.abiword_canvas) para_toolbar.props.icon_name = 'paragraph-bar' para_toolbar.props.label = _('Paragraph') toolbar_box.toolbar.insert(para_toolbar, -1) insert_toolbar = ToolbarButton() insert_toolbar.props.page = InsertToolbar(self.abiword_canvas) insert_toolbar.props.icon_name = 'insert-table' insert_toolbar.props.label = _('Table') toolbar_box.toolbar.insert(insert_toolbar, -1) image = ToolButton('insert-picture') image.set_tooltip(_('Insert Image')) self._image_id = image.connect('clicked', self.__image_cb) toolbar_box.toolbar.insert(image, -1) palette = image.get_palette() box = PaletteMenuBox() palette.set_content(box) box.show() menu_item = PaletteMenuItem(_('Floating')) menu_item.connect('activate', self.__image_cb, True) box.append_item(menu_item) menu_item.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) separator.show() toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box) # add a overlay to be able to show a icon while joining a shared doc overlay = Gtk.Overlay() overlay.add(self.abiword_canvas) overlay.show() self._connecting_box = ConnectingBox() overlay.add_overlay(self._connecting_box) self.set_canvas(overlay) # we want a nice border so we can select paragraphs easily self.abiword_canvas.set_show_margin(True) # Set default font face and size self._default_font_face = 'Sans' self._default_font_size = 12 # activity sharing self.participants = {} self.joined = False self.connect('shared', self._shared_cb) if self.shared_activity: # we are joining the activity logger.debug('We are joining an activity') # display a icon while joining self._connecting_box.show() # disable the abi widget self.abiword_canvas.set_sensitive(False) self._new_instance = False self.connect('joined', self._joined_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) if self.get_shared(): self._joined_cb(self) else: # we are creating the activity logger.debug("We are creating an activity") self.abiword_canvas.zoom_width() self.abiword_canvas.show() self.connect_after('map-event', self.__map_activity_event_cb) self.abiword_canvas.connect('size-allocate', self.size_allocate_cb)
def __init__(self, handle): activity.Activity.__init__(self, handle, True) self.max_participants = 1 self.dic = {} # Canvas self._canvas = Gtk.VBox() hbox = Gtk.HBox() self._liststore = Gtk.ListStore(str) self.combo1 = Gtk.ComboBox.new_with_model_and_entry(self._liststore) cell = Gtk.CellRendererText() self.combo1.pack_start(cell, True) self.combo1.set_entry_text_column(0) self.combo1.connect('changed', self._call) flip_btn = Gtk.Button() flip_btn.connect('clicked', self._flip) flip_btn.add(Gtk.Image.new_from_file('icons/flip.svg')) self.combo2 = Gtk.ComboBox.new_with_model_and_entry(self._liststore) cell = Gtk.CellRendererText() self.combo2.pack_start(cell, True) self.combo2.set_entry_text_column(0) self.combo2.connect('changed', self._call) self.label_box = Gtk.HBox() self.adjustment = Gtk.Adjustment(1.0, 0, 10.00**10.00, 1.0, 1.0, 0) self.spin = Gtk.SpinButton() self.spin.set_adjustment(self.adjustment) self.spin.set_numeric(True) self.label = Gtk.Label() self.label._size = 12 self.label.set_selectable(True) self.label.connect('draw', self.resize_label) self.convert_btn = Gtk.Button(_('Convert')) self.convert_btn.connect('clicked', self._call) self._canvas.pack_start(hbox, False, False, 20) hbox.pack_start(self.combo1, False, True, 20) hbox.pack_start(flip_btn, True, False, 20) hbox.pack_end(self.combo2, False, True, 20) spin_box = Gtk.HBox() convert_box = Gtk.HBox() convert_box.pack_start(spin_box, True, False, 0) spin_box.pack_start(self.spin, False, False, 0) self._canvas.pack_start(convert_box, False, False, 5) self._canvas.pack_start(self.label_box, True, False, 0) self.label_box.add(self.label) spin_box.pack_start(self.convert_btn, False, False, 20) self.set_canvas(self._canvas) # Toolbar toolbarbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbarbox.toolbar.insert(activity_button, 0) separator = Gtk.SeparatorToolItem() separator.set_expand(False) separator.set_draw(True) toolbarbox.toolbar.insert(separator, -1) self._edit_toolbar = EditToolbar() self._edit_toolbar.undo.props.visible = False self._edit_toolbar.redo.props.visible = False self._edit_toolbar.separator.props.visible = False self._edit_toolbar.copy.set_sensitive = False self._edit_toolbar.copy.connect('clicked', self._edit_copy_cb) edit_toolbar_button = ToolbarButton(page=self._edit_toolbar, icon_name='toolbar-edit') edit_toolbar_button.props.label = _('Edit') self._edit_toolbar.show() edit_toolbar_button.show() toolbarbox.toolbar.insert(edit_toolbar_button, -1) # RadioToolButton self._length_btn = RadioToolButton() self._length_btn.connect('clicked', lambda w: self._update_combo(convert.length)) # TRANS: https://en.wikipedia.org/wiki/Length self._length_btn.set_tooltip(_('Length')) self._length_btn.props.icon_name = 'length' self._volume_btn = RadioToolButton() self._volume_btn.connect('clicked', lambda w: self._update_combo(convert.volume)) # TRANS: https://en.wikipedia.org/wiki/Volume self._volume_btn.set_tooltip(_('Volume')) self._volume_btn.props.icon_name = 'volume' self._volume_btn.props.group = self._length_btn self._area_btn = RadioToolButton() self._area_btn.connect('clicked', lambda w: self._update_combo(convert.area)) # TRANS: https://en.wikipedia.org/wiki/Area self._area_btn.set_tooltip(_('Area')) self._area_btn.props.icon_name = 'area' self._area_btn.props.group = self._length_btn self._weight_btn = RadioToolButton() self._weight_btn.connect('clicked', lambda w: self._update_combo(convert.weight)) # TRANS: https://en.wikipedia.org/wiki/Weight self._weight_btn.set_tooltip(_('Weight')) self._weight_btn.props.icon_name = 'weight' self._weight_btn.props.group = self._length_btn self._speed_btn = RadioToolButton() self._speed_btn.connect('clicked', lambda w: self._update_combo(convert.speed)) # TRANS: https://en.wikipedia.org/wiki/Speed self._speed_btn.set_tooltip(_('Speed')) self._speed_btn.props.icon_name = 'speed' self._speed_btn.props.group = self._length_btn self._time_btn = RadioToolButton() self._time_btn.connect('clicked', lambda w: self._update_combo(convert.time)) # TRANS: https://en.wikipedia.org/wiki/Time self._time_btn.set_tooltip(_('Time')) self._time_btn.props.icon_name = 'time' self._time_btn.props.group = self._length_btn self._temp_btn = RadioToolButton() self._temp_btn.connect('clicked', lambda w: self._update_combo(convert.temp)) # TRANS: https://en.wikipedia.org/wiki/Temperature self._temp_btn.set_tooltip(_('Temperature')) self._temp_btn.props.icon_name = 'temp' self._temp_btn.props.group = self._length_btn toolbarbox.toolbar.insert(self._length_btn, -1) toolbarbox.toolbar.insert(self._volume_btn, -1) toolbarbox.toolbar.insert(self._area_btn, -1) toolbarbox.toolbar.insert(self._weight_btn, -1) toolbarbox.toolbar.insert(self._speed_btn, -1) toolbarbox.toolbar.insert(self._time_btn, -1) toolbarbox.toolbar.insert(self._temp_btn, -1) separator = Gtk.SeparatorToolItem() separator.set_expand(True) separator.set_draw(False) toolbarbox.toolbar.insert(separator, -1) stopbtn = StopButton(self) toolbarbox.toolbar.insert(stopbtn, -1) self.set_toolbar_box(toolbarbox) self._update_combo(convert.length) self.show_all()
def build_toolbar(self): self.max_participants = 4 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() create_toolbar = ToolbarButton() create_toolbar.props.page = Gtk.Toolbar() create_toolbar.props.icon_name = 'magicpen' create_toolbar.props.label = _('Create') toolbar_box.toolbar.insert(create_toolbar, -1) self._insert_create_tools(create_toolbar) color = ColorToolButton('color') color.connect('notify::color', self.__color_notify_cb) toolbar_box.toolbar.insert(color, -1) color.show() random = ToggleToolButton('colorRandom') random.set_tooltip(_('Toggle random color')) toolbar_box.toolbar.insert(random, -1) random.set_active(True) random.connect('toggled', self.__random_toggled_cb) random.show() color.random = random random.color = color random.timeout_id = GObject.timeout_add(100, self.__timeout_cb, random) self._insert_stop_play_button(toolbar_box.toolbar) clear_trace = ToolButton('clear-trace') clear_trace.set_tooltip(_('Clear Trace Marks')) clear_trace.set_accelerator(_('<ctrl>x')) clear_trace.connect('clicked', self.clear_trace_cb) clear_trace.set_sensitive(False) toolbar_box.toolbar.insert(clear_trace, -1) clear_trace.show() self.clear_trace = clear_trace self._insert_clear_all_button(toolbar_box.toolbar) load_example = ToolButton('load-sample') load_example.set_tooltip(_('Show sample projects')) load_example.connect('clicked', self._create_store) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_box.toolbar.insert(load_example, -1) load_example.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) stop.show() separator = Gtk.SeparatorToolItem() activity_button.props.page.insert(separator, -1) separator.show() export_json = ToolButton('save-as-json') export_json.set_tooltip(_('Export tracked objects to journal')) export_json.connect('clicked', self._export_json_cb) activity_button.props.page.insert(export_json, -1) export_json.show() load_project = ToolButton('load-project') load_project.set_tooltip(_('Load project from journal')) load_project.connect('clicked', self._load_project) activity_button.props.page.insert(load_project, -1) load_project.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() create_toolbar.set_expanded(True) return toolbar_box
def build_toolbar(self): self.max_participants = 4 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() create_toolbar = ToolbarButton() create_toolbar.props.page = Gtk.Toolbar() create_toolbar.props.icon_name = 'magicpen' create_toolbar.props.label = _('Create') toolbar_box.toolbar.insert(create_toolbar, -1) self._insert_create_tools(create_toolbar) self._insert_stop_play_button(toolbar_box.toolbar) clear_trace = ToolButton('clear-trace') clear_trace.set_tooltip(_('Clear Trace Marks')) clear_trace.set_accelerator(_('<ctrl>x')) clear_trace.connect('clicked', self.clear_trace_cb) clear_trace.set_sensitive(False) toolbar_box.toolbar.insert(clear_trace, -1) clear_trace.show() self.clear_trace = clear_trace self._insert_clear_all_button(toolbar_box.toolbar) load_example = ToolButton('load-sample') load_example.set_tooltip(_('Show sample projects')) load_example.connect('clicked', self._create_store) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_box.toolbar.insert(load_example, -1) load_example.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) stop.show() separator = Gtk.SeparatorToolItem() activity_button.props.page.insert(separator, -1) separator.show() export_json = ToolButton('save-as-json') export_json.set_tooltip(_('Export tracked objects to journal')) export_json.connect('clicked', self._export_json_cb) activity_button.props.page.insert(export_json, -1) export_json.show() export_csv = ToolButton('save-as-csv') export_csv.set_tooltip(_('Export tracked objects to journal')) export_csv.connect('clicked', self._export_csv_cb) activity_button.props.page.insert(export_csv, -1) export_csv.show() load_project = ToolButton('load-project') load_project.set_tooltip(_('Load project from journal')) load_project.connect('clicked', self._load_project) activity_button.props.page.insert(load_project, -1) load_project.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() create_toolbar.set_expanded(True) return toolbar_box
class PhysicsActivity(activity.Activity): def __init__(self, handle): super(PhysicsActivity, self).__init__(handle) self._collab = CollabWrapper(self) self._collab.message.connect(self.__message_cb) self.metadata['mime_type'] = 'application/x-physics-activity' self.add_events(Gdk.EventMask.ALL_EVENTS_MASK | Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self.connect('visibility-notify-event', self._focus_event) self.connect('window-state-event', self._window_event) self.game_canvas = sugargame.canvas.PygameCanvas(self) self.game = physics.main(self) self.preview = None self._sample_window = None self._fixed = Gtk.Fixed() self._fixed.put(self.game_canvas, 0, 0) w = Gdk.Screen.width() h = Gdk.Screen.height() - 2 * GRID_CELL_SIZE self.game_canvas.set_size_request(w, h) self._constructors = {} self.build_toolbar() self.set_canvas(self._fixed) Gdk.Screen.get_default().connect('size-changed', self.__configure_cb) logging.debug(os.path.join( activity.get_activity_root(), 'data', 'data')) self.game_canvas.run_pygame(self.game.run) self.show_all() self._collab.setup() def __configure_cb(self, event): ''' Screen size has changed ''' self.write_file(os.path.join( activity.get_activity_root(), 'data', 'data')) w = Gdk.Screen.width() h = Gdk.Screen.height() - 2 * GRID_CELL_SIZE pygame.display.set_mode((w, h), pygame.RESIZABLE) self.read_file(os.path.join( activity.get_activity_root(), 'data', 'data')) self.game.run(True) def read_file(self, file_path): self.game.read_file(file_path) def write_file(self, file_path): self.game.write_file(file_path) def get_preview(self): ''' Custom preview code to get image from pygame. ''' return self.game_canvas.get_preview() def build_toolbar(self): self.max_participants = 4 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() create_toolbar = ToolbarButton() create_toolbar.props.page = Gtk.Toolbar() create_toolbar.props.icon_name = 'magicpen' create_toolbar.props.label = _('Create') toolbar_box.toolbar.insert(create_toolbar, -1) self._insert_create_tools(create_toolbar) color = ColorToolButton('color') color.connect('notify::color', self.__color_notify_cb) toolbar_box.toolbar.insert(color, -1) color.show() random = ToggleToolButton('colorRandom') random.set_tooltip(_('Toggle random color')) toolbar_box.toolbar.insert(random, -1) random.set_active(True) random.connect('toggled', self.__random_toggled_cb) random.show() color.random = random random.color = color random.timeout_id = GObject.timeout_add(100, self.__timeout_cb, random) self._insert_stop_play_button(toolbar_box.toolbar) clear_trace = ToolButton('clear-trace') clear_trace.set_tooltip(_('Clear Trace Marks')) clear_trace.set_accelerator(_('<ctrl>x')) clear_trace.connect('clicked', self.clear_trace_cb) clear_trace.set_sensitive(False) toolbar_box.toolbar.insert(clear_trace, -1) clear_trace.show() self.clear_trace = clear_trace self._insert_clear_all_button(toolbar_box.toolbar) load_example = ToolButton('load-sample') load_example.set_tooltip(_('Show sample projects')) load_example.connect('clicked', self._create_store) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_box.toolbar.insert(load_example, -1) load_example.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) stop.show() separator = Gtk.SeparatorToolItem() activity_button.props.page.insert(separator, -1) separator.show() export_json = ToolButton('save-as-json') export_json.set_tooltip(_('Export tracked objects to journal')) export_json.connect('clicked', self._export_json_cb) activity_button.props.page.insert(export_json, -1) export_json.show() load_project = ToolButton('load-project') load_project.set_tooltip(_('Load project from journal')) load_project.connect('clicked', self._load_project) activity_button.props.page.insert(load_project, -1) load_project.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() create_toolbar.set_expanded(True) return toolbar_box def __color_notify_cb(self, button, pdesc): """ when a color is chosen; change world object add color, and change color of buttons. """ color = button.get_color() self._set_color(color) button.random.set_active(False) button.random.get_icon_widget().set_stroke_color(self._rgb8x(color)) def __random_toggled_cb(self, random): if random.props.active: self._random_on(random) else: self._random_off(random) def _random_on(self, random): """ when random is turned on; reset world object add color, and begin watching for changed world object add color. """ self.game.world.add.reset_color() if random.timeout_id is None: random.timeout_id = GObject.timeout_add(100, self.__timeout_cb, random) self.__timeout_cb(random) def _random_off(self, random): """ when random is turned off; change world object add color back to chosen color, change color of buttons, and stop watching for changed world object add color. """ color = random.color.get_color() self._set_color(color) random.get_icon_widget().set_stroke_color(self._rgb8x(color)) if random.timeout_id is not None: GObject.source_remove(random.timeout_id) random.timeout_id = None def __timeout_cb(self, random): """ copy the next color to the random button stroke color. """ if hasattr(self.game, "world"): color = self.game.world.add.next_color() random.get_icon_widget().set_stroke_color('#%.2X%.2X%.2X' % color) return True def _set_color(self, color): """ set world object add color. """ self.game.world.add.set_color(self._rgb8(color)) def _rgb8x(self, color): """ convert a Gdk.Color into hex triplet. """ return '#%.2X%.2X%.2X' % self._rgb8(color) def _rgb8(self, color): """ convert a Gdk.Color into an 8-bit RGB tuple. """ return (color.red / 256, color.green / 256, color.blue / 256) def can_close(self): self.preview = self.get_preview() self.game.loop = False return True def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = 'media-playback-stop' self.stop_play_state = True self.stop_play = ToolButton('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play.set_accelerator(_('<ctrl>space')) self.stop_play.connect('clicked', self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name('slow-walk-milton-raposo') slowest_button.set_tooltip(_('Run slower')) slowest_button.connect('clicked', self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name('walking') slow_button.set_tooltip(_('Run slow')) slow_button.connect('clicked', self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name('running') fast_button.set_tooltip('Run fast') fast_button.connect('clicked', self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all() def _set_fps_cb(self, button, value): self.game.set_game_fps(value) def _insert_clear_all_button(self, toolbar): self.clear_all = ToolButton('clear_all') self.clear_all.set_tooltip(_('Erase All')) self.clear_all.set_accelerator(_('<ctrl>a')) self.clear_all.connect('clicked', self.clear_all_cb) toolbar.insert(self.clear_all, -1) self.clear_all.set_sensitive(False) self.clear_all.show() def _insert_item(self, toolbar, item, pos=-1): if hasattr(toolbar, 'insert'): toolbar.insert(item, pos) else: toolbar.props.page.insert(item, pos) def _insert_create_tools(self, create_toolbar): # Make + add the component buttons self.radioList = {} for i, c in enumerate(tools.allTools): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(c.icon) button.set_tooltip(c.toolTip) button.set_accelerator(c.toolAccelerator) button.connect('clicked', self.radioClicked) palette = self._build_palette(c) if palette is not None: palette.show() button.get_palette().set_content(palette) self._insert_item(create_toolbar, button, -1) button.show() self.radioList[button] = c.name if hasattr(c, 'constructor'): self._constructors[c.name] = \ self.game.toolList[c.name].constructor def __icon_path(self, name): activity_path = activity.get_bundle_path() icon_path = os.path.join(activity_path, 'icons', name + '.svg') return icon_path def _build_palette(self, tool): if tool.palette_enabled: if tool.palette_mode == tools.PALETTE_MODE_ICONS: grid = Gtk.Grid() for s, settings in enumerate(tool.palette_settings): self.game.toolList[tool.name].buttons.append([]) for i, icon_value in enumerate(settings['icon_values']): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(settings['icons'][i]) button.connect('clicked', self._palette_icon_clicked, tool.name, s, settings['name'], icon_value) grid.attach(button, i, s, 1, 1) self.game.toolList[tool.name].buttons[s].append(button) button.show() if settings['active'] == settings['icons'][i]: button.set_icon_name(settings['icons'][i] + '-selected') button.set_active(True) return grid else: return None def _palette_icon_clicked(self, widget, toolname, s, value_name, value): for tool in tools.allTools: if tool.name == toolname: # Radio buttons are not highlighting in the palette # so adding highlight by hand # See http://bugs.sugarlabs.org/ticket/305 setting = self.game.toolList[tool.name].palette_settings[s] for i, button in enumerate( self.game.toolList[tool.name].buttons[s]): icon_name = setting['icons'][i] if button == widget: button.set_icon_name(icon_name + '-selected') else: button.set_icon_name(icon_name) if hasattr(tool, 'palette_data_type'): tool.palette_data_type = value else: tool.palette_data[value_name] = value def clear_trace_alert_cb(self, alert, response): self.remove_alert(alert) if response is Gtk.ResponseType.OK: self.game.full_pos_list = [[] for _ in self.game.full_pos_list] self.game.tracked_bodies = 0 def clear_trace_cb(self, button): clear_trace_alert = ConfirmationAlert() clear_trace_alert.props.title = _('Are You Sure?') clear_trace_alert.props.msg = \ _('All trace points will be erased. This cannot be undone!') clear_trace_alert.connect('response', self.clear_trace_alert_cb) self.add_alert(clear_trace_alert) def stop_play_cb(self, button): pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='stop_start_toggle')) self.stop_play_state = not self.stop_play_state if self.stop_play_state: self.stop_play.set_icon_name('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play_toolbar.set_icon_name('media-playback-stop') else: self.stop_play.set_icon_name('media-playback-start') self.stop_play.set_tooltip(_('Start')) self.stop_play_toolbar.set_icon_name('media-playback-start') def clear_all_cb(self, button): def clear_all_alert_cb(alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='clear_all')) if len(self.game.world.world.bodies) > 2: clear_all_alert = ConfirmationAlert() clear_all_alert.props.title = _('Are You Sure?') clear_all_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') clear_all_alert.connect('response', clear_all_alert_cb) self.add_alert(clear_all_alert) def radioClicked(self, button): pygame.event.post(pygame.event.Event(pygame.USEREVENT, action=self.radioList[button])) def _focus_event(self, event, data=None): ''' Send focus events to pygame to allow it to idle when in background. ''' if not self.game.pygame_started: logging.debug('focus_event: pygame not yet initialized') return if data.state == Gdk.VisibilityState.FULLY_OBSCURED: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='focus_out')) else: self.game.show_fake_cursor = True pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='focus_in')) def _export_json_cb(self, button): jobject = datastore.create() jobject.metadata['title'] = _('Physics export') jobject.metadata['mime_type'] = 'text/plain' tmp_dir = os.path.join(self.get_activity_root(), 'instance') fd, file_path = tempfile.mkstemp(dir=tmp_dir) os.close(fd) self.game.world.json_save(file_path) jobject.set_file_path(file_path) datastore.write(jobject) def _window_event(self, window, event): ''' Send focus out event to pygame when switching to a desktop view. ''' if event.changed_mask & Gdk.WindowState.ICONIFIED: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='focus_out')) def _restore_cursor(self): ''' No longer waiting, so restore standard cursor. ''' if not hasattr(self, 'get_window'): return self.get_window().set_cursor(self.old_cursor) def _waiting_cursor(self): ''' Waiting, so set watch cursor. ''' if not hasattr(self, 'get_window'): return self.old_cursor = self.get_window().get_cursor() self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) def __message_cb(self, collab, buddy, msg): ''' Data is passed as tuples: cmd:text ''' action = msg.get('action') if action != 'text': return text = msg['text'] dispatch_table = {'C': self._construct_shared_circle, 'B': self._construct_shared_box, 'T': self._construct_shared_triangle, 'P': self._construct_shared_polygon, 'M': self._construct_shared_magicpen, 'j': self._add_shared_joint, 'p': self._add_shared_pin, 'm': self._add_shared_motor, 't': self._add_shared_track, 'c': self._add_shared_chain, } logging.debug('<<< %s' % (text[0])) dispatch_table[text[0]](text[2:]) def _construct_shared_circle(self, data): circle_data = json.loads(data) pos = circle_data[0] radius = circle_data[1] density = circle_data[2] restitution = circle_data[3] friction = circle_data[4] self._constructors['Circle'](pos, radius, density, restitution, friction, share=False) def _construct_shared_box(self, data): box_data = json.loads(data) pos1 = box_data[0] pos2 = box_data[1] density = box_data[2] restitution = box_data[3] friction = box_data[4] self._constructors['Box'](pos1, pos2, density, restitution, friction, share=False) def _construct_shared_triangle(self, data): triangle_data = json.loads(data) pos1 = triangle_data[0] pos2 = triangle_data[1] density = triangle_data[2] restitution = triangle_data[3] friction = triangle_data[4] self._constructors['Triangle'](pos1, pos2, density, restitution, friction, share=False) def _construct_shared_polygon(self, data): polygon_data = json.loads(data) vertices = polygon_data[0] density = polygon_data[1] restitution = polygon_data[2] friction = polygon_data[3] self._constructors['Polygon'](vertices, density, restitution, friction, share=False) def _construct_shared_magicpen(self, data): magicpen_data = json.loads(data) vertices = magicpen_data[0] density = magicpen_data[1] restitution = magicpen_data[2] friction = magicpen_data[3] self._constructors['Magicpen'](vertices, density, restitution, friction, share=False) def _add_shared_joint(self, data): joint_data = json.loads(data) pos1 = joint_data[0] pos2 = joint_data[1] self._constructors['Joint'](pos1, pos2, share=False) def _add_shared_pin(self, data): joint_data = json.loads(data) pos = joint_data[0] self._constructors['Pin'](pos, share=False) def _add_shared_motor(self, data): joint_data = json.loads(data) pos = joint_data[0] speed = joint_data[1] self._constructors['Motor'](pos, speed, share=False) def _add_shared_track(self, data): joint_data = json.loads(data) pos = joint_data[0] color = joint_data[1] self._constructors['Track'](pos, color, share=False) def _add_shared_chain(self, data): joint_data = json.loads(data) vertices = joint_data[0] link_length = joint_data[1] radius = joint_data[2] self._constructors['Chain'](vertices, link_length, radius, share=False) def send_event(self, text): self._collab.post(dict(action='text', text=text)) def _load_project(self, button): chooser = ObjectChooser(parent=self) result = chooser.run() if result == Gtk.ResponseType.ACCEPT: dsobject = chooser.get_selected_object() file_path = dsobject.get_file_path() self.__load_game(file_path, True) chooser.destroy() def __load_game(self, file_path, journal=False): confirmation_alert = ConfirmationAlert() confirmation_alert.props.title = _('Are You Sure?') confirmation_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') def action(alert, response): self.remove_alert(alert) if response is not Gtk.ResponseType.OK: return try: f = open(file_path, 'r') # Test if the file is valid project. json.loads(f.read()) f.close() self.read_file(file_path) self.game.run(True) except: title = _('Load project from journal') if not journal: title = _('Load example') msg = _( 'Error: Cannot open Physics project from this file.') alert = NotifyAlert(5) alert.props.title = title alert.props.msg = msg alert.connect( 'response', lambda alert, response: self.remove_alert(alert)) self.add_alert(alert) confirmation_alert.connect('response', action) self.add_alert(confirmation_alert) def _create_store(self, widget=None): width = Gdk.Screen.width() / 4 height = Gdk.Screen.height() / 4 if self._sample_window is None: self._sample_box = Gtk.EventBox() vbox = Gtk.VBox() self._sample_window = Gtk.ScrolledWindow() self._sample_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self._sample_window.set_border_width(4) w = Gdk.Screen.width() / 2 h = Gdk.Screen.height() / 2 self._sample_window.set_size_request(w, h) self._sample_window.show() store = Gtk.ListStore(GdkPixbuf.Pixbuf, str) icon_view = Gtk.IconView() icon_view.set_model(store) icon_view.set_selection_mode(Gtk.SelectionMode.SINGLE) icon_view.connect('selection-changed', self._sample_selected, store) icon_view.set_pixbuf_column(0) icon_view.grab_focus() self._sample_window.add(icon_view) icon_view.show() self._fill_samples_list(store) title = Gtk.HBox() title_label = Gtk.Label(_("Select a sample...")) separator = Gtk.HSeparator() separator.props.expand = True separator.props.visible = False btn = Gtk.Button.new_from_stock(Gtk.STOCK_CANCEL) btn.connect('clicked', lambda button: self._sample_box.hide()) title.pack_start(title_label, False, False, 5) title.pack_start(separator, False, False, 0) title.pack_end(btn, False, False, 0) vbox.pack_start(title, False, False, 5) vbox.pack_end(self._sample_window, True, True, 0) self._sample_box.add(vbox) self._fixed.put(self._sample_box, width, height) if self._sample_window: # Remove and add again. Maybe its on portrait mode. self._fixed.remove(self._sample_box) self._fixed.put(self._sample_box, width, height) self._sample_box.show_all() def _get_selected_path(self, widget, store): try: iter_ = store.get_iter(widget.get_selected_items()[0]) image_path = store.get(iter_, 1)[0] return image_path, iter_ except: return None def _sample_selected(self, widget, store): selected = self._get_selected_path(widget, store) if selected is None: self._selected_sample = None self._sample_box.hide() return image_path, _iter = selected iter_ = store.get_iter(widget.get_selected_items()[0]) image_path = store.get(iter_, 1)[0] self._selected_sample = image_path self._sample_box.hide() self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) GObject.idle_add(self._sample_loader) def _sample_loader(self): # Convert from thumbnail path to sample path basename = os.path.basename(self._selected_sample)[:-4] file_path = os.path.join(activity.get_bundle_path(), 'samples', basename + '.json') self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) self.__load_game(file_path) def _fill_samples_list(self, store): ''' Append images from the artwork_paths to the store. ''' for filepath in self._scan_for_samples(): pixbuf = None pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filepath, 100, 100) store.append([pixbuf, filepath]) def _scan_for_samples(self): samples = sorted( glob.glob( os.path.join( activity.get_bundle_path(), 'samples', 'thumbnails', '*.png'))) return samples
class PhysicsActivity(activity.Activity): def __init__(self, handle): super(PhysicsActivity, self).__init__(handle) self.metadata['mime_type'] = 'application/x-physics-activity' self.add_events(Gdk.EventMask.ALL_EVENTS_MASK | Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self.connect('visibility-notify-event', self._focus_event) self.connect('window-state-event', self._window_event) self.game_canvas = sugargame.canvas.PygameCanvas(self) self.game = physics.main(self) self.preview = None self._sample_window = None self._fixed = Gtk.Fixed() self._fixed.put(self.game_canvas, 0, 0) w = Gdk.Screen.width() h = Gdk.Screen.height() - 2 * GRID_CELL_SIZE self.game_canvas.set_size_request(w, h) self._constructors = {} self.build_toolbar() self.set_canvas(self._fixed) Gdk.Screen.get_default().connect('size-changed', self.__configure_cb) logging.debug(os.path.join( activity.get_activity_root(), 'data', 'data')) self.game_canvas.run_pygame(self.game.run) GObject.idle_add(self._setup_sharing) self.show_all() def _setup_sharing(self): self.we_are_sharing = False if self.shared_activity: # We're joining if not self.get_shared(): xocolors = XoColor(profile.get_color().to_string()) share_icon = Icon(icon_name='zoom-neighborhood', xo_color=xocolors) self._joined_alert = Alert() self._joined_alert.props.icon = share_icon self._joined_alert.props.title = _('Please wait') self._joined_alert.props.msg = _('Starting connection...') self.add_alert(self._joined_alert) self._waiting_cursor() self._setup_presence_service() def __configure_cb(self, event): ''' Screen size has changed ''' self.write_file(os.path.join( activity.get_activity_root(), 'data', 'data')) w = Gdk.Screen.width() h = Gdk.Screen.height() - 2 * GRID_CELL_SIZE pygame.display.set_mode((w, h), pygame.RESIZABLE) self.read_file(os.path.join( activity.get_activity_root(), 'data', 'data')) self.game.run(True) def read_file(self, file_path): self.game.read_file(file_path) def write_file(self, file_path): self.game.write_file(file_path) def get_preview(self): ''' Custom preview code to get image from pygame. ''' return self.game_canvas.get_preview() def build_toolbar(self): self.max_participants = 4 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() create_toolbar = ToolbarButton() create_toolbar.props.page = Gtk.Toolbar() create_toolbar.props.icon_name = 'magicpen' create_toolbar.props.label = _('Create') toolbar_box.toolbar.insert(create_toolbar, -1) self._insert_create_tools(create_toolbar) self._insert_stop_play_button(toolbar_box.toolbar) clear_trace = ToolButton('clear-trace') clear_trace.set_tooltip(_('Clear Trace Marks')) clear_trace.set_accelerator(_('<ctrl>x')) clear_trace.connect('clicked', self.clear_trace_cb) clear_trace.set_sensitive(False) toolbar_box.toolbar.insert(clear_trace, -1) clear_trace.show() self.clear_trace = clear_trace self._insert_clear_all_button(toolbar_box.toolbar) load_example = ToolButton('load-sample') load_example.set_tooltip(_('Show sample projects')) load_example.connect('clicked', self._create_store) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_box.toolbar.insert(load_example, -1) load_example.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) stop.show() separator = Gtk.SeparatorToolItem() activity_button.props.page.insert(separator, -1) separator.show() export_json = ToolButton('save-as-json') export_json.set_tooltip(_('Export tracked objects to journal')) export_json.connect('clicked', self._export_json_cb) activity_button.props.page.insert(export_json, -1) export_json.show() export_csv = ToolButton('save-as-csv') export_csv.set_tooltip(_('Export tracked objects to journal')) export_csv.connect('clicked', self._export_csv_cb) activity_button.props.page.insert(export_csv, -1) export_csv.show() load_project = ToolButton('load-project') load_project.set_tooltip(_('Load project from journal')) load_project.connect('clicked', self._load_project) activity_button.props.page.insert(load_project, -1) load_project.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() create_toolbar.set_expanded(True) return toolbar_box def can_close(self): self.preview = self.get_preview() self.game.loop = False return True def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = 'media-playback-stop' self.stop_play_state = True self.stop_play = ToolButton('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play.set_accelerator(_('<ctrl>space')) self.stop_play.connect('clicked', self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name('slow-walk-milton-raposo') slowest_button.set_tooltip(_('Run slower')) slowest_button.connect('clicked', self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name('walking') slow_button.set_tooltip(_('Run slow')) slow_button.connect('clicked', self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name('running') fast_button.set_tooltip('Run fast') fast_button.connect('clicked', self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all() def _set_fps_cb(self, button, value): self.game.set_game_fps(value) def _insert_clear_all_button(self, toolbar): self.clear_all = ToolButton('clear_all') self.clear_all.set_tooltip(_('Erase All')) self.clear_all.set_accelerator(_('<ctrl>a')) self.clear_all.connect('clicked', self.clear_all_cb) toolbar.insert(self.clear_all, -1) self.clear_all.set_sensitive(False) self.clear_all.show() def _insert_item(self, toolbar, item, pos=-1): if hasattr(toolbar, 'insert'): toolbar.insert(item, pos) else: toolbar.props.page.insert(item, pos) def _insert_create_tools(self, create_toolbar): # Make + add the component buttons self.radioList = {} for i, c in enumerate(tools.allTools): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(c.icon) button.set_tooltip(c.toolTip) button.set_accelerator(c.toolAccelerator) button.connect('clicked', self.radioClicked) palette = self._build_palette(c) if palette is not None: palette.show() button.get_palette().set_content(palette) self._insert_item(create_toolbar, button, -1) button.show() self.radioList[button] = c.name if hasattr(c, 'constructor'): self._constructors[c.name] = \ self.game.toolList[c.name].constructor def __icon_path(self, name): activity_path = activity.get_bundle_path() icon_path = os.path.join(activity_path, 'icons', name + '.svg') return icon_path def _build_palette(self, tool): if tool.palette_enabled: if tool.palette_mode == tools.PALETTE_MODE_ICONS: grid = Gtk.Grid() for s, settings in enumerate(tool.palette_settings): self.game.toolList[tool.name].buttons.append([]) for i, icon_value in enumerate(settings['icon_values']): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(settings['icons'][i]) button.connect('clicked', self._palette_icon_clicked, tool.name, s, settings['name'], icon_value) grid.attach(button, i, s, 1, 1) self.game.toolList[tool.name].buttons[s].append(button) button.show() if settings['active'] == settings['icons'][i]: button.set_icon_name(settings['icons'][i] + '-selected') button.set_active(True) return grid else: return None def _palette_icon_clicked(self, widget, toolname, s, value_name, value): for tool in tools.allTools: if tool.name == toolname: # Radio buttons are not highlighting in the palette # so adding highlight by hand # See http://bugs.sugarlabs.org/ticket/305 setting = self.game.toolList[tool.name].palette_settings[s] for i, button in enumerate( self.game.toolList[tool.name].buttons[s]): icon_name = setting['icons'][i] if button == widget: button.set_icon_name(icon_name + '-selected') else: button.set_icon_name(icon_name) if hasattr(tool, 'palette_data_type'): tool.palette_data_type = value else: tool.palette_data[value_name] = value def clear_trace_alert_cb(self, alert, response): self.remove_alert(alert) if response is Gtk.ResponseType.OK: self.game.full_pos_list = [[] for _ in self.game.full_pos_list] self.game.tracked_bodies = 0 def clear_trace_cb(self, button): clear_trace_alert = ConfirmationAlert() clear_trace_alert.props.title = _('Are You Sure?') clear_trace_alert.props.msg = \ _('All trace points will be erased. This cannot be undone!') clear_trace_alert.connect('response', self.clear_trace_alert_cb) self.add_alert(clear_trace_alert) def stop_play_cb(self, button): pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='stop_start_toggle')) self.stop_play_state = not self.stop_play_state if self.stop_play_state: self.stop_play.set_icon_name('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play_toolbar.set_icon_name('media-playback-stop') else: self.stop_play.set_icon_name('media-playback-start') self.stop_play.set_tooltip(_('Start')) self.stop_play_toolbar.set_icon_name('media-playback-start') def clear_all_cb(self, button): def clear_all_alert_cb(alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='clear_all')) if len(self.game.world.world.GetBodyList()) > 2: clear_all_alert = ConfirmationAlert() clear_all_alert.props.title = _('Are You Sure?') clear_all_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') clear_all_alert.connect('response', clear_all_alert_cb) self.add_alert(clear_all_alert) def radioClicked(self, button): pygame.event.post(pygame.event.Event(pygame.USEREVENT, action=self.radioList[button])) def _focus_event(self, event, data=None): ''' Send focus events to pygame to allow it to idle when in background. ''' if not self.game.pygame_started: logging.debug('focus_event: pygame not yet initialized') return if data.state == Gdk.VisibilityState.FULLY_OBSCURED: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='focus_out')) else: self.game.show_fake_cursor = True pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='focus_in')) def _export_json_cb(self, button): jobject = datastore.create() jobject.metadata['title'] = _('Physics export') jobject.metadata['mime_type'] = 'text/plain' tmp_dir = os.path.join(self.get_activity_root(), 'instance') fd, file_path = tempfile.mkstemp(dir=tmp_dir) os.close(fd) data = self.game.full_pos_list jsonfile = open(file_path, 'wb') jsonfile.write(json.dumps(data)) jsonfile.close() jobject.set_file_path(os.path.abspath(jsonfile.name)) datastore.write(jobject) def _export_csv_cb(self, button): jobject = datastore.create() jobject.metadata['title'] = _('Physics export') jobject.metadata['mime_type'] = 'text/csv' tmp_dir = os.path.join(self.get_activity_root(), 'instance') fd, file_path = tempfile.mkstemp(dir=tmp_dir) os.close(fd) data = self.game.full_pos_list csvfile = open(file_path, 'wb') writer = csv.writer(csvfile) writer.writerows(data) csvfile.close() jobject.set_file_path(os.path.abspath(csvfile.name)) datastore.write(jobject) def _window_event(self, window, event): ''' Send focus out event to pygame when switching to a desktop view. ''' if event.changed_mask & Gdk.WindowState.ICONIFIED: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='focus_out')) def _setup_presence_service(self): ''' Setup the Presence Service. ''' self.pservice = presenceservice.get_instance() owner = self.pservice.get_owner() self.owner = owner self.buddies = [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...''' if self.get_shared_activity() is None: logging.error('Failed to share or join activity ... \ shared_activity is null in _shared_cb()') return self.initiating = True self.waiting = False self.we_are_sharing = True logging.debug('I am sharing...') 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) logging.debug('This is my activity: making a tube...') id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _joined_cb(self, activity): ''' ...or join an exisiting share. ''' if self.get_shared_activity() is None: logging.error('Failed to share or join activity ... \ shared_activity is null in _shared_cb()') return self.initiating = False logging.debug('I joined a shared activity.') 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) logging.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.waiting = True if self._joined_alert is not None: self.remove_alert(self._joined_alert) self._joined_alert = None self._restore_cursor() self.we_are_sharing = True def _restore_cursor(self): ''' No longer waiting, so restore standard cursor. ''' if not hasattr(self, 'get_window'): return self.get_window().set_cursor(self.old_cursor) def _waiting_cursor(self): ''' Waiting, so set watch cursor. ''' if not hasattr(self, 'get_window'): return self.old_cursor = self.get_window().get_cursor() self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) 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. ''' logging.error('ListTubes() failed: %s', e) def _new_tube_cb(self, id, initiator, type, service, params, state): ''' Create a new tube. ''' logging.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 event_received_cb(self, text): ''' Data is passed as tuples: cmd:text ''' dispatch_table = {'C': self._construct_shared_circle, 'B': self._construct_shared_box, 'T': self._construct_shared_triangle, 'P': self._construct_shared_polygon, 'M': self._construct_shared_magicpen, 'j': self._add_shared_joint, 'p': self._add_shared_pin, 'm': self._add_shared_motor, 't': self._add_shared_track, 'c': self._add_shared_chain, } logging.debug('<<< %s' % (text[0])) dispatch_table[text[0]](text[2:]) def _construct_shared_circle(self, data): circle_data = json.loads(data) pos = circle_data[0] radius = circle_data[1] density = circle_data[2] restitution = circle_data[3] friction = circle_data[4] self._constructors['Circle'](pos, radius, density, restitution, friction, share=False) def _construct_shared_box(self, data): box_data = json.loads(data) pos1 = box_data[0] pos2 = box_data[1] density = box_data[2] restitution = box_data[3] friction = box_data[4] self._constructors['Box'](pos1, pos2, density, restitution, friction, share=False) def _construct_shared_triangle(self, data): triangle_data = json.loads(data) pos1 = triangle_data[0] pos2 = triangle_data[1] density = triangle_data[2] restitution = triangle_data[3] friction = triangle_data[4] self._constructors['Triangle'](pos1, pos2, density, restitution, friction, share=False) def _construct_shared_polygon(self, data): polygon_data = json.loads(data) vertices = polygon_data[0] density = polygon_data[1] restitution = polygon_data[2] friction = polygon_data[3] self._constructors['Polygon'](vertices, density, restitution, friction, share=False) def _construct_shared_magicpen(self, data): magicpen_data = json.loads(data) vertices = magicpen_data[0] density = magicpen_data[1] restitution = magicpen_data[2] friction = magicpen_data[3] self._constructors['Magicpen'](vertices, density, restitution, friction, share=False) def _add_shared_joint(self, data): joint_data = json.loads(data) pos1 = joint_data[0] pos2 = joint_data[1] self._constructors['Joint'](pos1, pos2, share=False) def _add_shared_pin(self, data): joint_data = json.loads(data) pos = joint_data[0] self._constructors['Pin'](pos, share=False) def _add_shared_motor(self, data): joint_data = json.loads(data) pos = joint_data[0] speed = joint_data[1] self._constructors['Motor'](pos, speed, share=False) def _add_shared_track(self, data): joint_data = json.loads(data) pos = joint_data[0] color = joint_data[1] self._constructors['Track'](pos, color, share=False) def _add_shared_chain(self, data): joint_data = json.loads(data) vertices = joint_data[0] link_length = joint_data[1] radius = joint_data[2] self._constructors['Chain'](vertices, link_length, radius, share=False) def send_event(self, text): ''' Send event through the tube. ''' if hasattr(self, 'chattube') and self.chattube is not None: logging.debug('>>> %s' % (text[0])) self.chattube.SendText(text) def _load_project(self, button): chooser = ObjectChooser(parent=self) result = chooser.run() if result == Gtk.ResponseType.ACCEPT: dsobject = chooser.get_selected_object() file_path = dsobject.get_file_path() self.__load_game(file_path, True) chooser.destroy() def __load_game(self, file_path, journal=False): confirmation_alert = ConfirmationAlert() confirmation_alert.props.title = _('Are You Sure?') confirmation_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') def action(alert, response): self.remove_alert(alert) if not response is Gtk.ResponseType.OK: return try: f = open(file_path, 'r') # Test if the file is valid project. json.loads(f.read()) f.close() self.read_file(file_path) self.game.run(True) except: title = _('Load project from journal') if not journal: title = _('Load example') msg = _( 'Error: Cannot open Physics project from this file.') alert = NotifyAlert(5) alert.props.title = title alert.props.msg = msg alert.connect( 'response', lambda alert, response: self.remove_alert(alert)) self.add_alert(alert) confirmation_alert.connect('response', action) self.add_alert(confirmation_alert) def _create_store(self, widget=None): width = Gdk.Screen.width() / 4 height = Gdk.Screen.height() / 4 if self._sample_window is None: self._sample_box = Gtk.EventBox() vbox = Gtk.VBox() self._sample_window = Gtk.ScrolledWindow() self._sample_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self._sample_window.set_border_width(4) w = Gdk.Screen.width() / 2 h = Gdk.Screen.height() / 2 self._sample_window.set_size_request(w, h) self._sample_window.show() store = Gtk.ListStore(GdkPixbuf.Pixbuf, str) icon_view = Gtk.IconView() icon_view.set_model(store) icon_view.set_selection_mode(Gtk.SelectionMode.SINGLE) icon_view.connect('selection-changed', self._sample_selected, store) icon_view.set_pixbuf_column(0) icon_view.grab_focus() self._sample_window.add(icon_view) icon_view.show() self._fill_samples_list(store) title = Gtk.HBox() title_label = Gtk.Label(_("Select a sample...")) separator = Gtk.HSeparator() separator.props.expand = True separator.props.visible = False btn = Gtk.Button.new_from_stock(Gtk.STOCK_CANCEL) btn.connect('clicked', lambda button: self._sample_box.hide()) title.pack_start(title_label, False, False, 5) title.pack_start(separator, False, False, 0) title.pack_end(btn, False, False, 0) vbox.pack_start(title, False, False, 5) vbox.pack_end(self._sample_window, True, True, 0) self._sample_box.add(vbox) self._fixed.put(self._sample_box, width, height) if self._sample_window: # Remove and add again. Maybe its on portrait mode. self._fixed.remove(self._sample_box) self._fixed.put(self._sample_box, width, height) self._sample_box.show_all() def _get_selected_path(self, widget, store): try: iter_ = store.get_iter(widget.get_selected_items()[0]) image_path = store.get(iter_, 1)[0] return image_path, iter_ except: return None def _sample_selected(self, widget, store): selected = self._get_selected_path(widget, store) if selected is None: self._selected_sample = None self._sample_box.hide() return image_path, _iter = selected iter_ = store.get_iter(widget.get_selected_items()[0]) image_path = store.get(iter_, 1)[0] self._selected_sample = image_path self._sample_box.hide() self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) GObject.idle_add(self._sample_loader) def _sample_loader(self): # Convert from thumbnail path to sample path basename = os.path.basename(self._selected_sample)[:-4] file_path = os.path.join(activity.get_bundle_path(), 'samples', basename + '.json') self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) self.__load_game(file_path) def _fill_samples_list(self, store): ''' Append images from the artwork_paths to the store. ''' for filepath in self._scan_for_samples(): pixbuf = None pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filepath, 100, 100) store.append([pixbuf, filepath]) def _scan_for_samples(self): samples = sorted( glob.glob( os.path.join( activity.get_bundle_path(), 'samples', 'thumbnails', '*.png'))) return samples
def _build_toolbox(self): toolbar_box = ToolbarBox() self.max_participants = 1 activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page self._toolbar = toolbar_box.toolbar self._toolbar.insert(activity_button, -1) self._secondary_toolbar = Gtk.Toolbar() self._secondary_toolbar_button = ToolbarButton( page=self._secondary_toolbar, icon_name='system-search') self._secondary_toolbar.show() self._toolbar.insert(self._secondary_toolbar_button, -1) self._secondary_toolbar_button.hide() show_list = ToggleToolButton('view-list') show_list.set_active(True) show_list.set_tooltip(_('Show list of files')) show_list.connect('toggled', self._list_toggled_cb) self._toolbar.insert(show_list, -1) show_list.show() copy = CopyButton() copy.connect('clicked', self.__copy_clicked_cb) self._toolbar.insert(copy, -1) wrap_btn = ToggleToolButton("format-wrap") wrap_btn.set_tooltip(_('Word Wrap')) wrap_btn.connect('clicked', self._wrap_cb) self._toolbar.insert(wrap_btn, -1) self.search_entry = iconentry.IconEntry() self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1) self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'entry-search') self.search_entry.add_clear_button() self.search_entry.connect('activate', self._search_entry_activate_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self._search_item = Gtk.ToolItem() self._search_item.add(self.search_entry) self._toolbar.insert(self._search_item, -1) self._search_prev = ToolButton('go-previous-paired') self._search_prev.set_tooltip(_('Previous')) self._search_prev.connect('clicked', self._search_prev_cb) self._toolbar.insert(self._search_prev, -1) self._search_next = ToolButton('go-next-paired') self._search_next.set_tooltip(_('Next')) self._search_next.connect('clicked', self._search_next_cb) self._toolbar.insert(self._search_next, -1) self._update_search_buttons() self.collector_palette = CollectorPalette(self) collector_btn = ToolButton('log-export') collector_btn.set_palette(self.collector_palette) collector_btn.connect('clicked', self._logviewer_cb) collector_btn.show() activity_toolbar.insert(collector_btn, -1) self._delete_btn = ToolButton('list-remove') self._delete_btn.set_tooltip(_('Delete Log File')) self._delete_btn.connect('clicked', self._delete_log_cb) self._toolbar.insert(self._delete_btn, -1) self._separator = Gtk.SeparatorToolItem() self._separator.set_expand(True) self._separator.set_draw(False) self._toolbar.insert(self._separator, -1) self._stop_btn = StopButton(self) self._toolbar.insert(self._stop_btn, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box)
def __init__(self, handle): activity.Activity.__init__(self, handle) _logger.debug('Starting the web activity') session = WebKit.get_default_session() session.set_property('accept-language-auto', True) session.set_property('ssl-use-system-ca-file', True) session.set_property('ssl-strict', False) # By default, cookies are not stored persistently, we have to # add a cookie jar so that they get saved to disk. We use one # with a SQlite database: cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path, read_only=False) session.add_feature(cookie_jar) _seed_xs_cookie(cookie_jar) # FIXME # downloadmanager.remove_old_parts() self._force_close = False self._tabbed_view = TabbedView() self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._tray = HTray() self.set_tray(self._tray, Gtk.PositionType.BOTTOM) self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) self._view_toolbar = ViewToolbar(self) self._primary_toolbar.connect('add-link', self._link_add_button_cb) self._primary_toolbar.connect('go-home', self._go_home_button_cb) self._primary_toolbar.connect('go-library', self._go_library_button_cb) self._primary_toolbar.connect('set-home', self._set_home_button_cb) self._primary_toolbar.connect('reset-home', self._reset_home_button_cb) self._edit_toolbar_button = ToolbarButton( page=self._edit_toolbar, icon_name='toolbar-edit') self._primary_toolbar.toolbar.insert( self._edit_toolbar_button, 1) view_toolbar_button = ToolbarButton( page=self._view_toolbar, icon_name='toolbar-view') self._primary_toolbar.toolbar.insert( view_toolbar_button, 2) self._primary_toolbar.show_all() self.set_toolbar_box(self._primary_toolbar) self.set_canvas(self._tabbed_view) self._tabbed_view.show() self.model = Model() self.model.connect('add_link', self._add_link_model_cb) self.connect('key-press-event', self._key_press_cb) if handle.uri: self._tabbed_view.current_browser.load_uri(handle.uri) elif not self._jobject.file_path: # TODO: we need this hack until we extend the activity API for # opening URIs and default docs. self._tabbed_view.load_homepage() self.messenger = None self.connect('shared', self._shared_cb) # Get the Presence Service self.pservice = presenceservice.get_instance() try: name, path = self.pservice.get_preferred_connection() self.tp_conn_name = name self.tp_conn_path = path self.conn = telepathy.client.Connection(name, path) except TypeError: _logger.debug('Offline') self.initiating = None if self.get_shared_activity() is not None: _logger.debug('shared: %s', self.get_shared()) # We are joining the activity _logger.debug('Joined activity') self.connect('joined', self._joined_cb) if self.get_shared(): # We've already joined self._joined_cb() else: _logger.debug('Created activity') # README: this is a workaround to remove old temp file # http://bugs.sugarlabs.org/ticket/3973 self._cleanup_temp_files()
def __init__(self, handle): activity.Activity.__init__(self, handle) # abiword uses the current directory for all its file dialogs os.chdir(os.path.expanduser('~')) # create our main abiword canvas self.abiword_canvas = DocumentView() self._new_instance = True toolbar_box = ToolbarBox() self.activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(self.activity_button, -1) separator = Gtk.SeparatorToolItem() separator.show() self.activity_button.props.page.insert(separator, 2) ExportButtonFactory(self, self.abiword_canvas) self.activity_button.show() edit_toolbar = ToolbarButton() edit_toolbar.props.page = EditToolbar(self, toolbar_box) edit_toolbar.props.icon_name = 'toolbar-edit' edit_toolbar.props.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar, -1) view_toolbar = ToolbarButton() view_toolbar.props.page = ViewToolbar(self.abiword_canvas) view_toolbar.props.icon_name = 'toolbar-view' view_toolbar.props.label = _('View') toolbar_box.toolbar.insert(view_toolbar, -1) # due to http://bugzilla.abisource.com/show_bug.cgi?id=13585 if self.abiword_canvas.get_version() != '3.0': self.speech_toolbar_button = ToolbarButton(icon_name='speak') toolbar_box.toolbar.insert(self.speech_toolbar_button, -1) self._init_speech() separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) text_toolbar = ToolbarButton() text_toolbar.props.page = TextToolbar(self.abiword_canvas) text_toolbar.props.icon_name = 'format-text' text_toolbar.props.label = _('Text') toolbar_box.toolbar.insert(text_toolbar, -1) para_toolbar = ToolbarButton() para_toolbar.props.page = ParagraphToolbar(self.abiword_canvas) para_toolbar.props.icon_name = 'paragraph-bar' para_toolbar.props.label = _('Paragraph') toolbar_box.toolbar.insert(para_toolbar, -1) insert_toolbar = ToolbarButton() insert_toolbar.props.page = InsertToolbar(self.abiword_canvas) insert_toolbar.props.icon_name = 'insert-table' insert_toolbar.props.label = _('Table') toolbar_box.toolbar.insert(insert_toolbar, -1) image = ToolButton('insert-picture') image.set_tooltip(_('Insert Image')) self._image_id = image.connect('clicked', self._image_cb) toolbar_box.toolbar.insert(image, -1) palette = image.get_palette() content_box = Gtk.VBox() palette.set_content(content_box) image_floating_checkbutton = Gtk.CheckButton(_('Floating')) image_floating_checkbutton.connect( 'toggled', self._image_floating_checkbutton_toggled_cb) content_box.pack_start(image_floating_checkbutton, True, True, 0) content_box.show_all() self.floating_image = False separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) separator.show() toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box) # add a overlay to be able to show a icon while joining a shared doc overlay = Gtk.Overlay() overlay.add(self.abiword_canvas) overlay.show() self._connecting_box = ConnectingBox() overlay.add_overlay(self._connecting_box) self.set_canvas(overlay) # we want a nice border so we can select paragraphs easily self.abiword_canvas.set_show_margin(True) # Read default font face and size client = GConf.Client.get_default() self._default_font_face = client.get_string( '/desktop/sugar/activities/write/font_face') if not self._default_font_face: self._default_font_face = 'Sans' self._default_font_size = client.get_int( '/desktop/sugar/activities/write/font_size') if self._default_font_size == 0: self._default_font_size = 12 # activity sharing self.participants = {} self.joined = False self.connect('shared', self._shared_cb) if self.shared_activity: # we are joining the activity logger.error('We are joining an activity') # display a icon while joining self._connecting_box.show() # disable the abi widget self.abiword_canvas.set_sensitive(False) self._new_instance = False self.connect('joined', self._joined_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) if self.get_shared(): self._joined_cb(self) else: # we are creating the activity logger.error("We are creating an activity") self.abiword_canvas.zoom_width() self.abiword_canvas.show() self.connect_after('map-event', self.__map_activity_event_cb) self.abiword_canvas.connect('size-allocate', self.size_allocate_cb)
def _build_toolbox(self): toolbar_box = ToolbarBox() self.max_participants = 1 activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page self._toolbar = toolbar_box.toolbar self._toolbar.insert(activity_button, -1) self._secondary_toolbar = Gtk.Toolbar() self._secondary_toolbar_button = ToolbarButton( page=self._secondary_toolbar, icon_name='system-search') self._secondary_toolbar.show() self._toolbar.insert(self._secondary_toolbar_button, -1) self._secondary_toolbar_button.hide() show_list = ToggleToolButton('view-list') show_list.set_active(True) show_list.set_tooltip(_('Show list of files')) show_list.connect('toggled', self._list_toggled_cb) self._toolbar.insert(show_list, -1) show_list.show() copy = CopyButton() copy.connect('clicked', self.__copy_clicked_cb) self._toolbar.insert(copy, -1) wrap_btn = ToggleToolButton("format-wrap") wrap_btn.set_tooltip(_('Word Wrap')) wrap_btn.connect('clicked', self._wrap_cb) self._toolbar.insert(wrap_btn, -1) self.search_entry = iconentry.IconEntry() self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1) self.search_entry.set_icon_from_name( iconentry.ICON_ENTRY_PRIMARY, 'entry-search') self.search_entry.add_clear_button() self.search_entry.connect('activate', self._search_entry_activate_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self._search_item = Gtk.ToolItem() self._search_item.add(self.search_entry) self._toolbar.insert(self._search_item, -1) self._search_prev = ToolButton('go-previous-paired') self._search_prev.set_tooltip(_('Previous')) self._search_prev.connect('clicked', self._search_prev_cb) self._toolbar.insert(self._search_prev, -1) self._search_next = ToolButton('go-next-paired') self._search_next.set_tooltip(_('Next')) self._search_next.connect('clicked', self._search_next_cb) self._toolbar.insert(self._search_next, -1) self._update_search_buttons() self.collector_palette = CollectorPalette(self) collector_btn = ToolButton('log-export') collector_btn.set_palette(self.collector_palette) collector_btn.connect('clicked', self._logviewer_cb) collector_btn.show() activity_toolbar.insert(collector_btn, -1) self._delete_btn = ToolButton('list-remove') self._delete_btn.set_tooltip(_('Delete Log File')) self._delete_btn.connect('clicked', self._delete_log_cb) self._toolbar.insert(self._delete_btn, -1) self._separator = Gtk.SeparatorToolItem() self._separator.set_expand(True) self._separator.set_draw(False) self._toolbar.insert(self._separator, -1) self._stop_btn = StopButton(self) self._toolbar.insert(self._stop_btn, -1) toolbar_box.show_all() self.set_toolbar_box(toolbar_box)
from gi.repository import Gtk from sugar3.graphics.toolbutton import ToolButton from sugar3.graphics.toolbarbox import ToolbarBox, ToolbarButton window = Gtk.Window() box = Gtk.VBox() window.add(box) toolbar = ToolbarBox() box.pack_start(toolbar, False) tollbarbutton_1 = ToolbarButton(page=Gtk.Button('sub-widget #1'), icon_name='computer-xo') toolbar.toolbar.insert(tollbarbutton_1, -1) tollbarbutton_2 = ToolbarButton( page=Gtk.Button('sub-widget #2'), icon_name='button_cancel', tooltip='with custom palette instead of sub-widget') toolbar.toolbar.insert(tollbarbutton_2, -1) toolbar.toolbar.insert(Gtk.SeparatorToolItem(), -1) def del_cb(widget): toolbar.toolbar.remove(tollbarbutton_3) del_b = Gtk.Button('delete sub-widget #3')
class WebActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self._collab = CollabWrapper(self) self._collab.message.connect(self.__message_cb) _logger.debug('Starting the web activity') # TODO PORT # session = WebKit2.get_default_session() # session.set_property('accept-language-auto', True) # session.set_property('ssl-use-system-ca-file', True) # session.set_property('ssl-strict', False) # But of a hack, but webkit doesn't let us change the cookie jar # contents, we we can just pre-seed it cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path, read_only=False) _seed_xs_cookie(cookie_jar) del cookie_jar context = WebKit2.WebContext.get_default() cookie_manager = context.get_cookie_manager() cookie_manager.set_persistent_storage( _cookies_db_path, WebKit2.CookiePersistentStorage.SQLITE) # FIXME # downloadmanager.remove_old_parts() context.connect('download-started', self.__download_requested_cb) self._force_close = False self._tabbed_view = TabbedView(self) self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._titled_tray = TitledTray(_('Bookmarks')) self._tray = self._titled_tray.tray self.set_tray(self._titled_tray, Gtk.PositionType.BOTTOM) self._tray_links = {} self.model = Model() self.model.add_link_signal.connect(self._add_link_model_cb) self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) self._view_toolbar = ViewToolbar(self) self._primary_toolbar.connect('add-link', self.__link_add_button_cb) self._primary_toolbar.connect('remove-link', self.__link_remove_button_cb) self._primary_toolbar.connect('go-home', self._go_home_button_cb) self._primary_toolbar.connect('go-library', self._go_library_button_cb) self._primary_toolbar.connect('set-home', self._set_home_button_cb) self._primary_toolbar.connect('reset-home', self._reset_home_button_cb) self._edit_toolbar_button = ToolbarButton(page=self._edit_toolbar, icon_name='toolbar-edit') self._primary_toolbar.toolbar.insert(self._edit_toolbar_button, 1) view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view') self._primary_toolbar.toolbar.insert(view_toolbar_button, 2) self._primary_toolbar.show_all() self.set_toolbar_box(self._primary_toolbar) self.set_canvas(self._tabbed_view) self._tabbed_view.show() self.connect('key-press-event', self._key_press_cb) if handle.uri: self._tabbed_view.current_browser.load_uri(handle.uri) elif not self._jobject.file_path: # TODO: we need this hack until we extend the activity API for # opening URIs and default docs. self._tabbed_view.load_homepage() # README: this is a workaround to remove old temp file # http://bugs.sugarlabs.org/ticket/3973 self._cleanup_temp_files() self._collab.setup() def __download_requested_cb(self, context, download): if hasattr(self, 'busy'): while self.unbusy() > 0: continue logging.debug('__download_requested_cb %r', download.get_request().get_uri()) downloadmanager.add_download(download, self) return True def unfullscreen(self): activity.Activity.unfullscreen(self) # Always show tabs here, because they are automatically hidden # if it is like a video fullscreening. We ALWAYS need to make # sure these are visible. Don't make the user lost self._tabbed_view.props.show_tabs = True def _cleanup_temp_files(self): """Removes temporary files generated by Download Manager that were cancelled by the user or failed for any reason. There is a bug in GLib that makes this to happen: https://bugzilla.gnome.org/show_bug.cgi?id=629301 """ try: uptime_proc = open('/proc/uptime', 'r').read() uptime = int(float(uptime_proc.split()[0])) except EnvironmentError: logging.warning('/proc/uptime could not be read') uptime = None temp_path = os.path.join(self.get_activity_root(), 'instance') now = int(time.time()) cutoff = now - 24 * 60 * 60 # yesterday if uptime is not None: boot_time = now - uptime cutoff = max(cutoff, boot_time) for f in os.listdir(temp_path): if f.startswith('.goutputstream-'): fpath = os.path.join(temp_path, f) mtime = int(os.path.getmtime(fpath)) if mtime < cutoff: logging.warning('Removing old temporary file: %s', fpath) try: os.remove(fpath) except EnvironmentError: logging.error( 'Temporary file could not be ' 'removed: %s', fpath) def _on_focus_url_entry(self, gobject): self._primary_toolbar.entry.grab_focus() def _get_data_from_file_path(self, file_path): fd = open(file_path, 'r') try: data = fd.read() finally: fd.close() return data def _get_save_as(self): if not hasattr(profile, 'get_save_as'): return False return profile.get_save_as() def read_file(self, file_path): if self.metadata['mime_type'] == 'text/plain': data = self._get_data_from_file_path(file_path) self.model.deserialize(data) for link in self.model.data['shared_links']: _logger.debug('read: url=%s title=%s d=%s' % (link['url'], link['title'], link['color'])) self._add_link_totray(link['url'], b64decode(link['thumb']), link['color'], link['title'], link['owner'], -1, link['hash'], link.get('notes')) logging.debug('########## reading %s', data) if 'session_state' in self.model.data: self._tabbed_view.set_session_state( self.model.data['session_state']) else: self._tabbed_view.set_legacy_history( self.model.data['history'], self.model.data['currents']) for number, tab in enumerate(self.model.data['currents']): tab_page = self._tabbed_view.get_nth_page(number) zoom_level = tab.get('zoom_level') if zoom_level is not None: tab_page.browser.set_zoom_level(zoom_level) tab_page.browser.grab_focus() self._tabbed_view.set_current_page(self.model.data['current_tab']) elif self.metadata['mime_type'] == 'text/uri-list': data = self._get_data_from_file_path(file_path) uris = mime.split_uri_list(data) if len(uris) == 1: self._tabbed_view.props.current_browser.load_uri(uris[0]) else: _logger.error('Open uri-list: Does not support' 'list of multiple uris by now.') else: file_uri = 'file://' + file_path self._tabbed_view.props.current_browser.load_uri(file_uri) self._tabbed_view.props.current_browser.grab_focus() def write_file(self, file_path): if not hasattr(self, '_tabbed_view'): _logger.error('Called write_file before the tabbed_view was made') return if not self.metadata['mime_type']: self.metadata['mime_type'] = 'text/plain' if self.metadata['mime_type'] == 'text/plain': browser = self._tabbed_view.current_browser if not self._jobject.metadata['title_set_by_user'] == '1' and \ not self._get_save_as(): if browser.props.title is None: self.metadata['title'] = _('Untitled') else: self.metadata['title'] = browser.props.title self.model.data['history'] = self._tabbed_view.get_legacy_history() current_tab = self._tabbed_view.get_current_page() self.model.data['current_tab'] = current_tab self.model.data['currents'] = [] for n in range(0, self._tabbed_view.get_n_pages()): tab_page = self._tabbed_view.get_nth_page(n) n_browser = tab_page.browser if n_browser is not None: uri = n_browser.get_uri() history_index = n_browser.get_history_index() info = { 'title': n_browser.props.title, 'url': uri, 'history_index': history_index, 'zoom_level': n_browser.get_zoom_level() } self.model.data['currents'].append(info) self.model.data['session_state'] = \ self._tabbed_view.get_state() f = open(file_path, 'w') try: logging.debug('########## writing %s', self.model.serialize()) f.write(self.model.serialize()) finally: f.close() def __link_add_button_cb(self, button): self._add_link() def __link_remove_button_cb(self, button): browser = self._tabbed_view.props.current_browser uri = browser.get_uri() self.__link_removed_cb(None, sha1(uri).hexdigest()) def _go_home_button_cb(self, button): self._tabbed_view.load_homepage() def _go_library_button_cb(self, button): self._tabbed_view.load_homepage(ignore_gconf=True) def _set_home_button_cb(self, button): self._tabbed_view.set_homepage() self._alert(_('The initial page was configured')) def _reset_home_button_cb(self, button): self._tabbed_view.reset_homepage() self._alert(_('The default initial page was configured')) def _alert(self, title, text=None): alert = NotifyAlert(timeout=5) alert.props.title = title alert.props.msg = text self.add_alert(alert) alert.connect('response', self._alert_cancel_cb) alert.show() def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) def _key_press_cb(self, widget, event): browser = self._tabbed_view.props.current_browser if event.get_state() & Gdk.ModifierType.CONTROL_MASK: if event.keyval == Gdk.KEY_f: self._edit_toolbar_button.set_expanded(True) self._edit_toolbar.search_entry.grab_focus() return True if event.keyval == Gdk.KEY_l: self._primary_toolbar.entry.grab_focus() return True if event.keyval == Gdk.KEY_equal: # On US keyboards, KEY_equal is KEY_plus without # SHIFT_MASK, so for convenience treat this as the # same as the zoom in accelerator configured in # WebKit2 browser.zoom_in() return True if event.keyval == Gdk.KEY_t: self._tabbed_view.add_tab() return True if event.keyval == Gdk.KEY_w: self._tabbed_view.close_tab() return True # FIXME: copy and paste is supposed to be handled by # Gtk.Entry, but does not work when we catch # key-press-event and return False. if self._primary_toolbar.entry.is_focus(): if event.keyval == Gdk.KEY_c: self._primary_toolbar.entry.copy_clipboard() return True if event.keyval == Gdk.KEY_v: self._primary_toolbar.entry.paste_clipboard() return True return False if event.keyval in (Gdk.KEY_KP_Up, Gdk.KEY_KP_Down, Gdk.KEY_KP_Left, Gdk.KEY_KP_Right): scrolled_window = browser.get_parent() if event.keyval in (Gdk.KEY_KP_Up, Gdk.KEY_KP_Down): adjustment = scrolled_window.get_vadjustment() elif event.keyval in (Gdk.KEY_KP_Left, Gdk.KEY_KP_Right): adjustment = scrolled_window.get_hadjustment() value = adjustment.get_value() step = adjustment.get_step_increment() if event.keyval in (Gdk.KEY_KP_Up, Gdk.KEY_KP_Left): adjustment.set_value(value - step) else: adjustment.set_value(value + step) return True if event.keyval == Gdk.KEY_Escape: browser.stop_loading() return False # allow toolbar entry to handle escape too return False def _add_link(self): ''' take screenshot and add link info to the model ''' browser = self._tabbed_view.props.current_browser ui_uri = browser.get_uri() if self.model.has_link(ui_uri): return buf = b64encode(self._get_screenshot()) timestamp = time.time() args = (ui_uri, browser.props.title, buf, profile.get_nick_name(), profile.get_color().to_string(), timestamp) self.model.add_link(*args, by_me=True) self._collab.post({'type': 'add_link', 'args': args}) def __message_cb(self, collab, buddy, message): type_ = message.get('type') if type_ == 'add_link': self.model.add_link(*message['args']) elif type_ == 'add_link_from_info': self.model.add_link_from_info(message['dict']) elif type_ == 'remove_link': self.remove_link(message['hash']) def get_data(self): return self.model.data def set_data(self, data): for link in data['shared_links']: if link['hash'] not in self.model.get_links_ids(): self.model.add_link_from_info(link) # FIXME: Case where buddy has updated link desciption their_model = Model() their_model.data = data for link in self.model.data['shared_links']: if link['hash'] not in their_model.get_links_ids(): self._collab.post({'type': 'add_link_from_info', 'dict': link}) def _add_link_model_cb(self, model, index, by_me): ''' receive index of new link from the model ''' link = self.model.data['shared_links'][index] widget = self._add_link_totray(link['url'], b64decode(link['thumb']), link['color'], link['title'], link['owner'], index, link['hash'], link.get('notes')) if by_me: animator = Animator(1, widget=self) animator.add( AddLinkAnimation(self, self._tabbed_view.props.current_browser, widget)) animator.start() def _add_link_totray(self, url, buf, color, title, owner, index, hash, notes=None): ''' add a link to the tray ''' item = LinkButton(buf, color, title, owner, hash, notes) item.connect('clicked', self._link_clicked_cb, url) item.connect('remove_link', self.__link_removed_cb) item.notes_changed_signal.connect(self.__link_notes_changed) # use index to add to the tray self._tray_links[hash] = item self._tray.add_item(item, index) item.show() self._view_toolbar.traybutton.props.sensitive = True self._view_toolbar.traybutton.props.active = True self._view_toolbar.update_traybutton_tooltip() return item def __link_removed_cb(self, button, hash): self.remove_link(hash) self._collab.post({'type': 'remove_link', 'hash': hash}) def remove_link(self, hash): ''' remove a link from tray and delete it in the model ''' self._tray_links[hash].hide() self._tray_links[hash].destroy() del self._tray_links[hash] self.model.remove_link(hash) if len(self._tray.get_children()) == 0: self._view_toolbar.traybutton.props.sensitive = False self._view_toolbar.traybutton.props.active = False self._view_toolbar.update_traybutton_tooltip() def __link_notes_changed(self, button, hash, notes): self.model.change_link_notes(hash, notes) def _link_clicked_cb(self, button, url): ''' an item of the link tray has been clicked ''' browser = self._tabbed_view.add_tab() browser.load_uri(url) browser.grab_focus() def _get_screenshot(self): browser = self._tabbed_view.props.current_browser window = browser.get_window() width, height = window.get_width(), window.get_height() thumb_surface = Gdk.Window.create_similar_surface( window, cairo.CONTENT_COLOR, THUMB_WIDTH, THUMB_HEIGHT) cairo_context = cairo.Context(thumb_surface) thumb_scale_w = THUMB_WIDTH * 1.0 / width thumb_scale_h = THUMB_HEIGHT * 1.0 / height cairo_context.scale(thumb_scale_w, thumb_scale_h) Gdk.cairo_set_source_window(cairo_context, window, 0, 0) cairo_context.paint() thumb_str = StringIO.StringIO() thumb_surface.write_to_png(thumb_str) return thumb_str.getvalue() def can_close(self): if self._force_close: return True elif downloadmanager.can_quit(): return True else: alert = Alert() alert.props.title = ngettext('Download in progress', 'Downloads in progress', downloadmanager.num_downloads()) message = ngettext('Stopping now will erase your download', 'Stopping now will erase your downloads', downloadmanager.num_downloads()) alert.props.msg = message cancel_icon = Icon(icon_name='dialog-cancel') cancel_label = ngettext('Continue download', 'Continue downloads', downloadmanager.num_downloads()) alert.add_button(Gtk.ResponseType.CANCEL, cancel_label, cancel_icon) stop_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Stop'), stop_icon) stop_icon.show() self.add_alert(alert) alert.connect('response', self.__inprogress_response_cb) alert.show() self.present() return False def __inprogress_response_cb(self, alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.CANCEL: logging.debug('Keep on') elif response_id == Gtk.ResponseType.OK: logging.debug('Stop downloads and quit') self._force_close = True downloadmanager.remove_all_downloads() self.close() def __switch_page_cb(self, tabbed_view, page, page_num): if not hasattr(self, 'busy'): return browser = page._browser progress = browser.props.estimated_load_progress uri = browser.props.uri if progress < 1.0 and uri: self.busy() else: while self.unbusy() > 0: continue def get_document_path(self, async_cb, async_err_cb): browser = self._tabbed_view.props.current_browser browser.get_source(async_cb, async_err_cb) def get_canvas(self): return self._tabbed_view
class Dimensions(activity.Activity): ''' Dimension matching game ''' def __init__(self, handle): ''' Initialize the Sugar activity ''' super(Dimensions, self).__init__(handle) self.ready_to_play = False self._prompt = '' self._read_journal_data() self._sep = [] self._setup_toolbars() self._setup_canvas() if self.shared_activity: # We're joining if not self.get_shared(): xocolors = XoColor(profile.get_color().to_string()) share_icon = Icon(icon_name='zoom-neighborhood', xo_color=xocolors) self._joined_alert = Alert() self._joined_alert.props.icon = share_icon self._joined_alert.props.title = _('Please wait') self._joined_alert.props.msg = _('Starting connection...') self.add_alert(self._joined_alert) # Wait for joined signal self.connect("joined", self._joined_cb) self._setup_presence_service() if not hasattr(self, '_saved_state'): self._saved_state = None self.vmw.new_game(show_selector=True) else: self.vmw.new_game(saved_state=self._saved_state, deck_index=self._deck_index) self.ready_to_play = True if self._editing_word_list: self.vmw.editing_word_list = True self.vmw.edit_word_list() elif self._editing_custom_cards: self.vmw.editing_custom_cards = True self.vmw.edit_custom_card() Gdk.Screen.get_default().connect('size-changed', self._configure_cb) self._configure_cb(None) def _select_game_cb(self, button, card_type): ''' Choose which game we are playing. ''' if self.vmw.joiner(): # joiner cannot change level return # self.vmw.card_type = card_type self._prompt = PROMPT_DICT[card_type] self._load_new_game(card_type) def _load_new_game(self, card_type=None, show_selector=True): if not self.ready_to_play: return # self._notify_new_game(self._prompt) GObject.idle_add(self._new_game, card_type, show_selector) def _new_game(self, card_type, show_selector=True): if card_type == 'custom' and self.vmw.custom_paths[0] is None: self.image_import_cb() else: self.tools_toolbar_button.set_expanded(False) self.vmw.new_game(show_selector=show_selector) def _robot_cb(self, button=None): ''' Toggle robot assist on/off ''' if self.vmw.robot: self.vmw.robot = False self.robot_button.set_tooltip(_('Play with the computer.')) self.robot_button.set_icon_name('robot-off') elif not self.vmw.editing_word_list: self.vmw.robot = True self.robot_button.set_tooltip( _('Stop playing with the computer.')) self.robot_button.set_icon_name('robot-on') def _level_cb(self, button, level): ''' Cycle between levels ''' if self.vmw.joiner(): # joiner cannot change level return self.vmw.level = level # self.level_label.set_text(self.calc_level_label(self.vmw.low_score, # self.vmw.level)) self._load_new_game(show_selector=False) def calc_level_label(self, low_score, play_level): ''' Show the score. ''' if low_score[play_level] == -1: return LEVEL_LABELS[play_level] else: return '%s (%d:%02d)' % \ (LEVEL_LABELS[play_level], int(low_score[play_level] / 60), int(low_score[play_level] % 60)) def image_import_cb(self, button=None): ''' Import custom cards from the Journal ''' self.vmw.editing_custom_cards = True self.vmw.editing_word_list = False self.vmw.edit_custom_card() if self.vmw.robot: self._robot_cb(button) def _number_card_O_cb(self, button, numberO): ''' Choose between O-card list for numbers game. ''' if self.vmw.joiner(): # joiner cannot change decks return self.vmw.numberO = numberO self.vmw.card_type = 'number' self._load_new_game() def _number_card_C_cb(self, button, numberC): ''' Choose between C-card list for numbers game. ''' if self.vmw.joiner(): # joiner cannot change decks return self.vmw.numberC = numberC self.vmw.card_type = 'number' self._load_new_game() def _edit_words_cb(self, button): ''' Edit the word list. ''' self.vmw.editing_word_list = True self.vmw.editing_custom_cards = False self.vmw.edit_word_list() if self.vmw.robot: self._robot_cb(button) def _read_metadata(self, keyword, default_value, json=False): ''' If the keyword is found, return stored value ''' if keyword in self.metadata: data = self.metadata[keyword] else: data = default_value if json: try: return jloads(data) except: pass return data def _read_journal_data(self): ''' There may be data from a previous instance. ''' self._play_level = int(self._read_metadata('play_level', 0)) self._robot_time = int(self._read_metadata('robot_time', ROBOT_TIMER_DEFAULT)) self._card_type = self._read_metadata('cardtype', MODE) self._low_score = [int(self._read_metadata('low_score_beginner', -1)), int(self._read_metadata('low_score_intermediate', -1)), int(self._read_metadata('low_score_expert', -1))] self._all_scores = self._read_metadata( 'all_scores', '{"pattern": [], "word": [], "number": [], "custom": []}', True) self._numberO = int(self._read_metadata('numberO', PRODUCT)) self._numberC = int(self._read_metadata('numberC', HASH)) self._matches = int(self._read_metadata('matches', 0)) self._robot_matches = int(self._read_metadata('robot_matches', 0)) self._total_time = int(self._read_metadata('total_time', 0)) self._deck_index = int(self._read_metadata('deck_index', 0)) self._word_lists = [[self._read_metadata('mouse', _('mouse')), self._read_metadata('cat', _('cat')), self._read_metadata('dog', _('dog'))], [self._read_metadata('cheese', _('cheese')), self._read_metadata('apple', _('apple')), self._read_metadata('bread', _('bread'))], [self._read_metadata('moon', _('moon')), self._read_metadata('sun', _('sun')), self._read_metadata('earth', _('earth'))]] self._editing_word_list = bool(int(self._read_metadata( 'editing_word_list', 0))) self._editing_custom_cards = bool(int(self._read_metadata( 'editing_custom_cards', 0))) if self._card_type == 'custom': self._custom_object = self._read_metadata('custom_object', None) if self._custom_object is None: self._card_type = MODE self._custom_jobject = [] for i in range(9): self._custom_jobject.append(self._read_metadata( 'custom_' + str(i), None)) def _write_scores_to_clipboard(self, button=None): ''' SimpleGraph will plot the cululative results ''' jscores = '' c = 0 for key in self.vmw.all_scores.keys(): for data in self.vmw.all_scores[key]: jscores += '%s: %s\n' % (str(c + 1), data[1]) c += 1 clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clipboard.set_text(jscores, -1) def _setup_toolbars(self): ''' Setup the toolbars.. ''' tools_toolbar = Gtk.Toolbar() numbers_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() self.activity_toolbar_button = ActivityToolbarButton(self) toolbox.toolbar.insert(self.activity_toolbar_button, 0) self.activity_toolbar_button.show() self.numbers_toolbar_button = ToolbarButton( page=numbers_toolbar, icon_name='number-tools') if MODE == 'number': numbers_toolbar.show() toolbox.toolbar.insert(self.numbers_toolbar_button, -1) self.numbers_toolbar_button.show() self.tools_toolbar_button = ToolbarButton( page=tools_toolbar, icon_name='view-source') self.button_pattern = button_factory( 'new-pattern-game', toolbox.toolbar, self._select_game_cb, cb_arg='pattern', tooltip=_('New game')) self._set_extras(toolbox.toolbar) self._sep.append(separator_factory(toolbox.toolbar, True, False)) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() button_factory('score-copy', self.activity_toolbar_button, self._write_scores_to_clipboard, tooltip=_('Export scores to clipboard')) self.set_toolbar_box(toolbox) toolbox.show() if MODE == 'word': self.words_tool_button = button_factory( 'word-tools', tools_toolbar, self._edit_words_cb, tooltip=_('Edit word lists.')) self.import_button = button_factory( 'image-tools', tools_toolbar, self.image_import_cb, tooltip=_('Import custom cards')) self.button_custom = button_factory( 'new-custom-game', tools_toolbar, self._select_game_cb, cb_arg='custom', tooltip=_('New custom game')) self.button_custom.set_sensitive(False) if MODE == 'number': self._setup_number_buttons(numbers_toolbar) def _setup_number_buttons(self, numbers_toolbar): self.product_button = radio_factory( 'product', numbers_toolbar, self._number_card_O_cb, cb_arg=PRODUCT, tooltip=_('product'), group=None) NUMBER_O_BUTTONS[PRODUCT] = self.product_button self.roman_button = radio_factory( 'roman', numbers_toolbar, self._number_card_O_cb, cb_arg=ROMAN, tooltip=_('Roman numerals'), group=self.product_button) NUMBER_O_BUTTONS[ROMAN] = self.roman_button self.word_button = radio_factory( 'word', numbers_toolbar, self._number_card_O_cb, cb_arg=WORD, tooltip=_('word'), group=self.product_button) NUMBER_O_BUTTONS[WORD] = self.word_button self.chinese_button = radio_factory( 'chinese', numbers_toolbar, self._number_card_O_cb, cb_arg=CHINESE, tooltip=_('Chinese'), group=self.product_button) NUMBER_O_BUTTONS[CHINESE] = self.chinese_button self.mayan_button = radio_factory( 'mayan', numbers_toolbar, self._number_card_O_cb, cb_arg=MAYAN, tooltip=_('Mayan'), group=self.product_button) NUMBER_O_BUTTONS[MAYAN] = self.mayan_button self.incan_button = radio_factory( 'incan', numbers_toolbar, self._number_card_O_cb, cb_arg=INCAN, tooltip=_('Quipu'), group=self.product_button) NUMBER_O_BUTTONS[INCAN] = self.incan_button separator_factory(numbers_toolbar, False, True) self.hash_button = radio_factory( 'hash', numbers_toolbar, self._number_card_C_cb, cb_arg=HASH, tooltip=_('hash marks'), group=None) NUMBER_C_BUTTONS[HASH] = self.hash_button self.dots_button = radio_factory( 'dots', numbers_toolbar, self._number_card_C_cb, cb_arg=DOTS, tooltip=_('dots in a circle'), group=self.hash_button) NUMBER_C_BUTTONS[DOTS] = self.dots_button self.star_button = radio_factory( 'star', numbers_toolbar, self._number_card_C_cb, cb_arg=STAR, tooltip=_('points on a star'), group=self.hash_button) NUMBER_C_BUTTONS[STAR] = self.star_button self.dice_button = radio_factory( 'dice', numbers_toolbar, self._number_card_C_cb, cb_arg=DICE, tooltip=_('dice'), group=self.hash_button) NUMBER_C_BUTTONS[DICE] = self.dice_button self.lines_button = radio_factory( 'lines', numbers_toolbar, self._number_card_C_cb, cb_arg=LINES, tooltip=_('dots in a line'), group=self.hash_button) NUMBER_C_BUTTONS[LINES] = self.lines_button def _configure_cb(self, event): self._vbox.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self._vbox.show() if Gdk.Screen.width() < Gdk.Screen.height(): for sep in self._sep: sep.hide() else: for sep in self._sep: sep.show() def _robot_selection_cb(self, widget): if self._robot_palette: if not self._robot_palette.is_up(): self._robot_palette.popup(immediate=True, state=self._robot_palette.SECONDARY) else: self._robot_palette.popdown(immediate=True) return def _setup_robot_palette(self): self._robot_palette = self._robot_time_button.get_palette() self._robot_timer_menu = {} for seconds in ROBOT_TIMER_VALUES: self._robot_timer_menu[seconds] = { 'menu_item': MenuItem(), 'label': ROBOT_TIMER_LABELS[seconds], 'icon': image_from_svg_file( 'timer-%d.svg' % (seconds)), 'icon-selected': image_from_svg_file( 'timer-%d-selected.svg' % (seconds)) } self._robot_timer_menu[seconds]['menu_item'].set_label( self._robot_timer_menu[seconds]['label']) if seconds == ROBOT_TIMER_DEFAULT: self._robot_timer_menu[seconds]['menu_item'].set_image( self._robot_timer_menu[seconds]['icon-selected']) else: self._robot_timer_menu[seconds]['menu_item'].set_image( self._robot_timer_menu[seconds]['icon']) self._robot_timer_menu[seconds]['menu_item'].connect( 'activate', self._robot_selected_cb, seconds) self._robot_palette.menu.append( self._robot_timer_menu[seconds]['menu_item']) self._robot_timer_menu[seconds]['menu_item'].show() def _robot_selected_cb(self, button, seconds): self.vmw.robot_time = seconds if hasattr(self, '_robot_time_button') and \ seconds in ROBOT_TIMER_VALUES: self._robot_time_button.set_icon_name('timer-%d' % seconds) for time in ROBOT_TIMER_VALUES: if time == seconds: self._robot_timer_menu[time]['menu_item'].set_image( self._robot_timer_menu[time]['icon-selected']) else: self._robot_timer_menu[time]['menu_item'].set_image( self._robot_timer_menu[time]['icon']) def _set_extras(self, toolbar): self.robot_button = button_factory( 'robot-off', toolbar, self._robot_cb, tooltip=_('Play with the computer')) self._robot_time_button = button_factory( 'timer-15', toolbar, self._robot_selection_cb, tooltip=_('robot pause time')) self._setup_robot_palette() self._sep.append(separator_factory(toolbar, False, True)) self.beginner_button = radio_factory( 'beginner', toolbar, self._level_cb, cb_arg=BEGINNER, tooltip=_('beginner'), group=None) LEVEL_BUTTONS[BEGINNER] = self.beginner_button self.intermediate_button = radio_factory( 'intermediate', toolbar, self._level_cb, cb_arg=INTERMEDIATE, tooltip=_('intermediate'), group=self.beginner_button) LEVEL_BUTTONS[INTERMEDIATE] = self.intermediate_button self.expert_button = radio_factory( 'expert', toolbar, self._level_cb, cb_arg=EXPERT, tooltip=_('expert'), group=self.beginner_button) LEVEL_BUTTONS[EXPERT] = self.expert_button def _fixed_resize_cb(self, widget=None, rect=None): ''' If a toolbar opens or closes, we need to resize the vbox holding out scrolling window. ''' self._vbox.set_size_request(rect.width, rect.height) def _setup_canvas(self): ''' Create a canvas in a Gtk.Fixed ''' self.fixed = Gtk.Fixed() self.fixed.connect('size-allocate', self._fixed_resize_cb) self.fixed.show() self.set_canvas(self.fixed) self._vbox = Gtk.VBox(False, 0) self._vbox.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self.fixed.put(self._vbox, 0, 0) self._vbox.show() self._canvas = Gtk.DrawingArea() self._canvas.set_size_request(int(Gdk.Screen.width()), int(Gdk.Screen.height())) self._canvas.show() self.show_all() self._vbox.pack_end(self._canvas, True, True, 0) self._vbox.show() self.show_all() self.vmw = Game(self._canvas, parent=self, card_type=MODE) self.vmw.level = self._play_level LEVEL_BUTTONS[self._play_level].set_active(True) self.vmw.card_type = self._card_type self.vmw.robot = False self.vmw.robot_time = self._robot_time self.vmw.low_score = self._low_score self.vmw.all_scores = self._all_scores self.vmw.numberO = self._numberO self.vmw.numberC = self._numberC self.vmw.matches = self._matches self.vmw.robot_matches = self._robot_matches self.vmw.total_time = self._total_time self.vmw.buddies = [] self.vmw.word_lists = self._word_lists self.vmw.editing_word_list = self._editing_word_list if hasattr(self, '_custom_object') and self._custom_object is not None: self.vmw._find_custom_paths(datastore.get(self._custom_object)) for i in range(9): if hasattr(self, '_custom_jobject') and \ self._custom_jobject[i] is not None: self.vmw.custom_paths[i] = datastore.get( self._custom_jobject[i]) self.button_custom.set_sensitive(True) return self._canvas def write_file(self, file_path): ''' Write data to the Journal. ''' if hasattr(self, 'vmw'): self.metadata['play_level'] = self.vmw.level self.metadata['low_score_beginner'] = int(self.vmw.low_score[0]) self.metadata['low_score_intermediate'] = int( self.vmw.low_score[1]) self.metadata['low_score_expert'] = int(self.vmw.low_score[2]) self.metadata['all_scores'] = jdumps(self.vmw.all_scores) print jdumps(self.vmw.all_scores) self.metadata['robot_time'] = self.vmw.robot_time self.metadata['numberO'] = self.vmw.numberO self.metadata['numberC'] = self.vmw.numberC self.metadata['cardtype'] = self.vmw.card_type self.metadata['matches'] = self.vmw.matches self.metadata['robot_matches'] = self.vmw.robot_matches self.metadata['total_time'] = int(self.vmw.total_time) self.metadata['deck_index'] = self.vmw.deck.index self.metadata['mouse'] = self.vmw.word_lists[0][0] self.metadata['cat'] = self.vmw.word_lists[0][1] self.metadata['dog'] = self.vmw.word_lists[0][2] self.metadata['cheese'] = self.vmw.word_lists[1][0] self.metadata['apple'] = self.vmw.word_lists[1][1] self.metadata['bread'] = self.vmw.word_lists[1][2] self.metadata['moon'] = self.vmw.word_lists[2][0] self.metadata['sun'] = self.vmw.word_lists[2][1] self.metadata['earth'] = self.vmw.word_lists[2][2] self.metadata['editing_word_list'] = self.vmw.editing_word_list self.metadata['mime_type'] = 'application/x-visualmatch' f = file(file_path, 'w') f.write(self._dump()) f.close() else: _logger.debug('Deferring saving to %s' % file_path) def _dump(self): ''' Dump game data to the journal.''' data = [] for i in self.vmw.grid.grid: if i is None or self.vmw.editing_word_list: data.append(None) else: data.append(i.index) for i in self.vmw.clicked: if i.spr is None or self.vmw.deck.spr_to_card(i.spr) is None or \ self.vmw.editing_word_list: data.append(None) else: data.append(self.vmw.deck.spr_to_card(i.spr).index) for i in self.vmw.deck.cards: if i is None or self.vmw.editing_word_list: data.append(None) else: data.append(i.index) for i in self.vmw.match_list: if self.vmw.deck.spr_to_card(i) is not None: data.append(self.vmw.deck.spr_to_card(i).index) for i in self.vmw.word_lists: for j in i: data.append(j) return self._data_dumper(data) def _data_dumper(self, data): io = StringIO() jdump(data, io) return io.getvalue() def read_file(self, file_path): ''' Read data from the Journal. ''' f = open(file_path, 'r') self._load(f.read()) f.close() def _load(self, data): ''' Load game data from the journal. ''' saved_state = self._data_loader(data) if len(saved_state) > 0: self._saved_state = saved_state def _data_loader(self, data): json_data = jloads(data) return json_data def _notify_new_game(self, prompt): ''' Called from New Game button since loading a new game can be slooow!! ''' alert = NotifyAlert(3) alert.props.title = prompt alert.props.msg = _('A new game is loading.') def _notification_alert_response_cb(alert, response_id, self): self.remove_alert(alert) alert.connect('response', _notification_alert_response_cb, self) self.add_alert(alert) alert.show() def _new_help_box(self, name, button=None): help_box = Gtk.VBox() help_box.set_homogeneous(False) help_palettes[name] = help_box if button is not None: help_buttons[name] = button help_windows[name] = Gtk.ScrolledWindow() help_windows[name].set_size_request( int(Gdk.Screen.width() / 3), Gdk.Screen.height() - style.GRID_CELL_SIZE * 3) help_windows[name].set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) help_windows[name].add_with_viewport(help_palettes[name]) help_palettes[name].show() return help_box def _setup_toolbar_help(self): ''' Set up a help palette for the main toolbars ''' help_box = self._new_help_box('main-toolbar') add_section(help_box, _('Dimensions'), icon='activity-dimensions') add_paragraph(help_box, _('Tools'), icon='view-source') if MODE == 'pattern': add_paragraph(help_box, _('Game'), icon='new-pattern-game') elif MODE == 'number': add_paragraph(help_box, PROMPT_DICT['number'], icon='new-number-game') add_paragraph(help_box, _('Numbers'), icon='number-tools') elif MODE == 'word': add_paragraph(help_box, PROMPT_DICT['word'], icon='new-word-game') add_paragraph(help_box, _('Play with the computer'), icon='robot-off') add_paragraph(help_box, _('robot pause time'), icon='timer-60') add_paragraph(help_box, _('beginner'), icon='beginner') add_paragraph(help_box, _('intermediate'), icon='intermediate') add_paragraph(help_box, _('expert'), icon='expert') add_section(help_box, _('Dimensions'), icon='activity-dimensions') add_paragraph(help_box, _('Export scores to clipboard'), icon='score-copy') add_section(help_box, _('Tools'), icon='view-source') add_section(help_box, _('Import image cards'), icon='image-tools') add_paragraph(help_box, PROMPT_DICT['custom'], icon='new-custom-game') if MODE == 'word': add_section(help_box, _('Edit word lists.'), icon='word-tools') if MODE == 'number': add_section(help_box, _('Numbers'), icon='number-tools') add_paragraph(help_box, _('product'), icon='product') add_paragraph(help_box, _('Roman numerals'), icon='roman') add_paragraph(help_box, _('word'), icon='word') add_paragraph(help_box, _('Chinese'), icon='chinese') add_paragraph(help_box, _('Mayan'), icon='mayan') add_paragraph(help_box, _('Quipu'), icon='incan') add_paragraph(help_box, _('hash marks'), icon='hash') add_paragraph(help_box, _('dots in a circle'), icon='dots') add_paragraph(help_box, _('points on a star'), icon='star') add_paragraph(help_box, _('dice'), icon='dice') add_paragraph(help_box, _('dots in a line'), icon='lines') 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.vmw.buddies.append(self.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...''' if self.shared_activity is None: _logger.error('Failed to share or join activity ... \ shared_activity is null in _shared_cb()') return self.initiating = True self.waiting_for_deck = False _logger.debug('I am sharing...') 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) _logger.debug('This is my activity: making a tube...') self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _joined_cb(self, activity): ''' ...or join an exisiting share. ''' if self.shared_activity is None: _logger.error('Failed to share or join activity ... \ shared_activity is null in _shared_cb()') return if self._joined_alert is not None: self.remove_alert(self._joined_alert) self._joined_alert = None self.initiating = False _logger.debug('I joined a shared activity.') 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) _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.waiting_for_deck = True self.button_pattern.set_sensitive(False) self.robot_button.set_sensitive(False) self._robot_time_button.set_sensitive(False) self.beginner_button.set_sensitive(False) self.intermediate_button.set_sensitive(False) self.expert_button.set_sensitive(False) 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.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) if self.waiting_for_deck: self._send_event('j') def event_received_cb(self, text): ''' Data is passed as tuples: cmd:text ''' if text[0] == 'B': e, card_index = text.split(':') self.vmw.add_to_clicked( self.vmw.deck.index_to_card(int(card_index)).spr) elif text[0] == 'r': self.vmw.clean_up_match() elif text[0] == 'R': self.vmw.clean_up_no_match(None) elif text[0] == 'S': e, card_index = text.split(':') i = int(card_index) self.vmw.process_click(self.vmw.clicked[i].spr) self.vmw.process_selection(self.vmw.clicked[i].spr) elif text[0] == 'j': if self.initiating: # Only the sharer 'shares'. self._send_event('P:' + str(self.vmw.level)) self._send_event('X:' + str(self.vmw.deck.index)) self._send_event('M:' + str(self.vmw.matches)) self._send_event('C:' + self.vmw.card_type) self._send_event('D:' + str(self._dump())) elif text[0] == 'J': # Force a request for current state. self._send_event('j') self.waiting_for_deck = True elif text[0] == 'C': e, text = text.split(':') self.vmw.card_type = text elif text[0] == 'P': e, text = text.split(':') self.vmw.level = int(text) # self.level_label.set_text(self.calc_level_label( # self.vmw.low_score, self.vmw.level)) LEVEL_BUTTONS[self.vmw.level].set_active(True) elif text[0] == 'X': e, text = text.split(':') self.vmw.deck.index = int(text) elif text[0] == 'M': e, text = text.split(':') self.vmw.matches = int(text) elif text[0] == 'D': if self.waiting_for_deck: e, text = text.split(':') self._load(text) self.waiting_for_deck = False self.vmw.new_game(self._saved_state, self.vmw.deck.index) def _send_event(self, entry): ''' Send event through the tube. ''' if hasattr(self, 'chattube') and self.chattube is not None: self.chattube.SendText(entry)
def __init__(self, handle): activity.Activity.__init__(self, handle) self._collab = CollabWrapper(self) self._collab.message.connect(self.__message_cb) _logger.debug('Starting the web activity') # TODO PORT # session = WebKit2.get_default_session() # session.set_property('accept-language-auto', True) # session.set_property('ssl-use-system-ca-file', True) # session.set_property('ssl-strict', False) # But of a hack, but webkit doesn't let us change the cookie jar # contents, we we can just pre-seed it cookie_jar = SoupGNOME.CookieJarSqlite(filename=_cookies_db_path, read_only=False) _seed_xs_cookie(cookie_jar) del cookie_jar context = WebKit2.WebContext.get_default() cookie_manager = context.get_cookie_manager() cookie_manager.set_persistent_storage( _cookies_db_path, WebKit2.CookiePersistentStorage.SQLITE) # FIXME # downloadmanager.remove_old_parts() context.connect('download-started', self.__download_requested_cb) self._force_close = False self._tabbed_view = TabbedView(self) self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._titled_tray = TitledTray(_('Bookmarks')) self._tray = self._titled_tray.tray self.set_tray(self._titled_tray, Gtk.PositionType.BOTTOM) self._tray_links = {} self.model = Model() self.model.add_link_signal.connect(self._add_link_model_cb) self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) self._view_toolbar = ViewToolbar(self) self._primary_toolbar.connect('add-link', self.__link_add_button_cb) self._primary_toolbar.connect('remove-link', self.__link_remove_button_cb) self._primary_toolbar.connect('go-home', self._go_home_button_cb) self._primary_toolbar.connect('go-library', self._go_library_button_cb) self._primary_toolbar.connect('set-home', self._set_home_button_cb) self._primary_toolbar.connect('reset-home', self._reset_home_button_cb) self._edit_toolbar_button = ToolbarButton(page=self._edit_toolbar, icon_name='toolbar-edit') self._primary_toolbar.toolbar.insert(self._edit_toolbar_button, 1) view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view') self._primary_toolbar.toolbar.insert(view_toolbar_button, 2) self._primary_toolbar.show_all() self.set_toolbar_box(self._primary_toolbar) self.set_canvas(self._tabbed_view) self._tabbed_view.show() self.connect('key-press-event', self._key_press_cb) if handle.uri: self._tabbed_view.current_browser.load_uri(handle.uri) elif not self._jobject.file_path: # TODO: we need this hack until we extend the activity API for # opening URIs and default docs. self._tabbed_view.load_homepage() # README: this is a workaround to remove old temp file # http://bugs.sugarlabs.org/ticket/3973 self._cleanup_temp_files() self._collab.setup()