def __init__(self): Gtk.Toolbar.__init__(self) self.button = ToolbarButton(page=self, icon_name="toolbar-view") self.buttons = { CelestialBodyType.MERCURY: None, CelestialBodyType.VENUS: None, CelestialBodyType.EARTH: None, CelestialBodyType.MARS: None, CelestialBodyType.JUPITER: None, CelestialBodyType.SATURN: None, CelestialBodyType.URANUS: None, CelestialBodyType.NEPTUNE: None } self.orbits_button = ToggleToolButton("show-orbits") self.orbits_button.set_tooltip(_("Show planets orbits")) self.orbits_button.set_active(True) self.orbits_button.connect("toggled", self._show_orbits_cb) self.insert(self.orbits_button, -1) self.insert(make_separator(False), -1) for planet in self.buttons: button = ToggleToolButton(get_icon_name(planet)) button.set_tooltip(get_body_name(planet)) button.set_active(True) button.connect("toggled", self._show_planet_cb, planet) self.insert(button, -1) self.buttons[planet] = button self.show_all()
class ViewToolbar(Gtk.Toolbar): __gtype_name__ = 'ViewToolbar' __gsignals__ = { 'go-fullscreen': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'toggle-playlist': (GObject.SignalFlags.RUN_FIRST, None, ([])) } def __init__(self): GObject.GObject.__init__(self) self._show_playlist = ToggleToolButton('view-list') self._show_playlist.set_active(False) self._show_playlist.set_tooltip(_('Show Playlist')) self._show_playlist.connect('toggled', self._playlist_toggled_cb) self.insert(self._show_playlist, -1) self._show_playlist.show() self._fullscreen = ToolButton('view-fullscreen') self._fullscreen.set_tooltip(_('Fullscreen')) self._fullscreen.connect('clicked', self._fullscreen_cb) self.insert(self._fullscreen, -1) self._fullscreen.show() def _fullscreen_cb(self, button): self.emit('go-fullscreen') def _playlist_toggled_cb(self, button): self.emit('toggle-playlist')
class ViewToolbar(Gtk.Toolbar): __gtype_name__ = 'ViewToolbar' __gsignals__ = { 'go-fullscreen': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'toggle-playlist': (GObject.SignalFlags.RUN_FIRST, None, ([])) } def __init__(self): Gtk.Toolbar.__init__(self) self._show_playlist = ToggleToolButton('view-list') self._show_playlist.set_active(True) # due to Activity.show_all() self._show_playlist.set_tooltip(_('Playlist')) self._show_playlist.set_accelerator('<ctrl>l') self._show_playlist.connect('toggled', self._playlist_toggled_cb) self.insert(self._show_playlist, -1) self._show_playlist.show() self._fullscreen = ToolButton('view-fullscreen') self._fullscreen.set_tooltip(_('Fullscreen')) self._fullscreen.set_accelerator('<ctrl>f') self._fullscreen.connect('clicked', self._fullscreen_cb) self.insert(self._fullscreen, -1) self._fullscreen.show() def _fullscreen_cb(self, button): self.emit('go-fullscreen') def _playlist_toggled_cb(self, button): self.emit('toggle-playlist')
def __init__(self, conf): Gtk.Toolbar.__init__(self) self.button = ToolbarButton(page=self, icon_name="toolbar-view") combo_font = FontComboBox(conf["font"]) combo_font.connect("changed", self.__font_changed_cb) self.insert(combo_font, -1) item_font_size = FontSize() item_font_size.set_font_size(conf["font-size"]) item_font_size.connect("changed", self.__font_size_changed_cb) self.insert(item_font_size, -1) self.insert(utils.make_separator(False), -1) button_numbers = ToggleToolButton("show-numbers") button_numbers.props.accelerator = "<Ctrl><Mayus>N" button_numbers.set_tooltip(_("Show line numbers")) button_numbers.set_active(conf["show-line-numbers"]) button_numbers.connect("toggled", self.__show_line_numbers_changed_cb) self.insert(button_numbers, -1) button_right_line = ToggleToolButton("show-right-line") button_right_line.props.accelerator = "<Ctrl>L" button_right_line.set_tooltip(_("Show a line in a specific position")) button_right_line.set_active(conf["show-right-line"]) button_right_line.connect("toggled", self.__show_right_line_changed_cb) self.insert(button_right_line, -1) adjustement = Gtk.Adjustment( value=conf["right-line-pos"], lower=1, upper=150, step_increment=1, page_increment=5, page_size=0, ) toolItem1 = Gtk.ToolItem() self.spinner_right_line = Gtk.SpinButton() self.spinner_right_line.set_margin_left(5) self.spinner_right_line.set_adjustment(adjustement) # Ensuring that the value is displayed when starting: self.spinner_right_line.set_value(conf["right-line-pos"]) self.spinner_right_line.connect('notify::value', self.__right_line_pos_changed_cb) toolItem1.add(self.spinner_right_line) self.insert(toolItem1, -1) self.insert(utils.make_separator(False), -1) combo_styles = ComboStyles(conf["theme"]) combo_styles.connect("theme-changed", self.__theme_changed_cb) self.insert(combo_styles, -1) self.show_all()
class ToolbarView(Gtk.Toolbar): __gsignals__ = { "show-orbits": (GObject.SIGNAL_RUN_FIRST, None, [bool]), "show-body": (GObject.SIGNAL_RUN_FIRST, None, [int, bool]), } def __init__(self): Gtk.Toolbar.__init__(self) self.button = ToolbarButton(page=self, icon_name="toolbar-view") self.buttons = { CelestialBodyType.MERCURY: None, CelestialBodyType.VENUS: None, CelestialBodyType.EARTH: None, CelestialBodyType.MARS: None, CelestialBodyType.JUPITER: None, CelestialBodyType.SATURN: None, CelestialBodyType.URANUS: None, CelestialBodyType.NEPTUNE: None } self.orbits_button = ToggleToolButton("show-orbits") self.orbits_button.set_tooltip(_("Show planets orbits")) self.orbits_button.set_active(True) self.orbits_button.connect("toggled", self._show_orbits_cb) self.insert(self.orbits_button, -1) self.insert(make_separator(False), -1) for planet in self.buttons: button = ToggleToolButton(get_icon_name(planet)) button.set_tooltip(get_body_name(planet)) button.set_active(True) button.connect("toggled", self._show_planet_cb, planet) self.insert(button, -1) self.buttons[planet] = button self.show_all() def disable_simulation_widgets(self): self.orbits_button.set_sensitive(False) for planet in self.buttons: self.buttons[planet].set_sensitive(False) def enable_simulation_widgets(self): self.orbits_button.set_sensitive(True) for planet in self.buttons: self.buttons[planet].set_sensitive(True) def _show_orbits_cb(self, button): self.emit("show-orbits", button.get_active()) def _show_planet_cb(self, button, planet): self.emit("show-body", planet, button.get_active())
def toggle_factory(icon_name, callback, toolbar, tooltip=None): ''' add a toggle button to a toolbar''' t_button = ToggleToolButton(icon_name) t_button.connect('toggled', callback) if tooltip: t_button.set_tooltip(tooltip) if hasattr(toolbar, 'insert'): # the main toolbar toolbar.insert(t_button, -1) else: # or a secondary toolbar toolbar.props.page.insert(t_button, -1) t_button.show()
def toggle_factory(icon_name, callback, toolbar, tooltip=None): ''' add a toggle button to a toolbar''' t_button = ToggleToolButton(icon_name) t_button.connect('toggled', callback) if tooltip: t_button.set_tooltip(tooltip) if hasattr(toolbar, 'insert'): # the main toolbar toolbar.insert(t_button, -1) else: # or a secondary toolbar toolbar.props.page.insert(t_button, -1) t_button.show()
def __init__(self, handle): activity.Activity.__init__(self, handle) logging.debug('Starting the IRC Activity') self.set_title(_('IRC Activity')) self.add_events(Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self.connect('visibility-notify-event', self.__visibility_notify_event_cb) self.is_visible = False self.client = purk.Client(self) if handle.object_id is None: self.default_config() self.client.show() widget = self.client.get_widget() # CANVAS self.set_canvas(widget) toolbar_box = ToolbarBox() self.activity_button = ActivityButton(self) toolbar_box.toolbar.insert(self.activity_button, 0) self.activity_button.show() title_entry = TitleEntry(self) toolbar_box.toolbar.insert(title_entry, -1) title_entry.show() connectionbtn = ToggleToolButton('connect') connectionbtn.set_active(True) connectionbtn.set_tooltip(_('Disconnect')) connectionbtn.connect('toggled', self._connection_cb) toolbar_box.toolbar.insert(connectionbtn, -1) connectionbtn.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 __init__(self, handle): activity.Activity.__init__(self, handle) logging.debug('Starting the IRC Activity') self.set_title(_('IRC Activity')) self.add_events(Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self.connect('visibility-notify-event', self.__visibility_notify_event_cb) self.is_visible = False self.client = purk.Client(self) if handle.object_id is None: self.default_config() self.client.show() widget = self.client.get_widget() # CANVAS self.set_canvas(widget) toolbar_box = ToolbarBox() self.activity_button = ActivityButton(self) toolbar_box.toolbar.insert(self.activity_button, 0) self.activity_button.show() title_entry = TitleEntry(self) toolbar_box.toolbar.insert(title_entry, -1) title_entry.show() connectionbtn = ToggleToolButton('connect') connectionbtn.set_active(True) connectionbtn.set_tooltip(_('Disconnect')) connectionbtn.connect('toggled', self._connection_cb) toolbar_box.toolbar.insert(connectionbtn, -1) connectionbtn.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()
class CollabEditActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self.toolbarbox = ToolbarBox() self.toolbar = self.toolbarbox.toolbar self.set_toolbar_box(self.toolbarbox) self.edit = collabedit.CollabEdit(self) self.edit.connect("cursor-position-changed", self._cursor_positon_changed_cb) self.set_canvas(self.edit) self.setup_toolbar() self.show_all() def _cursor_positon_changed_cb(self, edit, pos): self.button_bold.props.active = self.edit.check_tag_at_offset("bold", pos) self.button_italic.props.active = self.edit.check_tag_at_offset("italic", pos) self.button_underline.props.active = self.edit.check_tag_at_offset("underline", pos) def setup_toolbar(self): activity_button = ActivityToolbarButton(self) self.toolbar.insert(activity_button, -1) self.toolbar.insert(Gtk.SeparatorToolItem(), -1) edit_toolbar = EditToolbar() self.toolbar.insert(ToolbarButton(page=edit_toolbar, icon_name="toolbar-edit"), -1) edit_toolbar.insert(Gtk.SeparatorToolItem(), -1) self.button_bold = ToggleToolButton("format-text-bold") self.button_bold.set_tooltip(_("Bold")) self.button_bold.props.accelerator = "<Ctrl>B" self.button_bold.connect("toggled", lambda button: self.edit.toggle_bold()) edit_toolbar.insert(self.button_bold, -1) self.button_italic = ToggleToolButton("format-text-italic") self.button_italic.set_tooltip(_("Italic")) self.button_italic.props.accelerator = "<Ctrl>I" self.button_italic.connect("toggled", lambda button: self.edit.toggle_italic()) edit_toolbar.insert(self.button_italic, -1) self.button_underline = ToggleToolButton("format-text-underline") self.button_underline.set_tooltip(_("Underline")) self.button_underline.props.accelerator = "<Ctrl>B" self.button_underline.connect("toggled", lambda button: self.edit.toggle_underline()) edit_toolbar.insert(self.button_underline, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self.toolbar.insert(separator, -1) stop_button = StopButton(self) self.toolbar.insert(stop_button, -1) self.toolbarbox.show_all() edit_toolbar.show_all()
def _add_clock_controls(self, display_toolbar): # First group of radio button to select the type of clock to display button1 = RadioToolButton(icon_name="simple-clock") button1.set_tooltip(_('Simple Clock')) button1.connect("toggled", self._display_mode_changed_cb, _MODE_SIMPLE_CLOCK) display_toolbar.insert(button1, -1) button2 = RadioToolButton(icon_name="nice-clock", group=button1) button2.set_tooltip(_('Nice Clock')) button2.connect("toggled", self._display_mode_changed_cb, _MODE_NICE_CLOCK) display_toolbar.insert(button2, -1) button3 = RadioToolButton(icon_name="digital-clock", group=button1) button3.set_tooltip(_('Digital Clock')) button3.connect("toggled", self._display_mode_changed_cb, _MODE_DIGITAL_CLOCK) display_toolbar.insert(button3, -1) # A separator between the two groups of buttons separator = Gtk.SeparatorToolItem() separator.set_draw(True) display_toolbar.insert(separator, -1) # Now the options buttons to display other elements: date, day # of week... A button in the toolbar to write the time in # full letters button = ToggleToolButton("write-time") button.set_tooltip(_('Display time in full letters')) button.connect("toggled", self._write_time_clicked_cb) display_toolbar.insert(button, -1) # The button to display the weekday and date button = ToggleToolButton("write-date") button.set_tooltip(_('Display weekday and date')) button.connect("toggled", self._write_date_clicked_cb) display_toolbar.insert(button, -1) # Another button to speak aloud the time button = ToggleToolButton("microphone") button.set_tooltip(_('Talking clock')) button.connect("toggled", self._speak_time_clicked_cb) display_toolbar.insert(button, -1) # A separator between the two groups of buttons separator = Gtk.SeparatorToolItem() separator.set_draw(True) display_toolbar.insert(separator, -1) # And another button to toggle grabbing the hands self._grab_button = ToggleToolButton("grab") self._grab_button.set_tooltip(_('Grab the hands')) self._grab_button.connect("toggled", self._grab_clicked_cb) display_toolbar.insert(self._grab_button, -1)
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 = ToolButton('list-remove', accelerator='<ctrl>d') 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)
class CartoonBuilderActivity(SharedActivity): def __init__(self, handle): self.notebook = Gtk.Notebook() SharedActivity.__init__(self, self.notebook, SERVICE, handle) self.notebook.show() self.notebook.props.show_border = False self.notebook.props.show_tabs = False self.montage = montage.View() self.notebook.append_page(self.montage, Gtk.Label('')) toolbox = ToolbarBox() toolbox.show() toolbox.toolbar.insert(ActivityToolbarButton(self), -1) separator = Gtk.SeparatorToolItem() separator.set_draw(False) toolbox.toolbar.insert(separator, -1) self.notebook_toolbar = Gtk.Notebook() self.notebook_toolbar.props.show_border = False self.notebook_toolbar.props.show_tabs = False self.notebook_toolbar.append_page(self._create_montage_toolbar(), Gtk.Label('')) self.notebook_toolbar.show() notebook_item = Gtk.ToolItem() notebook_item.set_expand(True) notebook_item.add(self.notebook_toolbar) notebook_item.show() toolbox.toolbar.insert(notebook_item, -1) toolbox.toolbar.insert(StopButton(self), -1) toolbox.show_all() self.toolbar_box = toolbox def new_instance(self): logger.debug('new_instance') self.montage.restore() def resume_instance(self, filepath): logger.debug('resume_instance from %s' % filepath) document.load(filepath) char.load() ground.load() sound.load() self.montage.restore() def save_instance(self, filepath): logger.debug('save_instance to %s' % filepath) document.save(filepath) def share_instance(self, tube_conn, initiating): logger.debug('share_instance') self.messenger = Messenger(tube_conn, initiating, self.montage) def _create_montage_toolbar(self): toolbar = Gtk.Toolbar() playButtonImg = Gtk.Image() playButtonImg.show() playButtonImg.set_from_icon_name('media-playback-start', Gtk.IconSize.LARGE_TOOLBAR) pauseButtonImg = Gtk.Image() pauseButtonImg.show() pauseButtonImg.set_from_icon_name('media-playback-pause', Gtk.IconSize.LARGE_TOOLBAR) self.playButton = ToggleToolButton('media-playback-start') self.playButton.connect('toggled', self.__play_cb, playButtonImg, pauseButtonImg) toolbar.insert(self.playButton, -1) self.playButton.set_tooltip(_('Play / Pause')) tempo = TempoSlider(0, 10) tempo.adjustment.connect("value-changed", self.__tempo_cb) tempo.set_size_request(250, -1) tempo.set_value(5) tempo_item = Gtk.ToolItem() tempo_item.add(tempo) toolbar.insert(tempo_item, -1) separator = Gtk.SeparatorToolItem() toolbar.insert(separator, -1) clear_tape = ToolButton('sl-reset') clear_tape.connect('clicked', self.__clear_tape_cb) clear_tape.set_tooltip(_('Reset')) toolbar.insert(clear_tape, -1) toolbar.show_all() return toolbar def __clear_tape_cb(self, widget): for i in range(TAPE_COUNT): self.montage.props.frame = (i, None) def __tempo_cb(self, widget): self.montage.set_tempo(widget.get_value()) def __play_cb(self, widget, playButtonImg, pauseButtonImg): if widget.get_active(): widget.set_icon_widget(pauseButtonImg) sound.play() self.montage.play() else: widget.set_icon_widget(playButtonImg) sound.stop() self.montage.stop()
class SpeechToolbar(Gtk.Toolbar): def __init__(self, activity): Gtk.Toolbar.__init__(self) self._activity = activity if not speech.supported: return self._cnf_client = GConf.Client.get_default() self.load_speech_parameters() self.sorted_voices = [i for i in speech.voices()] self.sorted_voices.sort(self.compare_voices) default = 0 for voice in self.sorted_voices: if voice[0] == speech.voice[0]: break default = default + 1 # Play button self.play_btn = ToggleToolButton('media-playback-start') self.play_btn.show() self.play_btn.connect('toggled', self.play_cb) self.insert(self.play_btn, -1) self.play_btn.set_tooltip(_('Play / Pause')) # Stop button self.stop_btn = ToolButton('media-playback-stop') self.stop_btn.show() self.stop_btn.connect('clicked', self.stop_cb) self.stop_btn.set_sensitive(False) self.insert(self.stop_btn, -1) self.stop_btn.set_tooltip(_('Stop')) self.voice_combo = ComboBox() for voice in self.sorted_voices: self.voice_combo.append_item(voice, voice[0]) self.voice_combo.set_active(default) self.voice_combo.connect('changed', self.voice_changed_cb) combotool = ToolComboBox(self.voice_combo) self.insert(combotool, -1) combotool.show() speech.reset_buttons_cb = self.reset_buttons_cb def compare_voices(self, a, b): if a[0].lower() == b[0].lower(): return 0 if a[0] .lower() < b[0].lower(): return -1 if a[0] .lower() > b[0].lower(): return 1 def voice_changed_cb(self, combo): speech.voice = combo.props.value speech.say(speech.voice[0]) self.save_speech_parameters() def load_speech_parameters(self): speech_parameters = {} data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') if os.path.exists(data_file_name): f = open(data_file_name, 'r') try: speech_parameters = simplejson.load(f) speech.voice = speech_parameters['voice'] finally: f.close() self._cnf_client.add_dir('/desktop/sugar/speech', GConf.ClientPreloadType.PRELOAD_NONE) speech.pitch = self._cnf_client.get_int('/desktop/sugar/speech/pitch') speech.rate = self._cnf_client.get_int('/desktop/sugar/speech/rate') self._cnf_client.notify_add('/desktop/sugar/speech/pitch', \ self.__conf_changed_cb, None) self._cnf_client.notify_add('/desktop/sugar/speech/rate', \ self.__conf_changed_cb, None) def __conf_changed_cb(self, client, connection_id, entry, args): key = entry.get_key() value = client.get_int(key) if key == '/desktop/sugar/speech/pitch': speech.pitch = value if key == '/desktop/sugar/speech/rate': speech.rate = value def save_speech_parameters(self): speech_parameters = {} speech_parameters['voice'] = speech.voice data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') f = open(data_file_name, 'w') try: simplejson.dump(speech_parameters, f) finally: f.close() def reset_buttons_cb(self): logging.error('reset buttons') self.play_btn.set_named_icon('media-playback-start') self.stop_btn.set_sensitive(False) def play_cb(self, widget): self.stop_btn.set_sensitive(True) if widget.get_active(): self.play_btn.set_named_icon('media-playback-pause') if speech.is_stopped(): speech.play(self._activity._view.get_marked_words()) else: self.play_btn.set_named_icon('media-playback-start') speech.pause() def stop_cb(self, widget): self.stop_btn.set_sensitive(False) self.play_btn.set_named_icon('media-playback-start') self.play_btn.set_active(False) speech.stop()
class MazeActivity(activity.Activity): def __init__(self, handle): """Set up the Maze activity.""" activity.Activity.__init__(self, handle) self._busy_count = 0 self._unbusy_idle_sid = None self.build_toolbar() self.pservice = PresenceService() self.owner = self.pservice.get_owner() state = None if 'state' in self.metadata: state = json.loads(self.metadata['state']) self.game = game.MazeGame(self, self.owner, state) self.set_canvas(self.game) self.game.show() self.connect("key_press_event", self.game.key_press_cb) self.text_channel = None self.my_key = profile.get_pubkey() self._alert = None if self.shared_activity: # we are joining the activity self._add_alert(_('Joining a maze'), _('Connecting...')) self.connect('joined', self._joined_cb) if self.get_shared(): # we have already joined self._joined_cb() else: # we are creating the activity self.connect('shared', self._shared_cb) def busy(self): if self._busy_count == 0: if self._unbusy_idle_sid is not None: GLib.source_remove(self._unbusy_idle_sid) self._unbusy_idle_sid = None self._old_cursor = self.get_window().get_cursor() self._set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) self._busy_count += 1 def unbusy(self): self._unbusy_idle_sid = GLib.idle_add(self._unbusy_idle_cb) def _unbusy_idle_cb(self): self._unbusy_idle_sid = None self._busy_count -= 1 if self._busy_count == 0: self._set_cursor(self._old_cursor) def _set_cursor(self, cursor): self.get_window().set_cursor(cursor) Gdk.flush() def build_toolbar(self): """Build our Activity toolbar for the Sugar system.""" toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() easier_button = ToolButton('create-easier') easier_button.set_tooltip(_('Easier level')) easier_button.connect('clicked', self._easier_button_cb) toolbar_box.toolbar.insert(easier_button, -1) harder_button = ToolButton('create-harder') harder_button.set_tooltip(_('Harder level')) harder_button.connect('clicked', self._harder_button_cb) toolbar_box.toolbar.insert(harder_button, -1) separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() self.show_trail_button = ToggleToolButton('show-trail') self.show_trail_button.set_tooltip(_('Show trail')) self.show_trail_button.set_active(True) self.show_trail_button.connect('toggled', self._toggled_show_trail_cb) toolbar_box.toolbar.insert(self.show_trail_button, -1) 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_button = StopButton(self) toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() return toolbar_box def _easier_button_cb(self, button): self.game.easier() def _harder_button_cb(self, button): self.game.harder() def _toggled_show_trail_cb(self, button): if self.game.set_show_trail(button.get_active()): self.broadcast_msg('show_trail:%s' % str(button.get_active())) def _shared_cb(self, activity): logging.debug('Maze was shared') self._add_alert(_('Sharing'), _('This maze is shared.')) self._setup() def _joined_cb(self, activity): """Joined a shared activity.""" if not self.shared_activity: return logging.debug('Joined a shared chat') for buddy in self.shared_activity.get_joined_buddies(): self._buddy_already_exists(buddy) self._setup() # request maze data self.broadcast_msg('req_maze') def _setup(self): self.text_channel = TextChannelWrapper( self.shared_activity.telepathy_text_chan, self.shared_activity.telepathy_conn, self.pservice) self.text_channel.set_received_callback(self._received_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) def _received_cb(self, buddy, text): if buddy == self.owner: return self.game.msg_received(buddy, text) def _add_alert(self, title, text=None): self.grab_focus() self._alert = ErrorAlert() self._alert.props.title = title self._alert.props.msg = text self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show() def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) self._alert = None def update_alert(self, title, text=None): if self._alert is not None: self._alert.props.title = title self._alert.props.msg = text def show_accelerator_alert(self): self.grab_focus() self._alert = NotifyAlert() self._alert.props.title = _('Tablet mode detected.') self._alert.props.msg = _('Hold your XO flat and tilt to play!') self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show() def _buddy_joined_cb(self, activity, buddy): """Show a buddy who joined""" logging.debug('buddy joined') if buddy == self.owner: logging.debug('its me, exit!') return self.game.buddy_joined(buddy) def _buddy_left_cb(self, activity, buddy): self.game.buddy_left(buddy) def _buddy_already_exists(self, buddy): """Show a buddy already in the chat.""" if buddy == self.owner: return self.game.buddy_joined(buddy) def broadcast_msg(self, message): if self.text_channel: # FIXME: can't identify the sender at the other end, # add the pubkey to the text message self.text_channel.send('%s|%s' % (self.my_key, message)) def write_file(self, file_path): logging.debug('Saving the state of the game...') data = {'seed': self.game.maze.seed, 'width': self.game.maze.width, 'height': self.game.maze.height, 'finish_time': self.game.finish_time} logging.debug('Saving data: %s', data) self.metadata['state'] = json.dumps(data) def can_close(self): self.game.close_finish_window() return True def read_file(self, file_path): pass
def __init__(self, handle): activity.Activity.__init__(self, handle) self.set_title('FotoToon') self._max_participants = 1 self.page = None toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page toolbar_box.toolbar.insert(activity_button, 0) edit_toolbar_btn = ToolbarButton() edit_toolbar = Gtk.Toolbar() edit_toolbar_btn.props.page = edit_toolbar edit_toolbar_btn.props.icon_name = 'toolbar-edit' edit_toolbar_btn.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar_btn, -1) view_toolbar_btn = ToolbarButton() view_toolbar = Gtk.Toolbar() view_toolbar_btn.props.page = view_toolbar view_toolbar_btn.props.icon_name = 'toolbar-view' view_toolbar_btn.label = _('View') toolbar_box.toolbar.insert(view_toolbar_btn, -1) slideview_btn = ToggleToolButton('slideshow') slideview_btn.set_tooltip(_('Slideshow')) slideview_btn.set_active(False) slideview_btn.connect('clicked', self._switch_view_mode, False) view_toolbar.insert(slideview_btn, -1) slideview_btn.show() slideview_timings_btn = ToggleToolButton('slideshow-stopwatch') slideview_timings_btn.set_tooltip(_('Slideshow with Timings')) slideview_timings_btn.set_active(False) slideview_timings_btn.connect('clicked', self._switch_view_mode, True) view_toolbar.insert(slideview_timings_btn, -1) slideview_timings_btn.show() time_button = ToolButton('stopwatch') time_button.set_tooltip(_('Set Image Duration in Slideshow (Seconds)')) view_toolbar.insert(time_button, -1) time_button.show() self._time_spin = Gtk.SpinButton.new_with_range(MIN_TIME, MAX_TIME, 1) self._time_spin.connect('value-changed', self.__time_spin_changed_cb) self._time_spin.props.value = DEFAULT_TIME self._time_spin.props.update_policy = \ Gtk.SpinButtonUpdatePolicy.IF_VALID palette = time_button.get_palette() palette.connect('popup', self.__time_button_popup_cb) time_button.connect( 'clicked', lambda *args: palette.popup(immediate=True, state=Palette.SECONDARY)) alignment = Gtk.Alignment() alignment.set_padding(style.DEFAULT_PADDING, style.DEFAULT_PADDING, style.DEFAULT_PADDING, style.DEFAULT_PADDING) alignment.add(self._time_spin) self._time_spin.show() palette.set_content(alignment) alignment.show() fullscreen_btn = ToolButton('view-fullscreen') fullscreen_btn.set_tooltip(_('Fullscreen')) fullscreen_btn.props.accelerator = '<Alt>Return' fullscreen_btn.connect('clicked', lambda w: self.fullscreen()) view_toolbar.insert(fullscreen_btn, -1) fullscreen_btn.show() self.set_toolbar_box(toolbar_box) toolbar = toolbar_box.toolbar self.page = Page() self.globes_manager = GlobesManager(toolbar, edit_toolbar, self) # fonts self._text_button = ToolbarButton() self._text_button.props.page = TextToolbar(self.page) self._text_button.props.icon_name = 'format-text-size' self._text_button.props.label = _('Text') self._toolbar_box.toolbar.insert(self._text_button, -1) reorder_img_btn = ToolButton('thumbs-view') reorder_img_btn.set_icon_name('thumbs-view') reorder_img_btn.set_tooltip(_('Change image order')) reorder_img_btn.connect('clicked', self.__image_order_cb) edit_toolbar.insert(reorder_img_btn, -1) reorder_img_btn.show() bgchange = ToolButton(icon_name='contract-coordinates') bgchange.set_tooltip(_('Edit background image')) bgchange.connect('clicked', self.__bgchange_clicked_cb) edit_toolbar.insert(bgchange, -1) bgchange.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() # add export button separator_2 = Gtk.SeparatorToolItem() separator_2.show() activity_toolbar.insert(separator_2, -1) self.bt_save_as_image = ToolButton() self.bt_save_as_image.props.icon_name = 'save-as-image' self.bt_save_as_image.connect('clicked', self.write_image) self.bt_save_as_image.set_tooltip(_('Save as Image')) activity_toolbar.insert(self.bt_save_as_image, -1) self.bt_save_as_image.show() save_as_pdf = ToolButton() save_as_pdf.props.icon_name = 'save-as-pdf' save_as_pdf.connect('clicked', self._save_as_pdf) save_as_pdf.set_tooltip(_('Save as a Book (PDF)')) activity_toolbar.insert(save_as_pdf, -1) save_as_pdf.show() save_as_ogg = ToolButton() save_as_ogg.props.icon_name = 'save-as-ogg' save_as_ogg.connect('clicked', self.__save_as_ogg_cb) save_as_ogg.set_tooltip(_('Save as a Movie (OGG)')) activity_toolbar.insert(save_as_ogg, -1) Gst.init(None) if Gst.version_string() != 'GStreamer 1.0.10': save_as_ogg.show() activity_button.page.title.connect("focus-in-event", self.on_title) scrolled = Gtk.ScrolledWindow() # scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS) scrolled.add_with_viewport(self.page) scrolled.set_kinetic_scrolling(False) scrolled.show_all() self._slideview = SlideView(self) self._slideview.show_all() self._notebook = Gtk.Notebook() self._notebook.set_show_tabs(False) self._notebook.append_page(scrolled, None) self._notebook.append_page(self._slideview, None) self._notebook.show_all() if self._jobject.file_path is None or self._jobject.file_path == '': empty_widget = EmptyWidget() empty_widget.connect('choose-image', self.__add_image) self.set_canvas(empty_widget) else: self.set_canvas(self._notebook) self.show() self.metadata['mime_type'] = 'application/x-fototoon-activity' self.page.empty_page = handle.object_id is None self._key_press_signal_id = None
class PrimaryToolbar(ToolbarBase): __gtype_name__ = 'PrimaryToolbar' __gsignals__ = { 'add-link': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'remove-link': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'go-home': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'set-home': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'reset-home': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'go-library': (GObject.SignalFlags.RUN_FIRST, None, ([])), } def __init__(self, tabbed_view, act): ToolbarBase.__init__(self) self._url_toolbar = UrlToolbar() self._activity = act self.model = act.model self.model.link_removed_signal.connect(self.__link_removed_cb) self._tabbed_view = self._canvas = tabbed_view self._loading = False self._download_running_hid = None toolbar = self.toolbar activity_button = ActivityToolbarButton(self._activity) toolbar.insert(activity_button, 0) separator = Gtk.SeparatorToolItem() ''' Disabled since the python gi bindings don't expose the critical WebKit2.PrintOperation.print function save_as_pdf = ToolButton('save-as-pdf') save_as_pdf.set_tooltip(_('Save page as pdf')) save_as_pdf.connect('clicked', self.save_as_pdf) activity_button.props.page.insert(separator, -1) activity_button.props.page.insert(save_as_pdf, -1) separator.show() save_as_pdf.show() ''' inspect_view = ToolButton('emblem-view-source') inspect_view.set_tooltip(_('Show Web Inspector')) inspect_view.connect('clicked', self.inspect_view) activity_button.props.page.insert(separator, -1) activity_button.props.page.insert(inspect_view, -1) separator.show() inspect_view.show() self._go_home = ToolButton('go-home') self._go_home.set_tooltip(_('Home page')) self._go_home.connect('clicked', self._go_home_cb) # add a menu to save the home page menu_box = PaletteMenuBox() self._go_home.props.palette.set_content(menu_box) menu_item = PaletteMenuItem() menu_item.set_label(_('Select as initial page')) menu_item.connect('activate', self._set_home_cb) menu_box.append_item(menu_item) self._reset_home_menu = PaletteMenuItem() self._reset_home_menu.set_label(_('Reset initial page')) self._reset_home_menu.connect('activate', self._reset_home_cb) menu_box.append_item(self._reset_home_menu) if os.path.isfile(LIBRARY_PATH): library_menu = PaletteMenuItem() library_menu.set_label(_('Library')) library_menu.connect('activate', self._go_library_cb) menu_box.append_item(library_menu) menu_box.show_all() # verify if the home page is configured client = GConf.Client.get_default() self._reset_home_menu.set_visible( client.get_string(HOME_PAGE_GCONF_KEY) is not None) toolbar.insert(self._go_home, -1) self._go_home.show() self.entry = WebEntry() self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, 'entry-stop') self.entry.connect('icon-press', self._stop_and_reload_cb) self.entry.connect('activate', self._entry_activate_cb) self.entry.connect('focus-in-event', self.__focus_in_event_cb) self.entry.connect('focus-out-event', self.__focus_out_event_cb) self.entry.connect('key-press-event', self.__key_press_event_cb) self.entry.connect('changed', self.__changed_cb) # In an event box so that it can render the background entry_box = Gtk.EventBox() entry_box.add(self.entry) entry_box.show() self._entry_item = Gtk.ToolItem() self._entry_item.set_expand(True) self._entry_item.add(entry_box) self.entry.show() toolbar.insert(self._entry_item, -1) self._entry_item.show() self._back = ToolButton('go-previous-paired', accelerator='<ctrl>Left') self._back.set_tooltip(_('Back')) self._back.props.sensitive = False self._back.connect('clicked', self._go_back_cb) toolbar.insert(self._back, -1) self._back.show() palette = self._back.get_palette() self._back_box_menu = Gtk.VBox() self._back_box_menu.show() palette.set_content(self._back_box_menu) # FIXME, this is a hack, should be done in the theme: palette._content.set_border_width(1) self._forward = ToolButton('go-next-paired', accelerator='<ctrl>Right') self._forward.set_tooltip(_('Forward')) self._forward.props.sensitive = False self._forward.connect('clicked', self._go_forward_cb) toolbar.insert(self._forward, -1) self._forward.show() palette = self._forward.get_palette() self._forward_box_menu = Gtk.VBox() self._forward_box_menu.show() palette.set_content(self._forward_box_menu) # FIXME, this is a hack, should be done in the theme: palette._content.set_border_width(1) self._download_icon = ProgressToolButton( icon_name='emblem-downloads', tooltip=_('No Downloads Running')) toolbar.insert(self._download_icon, -1) self._download_icon.show() downloadmanager.connect_download_started(self.__download_started_cb) self._link_add = ToggleToolButton('emblem-favorite') self._link_add.set_accelerator('<ctrl>d') self._link_add.set_tooltip(_('Bookmark')) self._link_add_toggled_hid = \ self._link_add.connect('toggled', self.__link_add_toggled_cb) toolbar.insert(self._link_add, -1) self._link_add.show() self._toolbar_separator = Gtk.SeparatorToolItem() self._toolbar_separator.props.draw = False self._toolbar_separator.set_expand(True) self._stop_button = StopButton(self._activity) toolbar.insert(self._stop_button, -1) self._progress_listener = None self._browser = None self._loading_changed_hid = None self._progress_changed_hid = None self._session_history_changed_hid = None self._uri_changed_hid = None self._load_changed_hid = None self._security_status_changed_hid = None if tabbed_view.get_n_pages(): self._connect_to_browser(tabbed_view.props.current_browser) tabbed_view.connect_after('switch-page', self.__switch_page_cb) tabbed_view.connect_after('page-added', self.__page_added_cb) Gdk.Screen.get_default().connect('size-changed', self.__screen_size_changed_cb) self._configure_toolbar() def __download_started_cb(self): if self._download_running_hid is None: self._download_running_hid = GLib.timeout_add( 80, self.__download_running_cb) def __download_running_cb(self): progress = downloadmanager.overall_downloads_progress() self._download_icon.update(progress) if downloadmanager.num_downloads() > 0: self._download_icon.props.tooltip = \ _('{}% Downloaded').format(int(progress*100)) return True else: self._download_running_hid = None self._download_icon.props.tooltip = _('No Downloads Running') return False def __key_press_event_cb(self, entry, event): self._tabbed_view.current_browser.loading_uri = entry.props.text def __switch_page_cb(self, tabbed_view, page, page_num): if tabbed_view.get_n_pages(): self._connect_to_browser(tabbed_view.props.current_browser) def __page_added_cb(self, notebook, child, pagenum): self.entry._search_popdown() def _configure_toolbar(self, screen=None): # Adapt the toolbars for portrait or landscape mode. if screen is None: screen = Gdk.Screen.get_default() if screen.get_width() < screen.get_height(): if self._entry_item in self._url_toolbar.toolbar.get_children(): return self.toolbar.remove(self._entry_item) self._url_toolbar.toolbar.insert(self._entry_item, -1) separator_pos = len(self.toolbar.get_children()) - 1 self.toolbar.insert(self._toolbar_separator, separator_pos) self._toolbar_separator.show() self.pack_end(self._url_toolbar, True, True, 0) self._url_toolbar.show() else: if self._entry_item in self.toolbar.get_children(): return self.toolbar.remove(self._toolbar_separator) position = len(self.toolbar.get_children()) - 4 self._url_toolbar.toolbar.remove(self._entry_item) self.toolbar.insert(self._entry_item, position) self._toolbar_separator.hide() self.remove(self._url_toolbar) def __screen_size_changed_cb(self, screen): self._configure_toolbar(screen) def _connect_to_browser(self, browser): if self._browser is not None: self._browser.disconnect(self._uri_changed_hid) self._browser.disconnect(self._load_changed_hid) self._browser.disconnect(self._progress_changed_hid) self._browser.disconnect(self._security_status_changed_hid) self._browser = browser if not isinstance(self._browser, DummyBrowser): address = self._browser.props.uri or self._browser.loading_uri else: address = self._browser.props.uri self._set_address(address) self._set_progress(self._browser.props.estimated_load_progress) self._set_loading(self._browser.props.estimated_load_progress < 1.0) self._set_security_status(self._browser.security_status) is_webkit_browser = isinstance(self._browser, Browser) self.entry.props.editable = is_webkit_browser self._uri_changed_hid = self._browser.connect( 'notify::uri', self.__uri_changed_cb) self._load_changed_hid = self._browser.connect( 'load-changed', self.__load_changed_cb) self._progress_changed_hid = self._browser.connect( 'notify::estimated-load-progress', self.__progress_changed_cb) self._security_status_changed_hid = self._browser.connect( 'security-status-changed', self.__security_status_changed_cb) self._update_navigation_buttons() def __security_status_changed_cb(self, widget): self._set_security_status(widget.security_status) def __progress_changed_cb(self, widget, param): self._set_progress(widget.props.estimated_load_progress) self._set_loading(widget.props.estimated_load_progress < 1.0) def _set_security_status(self, security_status): # Display security status as a lock icon in the left side of # the URL entry. if security_status is None: self.entry.set_icon_from_pixbuf( iconentry.ICON_ENTRY_PRIMARY, None) elif security_status == Browser.SECURITY_STATUS_SECURE: self.entry.set_icon_from_name( iconentry.ICON_ENTRY_PRIMARY, 'channel-secure-symbolic') elif security_status == Browser.SECURITY_STATUS_INSECURE: self.entry.set_icon_from_name( iconentry.ICON_ENTRY_PRIMARY, 'channel-insecure-symbolic') def _set_progress(self, progress): if progress == 1.0: self.entry.set_progress_fraction(0.0) else: self.entry.set_progress_fraction(progress) def _set_address(self, uri): if uri is None: self.entry.props.address = '' else: self.entry.props.address = uri def __changed_cb(self, iconentry): # The WebEntry can be changed when we click on a link, then we # have to show the clear icon only if is the user who has # changed the entry if self.entry.has_focus(): if not self.entry.props.text: self._show_no_icon() else: self._show_clear_icon() def __focus_in_event_cb(self, entry, event): if not self._tabbed_view.is_current_page_pdf(): if not self.entry.props.text: self._show_no_icon() else: self._show_clear_icon() def __focus_out_event_cb(self, entry, event): if self._loading: self._show_stop_icon() else: if not self._tabbed_view.is_current_page_pdf(): self._show_reload_icon() def _show_no_icon(self): self.entry.remove_icon(iconentry.ICON_ENTRY_SECONDARY) def _show_stop_icon(self): self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, 'entry-stop') def _show_reload_icon(self): self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, 'entry-refresh') def _show_clear_icon(self): self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, 'entry-cancel') def _update_navigation_buttons(self): can_go_back = self._browser.can_go_back() self._back.props.sensitive = can_go_back can_go_forward = self._browser.can_go_forward() self._forward.props.sensitive = can_go_forward is_webkit_browser = isinstance(self._browser, Browser) self._go_home.props.sensitive = is_webkit_browser if is_webkit_browser: self._reload_session_history() with self._link_add.handler_block(self._link_add_toggled_hid): uri = self._browser.get_uri() self._link_add.props.active = self.model.has_link(uri) def __link_removed_cb(self, model): self._update_navigation_buttons() def _entry_activate_cb(self, entry): url = entry.props.text effective_url = self._tabbed_view.normalize_or_autosearch_url(url) self._browser.load_uri(effective_url) self._browser.loading_uri = effective_url self.entry.props.address = effective_url self._browser.grab_focus() def _go_home_cb(self, button): self.emit('go-home') def _go_library_cb(self, button): self.emit('go-library') def _set_home_cb(self, button): self._reset_home_menu.set_visible(True) self.emit('set-home') def _reset_home_cb(self, button): self._reset_home_menu.set_visible(False) self.emit('reset-home') def _go_back_cb(self, button): self._browser.go_back() def _go_forward_cb(self, button): self._browser.go_forward() def __uri_changed_cb(self, widget, param): self._set_address(widget.get_uri()) self._update_navigation_buttons() filepicker.cleanup_temp_files() def __load_changed_cb(self, widget, event): self._update_navigation_buttons() def _stop_and_reload_cb(self, entry, icon_pos, button): if entry.has_focus() and \ not self._tabbed_view.is_current_page_pdf(): entry.set_text('') else: if self._loading: self._browser.stop_loading() else: self._browser.reload() def _set_loading(self, loading): self._loading = loading if self._loading: self._show_stop_icon() else: if not self._tabbed_view.is_current_page_pdf(): self._set_sensitive(True) self._show_reload_icon() else: self._set_sensitive(False) self._show_no_icon() def _set_sensitive(self, value): for widget in self.toolbar: if widget not in (self._stop_button, self._link_add): widget.set_sensitive(value) def _reload_session_history(self): back_forward_list = self._browser.get_back_forward_list() item_index = 0 # The index of the history item # Clear menus in palettes: for box_menu in (self._back_box_menu, self._forward_box_menu): for menu_item in box_menu.get_children(): box_menu.remove(menu_item) def create_menu_item(history_item): """Create a MenuItem for the back or forward palettes.""" title = history_item.get_title() or _('No Title') if not isinstance(title, unicode): title = unicode(title, 'utf-8') # This is a fix until the Sugar MenuItem is fixed: menu_item = PaletteMenuItem(text_label=title) menu_item.connect('activate', self._history_item_activated_cb, history_item) return menu_item back_list = back_forward_list.get_back_list_with_limit( _MAX_HISTORY_ENTRIES) back_list.reverse() for item in back_list: menu_item = create_menu_item(item) self._back_box_menu.pack_end(menu_item, False, False, 0) menu_item.show() item_index += 1 # Increment the item index to count the current page: item_index += 1 forward_list = back_forward_list.get_forward_list_with_limit( _MAX_HISTORY_ENTRIES) forward_list.reverse() for item in forward_list: menu_item = create_menu_item(item) self._forward_box_menu.pack_start(menu_item, False, False, 0) menu_item.show() item_index += 1 def _history_item_activated_cb(self, menu_item, history_item): self._back.get_palette().popdown(immediate=True) self._forward.get_palette().popdown(immediate=True) # self._browser.set_history_index(index) self._browser.go_to_back_forward_list_item(history_item) def __link_add_toggled_cb(self, button): if button.props.active: self.emit('add-link') else: self.emit('remove-link') def inspect_view(self, button): page = self._canvas.get_current_page() webview = self._canvas.get_children()[page].props.browser # If get_inspector returns None, it is not a real WebView inspector = webview.get_inspector() if inspector is not None: # Inspector window will be blank if disabled web_settings = webview.get_settings() web_settings.props.enable_developer_extras = True inspector.show() inspector.attach() '''
class CollabEditActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self.toolbarbox = ToolbarBox() self.toolbar = self.toolbarbox.toolbar self.set_toolbar_box(self.toolbarbox) self.edit = collabedit.CollabEdit(self) self.edit.connect( "cursor-position-changed", self._cursor_positon_changed_cb) self.set_canvas(self.edit) self.setup_toolbar() self.show_all() def _cursor_positon_changed_cb(self, edit, pos): self.button_bold.props.active = self.edit.check_tag_at_offset( "bold", pos) self.button_italic.props.active = self.edit.check_tag_at_offset( "italic", pos) self.button_underline.props.active = self.edit.check_tag_at_offset( "underline", pos) def setup_toolbar(self): activity_button = ActivityToolbarButton(self) self.toolbar.insert(activity_button, -1) self.toolbar.insert(Gtk.SeparatorToolItem(), -1) edit_toolbar = EditToolbar() self.toolbar.insert( ToolbarButton( page=edit_toolbar, icon_name="toolbar-edit"), -1) edit_toolbar.insert(Gtk.SeparatorToolItem(), -1) self.button_bold = ToggleToolButton("format-text-bold") self.button_bold.set_tooltip(_("Bold")) self.button_bold.props.accelerator = "<Ctrl>B" self.button_bold.connect( "toggled", lambda button: self.edit.toggle_bold()) edit_toolbar.insert(self.button_bold, -1) self.button_italic = ToggleToolButton("format-text-italic") self.button_italic.set_tooltip(_("Italic")) self.button_italic.props.accelerator = "<Ctrl>I" self.button_italic.connect( "toggled", lambda button: self.edit.toggle_italic()) edit_toolbar.insert(self.button_italic, -1) self.button_underline = ToggleToolButton("format-text-underline") self.button_underline.set_tooltip(_("Underline")) self.button_underline.props.accelerator = "<Ctrl>U" self.button_underline.connect( "toggled", lambda button: self.edit.toggle_underline()) edit_toolbar.insert(self.button_underline, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self.toolbar.insert(separator, -1) stop_button = StopButton(self) self.toolbar.insert(stop_button, -1) self.toolbarbox.show_all() edit_toolbar.show_all()
class TextToolbar(Gtk.Toolbar): def __init__(self, page): self._colorseldlg = None Gtk.Toolbar.__init__(self) self._page = page page._text_toolbar = self self._bold = ToggleToolButton('format-text-bold') self._bold.set_tooltip(_('Bold')) self._bold_id = self._bold.connect('clicked', self._bold_cb) self.insert(self._bold, -1) self._italic = ToggleToolButton('format-text-italic') self._italic.set_tooltip(_('Italic')) self._italic_id = self._italic.connect('clicked', self._italic_cb) self.insert(self._italic, -1) """ self._underline = ToggleToolButton('format-text-underline') self._underline.set_tooltip(_('Underline')) self._underline_id = self._underline.connect('clicked', self._underline_cb) self.insert(self._underline, -1) self._underline.show() """ self._text_color = TextButtonColor(page) self._text_color.set_title(_('Text Color')) item = Gtk.ToolItem() item.add(self._text_color) self.insert(item, -1) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._font_size_combo = FontSize() self._font_size_changed_id = self._font_size_combo.connect( 'changed', self._font_size_changed_cb) self.insert(self._font_size_combo, -1) # font self._font_combo = FontComboBox() self._font_combo.set_font_name(globos.DEFAULT_FONT) self._fonts_changed_id = self._font_combo.connect( 'changed', self._font_changed_cb) self.insert(ToolComboBox(self._font_combo), -1) self.show_all() def get_text_selected_handler(self): return self._text_selected_handler def _add_widget(self, widget, expand=False): tool_item = Gtk.ToolItem() tool_item.set_expand(expand) tool_item.add(widget) widget.show() self.insert(tool_item, -1) tool_item.show() def _bold_cb(self, button): globo_activo = self._page.get_globo_activo() if globo_activo is not None and globo_activo.texto is not None: globo_activo.texto.bold = not globo_activo.texto.bold self._page.get_active_box().redraw() def _italic_cb(self, button): globo_activo = self._page.get_globo_activo() if globo_activo is not None and globo_activo.texto is not None: globo_activo.texto.italic = not globo_activo.texto.italic self._page.get_active_box().redraw() # para la version 0.82 def _text_color_cb(self, button): globo_activo = self._page.get_globo_activo() if globo_activo is not None and globo_activo.texto is not None: color = self._text_color.get_color() texto = globo_activo.texto texto.color = (color.red, color.green, color.blue) self._page.get_active_box().redraw() def _font_size_changed_cb(self, widget): size = widget.get_font_size() logger.debug('Setting font size: %d', size) globo_activo = self._page.get_globo_activo() if globo_activo is not None and globo_activo.texto is not None: globo_activo.texto.font_size = size self._page.get_active_box().redraw() def _font_changed_cb(self, widget): font_name = widget.get_font_name() logger.debug('Setting font name: %s', font_name) globo_activo = self._page.get_globo_activo() if globo_activo is not None and globo_activo.texto is not None: globo_activo.texto.font_type = font_name self._page.selected_font_name = font_name self._page.get_active_box().redraw() """ Estos son los metodos para setear los contrles de la barra en base a el texto del globo como el globo va a tener un solo font seleccionado, voy a hacer un solo metodo """ def setToggleButtonState(self, button, b, id): button.handler_block(id) button.set_active(b) button.handler_unblock(id) def setToolbarState(self, globeText): # seteo bold self.setToggleButtonState(self._bold, globeText.bold, self._bold_id) # seteo italic self.setToggleButtonState(self._italic, globeText.italic, self._italic_id) # color self._text_color.set_color(Gdk.Color(*globeText.color)) # font size logging.error('Setting font size from globe %s %s', globeText.font_size, globeText.font_size.__class__) self._font_size_combo.handler_block(self._font_size_changed_id) self._font_size_combo.set_font_size(int(globeText.font_size)) self._font_size_combo.handler_unblock(self._font_size_changed_id) # font seleccionada self._font_combo.handler_block(self._fonts_changed_id) self._font_combo.set_font_name(globeText.font_type) self._page.selected_font_name = globeText.font_type self._font_combo.handler_unblock(self._fonts_changed_id)
class TextToolbar(Gtk.Toolbar): _ACTION_TEXT_NAME = 'text' def __init__(self, activity): GObject.GObject.__init__(self) self._activity = activity self.properties = self._activity.area.tool self._text = DrawToolButton('text', activity.tool_group, _('Type')) self.insert(self._text, -1) self._text.connect('clicked', self.set_tool, self._ACTION_TEXT_NAME) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._bold = ToggleToolButton('format-text-bold') self.insert(self._bold, -1) self._bold.show() self._bold.connect('clicked', self.__bold_bt_cb) self._italic = ToggleToolButton('format-text-italic') self.insert(self._italic, -1) self._italic.show() self._italic.connect('clicked', self.__italic_bt_cb) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._font_size = FontSize() self.insert(self._font_size, -1) self._font_size_changed_id = self._font_size.connect( 'changed', self.__font_size_changed_cb) self._font_combo = FontComboBox() self._fonts_changed_id = self._font_combo.connect( 'changed', self.__font_changed_cb) fd = activity.area.get_font_description() font_name = fd.get_family() self._font_combo.set_font_name(font_name) self._font_size.set_font_size(int(fd.get_size() / Pango.SCALE)) tool_item = ToolComboBox(self._font_combo) self.insert(tool_item, -1) self.show_all() def __bold_bt_cb(self, button): fd = self._activity.area.get_font_description() if button.get_active(): fd.set_weight(Pango.Weight.BOLD) else: fd.set_weight(Pango.Weight.NORMAL) self._activity.area.set_font_description(fd) def __italic_bt_cb(self, button): fd = self._activity.area.get_font_description() if button.get_active(): fd.set_style(Pango.Style.ITALIC) else: fd.set_style(Pango.Style.NORMAL) self._activity.area.set_font_description(fd) def __font_size_changed_cb(self, widget): fd = self._activity.area.get_font_description() value = widget.get_font_size() fd.set_size(int(value) * Pango.SCALE) self._activity.area.set_font_description(fd) def __font_changed_cb(self, combo): fd = self._activity.area.get_font_description() font_name = combo.get_font_name() fd.set_family(font_name) self._activity.area.set_font_description(fd) def get_active_text(self, combobox): model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][0] def set_tool(self, widget, tool_name): self.properties['name'] = tool_name self._activity.area.set_tool(self.properties)
class ToolbarBuilder(): def __init__(self, edit, toolbar): self.edit = edit logging.debug('init edit toolbar') logging.debug(self.edit) self.txt_toggle = ToggleToolButton('ascii') self.img_toggle = ToggleToolButton('image') self.jimg_toggle = ToggleToolButton('journal-image') self.jimg_chooser_toggle = ToolButton('load-image-from-journal') self.jtext_chooser_toggle = ToolButton('load-text-from-journal') self.txt_toggle.set_tooltip(_('Text')) self.txt_toggle.connect( 'toggled', self._toggle_cb, [self.txt_toggle, self.img_toggle, self.jimg_toggle]) toolbar.insert(self.txt_toggle, -1) self.img_toggle.set_tooltip(_('Images')) self.img_toggle.connect( 'toggled', self._toggle_cb, [self.txt_toggle, self.img_toggle, self.jimg_toggle]) toolbar.insert(self.img_toggle, -1) self.jimg_toggle.set_tooltip(_('Journal Images')) self.jimg_toggle.connect( 'toggled', self._toggle_cb, [self.txt_toggle, self.img_toggle, self.jimg_toggle]) toolbar.insert(self.jimg_toggle, -1) self.jimg_chooser_toggle.set_tooltip(_('Choose Journal Images')) self.jimg_chooser_toggle.connect('clicked', self._toggle_image_chooser) toolbar.insert(self.jimg_chooser_toggle, -1) self.jtext_chooser_toggle.set_tooltip(_('Choose Journal Text')) self.jtext_chooser_toggle.connect('clicked', self._toggle_text_chooser) toolbar.insert(self.jtext_chooser_toggle, -1) for tab in TABS: for i in tab.toolitems: toolbar.insert(i, -1) self.txt_toggle.set_active(True) def sensitize_all(self): self.txt_toggle.set_sensitive(True) self.img_toggle.set_sensitive(True) self.jimg_toggle.set_sensitive(True) def unsensitize_all(self): self.txt_toggle.set_sensitive(False) self.img_toggle.set_sensitive(False) self.jimg_toggle.set_sensitive(False) def _toggle_image_chooser(self, widget): # self._old_cursor = self.edit.get_window().get_cursor() # self.edit.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) GObject.idle_add(self.__image_chooser) def __image_chooser(self): chooser = ObjectChooser(what_filter=mime.GENERIC_TYPE_IMAGE) result = chooser.run() if result == Gtk.ResponseType.ACCEPT: jobject = chooser.get_selected_object() if jobject and jobject.file_path: title = str(jobject.metadata['title']) path = str(jobject.file_path) TABS[2].gallery.add_image(path, title) # self.edit.get_window().set_cursor(self._old_cursor) def _toggle_text_chooser(self, widget): # self._old_cursor = self.edit.get_window().get_cursor() # self.edit.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) GObject.idle_add(self.__text_chooser) def __text_chooser(self): chooser = ObjectChooser(what_filter=mime.GENERIC_TYPE_TEXT) result = chooser.run() if result == Gtk.ResponseType.ACCEPT: jobject = chooser.get_selected_object() if jobject and jobject.file_path: title = str(jobject.metadata['title']) path = str(jobject.file_path) fp = open(path, 'r') text = fp.read() fp.close() article_data = dehtml(text, title) TABS[0].set_source_article(Article(article_data)) # self.edit.get_window().set_cursor(self._old_cursor) def _toggle_cb(self, widget, toggles): for tab in TABS: for i in tab.toolitems: i.hide() if not widget.get_active(): index = 3 else: for t in range(0, len(toggles)): if toggles[t] != widget: toggles[t].set_active(False) else: index = t for i in TABS[index].toolitems: i.show() # We don't require any article data to display jounal images if book.wiki.article and index != 2: TABS[index].set_source_article(book.wiki.article) if book.custom.article: TABS[index].set_working_article(book.custom.article) self.edit.set_current_page(index)
class DrawEditToolbar(EditToolbar): def __init__(self, activity): EditToolbar.__init__(self) self._activity = activity self.undo.set_tooltip(_('Undo')) self.redo.set_tooltip(_('Redo')) self.copy.set_tooltip(_('Copy')) self.paste.set_tooltip(_('Paste')) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._clear_all = ToolButton('edit-clear') self.insert(self._clear_all, -1) self._clear_all.set_tooltip(_('Clear')) self._clear_all.show() self._sound = ToggleToolButton('speaker-100') self._sound.set_tooltip(_('Enable sound')) if self._activity.area._player is not None: self.insert(self._sound, -1) self._sound.show() self._sound.connect('clicked', self.__sound_cb) self.undo.connect('clicked', self._undo_cb) self.redo.connect('clicked', self._redo_cb) self.copy.connect('clicked', self._copy_cb) self.paste.connect('clicked', self._paste_cb) self._clear_all.connect('clicked', self._clear_all_cb) self._activity.area.connect('undo', self._on_signal_undo_cb) self._activity.area.connect('redo', self._on_signal_redo_cb) self._activity.area.connect('select', self._on_signal_select_cb) self._activity.area.connect('action-saved', self._on_signal_action_saved_cb) def _undo_cb(self, widget, data=None): self._activity.area.undo() def _redo_cb(self, widget, data=None): self._activity.area.redo() def _copy_cb(self, widget, data=None): self._activity.area.copy() def _paste_cb(self, widget, data=None): self._activity.area.paste(self._activity.area) def _on_signal_undo_cb(self, widget, data=None): self._verify_sensitive_buttons() def _on_signal_redo_cb(self, widget, data=None): self._verify_sensitive_buttons() def _on_signal_select_cb(self, widget, data=None): self._verify_sensitive_buttons() def _on_signal_action_saved_cb(self, widget, data=None): self._verify_sensitive_buttons() # define when a button is active def _verify_sensitive_buttons(self): self.undo.set_sensitive(self._activity.area.can_undo()) self.redo.set_sensitive(self._activity.area.can_redo()) self.copy.set_sensitive(self._activity.area.is_selected()) # TODO: it is not possible to verify this yet. # self.paste.set_sensitive(self._activity.area.can_paste()) def _clear_all_cb(self, widget, data=None): self._activity.area.clear() def __sound_cb(self, widget): self._activity.area.enable_sounds(widget.get_active()) if widget.get_active(): self._sound.set_tooltip(_('Disable sound')) else: self._sound.set_tooltip(_('Enable sound'))
class MainToolbox(ToolbarBox): query_changed_signal = GObject.Signal('query-changed', arg_types=([object])) def __init__(self, default_what_filter=None, default_filter_type=None): ToolbarBox.__init__(self) self._mount_point = None self._filter_type = default_filter_type self._what_filter = default_what_filter self._when_filter = None self._default_what_filter = default_what_filter self._default_filter_type = default_filter_type self.search_entry = iconentry.IconEntry() self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'entry-search') text = _('Search in %s') % _('Journal') self.search_entry.set_placeholder_text(text) self.search_entry.connect('activate', self._search_entry_activated_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self.search_entry.add_clear_button() self._autosearch_timer = None self._add_widget(self.search_entry, expand=True) self._favorite_button = ToggleToolButton('emblem-favorite') self._favorite_button.set_tooltip(_('Favorite entries')) self._favorite_button.connect('toggled', self.__favorite_button_toggled_cb) self.toolbar.insert(self._favorite_button, -1) self._favorite_button.show() self._proj_list_button = ToggleToolButton('project-box') self._proj_list_button.set_tooltip(_('Projects')) self._proj_list_button.connect('toggled', self._proj_list_button_clicked_cb) self.toolbar.insert(self._proj_list_button, -1) self._proj_list_button.show() if not self._proj_list_button.props.active: self._what_widget_contents = None self._what_widget = Gtk.ToolItem() self._what_search_button = FilterToolItem('view-type', _('Anything'), self._what_widget) self._what_widget.show() self.toolbar.insert(self._what_search_button, -1) self._what_search_button.show() self._when_search_button = FilterToolItem( 'view-created', _('Anytime'), self._get_when_search_items()) self.toolbar.insert(self._when_search_button, -1) self._when_search_button.show() self._sorting_button = SortingButton() self.toolbar.insert(self._sorting_button, -1) self._sorting_button.connect('sort-property-changed', self.__sort_changed_cb) self._sorting_button.show() ''' # TODO: enable it when the DS supports saving the buddies. self._with_widget = Gtk.ToolItem() self._with_search_button = FilterToolItem( 'view-who', _('Anyone'), self._with_widget) self._with_widget.show() self.toolbar.insert(self._with_search_button, -1) self._with_search_button.show() self._get_with_search_items() ''' self._query = self._build_query() self.refresh_filters() self.connect('size-allocate', self.__size_allocate_cb) def __size_allocate_cb(self, widget, allocation): GLib.idle_add(self._update_buttons, allocation.width) def _update_buttons(self, toolbar_width): # Show the label next to the button icon if there is room on # the toolbar. important = toolbar_width > 13 * style.GRID_CELL_SIZE if not important: self.search_entry.set_size_request( toolbar_width - style.GRID_CELL_SIZE * 7, 0) self._what_search_button.set_is_important(important) self._when_search_button.set_is_important(important) # self._with_search_button.set_is_important(important) return False def _get_when_search_items(self): when_list = [] when_list.append({ 'label': _('Anytime'), 'callback': self._when_palette_cb, 'id': _ACTION_ANYTIME }) when_list.append({'separator': True}) when_list.append({ 'label': _('Today'), 'callback': self._when_palette_cb, 'id': _ACTION_TODAY }) when_list.append({ 'label': _('Since yesterday'), 'callback': self._when_palette_cb, 'id': _ACTION_SINCE_YESTERDAY }) when_list.append({ 'label': _('Past week'), 'callback': self._when_palette_cb, 'id': _ACTION_PAST_WEEK }) when_list.append({ 'label': _('Past month'), 'callback': self._when_palette_cb, 'id': _ACTION_PAST_MONTH }) when_list.append({ 'label': _('Past year'), 'callback': self._when_palette_cb, 'id': _ACTION_PAST_YEAR }) return set_palette_list(when_list) ''' def _get_with_search_items(self): with_list = [] with_list.append({'label':_('Anyone'), 'callback': self._with_palette_cb, 'id': _ACTION_EVERYBODY}) with_list.append({'separator': True}) with_list.append({'label':_('My friends'), 'callback': self._with_palette_cb, 'id': _ACTION_MY_FRIENDS}) with_list.append({'label':_('My class'), 'callback': self._with_palette_cb, 'id': _ACTION_MY_CLASS}) with_list.append({'separator': True}) # TODO: Ask the model for buddies. for i, buddy in enumerate(model.get_buddies()): nick, color = buddy with_list.append({'label': nick, 'callback': self._with_palette_cb, 'icon': 'computer-xo', 'xocolors': XOColor(color), 'id': i + _ACTION_MY_CLASS + 1}) widget = set_palette_list(with_list) self._with_widget.add(widget) widget.show() ''' def _add_widget(self, widget, expand=False): tool_item = Gtk.ToolItem() tool_item.set_expand(expand) tool_item.add(widget) widget.show() self.toolbar.insert(tool_item, -1) tool_item.show() def _build_query(self): query = {} if self._mount_point: query['mountpoints'] = [self._mount_point] if self._favorite_button.props.active: query['keep'] = 1 if self._proj_list_button.props.active: query['activity'] = 'org.sugarlabs.Project' elif self._what_filter: filter_type = self._filter_type value = self._what_filter if filter_type == FILTER_TYPE_GENERIC_MIME: generic_type = mime.get_generic_type(value) if generic_type: mime_types = generic_type.mime_types query['mime_type'] = mime_types else: logging.error('filter_type="generic_mime", ' 'but "%s" is not a generic mime' % value) elif filter_type == FILTER_TYPE_ACTIVITY: query['activity'] = value elif self._filter_type == FILTER_TYPE_MIME_BY_ACTIVITY: registry = bundleregistry.get_registry() bundle = \ registry.get_bundle(value) if bundle is not None: query['mime_type'] = bundle.get_mime_types() else: logging.error('Trying to filter using activity mimetype ' 'but bundle id is wrong %s' % value) if self._when_filter: date_from, date_to = self._get_date_range() query['timestamp'] = {'start': date_from, 'end': date_to} if self.search_entry.props.text: text = self.search_entry.props.text.strip() if text: query['query'] = text property_, order = self._sorting_button.get_current_sort() if order == Gtk.SortType.ASCENDING: sign = '+' else: sign = '-' query['order_by'] = [sign + property_] return query def _get_date_range(self): today_start = datetime.today().replace(hour=0, minute=0, second=0) right_now = datetime.today() if self._when_filter == _ACTION_TODAY: date_range = (today_start, right_now) elif self._when_filter == _ACTION_SINCE_YESTERDAY: date_range = (today_start - timedelta(1), right_now) elif self._when_filter == _ACTION_PAST_WEEK: date_range = (today_start - timedelta(7), right_now) elif self._when_filter == _ACTION_PAST_MONTH: date_range = (today_start - timedelta(30), right_now) elif self._when_filter == _ACTION_PAST_YEAR: date_range = (today_start - timedelta(356), right_now) return (time.mktime(date_range[0].timetuple()), time.mktime(date_range[1].timetuple())) def __sort_changed_cb(self, button): self._update_if_needed() def _update_if_needed(self): new_query = self._build_query() if self._query != new_query: self._query = new_query self.query_changed_signal.emit(self._query) def _search_entry_activated_cb(self, search_entry): if self._autosearch_timer: GLib.source_remove(self._autosearch_timer) self._update_if_needed() def _search_entry_changed_cb(self, search_entry): if not search_entry.props.text: search_entry.activate() return if self._autosearch_timer: GLib.source_remove(self._autosearch_timer) self._autosearch_timer = GLib.timeout_add(_AUTOSEARCH_TIMEOUT, self._autosearch_timer_cb) def _autosearch_timer_cb(self): logging.debug('_autosearch_timer_cb') self._autosearch_timer = None self.search_entry.activate() return False def set_mount_point(self, mount_point): self._mount_point = mount_point self._update_if_needed() def set_what_filter(self, what_filter): for item in self._what_list: if 'id' in item and item['id'] == what_filter: self._what_search_button.set_widget_label(item['label']) if item['id'] == 0: self._what_search_button.set_widget_icon( icon_name='view-type') elif 'icon' in item: self._what_search_button.set_widget_icon( icon_name=item['icon']) self._filter_type = FILTER_TYPE_GENERIC_MIME elif 'file' in item: self._what_search_button.set_widget_icon( file_name=item['file']) if self._default_filter_type is not None: self._filter_type = self._default_filter_type else: self._filter_type = FILTER_TYPE_ACTIVITY self._what_filter = what_filter break def update_filters(self, mount_point, what_filter, filter_type=None): self._mount_point = mount_point self._filter_type = filter_type self._what_filter = what_filter self.set_what_filter(what_filter) self._update_if_needed() def set_filter_type(self, filter_type): self._filter_type = filter_type self._update_if_needed() def _what_palette_cb(self, widget, event, item): self._what_search_button.set_widget_label(item['label']) if item['id'] == 0: self._what_search_button.set_widget_icon(icon_name='view-type') elif 'icon' in item: self._what_search_button.set_widget_icon(icon_name=item['icon']) self._filter_type = FILTER_TYPE_GENERIC_MIME elif 'file' in item: self._what_search_button.set_widget_icon(file_name=item['file']) if self._default_filter_type is not None: self._filter_type = self._default_filter_type else: self._filter_type = FILTER_TYPE_ACTIVITY self._what_filter = item['id'] new_query = self._build_query() if self._query != new_query: self._query = new_query self.query_changed_signal.emit(self._query) def _when_palette_cb(self, widget, event, item): self._when_search_button.set_widget_label(item['label']) self._when_filter = item['id'] new_query = self._build_query() if self._query != new_query: self._query = new_query self.query_changed_signal.emit(self._query) def refresh_filters(self): # refresh_what_filters self._what_list = [] what_list_activities = [] try: # TRANS: Item on a palette that filters by entry type. self._what_list.append({ 'label': _('Anything'), 'icon': 'application-octet-stream', 'callback': self._what_palette_cb, 'id': _ACTION_ANYTHING }) registry = bundleregistry.get_registry() appended_separator = False types = mime.get_all_generic_types() for generic_type in types: if not appended_separator: self._what_list.append({'separator': True}) appended_separator = True self._what_list.append({ 'label': generic_type.name, 'icon': generic_type.icon, 'callback': self._what_palette_cb, 'id': generic_type.type_id }) self._what_list.append({'separator': True}) for bundle_id in model.get_unique_values('activity'): activity_info = registry.get_bundle(bundle_id) if activity_info is None: continue # try activity-provided icon if os.path.exists(activity_info.get_icon()): try: what_list_activities.append({ 'label': activity_info.get_name(), 'file': activity_info.get_icon(), 'callback': self._what_palette_cb, 'id': bundle_id }) except GLib.GError as exception: # fall back to generic icon logging.warning( 'Falling back to default icon for' ' "what" filter because %r (%r) has an' ' invalid icon: %s', activity_info.get_name(), str(bundle_id), exception) what_list_activities.append({ 'label': activity_info.get_name(), 'icon': 'application-octet-stream', 'callback': self._what_palette_cb, 'id': bundle_id }) finally: for item in sorted(what_list_activities, key=lambda x: x['label']): self._what_list.append(item) if self._what_widget_contents is not None: self._what_widget.remove(self._what_widget_contents) self._what_widget_contents = set_palette_list(self._what_list) self._what_widget.add(self._what_widget_contents) self._what_widget_contents.show() def _proj_list_button_clicked_cb(self, proj_list_button): if self._proj_list_button.props.active: self._what_widget.hide() self._what_search_button.hide() else: self._what_widget.show() self._what_search_button.show() self._update_if_needed() def __favorite_button_toggled_cb(self, favorite_button): self._update_if_needed() def is_filter_changed(self): return not (self._filter_type == self._default_filter_type and self._what_filter == self._default_what_filter and self._when_filter is None and self._favorite_button.props.active is False and self.search_entry.props.text == '') def clear_query(self): self.search_entry.props.text = '' self._filter_type = self._default_filter_type self._what_search_button.set_widget_icon(icon_name='view-type') self._what_search_button.set_widget_label(_('Anything')) self.set_what_filter(self._default_what_filter) self._when_search_button.set_widget_icon(icon_name='view-created') self._when_search_button.set_widget_label(_('Anytime')) self._when_filter = None ''' self._with_search_button.set_widget_icon(icon_name='view-who') self._with_search_button.set_widget_label(_('Anyone')) self._with_filter = None ''' self._favorite_button.props.active = False if self._proj_list_button.props.active: self._what_widget.show() self._what_search_button.show() self._proj_list_button.props.active = False self._update_if_needed()
class SpeechToolbar(Gtk.Toolbar): def __init__(self, activity): Gtk.Toolbar.__init__(self) self._activity = activity if not speech.supported: return self.is_paused = False self._cnf_client = GConf.Client.get_default() self.load_speech_parameters() self.sorted_voices = [i for i in speech.voices()] self.sorted_voices.sort(self.compare_voices) default = 0 for voice in self.sorted_voices: if voice[0] == speech.voice[0]: break default = default + 1 # Play button self.play_btn = ToggleToolButton('media-playback-start') self.play_btn.show() self.play_btn.connect('toggled', self.play_cb) self.insert(self.play_btn, -1) self.play_btn.set_tooltip(_('Play / Pause')) # Stop button self.stop_btn = ToolButton('media-playback-stop') self.stop_btn.show() self.stop_btn.connect('clicked', self.stop_cb) self.stop_btn.set_sensitive(False) self.insert(self.stop_btn, -1) self.stop_btn.set_tooltip(_('Stop')) self.voice_combo = ComboBox() for voice in self.sorted_voices: self.voice_combo.append_item(voice, voice[0]) self.voice_combo.set_active(default) self.voice_combo.connect('changed', self.voice_changed_cb) combotool = ToolComboBox(self.voice_combo) self.insert(combotool, -1) combotool.show() speech.reset_buttons_cb = self.reset_buttons_cb def compare_voices(self, a, b): if a[0].lower() == b[0].lower(): return 0 if a[0] .lower() < b[0].lower(): return -1 if a[0] .lower() > b[0].lower(): return 1 def voice_changed_cb(self, combo): speech.voice = combo.props.value speech.say(speech.voice[0]) self.save_speech_parameters() def load_speech_parameters(self): speech_parameters = {} data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') if os.path.exists(data_file_name): f = open(data_file_name, 'r') try: speech_parameters = json.load(f) speech.voice = speech_parameters['voice'] finally: f.close() self._cnf_client.add_dir('/desktop/sugar/speech', GConf.ClientPreloadType.PRELOAD_NONE) speech.pitch = self._cnf_client.get_int('/desktop/sugar/speech/pitch') speech.rate = self._cnf_client.get_int('/desktop/sugar/speech/rate') self._cnf_client.notify_add('/desktop/sugar/speech/pitch', self.__conf_changed_cb, None) self._cnf_client.notify_add('/desktop/sugar/speech/rate', self.__conf_changed_cb, None) def __conf_changed_cb(self, client, connection_id, entry, args): key = entry.get_key() value = client.get_int(key) if key == '/desktop/sugar/speech/pitch': speech.pitch = value if key == '/desktop/sugar/speech/rate': speech.rate = value def save_speech_parameters(self): speech_parameters = {} speech_parameters['voice'] = speech.voice data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') f = open(data_file_name, 'w') try: json.dump(speech_parameters, f) finally: f.close() def reset_buttons_cb(self): self.play_btn.set_icon_name('media-playback-start') self.stop_btn.set_sensitive(False) self.is_paused = False def play_cb(self, widget): self.stop_btn.set_sensitive(True) if widget.get_active(): self.play_btn.set_icon_name('media-playback-pause') if not self.is_paused: speech.play(self._activity._view.get_marked_words()) else: speech.continue_play() else: self.play_btn.set_icon_name('media-playback-start') self.is_paused = True speech.pause() def stop_cb(self, widget): self.stop_btn.set_sensitive(False) self.play_btn.set_icon_name('media-playback-start') self.play_btn.set_active(False) self.is_paused = False speech.stop()
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 = GLib.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
class MazeActivity(activity.Activity): def __init__(self, handle): """Set up the Maze activity.""" activity.Activity.__init__(self, handle) self._busy_count = 0 self._unbusy_idle_sid = None self.build_toolbar() self.pservice = PresenceService() self.owner = self.pservice.get_owner() state = None if 'state' in self.metadata: state = json.loads(self.metadata['state']) self.game = game.MazeGame(self, self.owner, state) self.set_canvas(self.game) self.game.show() self.connect("key_press_event", self.game.key_press_cb) self.text_channel = None self.my_key = profile.get_pubkey() self._alert = None if self.shared_activity: # we are joining the activity self._add_alert(_('Joining a maze'), _('Connecting...')) self.connect('joined', self._joined_cb) if self.get_shared(): # we have already joined self._joined_cb() else: # we are creating the activity self.connect('shared', self._shared_cb) def busy(self): if self._busy_count == 0: if self._unbusy_idle_sid is not None: GLib.source_remove(self._unbusy_idle_sid) self._unbusy_idle_sid = None self._old_cursor = self.get_window().get_cursor() self._set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) self._busy_count += 1 def unbusy(self): self._unbusy_idle_sid = GLib.idle_add(self._unbusy_idle_cb) def _unbusy_idle_cb(self): self._unbusy_idle_sid = None self._busy_count -= 1 if self._busy_count == 0: self._set_cursor(self._old_cursor) def _set_cursor(self, cursor): self.get_window().set_cursor(cursor) Gdk.flush() def build_toolbar(self): """Build our Activity toolbar for the Sugar system.""" toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() easier_button = ToolButton('create-easier') easier_button.set_tooltip(_('Easier level')) easier_button.connect('clicked', self._easier_button_cb) toolbar_box.toolbar.insert(easier_button, -1) harder_button = ToolButton('create-harder') harder_button.set_tooltip(_('Harder level')) harder_button.connect('clicked', self._harder_button_cb) toolbar_box.toolbar.insert(harder_button, -1) separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() self.show_trail_button = ToggleToolButton('show-trail') self.show_trail_button.set_tooltip(_('Show trail')) self.show_trail_button.set_active(True) self.show_trail_button.connect('toggled', self._toggled_show_trail_cb) toolbar_box.toolbar.insert(self.show_trail_button, -1) 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_button = StopButton(self) toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() return toolbar_box def _easier_button_cb(self, button): self.game.easier() def _harder_button_cb(self, button): self.game.harder() def _toggled_show_trail_cb(self, button): if self.game.set_show_trail(button.get_active()): self.broadcast_msg('show_trail:%s' % str(button.get_active())) def _shared_cb(self, activity): logging.debug('Maze was shared') self._add_alert(_('Sharing'), _('This maze is shared.')) self._setup() def _joined_cb(self, activity): """Joined a shared activity.""" if not self.shared_activity: return logging.debug('Joined a shared chat') for buddy in self.shared_activity.get_joined_buddies(): self._buddy_already_exists(buddy) self._setup() # request maze data self.broadcast_msg('req_maze') def _setup(self): self.text_channel = TextChannelWrapper( self.shared_activity.telepathy_text_chan, self.shared_activity.telepathy_conn, self.pservice) self.text_channel.set_received_callback(self._received_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) def _received_cb(self, buddy, text): if buddy == self.owner: return self.game.msg_received(buddy, text) def _add_alert(self, title, text=None): self.grab_focus() self._alert = ErrorAlert() self._alert.props.title = title self._alert.props.msg = text self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show() def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) self._alert = None def update_alert(self, title, text=None): if self._alert is not None: self._alert.props.title = title self._alert.props.msg = text def show_accelerator_alert(self): self.grab_focus() self._alert = NotifyAlert() self._alert.props.title = _('Tablet mode detected.') self._alert.props.msg = _('Hold your XO flat and tilt to play!') self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show() def _buddy_joined_cb(self, activity, buddy): """Show a buddy who joined""" logging.debug('buddy joined') if buddy == self.owner: logging.debug('its me, exit!') return self.game.buddy_joined(buddy) def _buddy_left_cb(self, activity, buddy): self.game.buddy_left(buddy) def _buddy_already_exists(self, buddy): """Show a buddy already in the chat.""" if buddy == self.owner: return self.game.buddy_joined(buddy) def broadcast_msg(self, message): if self.text_channel: # FIXME: can't identify the sender at the other end, # add the pubkey to the text message self.text_channel.send('%s|%s' % (self.my_key, message)) def write_file(self, file_path): logging.debug('Saving the state of the game...') data = { 'seed': self.game.maze.seed, 'width': self.game.maze.width, 'height': self.game.maze.height, 'finish_time': self.game.finish_time } logging.debug('Saving data: %s', data) self.metadata['state'] = json.dumps(data) def can_close(self): self.game.close_finish_window() return True def read_file(self, file_path): pass
class ReadToolbar(Gtk.Toolbar): __gtype_name__ = 'ReadToolbar' def __init__(self): Gtk.Toolbar.__init__(self) self.back = ToolButton('go-previous') self.back.set_tooltip(_('Back')) self.back.props.sensitive = False palette = self.back.get_palette() self.prev_page = MenuItem(text_label=_("Previous page")) palette.menu.append(self.prev_page) self.prev_page.show_all() self.prev_bookmark = MenuItem(text_label=_("Previous bookmark")) palette.menu.append(self.prev_bookmark) self.prev_bookmark.show_all() self.back.connect('clicked', self.go_back_cb) self.prev_page.connect('activate', self.go_back_cb) self.prev_bookmark.connect('activate', self.prev_bookmark_activate_cb) self.insert(self.back, -1) self.back.show() self.forward = ToolButton('go-next') self.forward.set_tooltip(_('Forward')) self.forward.props.sensitive = False palette = self.forward.get_palette() self.next_page = MenuItem(text_label=_("Next page")) palette.menu.append(self.next_page) self.next_page.show_all() self.next_bookmark = MenuItem(text_label=_("Next bookmark")) palette.menu.append(self.next_bookmark) self.next_bookmark.show_all() self.forward.connect('clicked', self.go_forward_cb) self.next_page.connect('activate', self.go_forward_cb) self.next_bookmark.connect('activate', self.next_bookmark_activate_cb) self.insert(self.forward, -1) self.forward.show() num_page_item = Gtk.ToolItem() self.num_page_entry = Gtk.Entry() self.num_page_entry.set_text('0') self.num_page_entry.set_alignment(1) self.num_page_entry.connect('insert-text', self.num_page_entry_insert_text_cb) self.num_page_entry.connect('activate', self.num_page_entry_activate_cb) self.num_page_entry.set_width_chars(4) num_page_item.add(self.num_page_entry) self.num_page_entry.show() self.insert(num_page_item, -1) num_page_item.show() total_page_item = Gtk.ToolItem() self.total_page_label = Gtk.Label() self.total_page_label.set_markup( "<span size='14000' foreground='black'>") self.total_page_label.set_text(' / 0') total_page_item.add(self.total_page_label) self.total_page_label.show() self.insert(total_page_item, -1) total_page_item.show() spacer = Gtk.SeparatorToolItem() self.insert(spacer, -1) spacer.show() bookmarkitem = Gtk.ToolItem() self.bookmarker = ToggleToolButton('emblem-favorite') self.bookmarker.set_tooltip(_('Toggle Bookmark')) self.bookmarker_handler_id = self.bookmarker.connect( 'clicked', self.bookmarker_clicked_cb) bookmarkitem.add(self.bookmarker) self.insert(bookmarkitem, -1) bookmarkitem.show_all() underline_item = Gtk.ToolItem() self.underline = ToggleToolButton('format-text-underline') self.underline.set_tooltip(_('Underline')) self.underline.props.sensitive = False self.underline_id = self.underline.connect('clicked', self.underline_cb) underline_item.add(self.underline) self.insert(underline_item, -1) underline_item.show_all() def num_page_entry_insert_text_cb(self, entry, text, length, position): if not re.match('[0-9]', text): entry.emit_stop_by_name('insert-text') return True return False def num_page_entry_activate_cb(self, entry): if entry.props.text: page = int(entry.props.text) - 1 else: page = 0 if page >= self.total_pages: page = self.total_pages - 1 elif page < 0: page = 0 self.current_page = page self.activity.set_current_page(page) self.activity.show_page(page) entry.props.text = str(page + 1) self.update_nav_buttons() def go_back_cb(self, button): self.activity.page_previous() def go_forward_cb(self, button): self.activity.page_next() def update_nav_buttons(self): current_page = self.current_page self.back.props.sensitive = current_page > 0 self.forward.props.sensitive = \ current_page < self.total_pages - 1 self.num_page_entry.props.text = str(current_page + 1) self.total_page_label.props.label = \ ' / ' + str(self.total_pages) def set_total_pages(self, pages): self.total_pages = pages def set_current_page(self, page): self.current_page = page self.update_nav_buttons() def set_activity(self, activity): self.activity = activity def prev_bookmark_activate_cb(self, menuitem): self.activity.prev_bookmark() def next_bookmark_activate_cb(self, menuitem): self.activity.next_bookmark() def bookmarker_clicked_cb(self, button): self.activity.bookmarker_clicked(button) def underline_cb(self, button): self.activity.underline_clicked(button) def setToggleButtonState(self, button, b, id): button.handler_block(id) button.set_active(b) button.handler_unblock(id) def update_underline_button(self, state): self.setToggleButtonState(self.underline, state, self.underline_id) def update_bookmark_button(self, state): self.setToggleButtonState(self.bookmarker, state, self.bookmarker_handler_id)
class SpeechToolbar(Gtk.Toolbar): def __init__(self, activity): Gtk.Toolbar.__init__(self) self._activity = activity self._speech = SpeechManager() self._is_paused = False self.load_speech_parameters() self._voices = self._speech.get_all_voices() # a dictionary locale = os.environ.get('LANG', '') language_location = locale.split('.', 1)[0].lower() language = language_location.split('_')[0] # if the language is es but not es_es default to es_la (latin voice) if language == 'es' and language_location != 'es_es': language_location = 'es_la' self._voice = 'en_us' if language_location in self._voices: self._voice = language_location elif language in self._voices: self._voice = language voice_names = [] for language, name in self._voices.iteritems(): voice_names.append((language, name)) voice_names.sort(self._compare_voice) # Play button self._play_button = ToggleToolButton('media-playback-start') self._play_button.show() self._play_button.connect('toggled', self._play_toggled_cb) self.insert(self._play_button, -1) self._play_button.set_tooltip(_('Play / Pause')) # Stop button self._stop_button = ToolButton('media-playback-stop') self._stop_button.show() self._stop_button.connect('clicked', self._stop_clicked_cb) self._stop_button.set_sensitive(False) self.insert(self._stop_button, -1) self._stop_button.set_tooltip(_('Stop')) # Language list combo = ComboBox() which = 0 for pair in voice_names: language, name = pair combo.append_item(language, name) if language == self._voice: combo.set_active(which) which += 1 combo.connect('changed', self._voice_changed_cb) combotool = ToolComboBox(combo) self.insert(combotool, -1) combotool.show() self._speech.connect('stop', self._reset_buttons_cb) def _compare_voice(self, a, b): if a[1].lower() == b[1].lower(): return 0 if a[1].lower() < b[1].lower(): return -1 if a[1].lower() > b[1].lower(): return 1 def _voice_changed_cb(self, combo): self._voice = combo.props.value self._speech.say_text(self._voices[self._voice]) self.save_speech_parameters() def load_speech_parameters(self): speech_parameters = {} data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') if os.path.exists(data_file_name): f = open(data_file_name, 'r') try: speech_parameters = json.load(f) self._voice = speech_parameters['voice'] finally: f.close() def save_speech_parameters(self): speech_parameters = {} speech_parameters['voice'] = self._voice data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') f = open(data_file_name, 'w') try: json.dump(speech_parameters, f) finally: f.close() def _reset_buttons_cb(self, widget=None): self._play_button.set_icon_name('media-playback-start') self._stop_button.set_sensitive(False) self._is_paused = False def _play_toggled_cb(self, widget): self._stop_button.set_sensitive(True) if widget.get_active(): self._play_button.set_icon_name('media-playback-pause') if not self._is_paused: self._speech.say_text(self._activity._view.get_marked_words(), lang_code=self._voice) else: self._speech.restart() else: self._play_button.set_icon_name('media-playback-start') self._is_paused = True self._speech.pause() def _stop_clicked_cb(self, widget): self._stop_button.set_sensitive(False) self._play_button.set_icon_name('media-playback-start') self._play_button.set_active(False) self._is_paused = False self._speech.stop()
class DrawEditToolbar(EditToolbar): def __init__(self, activity): EditToolbar.__init__(self) self._activity = activity self.undo.set_tooltip(_('Undo')) self.redo.set_tooltip(_('Redo')) self.copy.set_tooltip(_('Copy')) self.paste.set_tooltip(_('Paste')) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._clear_all = ToolButton('edit-clear') self.insert(self._clear_all, -1) self._clear_all.set_tooltip(_('Clear')) self._clear_all.show() self._sound = ToggleToolButton('speaker-100') self._sound.set_tooltip(_('Enable sound')) if self._activity.area._player is not None: self.insert(self._sound, -1) self._sound.show() self._sound.connect('clicked', self.__sound_cb) self.undo.connect('clicked', self._undo_cb) self.redo.connect('clicked', self._redo_cb) self.copy.connect('clicked', self._copy_cb) self.paste.connect('clicked', self._paste_cb) self._clear_all.connect('clicked', self._clear_all_cb) self._activity.area.connect('undo', self._on_signal_undo_cb) self._activity.area.connect('redo', self._on_signal_redo_cb) self._activity.area.connect('select', self._on_signal_select_cb) self._activity.area.connect('action-saved', self._on_signal_action_saved_cb) def _undo_cb(self, widget, data=None): self._activity.area.undo() def _redo_cb(self, widget, data=None): self._activity.area.redo() def _copy_cb(self, widget, data=None): self._activity.area.copy() def _paste_cb(self, widget, data=None): self._activity.area.paste(self._activity.area) def _on_signal_undo_cb(self, widget, data=None): self._verify_sensitive_buttons() def _on_signal_redo_cb(self, widget, data=None): self._verify_sensitive_buttons() def _on_signal_select_cb(self, widget, data=None): self._verify_sensitive_buttons() def _on_signal_action_saved_cb(self, widget, data=None): self._verify_sensitive_buttons() # define when a button is active def _verify_sensitive_buttons(self): self.undo.set_sensitive(self._activity.area.can_undo()) self.redo.set_sensitive(self._activity.area.can_redo()) self.copy.set_sensitive(self._activity.area.is_selected()) # TODO: it is not possible to verify this yet. # self.paste.set_sensitive(self._activity.area.can_paste()) def _clear_all_cb(self, widget, data=None): self._activity.area.clear() def __sound_cb(self, widget): self._activity.area.enable_sounds(widget.get_active()) if widget.get_active(): self._sound.set_tooltip(_('Disable sound')) else: self._sound.set_tooltip(_('Enable sound'))
def __init__(self, handle): activity.Activity.__init__(self, handle) self.set_title('FotoToon') self._max_participants = 1 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page toolbar_box.toolbar.insert(activity_button, 0) edit_toolbar_btn = ToolbarButton() edit_toolbar = Gtk.Toolbar() edit_toolbar_btn.props.page = edit_toolbar edit_toolbar_btn.props.icon_name = 'toolbar-edit' edit_toolbar_btn.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar_btn, -1) view_toolbar_btn = ToolbarButton() view_toolbar = Gtk.Toolbar() view_toolbar_btn.props.page = view_toolbar view_toolbar_btn.props.icon_name = 'toolbar-view' view_toolbar_btn.label = _('View') toolbar_box.toolbar.insert(view_toolbar_btn, -1) slideview_btn = ToggleToolButton('slideshow') slideview_btn.set_tooltip(_('Slideshow')) slideview_btn.set_active(False) view_toolbar.insert(slideview_btn, -1) slideview_btn.show() fullscreen_btn = ToolButton('view-fullscreen') fullscreen_btn.set_tooltip(_('Fullscreen')) fullscreen_btn.props.accelerator = '<Alt>Return' fullscreen_btn.connect('clicked', lambda w: self.fullscreen()) view_toolbar.insert(fullscreen_btn, -1) fullscreen_btn.show() self.set_toolbar_box(toolbar_box) toolbar = toolbar_box.toolbar self.page = Page() self.globes_manager = GlobesManager(toolbar, edit_toolbar, self) # fonts text_button = ToolbarButton() text_button.props.page = TextToolbar(self.page) text_button.props.icon_name = 'format-text-size' text_button.props.label = _('Text') slideview_btn.connect('clicked', self._switch_view_mode, text_button) toolbar_box.toolbar.insert(text_button, -1) reorder_img_btn = ToolButton('thumbs-view') reorder_img_btn.set_icon_name('thumbs-view') reorder_img_btn.set_tooltip(_('Change image order')) reorder_img_btn.connect('clicked', self.__image_order_cb) edit_toolbar.insert(reorder_img_btn, -1) reorder_img_btn.show() bgchange = ToolButton(icon_name='contract-coordinates') bgchange.set_tooltip(_('Edit background image')) bgchange.connect('clicked', self.__bgchange_clicked_cb) edit_toolbar.insert(bgchange, -1) bgchange.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() # add export button separator_2 = Gtk.SeparatorToolItem() separator_2.show() activity_toolbar.insert(separator_2, -1) self.bt_save_as_image = ToolButton() self.bt_save_as_image.props.icon_name = 'save-as-image' self.bt_save_as_image.connect('clicked', self.write_image) self.bt_save_as_image.set_tooltip(_('Save as Image')) activity_toolbar.insert(self.bt_save_as_image, -1) self.bt_save_as_image.show() save_as_pdf = ToolButton() save_as_pdf.props.icon_name = 'save-as-pdf' save_as_pdf.connect('clicked', self._save_as_pdf) save_as_pdf.set_tooltip(_('Save as a Book (PDF)')) activity_toolbar.insert(save_as_pdf, -1) save_as_pdf.show() activity_button.page.title.connect("focus-in-event", self.on_title) scrolled = Gtk.ScrolledWindow() #scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS) scrolled.add_with_viewport(self.page) scrolled.set_kinetic_scrolling(False) scrolled.show_all() self._slideview = SlideView(self) self._slideview.show_all() self._notebook = Gtk.Notebook() self._notebook.set_show_tabs(False) self._notebook.append_page(scrolled, None) self._notebook.append_page(self._slideview, None) self._notebook.show_all() self.set_canvas(self._notebook) self.show() self.metadata['mime_type'] = 'application/x-fototoon-activity' self.page.empty_page = handle.object_id is None self._key_press_signal_id = None
class SpeechToolbar(Gtk.Toolbar): def __init__(self, activity): Gtk.Toolbar.__init__(self) voicebar = Gtk.Toolbar() self._activity = activity if not speech.supported: return self.load_speech_parameters() self.sorted_voices = [i for i in speech.voices()] self.sorted_voices.sort(self.compare_voices) default = 0 for voice in self.sorted_voices: if voice[0] == speech.voice[0]: break default = default + 1 # Play button self.play_btn = ToggleToolButton('media-playback-start') self.play_btn.show() self.play_btn.connect('toggled', self.play_cb) self.insert(self.play_btn, -1) self.play_btn.set_tooltip(_('Play / Pause')) self.voice_combo = ComboBox() for voice in self.sorted_voices: self.voice_combo.append_item(voice, voice[0]) self.voice_combo.set_active(default) self.voice_combo.connect('changed', self.voice_changed_cb) combotool = ToolComboBox(self.voice_combo) self.insert(combotool, -1) combotool.show() self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0) pitchbar = Gtk.HScale(self.pitchadj) pitchbar.set_draw_value(False) pitchbar.set_update_policy(Gtk.UPDATE_DISCONTINUOUS) pitchbar.set_size_request(150, 15) self.pitchadj.set_value(speech.pitch) pitchtool = Gtk.ToolItem() pitchtool.add(pitchbar) pitchtool.show() self.insert(pitchtool, -1) pitchbar.show() self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0) ratebar = Gtk.HScale(self.rateadj) ratebar.set_draw_value(False) ratebar.set_update_policy(Gtk.UPDATE_DISCONTINUOUS) ratebar.set_size_request(150, 15) self.rateadj.set_value(speech.rate) ratetool = Gtk.ToolItem() ratetool.add(ratebar) ratetool.show() self.insert(ratetool, -1) ratebar.show() self.pitchadj.connect("value_changed", self.pitch_adjusted_cb) self.rateadj.connect("value_changed", self.rate_adjusted_cb) def compare_voices(self, a, b): if a[0].lower() == b[0].lower(): return 0 if a[0] .lower() < b[0].lower(): return -1 if a[0] .lower() > b[0].lower(): return 1 def voice_changed_cb(self, combo): speech.voice = combo.props.value speech.say(speech.voice[0]) self.save_speech_parameters() def pitch_adjusted_cb(self, get): speech.pitch = int(get.value) speech.say(_("pitch adjusted")) self.save_speech_parameters() def rate_adjusted_cb(self, get): speech.rate = int(get.value) speech.say(_("rate adjusted")) self.save_speech_parameters() def load_speech_parameters(self): speech_parameters = {} data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') if os.path.exists(data_file_name): f = open(data_file_name, 'r') try: speech_parameters = simplejson.load(f) speech.pitch = speech_parameters['pitch'] speech.rate = speech_parameters['rate'] speech.voice = speech_parameters['voice'] finally: f.close() def save_speech_parameters(self): speech_parameters = {} speech_parameters['pitch'] = speech.pitch speech_parameters['rate'] = speech.rate speech_parameters['voice'] = speech.voice data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') f = open(data_file_name, 'w') try: simplejson.dump(speech_parameters, f) finally: f.close() def play_cb(self, widget): if widget.get_active(): self.play_btn.set_named_icon('media-playback-pause') if speech.is_stopped(): speech.play(self._activity._view.get_marked_words()) else: self.play_btn.set_named_icon('media-playback-start') speech.stop()
class SpeechToolbar(Gtk.Toolbar): def __init__(self, activity): GObject.GObject.__init__(self) self._activity = activity if not speech.supported: return self.is_paused = False self._cnf_client = GConf.Client.get_default() self.load_speech_parameters() self.sorted_voices = [i for i in speech.voices()] self.sorted_voices.sort(self.compare_voices) default = 0 for voice in self.sorted_voices: if voice[0] == speech.voice[0]: break default = default + 1 # Play button self.play_btn = ToggleToolButton("media-playback-start") self.play_btn.show() self.play_toggled_handler = self.play_btn.connect("toggled", self.play_cb) self.insert(self.play_btn, -1) self.play_btn.set_tooltip(_("Play / Pause")) # Stop button self.stop_btn = ToolButton("media-playback-stop") self.stop_btn.show() self.stop_btn.connect("clicked", self.stop_cb) self.stop_btn.set_sensitive(False) self.insert(self.stop_btn, -1) self.stop_btn.set_tooltip(_("Stop")) self.voice_combo = ComboBox() for voice in self.sorted_voices: self.voice_combo.append_item(voice, voice[0]) self.voice_combo.set_active(default) self.voice_combo.connect("changed", self.voice_changed_cb) combotool = ToolComboBox(self.voice_combo) self.insert(combotool, -1) combotool.show() speech.reset_cb = self.reset_buttons_cb speech.end_text_cb = self.reset_buttons_cb def compare_voices(self, a, b): if a[0].lower() == b[0].lower(): return 0 if a[0].lower() < b[0].lower(): return -1 if a[0].lower() > b[0].lower(): return 1 def voice_changed_cb(self, combo): speech.voice = combo.props.value speech.say(speech.voice[0]) self.save_speech_parameters() def load_speech_parameters(self): speech_parameters = {} data_path = os.path.join(self._activity.get_activity_root(), "data") data_file_name = os.path.join(data_path, "speech_params.json") if os.path.exists(data_file_name): f = open(data_file_name, "r") try: speech_parameters = json.load(f) speech.voice = speech_parameters["voice"] finally: f.close() else: speech.voice = self.get_default_voice() logging.error("Default voice %s", speech.voice) self._cnf_client.add_dir("/desktop/sugar/speech", GConf.ClientPreloadType.PRELOAD_NONE) speech.pitch = self._cnf_client.get_int("/desktop/sugar/speech/pitch") speech.rate = self._cnf_client.get_int("/desktop/sugar/speech/rate") self._cnf_client.notify_add("/desktop/sugar/speech/pitch", self.__conf_changed_cb, None) self._cnf_client.notify_add("/desktop/sugar/speech/rate", self.__conf_changed_cb, None) def get_default_voice(self): """Try to figure out the default voice, from the current locale ($LANG) Fall back to espeak's voice called Default.""" voices = speech.get_all_voices() locale = os.environ.get("LANG", "") language_location = locale.split(".", 1)[0].lower() language = language_location.split("_")[0] variant = "" if language_location.find("_") > -1: variant = language_location.split("_")[1] # if the language is es but not es_es default to es_la (latin voice) if language == "es" and language_location != "es_es": language_location = "es_la" best = voices.get(language_location) or voices.get(language) or "default" logging.debug("Best voice for LANG %s seems to be %s", locale, best) return [best, language, variant] def __conf_changed_cb(self, client, connection_id, entry, args): key = entry.get_key() value = client.get_int(key) if key == "/desktop/sugar/speech/pitch": speech.pitch = value if key == "/desktop/sugar/speech/rate": speech.rate = value def save_speech_parameters(self): speech_parameters = {} speech_parameters["voice"] = speech.voice data_path = os.path.join(self._activity.get_activity_root(), "data") data_file_name = os.path.join(data_path, "speech_params.json") f = open(data_file_name, "w") try: json.dump(speech_parameters, f) finally: f.close() def reset_buttons_cb(self): logging.error("reset buttons") self.play_btn.set_icon_name("media-playback-start") self.stop_btn.set_sensitive(False) self.play_btn.handler_block(self.play_toggled_handler) self.play_btn.set_active(False) self.play_btn.handler_unblock(self.play_toggled_handler) self.is_paused = False def play_cb(self, widget): self.stop_btn.set_sensitive(True) if widget.get_active(): self.play_btn.set_icon_name("media-playback-pause") logging.error("Paused %s", self.is_paused) if not self.is_paused: # get the text to speech, if there are a selection, # play selected text, if not, play all abi = self._activity.abiword_canvas selection = abi.get_selection("text/plain") if not selection or selection[0] is None or selection[1] == 0: # nothing selected abi.select_all() text = abi.get_selection("text/plain")[0] abi.moveto_bod() else: text = selection[0] speech.play(text) else: logging.error("Continue play") speech.continue_play() else: self.play_btn.set_icon_name("media-playback-start") self.is_paused = True speech.pause() def stop_cb(self, widget): self.stop_btn.set_sensitive(False) self.play_btn.set_icon_name("media-playback-start") self.play_btn.set_active(False) self.is_paused = False speech.stop()
class WriteBooksActivity(activity.Activity): 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() def create_edition_canvas(self): self._image_canvas = ImageCanvas() self._image_canvas.connect('images-modified', self.__images_modified_cb) self._image_canvas.set_halign(Gtk.Align.CENTER) self._image_canvas.set_valign(Gtk.Align.CENTER) self._image_canvas.set_vexpand(True) self._text_editor = TextEditor() self._text_changed_signal_id = self._text_editor.connect( 'changed', self.__text_changed_cb) self._page_counter_label = Gtk.Label('1 / 1') font_desc = Pango.font_description_from_string('12') self._page_counter_label.modify_font(font_desc) self._page_counter_label.set_halign(Gtk.Align.END) self._page_counter_label.set_valign(Gtk.Align.END) self._page_counter_label.set_margin_right(style.DEFAULT_PADDING) self._page_counter_label.set_margin_top(style.DEFAULT_PADDING) background = Gtk.EventBox() rgba = Gdk.RGBA() rgba.red, rgba.green, rgba.blue, rgba.alpha = 1., 1., 1., 1. background.override_background_color(Gtk.StateFlags.NORMAL, rgba) self._scrolled_window = Gtk.ScrolledWindow() self._scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN) self._scrolled_window.set_size_request( Gdk.Screen.width() - style.GRID_CELL_SIZE * 2, style.GRID_CELL_SIZE * 2) self._scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self._scrolled_window.add(self._text_editor) self._scrolled_window.set_margin_left(style.GRID_CELL_SIZE) self._scrolled_window.set_margin_right(style.GRID_CELL_SIZE) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box.pack_start(self._page_counter_label, False, False, 0) box.pack_start(self._image_canvas, True, True, 0) box.pack_start(self._scrolled_window, False, False, style.DEFAULT_PADDING) background.add(box) background.show_all() background.connect('size_allocate', self.__background_size_allocate_cb) return background def __background_size_allocate_cb(self, widget, allocation): height = allocation.height / 4 * 3 width = height / 3 * 4 logging.debug('size allocate %s x %s', width, height) self._image_canvas.set_size_request(width, height) widget.check_resize() def __view_list_toggled_cb(self, button): if button.get_active(): self._preview_panel.update_model(self._book_model.get_pages()) self._preview_panel.show() self._image_canvas.set_editable(False) self._text_editor.set_editable(False) self._scrolled_window.set_size_request( (Gdk.Screen.width() * 3 / 4) - style.GRID_CELL_SIZE * 2, style.GRID_CELL_SIZE * 2) else: self._preview_panel.hide() self._image_canvas.set_editable(True) self._text_editor.set_editable(True) self._scrolled_window.set_size_request( Gdk.Screen.width() - style.GRID_CELL_SIZE * 2, style.GRID_CELL_SIZE * 2) def write_file(self, file_path): self._book_model.write(file_path) self.metadata['mime_type'] = 'application/x-writebooks-activity' def read_file(self, file_path): self._book_model.read(file_path) self._update_page_buttons() def prepare_edit_toolbar(self): self._edit_toolbar.copy.connect('clicked', self.__copy_clicked_cb) self._edit_toolbar.paste.connect('clicked', self.__paste_clicked_cb) self._edit_toolbar.undo.connect('clicked', self.__undo_clicked_cb) self._edit_toolbar.redo.connect('clicked', self.__redo_clicked_cb) def __copy_clicked_cb(self, button): if self._text_editor.get_buffer().get_has_selection(): self._text_editor.get_buffer().copy_clipboard( Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)) elif self._image_canvas.is_image_active(): # if not text is selected # and a image is selected, copy as pixbuf clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) pxb = self._image_canvas.create_pixbuf_with_active_image() clipboard.set_image(pxb) def __paste_clicked_cb(self, button): self._text_editor.get_buffer().paste_clipboard( Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD), None, True) def __undo_clicked_cb(self, button): self._text_editor.get_buffer().undo() def __redo_clicked_cb(self, button): self._text_editor.get_buffer().redo() def __set_background_clicked_cb(self, button): categories = { _('Indoors'): [os.path.join(SCRATCH_BACKGROUNDS_PATH, 'Indoors')], _('Nature'): [os.path.join(SCRATCH_BACKGROUNDS_PATH, 'Nature')], _('Outdoors'): [os.path.join(SCRATCH_BACKGROUNDS_PATH, 'Outdoors')], _('Sports'): [os.path.join(SCRATCH_BACKGROUNDS_PATH, 'Sports')]} chooser = ImageFileChooser(image_type='backgrounds', title=_('Select a background'), categories=categories, language=self._language, translations=self._translations, parent=self.get_window()) chooser.connect('response', self.__chooser_response_cb, self._change_background) self.set_sensitive(False) chooser.show() def __chooser_response_cb(self, chooser, response_id, operation_function): self.set_sensitive(True) if response_id == Gtk.ResponseType.ACCEPT: logging.error('selected %s', chooser.get_selected_object_id()) file_path = chooser.get_selected_object_id() tempfile_name = \ os.path.join(self.get_activity_root(), 'instance', 'tmp%i' % time.time()) os.link(file_path, tempfile_name) operation_function(tempfile_name) chooser.destroy() del chooser if response_id == Gtk.ResponseType.REJECT: 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.error('ObjectChooser: %r' % chooser.get_selected_object()) jobject = chooser.get_selected_object() if jobject and jobject.file_path: logging.error("imagen seleccionada: %s", jobject.file_path) tempfile_name = \ os.path.join(self.get_activity_root(), 'instance', 'tmp%i' % time.time()) os.link(jobject.file_path, tempfile_name) operation_function(tempfile_name) finally: chooser.destroy() del chooser def _change_background(self, file_name): self._book_model.set_page_background(self._actual_page, file_name) self._update_page_view() def __add_image_clicked_cb(self, button): categories = { _('Animals'): [os.path.join(SCRATCH_COSTUMES_PATH, 'Animals'), os.path.join(TUXPAINT_STAMPS_PATH, 'animals')], _('Fantasy'): [os.path.join(SCRATCH_COSTUMES_PATH, 'Fantasy'), os.path.join(TUXPAINT_STAMPS_PATH, 'cartoon')], _('Letters'): [os.path.join(SCRATCH_COSTUMES_PATH, 'Letters')], _('People'): [os.path.join(SCRATCH_COSTUMES_PATH, 'People'), os.path.join(TUXPAINT_STAMPS_PATH, 'people')], _('Things'): [os.path.join(SCRATCH_COSTUMES_PATH, 'Things'), os.path.join(TUXPAINT_STAMPS_PATH, 'clothes'), os.path.join(TUXPAINT_STAMPS_PATH, 'hobbies'), os.path.join(TUXPAINT_STAMPS_PATH, 'medical'), os.path.join(TUXPAINT_STAMPS_PATH, 'household'), os.path.join(TUXPAINT_STAMPS_PATH, 'food')], _('Transportation'): [ os.path.join(SCRATCH_COSTUMES_PATH, 'Transportation'), os.path.join(TUXPAINT_STAMPS_PATH, 'vehicles')]} chooser = ImageFileChooser(image_type='actors', title=_('Select an image to add'), categories=categories, language=self._language, translations=self._translations, parent=self.get_window()) chooser.connect('response', self.__chooser_response_cb, self._add_image) self.set_sensitive(False) chooser.show() def _add_image(self, file_name): logging.error('Add image %s', file_name) self._book_model.add_image(self._actual_page, file_name) self._update_page_view() def __remove_clicked_cb(self, file_name): if self._image_canvas.is_image_active(): alert = ConfirmationAlert() alert.props.title = _('Do you want remove the selected image?') # alert.props.msg = _('') alert.connect('response', self.__confirm_remove_image_cb) self.add_alert(alert) else: if len(self._book_model.get_pages()) > 1: alert = ConfirmationAlert() alert.props.title = _('Do you want remove the page?') # alert.props.msg = _('') alert.connect('response', self.__confirm_remove_page_cb) self.add_alert(alert) def __confirm_remove_image_cb(self, alert, response_id): # Callback for conf alert self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: self._image_canvas.remove_active_image() def __confirm_remove_page_cb(self, alert, response_id): # Callback for conf alert self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: if self._book_model.remove_page(self._actual_page): if self._actual_page > len(self._book_model.get_pages()): self._actual_page -= 1 self._update_page_buttons() self._preview_panel.update_model(self._book_model.get_pages()) def __images_modified_cb(self, canvas, images_views): self._book_model.update_images(self._actual_page, images_views) def _update_page_buttons(self): cant_pages = len(self._book_model.get_pages()) self._page_counter_label.set_text('%d / %d' % (self._actual_page, cant_pages)) self._prev_page_button.set_sensitive(self._actual_page > 1) self._next_page_button.set_sensitive(self._actual_page < cant_pages) self._update_page_view() def _update_page_view(self): page_model = self._book_model.get_page_model(self._actual_page) self._image_canvas.set_background(page_model.background_path) self._image_canvas.set_images(page_model.images) self._text_editor.disconnect(self._text_changed_signal_id) self._text_editor.set_text(page_model.text) self._text_changed_signal_id = self._text_editor.connect( 'changed', self.__text_changed_cb) def __add_page_clicked_cb(self, button): self._book_model.add_page() self._actual_page = len(self._book_model.get_pages()) self._update_page_buttons() self._preview_panel.update_model(self._book_model.get_pages()) def __duplicate_page_clicked_cb(self, button): actual_page_model = self._book_model.get_page_model(self._actual_page) self._book_model.add_page(actual_page_model) self._actual_page = len(self._book_model.get_pages()) self._update_page_buttons() self._preview_panel.update_model(self._book_model.get_pages()) def __next_page_clicked_cb(self, button): self._actual_page += 1 self._update_page_buttons() self._preview_panel.update_position(1) def __prev_page_clicked_cb(self, button): self._actual_page -= 1 self._update_page_buttons() self._preview_panel.update_position(-1) def __page_activated_cb(self, preview_panel, order): self._actual_page = order self._update_page_buttons() def __page_moved_cb(self, preview_panel, pages_order_array): new_pages = [] for n in pages_order_array: new_pages.append(self._book_model.get_pages()[n]) # actual_page is 1 based and order is 0 based actual_page_order = self._actual_page - 1 new_order_actual_page = pages_order_array.index(actual_page_order) self._actual_page = new_order_actual_page + 1 self._book_model.set_pages(new_pages) self._update_page_buttons() preview_panel.update_model(self._book_model.get_pages()) def __text_changed_cb(self, texteditor): self._book_model.set_page_text(self._actual_page, texteditor.get_text()) def __save_ebook_clicked_cb(self, button): alert = Alert() alert.props.title = _('Book creation') alert.props.msg = _('Do you want to add an image for the cover?') icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.YES, _('Yes'), icon) icon.show() icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.NO, _('No'), icon) icon.show() alert.connect('response', self.__add_cover_response_cb, self._set_cover_and_create_book) self.add_alert(alert) def __add_cover_response_cb(self, alert, response_id, operation_function): if response_id == Gtk.ResponseType.YES: 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.error('ObjectChooser: %r' % chooser.get_selected_object()) jobject = chooser.get_selected_object() if jobject and jobject.file_path: logging.error("imagen seleccionada: %s", jobject.file_path) mime_type = mime.get_for_file(jobject.file_path) extension = mime.get_primary_extension(mime_type) tempfile_name = \ os.path.join( self.get_activity_root(), 'instance', 'tmp%i.%s' % (time.time(), extension)) os.link(jobject.file_path, tempfile_name) operation_function(tempfile_name) finally: chooser.destroy() del chooser elif response_id == Gtk.ResponseType.NO: self._save_epub() self.remove_alert(alert) def _set_cover_and_create_book(self, cover_file_name): self._book_model.cover_path = cover_file_name self._save_epub() def _save_epub(self): epub_file_name = create_ebub_from_book_model( self.metadata['title'], self._book_model) # create a new journal item fileObject = datastore.create() fileObject.metadata['title'] = \ _('"%s" as book') % self.metadata['title'] fileObject.metadata['mime_type'] = 'application/epub+zip' full_text = '' for page in self._book_model.get_pages(): full_text += page.text + '\n' fileObject.metadata['fulltext'] = full_text fileObject.metadata['icon-color'] = self.metadata['icon-color'] fileObject.metadata['keep'] = self.metadata.get('keep', '0') fileObject.metadata['preview'] = self.metadata['preview'] fileObject.file_path = epub_file_name # store the journal item datastore.write(fileObject, transfer_ownership=True) book_object_id = fileObject.object_id fileObject.destroy() del fileObject shutil.rmtree(os.path.dirname(epub_file_name)) finish_alert = Alert() finish_alert.props.title = _('Book created') finish_alert.props.msg = _('You can read the book in your Journal') open_icon = Icon(icon_name='zoom-activity') finish_alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'), open_icon) open_icon.show() ok_icon = Icon(icon_name='dialog-ok') finish_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(finish_alert) finish_alert.connect('response', self.__book_saved_alert_response_cb, book_object_id) finish_alert.show() def __book_saved_alert_response_cb(self, alert, response_id, book_object_id): if response_id is Gtk.ResponseType.APPLY: activity.show_object_in_journal(book_object_id) self.remove_alert(alert)
class Record(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) if Gst.version() == (1, 0, 10, 0): return self._incompatible() # for fullscreen feature, use local rather than toolkit self.props.enable_fullscreen_mode = False self._state = None Instance(self) # the main classes self.model = Model(self) self.ui_init() # CSCL self.connect("shared", self._shared_cb) if self.get_shared_activity(): # have you joined or shared this activity yourself? if self.get_shared(): self._joined_cb(self) else: self.connect("joined", self._joined_cb) # Changing to the first toolbar kicks off the rest of the setup if self.model.get_cameras(): self.model.change_mode(constants.MODE_PHOTO) else: self.model.change_mode(constants.MODE_AUDIO) # Start live video pipeline when the video window becomes visible def on_defer_cb(): self.model.set_visible(True) self.connect("notify::active", self.__active_cb) return False def on_event_cb(widget, event): if event.state == Gdk.VisibilityState.UNOBSCURED: GLib.timeout_add(50, on_defer_cb) self._media_view._video.disconnect_by_func(on_event_cb) self._media_view._video.add_events( Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self._media_view._video.connect('visibility-notify-event', on_event_cb) def _incompatible(self): ''' Display abbreviated activity user interface with alert ''' toolbox = ToolbarBox() stop = StopButton(self) toolbox.toolbar.add(stop) self.set_toolbar_box(toolbox) title = _('Activity not compatible with this system.') msg = _('Please downgrade activity and try again.') alert = Alert(title=title, msg=msg) alert.add_button(0, 'Stop', Icon(icon_name='activity-stop')) self.add_alert(alert) label = Gtk.Label(_('Uh oh, GStreamer is too old.')) self.set_canvas(label) alert.connect('response', self.__incompatible_response_cb) stop.connect('clicked', self.__incompatible_stop_clicked_cb, alert) self.show_all() def __incompatible_stop_clicked_cb(self, button, alert): self.remove_alert(alert) def __incompatible_response_cb(self, alert, response): self.remove_alert(alert) self.close() def read_file(self, path): if hasattr(self, 'model'): self.model.read_file(path) def write_file(self, path): if hasattr(self, 'model'): self.model.write_file(path) def close(self, **kwargs): if hasattr(self, 'model'): self.model.close() activity.Activity.close(self, **kwargs) def __active_cb(self, widget, pspec): self.model.set_visible(self.props.active) def _shared_cb(self, activity): self.model.collab.set_activity_shared() def _joined_cb(self, activity): self.model.collab.joined() def ui_init(self): self._fullscreen = False self._showing_info = False # FIXME: if _thumb_tray becomes some kind of button group, we wouldn't # have to track which recd is active self._active_recd = None self.connect('key-press-event', self._key_pressed) self._active_toolbar_idx = 0 toolbar_box = ToolbarBox() self._activity_toolbar_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(self._activity_toolbar_button, 0) self.set_toolbar_box(toolbar_box) self._toolbar = self.get_toolbar_box().toolbar tool_group = None if self.model.get_cameras(): self._photo_button = RadioToolButton() self._photo_button.props.group = tool_group tool_group = self._photo_button self._photo_button.props.icon_name = 'camera-external' self._photo_button.props.label = _('Photo') self._photo_button.props.accelerator = '<ctrl>1' self._photo_button.props.tooltip = _( 'Picture camera mode\n\n' 'When the record button is pressed,\n' 'take one picture from the camera.') self._photo_button.mode = constants.MODE_PHOTO self._photo_button.connect('clicked', self._mode_button_clicked) self._toolbar.insert(self._photo_button, -1) self._video_button = RadioToolButton() self._video_button.props.group = tool_group self._video_button.props.icon_name = 'media-video' self._video_button.props.accelerator = '<ctrl>2' self._video_button.props.label = _('Video') self._video_button.props.tooltip = _( 'Video camera mode\n\n' 'When the record button is pressed,\n' 'take photographs many times a second,\n' 'and record sound using the microphone,\n' 'until the button is pressed again.') self._video_button.mode = constants.MODE_VIDEO self._video_button.connect('clicked', self._mode_button_clicked) self._toolbar.insert(self._video_button, -1) else: self._photo_button = None self._video_button = None self._audio_button = RadioToolButton() self._audio_button.props.group = tool_group self._audio_button.props.icon_name = 'media-audio' self._audio_button.props.accelerator = '<ctrl>3' self._audio_button.props.label = _('Audio') self._audio_button.props.tooltip = _( 'Audio recording mode\n\n' 'When the record button is pressed,\n' 'take one photograph,\n' 'and record sound using the microphone,\n' 'until the button is pressed again.') self._audio_button.mode = constants.MODE_AUDIO self._audio_button.connect('clicked', self._mode_button_clicked) self._toolbar.insert(self._audio_button, -1) self._toolbar.insert(Gtk.SeparatorToolItem(), -1) self._mirror_btn = ToggleToolButton('mirror-horizontal') self._mirror_btn.set_tooltip(_( 'Mirror view\n\n' 'Swap left for right, as if looking at a mirror.\n' 'Does not affect recording.')) self._mirror_btn.props.accelerator = '<ctrl>m' self._mirror_btn.show() self._mirror_btn.connect('toggled', self.__mirror_toggled_cb) self._toolbar.insert(self._mirror_btn, -1) self._toolbar_controls = RecordControl(self._toolbar) if self.model.get_cameras() and len(self.model.get_cameras()) > 1: switch_camera_btn = ToolButton('switch-camera') switch_camera_btn.set_tooltip(_('Switch camera')) switch_camera_btn.show() switch_camera_btn.connect('clicked', self.__switch_camera_click_cb) self._toolbar.insert(switch_camera_btn, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self._toolbar.insert(separator, -1) self._toolbar.insert(StopButton(self), -1) self.get_toolbar_box().show_all() self._media_view = MediaView() self._media_view.connect('media-clicked', self._media_view_media_clicked) self._media_view.connect('pip-clicked', self._media_view_pip_clicked) self._media_view.connect('info-clicked', self._media_view_info_clicked) self._media_view.connect('fullscreen-clicked', self._media_view_fullscreen_clicked) self._media_view.connect('tags-changed', self._media_view_tags_changed) self._media_view.show() self._controls_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) trim_height_shutter_button = 7 self._controls_hbox.set_size_request(-1, style.GRID_CELL_SIZE + trim_height_shutter_button) self._shutter_button = ShutterButton() self._shutter_button.connect("clicked", self._shutter_clicked) self._shutter_button.modify_bg(Gtk.StateType.NORMAL, COLOR_BLACK) self._controls_hbox.pack_start(self._shutter_button, True, False, 0) self._countdown_image = CountdownImage() self._controls_hbox.pack_start(self._countdown_image, True, False, 0) self._play_button = PlayButton() self._play_button.connect('clicked', self._play_pause_clicked) self._controls_hbox.pack_start(self._play_button, False, True, 0) self._playback_scale = PlaybackScale(self.model) self._controls_hbox.pack_start(self._playback_scale, True, True, 0) self._progress = ProgressInfo() self._controls_hbox.pack_start(self._progress, True, True, 0) self._title_label = Gtk.Label() self._title_label.set_markup("<b><span foreground='white'>" + _('Title:') + '</span></b>') self._controls_hbox.pack_start(self._title_label, False, True, 0) self._title_entry = Gtk.Entry() self._title_entry.modify_bg(Gtk.StateType.INSENSITIVE, COLOR_BLACK) self._title_entry.connect('changed', self._title_changed) self._controls_hbox.pack_start(self._title_entry, expand=True, fill=True, padding=10) self._controls_hbox.show() height_tray = 150 # height of tray self._thumb_tray = HTray(hexpand=True, height_request=height_tray) self._thumb_tray.show() height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2 - \ height_tray - trim_height_shutter_button self._media_view.set_size_request(-1, height) self._grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self._media_view.props.hexpand = True self._media_view.props.vexpand = True for row in [self._media_view, self._controls_hbox, self._thumb_tray]: self._grid.add(row) self._grid.modify_bg(Gtk.StateType.NORMAL, COLOR_BLACK) self._grid.show() self.set_canvas(self._grid) def set_title_visible(self, visible): self._grid.remove(self._controls_hbox) if visible: self._grid.attach_next_to(self._controls_hbox, self._media_view, Gtk.PositionType.TOP, 1, 1) else: self._grid.attach_next_to(self._controls_hbox, self._media_view, Gtk.PositionType.BOTTOM, 1, 1) def __switch_camera_click_cb(self, btn): self.model.switch_camera() def __mirror_toggled_cb(self, button): self.model.set_mirror(button.props.active) def serialize(self): data = {} data['timer'] = self._toolbar_controls.get_timer_idx() data['duration'] = self._toolbar_controls.get_duration_idx() data['quality'] = self._toolbar_controls.get_quality() return data def deserialize(self, data): self._toolbar_controls.set_timer_idx(data.get('timer', 0)) self._toolbar_controls.set_duration_idx(data.get('duration', 0)) self._toolbar_controls.set_quality(data.get('quality', 0)) def _key_pressed(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, only escape key is taken if self._title_entry.is_focus(): if key == Gdk.KEY_Escape: self.model.set_state(constants.STATE_READY) return False # while info tags are focused, only escape key is taken if self._media_view.info_view.textview.is_focus(): if key == Gdk.KEY_Escape: self.model.set_state(constants.STATE_READY) return False if ctrl and key == Gdk.KEY_f: self._toggle_fullscreen() return True if ctrl and key == Gdk.KEY_s: self.model.glive.stop() return True if ctrl and key == Gdk.KEY_p: self.model.glive.play() return True if (ctrl and key == Gdk.KEY_space) or \ (ctrl and key == Gdk.KEY_r) or \ key == Gdk.KEY_KP_Page_Up: # game key O if self._shutter_button.props.visible: if self._shutter_button.props.sensitive: self._shutter_button.clicked() else: # return to live mode self.model.set_state(constants.STATE_READY) return True if key == Gdk.KEY_space and self._active_recd: if self._active_recd.type in (constants.TYPE_VIDEO, constants.TYPE_AUDIO): self.model.play_pause() return True # if viewing media, return to live mode if key == Gdk.KEY_Escape and self._active_recd: self.model.set_state(constants.STATE_READY) return True if self.model.ui_frozen(): return True if ctrl and key == Gdk.KEY_c: self._copy_to_clipboard(self._active_recd) return True if key == Gdk.KEY_i and self._active_recd: self._toggle_info() return True if key == Gdk.KEY_Escape and self._fullscreen: self._toggle_fullscreen() return True return False def _play_pause_clicked(self, widget): self.model.play_pause() def set_mode(self, mode): self._toolbar_controls.set_mode(mode) # can be called from GStreamer thread, so must not do any GTK+ stuff def set_glive_sink(self, sink): return self._media_view.set_video_sink(sink) # can be called from GStreamer thread, so must not do any GTK+ stuff def set_gplay_sink(self, sink): return self._media_view.set_video2_sink(sink) def get_selected_quality(self): return self._toolbar_controls.get_quality() def get_selected_timer(self): return self._toolbar_controls.get_timer() def get_selected_duration(self): return self._toolbar_controls.get_duration() * 60 # convert to secs def set_progress(self, value, text): self._progress.set_progress(value) self._progress.set_text(text) def set_countdown(self, value): if value == 0: self._shutter_button.show() self._countdown_image.hide() return self._shutter_button.hide() self._countdown_image.show() self._countdown_image.set_value(value) def _title_changed(self, widget): self._active_recd.setTitle(self._title_entry.get_text()) def _media_view_media_clicked(self, widget): if self._play_button.props.visible and \ self._play_button.props.sensitive: self._play_button.clicked() def _media_view_pip_clicked(self, widget): # clicking on the PIP always returns to live mode self.model.set_state(constants.STATE_READY) def _media_view_info_clicked(self, widget): self._toggle_info() def _toggle_info(self): recd = self._active_recd if not recd: return if self._showing_info: self._show_recd(recd, play=False) return self._showing_info = True still_modes = (constants.MODE_PHOTO, constants.MODE_AUDIO) if self.model.get_mode() in still_modes: func = self._media_view.show_info_photo else: func = self._media_view.show_info_video self._play_button.hide() self._progress.hide() self._playback_scale.hide() self._title_entry.set_text(recd.title) self._title_entry.show() self._title_label.show() self.set_title_visible(True) func(recd.recorderName, recd.colorStroke, recd.colorFill, utils.getDateString(recd.time), recd.tags) def _media_view_fullscreen_clicked(self, widget): # logger.debug('_media_view_fullscreen_clicked') self._toggle_fullscreen() def _media_view_tags_changed(self, widget, tbuffer): text = tbuffer.get_text(tbuffer.get_start_iter(), tbuffer.get_end_iter(), True) self._active_recd.setTags(text) def _toggle_fullscreen(self): # logger.debug('_toggle_fullscreen') self._fullscreen = not self._fullscreen if not self._active_recd: self.model.glive.stop() if self._fullscreen: self.get_toolbar_box().hide() self._thumb_tray.hide() if self._active_recd: self._controls_hbox.hide() else: self.get_toolbar_box().show() self._thumb_tray.show() self._controls_hbox.show() self._media_view.set_fullscreen(self._fullscreen) if self._active_recd: return if self.model.get_state() == constants.STATE_RECORDING: return # hack, reason unknown # problem: call to self.mode.glive.play() does not show live view # solution: defer until after VideoBox resize is complete self._timer_hid = None def on_timer_cb(): self.model.glive.play() self._timer_hid = None return False self._timer_hid = GLib.timeout_add(1000, on_timer_cb) def on_defer_cb(): self.model.glive.play() if self._timer_hid: GLib.source_remove(self._timer_hid) self._timer_hid = None return False def on_event_cb(widget, event): if event.state == Gdk.VisibilityState.UNOBSCURED: GLib.timeout_add(30, on_defer_cb) self._media_view._video.disconnect_by_func(on_event_cb) self._media_view._video.add_events( Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self._media_view._video.connect('visibility-notify-event', on_event_cb) # FIXME: fullscreen toggle during video recording gives black # window, TODO: do the same as above for the video recording # pipeline when it is active def _mode_button_clicked(self, button): self.model.change_mode(button.mode) def _shutter_clicked(self, arg): self.model.do_shutter() def set_shutter_sensitive(self, value): self._shutter_button.set_sensitive(value) def set_state(self, state): radio_state = (state == constants.STATE_READY) for item in (self._photo_button, self._audio_button, self._video_button): if item: item.set_sensitive(radio_state) self._showing_info = False if state == constants.STATE_READY: if self._state == constants.STATE_PROCESSING: self.unbusy() self._active_recd = None self._mirror_btn.props.sensitive = True self._title_entry.hide() self._title_label.hide() self.set_title_visible(False) self._play_button.hide() self._playback_scale.hide() self._progress.hide() self._controls_hbox.set_child_packing(self._shutter_button, expand=True, fill=False, padding=0, pack_type=Gtk.PackType.START) self._shutter_button.set_normal() self._shutter_button.set_sensitive(True) self._shutter_button.show() self._media_view.show_live() elif state == constants.STATE_RECORDING: self._mirror_btn.props.sensitive = False self._shutter_button.set_recording() self._controls_hbox.set_child_packing(self._shutter_button, expand=False, fill=False, padding=0, pack_type=Gtk.PackType.START) self._progress.show() elif state == constants.STATE_PROCESSING: self.busy() self._shutter_button.hide() self._progress.show() elif state == constants.STATE_DOWNLOADING: self._shutter_button.hide() self._progress.show() self._state = state def set_paused(self, value): if value: self._play_button.set_play() else: self._play_button.set_pause() def _thumbnail_clicked(self, button, recd): if self.model.ui_frozen(): return self.model.abort_countdown() self.model.glive.stop() self._mirror_btn.props.sensitive = False self._active_recd = recd self._show_recd(recd) def add_thumbnail(self, recd): button = RecdButton(recd) clicked_handler = button.connect("clicked", self._thumbnail_clicked, recd) remove_handler = button.connect("remove-requested", self._remove_recd) clipboard_handler = button.connect("copy-clipboard-requested", self._thumbnail_copy_clipboard) button.handler_ids = (clicked_handler, remove_handler, clipboard_handler) button.show() self._thumb_tray.add_item(button) self._thumb_tray.scroll_to_item(button) # FIXME: possible toolkit bug; scroll_to_item is ineffective, # only noticed when the tray is full def _copy_to_clipboard(self, recd): if recd is None: return if not recd.isClipboardCopyable(): return clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clipboard.set_image(recd.getCopyClipboardPixbuf()) def _thumbnail_copy_clipboard(self, recdbutton): self._copy_to_clipboard(recdbutton.get_recd()) def _remove_recd(self, recdbutton): recd = recdbutton.get_recd() self.model.delete_recd(recd) if self._active_recd == recd: self.model.set_state(constants.STATE_READY) self._remove_thumbnail(recdbutton) def _remove_thumbnail(self, recdbutton): for handler in recdbutton.handler_ids: recdbutton.disconnect(handler) self._thumb_tray.remove_item(recdbutton) recdbutton.cleanup() def show_still(self, pixbuf): self._media_view.show_still(pixbuf) def _show_photo(self, recd): path = self._get_photo_path(recd) self._media_view.show_photo(path) self._title_entry.set_text(recd.title) self._title_entry.show() self._title_label.show() self.set_title_visible(True) self._shutter_button.hide() self._progress.hide() def _show_audio(self, recd, play): self._progress.hide() self._shutter_button.hide() self._title_entry.hide() self._title_label.hide() self.set_title_visible(False) self._play_button.show() self._playback_scale.show() path = recd.getAudioImageFilepath() self._media_view.show_photo(path) if play: self.model.play_audio(recd) def _show_video(self, recd, play): self._progress.hide() self._shutter_button.hide() self._title_entry.hide() self._title_label.hide() self.set_title_visible(False) self._play_button.show() self._playback_scale.show() self._media_view.show_video() if play: self.model.play_video(recd) def set_playback_scale(self, value): self._playback_scale.set_value(value) def _get_photo_path(self, recd): # FIXME should live (partially) in recd? # downloading = self.ca.requestMeshDownload(recd) # self.MESHING = downloading if True: # not downloading: # self.progressWindow.updateProgress(0, "") return recd.getMediaFilepath() # maybe it is not downloaded from the mesh yet... # but we can show the low res thumb in the interim return recd.getThumbFilepath() def _show_recd(self, recd, play=True): self._showing_info = False if recd.buddy and not recd.downloadedFromBuddy: self.model.request_download(recd) elif recd.type == constants.TYPE_PHOTO: self._show_photo(recd) elif recd.type == constants.TYPE_AUDIO: self._show_audio(recd, play) elif recd.type == constants.TYPE_VIDEO: self._show_video(recd, play) def remote_recd_available(self, recd): self.model.set_state(constants.STATE_INVISIBLE) if recd == self._active_recd: self._show_recd(recd) def update_download_progress(self, recd): if recd != self._active_recd: return if not recd.meshDownloading: msg = _('Download failed.') elif recd.meshDownloadingProgress: msg = _('Downloading...') else: msg = _('Requesting...') self.set_progress(recd.meshDownlodingPercent, msg)
def __init__(self, abiword_canvas): GObject.GObject.__init__(self) self.font_name_combo = FontComboBox() self.font_name_combo.set_font_name('Sans') self._fonts_changed_id = self.font_name_combo.connect( 'changed', self._font_changed_cb, abiword_canvas) self._abi_handler = abiword_canvas.connect('font-family', self._font_family_cb) self.insert(ToolComboBox(self.font_name_combo), -1) self.font_size = FontSize() self._abi_handler = abiword_canvas.connect('font-size', self._font_size_cb) self._changed_id = self.font_size.connect( 'changed', self._font_size_changed_cb, abiword_canvas) self.insert(self.font_size, -1) bold = ToggleToolButton('format-text-bold') bold.set_tooltip(_('Bold')) bold.props.accelerator = '<Ctrl>B' bold_id = bold.connect('clicked', lambda sender: abiword_canvas.toggle_bold()) abiword_canvas.connect('bold', lambda abi, b: self._setToggleButtonState(bold, b, bold_id)) self.insert(bold, -1) italic = ToggleToolButton('format-text-italic') italic.set_tooltip(_('Italic')) italic.props.accelerator = '<Ctrl>I' italic_id = italic.connect('clicked', lambda sender: abiword_canvas.toggle_italic()) abiword_canvas.connect('italic', lambda abi, b: self._setToggleButtonState(italic, b, italic_id)) self.insert(italic, -1) underline = ToggleToolButton('format-text-underline') underline.set_tooltip(_('Underline')) underline.props.accelerator = '<Ctrl>U' underline_id = underline.connect('clicked', lambda sender: abiword_canvas.toggle_underline()) abiword_canvas.connect('underline', lambda abi, b: self._setToggleButtonState(underline, b, underline_id)) self.insert(underline, -1) color = ColorToolButton() color.connect('notify::color', self._text_color_cb, abiword_canvas) tool_item = Gtk.ToolItem() tool_item.add(color) self.insert(tool_item, -1) abiword_canvas.connect( 'color', lambda abi, r, g, b: color.set_color(Gdk.Color(r * 256, g * 256, b * 256))) # MAGIC NUMBER WARNING: Secondary toolbars are not a standard height? self.set_size_request(-1, style.GRID_CELL_SIZE) def append_align(icon_name, tooltip, do_abi_cb, style_name, button, menu_box): menu_item = AbiMenuItem(abiword_canvas, style_name, do_abi_cb, icon_name, tooltip, button) menu_box.append_item(menu_item) menu_item.show() self._aligment_btn = ToolButton(icon_name='format-justify-left') self._aligment_btn.props.tooltip = _('Choose alignment') self._aligment_btn.props.hide_tooltip_on_click = False self._aligment_btn.palette_invoker.props.toggle_palette = True menu_box = PaletteMenuBox() self._aligment_btn.props.palette.set_content(menu_box) menu_box.show() append_align('format-justify-left', _('Left justify'), abiword_canvas.align_left, 'left-align', self._aligment_btn, menu_box) append_align('format-justify-center', _('Center justify'), abiword_canvas.align_center, 'center-align', self._aligment_btn, menu_box) append_align('format-justify-right', _('Right justify'), abiword_canvas.align_right, 'right-align', self._aligment_btn, menu_box) append_align('format-justify-fill', _('Fill justify'), abiword_canvas.align_justify, 'justify-align', self._aligment_btn, menu_box) self.insert(self._aligment_btn, -1) self.show_all()
class CardEditor(Gtk.EventBox): __gsignals__ = { 'has-text': (GObject.SignalFlags.RUN_FIRST, None, [GObject.TYPE_PYOBJECT]), 'has-picture': (GObject.SignalFlags.RUN_FIRST, None, [GObject.TYPE_PYOBJECT]), 'has-sound': (GObject.SignalFlags.RUN_FIRST, None, [GObject.TYPE_PYOBJECT]), 'change-font': (GObject.SignalFlags.RUN_FIRST, None, [GObject.TYPE_PYOBJECT]), } def __init__(self, game, editor_index): Gtk.EventBox.__init__(self) self._game = game self.snd = None self.editor_index = editor_index self.temp_folder = None box = Gtk.Grid() box.set_column_spacing(style.DEFAULT_SPACING) box.set_row_spacing(style.DEFAULT_SPACING) box.props.margin = style.DEFAULT_SPACING self.card = Card( -1, {'front_text': {'card_text': '', 'text_color': style.Color('#ffffff')}}, None, PAIR_SIZE, '#c0c0c0') self.card.flip() card_align = Gtk.Alignment.new(.5, .5, 0, 0) card_align.add(self.card) box.attach(card_align, 0, 0, 1, 1) self.textentry = Gtk.Entry() self.textentry.connect('changed', self.update_text) self.textentry.set_valign(Gtk.Align.START) box.attach(self.textentry, 0, 1, 1, 1) toolbar = Gtk.VBox() toolbar.set_valign(Gtk.Align.CENTER) browsepicture = ToolButton(icon_name='import_picture', tooltip=_('Insert picture')) toolbar.add(browsepicture) browsesound = ToolButton(icon_name='import_sound', tooltip=_('Insert sound')) toolbar.add(browsesound) browsepicture.connect('clicked', self._load_image) browsesound.connect('clicked', self._load_audio) self.usespeak = ToggleToolButton(icon_name='speak') self.usespeak.set_palette(SpeakPalette(self)) toolbar.add(self.usespeak) self.usespeak.connect('toggled', self._usespeak_cb) self.fontbutton = FontButton() toolbar.add(self.fontbutton) self.id_font_changed = self.fontbutton.connect( 'changed', self.__font_changed_cb) box.attach(toolbar, 1, 0, 1, 2) self.add(box) def __font_changed_cb(self, widget): font = widget.get_font_name() if font: self.card.change_font(font) self.emit('change-font', font) def set_font_name(self, font_name): self.fontbutton.handler_block(self.id_font_changed) self.fontbutton.set_font_name(font_name) self.fontbutton.handler_unblock(self.id_font_changed) def update_text(self, entry): self.card.change_text(entry.get_text()) if len(entry.get_text()) == 0: self.emit('has-text', False) else: self.emit('has-text', True) def get_text(self): return self.textentry.get_text() def set_text(self, newtext): if newtext is None: newtext = '' self.textentry.set_text(newtext) def get_speak(self): if self.usespeak is None: return None if self.usespeak.props.active: return self.usespeak.palette.face.status.voice.language def set_speak(self, value): if self.usespeak is None: return if value is None: self.usespeak.props.active = False else: try: self.usespeak.handler_block_by_func(self._usespeak_cb) self.usespeak.props.active = True finally: self.usespeak.handler_unblock_by_func(self._usespeak_cb) self.usespeak.palette.voices.resume(value) def get_image_path(self): return self.card.get_image_path() def set_image_path(self, image_path): self.card.set_image_path(image_path) self.emit('has-picture', True) def _load_image(self, widget): def load(jobject): origin_path = jobject.file_path self._game.model.mark_modified() self._game.model.create_temp_directories() destination_path = join(self._game.model.data['pathimg'], basename(origin_path)) shutil.copy(origin_path, destination_path) self.set_speak(None) self.card.set_image_path(destination_path) logging.debug('Picture Loaded: %s', destination_path) self.emit('has-picture', True) chooser.pick(parent=self.get_toplevel(), what=chooser.IMAGE, cb=load) def _load_audio(self, widget): def load(jobject): origin_path = jobject.file_path self.set_speak(None) self._game.model.mark_modified() self._game.model.create_temp_directories() destination_path = join(self._game.model.data['pathsnd'], basename(origin_path)) shutil.copy(origin_path, destination_path) self.set_snd(destination_path) logging.debug('Audio Loaded: %s', destination_path) # add a icon too sound_icon_path = join(activity.get_bundle_path(), 'icons/sound.svg') destination_path = join(self._game.model.data['pathimg'], 'sound.svg') shutil.copy(sound_icon_path, destination_path) self.card.set_image_path(destination_path) self.emit('has-sound', True) chooser.pick(parent=self.get_toplevel(), what=chooser.AUDIO, cb=load) def _usespeak_cb(self, button): self.card.change_speak(button.props.active) if not button.props.active: self.usespeak.palette.face.shut_up() return self.snd = None self.emit('has-sound', False) self.emit('has-picture', False) button.palette.face.say(self.get_text()) def set_snd(self, snd): self.snd = snd def get_snd(self): return self.snd def get_font_name(self): return self.fontbutton.get_font_name() def clean(self): self.textentry.set_text('') self.card.set_image_path(None) self.snd = None self.emit('has-text', False) self.emit('has-picture', False) self.emit('has-sound', False) if self.usespeak is not None and self.usespeak.palette is not None: self.usespeak.props.active = False self.usespeak.palette.face.shut_up()
class ReadToolbar(Gtk.Toolbar): __gtype_name__ = 'ReadToolbar' def __init__(self): Gtk.Toolbar.__init__(self) self.back = ToolButton('go-previous') self.back.set_tooltip(_('Back')) self.back.props.sensitive = False palette = self.back.get_palette() self.prev_page = MenuItem(text_label= _("Previous page")) palette.menu.append(self.prev_page) self.prev_page.show_all() self.prev_bookmark = MenuItem(text_label= _("Previous bookmark")) palette.menu.append(self.prev_bookmark) self.prev_bookmark.show_all() self.back.connect('clicked', self.go_back_cb) self.prev_page.connect('activate', self.go_back_cb) self.prev_bookmark.connect('activate', self.prev_bookmark_activate_cb) self.insert(self.back, -1) self.back.show() self.forward = ToolButton('go-next') self.forward.set_tooltip(_('Forward')) self.forward.props.sensitive = False palette = self.forward.get_palette() self.next_page = MenuItem(text_label= _("Next page")) palette.menu.append(self.next_page) self.next_page.show_all() self.next_bookmark = MenuItem(text_label= _("Next bookmark")) palette.menu.append(self.next_bookmark) self.next_bookmark.show_all() self.forward.connect('clicked', self.go_forward_cb) self.next_page.connect('activate', self.go_forward_cb) self.next_bookmark.connect('activate', self.next_bookmark_activate_cb) self.insert(self.forward, -1) self.forward.show() num_page_item = Gtk.ToolItem() self.num_page_entry = Gtk.Entry() self.num_page_entry.set_text('0') self.num_page_entry.set_alignment(1) self.num_page_entry.connect('insert-text', self.num_page_entry_insert_text_cb) self.num_page_entry.connect('activate', self.num_page_entry_activate_cb) self.num_page_entry.set_width_chars(4) num_page_item.add(self.num_page_entry) self.num_page_entry.show() self.insert(num_page_item, -1) num_page_item.show() total_page_item = Gtk.ToolItem() self.total_page_label = Gtk.Label() self.total_page_label.set_markup("<span size='14000' foreground='black'>") self.total_page_label.set_text(' / 0') total_page_item.add(self.total_page_label) self.total_page_label.show() self.insert(total_page_item, -1) total_page_item.show() spacer = Gtk.SeparatorToolItem() self.insert(spacer, -1) spacer.show() bookmarkitem = Gtk.ToolItem() self.bookmarker = ToggleToolButton('emblem-favorite') self.bookmarker.set_tooltip(_('Toggle Bookmark')) self.bookmarker_handler_id = self.bookmarker.connect('clicked', self.bookmarker_clicked_cb) bookmarkitem.add(self.bookmarker) self.insert(bookmarkitem, -1) bookmarkitem.show_all() underline_item = Gtk.ToolItem() self.underline = ToggleToolButton('format-text-underline') self.underline.set_tooltip(_('Underline')) self.underline.props.sensitive = False self.underline_id = self.underline.connect('clicked', self.underline_cb) underline_item.add(self.underline) self.insert(underline_item, -1) underline_item.show_all() def num_page_entry_insert_text_cb(self, entry, text, length, position): if not re.match('[0-9]', text): entry.emit_stop_by_name('insert-text') return True return False def num_page_entry_activate_cb(self, entry): if entry.props.text: page = int(entry.props.text) - 1 else: page = 0 if page >= self.total_pages: page = self.total_pages - 1 elif page < 0: page = 0 self.current_page = page self.activity.set_current_page(page) self.activity.show_page(page) entry.props.text = str(page + 1) self.update_nav_buttons() def go_back_cb(self, button): self.activity.page_previous() def go_forward_cb(self, button): self.activity.page_next() def update_nav_buttons(self): current_page = self.current_page self.back.props.sensitive = current_page > 0 self.forward.props.sensitive = \ current_page < self.total_pages - 1 self.num_page_entry.props.text = str(current_page + 1) self.total_page_label.props.label = \ ' / ' + str(self.total_pages) def set_total_pages(self, pages): self.total_pages = pages def set_current_page(self, page): self.current_page = page self.update_nav_buttons() def set_activity(self, activity): self.activity = activity def prev_bookmark_activate_cb(self, menuitem): self.activity.prev_bookmark() def next_bookmark_activate_cb(self, menuitem): self.activity.next_bookmark() def bookmarker_clicked_cb(self, button): self.activity.bookmarker_clicked(button) def underline_cb(self, button): self.activity.underline_clicked(button) def setToggleButtonState(self,button,b,id): button.handler_block(id) button.set_active(b) button.handler_unblock(id) def update_underline_button(self, state): self.setToggleButtonState(self.underline, state, self.underline_id) def update_bookmark_button(self, state): self.setToggleButtonState(self.bookmarker, state, self.bookmarker_handler_id)
def make_toolbar(self): def make_separator(toolbar, expand=True): separator = Gtk.SeparatorToolItem() separator.props.draw = not expand separator.set_expand(expand) toolbar.insert(separator, -1) toolbar_box = ToolbarBox() toolbar = toolbar_box.toolbar activity_button = ToolButton() activity_button.set_icon_widget(ActivityIcon(None)) toolbar.insert(activity_button, -1) toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_file = Gtk.Toolbar() boton_toolbar_file = ToolbarButton(page=toolbar_file, icon_name='txt') toolbar.add(boton_toolbar_file) toolbar_edit = EditToolbar() button_toolbar_edit = ToolbarButton(page=toolbar_edit, icon_name='toolbar-edit') toolbar.insert(button_toolbar_edit, -1) toolbar_view = Gtk.Toolbar() boton_toolbar_view = ToolbarButton(page=toolbar_view, icon_name='toolbar-view') toolbar.insert(boton_toolbar_view, -1) self.button_undo = toolbar_edit.undo self.button_undo.props.accelerator = '<Ctrl>Z' self.button_undo.set_sensitive(False) toolbar_edit.undo.connect('clicked', self.undo) self.button_redo = toolbar_edit.redo self.button_redo.props.accelerator = '<Ctrl><Mayus>Z' self.button_redo.set_sensitive(False) self.button_redo.connect('clicked', self.redo) self.entry_search = IconEntry() item_entry = Gtk.ToolItem() self.entry_search.set_size_request(250, -1) self.entry_search.set_placeholder_text('Search...') self.entry_search.set_icon_from_name(Gtk.EntryIconPosition.SECONDARY, 'search') self.entry_search.connect('changed', self.search_text) self.entry_search.connect('activate', self.search_text, True) item_entry.add(self.entry_search) toolbar_edit.insert(item_entry, -1) self.entry_replace = IconEntry() item_entry = Gtk.ToolItem() self.entry_replace.set_size_request(250, -1) self.entry_replace.set_placeholder_text('Replace...') self.entry_replace.connect('activate', self.replace_text) item_entry.add(self.entry_replace) toolbar_edit.insert(item_entry, -1) button_new = ToolButton('new-file') button_new.props.accelerator = '<Ctrl>N' button_new.connect('clicked', lambda w: self.new_page()) button_new.set_tooltip(_('New file')) toolbar_file.insert(button_new, -1) button_open = ToolButton('fileopen') button_open.props.accelerator = '<Ctrl>O' button_open.set_tooltip(_('Open file from file system')) button_open.connect('clicked', self.file_chooser_open) toolbar_file.insert(button_open, -1) self.button_save = ToolButton('filesave') self.button_save.props.accelerator = '<Ctrl>S' self.button_save.set_tooltip(_('Save file to the file system')) self.button_save.connect('clicked', self.file_chooser_save) toolbar_file.insert(self.button_save, -1) button_save_as = ToolButton('save-as') button_save_as.props.accelerator = '<Ctrl><Mayus>S' button_save_as.set_tooltip(_('Save as file to the file system')) button_save_as.connect('clicked', self.file_chooser_save, True) toolbar_file.insert(button_save_as, -1) make_separator(toolbar_file, False) button_print = ToolButton('printer') button_print.props.accelerator = '<Ctrl>I' button_print.set_tooltip(_('Print file')) button_print.connect('clicked', self.print_file) toolbar_file.insert(button_print, -1) make_separator(toolbar_edit, False) button_clock = ToolButton('clock') button_clock.props.accelerator = '<Ctrl>T' button_clock.set_tooltip(_('Insert date and time')) button_clock.connect('clicked', self.insert_date_and_time) toolbar_edit.insert(button_clock, -1) button_wrap_none = Gtk.RadioToolButton() button_wrap_none.set_icon_name('wrap-none') button_wrap_none.connect("toggled", self.wrap_mode_changed, 'none') toolbar_view.insert(button_wrap_none, -1) button_wrap_char = Gtk.RadioToolButton.new_from_widget( button_wrap_none) button_wrap_char.set_icon_name('format-justify-fill') button_wrap_char.connect("toggled", self.wrap_mode_changed, 'char') toolbar_view.insert(button_wrap_char, -1) button_wrap_word = Gtk.RadioToolButton.new_from_widget( button_wrap_none) button_wrap_word.set_icon_name('format-justify-left') button_wrap_word.connect("toggled", self.wrap_mode_changed, 'word') toolbar_view.insert(button_wrap_word, -1) if self.conf['wrap-mode'] == 'none': button_wrap_none.set_active(True) elif self.conf['wrap-mode'] == 'char': button_wrap_none.set_active(True) elif self.conf['wrap-mode'] == 'word': button_wrap_none.set_active(True) make_separator(toolbar_view, False) item_font_size = FontSize() item_font_size.set_font_size(self.conf['font-size']) item_font_size.connect('changed', self.font_size_changed) toolbar_view.insert(item_font_size, -1) combo_font = FontComboBox(self.conf['font']) combo_font.connect('changed', self.font_changed) toolbar_view.insert(combo_font, -1) make_separator(toolbar_view, False) button_numbers = ToggleToolButton('show-numbers') button_numbers.props.accelerator = '<Ctrl><Mayus>N' button_numbers.set_tooltip(_('Show line numbers')) button_numbers.set_active(self.conf['show-line-numbers']) button_numbers.connect('toggled', self.show_numbers_changed) toolbar_view.insert(button_numbers, -1) button_right_line = ToggleToolButton('show-right-line') button_right_line.props.accelerator = '<Ctrl>L' button_right_line.set_tooltip(_('Show a line in a specific position')) button_right_line.set_active(self.conf['show-right-line']) button_right_line.connect('toggled', self.show_right_line_changed) toolbar_view.insert(button_right_line, -1) self.spinner_right_line = Spinner(self.conf['right-line-pos'], 1, 150) self.spinner_right_line.set_sensitive(self.conf['show-right-line']) self.spinner_right_line.connect('value-changed', self.right_line_pos_changed) toolbar_view.insert(self.spinner_right_line, -1) make_separator(toolbar_view, False) combo_styles = ComboStyles(self.conf['theme']) combo_styles.connect('theme-changed', self.theme_changed) toolbar_view.insert(combo_styles, -1) make_separator(toolbar, True) button_stop = ToolButton('activity-stop') button_stop.props.accelerator = '<Ctrl>Q' button_stop.connect('clicked', self._exit) toolbar.insert(button_stop, -1) toolbar_file.show_all() toolbar_edit.show_all() toolbar_view.show_all() toolbar_edit.copy.hide() toolbar_edit.paste.hide() self.set_toolbar_box(toolbar_box)
def __init__(self, handle): activity.Activity.__init__(self, handle) self.set_title('FotoToon') self._max_participants = 1 self.page = None toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page toolbar_box.toolbar.insert(activity_button, 0) edit_toolbar_btn = ToolbarButton() edit_toolbar = Gtk.Toolbar() edit_toolbar_btn.props.page = edit_toolbar edit_toolbar_btn.props.icon_name = 'toolbar-edit' edit_toolbar_btn.label = _('Edit') toolbar_box.toolbar.insert(edit_toolbar_btn, -1) view_toolbar_btn = ToolbarButton() view_toolbar = Gtk.Toolbar() view_toolbar_btn.props.page = view_toolbar view_toolbar_btn.props.icon_name = 'toolbar-view' view_toolbar_btn.label = _('View') toolbar_box.toolbar.insert(view_toolbar_btn, -1) slideview_btn = ToggleToolButton('slideshow') slideview_btn.set_tooltip(_('Slideshow')) slideview_btn.set_active(False) slideview_btn.connect('clicked', self._switch_view_mode, False) view_toolbar.insert(slideview_btn, -1) slideview_btn.show() slideview_timings_btn = ToggleToolButton('slideshow-stopwatch') slideview_timings_btn.set_tooltip(_('Slideshow with Timings')) slideview_timings_btn.set_active(False) slideview_timings_btn.connect('clicked', self._switch_view_mode, True) view_toolbar.insert(slideview_timings_btn, -1) slideview_timings_btn.show() time_button = ToolButton('stopwatch') time_button.set_tooltip(_('Set Image Duration in Slideshow (Seconds)')) view_toolbar.insert(time_button, -1) time_button.show() self._time_spin = Gtk.SpinButton.new_with_range(MIN_TIME, MAX_TIME, 1) self._time_spin.connect('value-changed', self.__time_spin_changed_cb) self._time_spin.props.value = DEFAULT_TIME self._time_spin.props.update_policy = \ Gtk.SpinButtonUpdatePolicy.IF_VALID palette = time_button.get_palette() palette.connect('popup', self.__time_button_popup_cb) time_button.connect( 'clicked', lambda *args: palette.popup(immediate=True, state=Palette.SECONDARY)) alignment = Gtk.Alignment() alignment.set_padding(style.DEFAULT_PADDING, style.DEFAULT_PADDING, style.DEFAULT_PADDING, style.DEFAULT_PADDING) alignment.add(self._time_spin) self._time_spin.show() palette.set_content(alignment) alignment.show() fullscreen_btn = ToolButton('view-fullscreen') fullscreen_btn.set_tooltip(_('Fullscreen')) fullscreen_btn.props.accelerator = '<Alt>Return' fullscreen_btn.connect('clicked', lambda w: self.fullscreen()) view_toolbar.insert(fullscreen_btn, -1) fullscreen_btn.show() self.set_toolbar_box(toolbar_box) toolbar = toolbar_box.toolbar self.page = Page() self.globes_manager = GlobesManager(toolbar, edit_toolbar, self) # fonts self._text_button = ToolbarButton() self._text_button.props.page = TextToolbar(self.page) self._text_button.props.icon_name = 'format-text-size' self._text_button.props.label = _('Text') self._toolbar_box.toolbar.insert(self._text_button, -1) reorder_img_btn = ToolButton('thumbs-view') reorder_img_btn.set_icon_name('thumbs-view') reorder_img_btn.set_tooltip(_('Change image order')) reorder_img_btn.connect('clicked', self.__image_order_cb) edit_toolbar.insert(reorder_img_btn, -1) reorder_img_btn.show() bgchange = ToolButton(icon_name='contract-coordinates') bgchange.set_tooltip(_('Edit background image')) bgchange.connect('clicked', self.__bgchange_clicked_cb) edit_toolbar.insert(bgchange, -1) bgchange.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) stop = StopButton(self) toolbar_box.toolbar.insert(stop, -1) toolbar_box.show_all() # add export button separator_2 = Gtk.SeparatorToolItem() separator_2.show() activity_toolbar.insert(separator_2, -1) self.bt_save_as_image = ToolButton() self.bt_save_as_image.props.icon_name = 'save-as-image' self.bt_save_as_image.connect('clicked', self.write_image) self.bt_save_as_image.set_tooltip(_('Save as Image')) activity_toolbar.insert(self.bt_save_as_image, -1) self.bt_save_as_image.show() save_as_pdf = ToolButton() save_as_pdf.props.icon_name = 'save-as-pdf' save_as_pdf.connect('clicked', self._save_as_pdf) save_as_pdf.set_tooltip(_('Save as a Book (PDF)')) activity_toolbar.insert(save_as_pdf, -1) save_as_pdf.show() save_as_ogg = ToolButton() save_as_ogg.props.icon_name = 'save-as-ogg' save_as_ogg.connect('clicked', self.__save_as_ogg_cb) save_as_ogg.set_tooltip(_('Save as a Movie (OGG)')) activity_toolbar.insert(save_as_ogg, -1) save_as_ogg.show() activity_button.page.title.connect("focus-in-event", self.on_title) scrolled = Gtk.ScrolledWindow() # scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS) scrolled.add_with_viewport(self.page) scrolled.set_kinetic_scrolling(False) scrolled.show_all() self._slideview = SlideView(self) self._slideview.show_all() self._notebook = Gtk.Notebook() self._notebook.set_show_tabs(False) self._notebook.append_page(scrolled, None) self._notebook.append_page(self._slideview, None) self._notebook.show_all() if self._jobject.file_path is None or self._jobject.file_path == '': empty_widget = EmptyWidget() empty_widget.connect('choose-image', self.__add_image) self.set_canvas(empty_widget) else: self.set_canvas(self._notebook) self.show() self.metadata['mime_type'] = 'application/x-fototoon-activity' self.page.empty_page = handle.object_id is None self._key_press_signal_id = None
class ClockActivity(activity.Activity): """The clock activity displays a simple clock widget. """ def __init__(self, handle): """Create and initialize the clock activity. """ super(ClockActivity, self).__init__(handle) # TRANS: Title of the activity self.set_title(_('What Time Is It?')) # TRANS: The format used when writing the time in full # letters. You must take care to use a font size large enough # so that kids can read it easily, but also small enough so # that all times combination fit on the screen, even when the # screen is rotated. Pango markup: # http://www.pyGtk.org/docs/pyGtk/pango-markup-language.html self._TIME_LETTERS_FORMAT = _('<markup>\ <span lang="en" font_desc="Sans 20">%s</span></markup>') # TRANS: The format used to display the weekday and date # (example: Tuesday 10/21/2008) We recommend to use the same # font size as for the time display. See # http://docs.python.org/lib/module-time.html for available # strftime formats. xgettext:no-python-format self._DATE_SHORT_FORMAT = _('<markup>\ <span lang="en" font_desc="Sans 20">\ <span foreground="#B20008">%A</span>, \ <span foreground="#5E008C">%m</span>/\ <span foreground="#B20008">%d</span>/\ <span foreground="#9A5200">%Y</span></span></markup>') # Should we write the time in full letters? self._time_writer = None self._time_in_letters = self.get_title() self._time_letters = None self._date = None self._time_speaker = None if 'clock-mode' not in self.metadata.keys(): self.metadata['clock-mode'] = _MODE_SIMPLE_CLOCK else: self.metadata['clock-mode'] = int(self.metadata['clock-mode']) if 'write-time' in self.metadata.keys(): self._write_time = bool(self.metadata['write-time']) else: self._write_time = False if 'speak-time' in self.metadata.keys(): self._speak_time = bool(self.metadata['speak-time']) else: self._speak_time = False if 'write-date' in self.metadata.keys(): self._write_date = bool(self.metadata['write-date']) else: self._write_date = False self._make_display() self._make_toolbars() # Show the activity on the screen self.show_all() # We want to be notified when the minutes change self._clock.connect("time_minute", self._minutes_changed_cb) if not self.powerd_running(): try: bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.ohm', '/org/freedesktop/ohm/Keystore') self.ohm_keystore = dbus.Interface( proxy, 'org.freedesktop.ohm.Keystore') except dbus.DBusException: self.ohm_keystore = None def write_file(self, file_path): self.metadata['write-time'] = 'True' if self._write_time else '' self.metadata['write-date'] = 'True' if self._write_date else '' self.metadata['speak-time'] = 'True' if self._speak_time else '' self.metadata['clock-mode'] = str(self._clock._mode) def powerd_running(self): self.using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK) return self.using_powerd def _inhibit_suspend(self): if self.using_powerd: fd = open(POWERD_INHIBIT_DIR + "/%u" % os.getpid(), 'w') fd.close() return True if self.ohm_keystore is not None: try: self.ohm_keystore.SetKey('suspend.inhibit', 1) return self.ohm_keystore.GetKey('suspend.inhibit') except dbus.exceptions.DBusException: return False else: return False def _allow_suspend(self): if self.using_powerd: os.unlink(POWERD_INHIBIT_DIR + "/%u" % os.getpid()) return True if self.ohm_keystore is not None: try: self.ohm_keystore.SetKey('suspend.inhibit', 0) return self.ohm_keystore.GetKey('suspend.inhibit') except dbus.exceptions.DBusException: return False else: return False def _make_toolbars(self): """Prepare and set the toolbars of the activity. Load and show icons. Associate them to the call back methods. """ self.max_participants = 1 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_button.show() toolbar_box.toolbar.insert(activity_button, 0) self._add_clock_controls(toolbar_box.toolbar) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_size_request(0, -1) separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) toolbar_box.toolbar.insert(StopButton(self), -1) self.set_toolbar_box(toolbar_box) toolbar_box.show_all() return toolbar_box def _add_clock_controls(self, display_toolbar): # First group of radio button to select the type of clock to display button1 = RadioToolButton(icon_name="simple-clock") button1.set_tooltip(_('Simple Clock')) button1.connect("toggled", self._display_mode_changed_cb, _MODE_SIMPLE_CLOCK) display_toolbar.insert(button1, -1) button2 = RadioToolButton(icon_name="nice-clock", group=button1) button2.set_tooltip(_('Nice Clock')) button2.connect("toggled", self._display_mode_changed_cb, _MODE_NICE_CLOCK) display_toolbar.insert(button2, -1) button3 = RadioToolButton(icon_name="digital-clock", group=button1) button3.set_tooltip(_('Digital Clock')) button3.connect("toggled", self._display_mode_changed_cb, _MODE_DIGITAL_CLOCK) display_toolbar.insert(button3, -1) # A separator between the two groups of buttons separator = Gtk.SeparatorToolItem() separator.set_draw(True) display_toolbar.insert(separator, -1) # Now the options buttons to display other elements: date, day # of week... A button in the toolbar to write the time in # full letters button = ToggleToolButton("write-time") button.set_tooltip(_('Display time in full letters')) button.connect("toggled", self._write_time_clicked_cb) display_toolbar.insert(button, -1) # The button to display the weekday and date button = ToggleToolButton("write-date") button.set_tooltip(_('Display weekday and date')) button.connect("toggled", self._write_date_clicked_cb) display_toolbar.insert(button, -1) # Another button to speak aloud the time button = ToggleToolButton("microphone") button.set_tooltip(_('Talking clock')) button.connect("toggled", self._speak_time_clicked_cb) display_toolbar.insert(button, -1) # A separator between the two groups of buttons separator = Gtk.SeparatorToolItem() separator.set_draw(True) display_toolbar.insert(separator, -1) # And another button to toggle grabbing the hands self._grab_button = ToggleToolButton("grab") self._grab_button.set_tooltip(_('Grab the hands')) self._grab_button.connect("toggled", self._grab_clicked_cb) display_toolbar.insert(self._grab_button, -1) def _make_display(self): """Prepare the display of the clock. The display has two parts: the clock face at the top, and the time in full letters at the bottom, when the user selects to show it. """ # The clock face self._clock = ClockFace() # The label to print the time in full letters self._time_letters = Gtk.Label() self._time_letters.set_no_show_all(True) # Following line in ineffective! # self._time_letters.set_line_wrap(True) # Resize the invisible label so that Gtk will know in advance # the height when we show it. self._time_letters.set_markup( self._TIME_LETTERS_FORMAT % self._time_in_letters) # The label to write the date self._date = Gtk.Label() self._date.set_no_show_all(True) self._date.set_markup( self._clock.get_time().strftime(self._DATE_SHORT_FORMAT)) # Put all these widgets in a vertical box vbox = Gtk.VBox() vbox.pack_start(self._clock, True, True, 0) vbox.pack_start(self._time_letters, False, False, 0) vbox.pack_start(self._date, False, False, 0) # Attach the display to the activity self.set_canvas(vbox) def _write_date_clicked_cb(self, button): """The user clicked on the "write date" button to display the current weekday and date. """ if button.get_active(): self._date.show() else: self._date.hide() def _display_mode_changed_cb(self, radiobutton, display_mode): """The user selected a clock display mode (simple clock, nice or digital). """ self._clock.set_display_mode(display_mode) self._clock.queue_draw() is_digital = display_mode == _MODE_DIGITAL_CLOCK # Exit grab hands mode if the clock is digital if self._clock.grab_hands_mode and is_digital: self._grab_button.set_active(False) # The hands can't be grabbed in the digital clock mode self._grab_button.props.sensitive = not is_digital def _write_time_clicked_cb(self, button): """The user clicked on the "write time" button to print the current time. """ self._write_time = button.get_active() if self._write_time: self._time_letters.show() self._write_and_speak(False) else: self._time_letters.hide() def _speak_time_clicked_cb(self, button): """The user clicked on the "speak time" button to hear the talking clock. """ self._speak_time = button.get_active() if self._speak_time: self._write_and_speak(True) def _grab_clicked_cb(self, button): """The user clicked on the "grab hands" button to toggle grabbing the hands. """ self._clock.change_grab_hands_mode(button.get_active()) def _minutes_changed_cb(self, clock): """Minutes have changed on the clock face: we have to update the display of the time in full letters if the user has chosen to have it and eventually croak the time. """ # Change time display and talk, if necessary self._write_and_speak(True) # Update the weekday and date in case it was midnight self._date.set_markup( clock.get_time().strftime(self._DATE_SHORT_FORMAT)) def _notify_active_cb(self, widget, event): """Sugar notify us that the activity is becoming active or inactive. When we are inactive, we change the activity status of the clock face widget, so that it can stop updating every seconds. """ self._clock.active = self.props.active if self.props.active: self._inhibit_suspend() else: self._allow_suspend() def _write_and_speak(self, speak): """ Write and speak the time (called in another thread not to block the clock). """ # A helper function for the running thread def thread_write_and_speak(): # Only update the time in full letters when necessary if self._write_time or self._speak_time: self._do_write_time() # And if requested, say it aloud if self._speak_time and speak: self._do_speak_time() # Now detach a thread to do the big job thread = threading.Thread(target=thread_write_and_speak) thread.start() def _do_write_time(self): """Translate the time to full letters. """ if self._time_writer is None: self._time_writer = TimeWriter() hour = self._clock.get_time().hour minute = self._clock.get_time().minute self._time_in_letters = self._time_writer.write_time(hour, minute) self._time_letters.set_markup( self._TIME_LETTERS_FORMAT % self._time_in_letters) def _do_speak_time(self): """Speak aloud the current time. """ def gstmessage_cb(bus, message, pipe): if message.type in (Gst.MessageType.EOS, Gst.MessageType.ERROR): pipe.set_state(Gst.State.NULL) if self._time_speaker is None: self._time_speaker = Speaker() pipeline = 'espeak text="%(text)s" voice="%(voice)s" pitch="%(pitch)s" \ rate="%(rate)s" gap="%(gap)s" ! autoaudiosink' % { 'text': self._untag(self._time_in_letters), 'voice': self._time_speaker.VOICE, 'pitch': self._time_speaker.PITCH, 'rate': self._time_speaker.SPEED, 'gap': self._time_speaker.WORD_GAP} try: pipe = Gst.parse_launch(pipeline) bus = pipe.get_bus() bus.add_signal_watch() bus.connect('message', gstmessage_cb, pipe) pipe.set_state(Gst.State.PLAYING) except: self._time_speaker.speak(self._untag(self._time_in_letters)) def _untag(self, text): """Remove all the tags (pango markup) from a text. """ if text is False or "<" not in text: return text else: result = "" for s in re.findall(r"(<.*?>)|([^<>]+)", text): result += s[1] return result
class FileChooserOpen(Gtk.Window): __gsignals__ = {'open-file': (GObject.SIGNAL_RUN_FIRST, None, [str])} def __init__(self, activity, folder=None): Gtk.Window.__init__(self) self._activity = activity self.vbox = Gtk.VBox() self.view = Gtk.IconView() self.model = Gtk.ListStore(str, GdkPixbuf.Pixbuf) self.folder = folder or os.path.expanduser('~/') self.files = [] self.show_hidden_files = False if os.path.isfile(self.folder): self.folder = self.go_up(self.folder, _return=True) self.set_modal(True) self.set_decorated(False) self.set_resizable(False) self.set_size_request(WIDTH, HEIGHT) self.set_border_width(style.LINE_WIDTH) self.add_events(Gdk.EventMask.KEY_RELEASE_MASK) self.set_position(Gtk.WindowPosition.CENTER_ALWAYS) self.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) self.view.set_model(self.model) self.view.set_selection_mode(Gtk.SelectionMode.MULTIPLE) self.view.set_text_column(0) self.view.set_pixbuf_column(1) self.connect('key-release-event', self.__key_release_event_cb) self.view.connect('selection-changed', self.__selection_changed) self.view.connect('button-press-event', self.__button_press_event_cb) scrolled = Gtk.ScrolledWindow() scrolled.add(self.view) self.__make_toolbar() self.show_folder() self.vbox.pack_end(scrolled, True, True, 0) self.add(self.vbox) self.show_all() GObject.timeout_add(500, self.check_files) def __make_toolbar(self): self.toolbar = Gtk.Toolbar() self.toolbar.modify_bg(Gtk.StateType.NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) self.go_up_button = ToolButton(icon_name='go-up') self.go_up_button.props.accelerator = '<Alt>S' self.go_up_button.set_tooltip(_('Go to pather directory')) self.go_up_button.connect('clicked', self.go_up) self.toolbar.insert(self.go_up_button, -1) self.toolbar.insert(Gtk.SeparatorToolItem(), -1) self.hidden_files_button = ToggleToolButton('show-hidden-files') self.hidden_files_button.props.accelerator = '<Ctrl>H' self.hidden_files_button.set_tooltip(_('Show hidden files')) self.hidden_files_button.connect('clicked', self.__show_hidden_files) self.toolbar.insert(self.hidden_files_button, -1) self.toolbar.insert(Gtk.SeparatorToolItem(), -1) item = Gtk.ToolItem() self.entry = Gtk.Entry() self.entry.set_size_request(300, -1) self.entry.set_text(self.folder) self.entry.connect('activate', self.__open_path_from_entry) item.add(self.entry) self.toolbar.insert(item, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self.toolbar.insert(separator, -1) self.button_open = ToolButton(icon_name='fileopen') self.button_open.set_tooltip(_('Open selected file')) self.button_open.set_sensitive(False) self.button_open.connect('clicked', self.__open_path) self.toolbar.insert(self.button_open, -1) self.close_button = ToolButton(icon_name='dialog-cancel') self.close_button.connect('clicked', self.close) self.toolbar.insert(self.close_button, -1) self.vbox.pack_start(self.toolbar, False, False, 0) def __key_release_event_cb(self, widget, event): if event.keyval == 65293: # Enter self.__open_path() def go_up(self, button=None, _return=False): path = '/' folders = [] if self.folder == '/': return for folder in self.folder.split('/'): if not folder: continue folders.append(folder) if not folders: return for folder in folders[:-1]: if folder: path += folder + '/' if not _return: self.folder = path self.check_files() else: return path def __show_hidden_files(self, button): self.show_hidden_files = button.get_active() self.show_folder() def __open_path(self, button=None): if len(self.view.get_selected_items()) == 1: if os.path.isdir(self.selected_path): self.folder = self.selected_path self.selected_path = None elif os.path.isfile(self.selected_path): self.emit('open-file', self.selected_path) else: files = [] directory = None for item in self.view.get_selected_items(): iter = self.model.get_iter(item) path = os.path.join(self.folder, self.model.get_value(iter, 0)) if os.path.isfile(path): files.append(path) elif os.path.isdir(path) and not directory: directory = path if files: for path in files: GObject.idle_add(self.emit, 'open-file', path) self.emit('open-file', path) self.selected_path = None else: if directory: self.folder = directory return # Evit destroy self.destroy() def __open_path_from_entry(self, entry): path = self.entry.get_text() if not os.path.exists(path): self.create_alert(path) return if os.path.isdir(path): self.folder = path self.check_files() elif os.path.isfile(path): self.emit('open-file', path) self.destroy() def create_alert(self, path): alert = TimeoutAlert(10) alert.props.title = _('This file not exists.') alert.props.msg = _( "Apparently you've selected a file that does not exist.") image = Gtk.Image.new_from_stock(Gtk.STOCK_OK, Gtk.IconSize.MENU) alert.add_button(Gtk.ResponseType.NO, _('Ok'), icon=image) alert.connect('response', self.__alert_response) self.vbox.pack_start(alert, False, False, 0) self.vbox.reorder_child(alert, 1) def __alert_response(self, alert): self.vbox.remove(alert) def check_files(self): files = os.listdir(self.folder) files.sort() if files != self.files: self.selected_path = None self.entry.set_text(self.folder) self.go_up_button.set_sensitive(self.folder != '/') self.show_folder() return True def show_folder(self): self.files = os.listdir(self.folder) self.files.sort() self.model.clear() folders = [] files = [] for x in self.files: path = os.path.join(self.folder, x) if os.path.isdir(path): folders.append(path) elif os.path.isfile(path): files.append(path) for path in folders + files: if not self.show_hidden_files: if path.endswith('~') or path.split('/')[-1].startswith('.'): continue pixbuf = G.get_pixbuf_from_path(path) self.model.append([path.split('/')[-1], pixbuf]) def __selection_changed(self, view): if self.view.get_selected_items(): path = self.view.get_selected_items()[0] iter = self.model.get_iter(path) self.selected_path = os.path.join(self.folder, self.model.get_value(iter, 0)) self.button_open.set_sensitive(True) else: self.selected_path = None self.button_open.set_sensitive(False) def __button_press_event_cb(self, view, event): if event.button != 1: return try: path = view.get_path_at_pos(int(event.x), int(event.y)) iter = self.model.get_iter(path) directory = os.path.join(self.folder, self.model.get_value(iter, 0)) if event.type.value_name == 'GDK_2BUTTON_PRESS': if os.path.isdir(directory): self.folder = directory elif os.path.isfile(directory): self.emit('open-file', directory) self.destroy() except TypeError: self.selected_path = None self.button_open.set_sensitive(False) def close(self, button=None): self.destroy()
class GetIABooksActivity(activity.Activity): def __init__(self, handle): "The entry point to the Activity" activity.Activity.__init__(self, handle, False) self.max_participants = 1 self._sequence = 0 self.selected_book = None self.queryresults = None self._getter = None self.show_images = True self.languages = {} self._lang_code_handler = languagenames.LanguageNames() self.catalogs_configuration = {} self.catalog_history = [] if os.path.exists('/etc/get-books.cfg'): self._read_configuration('/etc/get-books.cfg') else: self._read_configuration() toolbar_box = ToolbarBox() activity_button = ToolButton() color = profile.get_color() bundle = ActivityBundle(activity.get_bundle_path()) icon = Icon(file=bundle.get_icon(), xo_color=color) activity_button.set_icon_widget(icon) activity_button.show() toolbar_box.toolbar.insert(activity_button, 0) self._add_search_controls(toolbar_box.toolbar) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) toolbar_box.toolbar.insert(StopButton(self), -1) self.set_toolbar_box(toolbar_box) toolbar_box.show_all() self._books_toolbar = toolbar_box.toolbar self._create_controls() self.using_powerd = os.access(POWERD_INHIBIT_DIR, os.W_OK) self.__book_downloader = self.__image_downloader = None def get_path(self): self._sequence += 1 return os.path.join(self.get_activity_root(), 'instance', '%03d.tmp' % self._sequence) def _inhibit_suspend(self): if self.using_powerd: fd = open(POWERD_INHIBIT_DIR + "/%u" % os.getpid(), 'w') logging.error("inhibit_suspend file is %s", (POWERD_INHIBIT_DIR \ + "/%u" % os.getpid())) fd.close() return True return False def _allow_suspend(self): if self.using_powerd: if os.path.exists(POWERD_INHIBIT_DIR + "/%u" % os.getpid()): os.unlink(POWERD_INHIBIT_DIR + "/%u" % os.getpid()) logging.error("allow_suspend unlinking %s", (POWERD_INHIBIT_DIR \ + "/%u" % os.getpid())) return True return False def _read_configuration(self, file_name='get-books.cfg'): logging.error('Reading configuration from file %s', file_name) config = ConfigParser.ConfigParser() config.readfp(open(file_name)) if config.has_option('GetBooks', 'show_images'): self.show_images = config.getboolean('GetBooks', 'show_images') self.languages = {} if config.has_option('GetBooks', 'languages'): languages_param = config.get('GetBooks', 'languages') for language in languages_param.split(','): lang_code = language.strip() if len(lang_code) > 0: self.languages[lang_code] = \ self._lang_code_handler.get_full_language_name(lang_code) for section in config.sections(): if section != 'GetBooks' and not section.startswith('Catalogs'): name = config.get(section, 'name') _SOURCES[section] = name repo_config = {} repo_config['query_uri'] = config.get(section, 'query_uri') repo_config['opds_cover'] = config.get(section, 'opds_cover') if config.has_option(section, 'summary_field'): repo_config['summary_field'] = \ config.get(section, 'summary_field') else: repo_config['summary_field'] = None if config.has_option(section, 'blacklist'): blacklist = config.get(section, 'blacklist') repo_config['blacklist'] = blacklist.split(',') # TODO strip? else: repo_config['blacklist'] = [] _SOURCES_CONFIG[section] = repo_config logging.error('_SOURCES %s', pformat(_SOURCES)) logging.error('_SOURCES_CONFIG %s', pformat(_SOURCES_CONFIG)) for section in config.sections(): if section.startswith('Catalogs'): catalog_source = section.split('_')[1] if not catalog_source in _SOURCES_CONFIG: logging.error('There are not a source for the catalog ' + 'section %s', section) break source_config = _SOURCES_CONFIG[catalog_source] opds_cover = source_config['opds_cover'] for catalog in config.options(section): catalog_config = {} catalog_config['query_uri'] = config.get(section, catalog) catalog_config['opds_cover'] = opds_cover catalog_config['source'] = catalog_source catalog_config['name'] = catalog catalog_config['summary_field'] = \ source_config['summary_field'] self.catalogs_configuration[catalog] = catalog_config self.source = _SOURCES_CONFIG.keys()[0] self.filter_catalogs_by_source() logging.error('languages %s', pformat(self.languages)) logging.error('catalogs %s', pformat(self.catalogs)) def _add_search_controls(self, toolbar): book_search_item = Gtk.ToolItem() toolbar.search_entry = iconentry.IconEntry() toolbar.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'system-search') toolbar.search_entry.add_clear_button() toolbar.search_entry.connect('activate', self.__search_entry_activate_cb) width = int(Gdk.Screen.width() / 4) toolbar.search_entry.set_size_request(width, -1) book_search_item.add(toolbar.search_entry) toolbar.search_entry.show() toolbar.insert(book_search_item, -1) book_search_item.show() toolbar.source_combo = ComboBox() toolbar.source_combo.props.sensitive = True toolbar.source_changed_cb_id = \ toolbar.source_combo.connect('changed', self.__source_changed_cb) combotool = ToolComboBox(toolbar.source_combo) toolbar.insert(combotool, -1) combotool.show() self.bt_catalogs = ToggleToolButton('books') self.bt_catalogs.set_tooltip(_('Catalogs')) toolbar.insert(self.bt_catalogs, -1) self.bt_catalogs.connect('toggled', self.__toggle_cats_cb) if len(self.catalogs) > 0: self.bt_catalogs.show() if len(self.languages) > 0: toolbar.config_toolbarbutton = ToolbarButton() toolbar.config_toolbarbutton.props.icon_name = 'preferences-system' toolbar.config_toolbarbox = Gtk.Toolbar() toolbar.config_toolbarbutton.props.page = toolbar.config_toolbarbox toolbar.language_combo = ComboBox() toolbar.language_combo.props.sensitive = True combotool = ToolComboBox(toolbar.language_combo) toolbar.language_combo.append_item('all', _('Any language')) for key in self.languages.keys(): toolbar.language_combo.append_item(key, self.languages[key]) toolbar.language_combo.set_active(0) toolbar.config_toolbarbutton.props.page.insert(combotool, -1) toolbar.insert(toolbar.config_toolbarbutton, -1) toolbar.config_toolbarbutton.show() combotool.show() toolbar.language_changed_cb_id = \ toolbar.language_combo.connect('changed', self.__language_changed_cb) self._device_manager = devicemanager.DeviceManager() self._refresh_sources(toolbar) self._device_manager.connect('device-changed', self.__device_changed_cb) toolbar.search_entry.grab_focus() return toolbar def __bt_catalogs_clicked_cb(self, button): palette = button.get_palette() palette.popup(immediate=True, state=palette.SECONDARY) def __switch_catalog_cb(self, catalog_name): catalog_config = self.catalogs[catalog_name.decode('utf-8')] self.__activate_catalog_cb(None, catalog_config) def __activate_catalog_cb(self, menu, catalog_config): query_language = self.get_query_language() self.enable_button(False) self.clear_downloaded_bytes() self.book_selected = False self.listview.handler_block(self.selection_cb_id) self.listview.clear() self.listview.handler_unblock(self.selection_cb_id) logging.error('SOURCE %s', catalog_config['source']) self._books_toolbar.search_entry.props.text = '' self.source = catalog_config['source'] position = _SOURCES_CONFIG[self.source]['position'] self._books_toolbar.source_combo.set_active(position) if self.queryresults is not None: self.queryresults.cancel() self.queryresults = None self.queryresults = opds.RemoteQueryResult(catalog_config, '', query_language) self.show_message(_('Performing lookup, please wait...')) # README: I think we should create some global variables for # each cursor that we are using to avoid the creation of them # every time that we want to change it self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) self.queryresults.connect('updated', self.__query_updated_cb) def update_format_combo(self, links): self.format_combo.handler_block(self.__format_changed_cb_id) self.format_combo.remove_all() for key in _MIMETYPES.keys(): if _MIMETYPES[key] in links.keys(): self.format_combo.append_item(_MIMETYPES[key], key) self.format_combo.set_active(0) self.format_combo.handler_unblock(self.__format_changed_cb_id) def get_search_terms(self): return self._books_toolbar.search_entry.props.text def __device_changed_cb(self, mgr): logging.debug('Device was added/removed') self._refresh_sources(self._books_toolbar) def _refresh_sources(self, toolbar): toolbar.source_combo.handler_block(toolbar.source_changed_cb_id) #TODO: Do not blindly clear this toolbar.source_combo.remove_all() position = 0 for key in _SOURCES.keys(): toolbar.source_combo.append_item(_SOURCES[key], key, icon_name='internet-icon') _SOURCES_CONFIG[key]['position'] = position position = position + 1 # Add menu for local books if len(_SOURCES) > 0: toolbar.source_combo.append_separator() toolbar.source_combo.append_item('local_books', _('My books'), icon_name='activity-journal') devices = self._device_manager.get_devices() first_device = True for device_name in devices: device = devices[device_name] logging.debug('device %s', device) if device['removable']: mount_point = device['mount_path'] label = device['label'] if label == '' or label is None: capacity = device['size'] label = (_('%.2f GB Volume') % (capacity / (1024.0 ** 3))) logging.debug('Adding device %s', (label)) if first_device: toolbar.source_combo.append_separator() first_device = False toolbar.source_combo.append_item(mount_point, label) toolbar.source_combo.set_active(0) toolbar.source_combo.handler_unblock(toolbar.source_changed_cb_id) def __format_changed_cb(self, combo): self.show_book_data(False) def __language_changed_cb(self, combo): self.find_books(self.get_search_terms()) def __search_entry_activate_cb(self, entry): self.find_books(self.get_search_terms()) def __get_book_cb(self, button): self.get_book() def enable_button(self, state): self._download.props.sensitive = state self.format_combo.props.sensitive = state def move_up_catalog(self, treeview): len_cat = len(self.catalog_history) if len_cat == 1: return else: # move a level up the tree self.catalog_listview.handler_block(self._catalog_changed_id) self.catalog_history.pop() len_cat -= 1 if(len_cat == 1): title = self.catalog_history[0]['title'] self.bt_move_up_catalog.set_label(title) self.bt_move_up_catalog.hide_image() else: title = self.catalog_history[len_cat - 1]['title'] self.bt_move_up_catalog.set_label(title) self.bt_move_up_catalog.show_image() self.catalogs = self.catalog_history[len_cat - 1]['catalogs'] if len(self.catalogs) > 0: self.path_iter = {} self.categories = [] for key in self.catalogs.keys(): self.categories.append({'text': key, 'dentro': []}) self.treemodel.clear() for p in self.categories: self.path_iter[p['text']] = \ self.treemodel.append([p['text']]) self.catalog_listview.handler_unblock(self._catalog_changed_id) def move_down_catalog(self, treeview): treestore, coldex = \ self.catalog_listview.get_selection().get_selected() len_cat = len(self.catalog_history) if len_cat > 0 and self.catalog_history[len_cat - 1]['catalogs'] == []: self.catalog_history.pop() len_cat = len(self.catalog_history) # README: when the Activity starts by default there is nothing # selected and this signal is called, so we have to avoid this # 'append' because it fails if coldex is not None: self.catalog_history.append( {'title': treestore.get_value(coldex, 0), 'catalogs': []}) self.__switch_catalog_cb(treestore.get_value(coldex, 0)) def _sort_logfile(self, treemodel, itera, iterb): a = treemodel.get_value(itera, 0) b = treemodel.get_value(iterb, 0) if a == None or b == None: return 0 a = a.lower() b = b.lower() if a > b: return 1 if a < b: return -1 return 0 def __toggle_cats_cb(self, button): if button.get_active(): self.tree_scroller.show_all() self.separa.show() else: self.tree_scroller.hide() self.separa.hide() def _create_controls(self): self._download_content_length = 0 self._download_content_type = None self.msg_label = Gtk.Label() self.list_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) # Catalogs treeview self.catalog_listview = Gtk.TreeView() self.catalog_listview.headers_clickble = True self.catalog_listview.hover_expand = True self.catalog_listview.rules_hint = True self._catalog_changed_id = self.catalog_listview.connect( 'cursor-changed', self.move_down_catalog) self.catalog_listview.set_enable_search(False) self.treemodel = Gtk.ListStore(str) self.treemodel.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.catalog_listview.set_model(self.treemodel) renderer = Gtk.CellRendererText() renderer.set_property('wrap-mode', Pango.WrapMode.WORD) self.treecol = Gtk.TreeViewColumn(_('Catalogs'), renderer, text=0) self.treecol.set_property('clickable', True) self.treecol.connect('clicked', self.move_up_catalog) self.catalog_listview.append_column(self.treecol) self.bt_move_up_catalog = ButtonWithImage(_('Catalogs')) self.bt_move_up_catalog.hide_image() self.treecol.set_widget(self.bt_move_up_catalog) self.load_source_catalogs() self.tree_scroller = Gtk.ScrolledWindow(hadjustment=None, vadjustment=None) self.tree_scroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.tree_scroller.add(self.catalog_listview) self.list_box.pack_start(self.tree_scroller, expand=False, fill=False, padding=0) self.separa = Gtk.VSeparator() self.list_box.pack_start(self.separa, expand=False, fill=False, padding=0) # books listview self.listview = ListView(self._lang_code_handler) self.selection_cb_id = self.listview.connect('selection-changed', self.selection_cb) self.listview.set_enable_search(False) self.list_scroller = Gtk.ScrolledWindow(hadjustment=None, vadjustment=None) self.list_scroller.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) vadjustment = self.list_scroller.get_vadjustment() vadjustment.connect('value-changed', self.__vadjustment_value_changed_cb) self.list_scroller.add(self.listview) self.list_box.pack_start(self.list_scroller, expand=True, fill=True, padding=0) self.scrolled = Gtk.ScrolledWindow() self.scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.scrolled.props.shadow_type = Gtk.ShadowType.NONE self.textview = Gtk.TextView() self.textview.set_editable(False) self.textview.set_cursor_visible(False) self.textview.set_wrap_mode(Gtk.WrapMode.WORD) self.textview.set_justification(Gtk.Justification.LEFT) self.textview.set_left_margin(20) self.textview.set_right_margin(20) self.scrolled.add(self.textview) self.list_box.show_all() self.separa.hide() self.tree_scroller.hide() vbox_download = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) hbox_format = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) format_label = Gtk.Label(label=_('Format:')) self.format_combo = ComboBox() for key in _MIMETYPES.keys(): self.format_combo.append_item(_MIMETYPES[key], key) self.format_combo.set_active(0) self.format_combo.props.sensitive = False self.__format_changed_cb_id = \ self.format_combo.connect('changed', self.__format_changed_cb) hbox_format.pack_start(format_label, False, False, 10) hbox_format.pack_start(self.format_combo, False, False, 10) vbox_download.pack_start(hbox_format, False, False, 10) self._download = Gtk.Button(_('Get Book')) self._download.set_image(Icon(icon_name='data-download')) self._download.props.sensitive = False self._download.connect('clicked', self.__get_book_cb) vbox_download.pack_start(self._download, False, False, 10) self.progressbox = Gtk.Box(spacing=20, orientation=Gtk.Orientation.HORIZONTAL) self.progressbar = Gtk.ProgressBar() self.progressbar.set_fraction(0.0) self.progressbox.pack_start(self.progressbar, expand=True, fill=True, padding=0) self.cancel_btn = Gtk.Button(stock=Gtk.STOCK_CANCEL) self.cancel_btn.set_image(Icon(icon_name='dialog-cancel')) self.cancel_btn.connect('clicked', self.__cancel_btn_clicked_cb) self.progressbox.pack_start(self.cancel_btn, expand=False, fill=False, padding=0) vbox_download.pack_start(self.progressbox, False, False, 10) bottom_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) if self.show_images: self.__image_downloader = None self.image = Gtk.Image() self.add_default_image() bottom_hbox.pack_start(self.image, False, False, 10) bottom_hbox.pack_start(self.scrolled, True, True, 10) bottom_hbox.pack_start(vbox_download, False, False, 10) bottom_hbox.show_all() vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) vbox.pack_start(self.msg_label, False, False, 10) vbox.pack_start(self.list_box, True, True, 0) vbox.pack_start(bottom_hbox, False, False, 10) self.set_canvas(vbox) self.listview.show() vbox.show() self.list_scroller.show() self.progress_hide() self.show_message( _('Enter words from the Author or Title to begin search.')) self._books_toolbar.search_entry.grab_focus() if len(self.catalogs) > 0: self.bt_catalogs.set_active(True) def progress_hide(self): self.clear_downloaded_bytes() self.progressbar.set_sensitive(False) self.cancel_btn.set_sensitive(False) def progress_show(self): self.progressbar.set_sensitive(True) self.cancel_btn.set_sensitive(True) def filter_catalogs_by_source(self): self.catalogs = {} for catalog_key in self.catalogs_configuration: catalog = self.catalogs_configuration[catalog_key] if catalog['source'] == self.source: self.catalogs[catalog_key] = catalog def load_source_catalogs(self): self.filter_catalogs_by_source() if len(self.catalogs) > 0: self.categories = [] self.path_iter = {} self.catalog_history = [] self.catalog_history.append({'title': _('Catalogs'), 'catalogs': self.catalogs}) for key in self.catalogs.keys(): self.categories.append({'text': key, 'dentro': []}) self.treemodel.clear() for p in self.categories: self.path_iter[p['text']] = self.treemodel.append([p['text']]) def can_close(self): if self.queryresults is not None: self.queryresults.cancel() self.queryresults = None return True def selection_cb(self, widget): selected_book = self.listview.get_selected_book() if self.source == 'local_books': if selected_book: self.selected_book = selected_book self._download.hide() self.show_book_data() self._object_id = selected_book.get_object_id() self._show_journal_alert(_('Selected book'), self.selected_title) else: self.clear_downloaded_bytes() if selected_book: self.update_format_combo(selected_book.get_types()) self.selected_book = selected_book self._download.show() self.show_book_data() def show_message(self, text): self.msg_label.set_text(text) self.msg_label.show() def hide_message(self): self.msg_label.hide() def show_book_data(self, load_image=True): self.selected_title = self.selected_book.get_title() book_data = _('Title:\t\t') + self.selected_title + '\n' self.selected_author = self.selected_book.get_author() book_data += _('Author:\t\t') + self.selected_author + '\n' self.selected_publisher = self.selected_book.get_publisher() self.selected_summary = self.selected_book.get_summary() if (self.selected_summary is not 'Unknown'): book_data += _('Summary:\t') + self.selected_summary + '\n' self.selected_language_code = self.selected_book.get_language() if self.selected_language_code != '': try: self.selected_language = \ self._lang_code_handler.get_full_language_name( self.selected_book.get_language()) except: self.selected_language = self.selected_book.get_language() book_data += _('Language:\t') + self.selected_language + '\n' book_data += _('Publisher:\t') + self.selected_publisher + '\n' textbuffer = self.textview.get_buffer() textbuffer.set_text('\n' + book_data) self.enable_button(True) # Cover Image self.exist_cover_image = False if self.show_images and load_image: if self.source == 'local_books': cover_image_buffer = self.get_journal_entry_cover_image( self.selected_book.get_object_id()) if (cover_image_buffer): self.add_image_buffer( self.get_pixbuf_from_buffer(cover_image_buffer)) else: self.add_default_image() else: url_image = self.selected_book.get_image_url() self.add_default_image() if url_image: self.download_image(url_image.values()[0]) def get_pixbuf_from_buffer(self, image_buffer): """Buffer To Pixbuf""" pixbuf_loader = GdkPixbuf.PixbufLoader() pixbuf_loader.write(image_buffer) pixbuf_loader.close() pixbuf = pixbuf_loader.get_pixbuf() return pixbuf def get_journal_entry_cover_image(self, object_id): ds_object = datastore.get(object_id) if 'cover_image' in ds_object.metadata: cover_data = ds_object.metadata['cover_image'] return base64.b64decode(cover_data) elif 'preview' in ds_object.metadata: return ds_object.metadata['preview'] else: return "" def download_image(self, url): self._inhibit_suspend() self.progress_show() if self.__image_downloader is not None: self.__image_downloader.stop() self.__image_downloader = opds.FileDownloader(url, self.get_path()) self.__image_downloader.connect('updated', self.__image_updated_cb) self.__image_downloader.connect('progress', self.__image_progress_cb) def __image_updated_cb(self, downloader, path, content_type): if path is not None: self.add_image(path) self.exist_cover_image = True os.remove(path) else: self.add_default_image() self.__image_downloader = None GObject.timeout_add(500, self.progress_hide) self._allow_suspend() def __image_progress_cb(self, downloader, progress): self.progressbar.set_fraction(progress) while Gtk.events_pending(): Gtk.main_iteration() def add_default_image(self): file_path = os.path.join(activity.get_bundle_path(), 'generic_cover.png') self.add_image(file_path) def add_image(self, file_path): pixbuf = GdkPixbuf.Pixbuf.new_from_file(file_path) self.add_image_buffer(pixbuf) def add_image_buffer(self, pixbuf): image_height = int(Gdk.Screen.height() / 4) image_width = image_height / 3 * 2 width, height = pixbuf.get_width(), pixbuf.get_height() scale = 1 if (width > image_width) or (height > image_height): scale_x = image_width / float(width) scale_y = image_height / float(height) scale = min(scale_x, scale_y) pixbuf2 = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, pixbuf.get_has_alpha(), pixbuf.get_bits_per_sample(), image_width, image_height) pixbuf2.fill(style.COLOR_PANEL_GREY.get_int()) margin_x = int((image_width - (width * scale)) / 2) margin_y = int((image_height - (height * scale)) / 2) pixbuf.scale(pixbuf2, margin_x, margin_y, image_width - (margin_x * 2), image_height - (margin_y * 2), margin_x, margin_y, scale, scale, GdkPixbuf.InterpType.BILINEAR) self.image.set_from_pixbuf(pixbuf2) def get_query_language(self): query_language = None if len(self.languages) > 0: query_language = self._books_toolbar.language_combo.props.value return query_language def find_books(self, search_text=''): self._inhibit_suspend() self.source = self._books_toolbar.source_combo.props.value query_language = self.get_query_language() self.enable_button(False) self.clear_downloaded_bytes() self.book_selected = False self.listview.handler_block(self.selection_cb_id) self.listview.clear() self.listview.handler_unblock(self.selection_cb_id) if self.queryresults is not None: self.queryresults.cancel() self.queryresults = None if self.source == 'local_books': self.listview.populate_with_books( self.get_entrys_info(search_text)) else: if search_text is None: return elif len(search_text) < 3: self.show_message(_('You must enter at least 3 letters.')) self._books_toolbar.search_entry.grab_focus() return if self.source == 'Internet Archive': self.queryresults = \ opds.InternetArchiveQueryResult(search_text, self.get_path()) elif self.source in _SOURCES_CONFIG: repo_configuration = _SOURCES_CONFIG[self.source] self.queryresults = opds.RemoteQueryResult(repo_configuration, search_text, query_language) else: self.queryresults = opds.LocalVolumeQueryResult(self.source, search_text, query_language) self.show_message(_('Performing lookup, please wait...')) self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) self.queryresults.connect('updated', self.__query_updated_cb) def __query_updated_cb(self, query, midway): self.listview.populate(self.queryresults) if hasattr(self.queryresults, '_feedobj') and \ 'bozo_exception' in self.queryresults._feedobj: # something went wrong and we have to inform about this bozo_exception = self.queryresults._feedobj.bozo_exception if isinstance(bozo_exception, urllib2.URLError): if isinstance(bozo_exception.reason, socket.gaierror): if bozo_exception.reason.errno == -2: self.show_message(_('Could not reach the server. ' 'Maybe you are not connected to the network')) self.window.set_cursor(None) return self.show_message(_('There was an error downloading the list.')) elif (len(self.queryresults.get_catalog_list()) > 0): self.show_message(_('New catalog list %s was found') \ % self.queryresults._configuration["name"]) self.catalogs_updated(query, midway) elif len(self.queryresults) == 0: self.show_message(_('Sorry, no books could be found.')) if not midway and len(self.queryresults) > 0: self.hide_message() query_language = self.get_query_language() if query_language != 'all' and query_language != 'en': # the bookserver send english books if there are not books in # the requested language only_english = True for book in self.queryresults.get_book_list(): if book.get_language() == query_language: only_english = False break if only_english: self.show_message( _('Sorry, we only found english books.')) self.get_window().set_cursor(None) self._allow_suspend() def catalogs_updated(self, query, midway): self.catalogs = {} for catalog_item in self.queryresults.get_catalog_list(): logging.debug('Add catalog %s', catalog_item.get_title()) catalog_config = {} download_link = '' download_links = catalog_item.get_download_links() for link in download_links.keys(): download_link = download_links[link] break catalog_config['query_uri'] = download_link catalog_config['opds_cover'] = \ catalog_item._configuration['opds_cover'] catalog_config['source'] = catalog_item._configuration['source'] source_config = _SOURCES_CONFIG[catalog_config['source']] catalog_config['name'] = catalog_item.get_title() catalog_config['summary_field'] = \ catalog_item._configuration['summary_field'] if catalog_item.get_title() in source_config['blacklist']: logging.debug('Catalog "%s" is in blacklist', catalog_item.get_title()) else: self.catalogs[catalog_item.get_title().strip()] = \ catalog_config if len(self.catalogs) > 0: len_cat = len(self.catalog_history) self.catalog_history[len_cat - 1]['catalogs'] = self.catalogs self.path_iter = {} self.categories = [] for key in self.catalogs.keys(): self.categories.append({'text': key, 'dentro': []}) self.treemodel.clear() for p in self.categories: self.path_iter[p['text']] = \ self.treemodel.append([p['text']]) title = self.catalog_history[len_cat - 1]['title'] self.bt_move_up_catalog.set_label(title) self.bt_move_up_catalog.show_image() else: self.catalog_history.pop() def __source_changed_cb(self, widget): search_terms = self.get_search_terms() if search_terms == '': self.find_books(None) else: self.find_books(search_terms) # enable/disable catalogs button if configuration is available self.source = self._books_toolbar.source_combo.props.value # Get catalogs for this source self.load_source_catalogs() if len(self.catalogs) > 0: self.bt_catalogs.show() self.bt_catalogs.set_active(True) else: self.bt_catalogs.set_active(False) self.bt_catalogs.hide() def __vadjustment_value_changed_cb(self, vadjustment): if not self.queryresults.is_ready(): return try: # Use various tricks to update resultset as user scrolls down if ((vadjustment.props.upper - vadjustment.props.lower) > 1000 \ and (vadjustment.props.upper - vadjustment.props.value - \ vadjustment.props.page_size) / (vadjustment.props.upper - \ vadjustment.props.lower) < 0.3) or ((vadjustment.props.upper \ - vadjustment.props.value - vadjustment.props.page_size) < 200): if self.queryresults.has_next(): self.queryresults.update_with_next() finally: return def __cancel_btn_clicked_cb(self, btn): if self.__image_downloader is not None: self.__image_downloader.stop() if self.__book_downloader is not None: self.__book_downloader.stop() self.progress_hide() self.enable_button(True) self.listview.props.sensitive = True self._books_toolbar.search_entry.set_sensitive(True) self._allow_suspend() def get_book(self): self.enable_button(False) self.clear_downloaded_bytes() self.progress_show() if self.source != 'local_books': self.selected_book.get_download_links(self.format_combo.props.value, self.download_book, self.get_path()) def download_book(self, url): logging.error('DOWNLOAD BOOK %s', url) self._inhibit_suspend() self.listview.props.sensitive = False self._books_toolbar.search_entry.set_sensitive(False) self.__book_downloader = opds.FileDownloader(url, self.get_path()) self.__book_downloader.connect('updated', self.__book_updated_cb) self.__book_downloader.connect('progress', self.__book_progress_cb) def __book_updated_cb(self, downloader, path, content_type): self._books_toolbar.search_entry.set_sensitive(True) self.listview.props.sensitive = True self._allow_suspend() GObject.timeout_add(500, self.progress_hide) self.enable_button(True) self.__book_downloader = None if path is None: self._show_error_alert(_('Error: Could not download %s. ' + 'The path in the catalog seems to be incorrect.') % self.selected_title) return if os.stat(path).st_size == 0: self._show_error_alert(_('Error: Could not download %s. ' + 'The other end sent an empty file.') % self.selected_title) return if content_type.startswith('text/html'): self._show_error_alert(_('Error: Could not download %s. ' + 'The other end sent text/html instead of a book.') % self.selected_title) return self.process_downloaded_book(path) def __book_progress_cb(self, downloader, progress): self.progressbar.set_fraction(progress) while Gtk.events_pending(): Gtk.main_iteration() def clear_downloaded_bytes(self): self.progressbar.set_fraction(0.0) def process_downloaded_book(self, path): logging.debug("Got document %s", path) self.create_journal_entry(path) self._getter = None self._allow_suspend() def create_journal_entry(self, path): journal_entry = datastore.create() journal_title = self.selected_title if self.selected_author != '': journal_title = journal_title + ', by ' + self.selected_author journal_entry.metadata['title'] = journal_title journal_entry.metadata['title_set_by_user'] = '******' journal_entry.metadata['keep'] = '0' journal_entry.metadata['mime_type'] = \ self.format_combo.props.value # Fix fake mime type for black&white pdfs if journal_entry.metadata['mime_type'] == _MIMETYPES['PDF BW']: journal_entry.metadata['mime_type'] = _MIMETYPES['PDF'] journal_entry.metadata['buddies'] = '' journal_entry.metadata['icon-color'] = profile.get_color().to_string() textbuffer = self.textview.get_buffer() journal_entry.metadata['description'] = \ textbuffer.get_text(textbuffer.get_start_iter(), textbuffer.get_end_iter(), True) if self.exist_cover_image: image_buffer = self._get_preview_image_buffer() journal_entry.metadata['preview'] = dbus.ByteArray(image_buffer) image_buffer = self._get_cover_image_buffer() journal_entry.metadata['cover_image'] = \ dbus.ByteArray(base64.b64encode(image_buffer)) else: journal_entry.metadata['cover_image'] = "" journal_entry.metadata['tags'] = self.source journal_entry.metadata['source'] = self.source journal_entry.metadata['author'] = self.selected_author journal_entry.metadata['publisher'] = self.selected_publisher journal_entry.metadata['summary'] = self.selected_summary journal_entry.metadata['language'] = self.selected_language_code journal_entry.file_path = path datastore.write(journal_entry) os.remove(path) self.progress_hide() self._object_id = journal_entry.object_id self._show_journal_alert(_('Download completed'), self.selected_title) def _show_journal_alert(self, title, msg): _stop_alert = Alert() _stop_alert.props.title = title _stop_alert.props.msg = msg if _HAS_BUNDLE_LAUNCHER: bundle = get_bundle(object_id=self._object_id) if bundle is not None: icon = Icon(file=bundle.get_icon()) label = _('Open with %s') % bundle.get_name() _stop_alert.add_button(Gtk.ResponseType.ACCEPT, label, icon) else: icon = Icon(icon_name='zoom-activity') label = _('Show in Journal') _stop_alert.add_button(Gtk.ResponseType.APPLY, label, icon) icon.show() ok_icon = Icon(icon_name='dialog-ok') _stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(_stop_alert) _stop_alert.connect('response', self.__stop_response_cb) _stop_alert.show() def __stop_response_cb(self, alert, response_id): if response_id is Gtk.ResponseType.APPLY: activity.show_object_in_journal(self._object_id) elif response_id is Gtk.ResponseType.ACCEPT: launch_bundle(object_id=self._object_id) self.remove_alert(alert) def _get_preview_image_buffer(self): preview_width, preview_height = style.zoom(300), style.zoom(225) pixbuf = self.image.get_pixbuf() width, height = pixbuf.get_width(), pixbuf.get_height() scale = 1 if (width > preview_width) or (height > preview_height): scale_x = preview_width / float(width) scale_y = preview_height / float(height) scale = min(scale_x, scale_y) pixbuf2 = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, pixbuf.get_has_alpha(), pixbuf.get_bits_per_sample(), preview_width, preview_height) pixbuf2.fill(style.COLOR_WHITE.get_int()) margin_x = int((preview_width - (width * scale)) / 2) margin_y = int((preview_height - (height * scale)) / 2) pixbuf.scale(pixbuf2, margin_x, margin_y, preview_width - (margin_x * 2), preview_height - (margin_y * 2), margin_x, margin_y, scale, scale, GdkPixbuf.InterpType.BILINEAR) succes, data = pixbuf2.save_to_bufferv('png', [], []) return data def _get_cover_image_buffer(self): pixbuf = self.image.get_pixbuf() succes, data = pixbuf.save_to_bufferv('png', [], []) return data def _show_error_alert(self, title, text=None): alert = NotifyAlert(timeout=20) 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) self.textview.grab_focus() def get_entrys_info(self, query): books = [] for key in _MIMETYPES.keys(): books.extend(self.get_entry_info_format(query, _MIMETYPES[key])) return books def get_entry_info_format(self, query, mime): books = [] if query is not None and len(query) > 0: ds_objects, num_objects = datastore.find( {'mime_type': '%s' % mime, 'query': '*%s*' % query}) else: ds_objects, num_objects = datastore.find( {'mime_type': '%s' % mime}) logging.error('Local search %d books found %s format', num_objects, mime) for i in range(0, num_objects): entry = {} entry['title'] = ds_objects[i].metadata['title'] entry['mime'] = ds_objects[i].metadata['mime_type'] entry['object_id'] = ds_objects[i].object_id if 'author' in ds_objects[i].metadata: entry['author'] = ds_objects[i].metadata['author'] else: entry['author'] = '' if 'publisher' in ds_objects[i].metadata: entry['dcterms_publisher'] = \ ds_objects[i].metadata['publisher'] else: entry['dcterms_publisher'] = '' if 'language' in ds_objects[i].metadata: entry['dcterms_language'] = \ ds_objects[i].metadata['language'] else: entry['dcterms_language'] = '' if 'source' in ds_objects[i].metadata: entry['source'] = \ ds_objects[i].metadata['source'] else: entry['source'] = '' if entry['source'] in _SOURCES_CONFIG: repo_configuration = _SOURCES_CONFIG[entry['source']] summary_field = repo_configuration['summary_field'] if 'summary' in ds_objects[i].metadata: entry[summary_field] = ds_objects[i].metadata['summary'] else: entry[summary_field] = '' else: repo_configuration = None books.append(opds.Book(repo_configuration, entry, '')) return books def close(self, skip_save=False): "Override the close method so we don't try to create a Journal entry." activity.Activity.close(self, True) def save(self): pass
class SimplePianoActivity(activity.Activity): """SimplePianoActivity class as specified in activity.info""" def __init__(self, handle): activity.Activity.__init__(self, handle) GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.close) Gst.init(None) self._what_list = [] self.play_recording_thread = None self.playing_recording = False self.firstTime = False self.playing = False self.regularity = 0.7 self._drums_store = [] self.recording = False self.recorded_keys = [] self.is_valid_recording = False # we do not have collaboration features # make the share option insensitive self.max_participants = 1 self.csnd = new_csound_client() self.rythmInstrument = 'drum1kick' # toolbar with the new toolbar redesign toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) toolbar_box.toolbar.set_style(Gtk.ToolbarStyle.BOTH_HORIZ) self.play_index = 0 self.play_recording_button = ToolButton( icon_name='media-playback-start') self.play_recording_button.set_property('can-default', True) self.play_recording_button.show() self.record_button = ToggleToolButton(icon_name='media-record') self.record_button.set_property('can-default', True) self.record_button.show() self.play_recording_button.set_sensitive(False) self.record_button.connect('clicked', self.__record_button_click_cb) self.play_recording_button.connect('clicked', self.handlePlayRecordingButton) toolbar_box.toolbar.set_style(Gtk.ToolbarStyle.BOTH_HORIZ) # TODO: disabe until is implemented with csnd6 # self.createPercussionToolbar(toolbar_box) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) keybord_labels = RadioToolButton() keybord_labels.props.icon_name = 'q_key' keybord_labels.props.group = keybord_labels keybord_labels.connect('clicked', self.set_keyboard_labels_cb) toolbar_box.toolbar.insert(keybord_labels, -1) notes_labels = RadioToolButton() notes_labels.props.icon_name = 'do_key' notes_labels.props.group = keybord_labels notes_labels.connect('clicked', self.set_notes_labels_cb) toolbar_box.toolbar.insert(notes_labels, -1) ti_notes_labels = RadioToolButton() ti_notes_labels.props.icon_name = 'ti_key' ti_notes_labels.props.group = keybord_labels ti_notes_labels.connect('clicked', self.set_ti_notes_labels_cb) toolbar_box.toolbar.insert(ti_notes_labels, -1) german_labels = RadioToolButton() german_labels.props.icon_name = 'c_key' german_labels.props.group = keybord_labels german_labels.connect('clicked', self.set_german_labels_cb) toolbar_box.toolbar.insert(german_labels, -1) no_labels = RadioToolButton() no_labels.props.icon_name = 'edit-clear' no_labels.props.group = keybord_labels no_labels.connect('clicked', self.set_keyboard_no_labels_cb) toolbar_box.toolbar.insert(no_labels, -1) self._what_widget = Gtk.ToolItem() self._what_search_button = FilterToolItem(_('Select Instrument'), 'view-type', _('Piano'), self._what_widget) self._what_widget.show() toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_box.toolbar.insert(self._what_search_button, -1) self._what_search_button.show() self._what_search_button.set_is_important(True) self._what_widget_contents = None self._what_drum_widget_contents = None separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) toolbar_box.toolbar.insert(self.record_button, -1) toolbar_box.toolbar.insert(self.play_recording_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) stop_button.show() self._save_as_audio_bt = ToolButton(icon_name='save-as-audio') self._save_as_audio_bt.props.tooltip = _('Save as audio') self._save_as_audio_bt.connect('clicked', self._save_ogg_cb) self._save_as_audio_bt.show() self._save_as_audio_bt.set_sensitive(False) activity_button.page.insert(self._save_as_audio_bt, -1) self.set_toolbar_box(toolbar_box) toolbar_box.show_all() self.keyboard_letters = ['ZSXDCVGBHNJM', 'Q2W3ER5T6Y7U', 'I'] notes = [ 'DO', ['DO#', 'REb'], 'RE', ['RE#', 'MIb'], 'MI', 'FA', ['FA#', 'SOLb'], 'SOL', ['SOL#', 'LAb'], 'LA', ['LA#', 'SIb'], 'SI' ] self.notes_labels = [notes, notes, ['DO']] # some countries use TI instead of SI ti_notes = [ 'DO', ['DO#', 'REb'], 'RE', ['RE#', 'MIb'], 'MI', 'FA', ['FA#', 'SOLb'], 'SOL', ['SOL#', 'LAb'], 'LA', ['LA#', 'TIb'], 'TI' ] self.ti_notes_labels = [ti_notes, ti_notes, ['DO']] german_notes = [ 'C', ['C#', 'Db'], 'D', ['D#', 'Eb'], 'E', 'F', ['F#', 'Gb'], 'G', ['G#', 'Ab'], 'A', ['A#', 'Bb'], 'B' ] self.german_labels = [german_notes, german_notes, ['C']] self.piano = PianoKeyboard(octaves=2, add_c=True, labels=self.keyboard_letters) # init csound self.instrumentDB = InstrumentDB.getRef() self.timeout_ms = 50 self.instVolume = 50 self.drumVolume = 0.5 self.instrument = 'piano' self.beat = 4 self.reverb = 0.1 self.tempo = PLAYER_TEMPO self.beatDuration = 60.0 / self.tempo self.ticksPerSecond = Config.TICKS_PER_BEAT * self.tempo / 60.0 self.sequencer = MiniSequencer(self.recordStateButton, self.recordOverSensitivity) self.loop = Loop(self.beat, math.sqrt(self.instVolume * 0.01)) self.drumFillin = Fillin(self.beat, self.tempo, self.rythmInstrument, self.reverb, self.drumVolume) self.muteInst = False self.csnd.setTempo(self.tempo) self.noteList = [] for i in range(21): self.csnd.setTrackVolume(100, i) # TODO commented because apparently are not used in the activity # for i in range(10): # self.csnd.load_instrument('guidice' + str(i + 1)) self.volume = 100 self.csnd.setMasterVolume(self.volume) self.enableKeyboard() self.setInstrument(self.instrument) self.connect('key-press-event', self.onKeyPress) self.connect('key-release-event', self.onKeyRelease) self.piano.connect('key_pressed', self.__key_pressed_cb) self.piano.connect('key_released', self.__key_released_cb) vbox = Gtk.VBox() vbox.set_homogeneous(False) self.load_instruments() self._event_box = Gtk.EventBox() self._event_box.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) vbox.pack_start(self._event_box, False, False, 0) vbox.pack_end(self.piano, True, True, 0) vbox.show_all() self.set_canvas(vbox) piano_height = Gdk.Screen.width() / 2 self._event_box.set_size_request( -1, Gdk.Screen.height() - piano_height - style.GRID_CELL_SIZE) self.connect('size-allocate', self.__allocate_cb) # TODO: disabe until is implemented with csnd6 # GLib.idle_add(self.initializePercussion) 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 initializePercussion(self): self.rythmInstrument = 'drum1kit' self.csnd.load_drumkit(self.rythmInstrument) self.csnd.setTempo(self.tempo) self.beatPickup = False def flatten(ll): rval = [] for l in ll: rval += l return rval noteOnsets = [] notePitchs = [] i = 0 self.noteList = [] self.csnd.loopClear() for x in flatten( generator(self.rythmInstrument, self.beat, 0.8, self.regularity, self.reverb)): x.amplitude = x.amplitude * self.drumVolume noteOnsets.append(x.onset) notePitchs.append(x.pitch) n = Note(0, x.trackId, i, x) self.noteList.append((x.onset, n)) i = i + 1 self.csnd.loopPlay(n, 1) # add as active self.csnd.loopSetNumTicks(self.beat * Config.TICKS_PER_BEAT) self.drumFillin.unavailable(noteOnsets, notePitchs) if self.playing: self.csnd.loopStart() def __allocate_cb(self, widget, rect): GLib.idle_add(self.resize, rect.width, rect.height) return False def resize(self, width, height): logging.debug('activity.py resize......') piano_height = width / 2 self._event_box.set_size_request( -1, Gdk.Screen.height() - piano_height - style.GRID_CELL_SIZE) return False def load_instruments(self): self._instruments_store = [] # load the images images_path = os.path.join(activity.get_bundle_path(), 'instruments') logging.debug('Loading instrument images from %s', images_path) for file_name in os.listdir(images_path): image_file_name = os.path.join(images_path, file_name) pxb = GdkPixbuf.Pixbuf.new_from_file_at_size( image_file_name, 75, 75) # instrument_name = image_file_name[image_file_name.rfind('/'):] instrument_name = image_file_name[image_file_name.rfind('/') + 1:] instrument_name = instrument_name[:instrument_name.find('.')] instrument_desc = \ self.instrumentDB.instNamed[instrument_name].nameTooltip file_path = os.path.join(images_path, file_name) # set the default icon if (instrument_name == 'piano'): self._what_search_button.set_widget_icon(file_name=file_path) self._instruments_store.append({ "instrument_name": instrument_name, "pxb": pxb, "instrument_desc": instrument_desc, "file_name": file_path, "callback": self.__instrument_iconview_activated_cb }) self._what_widget_contents = set_palette_list(self._instruments_store) self._what_widget.add(self._what_widget_contents) self._what_widget_contents.show() # TODO: disabe until is implemented with csnd6 """ for drum_number in range(0, DRUMCOUNT): drum_name = 'drum%dkit' % (drum_number + 1) self._drums_store.append({ "instrument_name": drum_name, "file_name": imagefile(drum_name + '.svg'), "instrument_desc": self.instrumentDB.instNamed[drum_name].nameTooltip, "callback": self.__drum_iconview_activated_cb }) self._what_drum_widget_contents = set_palette_list(self._drums_store) self._what_drum_widget.add(self._what_drum_widget_contents) self._what_drum_widget_contents.show() """ def __drum_iconview_activated_cb(self, widget, event, item): data = item['instrument_name'] self.rythmInstrument = data self.csnd.load_drumkit(data) instrumentId = self.instrumentDB.instNamed[data].instrumentId for (o, n) in self.noteList: self.csnd.loopUpdate(n, NoteDB.PARAMETER.INSTRUMENT, instrumentId, -1) self.drumFillin.setInstrument(self.rythmInstrument) self._what_drum_search_button.set_widget_label( label=item['instrument_desc']) self._what_drum_search_button.set_widget_icon( file_name=item['file_name']) def __instrument_iconview_activated_cb(self, widget, event, item): self.setInstrument(item['instrument_name']) self._what_search_button.set_widget_icon(file_name=item['file_name']) self._what_search_button.set_widget_label( label=item['instrument_desc']) def set_notes_labels_cb(self, widget): self.piano.font_size = 16 self.piano.set_labels(self.notes_labels) def set_ti_notes_labels_cb(self, widget): self.piano.font_size = 16 self.piano.set_labels(self.ti_notes_labels) def set_keyboard_labels_cb(self, widget): self.piano.font_size = 25 self.piano.set_labels(self.keyboard_letters) def set_german_labels_cb(self, widget): self.piano.font_size = 25 self.piano.set_labels(self.german_labels) def beatSliderChange(self, widget, event): self.beat = int(self.beats_pm_button.get_value()) self.sequencer.beat = self.beat self.loop.beat = self.beat self.drumFillin.setBeats(self.beat) img = int(self.scale(self.beat, 2, 12, 1, 11)) self.beats_pm_button.set_image(imagefile('beat' + str(img) + '.svg')) self.beatPickup = False self.regenerate() self.beatPickup = True def regenerate(self): def flatten(ll): rval = [] for l in ll: rval += l return rval noteOnsets = [] notePitchs = [] i = 0 self.noteList = [] self.csnd.loopClear() for x in flatten( generator(self.rythmInstrument, self.beat, 0.8, self.regularity, self.reverb)): x.amplitude = x.amplitude * self.drumVolume noteOnsets.append(x.onset) notePitchs.append(x.pitch) n = Note(0, x.trackId, i, x) self.noteList.append((x.onset, n)) i = i + 1 self.csnd.loopPlay(n, 1) # add as active self.csnd.loopSetNumTicks(self.beat * Config.TICKS_PER_BEAT) self.drumFillin.unavailable(noteOnsets, notePitchs) self.recordOverSensitivity(False) if self.playing: self.csnd.loopStart() def handlePlayRecordingButton(self, val): if not self.playing_recording: self.playing_recording = True self.play_recording_button.props.icon_name = 'media-playback-stop' self.play_recording_thread = \ GLib.timeout_add(100, self._play_recorded_keys) else: self.playing_recording = False self.play_recording_button.props.icon_name = 'media-playback-start' def _save_ogg_cb(self, widget): self._wav_tempfile = tempfile.NamedTemporaryFile(mode='w+b', suffix='.wav', dir='/tmp/') self.csnd.inputMessage(Config.CSOUND_RECORD_PERF % self._wav_tempfile.name) self.playing_recording = True self.play_recording_thread = \ GLib.timeout_add(100, self._play_recorded_keys, self._save_ogg_end_cb) def _save_ogg_end_cb(self): self.csnd.inputMessage(Config.CSOUND_STOP_RECORD_PERF % self._wav_tempfile.name) self._ogg_tempfile = tempfile.NamedTemporaryFile(mode='w+b', suffix='.ogg', dir='/tmp/') line = 'filesrc location=%s ! ' \ 'wavparse ! audioconvert ! vorbisenc ! oggmux ! ' \ 'filesink location=%s' % (self._wav_tempfile.name, self._ogg_tempfile.name) pipe = Gst.parse_launch(line) pipe.get_bus().add_signal_watch() pipe.get_bus().connect('message::eos', self._save_ogg_eos_cb, pipe) pipe.set_state(Gst.State.PLAYING) def _save_ogg_eos_cb(self, bus, message, pipe): bus.remove_signal_watch() pipe.set_state(Gst.State.NULL) title = '%s saved as audio' % self.metadata['title'] jobject = datastore.create() jobject.metadata['title'] = title jobject.metadata['keep'] = '0' jobject.metadata['mime_type'] = 'audio/ogg' jobject.file_path = self._ogg_tempfile.name datastore.write(jobject) self._wav_tempfile.close() self._ogg_tempfile.close() alert = NotifyAlert(10) alert.props.title = _('Audio recorded') alert.props.msg = _('The audio file was saved in the Journal') alert.connect('response', self.__alert_response_cb) self.add_alert(alert) return False def __alert_response_cb(self, alert, result): self.remove_alert(alert) def __record_button_click_cb(self, button): if not self.recording: self.play_recording_button.set_sensitive(False) self._save_as_audio_bt.set_sensitive(False) self.recorded_keys = [] self.recording = True icon = Icon(icon_name='media-record', fill_color='#ff0000') icon.show() self.record_button.set_icon_widget(icon) else: self.recording = False icon = Icon(icon_name='media-record', fill_color='#ffffff') icon.show() self.record_button.set_icon_widget(icon) if len(self.recorded_keys) != 0: self.play_recording_button.set_sensitive(True) self._save_as_audio_bt.set_sensitive(True) def tempoSliderChange(self, widget, event): self._updateTempo(self.tempo_button.get_value()) img = int( self.scale(self.tempo, PLAYER_TEMPO_LOWER, PLAYER_TEMPO_UPPER, 1, 9)) self.tempo_button.set_image(imagefile('tempo' + str(img) + '.png')) def _updateTempo(self, val): self.tempo = val self.beatDuration = 60.0 / self.tempo self.ticksPerSecond = Config.TICKS_PER_BEAT * self.tempo / 60.0 self.csnd.setTempo(self.tempo) self.sequencer.tempo = self.tempo self.drumFillin.setTempo(self.tempo) def handlePlayButton(self, val): if not self.playing: if not self.firstTime: self.regenerate() self.firstTime = True self.drumFillin.play() self.csnd.loopSetTick(0) self.csnd.loopStart() self.playing = True self._play_percussion_btn.props.icon_name = 'media-playback-stop' else: self.drumFillin.stop() self.sequencer.stopPlayback() self.csnd.loopPause() self.playing = False self._play_percussion_btn.props.icon_name = 'media-playback-start' def scale(self, input, input_min, input_max, output_min, output_max): range_input = input_max - input_min range_output = output_max - output_min result = (input - input_min) * range_output / range_input + output_min if (input_min > input_max and output_min > output_max) or \ (output_min > output_max and input_min < input_max): if result > output_min: return output_min elif result < output_max: return output_max else: return result if (input_min < input_max and output_min < output_max) or \ (output_min < output_max and input_min > input_max): if result > output_max: return output_max elif result < output_min: return output_min else: return result def handleComplexityChange(self, widget, event): self.regularity = self.complexity_button.get_value() img = int(self.complexity_button.get_value() * 7) + 1 self.complexity_button.set_image( imagefile('complex' + str(img) + '.svg')) self.beatPickup = False self.regenerate() self.beatPickup = True """ def handleBalanceSlider(self, adj): self.instVolume = int(adj.get_value()) self.drumVolume = sqrt( (100-self.instVolume)*0.01 ) self.adjustDrumVolume() self.drumFillin.setVolume(self.drumVolume) instrumentVolume = sqrt( self.instVolume*0.01 ) self.loop.adjustLoopVolume(instrumentVolume) self.sequencer.adjustSequencerVolume(instrumentVolume) img = int(self.scale(self.instVolume,100,0,0,4.9)) self._playToolbar.balanceSliderImgLeft.set_from_file( imagefile('dru' + str(img) + '.png')) img2 = int(self.scale(self.instVolume,0,100,0,4.9)) self._playToolbar.balanceSliderImgRight.set_from_file( imagefile('instr' + str(img2) + '.png')) def handleReverbSlider(self, adj): self.reverb = adj.get_value() self.drumFillin.setReverb( self.reverb ) img = int(self.scale(self.reverb,0,1,0,4)) self._playToolbar.reverbSliderImgRight.set_from_file( imagefile('reverb' + str(img) + '.png')) self.keyboardStandAlone.setReverb(self.reverb) """ def set_keyboard_no_labels_cb(self, widget): self.piano.font_size = 25 self.piano.set_labels(None) def enableKeyboard(self): self.keyboardStandAlone = KeyboardStandAlone( self.sequencer.recording, self.sequencer.adjustDuration, self.csnd.loopGetTick, self.sequencer.getPlayState, self.loop) self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) def setInstrument(self, instrument): logging.debug("Set Instrument: %s" % instrument) self.instrument = instrument self.keyboardStandAlone.setInstrument(instrument) self.csnd.load_instrument(instrument) def recordStateButton(self, button, state): pass # if button == 1: # self._recordToolbar.keyboardRecButton.set_active( state ) # else: # self._recordToolbar.keyboardRecOverButton.set_active( state ) def recordOverSensitivity(self, state): pass # self._recordToolbar.keyboardRecOverButton.set_sensitive( state ) def _play_recorded_keys(self, end_cb=None): GLib.source_remove(self.play_recording_thread) letter = self.recorded_keys[self.play_index] time_difference = 0 if self.play_index == len(self.recorded_keys) - 1: time_difference = \ self.recorded_keys[self.play_index][0] - \ self.recorded_keys[self.play_index - 1][0] else: next_time = self.recorded_keys[self.play_index + 1][0] time_difference = next_time - letter[0] if not self.playing_recording: self.play_recording_button.props.icon_name = 'media-playback-start' return if letter[-1] == 1: self.keyboardStandAlone.do_key_release( LETTERS_TO_KEY_CODES[letter[3]]) GLib.idle_add(self.piano.physical_key_changed, LETTERS_TO_KEY_CODES[letter[3]], False) else: self.keyboardStandAlone.do_key_press( LETTERS_TO_KEY_CODES[letter[3]], None, math.sqrt(self.instVolume * 0.01)) GLib.idle_add(self.piano.physical_key_changed, LETTERS_TO_KEY_CODES[letter[3]], True) if self.play_index == len(self.recorded_keys) - 1: self.play_index = 0 self.play_recording_button.props.icon_name = 'media-playback-start' self.playing_recording = False if end_cb is not None: end_cb() else: self.play_index += 1 self.play_recording_thread = \ GLib.timeout_add(int((time_difference) * 1000), self._play_recorded_keys, end_cb) def __key_pressed_cb(self, widget, octave_clicked, key_clicked, letter, physicallKey): logging.debug('Pressed Octave: %d Key: %d Letter: %s' % (octave_clicked, key_clicked, letter)) if letter in LETTERS_TO_KEY_CODES.keys(): if self.recording: self.recorded_keys.append( [time.time(), octave_clicked, key_clicked, letter]) if not physicallKey: self.keyboardStandAlone.do_key_press( LETTERS_TO_KEY_CODES[letter], None, math.sqrt(self.instVolume * 0.01)) def __key_released_cb(self, widget, octave_clicked, key_clicked, letter, physicallKey): if self.recording: self.recorded_keys.append( [time.time(), octave_clicked, key_clicked, letter, 1]) if not physicallKey: if letter in LETTERS_TO_KEY_CODES.keys(): self.keyboardStandAlone.do_key_release( LETTERS_TO_KEY_CODES[letter]) def onKeyPress(self, widget, event): if event.state & Gdk.ModifierType.CONTROL_MASK: return if event.hardware_keycode == 37: if self.muteInst: self.muteInst = False else: self.muteInst = True self.piano.physical_key_changed(event.hardware_keycode, True) self.keyboardStandAlone.onKeyPress(widget, event, math.sqrt(self.instVolume * 0.01)) def onKeyRelease(self, widget, event): self.keyboardStandAlone.onKeyRelease(widget, event) self.piano.physical_key_changed(event.hardware_keycode, False) def write_file(self, file_path): f = open(file_path, 'w') # substract the initial time to all the saved values if len(self.recorded_keys) > 0: initial_time = self.recorded_keys[0][0] for key in self.recorded_keys: key[0] = key[0] - initial_time f.write(json.dumps(self.recorded_keys)) f.close() def read_file(self, file_path): f = open(file_path, 'r') contents = f.read().strip() self.recorded_keys = json.loads(contents) if len(self.recorded_keys) != 0: self.play_recording_button.set_sensitive(True) self._save_as_audio_bt.set_sensitive(True) f.close() def close(self, skip_save=False): self.csnd.stop() # without which Csound will segfault activity.Activity.close(self, skip_save=skip_save)
class SpeechToolbar(Gtk.Toolbar): def __init__(self, activity): GObject.GObject.__init__(self) self._activity = activity if not speech.supported: return self.is_paused = False self.load_speech_parameters() self.sorted_voices = [i for i in speech.voices()] self.sorted_voices.sort(self.compare_voices) default = 0 for voice in self.sorted_voices: if voice[0] == speech.voice[0]: break default = default + 1 # Play button self.play_btn = ToggleToolButton('media-playback-start') self.play_btn.show() self.play_toggled_handler = self.play_btn.connect( 'toggled', self.play_cb) self.insert(self.play_btn, -1) self.play_btn.set_tooltip(_('Play / Pause')) # Stop button self.stop_btn = ToolButton('media-playback-stop') self.stop_btn.show() self.stop_btn.connect('clicked', self.stop_cb) self.stop_btn.set_sensitive(False) self.insert(self.stop_btn, -1) self.stop_btn.set_tooltip(_('Stop')) self.voice_combo = ComboBox() for voice in self.sorted_voices: self.voice_combo.append_item(voice, voice[0]) self.voice_combo.set_active(default) self.voice_combo.connect('changed', self.voice_changed_cb) combotool = ToolComboBox(self.voice_combo) self.insert(combotool, -1) combotool.show() speech.reset_cb = self.reset_buttons_cb speech.end_text_cb = self.reset_buttons_cb def compare_voices(self, a, b): if a[0].lower() == b[0].lower(): return 0 if a[0].lower() < b[0].lower(): return -1 if a[0].lower() > b[0].lower(): return 1 def voice_changed_cb(self, combo): speech.voice = combo.props.value speech.say(speech.voice[0]) self.save_speech_parameters() def load_speech_parameters(self): speech_parameters = {} data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') if os.path.exists(data_file_name): f = open(data_file_name, 'r') try: speech_parameters = json.load(f) speech.voice = speech_parameters['voice'] finally: f.close() def save_speech_parameters(self): speech_parameters = {} speech_parameters['voice'] = speech.voice data_path = os.path.join(self._activity.get_activity_root(), 'data') data_file_name = os.path.join(data_path, 'speech_params.json') f = open(data_file_name, 'w') try: json.dump(speech_parameters, f) finally: f.close() def reset_buttons_cb(self): logging.error('reset buttons') self.play_btn.set_icon_name('media-playback-start') self.stop_btn.set_sensitive(False) self.play_btn.handler_block(self.play_toggled_handler) self.play_btn.set_active(False) self.play_btn.handler_unblock(self.play_toggled_handler) self.is_paused = False def play_cb(self, widget): self.stop_btn.set_sensitive(True) if widget.get_active(): self.play_btn.set_icon_name('media-playback-pause') logging.error('Paused %s', self.is_paused) if not self.is_paused: # get the text to speech, if there are a selection, # play selected text, if not, play all abi = self._activity.abiword_canvas selection = abi.get_selection('text/plain') if not selection or selection[0] is None or selection[1] == 0: # nothing selected abi.select_all() text = abi.get_selection('text/plain')[0] abi.moveto_bod() else: text = selection[0] speech.play(text) else: logging.error('Continue play') speech.continue_play() else: self.play_btn.set_icon_name('media-playback-start') self.is_paused = True speech.pause() def stop_cb(self, widget): self.stop_btn.set_sensitive(False) self.play_btn.set_icon_name('media-playback-start') self.play_btn.set_active(False) self.is_paused = False speech.stop()
class ViewToolbar(Gtk.Toolbar): __gtype_name__ = 'ViewToolbar' __gsignals__ = { 'go-fullscreen': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([])), 'toggle-index-show': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([bool])), 'toggle-tray-show': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([bool])), } def __init__(self): Gtk.Toolbar.__init__(self) self._view = None self._navigator_button = ToggleToolButton('view-list') self._navigator_button.set_tooltip(_('Table of contents')) self._navigator_button.connect('toggled', self.__navigator_toggled_cb) self.insert(self._navigator_button, -1) self._spacer_navigator = Gtk.SeparatorToolItem() self._spacer_navigator.props.draw = False self.insert(self._spacer_navigator, -1) self._zoom_out = ToolButton('zoom-out') self._zoom_out.set_tooltip(_('Zoom out')) self._zoom_out.connect('clicked', self._zoom_out_cb) self.insert(self._zoom_out, -1) self._zoom_out.show() self._zoom_in = ToolButton('zoom-in') self._zoom_in.set_tooltip(_('Zoom in')) self._zoom_in.connect('clicked', self._zoom_in_cb) self.insert(self._zoom_in, -1) self._zoom_in.show() self._zoom_to_width = ToolButton('zoom-to-width') self._zoom_to_width.set_tooltip(_('Zoom to width')) self._zoom_to_width.connect('clicked', self._zoom_to_width_cb) self.insert(self._zoom_to_width, -1) self._zoom_to_width.show() self._zoom_to_fit = ToolButton('zoom-best-fit') self._zoom_to_fit.set_tooltip(_('Zoom to fit')) self._zoom_to_fit.connect('clicked', self._zoom_to_fit_cb) self.insert(self._zoom_to_fit, -1) self._zoom_to_fit.show() self._zoom_to_original = ToolButton('zoom-original') self._zoom_to_original.set_tooltip(_('Actual size')) self._zoom_to_original.connect('clicked', self._actual_size_cb) self.insert(self._zoom_to_original, -1) self._zoom_to_original.show() spacer = Gtk.SeparatorToolItem() spacer.props.draw = True self.insert(spacer, -1) spacer.show() self._fullscreen = ToolButton('view-fullscreen') self._fullscreen.set_tooltip(_('Fullscreen')) self._fullscreen.connect('clicked', self._fullscreen_cb) self.insert(self._fullscreen, -1) self._fullscreen.show() self.traybutton = ToggleToolButton('tray-show') self.traybutton.set_icon_name('tray-favourite') self.traybutton.connect('toggled', self.__tray_toggled_cb) self.traybutton.props.active = False self.insert(self.traybutton, -1) self.traybutton.show() self._view_notify_zoom_handler = None spacer = Gtk.SeparatorToolItem() spacer.props.draw = True self.insert(spacer, -1) spacer.show() self._rotate_left = ToolButton('rotate_anticlockwise') self._rotate_left.set_tooltip(_('Rotate left')) self._rotate_left.connect('clicked', self._rotate_left_cb) self.insert(self._rotate_left, -1) self._rotate_left.show() self._rotate_right = ToolButton('rotate_clockwise') self._rotate_right.set_tooltip(_('Rotate right')) self._rotate_right.connect('clicked', self._rotate_right_cb) self.insert(self._rotate_right, -1) self._rotate_right.show() def set_view(self, view): self._view = view self._update_zoom_buttons() def show_nav_button(self): self._navigator_button.show() self._spacer_navigator.show() def zoom_in(self): self._view.zoom_in() self._update_zoom_buttons() def _zoom_in_cb(self, button): self.zoom_in() def _rotate_left_cb(self, button): self._view.rotate_left() def _rotate_right_cb(self, button): self._view.rotate_right() def zoom_out(self): self._view.zoom_out() self._update_zoom_buttons() def _zoom_out_cb(self, button): self.zoom_out() def zoom_to_width(self): self._view.zoom_to_width() self._update_zoom_buttons() def _zoom_to_width_cb(self, button): self.zoom_to_width() def __navigator_toggled_cb(self, button): self.emit('toggle-index-show', button.get_active()) def _update_zoom_buttons(self): self._zoom_in.props.sensitive = self._view.can_zoom_in() self._zoom_out.props.sensitive = self._view.can_zoom_out() self._zoom_to_width.props.sensitive = self._view.can_zoom_to_width() self._zoom_to_fit.props.sensitive = self._view.can_zoom_to_width() self._zoom_to_original.props.sensitive = self._view.can_zoom_to_width() self._rotate_left.props.sensitive = self._view.can_rotate() self._rotate_right.props.sensitive = self._view.can_rotate() def _zoom_to_fit_cb(self, menu_item): self._view.zoom_to_best_fit() self._update_zoom_buttons() def _actual_size_cb(self, menu_item): self._view.zoom_to_actual_size() self._update_zoom_buttons() def _fullscreen_cb(self, button): self.emit('go-fullscreen') def __tray_toggled_cb(self, button): self.emit('toggle-tray-show', button.get_active()) if button.props.active: self.traybutton.set_tooltip(_('Show Tray')) else: self.traybutton.set_tooltip(_('Hide Tray'))
class MemorizeActivity(Activity): def __init__(self, handle): Activity.__init__(self, handle) self.play_mode = None toolbar_box = ToolbarBox() self.set_toolbar_box(toolbar_box) self.activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(self.activity_button, -1) self._memorizeToolbarBuilder = \ memorizetoolbar.MemorizeToolbarBuilder(self) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) self._edit_button = ToggleToolButton('view-source') self._edit_button.set_tooltip(_('Edit game')) self._edit_button.set_active(False) toolbar_box.toolbar.insert(self._edit_button, -1) self._createToolbarBuilder = \ createtoolbar.CreateToolbarBuilder(self) separator = Gtk.SeparatorToolItem() separator.set_expand(True) separator.set_draw(False) separator.set_size_request(0, -1) toolbar_box.toolbar.insert(separator, -1) toolbar_box.toolbar.insert(StopButton(self), -1) self.game = game.MemorizeGame() # Play game mode self.table = cardtable.CardTable() self.scoreboard = scoreboard.Scoreboard() self.cardlist = cardlist.CardList() self.createcardpanel = createcardpanel.CreateCardPanel(self.game) self.cardlist.connect('pair-selected', self.createcardpanel.pair_selected) self.cardlist.connect( 'update-create-toolbar', self._createToolbarBuilder.update_create_toolbar) self.createcardpanel.connect('add-pair', self.cardlist.add_pair) self.createcardpanel.connect('update-pair', self.cardlist.update_selected) self.createcardpanel.connect('change-font', self.cardlist.change_font) self.createcardpanel.connect('pair-closed', self.cardlist.rem_current_pair) self._createToolbarBuilder.connect('create_new_game', self.cardlist.clean_list) self._createToolbarBuilder.connect('create_new_game', self.createcardpanel.clean) self._createToolbarBuilder.connect( 'create_new_game', self._memorizeToolbarBuilder.reset) self._createToolbarBuilder.connect('create_equal_pairs', self.change_equal_pairs) self._edit_button.connect('toggled', self._change_mode_bt) self.connect('key-press-event', self.table.key_press_event) self.table.connect('card-flipped', self.game.card_flipped) self.table.connect('card-highlighted', self.game.card_highlighted) self.game.connect('set-border', self.table.set_border) self.game.connect('flop-card', self.table.flop_card) self.game.connect('flip-card', self.table.flip_card) self.game.connect('cement-card', self.table.cement_card) self.game.connect('highlight-card', self.table.highlight_card) self.game.connect('load_mode', self.table.load_msg) self.game.connect('msg_buddy', self.scoreboard.set_buddy_message) self.game.connect('add_buddy', self.scoreboard.add_buddy) self.game.connect('rem_buddy', self.scoreboard.rem_buddy) self.game.connect('increase-score', self.scoreboard.increase_score) self.game.connect('wait_mode_buddy', self.scoreboard.set_wait_mode) self.game.connect('change-turn', self.scoreboard.set_selected) self.game.connect('change_game', self.scoreboard.change_game) self.game.connect('reset_scoreboard', self.scoreboard.reset) self.game.connect('reset_table', self.table.reset) self.game.connect('load_game', self.table.load_game) self.game.connect('change_game', self.table.change_game) self.game.connect('load_game', self._memorizeToolbarBuilder.update_toolbar) self.game.connect('change_game', self._memorizeToolbarBuilder.update_toolbar) self.game.connect('change_game', self.createcardpanel.update_font_combos) self._memorizeToolbarBuilder.connect('game_changed', self.change_game) self.box = Gtk.HBox(orientation=Gtk.Orientation.VERTICAL, homogeneous=False) width = Gdk.Screen.width() height = Gdk.Screen.height() - style.GRID_CELL_SIZE self.table.resize(width, height - style.GRID_CELL_SIZE) self.scoreboard.set_size_request(-1, style.GRID_CELL_SIZE) self.box.pack_start(self.table, True, True, 0) self.box.pack_start(self.scoreboard, False, False, 0) self.set_canvas(self.box) # connect to the in/out events of the memorize activity self.connect('focus_in_event', self._focus_in) self.connect('focus_out_event', self._focus_out) self.connect('destroy', self._cleanup_cb) self.add_events(Gdk.EventMask.POINTER_MOTION_MASK) self.connect('motion_notify_event', lambda widget, event: face.look_at()) Gdk.Screen.get_default().connect('size-changed', self.__configure_cb) # start on the game toolbar, might change this # to the create toolbar later self._change_mode(_MODE_PLAY) # Get the Presence Service self.pservice = presenceservice.get_instance() self.initiating = None # Buddy object for you owner = self.pservice.get_owner() self.owner = owner self.current = 0 self.game.set_myself(self.owner) self.connect('shared', self._shared_cb) # Owner.props.key if self.get_shared_activity(): # We are joining the activity self.connect('joined', self._joined_cb) if self.get_shared(): # We've already joined self._joined_cb(self) elif not self._jobject.file_path: logging.debug('buddy joined - __init__: %s', self.owner.props.nick) game_file = os.path.join(os.path.dirname(__file__), 'demos', 'addition.zip') self.game.load_game(game_file, 4, 'demo') logging.debug('loading conventional') self.game.add_buddy(self.owner) else: self.game.add_buddy(self.owner) self.show_all() def __configure_cb(self, event): ''' Screen size has changed ''' width = Gdk.Screen.width() height = Gdk.Screen.height() - style.GRID_CELL_SIZE self.box.set_size_request(width, height) self.scoreboard.set_size_request(-1, style.GRID_CELL_SIZE) self.table.resize(width, height - style.GRID_CELL_SIZE) self.show_all() def _change_mode_bt(self, button): if button.get_active(): self._change_mode(_MODE_CREATE) button.set_icon_name('player_play') button.set_tooltip(_('Play game')) else: self._change_mode(_MODE_PLAY) button.set_icon_name('view-source') button.set_tooltip(_('Edit game')) def read_file(self, file_path): if 'icon-color' in self.metadata: color = self.metadata['icon-color'] else: color = profile.get_color().to_string() self.change_game(None, file_path, 4, 'file', self.metadata['title'], color) def write_file(self, file_path): logging.debug('WRITE_FILE is_demo %s', self.game.model.is_demo) if self.game.model.is_demo: # if is a demo game only want keep the metadata self._jobject.set_file_path(None) raise NotImplementedError return if self.cardlist.pair_list_modified: self.cardlist.update_model(self.game.model) temp_img_folder = self.game.model.data['pathimg'] temp_snd_folder = self.game.model.data['pathsnd'] self.game.model.create_temp_directories() game_zip = zipfile.ZipFile(file_path, 'w') save_image_and_sound = True if 'origin' in self.game.model.data: if self.game.model.data['origin'] == 'art4apps': # we don't need save images and audio files # for art4apps games save_image_and_sound = False if save_image_and_sound: for pair in self.game.model.pairs: # aimg aimg = self.game.model.pairs[pair].get_property('aimg') logging.error('saving image a %s', aimg) if aimg is not None: game_zip.write(os.path.join(temp_img_folder, aimg), os.path.join('images', aimg)) # bimg bimg = self.game.model.pairs[pair].get_property('bimg') logging.error('saving image b %s', bimg) if bimg is not None: game_zip.write(os.path.join(temp_img_folder, bimg), os.path.join('images', bimg)) # asnd asnd = self.game.model.pairs[pair].get_property('asnd') if asnd is not None: if os.path.exists(os.path.join(temp_snd_folder, asnd)): game_zip.write(os.path.join(temp_snd_folder, asnd), os.path.join('sounds', asnd)) # bsnd bsnd = self.game.model.pairs[pair].get_property('bsnd') if bsnd is not None: if os.path.exists(os.path.join(temp_snd_folder, bsnd)): game_zip.write(os.path.join(temp_snd_folder, bsnd), os.path.join('sounds', bsnd)) self.game.model.game_path = self.game.model.temp_folder self.game.model.data['name'] = str(self.get_title()) self.game.model.write() game_zip.write(os.path.join(self.game.model.temp_folder, 'game.xml'), 'game.xml') game_zip.close() self.metadata['mime_type'] = 'application/x-memorize-project' def _complete_close(self): self._remove_temp_files() Activity._complete_close(self) def _remove_temp_files(self): tmp_root = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'], 'instance') for root, dirs, files in os.walk(tmp_root, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) def _change_mode(self, mode): logging.debug("Change mode %s" % mode) if mode == _MODE_CREATE: if self.play_mode: self.box.remove(self.scoreboard) self.box.remove(self.table) self.createcardpanel.update_orientation() self.box.pack_start(self.createcardpanel, True, True, 0) self.box.pack_start(self.cardlist, False, False, 0) self.cardlist.load_game(self.game) self.game.model.create_temp_directories() self.createcardpanel.set_temp_folder( self.game.model.temp_folder) self.play_mode = False else: if self.game.model.modified: self.cardlist.update_model(self.game.model) self.save() self.game.reset_game() self.table.change_game(None, self.game.model.data, self.game.model.grid) self.game.model.modified = False if not self.play_mode: self.box.remove(self.createcardpanel) self.box.remove(self.cardlist) if self.play_mode in (False, None): self.box.pack_start(self.table, True, True, 0) self.box.pack_start(self.scoreboard, False, False, 0) self.play_mode = True self._memorizeToolbarBuilder.update_controls(mode == _MODE_PLAY) self._createToolbarBuilder.update_controls(mode == _MODE_CREATE) def change_game(self, widget, game_name, size, mode, title=None, color=None): logging.debug('Change game %s', game_name) self.game.change_game(widget, game_name, size, mode, title, color) self.cardlist.game_loaded = False def change_equal_pairs(self, widget, state): self.cardlist.update_model(self.game.model) self.createcardpanel.change_equal_pairs(widget, state) def _shared_cb(self, activity): logging.debug('My activity was shared') self.initiating = True self._sharing_setup() logging.debug('This is my activity: making a tube...') self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _sharing_setup(self): if self.get_shared_activity() is None: logging.error('Failed to share or join activity') return shared_activity = self.get_shared_activity() self.conn = shared_activity.telepathy_conn self.tubes_chan = shared_activity.telepathy_tubes_chan self.text_chan = shared_activity.telepathy_text_chan self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) shared_activity.connect('buddy-joined', self._buddy_joined_cb) shared_activity.connect('buddy-left', self._buddy_left_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): logging.error('ListTubes() failed: %s', e) def _joined_cb(self, activity): if not self.get_shared_activity(): return logging.debug('Joined an existing shared activity') for buddy in self.get_shared_activity().get_joined_buddies(): if buddy != self.owner: logging.debug("buddy joined - _joined_cb: %s " "(get buddies and add them to my list)", buddy.props.nick) self.game.add_buddy(buddy) self.game.add_buddy(self.owner) self.initiating = False self._sharing_setup() logging.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, tube_type, service, params, state): logging.debug('New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', identifier, initiator, tube_type, service, params, state) if (tube_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]) self.messenger = messenger.Messenger(self.tube_conn, self.initiating, self._get_buddy, self.game) self.game.connect('flip-card-signal', self.messenger.flip_sender) self.game.connect('change_game_signal', self.messenger.change_game) def _get_buddy(self, cs_handle): """Get a Buddy from a channel specific handle.""" group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] my_csh = group.GetSelfHandle() if my_csh == cs_handle: handle = self.conn.GetSelfHandle() else: handle = group.GetHandleOwners([cs_handle])[0] assert handle != 0 return self.pservice.get_buddy_by_telepathy_handle( self.tp_conn_name, self.tp_conn_path, handle) def _buddy_joined_cb(self, activity, buddy): if buddy != self.owner: if buddy.props.nick == '': logging.debug("buddy joined: empty nick=%s. Will not add.", buddy.props.nick) else: logging.debug("buddy joined: %s", buddy.props.nick) self.game.add_buddy(buddy) def _buddy_left_cb(self, activity, buddy): if buddy.props.nick == '': logging.debug("buddy joined: empty nick=%s. Will not remove", buddy.props.nick) else: logging.debug("buddy left: %s", buddy.props.nick) self.game.rem_buddy(buddy) def _focus_in(self, event, data=None): self.game.audio.play() def _focus_out(self, event, data=None): self.game.audio.pause() def _cleanup_cb(self, data=None): self.game.audio.stop()
class MainToolbox(ToolbarBox): __gsignals__ = { 'query-changed': (GObject.SignalFlags.RUN_FIRST, None, ([object])), } def __init__(self): ToolbarBox.__init__(self) self._mount_point = None self._filter_type = None self._what_filter = None self.search_entry = iconentry.IconEntry() self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'entry-search') text = _('Search in %s') % _('Journal') self.search_entry.set_placeholder_text(text) self.search_entry.connect('activate', self._search_entry_activated_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self.search_entry.add_clear_button() self._autosearch_timer = None self._add_widget(self.search_entry, expand=True) self._favorite_button = ToggleToolButton('emblem-favorite') self._favorite_button.set_tooltip(_('Favorite entries')) self._favorite_button.connect('toggled', self.__favorite_button_toggled_cb) self.toolbar.insert(self._favorite_button, -1) self._favorite_button.show() self._what_search_combo = ComboBox() self._what_combo_changed_sid = self._what_search_combo.connect( 'changed', self._combo_changed_cb) tool_item = ToolComboBox(self._what_search_combo) self.toolbar.insert(tool_item, -1) tool_item.show() self._when_search_combo = self._get_when_search_combo() tool_item = ToolComboBox(self._when_search_combo) self.toolbar.insert(tool_item, -1) tool_item.show() self._sorting_button = SortingButton() self.toolbar.insert(self._sorting_button, -1) self._sorting_button.connect('sort-property-changed', self.__sort_changed_cb) self._sorting_button.show() # TODO: enable it when the DS supports saving the buddies. # self._with_search_combo = self._get_with_search_combo() # tool_item = ToolComboBox(self._with_search_combo) # self.insert(tool_item, -1) # tool_item.show() self._query = self._build_query() self.refresh_filters() def _get_when_search_combo(self): when_search = ComboBox() when_search.append_item(_ACTION_ANYTIME, _('Anytime')) when_search.append_separator() when_search.append_item(_ACTION_TODAY, _('Today')) when_search.append_item(_ACTION_SINCE_YESTERDAY, _('Since yesterday')) # TRANS: Filter entries modified during the last 7 days. when_search.append_item(_ACTION_PAST_WEEK, _('Past week')) # TRANS: Filter entries modified during the last 30 days. when_search.append_item(_ACTION_PAST_MONTH, _('Past month')) # TRANS: Filter entries modified during the last 356 days. when_search.append_item(_ACTION_PAST_YEAR, _('Past year')) when_search.set_active(0) when_search.connect('changed', self._combo_changed_cb) return when_search def _get_with_search_combo(self): with_search = ComboBox() with_search.append_item(_ACTION_EVERYBODY, _('Anyone')) with_search.append_separator() with_search.append_item(_ACTION_MY_FRIENDS, _('My friends')) with_search.append_item(_ACTION_MY_CLASS, _('My class')) with_search.append_separator() # TODO: Ask the model for buddies. with_search.append_item(3, 'Dan', 'theme:xo') with_search.set_active(0) with_search.connect('changed', self._combo_changed_cb) return with_search def _add_widget(self, widget, expand=False): tool_item = Gtk.ToolItem() tool_item.set_expand(expand) tool_item.add(widget) widget.show() self.toolbar.insert(tool_item, -1) tool_item.show() def _build_query(self): query = {} if self._mount_point: query['mountpoints'] = [self._mount_point] if self._favorite_button.props.active: query['keep'] = 1 if self._what_search_combo.props.value: value = self._what_search_combo.props.value filter_type = self._filter_type if self._filter_type is None: # for backward compatibility, try to guess the filter generic_type = mime.get_generic_type(value) if generic_type: filter_type = FILTER_TYPE_GENERIC_MIME else: filter_type = FILTER_TYPE_ACTIVITY logging.error('DEPRECATED: sety the filter_type parameter') if filter_type == FILTER_TYPE_GENERIC_MIME: generic_type = mime.get_generic_type(value) if generic_type: mime_types = generic_type.mime_types query['mime_type'] = mime_types else: logging.error('filter_type="generic_mime", ' 'but "%s" is not a generic mime' % value) elif filter_type == FILTER_TYPE_ACTIVITY: query['activity'] = value elif self._filter_type == FILTER_TYPE_MIME_BY_ACTIVITY: registry = bundleregistry.get_registry() bundle = \ registry.get_bundle(value) if bundle is not None: query['mime_type'] = bundle.get_mime_types() else: logging.error('Trying to filter using activity mimetype ' 'but bundle id is wrong %s' % value) if self._when_search_combo.props.value: date_from, date_to = self._get_date_range() query['timestamp'] = {'start': date_from, 'end': date_to} if self.search_entry.props.text: text = self.search_entry.props.text.strip() if text: query['query'] = text property_, order = self._sorting_button.get_current_sort() if order == Gtk.SortType.ASCENDING: sign = '+' else: sign = '-' query['order_by'] = [sign + property_] return query def _get_date_range(self): today_start = datetime.today().replace(hour=0, minute=0, second=0) right_now = datetime.today() if self._when_search_combo.props.value == _ACTION_TODAY: date_range = (today_start, right_now) elif self._when_search_combo.props.value == _ACTION_SINCE_YESTERDAY: date_range = (today_start - timedelta(1), right_now) elif self._when_search_combo.props.value == _ACTION_PAST_WEEK: date_range = (today_start - timedelta(7), right_now) elif self._when_search_combo.props.value == _ACTION_PAST_MONTH: date_range = (today_start - timedelta(30), right_now) elif self._when_search_combo.props.value == _ACTION_PAST_YEAR: date_range = (today_start - timedelta(356), right_now) return (time.mktime(date_range[0].timetuple()), time.mktime(date_range[1].timetuple())) def _combo_changed_cb(self, combo): self._update_if_needed() def __sort_changed_cb(self, button): self._update_if_needed() def _update_if_needed(self): # check if the what_search combo should be visible self._what_search_combo.set_visible( self._filter_type != FILTER_TYPE_MIME_BY_ACTIVITY) new_query = self._build_query() if self._query != new_query: self._query = new_query self.emit('query-changed', self._query) def _search_entry_activated_cb(self, search_entry): if self._autosearch_timer: GObject.source_remove(self._autosearch_timer) self._update_if_needed() def _search_entry_changed_cb(self, search_entry): if not search_entry.props.text: search_entry.activate() return if self._autosearch_timer: GObject.source_remove(self._autosearch_timer) self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT, self._autosearch_timer_cb) def _autosearch_timer_cb(self): logging.debug('_autosearch_timer_cb') self._autosearch_timer = None self.search_entry.activate() return False def set_mount_point(self, mount_point): self._mount_point = mount_point self._update_if_needed() def set_what_filter(self, what_filter): combo_model = self._what_search_combo.get_model() what_filter_index = -1 for i in range(0, len(combo_model) - 1): if combo_model[i][0] == what_filter: what_filter_index = i break if what_filter_index == -1: logging.warning('what_filter %r not known', what_filter) else: self._what_search_combo.set_active(what_filter_index) def update_filters(self, mount_point, what_filter, filter_type=None): self._mount_point = mount_point self._filter_type = filter_type self._what_filter = what_filter self.set_what_filter(what_filter) self._update_if_needed() def set_filter_type(self, filter_type): self._filter_type = filter_type self._update_if_needed() def refresh_filters(self): current_value = self._what_search_combo.props.value current_value_index = 0 self._what_search_combo.handler_block(self._what_combo_changed_sid) try: self._what_search_combo.remove_all() # TRANS: Item in a combo box that filters by entry type. self._what_search_combo.append_item(_ACTION_ANYTHING, _('Anything')) registry = bundleregistry.get_registry() appended_separator = False types = mime.get_all_generic_types() for generic_type in types: if not appended_separator: self._what_search_combo.append_separator() appended_separator = True self._what_search_combo.append_item( generic_type.type_id, generic_type.name, generic_type.icon) if generic_type.type_id == current_value: current_value_index = \ len(self._what_search_combo.get_model()) - 1 self._what_search_combo.set_active(current_value_index) self._what_search_combo.append_separator() for service_name in model.get_unique_values('activity'): activity_info = registry.get_bundle(service_name) if activity_info is None: continue if service_name == current_value: combo_model = self._what_search_combo.get_model() current_value_index = len(combo_model) # try activity-provided icon if os.path.exists(activity_info.get_icon()): try: self._what_search_combo.append_item( service_name, activity_info.get_name(), file_name=activity_info.get_icon()) except GObject.GError, exception: logging.warning('Falling back to default icon for' ' "what" filter because %r (%r) has an' ' invalid icon: %s', activity_info.get_name(), str(service_name), exception) else: continue # fall back to generic icon self._what_search_combo.append_item( service_name, activity_info.get_name(), icon_name='application-octet-stream') finally: self._what_search_combo.handler_unblock( self._what_combo_changed_sid) def __favorite_button_toggled_cb(self, favorite_button): self._update_if_needed() def clear_query(self): self.search_entry.props.text = '' if self._what_filter is None: self._what_search_combo.set_active(0) else: self.set_what_filter(self._what_filter) self._when_search_combo.set_active(0) self._favorite_button.props.active = False
class SimplePianoActivity(activity.Activity): """SimplePianoActivity class as specified in activity.info""" def __init__(self, handle): activity.Activity.__init__(self, handle) GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.close) Gst.init(None) self._what_list = [] self.play_recording_thread = None self.playing_recording = False self.firstTime = False self.playing = False self.regularity = 0.7 self._drums_store = [] self.recording = False self.recorded_keys = [] self.is_valid_recording = False # we do not have collaboration features # make the share option insensitive self.max_participants = 1 self.csnd = new_csound_client() self.rythmInstrument = 'drum1kick' # toolbar with the new toolbar redesign toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) toolbar_box.toolbar.set_style(Gtk.ToolbarStyle.BOTH_HORIZ) self.play_index = 0 self.play_recording_button = ToolButton( icon_name='media-playback-start') self.play_recording_button.set_property('can-default', True) self.play_recording_button.show() self.record_button = ToggleToolButton(icon_name='media-record') self.record_button.set_property('can-default', True) self.record_button.show() self.play_recording_button.set_sensitive(False) self.record_button.connect('clicked', self.__record_button_click_cb) self.play_recording_button.connect('clicked', self.handlePlayRecordingButton) toolbar_box.toolbar.set_style(Gtk.ToolbarStyle.BOTH_HORIZ) # TODO: disabe until is implemented with csnd6 # self.createPercussionToolbar(toolbar_box) toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) keybord_labels = RadioToolButton() keybord_labels.props.icon_name = 'q_key' keybord_labels.props.group = keybord_labels keybord_labels.connect('clicked', self.set_keyboard_labels_cb) toolbar_box.toolbar.insert(keybord_labels, -1) notes_labels = RadioToolButton() notes_labels.props.icon_name = 'do_key' notes_labels.props.group = keybord_labels notes_labels.connect('clicked', self.set_notes_labels_cb) toolbar_box.toolbar.insert(notes_labels, -1) ti_notes_labels = RadioToolButton() ti_notes_labels.props.icon_name = 'ti_key' ti_notes_labels.props.group = keybord_labels ti_notes_labels.connect('clicked', self.set_ti_notes_labels_cb) toolbar_box.toolbar.insert(ti_notes_labels, -1) german_labels = RadioToolButton() german_labels.props.icon_name = 'c_key' german_labels.props.group = keybord_labels german_labels.connect('clicked', self.set_german_labels_cb) toolbar_box.toolbar.insert(german_labels, -1) no_labels = RadioToolButton() no_labels.props.icon_name = 'edit-clear' no_labels.props.group = keybord_labels no_labels.connect('clicked', self.set_keyboard_no_labels_cb) toolbar_box.toolbar.insert(no_labels, -1) self._what_widget = Gtk.ToolItem() self._what_search_button = FilterToolItem(_('Select Instrument'), 'view-type', _('Piano'), self._what_widget) self._what_widget.show() toolbar_box.toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_box.toolbar.insert(self._what_search_button, -1) self._what_search_button.show() self._what_search_button.set_is_important(True) self._what_widget_contents = None self._what_drum_widget_contents = None separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) toolbar_box.toolbar.insert(self.record_button, -1) toolbar_box.toolbar.insert(self.play_recording_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) stop_button.show() self._save_as_audio_bt = ToolButton(icon_name='save-as-audio') self._save_as_audio_bt.props.tooltip = _('Save as audio') self._save_as_audio_bt.connect('clicked', self._save_ogg_cb) self._save_as_audio_bt.show() self._save_as_audio_bt.set_sensitive(False) activity_button.page.insert(self._save_as_audio_bt, -1) self.set_toolbar_box(toolbar_box) toolbar_box.show_all() self.keyboard_letters = ['ZSXDCVGBHNJM', 'Q2W3ER5T6Y7U', 'I'] notes = ['DO', ['DO#', 'REb'], 'RE', ['RE#', 'MIb'], 'MI', 'FA', ['FA#', 'SOLb'], 'SOL', ['SOL#', 'LAb'], 'LA', ['LA#', 'SIb'], 'SI'] self.notes_labels = [notes, notes, ['DO']] # some countries use TI instead of SI ti_notes = ['DO', ['DO#', 'REb'], 'RE', ['RE#', 'MIb'], 'MI', 'FA', ['FA#', 'SOLb'], 'SOL', ['SOL#', 'LAb'], 'LA', ['LA#', 'TIb'], 'TI'] self.ti_notes_labels = [ti_notes, ti_notes, ['DO']] german_notes = ['C', ['C#', 'Db'], 'D', ['D#', 'Eb'], 'E', 'F', ['F#', 'Gb'], 'G', ['G#', 'Ab'], 'A', ['A#', 'Bb'], 'B'] self.german_labels = [german_notes, german_notes, ['C']] self.piano = PianoKeyboard(octaves=2, add_c=True, labels=self.keyboard_letters) # init csound self.instrumentDB = InstrumentDB.getRef() self.timeout_ms = 50 self.instVolume = 50 self.drumVolume = 0.5 self.instrument = 'piano' self.beat = 4 self.reverb = 0.1 self.tempo = PLAYER_TEMPO self.beatDuration = 60.0 / self.tempo self.ticksPerSecond = Config.TICKS_PER_BEAT * self.tempo / 60.0 self.sequencer = MiniSequencer(self.recordStateButton, self.recordOverSensitivity) self.loop = Loop(self.beat, math.sqrt(self.instVolume * 0.01)) self.drumFillin = Fillin(self.beat, self.tempo, self.rythmInstrument, self.reverb, self.drumVolume) self.muteInst = False self.csnd.setTempo(self.tempo) self.noteList = [] for i in range(21): self.csnd.setTrackVolume(100, i) # TODO commented because apparently are not used in the activity # for i in range(10): # self.csnd.load_instrument('guidice' + str(i + 1)) self.volume = 100 self.csnd.setMasterVolume(self.volume) self.enableKeyboard() self.setInstrument(self.instrument) self.connect('key-press-event', self.onKeyPress) self.connect('key-release-event', self.onKeyRelease) self.piano.connect('key_pressed', self.__key_pressed_cb) self.piano.connect('key_released', self.__key_released_cb) vbox = Gtk.VBox() vbox.set_homogeneous(False) self.load_instruments() self._event_box = Gtk.EventBox() self._event_box.modify_bg( Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) vbox.pack_start(self._event_box, False, False, 0) vbox.pack_end(self.piano, True, True, 0) vbox.show_all() self.set_canvas(vbox) piano_height = Gdk.Screen.width() / 2 self._event_box.set_size_request( -1, Gdk.Screen.height() - piano_height - style.GRID_CELL_SIZE) self.connect('size-allocate', self.__allocate_cb) # TODO: disabe until is implemented with csnd6 # GLib.idle_add(self.initializePercussion) 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 initializePercussion(self): self.rythmInstrument = 'drum1kit' self.csnd.load_drumkit(self.rythmInstrument) self.csnd.setTempo(self.tempo) self.beatPickup = False def flatten(ll): rval = [] for l in ll: rval += l return rval noteOnsets = [] notePitchs = [] i = 0 self.noteList = [] self.csnd.loopClear() for x in flatten( generator(self.rythmInstrument, self.beat, 0.8, self.regularity, self.reverb)): x.amplitude = x.amplitude * self.drumVolume noteOnsets.append(x.onset) notePitchs.append(x.pitch) n = Note(0, x.trackId, i, x) self.noteList.append((x.onset, n)) i = i + 1 self.csnd.loopPlay(n, 1) # add as active self.csnd.loopSetNumTicks(self.beat * Config.TICKS_PER_BEAT) self.drumFillin.unavailable(noteOnsets, notePitchs) if self.playing: self.csnd.loopStart() def __allocate_cb(self, widget, rect): GLib.idle_add(self.resize, rect.width, rect.height) return False def resize(self, width, height): logging.debug('activity.py resize......') piano_height = width / 2 self._event_box.set_size_request( -1, Gdk.Screen.height() - piano_height - style.GRID_CELL_SIZE) return False def load_instruments(self): self._instruments_store = [] # load the images images_path = os.path.join(activity.get_bundle_path(), 'instruments') logging.debug('Loading instrument images from %s', images_path) for file_name in os.listdir(images_path): image_file_name = os.path.join(images_path, file_name) pxb = GdkPixbuf.Pixbuf.new_from_file_at_size( image_file_name, 75, 75) # instrument_name = image_file_name[image_file_name.rfind('/'):] instrument_name = image_file_name[image_file_name.rfind('/') + 1:] instrument_name = instrument_name[:instrument_name.find('.')] instrument_desc = \ self.instrumentDB.instNamed[instrument_name].nameTooltip file_path = os.path.join(images_path, file_name) # set the default icon if (instrument_name == 'piano'): self._what_search_button.set_widget_icon( file_name=file_path) self._instruments_store.append( {"instrument_name": instrument_name, "pxb": pxb, "instrument_desc": instrument_desc, "file_name": file_path, "callback": self.__instrument_iconview_activated_cb}) self._what_widget_contents = set_palette_list(self._instruments_store) self._what_widget.add(self._what_widget_contents) self._what_widget_contents.show() # TODO: disabe until is implemented with csnd6 """ for drum_number in range(0, DRUMCOUNT): drum_name = 'drum%dkit' % (drum_number + 1) self._drums_store.append({ "instrument_name": drum_name, "file_name": imagefile(drum_name + '.svg'), "instrument_desc": self.instrumentDB.instNamed[drum_name].nameTooltip, "callback": self.__drum_iconview_activated_cb }) self._what_drum_widget_contents = set_palette_list(self._drums_store) self._what_drum_widget.add(self._what_drum_widget_contents) self._what_drum_widget_contents.show() """ def __drum_iconview_activated_cb(self, widget, event, item): data = item['instrument_name'] self.rythmInstrument = data self.csnd.load_drumkit(data) instrumentId = self.instrumentDB.instNamed[data].instrumentId for (o, n) in self.noteList: self.csnd.loopUpdate(n, NoteDB.PARAMETER.INSTRUMENT, instrumentId, -1) self.drumFillin.setInstrument(self.rythmInstrument) self._what_drum_search_button.set_widget_label( label=item['instrument_desc']) self._what_drum_search_button.set_widget_icon( file_name=item['file_name']) def __instrument_iconview_activated_cb(self, widget, event, item): self.setInstrument(item['instrument_name']) self._what_search_button.set_widget_icon(file_name=item['file_name']) self._what_search_button.set_widget_label( label=item['instrument_desc']) def set_notes_labels_cb(self, widget): self.piano.font_size = 16 self.piano.set_labels(self.notes_labels) def set_ti_notes_labels_cb(self, widget): self.piano.font_size = 16 self.piano.set_labels(self.ti_notes_labels) def set_keyboard_labels_cb(self, widget): self.piano.font_size = 25 self.piano.set_labels(self.keyboard_letters) def set_german_labels_cb(self, widget): self.piano.font_size = 25 self.piano.set_labels(self.german_labels) def beatSliderChange(self, widget, event): self.beat = int(self.beats_pm_button.get_value()) self.sequencer.beat = self.beat self.loop.beat = self.beat self.drumFillin.setBeats(self.beat) img = int(self.scale(self.beat, 2, 12, 1, 11)) self.beats_pm_button.set_image(imagefile('beat' + str(img) + '.svg')) self.beatPickup = False self.regenerate() self.beatPickup = True def regenerate(self): def flatten(ll): rval = [] for l in ll: rval += l return rval noteOnsets = [] notePitchs = [] i = 0 self.noteList = [] self.csnd.loopClear() for x in flatten( generator(self.rythmInstrument, self.beat, 0.8, self.regularity, self.reverb)): x.amplitude = x.amplitude * self.drumVolume noteOnsets.append(x.onset) notePitchs.append(x.pitch) n = Note(0, x.trackId, i, x) self.noteList.append((x.onset, n)) i = i + 1 self.csnd.loopPlay(n, 1) # add as active self.csnd.loopSetNumTicks(self.beat * Config.TICKS_PER_BEAT) self.drumFillin.unavailable(noteOnsets, notePitchs) self.recordOverSensitivity(False) if self.playing: self.csnd.loopStart() def handlePlayRecordingButton(self, val): if not self.playing_recording: self.playing_recording = True self.play_recording_button.props.icon_name = 'media-playback-stop' self.play_recording_thread = \ GLib.timeout_add(100, self._play_recorded_keys) else: self.playing_recording = False self.play_recording_button.props.icon_name = 'media-playback-start' def _save_ogg_cb(self, widget): self._wav_tempfile = tempfile.NamedTemporaryFile( mode='w+b', suffix='.wav', dir='/tmp/') self.csnd.inputMessage(Config.CSOUND_RECORD_PERF % self._wav_tempfile.name) self.playing_recording = True self.play_recording_thread = \ GLib.timeout_add(100, self._play_recorded_keys, self._save_ogg_end_cb) def _save_ogg_end_cb(self): self.csnd.inputMessage(Config.CSOUND_STOP_RECORD_PERF % self._wav_tempfile.name) self._ogg_tempfile = tempfile.NamedTemporaryFile( mode='w+b', suffix='.ogg', dir='/tmp/') line = 'filesrc location=%s ! ' \ 'wavparse ! audioconvert ! vorbisenc ! oggmux ! ' \ 'filesink location=%s' % (self._wav_tempfile.name, self._ogg_tempfile.name) pipe = Gst.parse_launch(line) pipe.get_bus().add_signal_watch() pipe.get_bus().connect('message::eos', self._save_ogg_eos_cb, pipe) pipe.set_state(Gst.State.PLAYING) def _save_ogg_eos_cb(self, bus, message, pipe): bus.remove_signal_watch() pipe.set_state(Gst.State.NULL) title = '%s saved as audio' % self.metadata['title'] jobject = datastore.create() jobject.metadata['title'] = title jobject.metadata['keep'] = '0' jobject.metadata['mime_type'] = 'audio/ogg' jobject.file_path = self._ogg_tempfile.name datastore.write(jobject) self._wav_tempfile.close() self._ogg_tempfile.close() alert = NotifyAlert(10) alert.props.title = _('Audio recorded') alert.props.msg = _('The audio file was saved in the Journal') alert.connect('response', self.__alert_response_cb) self.add_alert(alert) return False def __alert_response_cb(self, alert, result): self.remove_alert(alert) def __record_button_click_cb(self, button): if not self.recording: self.play_recording_button.set_sensitive(False) self._save_as_audio_bt.set_sensitive(False) self.recorded_keys = [] self.recording = True icon = Icon(icon_name='media-record', fill_color='#ff0000') icon.show() self.record_button.set_icon_widget(icon) else: self.recording = False icon = Icon(icon_name='media-record', fill_color='#ffffff') icon.show() self.record_button.set_icon_widget(icon) if len(self.recorded_keys) != 0: self.play_recording_button.set_sensitive(True) self._save_as_audio_bt.set_sensitive(True) def tempoSliderChange(self, widget, event): self._updateTempo(self.tempo_button.get_value()) img = int(self.scale(self.tempo, PLAYER_TEMPO_LOWER, PLAYER_TEMPO_UPPER, 1, 9)) self.tempo_button.set_image(imagefile('tempo' + str(img) + '.png')) def _updateTempo(self, val): self.tempo = val self.beatDuration = 60.0 / self.tempo self.ticksPerSecond = Config.TICKS_PER_BEAT * self.tempo / 60.0 self.csnd.setTempo(self.tempo) self.sequencer.tempo = self.tempo self.drumFillin.setTempo(self.tempo) def handlePlayButton(self, val): if not self.playing: if not self.firstTime: self.regenerate() self.firstTime = True self.drumFillin.play() self.csnd.loopSetTick(0) self.csnd.loopStart() self.playing = True self._play_percussion_btn.props.icon_name = 'media-playback-stop' else: self.drumFillin.stop() self.sequencer.stopPlayback() self.csnd.loopPause() self.playing = False self._play_percussion_btn.props.icon_name = 'media-playback-start' def scale(self, input, input_min, input_max, output_min, output_max): range_input = input_max - input_min range_output = output_max - output_min result = (input - input_min) * range_output / range_input + output_min if (input_min > input_max and output_min > output_max) or \ (output_min > output_max and input_min < input_max): if result > output_min: return output_min elif result < output_max: return output_max else: return result if (input_min < input_max and output_min < output_max) or \ (output_min < output_max and input_min > input_max): if result > output_max: return output_max elif result < output_min: return output_min else: return result def handleComplexityChange(self, widget, event): self.regularity = self.complexity_button.get_value() img = int(self.complexity_button.get_value() * 7) + 1 self.complexity_button.set_image( imagefile('complex' + str(img) + '.svg')) self.beatPickup = False self.regenerate() self.beatPickup = True """ def handleBalanceSlider(self, adj): self.instVolume = int(adj.get_value()) self.drumVolume = sqrt( (100-self.instVolume)*0.01 ) self.adjustDrumVolume() self.drumFillin.setVolume(self.drumVolume) instrumentVolume = sqrt( self.instVolume*0.01 ) self.loop.adjustLoopVolume(instrumentVolume) self.sequencer.adjustSequencerVolume(instrumentVolume) img = int(self.scale(self.instVolume,100,0,0,4.9)) self._playToolbar.balanceSliderImgLeft.set_from_file( imagefile('dru' + str(img) + '.png')) img2 = int(self.scale(self.instVolume,0,100,0,4.9)) self._playToolbar.balanceSliderImgRight.set_from_file( imagefile('instr' + str(img2) + '.png')) def handleReverbSlider(self, adj): self.reverb = adj.get_value() self.drumFillin.setReverb( self.reverb ) img = int(self.scale(self.reverb,0,1,0,4)) self._playToolbar.reverbSliderImgRight.set_from_file( imagefile('reverb' + str(img) + '.png')) self.keyboardStandAlone.setReverb(self.reverb) """ def set_keyboard_no_labels_cb(self, widget): self.piano.font_size = 25 self.piano.set_labels(None) def enableKeyboard(self): self.keyboardStandAlone = KeyboardStandAlone( self.sequencer.recording, self.sequencer.adjustDuration, self.csnd.loopGetTick, self.sequencer.getPlayState, self.loop) self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) def setInstrument(self, instrument): logging.debug("Set Instrument: %s" % instrument) self.instrument = instrument self.keyboardStandAlone.setInstrument(instrument) self.csnd.load_instrument(instrument) def recordStateButton(self, button, state): pass # if button == 1: # self._recordToolbar.keyboardRecButton.set_active( state ) # else: # self._recordToolbar.keyboardRecOverButton.set_active( state ) def recordOverSensitivity(self, state): pass # self._recordToolbar.keyboardRecOverButton.set_sensitive( state ) def _play_recorded_keys(self, end_cb=None): GLib.source_remove(self.play_recording_thread) letter = self.recorded_keys[self.play_index] time_difference = 0 if self.play_index == len(self.recorded_keys) - 1: time_difference = \ self.recorded_keys[self.play_index][0] - \ self.recorded_keys[self.play_index - 1][0] else: next_time = self.recorded_keys[self.play_index + 1][0] time_difference = next_time - letter[0] if not self.playing_recording: self.play_recording_button.props.icon_name = 'media-playback-start' return if letter[-1] == 1: self.keyboardStandAlone.do_key_release( LETTERS_TO_KEY_CODES[letter[3]]) GLib.idle_add(self.piano.physical_key_changed, LETTERS_TO_KEY_CODES[letter[3]], False) else: self.keyboardStandAlone.do_key_press( LETTERS_TO_KEY_CODES[letter[3]], None, math.sqrt(self.instVolume * 0.01)) GLib.idle_add(self.piano.physical_key_changed, LETTERS_TO_KEY_CODES[letter[3]], True) if self.play_index == len(self.recorded_keys) - 1: self.play_index = 0 self.play_recording_button.props.icon_name = 'media-playback-start' self.playing_recording = False if end_cb is not None: end_cb() else: self.play_index += 1 self.play_recording_thread = \ GLib.timeout_add(int((time_difference) * 1000), self._play_recorded_keys, end_cb) def __key_pressed_cb(self, widget, octave_clicked, key_clicked, letter, physicallKey): logging.debug( 'Pressed Octave: %d Key: %d Letter: %s' % (octave_clicked, key_clicked, letter)) if letter in LETTERS_TO_KEY_CODES.keys(): if self.recording: self.recorded_keys.append( [time.time(), octave_clicked, key_clicked, letter]) if not physicallKey: self.keyboardStandAlone.do_key_press( LETTERS_TO_KEY_CODES[letter], None, math.sqrt(self.instVolume * 0.01)) def __key_released_cb(self, widget, octave_clicked, key_clicked, letter, physicallKey): if self.recording: self.recorded_keys.append( [time.time(), octave_clicked, key_clicked, letter, 1]) if not physicallKey: if letter in LETTERS_TO_KEY_CODES.keys(): self.keyboardStandAlone.do_key_release( LETTERS_TO_KEY_CODES[letter]) def onKeyPress(self, widget, event): if event.state & Gdk.ModifierType.CONTROL_MASK: return if event.hardware_keycode == 37: if self.muteInst: self.muteInst = False else: self.muteInst = True self.piano.physical_key_changed(event.hardware_keycode, True) self.keyboardStandAlone.onKeyPress( widget, event, math.sqrt(self.instVolume * 0.01)) def onKeyRelease(self, widget, event): self.keyboardStandAlone.onKeyRelease(widget, event) self.piano.physical_key_changed(event.hardware_keycode, False) def write_file(self, file_path): f = open(file_path, 'w') # substract the initial time to all the saved values if len(self.recorded_keys) > 0: initial_time = self.recorded_keys[0][0] for key in self.recorded_keys: key[0] = key[0] - initial_time f.write(json.dumps(self.recorded_keys)) f.close() def read_file(self, file_path): f = open(file_path, 'r') contents = f.read().strip() self.recorded_keys = json.loads(contents) if len(self.recorded_keys) != 0: self.play_recording_button.set_sensitive(True) self._save_as_audio_bt.set_sensitive(True) f.close() def close(self, skip_save=False): self.csnd.stop() # without which Csound will segfault activity.Activity.close(self, skip_save=skip_save)
class SpeechToolbar(Gtk.Toolbar): def __init__(self): Gtk.Toolbar.__init__(self) self.activity = None self._speech = SpeechManager() self._voices = self._speech.get_all_voices() # a dictionary locale = os.environ.get('LANG', '') language_location = locale.split('.', 1)[0].lower() language = language_location.split('_')[0] # if the language is es but not es_es default to es_la (latin voice) if language == 'es' and language_location != 'es_es': language_location = 'es_la' self._voice = 'en_us' if language_location in self._voices: self._voice = language_location elif language in self._voices: self._voice = language voice_names = [] for language, name in self._voices.items(): voice_names.append((language, name)) voice_names.sort() # Play button Image play_img = Gtk.Image() play_img.show() play_img.set_from_icon_name('media-playback-start', Gtk.IconSize.LARGE_TOOLBAR) # Pause button Image pause_img = Gtk.Image() pause_img.show() pause_img.set_from_icon_name('media-playback-pause', Gtk.IconSize.LARGE_TOOLBAR) # Play button self.play_button = ToggleToolButton('media-playback-start') self.play_button.show() self.play_button.connect('toggled', self._play_toggled_cb, [play_img, pause_img]) self.insert(self.play_button, -1) self.play_button.set_tooltip(_('Play / Pause')) combo = ComboBox() which = 0 for pair in voice_names: language, name = pair combo.append_item(language, name) if language == self._voice: combo.set_active(which) which += 1 combo.connect('changed', self._voice_changed_cb) combotool = ToolComboBox(combo) self.insert(combotool, -1) combotool.show() self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0) pitchbar = Gtk.HScale() pitchbar.set_adjustment(self.pitchadj) pitchbar.set_draw_value(False) # pitchbar.set_update_policy(Gtk.UpdatePolicy.ALWAYS) pitchbar.set_size_request(150, 15) pitchtool = Gtk.ToolItem() pitchtool.add(pitchbar) pitchtool.show() self.insert(pitchtool, -1) pitchbar.show() self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0) ratebar = Gtk.HScale() ratebar.set_adjustment(self.rateadj) ratebar.set_draw_value(False) # ratebar.set_update_policy(Gtk.UpdatePolicy.ALWAYS) ratebar.set_size_request(150, 15) ratetool = Gtk.ToolItem() ratetool.add(ratebar) ratetool.show() self.insert(ratetool, -1) ratebar.show() def _compare_voices(self, a, b): if a[1].lower() == b[1].lower(): return 0 if a[1].lower() < b[1].lower(): return -1 if a[1].lower() > b[1].lower(): return 1 def _voice_changed_cb(self, combo): self._voice = combo.props.value self._speech.say_text(self._voices[self._voice]) def pitch_adjusted_cb(self, get): self._speech.set_pitch(int(get.get_value())) self._speech.say_text(_("pitch adjusted")) f = open( os.path.join(self.activity.get_activity_root(), 'instance', 'pitch.txt'), 'w') try: f.write(str(self._speech.get_pitch())) finally: f.close() def rate_adjusted_cb(self, get): self._speech.set_rate(int(get.get_value())) self._speech.say_text(_("rate adjusted")) f = open( os.path.join(self.activity.get_activity_root(), 'instance', 'rate.txt'), 'w') try: f.write(str(self._speech.get_rate())) finally: f.close() def set_activity(self, activity): self.activity = activity if os.path.exists( os.path.join(activity.get_activity_root(), 'instance', 'pitch.txt')): f = open( os.path.join(activity.get_activity_root(), 'instance', 'pitch.txt'), 'r') line = f.readline() pitch = int(line.strip()) self.pitchadj.set_value(pitch) self._speech.set_pitch(pitch) f.close() if os.path.exists( os.path.join(activity.get_activity_root(), 'instance', 'rate.txt')): f = open( os.path.join(activity.get_activity_root(), 'instance', 'rate.txt'), 'r') line = f.readline() rate = int(line.strip()) self.rateadj.set_value(rate) self._speech.set_rate(rate) f.close() self.pitchadj.connect("value_changed", self.pitch_adjusted_cb) self.rateadj.connect("value_changed", self.rate_adjusted_cb) def _play_toggled_cb(self, widget, images): widget.set_icon_widget(images[int(widget.get_active())]) if widget.get_active(): self.play_button.set_icon_name('media-playback-pause') self._speech.say_text(self.activity.add_word_marks(), lang_code=self._voice) else: self.play_button.set_icon_name('media-playback-start') self._speech.pause() def is_playing(self): self._speech.get_is_playing() def stop(self): self._speech.stop()
class MainToolbox(ToolbarBox): query_changed_signal = GObject.Signal('query-changed', arg_types=([object])) def __init__(self, default_what_filter=None, default_filter_type=None): ToolbarBox.__init__(self) self._mount_point = None self._filter_type = default_filter_type self._what_filter = default_what_filter self._when_filter = None self._default_what_filter = default_what_filter self._default_filter_type = default_filter_type self.search_entry = iconentry.IconEntry() self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'entry-search') text = _('Search in %s') % _('Journal') self.search_entry.set_placeholder_text(text) self.search_entry.connect('activate', self._search_entry_activated_cb) self.search_entry.connect('changed', self._search_entry_changed_cb) self.search_entry.add_clear_button() self._autosearch_timer = None self._add_widget(self.search_entry, expand=True) self._favorite_button = ToggleToolButton('emblem-favorite') self._favorite_button.set_tooltip(_('Favorite entries')) self._favorite_button.connect('toggled', self.__favorite_button_toggled_cb) self.toolbar.insert(self._favorite_button, -1) self._favorite_button.show() self._proj_list_button = ToggleToolButton('project-box') self._proj_list_button.set_tooltip(_('Projects')) self._proj_list_button.connect('toggled', self._proj_list_button_clicked_cb) self.toolbar.insert(self._proj_list_button, -1) self._proj_list_button.show() if not self._proj_list_button.props.active: self._what_widget_contents = None self._what_widget = Gtk.ToolItem() self._what_search_button = FilterToolItem( 'view-type', _('Anything'), self._what_widget) self._what_widget.show() self.toolbar.insert(self._what_search_button, -1) self._what_search_button.show() self._when_search_button = FilterToolItem( 'view-created', _('Anytime'), self._get_when_search_items()) self.toolbar.insert(self._when_search_button, -1) self._when_search_button.show() self._sorting_button = SortingButton() self.toolbar.insert(self._sorting_button, -1) self._sorting_button.connect('sort-property-changed', self.__sort_changed_cb) self._sorting_button.show() ''' # TODO: enable it when the DS supports saving the buddies. self._with_widget = Gtk.ToolItem() self._with_search_button = FilterToolItem( 'view-who', _('Anyone'), self._with_widget) self._with_widget.show() self.toolbar.insert(self._with_search_button, -1) self._with_search_button.show() self._get_with_search_items() ''' self._query = self._build_query() self.refresh_filters() self.connect('size_allocate', self.__size_allocate_cb) def __size_allocate_cb(self, widget, allocation): GObject.idle_add(self._update_buttons, allocation.width) def _update_buttons(self, toolbar_width): # Show the label next to the button icon if there is room on # the toolbar. important = toolbar_width > 13 * style.GRID_CELL_SIZE if not important: self.search_entry.set_size_request( toolbar_width - style.GRID_CELL_SIZE * 7, 0) self._what_search_button.set_is_important(important) self._when_search_button.set_is_important(important) # self._with_search_button.set_is_important(important) return False def _get_when_search_items(self): when_list = [] when_list.append({'label': _('Anytime'), 'callback': self._when_palette_cb, 'id': _ACTION_ANYTIME}) when_list.append({'separator': True}) when_list.append({'label': _('Today'), 'callback': self._when_palette_cb, 'id': _ACTION_TODAY}) when_list.append({'label': _('Since yesterday'), 'callback': self._when_palette_cb, 'id': _ACTION_SINCE_YESTERDAY}) when_list.append({'label': _('Past week'), 'callback': self._when_palette_cb, 'id': _ACTION_PAST_WEEK}) when_list.append({'label': _('Past month'), 'callback': self._when_palette_cb, 'id': _ACTION_PAST_MONTH}) when_list.append({'label': _('Past year'), 'callback': self._when_palette_cb, 'id': _ACTION_PAST_YEAR}) return set_palette_list(when_list) ''' def _get_with_search_items(self): with_list = [] with_list.append({'label':_('Anyone'), 'callback': self._with_palette_cb, 'id': _ACTION_EVERYBODY}) with_list.append({'separator': True}) with_list.append({'label':_('My friends'), 'callback': self._with_palette_cb, 'id': _ACTION_MY_FRIENDS}) with_list.append({'label':_('My class'), 'callback': self._with_palette_cb, 'id': _ACTION_MY_CLASS}) with_list.append({'separator': True}) # TODO: Ask the model for buddies. for i, buddy in enumerate(model.get_buddies()): nick, color = buddy with_list.append({'label': nick, 'callback': self._with_palette_cb, 'icon': 'computer-xo', 'xocolors': XOColor(color), 'id': i + _ACTION_MY_CLASS + 1}) widget = set_palette_list(with_list) self._with_widget.add(widget) widget.show() ''' def _add_widget(self, widget, expand=False): tool_item = Gtk.ToolItem() tool_item.set_expand(expand) tool_item.add(widget) widget.show() self.toolbar.insert(tool_item, -1) tool_item.show() def _build_query(self): query = {} if self._mount_point: query['mountpoints'] = [self._mount_point] if self._favorite_button.props.active: query['keep'] = 1 if self._proj_list_button.props.active: query['activity'] = 'org.sugarlabs.Project' elif self._what_filter: filter_type = self._filter_type value = self._what_filter if filter_type == FILTER_TYPE_GENERIC_MIME: generic_type = mime.get_generic_type(value) if generic_type: mime_types = generic_type.mime_types query['mime_type'] = mime_types else: logging.error('filter_type="generic_mime", ' 'but "%s" is not a generic mime' % value) elif filter_type == FILTER_TYPE_ACTIVITY: query['activity'] = value elif self._filter_type == FILTER_TYPE_MIME_BY_ACTIVITY: registry = bundleregistry.get_registry() bundle = \ registry.get_bundle(value) if bundle is not None: query['mime_type'] = bundle.get_mime_types() else: logging.error('Trying to filter using activity mimetype ' 'but bundle id is wrong %s' % value) if self._when_filter: date_from, date_to = self._get_date_range() query['timestamp'] = {'start': date_from, 'end': date_to} if self.search_entry.props.text: text = self.search_entry.props.text.strip() if text: query['query'] = text property_, order = self._sorting_button.get_current_sort() if order == Gtk.SortType.ASCENDING: sign = '+' else: sign = '-' query['order_by'] = [sign + property_] return query def _get_date_range(self): today_start = datetime.today().replace(hour=0, minute=0, second=0) right_now = datetime.today() if self._when_filter == _ACTION_TODAY: date_range = (today_start, right_now) elif self._when_filter == _ACTION_SINCE_YESTERDAY: date_range = (today_start - timedelta(1), right_now) elif self._when_filter == _ACTION_PAST_WEEK: date_range = (today_start - timedelta(7), right_now) elif self._when_filter == _ACTION_PAST_MONTH: date_range = (today_start - timedelta(30), right_now) elif self._when_filter == _ACTION_PAST_YEAR: date_range = (today_start - timedelta(356), right_now) return (time.mktime(date_range[0].timetuple()), time.mktime(date_range[1].timetuple())) def __sort_changed_cb(self, button): self._update_if_needed() def _update_if_needed(self): new_query = self._build_query() if self._query != new_query: self._query = new_query self.query_changed_signal.emit(self._query) def _search_entry_activated_cb(self, search_entry): if self._autosearch_timer: GObject.source_remove(self._autosearch_timer) self._update_if_needed() def _search_entry_changed_cb(self, search_entry): if not search_entry.props.text: search_entry.activate() return if self._autosearch_timer: GObject.source_remove(self._autosearch_timer) self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT, self._autosearch_timer_cb) def _autosearch_timer_cb(self): logging.debug('_autosearch_timer_cb') self._autosearch_timer = None self.search_entry.activate() return False def set_mount_point(self, mount_point): self._mount_point = mount_point self._update_if_needed() def set_what_filter(self, what_filter): for item in self._what_list: if 'id' in item and item['id'] == what_filter: self._what_search_button.set_widget_label(item['label']) if item['id'] == 0: self._what_search_button.set_widget_icon( icon_name='view-type') elif 'icon' in item: self._what_search_button.set_widget_icon( icon_name=item['icon']) self._filter_type = FILTER_TYPE_GENERIC_MIME elif 'file' in item: self._what_search_button.set_widget_icon( file_name=item['file']) if self._default_filter_type is not None: self._filter_type = self._default_filter_type else: self._filter_type = FILTER_TYPE_ACTIVITY self._what_filter = what_filter break def update_filters(self, mount_point, what_filter, filter_type=None): self._mount_point = mount_point self._filter_type = filter_type self._what_filter = what_filter self.set_what_filter(what_filter) self._update_if_needed() def set_filter_type(self, filter_type): self._filter_type = filter_type self._update_if_needed() def _what_palette_cb(self, widget, event, item): self._what_search_button.set_widget_label(item['label']) if item['id'] == 0: self._what_search_button.set_widget_icon(icon_name='view-type') elif 'icon' in item: self._what_search_button.set_widget_icon(icon_name=item['icon']) self._filter_type = FILTER_TYPE_GENERIC_MIME elif 'file' in item: self._what_search_button.set_widget_icon(file_name=item['file']) if self._default_filter_type is not None: self._filter_type = self._default_filter_type else: self._filter_type = FILTER_TYPE_ACTIVITY self._what_filter = item['id'] new_query = self._build_query() if self._query != new_query: self._query = new_query self.query_changed_signal.emit(self._query) def _when_palette_cb(self, widget, event, item): self._when_search_button.set_widget_label(item['label']) self._when_filter = item['id'] new_query = self._build_query() if self._query != new_query: self._query = new_query self.query_changed_signal.emit(self._query) def refresh_filters(self): # refresh_what_filters self._what_list = [] what_list_activities = [] try: # TRANS: Item on a palette that filters by entry type. self._what_list.append({'label': _('Anything'), 'icon': 'application-octet-stream', 'callback': self._what_palette_cb, 'id': _ACTION_ANYTHING}) registry = bundleregistry.get_registry() appended_separator = False types = mime.get_all_generic_types() for generic_type in types: if not appended_separator: self._what_list.append({'separator': True}) appended_separator = True self._what_list.append({'label': generic_type.name, 'icon': generic_type.icon, 'callback': self._what_palette_cb, 'id': generic_type.type_id}) self._what_list.append({'separator': True}) for bundle_id in model.get_unique_values('activity'): activity_info = registry.get_bundle(bundle_id) if activity_info is None: continue # try activity-provided icon if os.path.exists(activity_info.get_icon()): try: what_list_activities.append( {'label': activity_info.get_name(), 'file': activity_info.get_icon(), 'callback': self._what_palette_cb, 'id': bundle_id}) except GObject.GError as exception: # fall back to generic icon logging.warning('Falling back to default icon for' ' "what" filter because %r (%r) has an' ' invalid icon: %s', activity_info.get_name(), str(bundle_id), exception) what_list_activities.append( {'label': activity_info.get_name(), 'icon': 'application-octet-stream', 'callback': self._what_palette_cb, 'id': bundle_id}) finally: def _cmp(a, b): if a['label'] < b['label']: return -1 else: return 1 for item in sorted(what_list_activities, _cmp): self._what_list.append(item) if self._what_widget_contents is not None: self._what_widget.remove(self._what_widget_contents) self._what_widget_contents = set_palette_list(self._what_list) self._what_widget.add(self._what_widget_contents) self._what_widget_contents.show() def _proj_list_button_clicked_cb(self, proj_list_button): if self._proj_list_button.props.active: self._what_widget.hide() self._what_search_button.hide() else: self._what_widget.show() self._what_search_button.show() self._update_if_needed() def __favorite_button_toggled_cb(self, favorite_button): self._update_if_needed() def is_filter_changed(self): return not (self._filter_type == self._default_filter_type and self._what_filter == self._default_what_filter and self._when_filter is None and self._favorite_button.props.active is False and self.search_entry.props.text == '') def clear_query(self): self.search_entry.props.text = '' self._filter_type = self._default_filter_type self._what_search_button.set_widget_icon(icon_name='view-type') self._what_search_button.set_widget_label(_('Anything')) self.set_what_filter(self._default_what_filter) self._when_search_button.set_widget_icon(icon_name='view-created') self._when_search_button.set_widget_label(_('Anytime')) self._when_filter = None ''' self._with_search_button.set_widget_icon(icon_name='view-who') self._with_search_button.set_widget_label(_('Anyone')) self._with_filter = None ''' self._favorite_button.props.active = False if self._proj_list_button.props.active: self._what_widget.show() self._what_search_button.show() self._proj_list_button.props.active = False self._update_if_needed()
class CreateToolbarBuilder(GObject.GObject): __gtype_name__ = 'CreateToolbar' __gsignals__ = { 'create_new_game': (GObject.SignalFlags.RUN_FIRST, None, []), 'create_equal_pairs': (GObject.SignalFlags.RUN_FIRST, None, [GObject.TYPE_PYOBJECT]), } def __init__(self, activity): GObject.GObject.__init__(self) self.activity = activity self.toolbar = self.activity.get_toolbar_box().toolbar self._equal_pairs = ToggleToolButton('pair-non-equals') self._equal_pairs.set_tooltip(_('Match different tiles')) self._equal_pairs.connect('toggled', self._emit_equal_pairs) self.toolbar.insert(self._equal_pairs, -1) self._grouped = ToggleToolButton('grouped_game1') self._grouped.set_tooltip(_('Mixed tiles game')) self._grouped.connect('toggled', self._grouped_cb) self.toolbar.insert(self._grouped, -1) self._clear_button = ToolButton('edit-clear') self._clear_button.set_tooltip(_('Clear all tiles')) self._clear_button.connect('clicked', self._clear_game_bt) self.toolbar.insert(self._clear_button, -1) self.toolbar.show_all() def _add_widget(self, widget, expand=False): tool_item = Gtk.ToolItem() tool_item.set_expand(expand) tool_item.add(widget) widget.show() self.toolbar.insert(tool_item, -1) tool_item.show() def _clear_game_bt(self, button): if self.activity.game.model.is_demo or \ len(self.activity.cardlist.pairs) == 0: self.clear_game() else: alert = Alert() alert.props.title = _('Clear all the tiles from the game?') icon = Icon(icon_name='dialog-ok') alert.add_button(1, _('Clear'), icon) icon = Icon(icon_name='dialog-cancel') alert.add_button(0, _('Do not clear'), icon) alert.connect('response', self._clear_game_alert_cb) self.activity.add_alert(alert) def _clear_game_alert_cb(self, alert, response_id): self.activity.remove_alert(alert) if response_id == 1: self.clear_game() def clear_game(self): self._equal_pairs.set_active(False) self._grouped.set_active(False) self.emit('create_new_game') def update_controls(self, active): self._equal_pairs.set_sensitive(active) self._grouped.set_sensitive(active) self._clear_button.set_sensitive(active) def _emit_equal_pairs(self, widget): if self._equal_pairs.get_active(): self._equal_pairs.set_icon_name('pair-equals') self._equal_pairs.set_tooltip(_('Match identical tiles')) equal_pairs = '1' else: self._equal_pairs.set_icon_name('pair-non-equals') self._equal_pairs.set_tooltip(_('Match different tiles')) equal_pairs = '0' self.emit('create_equal_pairs', self._equal_pairs.get_active()) logging.debug('createtoolbar._emit_equal_pairs') if self.activity.game.model.data['equal_pairs'] != equal_pairs: self.activity.game.model.data['equal_pairs'] = equal_pairs self.activity.game.model.mark_modified() def _grouped_cb(self, widget): if self._grouped.get_active(): self._grouped.set_icon_name('grouped_game2') self._grouped.set_tooltip(_('Grouped tiles game')) divided = '1' else: self._grouped.set_icon_name('grouped_game1') self._grouped.set_tooltip(_('Mixed tiles game')) divided = '0' logging.debug('createtoolbar._grouped_cb') if self.activity.game.model.data['divided'] != divided: self.activity.game.model.data['divided'] = divided self.activity.game.model.mark_modified() def update_create_toolbar(self, widget, game_name, equal_pairs, grouped): self._equal_pairs.set_active(equal_pairs == '1') self._grouped.set_active(grouped == '1')
class SpeechToolbar(Gtk.Toolbar): def __init__(self): Gtk.Toolbar.__init__(self) voicebar = Gtk.Toolbar() self.activity = None self.sorted_voices = [i for i in speech.voices()] self.sorted_voices.sort(self.compare_voices) default = 0 for voice in self.sorted_voices: if voice[0] == 'default': break default = default + 1 # Play button Image play_img = Gtk.Image() play_img.show() play_img.set_from_icon_name('media-playback-start', Gtk.IconSize.LARGE_TOOLBAR) # Pause button Image pause_img = Gtk.Image() pause_img.show() pause_img.set_from_icon_name('media-playback-pause', Gtk.IconSize.LARGE_TOOLBAR) # Play button self.play_btn = ToggleToolButton('media-playback-start') self.play_btn.show() self.play_btn.connect('toggled', self.play_cb, [play_img, pause_img]) self.insert(self.play_btn, -1) self.play_btn.set_tooltip(_('Play / Pause')) self.voice_combo = ComboBox() self.voice_combo.connect('changed', self.voice_changed_cb) for voice in self.sorted_voices: self.voice_combo.append_item(voice, voice[0]) self.voice_combo.set_active(default) combotool = ToolComboBox(self.voice_combo) self.insert(combotool, -1) combotool.show() self.pitchadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0) pitchbar = Gtk.HScale() pitchbar.set_adjustment(self.pitchadj) pitchbar.set_draw_value(False) # pitchbar.set_update_policy(Gtk.UpdatePolicy.ALWAYS) pitchbar.set_size_request(150,15) pitchtool = Gtk.ToolItem() pitchtool.add(pitchbar) pitchtool.show() self.insert(pitchtool, -1) pitchbar.show() self.rateadj = Gtk.Adjustment(0, -100, 100, 1, 10, 0) ratebar = Gtk.HScale() ratebar.set_adjustment(self.rateadj) ratebar.set_draw_value(False) #ratebar.set_update_policy(Gtk.UpdatePolicy.ALWAYS) ratebar.set_size_request(150,15) ratetool = Gtk.ToolItem() ratetool.add(ratebar) ratetool.show() self.insert(ratetool, -1) ratebar.show() def compare_voices(self, a, b): if a[0].lower() == b[0].lower(): return 0 if a[0].lower() < b[0].lower(): return -1 if a[0].lower() > b[0].lower(): return 1 def voice_changed_cb(self, combo): speech.voice = combo.props.value if self.activity != None: speech.say(speech.voice[0]) def pitch_adjusted_cb(self, get): speech.pitch = int(get.get_value()) speech.say(_("pitch adjusted")) f = open(os.path.join(self.activity.get_activity_root(), 'instance', 'pitch.txt'), 'w') try: f.write(str(speech.pitch)) finally: f.close() def rate_adjusted_cb(self, get): speech.rate = int(get.get_value()) speech.say(_("rate adjusted")) f = open(os.path.join(self.activity.get_activity_root(), 'instance', 'rate.txt'), 'w') try: f.write(str(speech.rate)) finally: f.close() def set_activity(self, activity): self.activity = activity if os.path.exists(os.path.join(activity.get_activity_root(), 'instance', 'pitch.txt')): f = open(os.path.join(activity.get_activity_root(), 'instance', 'pitch.txt'), 'r') line = f.readline() pitch = int(line.strip()) self.pitchadj.set_value(pitch) speech.pitch = pitch f.close() if os.path.exists(os.path.join(activity.get_activity_root(), 'instance', 'rate.txt')): f = open(os.path.join(activity.get_activity_root(), 'instance', 'rate.txt'), 'r') line = f.readline() rate = int(line.strip()) self.rateadj.set_value(rate) speech.rate = rate f.close() self.pitchadj.connect("value_changed", self.pitch_adjusted_cb) self.rateadj.connect("value_changed", self.rate_adjusted_cb) def play_cb(self, widget, images): widget.set_icon_widget(images[int(widget.get_active())]) if widget.get_active(): if speech.is_stopped(): speech.play(self.activity.add_word_marks()) else: speech.stop()
class TextToolbar(Gtk.Toolbar): _ACTION_TEXT_NAME = 'text' def __init__(self, activity): Gtk.Toolbar.__init__(self) self._activity = activity self.properties = self._activity.area.tool self._text = DrawToolButton('text', activity.tool_group, _('Type')) self.insert(self._text, -1) self._text.connect('clicked', self.set_tool, self._ACTION_TEXT_NAME) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._bold = ToggleToolButton('format-text-bold') self.insert(self._bold, -1) self._bold.show() self._bold.connect('clicked', self.__bold_bt_cb) self._italic = ToggleToolButton('format-text-italic') self.insert(self._italic, -1) self._italic.show() self._italic.connect('clicked', self.__italic_bt_cb) separator = Gtk.SeparatorToolItem() separator.set_draw(True) self.insert(separator, -1) self._font_size = FontSize() self.insert(self._font_size, -1) self._font_size_changed_id = self._font_size.connect( 'changed', self.__font_size_changed_cb) self._font_combo = FontComboBox() self._fonts_changed_id = self._font_combo.connect( 'changed', self.__font_changed_cb) fd = activity.area.get_font_description() font_name = fd.get_family() self._font_combo.set_font_name(font_name) self._font_size.set_font_size(int(fd.get_size() / Pango.SCALE)) tool_item = ToolComboBox(self._font_combo) self.insert(tool_item, -1) self.show_all() def __bold_bt_cb(self, button): fd = self._activity.area.get_font_description() if button.get_active(): fd.set_weight(Pango.Weight.BOLD) else: fd.set_weight(Pango.Weight.NORMAL) self._activity.area.set_font_description(fd) def __italic_bt_cb(self, button): fd = self._activity.area.get_font_description() if button.get_active(): fd.set_style(Pango.Style.ITALIC) else: fd.set_style(Pango.Style.NORMAL) self._activity.area.set_font_description(fd) def __font_size_changed_cb(self, widget): fd = self._activity.area.get_font_description() value = widget.get_font_size() fd.set_size(int(value) * Pango.SCALE) self._activity.area.set_font_description(fd) def __font_changed_cb(self, combo): fd = self._activity.area.get_font_description() font_name = combo.get_font_name() fd.set_family(font_name) self._activity.area.set_font_description(fd) def get_active_text(self, combobox): model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][0] def set_tool(self, widget, tool_name): self.properties['name'] = tool_name self._activity.area.set_tool(self.properties)
def __init__(self, handle): activity.Activity.__init__(self, handle) # avahi initialization self._service = None toolbar_box = ToolbarBox() self._vbox = Gtk.VBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() # get information from gconf client = GConf.Client.get_default() self._age = client.get_int('/desktop/sugar/user/age') self._gender = client.get_string('/desktop/sugar/user/gender') if self._gender is None: self._gender = 'male' teacher = (self._age >= 25) # if age is not configured age == 0 if teacher or self._age == 0: teacher_button = ToggleToolButton('%s-7' % self._gender) teacher_button.set_tooltip(_('Teacher')) teacher_button.show() teacher_button.connect('toggled', self.__start_teacher_cb) toolbar_box.toolbar.insert(teacher_button, -1) if teacher: teacher_button.set_active(True) if not teacher or self._age == 0: student_button = ToggleToolButton('%s-2' % self._gender) student_button.set_tooltip(_('Student')) student_button.show() student_button.connect('toggled', self.__start_student_cb) toolbar_box.toolbar.insert(student_button, -1) if self._age > 0: # is a student student_button.set_active(True) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) separator.show() toolbar_box.toolbar.insert(separator, -1) stopbutton = StopButton(self) toolbar_box.toolbar.insert(stopbutton, -1) stopbutton.show() self.set_toolbar_box(toolbar_box) toolbar_box.show() self.scrolled = Gtk.ScrolledWindow() self.scrolled.add_with_viewport(self._vbox) self.scrolled.show_all() self.set_canvas(self.scrolled) self._inhibit_suspend()
def __init__(self, abiword_canvas): GObject.GObject.__init__(self) self.font_name_combo = FontComboBox() self.font_name_combo.set_font_name('Sans') self._fonts_changed_id = self.font_name_combo.connect( 'changed', self._font_changed_cb, abiword_canvas) self._abi_handler = abiword_canvas.connect('font-family', self._font_family_cb) self.insert(ToolComboBox(self.font_name_combo), -1) self.font_size = FontSize() self._abi_handler = abiword_canvas.connect('font-size', self._font_size_cb) self._changed_id = self.font_size.connect( 'changed', self._font_size_changed_cb, abiword_canvas) self.insert(self.font_size, -1) bold = ToggleToolButton('format-text-bold') bold.set_tooltip(_('Bold')) bold.props.accelerator = '<Ctrl>B' bold_id = bold.connect('clicked', lambda sender: abiword_canvas.toggle_bold()) abiword_canvas.connect('bold', lambda abi, b: self._setToggleButtonState(bold, b, bold_id)) self.insert(bold, -1) italic = ToggleToolButton('format-text-italic') italic.set_tooltip(_('Italic')) italic.props.accelerator = '<Ctrl>I' italic_id = italic.connect('clicked', lambda sender: abiword_canvas.toggle_italic()) abiword_canvas.connect('italic', lambda abi, b: self._setToggleButtonState(italic, b, italic_id)) self.insert(italic, -1) underline = ToggleToolButton('format-text-underline') underline.set_tooltip(_('Underline')) underline.props.accelerator = '<Ctrl>U' underline_id = underline.connect('clicked', lambda sender: abiword_canvas.toggle_underline()) abiword_canvas.connect('underline', lambda abi, b: self._setToggleButtonState(underline, b, underline_id)) self.insert(underline, -1) # for super/subscript, we're using the same keyboard shorcuts as # abiword: <C-^> and <C-_> super_btn = ToggleToolButton('format-text-super') super_btn.set_tooltip(_('Superscript')) # found with gtk.accelerator_name super_btn.props.accelerator = '<Ctrl>asciicircum' super_id = super_btn.connect('clicked', lambda sender: abiword_canvas.toggle_super()) # no, this isn't a mistake. The method is called `toggle_super()', but # the *signal* is called `superscript'. Same goes for sub{script,}. abiword_canvas.connect('superscript', lambda abi, b: self._setToggleButtonState(super_btn, b, super_id)) self.insert(super_btn, -1) sub = ToggleToolButton('format-text-sub') sub.set_tooltip(_('Subscript')) sub.props.accelerator = '<Ctrl>underscore' sub_id = sub.connect('clicked', lambda sender: abiword_canvas.toggle_sub()) abiword_canvas.connect('subscript', lambda abi, b: self._setToggleButtonState(sub, b, sub_id)) self.insert(sub, -1) color = ColorToolButton() color.connect('notify::color', self._text_color_cb, abiword_canvas) tool_item = Gtk.ToolItem() tool_item.add(color) self.insert(tool_item, -1) abiword_canvas.connect( 'color', lambda abi, r, g, b: color.set_color(Gdk.Color(r * 256, g * 256, b * 256))) # MAGIC NUMBER WARNING: Secondary toolbars are not a standard height? self.set_size_request(-1, style.GRID_CELL_SIZE) def append_align(icon_name, tooltip, do_abi_cb, style_name, button, menu_box): menu_item = AbiMenuItem(abiword_canvas, style_name, do_abi_cb, icon_name, tooltip, button) menu_box.append_item(menu_item) menu_item.show() self._aligment_btn = ToolButton(icon_name='format-justify-left') self._aligment_btn.props.tooltip = _('Choose alignment') self._aligment_btn.props.hide_tooltip_on_click = False self._aligment_btn.palette_invoker.props.toggle_palette = True menu_box = PaletteMenuBox() self._aligment_btn.props.palette.set_content(menu_box) menu_box.show() append_align('format-justify-left', _('Left justify'), abiword_canvas.align_left, 'left-align', self._aligment_btn, menu_box) append_align('format-justify-center', _('Center justify'), abiword_canvas.align_center, 'center-align', self._aligment_btn, menu_box) append_align('format-justify-right', _('Right justify'), abiword_canvas.align_right, 'right-align', self._aligment_btn, menu_box) append_align('format-justify-fill', _('Fill justify'), abiword_canvas.align_justify, 'justify-align', self._aligment_btn, menu_box) self.insert(self._aligment_btn, -1) self.show_all()
class ViewToolbar(Gtk.Toolbar): __gtype_name__ = 'ViewToolbar' __gsignals__ = { 'go-fullscreen': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([])), 'toggle-index-show': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([bool])), 'toggle-tray-show': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ([bool])), } def __init__(self): Gtk.Toolbar.__init__(self) self._view = None self._navigator_button = ToggleToolButton('view-list') self._navigator_button.set_tooltip(_('Table of contents')) self._navigator_button.connect('toggled', self.__navigator_toggled_cb) self.insert(self._navigator_button, -1) self._spacer_navigator = Gtk.SeparatorToolItem() self._spacer_navigator.props.draw = False self.insert(self._spacer_navigator, -1) self._zoom_out = ToolButton('zoom-out') self._zoom_out.set_tooltip(_('Zoom out')) self._zoom_out.connect('clicked', self._zoom_out_cb) self.insert(self._zoom_out, -1) self._zoom_out.show() self._zoom_in = ToolButton('zoom-in') self._zoom_in.set_tooltip(_('Zoom in')) self._zoom_in.connect('clicked', self._zoom_in_cb) self.insert(self._zoom_in, -1) self._zoom_in.show() self._zoom_to_width = ToolButton('zoom-to-width') self._zoom_to_width.set_tooltip(_('Zoom to width')) self._zoom_to_width.connect('clicked', self._zoom_to_width_cb) self.insert(self._zoom_to_width, -1) self._zoom_to_width.show() self._zoom_to_fit = ToolButton('zoom-best-fit') self._zoom_to_fit.set_tooltip(_('Zoom to fit')) self._zoom_to_fit.connect('clicked', self._zoom_to_fit_cb) self.insert(self._zoom_to_fit, -1) self._zoom_to_fit.show() self._zoom_to_original = ToolButton('zoom-original') self._zoom_to_original.set_tooltip(_('Actual size')) self._zoom_to_original.connect('clicked', self._actual_size_cb) self.insert(self._zoom_to_original, -1) self._zoom_to_original.show() spacer = Gtk.SeparatorToolItem() spacer.props.draw = True self.insert(spacer, -1) spacer.show() self._fullscreen = ToolButton('view-fullscreen') self._fullscreen.set_tooltip(_('Fullscreen')) self._fullscreen.connect('clicked', self._fullscreen_cb) self.insert(self._fullscreen, -1) self._fullscreen.show() self.traybutton = ToggleToolButton('tray-show') self.traybutton.set_icon_name('tray-favourite') self.traybutton.connect('toggled', self.__tray_toggled_cb) #self.traybutton.props.sensitive = False self.traybutton.props.active = False self.insert(self.traybutton, -1) self.traybutton.show() self._view_notify_zoom_handler = None spacer = Gtk.SeparatorToolItem() spacer.props.draw = True self.insert(spacer, -1) spacer.show() self._rotate_left = ToolButton('rotate_anticlockwise') self._rotate_left.set_tooltip(_('Rotate left')) self._rotate_left.connect('clicked', self._rotate_left_cb) self.insert(self._rotate_left, -1) self._rotate_left.show() self._rotate_right = ToolButton('rotate_clockwise') self._rotate_right.set_tooltip(_('Rotate right')) self._rotate_right.connect('clicked', self._rotate_right_cb) self.insert(self._rotate_right, -1) self._rotate_right.show() def set_view(self, view): self._view = view self._update_zoom_buttons() def show_nav_button(self): self._navigator_button.show() self._spacer_navigator.show() def zoom_in(self): self._view.zoom_in() self._update_zoom_buttons() def _zoom_in_cb(self, button): self.zoom_in() def _rotate_left_cb(self, button): self._view.rotate_left() def _rotate_right_cb(self, button): self._view.rotate_right() def zoom_out(self): self._view.zoom_out() self._update_zoom_buttons() def _zoom_out_cb(self, button): self.zoom_out() def zoom_to_width(self): self._view.zoom_to_width() self._update_zoom_buttons() def _zoom_to_width_cb(self, button): self.zoom_to_width() def __navigator_toggled_cb(self, button): self.emit('toggle-index-show', button.get_active()) def _update_zoom_buttons(self): self._zoom_in.props.sensitive = self._view.can_zoom_in() self._zoom_out.props.sensitive = self._view.can_zoom_out() self._zoom_to_width.props.sensitive = self._view.can_zoom_to_width() self._zoom_to_fit.props.sensitive = self._view.can_zoom_to_width() self._zoom_to_original.props.sensitive = self._view.can_zoom_to_width() self._rotate_left.props.sensitive = self._view.can_rotate() self._rotate_right.props.sensitive = self._view.can_rotate() def _zoom_to_fit_cb(self, menu_item): self._view.zoom_to_best_fit() self._update_zoom_buttons() def _actual_size_cb(self, menu_item): self._view.zoom_to_actual_size() self._update_zoom_buttons() def _fullscreen_cb(self, button): self.emit('go-fullscreen') def __tray_toggled_cb(self, button): self.emit('toggle-tray-show', button.get_active()) if button.props.active: self.traybutton.set_tooltip(_('Show Tray')) else: self.traybutton.set_tooltip(_('Hide Tray'))
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)
class ViewToolbar(Gtk.Toolbar): def __init__(self, activity): GObject.GObject.__init__(self) self._browser = None self._activity = activity self.zoomout = ToolButton('zoom-out') self.zoomout.set_tooltip(_('Zoom out')) self.zoomout.connect('clicked', self.__zoomout_clicked_cb) self.insert(self.zoomout, -1) self.zoomout.show() self.zoomin = ToolButton('zoom-in') self.zoomin.set_tooltip(_('Zoom in')) self.zoomin.connect('clicked', self.__zoomin_clicked_cb) self.insert(self.zoomin, -1) self.zoomin.show() self.zoom_original = ToolButton('zoom-original') self.zoom_original.set_tooltip(_('Actual size')) self.zoom_original.connect('clicked', self.__zoom_original_clicked_cb) self.insert(self.zoom_original, -1) self.zoom_original.show() self.separator = Gtk.SeparatorToolItem() self.separator.set_draw(True) self.insert(self.separator, -1) self.separator.show() self.fullscreen = ToolButton('view-fullscreen') self.fullscreen.set_tooltip(_('Fullscreen')) self.fullscreen.connect('clicked', self.__fullscreen_clicked_cb) self.insert(self.fullscreen, -1) self.fullscreen.show() self.traybutton = ToggleToolButton('tray-show') self.traybutton.set_icon_name('tray-favourite') self.traybutton.connect('toggled', self.__tray_toggled_cb) self.traybutton.props.sensitive = False self.traybutton.props.active = False self.insert(self.traybutton, -1) self.traybutton.show() tabbed_view = self._activity.get_canvas() if tabbed_view.get_n_pages(): self._connect_to_browser(tabbed_view.props.current_browser) tabbed_view.connect_after('switch-page', self.__switch_page_cb) def __switch_page_cb(self, tabbed_view, page, page_num): self._connect_to_browser(tabbed_view.props.current_browser) def _connect_to_browser(self, browser): self._browser = browser self._update_zoom_buttons() def _update_zoom_buttons(self): is_webkit_browser = isinstance(self._browser, Browser) self.zoomin.set_sensitive(is_webkit_browser) self.zoomout.set_sensitive(is_webkit_browser) self.zoom_original.set_sensitive(is_webkit_browser) def __zoom_original_clicked_cb(self, button): tabbed_view = self._activity.get_canvas() tabbed_view.props.current_browser.set_zoom_level(ZOOM_ORIGINAL) def __zoomin_clicked_cb(self, button): tabbed_view = self._activity.get_canvas() tabbed_view.props.current_browser.zoom_in() def __zoomout_clicked_cb(self, button): tabbed_view = self._activity.get_canvas() tabbed_view.props.current_browser.zoom_out() def __fullscreen_clicked_cb(self, button): self._activity.fullscreen() def __tray_toggled_cb(self, button): if button.props.active: self._activity.tray.show() else: self._activity.tray.hide() self.update_traybutton_tooltip() def update_traybutton_tooltip(self): if not self.traybutton.props.active: self.traybutton.set_tooltip(_('Show Tray')) else: self.traybutton.set_tooltip(_('Hide Tray'))