def get_toolbar(self): toolbar = gtk.Toolbar() radio_adv = RadioToolButton() radio_adv.set_active(True) radio_adv.set_label("Avanzada") radio_adv.set_tooltip("Mostrar biblioteca avanzada") radio_adv.connect("clicked", self.switch, "advanced") toolbar.insert(radio_adv, -1) radio_adv.show() radio_bas = RadioToolButton(group=radio_adv) radio_bas.set_label("Simple") radio_bas.set_tooltip("Mostrar biblioteca sencilla") radio_bas.connect("clicked", self.switch, "basic") toolbar.insert(radio_bas, -1) toolbar.show_all() return toolbar
class RadioItem(ToggleItem): def __init__(self, group, default_value=True, stock_id=None, important=False): ToggleItem.__init__(self, default_value, stock_id, important) self.group = group def get_tool_item(self): self.toolitem = RadioToolButton() if self.group: self.toolitem.set_group(self.group.toolitem) self.toolitem.set_named_icon( stock.icons[self._stock_id] if self._stock_id in stock.icons else self._stock_id) self.toolitem.set_active(self.default_value) self.toolitem.connect('toggled', self.toggled_cb) self.setup_tooltip() return self.toolitem
def __init__(self): RadioToolButton.__init__(self) self.props.tooltip = _('Favorites view') self.props.accelerator = _('<Ctrl>1') self.props.group = None favorites_settings = favoritesview.get_settings() self._layout = favorites_settings.layout self._update_icon() # someday, this will be a gtk.Table() layouts_grid = gtk.HBox() layout_item = None for layoutid, layoutclass in sorted(favoritesview.LAYOUT_MAP.items()): layout_item = RadioToolButton(icon_name=layoutclass.icon_name, group=layout_item, active=False) if layoutid == self._layout: layout_item.set_active(True) layouts_grid.pack_start(layout_item, fill=False) layout_item.connect('toggled', self.__layout_activate_cb, layoutid) layouts_grid.show_all() self.props.palette.set_content(layouts_grid)
def __init__(self): RadioToolButton.__init__(self) self.props.tooltip = _('Pathway view') self.props.accelerator = _('<Ctrl>3') self.props.group = None favorites_settings = favoritesview.get_settings() self._layout = favorites_settings.layout self._update_icon() # someday, this will be a gtk.Table() layouts_grid = gtk.HBox() layout_item = None for layoutid, layoutclass in sorted(favoritesview.LAYOUT_MAP.items()): layout_item = RadioToolButton(icon_name=layoutclass.icon_name, group=layout_item, active=False) if layoutid == self._layout: layout_item.set_active(True) layouts_grid.pack_start(layout_item, fill=False) layout_item.connect('toggled', self.__layout_activate_cb, layoutid) layouts_grid.show_all() self.props.palette.set_content(layouts_grid)
class Activity(sugar.activity.activity.Activity): def __init__(self, handle): super(Activity, self).__init__(handle) self.paused = False watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(watch) self.p = gtk.VPaned() self.p.connect("notify::position", self.redraw) self.box = gtk.Notebook() self.p.pack2(self.box) self.p.show() self.box.set_show_tabs(False) self.splash = gtk.Image() pixbuf = gtk.gdk.pixbuf_new_from_file("images/splash_comodo.png") screen = self.window.get_screen() width, height = screen.get_width(), screen.get_height() - style.GRID_CELL_SIZE pixbuf = pixbuf.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR) self.splash.set_from_pixbuf(pixbuf) self.splash.show() eb = gtk.EventBox() eb.add(self.splash) eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("white")) eb.show() self.box.append_page(eb, gtk.Label("Inicio")) self._pygamecanvas = sugargame2.canvas.PygameCanvas(self) self._pygamecanvas.set_flags(gtk.EXPAND) self._pygamecanvas.set_flags(gtk.FILL) self.connect("visibility-notify-event", self.redraw) self._pygamecanvas.set_events(gtk.gdk.BUTTON_PRESS_MASK) self._pygamecanvas.connect("button-press-event", self._pygamecanvas.grab_focus) self.box.append_page(self._pygamecanvas, gtk.Label("Juego")) self.box.show() self.set_canvas(self.p) gobject.timeout_add(300, self.pump) gobject.timeout_add(2000, self.init_interpreter) #gobject.timeout_add(1000, self.build_editor) gobject.timeout_add(1500, self.check_modified) self.build_toolbar() self.credits = None self.editor = None #self.reader = None self._pygamecanvas.run_pygame(self.run_game) def redraw(self, widget=None, b=None, c=None): scene = spyral.director.get_scene() if scene: scene.redraw() def alert(self, title=None, text=None, delay=5): alert = NotifyAlert(delay) alert.props.title = title alert.props.msg = text self.add_alert(alert) alert.connect('response', self._alert_ok) alert.show() def _alert_ok(self, alert, *args): self.remove_alert(alert) def check_modified(self): if self.box.current_page()==2: if not self.save_button.get_sensitive(): if self.editor.modificado(): self.save_button.set_sensitive(True) return False return True def pump(self): # Esto es necesario porque sino pygame acumula demasiados eventos. pygame.event.pump() def focus_interpreter(self, widget, event): self._interpreter.text.grab_focus() return True def init_interpreter(self): # diferido unos segundos para evitar ver errores superfluos al iniciar self._interpreter = GTKInterpreterConsole(self.redraw) self._interpreter.text.connect('button-press-event', self.focus_interpreter) self.p.pack1(self._interpreter) return False def open_file(self, widget, path): if path: if not os.path.isdir(path): self.editor.open_file(widget, path) def save_file(self, widget): if self.editor.modificado(): self.save_button.set_sensitive(False) self.editor.save_file() filename = self.editor.current_file() self.alert(filename, "Archivo guardado.") gobject.timeout_add(1500, self.check_modified) def build_editor(self): dir_real = os.getcwd() f = os.path.realpath(JUEGO.__file__) f = "." + f.replace(dir_real ,"") # todo esto para obtener una ruta relativa f = f.rstrip("c") # en caso que sea .pyc compilado self.h = gtk.HPaned() self.tree = FileViewer(".", os.path.basename(f)) self.tree.connect("file-selected", self.open_file) self.tree.show() self.h.pack1(self.tree) self.box.append_page(self.h, gtk.Label("Editor")) if False: #os.path.isfile("/usr/bin/gvim"): # Si podemos, lo hacemos self.socket = gtk.Socket() self.socket.show() self.h.pack2(self.socket) sock_id = str(self.socket.get_id()) self.editor = VimSourceView(sock_id) if not self.editor.bufInfo.bufferList: f = JUEGO.__file__ if f.endswith("pyc"): f = f[:-1] self.open_file(None, f) else: self.editor = SourceView() scroller = gtk.ScrolledWindow() scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroller.add(self.editor) scroller.show() self.h.pack2(scroller) self.editor.show() self.h.show() self.open_file(None, f) def build_reader(self): self.reader = webkit.WebView() curdir = os.getcwd() self.reader.load_uri("file://%s/docs/index.html" % curdir) self.box.append_page(self.reader, gtk.Label("Lector")) self.reader.show() def build_toolbar(self): toolbar_box = ToolbarBox() self.set_toolbar_box(toolbar_box) toolbar_box.show() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, -1) activity_button.show() tool_group = None self.game_button = RadioToolButton() self.game_button.props.icon_name = 'gamecanvas' self.game_button.set_tooltip(_('Juego')) self.game_button.accelerator = "<Ctrl>1" self.game_button.props.group = tool_group self.game_button.connect('clicked', self.show_game) toolbar_box.toolbar.insert(self.game_button, -1) self.game_button.show() tool_group = self.game_button button = RadioToolButton() button.props.icon_name = 'view-source' button.set_tooltip(_('Editor')) button.accelerator = "<Ctrl>2" button.props.group = tool_group button.connect('clicked', self.show_editor) toolbar_box.toolbar.insert(button, -1) button.show() self.save_button = ToolButton('dialog-ok') self.save_button.set_tooltip(_('Guardar')) self.save_button.accelerator = "<Ctrl>s" self.save_button.connect('clicked', self.save_file) self.save_button.set_sensitive(False) toolbar_box.toolbar.insert(self.save_button, -1) self.save_button.show() separator = gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() button = ToolButton('system-restart') button.set_tooltip(_('Reiniciar juego')) button.accelerator = "<Alt><Shift>r" button.connect('clicked', self.restart_game) toolbar_box.toolbar.insert(button, -1) button.show() self.editor_button = ToolButton('sources') self.editor_button.set_tooltip(_('Consola')) self.editor_button.accelerator = "<Ctrl>grave" self.editor_button.connect('clicked', self.toggle_console) toolbar_box.toolbar.insert(self.editor_button, -1) self.editor_button.show() separator = gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() button = helpbutton.HelpButton(self) toolbar_box.toolbar.insert(button, -1) button.show() button = ToolButton() button.props.icon_name = 'activity-about' button.set_tooltip(_('Acerca de')) button.accelerator = "<Ctrl>i" button.connect('clicked', self.run_credits) toolbar_box.toolbar.insert(button, -1) button.show() # Blank space (separator) and Stop button at the end: 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() def run_game(self): spyral.director.init((0,0), fullscreen=False, max_fps=30) self.game = JUEGO.Juego(self, callback=self.game_ready) self.box.connect("switch-page", self.redraw) spyral.director.push(self.game) self.start() def run_credits(self, widget): if not (spyral.director.get_scene()==self.credits): self.credits = game.credits.Creditos(self.game.size) spyral.director.push(self.credits) def start(self): try: spyral.director.run(sugar = True) except AttributeError as detail: detail2 = traceback.format_exc() self.box.set_page(0) self.alert( detail2, "Spyral se ha detenido abruptamente.", 60) def show_game(self, widget): self.box.set_page(1) self.redraw() def show_editor(self, widget): if not self.editor: self.build_editor() self.box.set_page(2) self.redraw() def show_reader(self, widget): if not self.reader: self.build_reader() self.box.set_page(3) self.redraw() def restart_game(self, widget): global JUEGO import objetos try: objetos.reset() except AttributeError: pass self.box.set_page(0) watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(watch) JUEGO = reload(JUEGO) self.game = JUEGO.Juego(self, callback=self.game_ready) spyral.director.replace(self.game) self.start() def game_ready(self, widget = None): self.game_button.set_active(True) self.box.set_page(1) self._pygamecanvas.grab_focus() self.window.set_cursor(None) def read_file(self, file_path): pass def write_file(self, file_path): pass def can_close(self): if self.editor: self.editor.close() self.box.set_page(0) try: spyral.director.quit() except spyral.exceptions.GameEndException: pass finally: return True def toggle_console(self, e): if self._interpreter.props.visible: self._interpreter.hide() self._pygamecanvas.grab_focus() else: self.p.set_position(160) self._interpreter.show() self._interpreter.text.grab_focus() self.redraw() def animate_console(self): easing = spyral.easing.Linear(0,160) self.p.set_position(0)
class SensorToolbar(gtk.Toolbar): ''' The toolbar for specifiying the sensor: sound, resitance, or voltage ''' LOWER = 0.0 UPPER = 1.0 STR_DC_R = \ _("Resistive sensor (connect sensor to pink 'Mic In' on left side \ of XO)" ) + ' ' STR_DC_V = \ _("Voltage sensor (connect sensor to pink 'Mic In' on left side \ of XO)" ) + ' ' STR_AC = _('Sound') + ' ' STR_RESISTANCE = _('Resistance') + ' (' + _('Ohms') + ') ' STR_VOLTAGE = _('Voltage') + ' (' + _('Volts') + ') ' STR_TIME = _('Time Base') + ' ' STR_FREQUENCY = _('Frequency Base') + ' ' STR_INVERT = ' ' + _('Invert') + ' ' STR_XAXIS_TEXT = _('X Axis Scale: 1 division = %(division)s %(unit)s') # TRANSLATORS: This is milli seconds. MS = _('ms') # TRANSLATORS: This is Hertz, so 1/second. HZ = _('Hz') def __init__(self, activity, channels): ''' By default, start with resistance mode ''' gtk.Toolbar.__init__(self) self.activity = activity self._channels = channels self._lock_radio_buttons = False self._radio_button_pushed = False self.values = [] for i in range(self._channels): self.values.append('') self.string_for_textbox = '' self.gain = 1.0 self.y_mag = 3.0 self.capture_gain = CAPTURE_GAIN self.mic_boost = MIC_BOOST self.mode = 'sound' # Set up Time-domain Button self.time = RadioToolButton(group=None) self.time.set_named_icon('media-audio') self.insert(self.time, -1) self.time.set_tooltip(_('Sound')) self.time.connect('clicked', self.analog_resistance_voltage_mode_cb, 'sound') # Set up Resistance Button self.resistance = RadioToolButton(group=self.time) self.resistance.set_named_icon('resistance') if _is_xo(self.activity.hw): self.insert(self.resistance, -1) self.resistance.show() self.resistance.set_tooltip(_('Resistance Sensor')) self.resistance.connect('clicked', self.analog_resistance_voltage_mode_cb, 'resistance') # Set up Voltage Button self.voltage = RadioToolButton(group=self.time) self.voltage.set_named_icon('voltage') if _is_xo(self.activity.hw): self.insert(self.voltage, -1) self.voltage.set_tooltip(_('Voltage Sensor')) self.voltage.connect('clicked', self.analog_resistance_voltage_mode_cb, 'voltage') separator = gtk.SeparatorToolItem() separator.props.draw = True self.insert(separator, -1) self._log_interval_combo = ComboBox() self.interval = [ _('1/10 second'), _('1 second'), _('30 seconds'), _('5 minutes'), _('30 minutes') ] if hasattr(self._log_interval_combo, 'set_tooltip_text'): self._log_interval_combo.set_tooltip_text(_('Sampling interval')) self._interval_changed_id = self._log_interval_combo.connect( 'changed', self.log_interval_cb) for i, s in enumerate(self.interval): self._log_interval_combo.append_item(i, s, None) if s == _('1 second'): self._log_interval_combo.set_active(i) self._log_interval_tool = ToolComboBox(self._log_interval_combo) self.insert(self._log_interval_tool, -1) self.logging_interval_status = '1 second' # Set up Logging/Stop Logging Button self._record = ToolButton('media-record') self.insert(self._record, -1) self._record.set_tooltip(_('Start Recording')) self._record.connect('clicked', self.record_control_cb) if self.activity.has_toolbarbox: separator = gtk.SeparatorToolItem() separator.props.draw = True self.insert(separator, -1) # Set up Trigger Combo box self.trigger_combo = ComboBox() self.trigger = [_('None'), _('Rising Edge'), _('Falling Edge')] self.trigger_conf = [ self.activity.wave.TRIGGER_NONE, self.activity.wave.TRIGGER_POS, self.activity.wave.TRIGGER_NEG ] self._trigger_changed_id = self.trigger_combo.connect( 'changed', self.update_trigger_control) for i, s in enumerate(self.trigger): self.trigger_combo.append_item(i, s, None) self.trigger_combo.set_active(0) if hasattr(self.trigger_combo, 'set_tooltip_text'): self.trigger_combo.set_tooltip_text(_('Create a trigger')) self._trigger_tool = ToolComboBox(self.trigger_combo) self.insert(self._trigger_tool, -1) self.show_all() def add_frequency_slider(self, toolbar): ''' Either on the Sound toolbar or the Main toolbar ''' self._freq_stepper_up = ToolButton('freq-high') self._freq_stepper_up.set_tooltip(_('Zoom out')) self._freq_stepper_up.connect('clicked', self._freq_stepper_up_cb) self.activity.adjustmentf = gtk.Adjustment(0.5, self.LOWER, self.UPPER, 0.01, 0.1, 0) self.activity.adjustmentf.connect('value_changed', self.cb_page_sizef) self._freq_range = gtk.HScale(self.activity.adjustmentf) self._freq_range.set_inverted(True) self._freq_range.set_draw_value(False) self._freq_range.set_update_policy(gtk.UPDATE_CONTINUOUS) self._freq_range.set_size_request(120, 15) self._freq_stepper_down = ToolButton('freq-low') self._freq_stepper_down.set_tooltip(_('Zoom in')) self._freq_stepper_down.connect('clicked', self._freq_stepper_down_cb) self._freq_range_tool = gtk.ToolItem() self._freq_range_tool.add(self._freq_range) toolbar.insert(self._freq_stepper_up, -1) toolbar.insert(self._freq_range_tool, -1) toolbar.insert(self._freq_stepper_down, -1) return def update_trigger_control(self, *args): ''' Callback for trigger control ''' if self.activity.wave.get_fft_mode(): self.trigger_combo.set_active(self.activity.wave.TRIGGER_NONE) active = self.trigger_combo.get_active() if active == -1: return self.activity.wave.set_trigger(self.trigger_conf[active]) return def analog_resistance_voltage_mode_cb(self, button=None, mode_to_set='sound'): ''' Callback for Analog/Resistance/Voltage Buttons ''' if self._lock_radio_buttons: logging.debug('mode selector locked') self._radio_button_pushed = True return if self.mode == mode_to_set: logging.debug('mode already set to %s' % mode_to_set) return self._lock_radio_buttons = True if self.activity.CONTEXT == 'sound': self.sound_context_off() else: self.sensor_context_off() # Force time domain when switching modes if self.activity.wave.get_fft_mode(): self.activity.timefreq_control() # Turn off logging when switching modes if self.activity.audiograb.we_are_logging: self.record_control_cb() self.set_mode(mode_to_set) if mode_to_set == 'sound': self.set_sound_context() elif mode_to_set == 'resistance': self.set_sensor_context() elif mode_to_set == 'voltage': self.set_sensor_context() self.update_string_for_textbox() return False def unlock_radio_buttons(self): ''' Enable radio button selection ''' logging.debug('unlocking radio buttons') if self._radio_button_pushed: if self.mode == 'sound': self.time.set_active(True) elif self.mode == 'resistance': self.resistance.set_active(True) elif self.mode == 'voltage': self.voltage.set_active(True) self._lock_radio_buttons = False self._radio_button_pushed = False def set_mode(self, mode='sound'): ''' Set the mixer settings to match the current mode. ''' self.mode = mode self.activity.audiograb.set_sensor_type(self.mode) for i in range(self._channels): self.values[i] = 0.0 return def get_mode(self): ''' Get the mixer settings. ''' return self.mode def _freq_stepper_up_cb(self, button=None): ''' Moves the horizontal zoom slider to the left one notch, where one notch is 1/100 of the total range. This correspond to zooming out as a larger number of Hertz or milliseconds will be represented by the same space on the screen. ''' new_value = self._freq_range.get_value() +\ (self.UPPER - self.LOWER) / 100.0 if new_value <= self.UPPER: self._freq_range.set_value(new_value) else: self._freq_range.set_value(self.UPPER) def _freq_stepper_down_cb(self, button=None): ''' Moves the horizontal zoom slider to the right one notch, where one notch is 1/100 of the total range. This corresponds to zooming in. ''' new_value = self._freq_range.get_value() -\ (self.UPPER - self.LOWER) / 100.0 if new_value >= self.LOWER: self._freq_range.set_value(new_value) else: self._freq_range.set_value(self.LOWER) def cb_page_sizef(self, button=None): ''' Callback to scale the frequency range (zoom in and out) ''' if self._update_page_size_id: gobject.source_remove(self._update_page_size_id) self._update_page_size_id =\ gobject.timeout_add(250, self.update_page_size) return True def update_page_size(self): ''' Set up the scaling of the display. ''' self._update_page_size_id = None new_value = round(self.activity.adjustmentf.value * 100.0) / 100.0 if self.activity.adjustmentf.value != new_value: self.activity.adjustmentf.value = new_value return False time_div = 0.001 * max(self.activity.adjustmentf.value, 0.05) freq_div = 1000 * max(self.activity.adjustmentf.value, 0.01) self.activity.wave.set_div(time_div, freq_div) self.update_string_for_textbox() return False def set_sound_context(self): ''' Called when analog sensing is selected ''' self.set_show_hide_windows(mode='sound') gobject.timeout_add(500, self.sound_context_on) self.activity.CONTEXT = 'sound' def set_sensor_context(self): ''' Called when digital sensing is selected ''' self.set_show_hide_windows(mode='sensor') gobject.timeout_add(500, self.sensor_context_on) self.activity.CONTEXT = 'sensor' def set_show_hide_windows(self, mode='sound'): ''' Shows the appropriate window identified by the mode ''' self.activity.wave.set_context_on() for i in range(self._channels): self.activity.side_toolbars[i].set_show_hide(True, mode) def sensor_context_off(self): ''' Called when a DC sensor is no longer selected ''' # self.activity.audiograb.pause_grabbing() self.activity.audiograb.stop_grabbing() def sensor_context_on(self): ''' Called when a DC sensor is selected ''' self.update_string_for_textbox() self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE) # self.activity.audiograb.resume_grabbing() self.activity.audiograb.start_grabbing() return False def sound_context_off(self): ''' Called when an analog sensor is no longer selected ''' self.gain, self.y_mag = self.activity.wave.get_mag_params() self.capture_gain = self.activity.audiograb.get_capture_gain() self.mic_boost = self.activity.audiograb.get_mic_boost() self.activity.audiograb.stop_grabbing() def sound_context_on(self): ''' Called when an analog sensor is selected ''' self.activity.wave.set_mag_params(self.gain, self.y_mag) self.update_string_for_textbox() self.update_trigger_control() self.activity.audiograb.start_grabbing() return False def set_sample_value(self, value='', channel=0): ''' Write a sample value to the textbox. ''' gtk.threads_enter() self.values[channel] = value self.update_string_for_textbox() gtk.threads_leave() return def record_control_cb(self, button=None): ''' Depending upon the selected interval, does either a logging session, or just logs the current buffer. ''' if self.activity.audiograb.we_are_logging: self.activity.audiograb.set_logging_params(start_stop=False) self._record.set_icon('media-record') self._record.show() self._record.set_tooltip(_('Start Recording')) else: Xscale = (1.00 / self.activity.audiograb.get_sampling_rate()) Yscale = 0.0 interval = self.interval_convert() username = self.activity.nick if self.activity.wave.get_fft_mode(): self.activity.data_logger.start_new_session( username, Xscale, Yscale, _(self.logging_interval_status), channels=self._channels, mode='frequency') else: self.activity.data_logger.start_new_session( username, Xscale, Yscale, _(self.logging_interval_status), channels=self._channels, mode=self.mode) self.activity.audiograb.set_logging_params(start_stop=True, interval=interval, screenshot=False) self._record.set_icon('record-stop') self._record.show() self._record.set_tooltip(_('Stop Recording')) self.activity.new_recording = True def interval_convert(self): ''' Converts interval string to an integer that denotes the number of times the audiograb buffer must be called before a value is written. When set to 0, the whole of current buffer will be written. ''' interval_dictionary = { '1/10 second': 0.1, '1 second': 1, '30 seconds': 30, '5 minutes': 300, '30 minutes': 1800 } try: return interval_dictionary[self.logging_interval_status] except ValueError: logging.error('logging interval status = %s' %\ (str(self.logging_interval_status))) return 0 def log_interval_cb(self, combobox): ''' Callback from the Logging Interval Combo box: sets status ''' if self._log_interval_combo.get_active() != -1: intervals = [ '1/10 second', '1 second', '30 seconds', '5 minutes', '30 minutes' ] self.logging_interval_status = \ intervals[self._log_interval_combo.get_active()] def update_string_for_textbox(self): ''' Update the status field at the bottom of the canvas. ''' if self.activity.CONTEXT == 'butia': string_for_textbox = '' else: if self.mode == 'resistance': string_for_textbox = (self.STR_DC_R + '\n') string_for_textbox += self.STR_RESISTANCE elif self.mode == 'voltage': string_for_textbox = (self.STR_DC_V + '\n') string_for_textbox += self.STR_VOLTAGE else: string_for_textbox = (self.STR_AC + '\t') if self.activity.wave.get_fft_mode(): scalex = self.STR_XAXIS_TEXT % { 'unit': self.HZ, 'division': self.activity.wave.freq_div } string_for_textbox += self.STR_FREQUENCY string_for_textbox += ('\n' + scalex) elif self.mode == 'sound': scalex = self.STR_XAXIS_TEXT % { 'unit': self.MS, 'division': self.activity.wave.time_div * 1000 } string_for_textbox += self.STR_TIME string_for_textbox += ('\n' + scalex) else: for i in range(self._channels): string_for_textbox += '\t(%s)' % (self.values[i]) invert = False for i in range(self._channels): if self.activity.wave.get_invert_state(channel=i): invert = True if invert: string_for_textbox += self.STR_INVERT self.activity.text_box.set_label(string_for_textbox)
class Activity(sugar.activity.activity.Activity): def __init__(self, handle): super(Activity, self).__init__(handle) self.paused = False watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(watch) self.p = gtk.VPaned() self.p.connect("notify::position", self.redraw) self.box = gtk.Notebook() self.p.pack2(self.box) self.p.show() self.box.set_show_tabs(False) self.splash = gtk.Image() pixbuf = gtk.gdk.pixbuf_new_from_file("images/splash-colgadito.png") screen = self.window.get_screen() width, height = screen.get_width(), screen.get_height() - style.GRID_CELL_SIZE pixbuf = pixbuf.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR) self.splash.set_from_pixbuf(pixbuf) self.splash.show() eb = gtk.EventBox() eb.add(self.splash) eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("white")) eb.show() self.box.append_page(eb, gtk.Label("Inicio")) self._pygamecanvas = sugargame2.canvas.PygameCanvas(self) self._pygamecanvas.set_flags(gtk.EXPAND) self._pygamecanvas.set_flags(gtk.FILL) self.connect("visibility-notify-event", self.redraw) self._pygamecanvas.set_events(gtk.gdk.BUTTON_PRESS_MASK) self._pygamecanvas.connect("button-press-event", self._pygamecanvas.grab_focus) self.box.append_page(self._pygamecanvas, gtk.Label("Juego")) self.box.show() self.set_canvas(self.p) gobject.timeout_add(300, self.pump) gobject.timeout_add(2000, self.init_interpreter) #gobject.timeout_add(1000, self.build_editor) gobject.timeout_add(1500, self.check_modified) self.build_toolbar() self.credits = None self.editor = None self._pygamecanvas.run_pygame(self.run_game) def redraw(self, widget=None, b=None, c=None): scene = spyral.director.get_scene() if scene: scene.redraw() def alert(self, title=None, text=None, delay=5): alert = NotifyAlert(delay) alert.props.title = title alert.props.msg = text print text self.add_alert(alert) alert.connect('response', self._alert_ok) alert.show() def _alert_ok(self, alert, *args): self.remove_alert(alert) def check_modified(self): if self.box.current_page()==2: if not self.save_button.get_sensitive(): if self.editor.modificado(): self.save_button.set_sensitive(True) return False return True def pump(self): # Esto es necesario porque sino pygame acumula demasiados eventos. pygame.event.pump() def focus_interpreter(self, widget, event): self._interpreter.text.grab_focus() return True def init_interpreter(self): # diferido unos segundos para evitar ver errores superfluos al iniciar self._interpreter = GTKInterpreterConsole(self.redraw) self._interpreter.text.connect('button-press-event', self.focus_interpreter) self.p.pack1(self._interpreter) return False def open_file(self, widget, path): if path: if not os.path.isdir(path): self.editor.open_file(widget, path) def save_file(self, widget): if self.editor.modificado(): self.save_button.set_sensitive(False) self.editor.save_file() filename = self.editor.current_file() self.alert(filename, "Archivo guardado.") gobject.timeout_add(1500, self.check_modified) def build_editor(self): dir_real = os.getcwd() f = os.path.realpath(JUEGO.__file__) f = "." + f.replace(dir_real ,"") # todo esto para obtener una ruta relativa f = f.rstrip("c") # en caso que sea .pyc compilado self.h = gtk.HPaned() self.tree = FileViewer(".", os.path.basename(f)) self.tree.connect("file-selected", self.open_file) self.tree.show() self.h.pack1(self.tree) self.box.append_page(self.h, gtk.Label("Editor")) if False: #os.path.isfile("/usr/bin/gvim"): # Si podemos, lo hacemos self.socket = gtk.Socket() self.socket.show() self.h.pack2(self.socket) sock_id = str(self.socket.get_id()) self.editor = VimSourceView(sock_id) if not self.editor.bufInfo.bufferList: f = JUEGO.__file__ if f.endswith("pyc"): f = f[:-1] self.open_file(None, f) else: self.editor = SourceView() scroller = gtk.ScrolledWindow() scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroller.add(self.editor) scroller.show() self.h.pack2(scroller) self.editor.show() self.h.show() self.open_file(None, f) def build_toolbar(self): toolbar_box = ToolbarBox() self.set_toolbar_box(toolbar_box) toolbar_box.show() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, -1) activity_button.show() tool_group = None self.game_button = RadioToolButton() self.game_button.props.icon_name = 'gamecanvas' self.game_button.set_tooltip(_('Juego')) self.game_button.accelerator = "<Ctrl>1" self.game_button.props.group = tool_group self.game_button.connect('clicked', self.show_game) toolbar_box.toolbar.insert(self.game_button, -1) self.game_button.show() tool_group = self.game_button button = RadioToolButton() button.props.icon_name = 'view-source' button.set_tooltip(_('Editor')) button.accelerator = "<Ctrl>2" button.props.group = tool_group button.connect('clicked', self.show_editor) toolbar_box.toolbar.insert(button, -1) button.show() self.save_button = ToolButton('dialog-ok') self.save_button.set_tooltip(_('Guardar')) self.save_button.accelerator = "<Ctrl>s" self.save_button.connect('clicked', self.save_file) self.save_button.set_sensitive(False) toolbar_box.toolbar.insert(self.save_button, -1) self.save_button.show() separator = gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() button = ToolButton('system-restart') button.set_tooltip(_('Reiniciar juego')) button.accelerator = "<Alt><Shift>r" button.connect('clicked', self.restart_game) toolbar_box.toolbar.insert(button, -1) button.show() self.editor_button = ToolButton('sources') self.editor_button.set_tooltip(_('Consola')) self.editor_button.accelerator = "<Ctrl>grave" self.editor_button.connect('clicked', self.toggle_console) toolbar_box.toolbar.insert(self.editor_button, -1) self.editor_button.show() separator = gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) separator.show() button = helpbutton.HelpButton(self) toolbar_box.toolbar.insert(button, -1) button.show() button = ToolButton() button.props.icon_name = 'activity-about' button.set_tooltip(_('Acerca de')) button.accelerator = "<Ctrl>i" button.connect('clicked', self.run_credits) toolbar_box.toolbar.insert(button, -1) button.show() # Blank space (separator) and Stop button at the end: 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() def run_game(self): spyral.director.init((0,0), fullscreen=False, max_fps=30) self.game = JUEGO.Game(activity=self) self.box.connect("switch-page", self.redraw) spyral.director.push(self.game) self.start() def run_credits(self, widget): if not (spyral.director.get_scene()==self.credits): self.credits = game.credits.Creditos(self.game.size) spyral.director.push(self.credits) def start(self): #try: spyral.director.run(sugar = True) #except AttributeError as detail: # detail2 = traceback.format_exc() # self.box.set_page(0) # self.alert( detail2, "Spyral se ha detenido abruptamente.", 60) def show_game(self, widget): self.box.set_page(1) self.redraw() def show_editor(self, widget): if not self.editor: self.build_editor() self.box.set_page(2) self.redraw() def restart_game(self, widget): global JUEGO import objetos try: objetos.reset() except AttributeError: pass self.show_game(None) watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self.window.set_cursor(watch) JUEGO = reload(JUEGO) self.game = JUEGO.Game(activity=self) spyral.director.replace(self.game) self.start() def game_ready(self, widget = None): self.game_button.set_active(True) self.box.set_page(1) self._pygamecanvas.grab_focus() self.window.set_cursor(None) def read_file(self, file_path): pass def write_file(self, file_path): pass def can_close(self): if self.editor: self.editor.close() self.box.set_page(0) try: spyral.director.quit() except spyral.exceptions.GameEndException: pass finally: return True def toggle_console(self, e): if self._interpreter.props.visible: self._interpreter.hide() self._pygamecanvas.grab_focus() else: self.p.set_position(160) self._interpreter.show() self._interpreter.text.grab_focus() self.redraw() def animate_console(self): easing = spyral.easing.Linear(0,160) self.p.set_position(0)
class TagStar(gtk.HBox): """ A L{gtk.HBox} which arranges togglebuttons around the current position within a L{gtk.Fixed} widget. This is the central tag element, where a user can either tag his current position with a category specified in L{geotagplugin.ECategory}. If one of the user's already tagged features is selected in the tree, the made change action will be handled as an edit. """ IMG_SIZE = (100, 100) BUTTON_SIZE = (100, 100) EMPTY_LIST_STORE = gtk.ListStore(gobject.TYPE_STRING) toggled = NONE_CATEGORY # selected category selected = None # gtk.Image displaying selected category def __init__(self, toolbar, control): gtk.HBox.__init__(self) self._logger = logging.getLogger('TagStar') self._logger.setLevel(constants.LOG_LEVEL) self.toolbar = toolbar self.control = control self.size_cb = self.connect('size_allocate', self.size_allocate_cb) self.fixed = gtk.Fixed() self.pack_start(self.fixed) self.show_all() def size_allocate_cb(self, widget, event): """ Builds the tag star around the center where the selected category is shown. """ self._logger.debug('size_allocate_cb()') x, y, width, height = self.fixed.get_allocation() self._logger.debug('x: %s, y: %s, w: %s, h: %s', x, y, width, height) self.set_size_request(width, height) ###################################################################### # place togglebuttons around the current position in a radio group color_fill = profile.get_color().get_fill_color() color_stroke = profile.get_color().get_stroke_color() button_width, button_height = self.BUTTON_SIZE cat_names = get_categories() radius = 300 # px x_center = width / 2 - 40 y_center = height / 2 - 40 step_angle = math.radians(360 / (len(cat_names) + 1)) # plus reset btn # add a reset button self.reset_selected_btn = RadioToolButton() img_name = os.path.join(GeoTag.ICONS_PATH, 'reset.svg') icon = gtk.image_new_from_pixbuf(utils.load_svg_image(img_name, color_stroke, color_fill, self.IMG_SIZE)) self.reset_selected_btn.set_icon_widget(icon) self.reset_selected_btn.set_tooltip(_('Reset selected tag.')) self.reset_selected_btn.connect('clicked', self.reset_toggled) self.reset_selected_btn.show_all() self.reset_selected_btn.set_size_request(button_width, button_height) self.fixed.put(self.reset_selected_btn, x_center, # + int(radius * math.sin(i * step_angle)), y_center + radius) # + int(radius * math.cos(i * step_angle))) self.reset_selected_btn.set_active(False) # read all available categories dynamically for i, category in enumerate(cat_names): button = RadioToolButton(group=self.reset_selected_btn) img_name = os.path.join(GeoTag.ICONS_PATH, category) icon = get_gtkimage_from_plugin(img_name, color_stroke, color_fill, self.IMG_SIZE) button.set_icon_widget(icon) button.set_tooltip(_('Tag some %s.' % category)) # XXX check translation here!! button.connect('clicked', self.set_toggled, category) button.show_all() button.set_size_request(button_width, button_height) self.fixed.put(button, x_center + int(radius * math.sin((i + 1) * step_angle)), y_center + int(radius * math.cos((i + 1) * step_angle))) button.set_active(False) img_name = os.path.join(GeoTag.ICONS_PATH, NONE_CATEGORY) self._set_selected(get_gtkimage_from_plugin(img_name, color_stroke,color_fill, self.IMG_SIZE)) ################################################################### self._logger.debug("size_allocation done") self.disconnect(self.size_cb) ## use only once def reset_toggled(self, button): """ Resets toggled property and combobox liststore. @param button: The reset button (can be omitted by passing None). @note: If a tag was selected within the L{geotagmodel.GeotagModel}, the tag will be deleted. """ self.toggled = NONE_CATEGORY # reset liststore combo = self.toolbar.combobox combo.set_model(self.EMPTY_LIST_STORE) # reset selected widget color_fill = profile.get_color().get_fill_color() color_stroke = profile.get_color().get_stroke_color() self._set_selected(get_gtkimage_from_plugin(NONE_CATEGORY, color_stroke, color_fill, self.IMG_SIZE)) self.reset_selected_btn.set_active(True) self.selected.queue_draw() combo.queue_draw() def set_toggled(self, button, category): """ Switches the empty Button and the tagged category button clicked. Also, sets the appropriate liststore for the combobox. @param button: Toggled button (can be omittted). @param category: The corresponding category to set. """ self._logger.debug("set_toggled()") self.toggled = category # set liststore combo = self.toolbar.combobox combo.set_model(self.toolbar.description_sets[category]) color_fill = profile.get_color().get_fill_color() color_stroke = profile.get_color().get_stroke_color() # self._logger.debug("storage type: %s", self.selected.get_property("storage-type")) self._set_selected(get_gtkimage_from_plugin(category, color_stroke, color_fill, self.IMG_SIZE)) combo.queue_draw() def _set_selected(self, widget): """ Sets the widget as the currently selected tag category. @param widget: The L{gtk.Image} to set. """ x, y, width, height = self.fixed.get_allocation() x_center = width / 2 - 40 y_center = height / 2 - 40 if self.selected: self.selected.clear() button_width, button_height = self.BUTTON_SIZE widget.set_size_request(button_width, button_height) widget.show_all() self.selected = widget self.selected.queue_draw() self.fixed.put(self.selected, x_center, y_center)
def size_allocate_cb(self, widget, event): """ Builds the tag star around the center where the selected category is shown. """ self._logger.debug('size_allocate_cb()') x, y, width, height = self.fixed.get_allocation() self._logger.debug('x: %s, y: %s, w: %s, h: %s', x, y, width, height) self.set_size_request(width, height) ###################################################################### # place togglebuttons around the current position in a radio group color_fill = profile.get_color().get_fill_color() color_stroke = profile.get_color().get_stroke_color() button_width, button_height = self.BUTTON_SIZE cat_names = get_categories() radius = 300 # px x_center = width / 2 - 40 y_center = height / 2 - 40 step_angle = math.radians(360 / (len(cat_names) + 1)) # plus reset btn # add a reset button self.reset_selected_btn = RadioToolButton() img_name = os.path.join(GeoTag.ICONS_PATH, 'reset.svg') icon = gtk.image_new_from_pixbuf(utils.load_svg_image(img_name, color_stroke, color_fill, self.IMG_SIZE)) self.reset_selected_btn.set_icon_widget(icon) self.reset_selected_btn.set_tooltip(_('Reset selected tag.')) self.reset_selected_btn.connect('clicked', self.reset_toggled) self.reset_selected_btn.show_all() self.reset_selected_btn.set_size_request(button_width, button_height) self.fixed.put(self.reset_selected_btn, x_center, # + int(radius * math.sin(i * step_angle)), y_center + radius) # + int(radius * math.cos(i * step_angle))) self.reset_selected_btn.set_active(False) # read all available categories dynamically for i, category in enumerate(cat_names): button = RadioToolButton(group=self.reset_selected_btn) img_name = os.path.join(GeoTag.ICONS_PATH, category) icon = get_gtkimage_from_plugin(img_name, color_stroke, color_fill, self.IMG_SIZE) button.set_icon_widget(icon) button.set_tooltip(_('Tag some %s.' % category)) # XXX check translation here!! button.connect('clicked', self.set_toggled, category) button.show_all() button.set_size_request(button_width, button_height) self.fixed.put(button, x_center + int(radius * math.sin((i + 1) * step_angle)), y_center + int(radius * math.cos((i + 1) * step_angle))) button.set_active(False) img_name = os.path.join(GeoTag.ICONS_PATH, NONE_CATEGORY) self._set_selected(get_gtkimage_from_plugin(img_name, color_stroke,color_fill, self.IMG_SIZE)) ################################################################### self._logger.debug("size_allocation done") self.disconnect(self.size_cb) ## use only once
class SensorToolbar(gtk.Toolbar): """ The toolbar for specifiying the sensor: sound, resitance, or voltage """ LOWER = 0.0 UPPER = 1.0 STR_DC_R = ( _( "Resistive sensor (connect sensor to pink 'Mic In' on left side \ of XO)" ) + " " ) STR_DC_V = ( _( "Voltage sensor (connect sensor to pink 'Mic In' on left side \ of XO)" ) + " " ) STR_AC = _("Sound") + " " STR_RESISTANCE = _("Resistance") + " (" + _("Ohms") + ") " STR_VOLTAGE = _("Voltage") + " (" + _("Volts") + ") " STR_TIME = _("Time Base") + " " STR_FREQUENCY = _("Frequency Base") + " " STR_INVERT = " " + _("Invert") + " " STR_XAXIS_TEXT = _("X Axis Scale: 1 division = %(division)s %(unit)s") # TRANSLATORS: This is milli seconds. MS = _("ms") # TRANSLATORS: This is Hertz, so 1/second. HZ = _("Hz") def __init__(self, activity, channels): """ By default, start with resistance mode """ gtk.Toolbar.__init__(self) self.activity = activity self._channels = channels self._lock_radio_buttons = False self._radio_button_pushed = False self.values = [] for i in range(self._channels): self.values.append("") self.string_for_textbox = "" self.gain = 1.0 self.y_mag = 3.0 self.capture_gain = CAPTURE_GAIN self.mic_boost = MIC_BOOST self.mode = "sound" # Set up Time-domain Button self.time = RadioToolButton(group=None) self.time.set_named_icon("media-audio") self.insert(self.time, -1) self.time.set_tooltip(_("Sound")) self.time.connect("clicked", self.analog_resistance_voltage_mode_cb, "sound") # Set up Resistance Button self.resistance = RadioToolButton(group=self.time) self.resistance.set_named_icon("resistance") if _is_xo(self.activity.hw): self.insert(self.resistance, -1) self.resistance.show() self.resistance.set_tooltip(_("Resistance Sensor")) self.resistance.connect("clicked", self.analog_resistance_voltage_mode_cb, "resistance") # Set up Voltage Button self.voltage = RadioToolButton(group=self.time) self.voltage.set_named_icon("voltage") if _is_xo(self.activity.hw): self.insert(self.voltage, -1) self.voltage.set_tooltip(_("Voltage Sensor")) self.voltage.connect("clicked", self.analog_resistance_voltage_mode_cb, "voltage") separator = gtk.SeparatorToolItem() separator.props.draw = True self.insert(separator, -1) self._log_value = LOG_TIMER_VALUES[1] self.log_label = gtk.Label(self._log_to_string(self._log_value)) toolitem = gtk.ToolItem() toolitem.add(self.log_label) self.insert(toolitem, -1) self._log_button = ToolButton("timer-10") self._log_button.set_tooltip(_("Select logging interval")) self._log_button.connect("clicked", self._log_selection_cb) self.insert(self._log_button, -1) self._setup_log_palette() # Set up Logging/Stop Logging Button self._record = ToolButton("media-record") self.insert(self._record, -1) self._record.set_tooltip(_("Start logging")) self._record.connect("clicked", self.record_control_cb) separator = gtk.SeparatorToolItem() separator.props.draw = True self.insert(separator, -1) toolitem = gtk.ToolItem() self.trigger_label = gtk.Label(_("Trigger")) toolitem.add(self.trigger_label) self.insert(toolitem, -1) # Set up Trigger Combo box self.trigger_none = RadioToolButton() self.trigger_none.set_named_icon("trigger-none") self.insert(self.trigger_none, -1) self.trigger_none.set_tooltip(_("None")) self.trigger_none.connect("clicked", self.update_trigger_control_cb, self.activity.wave.TRIGGER_NONE) self.trigger_rise = RadioToolButton(group=self.trigger_none) self.trigger_rise.set_named_icon("trigger-rise") self.insert(self.trigger_rise, -1) self.trigger_rise.set_tooltip(_("Rising Edge")) self.trigger_rise.connect("clicked", self.update_trigger_control_cb, self.activity.wave.TRIGGER_POS) self.trigger_fall = RadioToolButton(group=self.trigger_none) self.trigger_fall.set_named_icon("trigger-fall") self.insert(self.trigger_fall, -1) self.trigger_fall.set_tooltip(_("Falling Edge")) self.trigger_fall.connect("clicked", self.update_trigger_control_cb, self.activity.wave.TRIGGER_NEG) self.show_all() def get_log(self): return self._log_value def get_log_idx(self): if self._log_value in LOG_TIMER_VALUES: return LOG_TIMER_VALUES.index(self._log_value) else: return LOG_TIMER_VALUES[0] def set_log_idx(self, idx): self._log_value = LOG_TIMER_VALUES[idx] self.log_label.set_text(self._log_to_string(self._log_value)) if hasattr(self, "_log_button"): self._log_button.set_icon("timer-%d" % (self._log_value)) def _log_selection_cb(self, widget): if self._log_palette: if not self._log_palette.is_up(): self._log_palette.popup(immediate=True, state=self._log_palette.SECONDARY) else: self._log_palette.popdown(immediate=True) return def _log_to_seconds(self, tenth_seconds): return tenth_seconds / 10.0 def _log_to_string(self, tenth_seconds): if tenth_seconds in LOG_TIMER_LABELS: return LOG_TIMER_LABELS[tenth_seconds] else: return _("1 second") def _setup_log_palette(self): self._log_palette = self._log_button.get_palette() for tenth_seconds in LOG_TIMER_VALUES: text = self._log_to_string(tenth_seconds) menu_item = MenuItem(icon_name="timer-%d" % (tenth_seconds), text_label=self._log_to_string(tenth_seconds)) menu_item.connect("activate", self._log_selected_cb, tenth_seconds) self._log_palette.menu.append(menu_item) menu_item.show() def _log_selected_cb(self, button, seconds): self.set_log_idx(LOG_TIMER_VALUES.index(seconds)) def add_frequency_slider(self, toolbox): """ Either on the Sound toolbar or the Main toolbar """ self._freq_stepper_up = ToolButton("freq-high") self._freq_stepper_up.set_tooltip(_("Zoom out")) self._freq_stepper_up.connect("clicked", self._freq_stepper_up_cb) self._freq_stepper_up.show() self.activity.adjustmentf = gtk.Adjustment(0.5, self.LOWER, self.UPPER, 0.01, 0.1, 0) self.activity.adjustmentf.connect("value_changed", self.cb_page_sizef) self._freq_range = gtk.HScale(self.activity.adjustmentf) self._freq_range.set_inverted(True) self._freq_range.set_draw_value(False) self._freq_range.set_update_policy(gtk.UPDATE_CONTINUOUS) self._freq_range.set_size_request(120, 15) self._freq_range.show() self._freq_stepper_down = ToolButton("freq-low") self._freq_stepper_down.set_tooltip(_("Zoom in")) self._freq_stepper_down.connect("clicked", self._freq_stepper_down_cb) self._freq_stepper_down.show() self._freq_range_tool = gtk.ToolItem() self._freq_range_tool.add(self._freq_range) self._freq_range_tool.show() toolbox.add(self._freq_stepper_up) toolbox.add(self._freq_range_tool) toolbox.add(self._freq_stepper_down) return def update_trigger_control_cb(self, button, value): if button is None: value = self.activity.wave.TRIGGER_NONE if self.activity.wave.get_fft_mode(): self.trigger_none.set_active(True) else: self.activity.wave.set_trigger(value) def analog_resistance_voltage_mode_cb(self, button=None, mode_to_set="sound"): """ Callback for Analog/Resistance/Voltage Buttons """ if self._lock_radio_buttons: logging.debug("mode selector locked") self._radio_button_pushed = True return if self.mode == mode_to_set: logging.debug("mode already set to %s" % mode_to_set) return self._lock_radio_buttons = True if self.activity.CONTEXT == "sound": self.sound_context_off() else: self.sensor_context_off() # Force time domain when switching modes if self.activity.wave.get_fft_mode(): self.activity.timefreq_control() # Turn off logging when switching modes if self.activity.audiograb.we_are_logging: self.record_control_cb() self.set_mode(mode_to_set) if mode_to_set == "sound": self.set_sound_context() elif mode_to_set == "resistance": self.set_sensor_context() elif mode_to_set == "voltage": self.set_sensor_context() self.update_string_for_textbox() return False def unlock_radio_buttons(self): """ Enable radio button selection """ logging.debug("unlocking radio buttons") if self._radio_button_pushed: if self.mode == "sound": self.time.set_active(True) elif self.mode == "resistance": self.resistance.set_active(True) elif self.mode == "voltage": self.voltage.set_active(True) self._lock_radio_buttons = False self._radio_button_pushed = False def set_mode(self, mode="sound"): """ Set the mixer settings to match the current mode. """ self.mode = mode self.activity.audiograb.set_sensor_type(self.mode) for i in range(self._channels): self.values[i] = 0.0 return def get_mode(self): """ Get the mixer settings. """ return self.mode def _freq_stepper_up_cb(self, button=None): """ Moves the horizontal zoom slider to the left one notch, where one notch is 1/100 of the total range. This correspond to zooming out as a larger number of Hertz or milliseconds will be represented by the same space on the screen. """ new_value = self._freq_range.get_value() + (self.UPPER - self.LOWER) / 100.0 if new_value <= self.UPPER: self._freq_range.set_value(new_value) else: self._freq_range.set_value(self.UPPER) def _freq_stepper_down_cb(self, button=None): """ Moves the horizontal zoom slider to the right one notch, where one notch is 1/100 of the total range. This corresponds to zooming in. """ new_value = self._freq_range.get_value() - (self.UPPER - self.LOWER) / 100.0 if new_value >= self.LOWER: self._freq_range.set_value(new_value) else: self._freq_range.set_value(self.LOWER) def cb_page_sizef(self, button=None): """ Callback to scale the frequency range (zoom in and out) """ if self._update_page_size_id: gobject.source_remove(self._update_page_size_id) self._update_page_size_id = gobject.timeout_add(250, self.update_page_size) return True def update_page_size(self): """ Set up the scaling of the display. """ self._update_page_size_id = None new_value = round(self.activity.adjustmentf.value * 100.0) / 100.0 if self.activity.adjustmentf.value != new_value: self.activity.adjustmentf.value = new_value return False time_div = 0.001 * max(self.activity.adjustmentf.value, 0.05) freq_div = 1000 * max(self.activity.adjustmentf.value, 0.01) self.activity.wave.set_div(time_div, freq_div) self.update_string_for_textbox() return False def set_sound_context(self): """ Called when analog sensing is selected """ self.set_show_hide_windows(mode="sound") gobject.timeout_add(500, self.sound_context_on) self.activity.CONTEXT = "sound" def set_sensor_context(self): """ Called when digital sensing is selected """ self.set_show_hide_windows(mode="sensor") gobject.timeout_add(500, self.sensor_context_on) self.activity.CONTEXT = "sensor" def set_show_hide_windows(self, mode="sound"): """ Shows the appropriate window identified by the mode """ self.activity.wave.set_context_on() for i in range(self._channels): self.activity.side_toolbars[i].set_show_hide(True, mode) def sensor_context_off(self): """ Called when a DC sensor is no longer selected """ # self.activity.audiograb.pause_grabbing() self.activity.audiograb.stop_grabbing() def sensor_context_on(self): """ Called when a DC sensor is selected """ self.update_string_for_textbox() self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE) # self.activity.audiograb.resume_grabbing() self.activity.audiograb.start_grabbing() return False def sound_context_off(self): """ Called when an analog sensor is no longer selected """ self.gain, self.y_mag = self.activity.wave.get_mag_params() self.capture_gain = self.activity.audiograb.get_capture_gain() self.mic_boost = self.activity.audiograb.get_mic_boost() self.activity.audiograb.stop_grabbing() def sound_context_on(self): """ Called when an analog sensor is selected """ self.activity.wave.set_mag_params(self.gain, self.y_mag) self.update_string_for_textbox() self.update_trigger_control_cb(None, self.activity.wave.TRIGGER_NONE) self.activity.audiograb.start_grabbing() return False def set_sample_value(self, value="", channel=0): """ Write a sample value to the textbox. """ gtk.threads_enter() self.values[channel] = value self.update_string_for_textbox() gtk.threads_leave() return def record_control_cb(self, button=None): """ Depending upon the selected interval, does either a logging session, or just logs the current buffer. """ if self.activity.audiograb.we_are_logging: self.activity.audiograb.set_logging_params(start_stop=False) self._record.set_icon("media-record") self._record.show() self._record.set_tooltip(_("Start Recording")) else: Xscale = 1.00 / self.activity.audiograb.get_sampling_rate() Yscale = 0.0 interval = self._log_value / 10.0 # self.interval_convert() username = self.activity.nick if self.activity.wave.get_fft_mode(): self.activity.data_logger.start_new_session( username, Xscale, Yscale, self._log_to_string(self._log_value), channels=self._channels, mode="frequency", ) else: self.activity.data_logger.start_new_session( username, Xscale, Yscale, self._log_to_string(self._log_value), channels=self._channels, mode=self.mode, ) self.activity.audiograb.set_logging_params(start_stop=True, interval=interval, screenshot=False) self._record.set_icon("record-stop") self._record.show() self._record.set_tooltip(_("Stop Recording")) self.activity.new_recording = True def update_string_for_textbox(self): """ Update the status field at the bottom of the canvas. """ if self.mode == "resistance": string_for_textbox = self.STR_DC_R + "\n" string_for_textbox += self.STR_RESISTANCE elif self.mode == "voltage": string_for_textbox = self.STR_DC_V + "\n" string_for_textbox += self.STR_VOLTAGE else: string_for_textbox = self.STR_AC + "\t" if self.activity.wave.get_fft_mode(): scalex = self.STR_XAXIS_TEXT % {"unit": self.HZ, "division": self.activity.wave.freq_div} string_for_textbox += self.STR_FREQUENCY string_for_textbox += "\n" + scalex elif self.mode == "sound": scalex = self.STR_XAXIS_TEXT % {"unit": self.MS, "division": self.activity.wave.time_div * 1000} string_for_textbox += self.STR_TIME string_for_textbox += "\n" + scalex else: for i in range(self._channels): string_for_textbox += "\t(%s)" % (self.values[i]) invert = False for i in range(self._channels): if self.activity.wave.get_invert_state(channel=i): invert = True if invert: string_for_textbox += self.STR_INVERT self.activity.text_box.set_label(string_for_textbox)
def __init__(self, handle): activity.Activity.__init__(self, handle, True) self.max_participants = 1 # CHART_OPTIONS self.x_label = "" self.y_label = "" self.chart_color = utils.get_user_fill_color('str') self.chart_line_color = utils.get_user_stroke_color('str') self.current_chart = None self.charts_area = None self.chart_data = [] # TOOLBARS toolbarbox = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_btn_toolbar = activity_button.page activity_btn_toolbar.title.connect('changed', self._set_chart_title) save_as_image = ToolButton("save-as-image") save_as_image.connect("clicked", self._save_as_image) save_as_image.set_tooltip(_("Save as image")) activity_btn_toolbar.insert(save_as_image, -1) save_as_image.show() toolbarbox.toolbar.insert(activity_button, 0) import_freespace = ToolButton("import-freespace") import_freespace.connect("clicked", self.__import_freespace_cb) import_freespace.set_tooltip(_("Read Freespace data")) toolbarbox.toolbar.insert(import_freespace, -1) import_freespace.show() import_journal = ToolButton('import-journal') import_journal.connect('clicked', self.__import_journal_cb) import_journal.set_tooltip(_('Read Journal data')) toolbarbox.toolbar.insert(import_journal, -1) import_journal.show() import_turtle = ToolButton('import-turtle') import_turtle.connect('clicked', self.__import_turtle_cb) import_turtle.set_tooltip(_('Read Turtle data')) toolbarbox.toolbar.insert(import_turtle, -1) import_turtle.show() separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) add_vbar_chart = RadioToolButton() add_vbar_chart.connect("clicked", self._add_chart_cb, "vbar") add_vbar_chart.set_tooltip(_("Vertical Bar Chart")) add_vbar_chart.props.icon_name = "vbar" charts_group = add_vbar_chart toolbarbox.toolbar.insert(add_vbar_chart, -1) add_hbar_chart = RadioToolButton() add_hbar_chart.connect("clicked", self._add_chart_cb, "hbar") add_hbar_chart.set_tooltip(_("Horizontal Bar Chart")) add_hbar_chart.props.icon_name = "hbar" add_hbar_chart.props.group = charts_group toolbarbox.toolbar.insert(add_hbar_chart, -1) add_pie_chart = RadioToolButton() add_pie_chart.connect("clicked", self._add_chart_cb, "pie") add_pie_chart.set_tooltip(_("Pie Chart")) add_pie_chart.props.icon_name = "pie" add_pie_chart.props.group = charts_group add_pie_chart.set_active(True) toolbarbox.toolbar.insert(add_pie_chart, -1) self.chart_type_buttons = [ add_vbar_chart, add_hbar_chart, add_pie_chart ] separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) fullscreen_btn = ToolButton('view-fullscreen') fullscreen_btn.set_tooltip(_('Fullscreen')) fullscreen_btn.connect("clicked", self.__fullscreen_cb) toolbarbox.toolbar.insert(fullscreen_btn, -1) charthelp.create_help(toolbarbox.toolbar) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(True) toolbarbox.toolbar.insert(separator, -1) stopbtn = StopButton(self) toolbarbox.toolbar.insert(stopbtn, -1) self.set_toolbar_box(toolbarbox) # CANVAS paned = gtk.HPaned() box = gtk.VBox() self.box = box # Set the info box width to 1/3 of the screen: def size_allocate_cb(widget, allocation): paned.disconnect(self._setup_handle) box_width = allocation.width / 3 box.set_size_request(box_width, -1) self._setup_handle = paned.connect('size_allocate', size_allocate_cb) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.labels_and_values = ChartData(self) scroll.add(self.labels_and_values) self.labels_and_values.connect("label-changed", self._label_changed) self.labels_and_values.connect("value-changed", self._value_changed) box.pack_start(scroll, True, True, 0) paned.add1(box) # CHARTS AREA eventbox = gtk.EventBox() self.charts_area = ChartArea(self) self.charts_area.connect('size_allocate', self._chart_size_allocate) eventbox.modify_bg(gtk.STATE_NORMAL, _WHITE) eventbox.add(self.charts_area) paned.add2(eventbox) self.set_canvas(paned) self.show_all()
class SpeakActivity(activity.Activity): def __init__(self, handle): super(SpeakActivity, self).__init__(handle) self._notebook = gtk.Notebook() self.set_canvas(self._notebook) self._notebook.show() self._colors = profile.get_color().to_string().split(',') lighter = style.Color(self._colors[ _lighter_color(self._colors)]) self._mode = MODE_TYPE self._tablet_mode = _is_tablet_mode() self._robot_idle_id = None self._active_eyes = None self._active_number_of_eyes = None self._current_voice = None # make an audio device for playing back and rendering audio self.connect('notify::active', self._active_cb) self._cfg = {} # make a box to type into hbox = gtk.HBox() if self._tablet_mode: self._entry = gtk.Entry() hbox.pack_start(self._entry, expand=True) talk_button = ToolButton('microphone') talk_button.set_tooltip(_('Speak')) talk_button.connect('clicked', self._talk_cb) hbox.pack_end(talk_button, expand=False) else: self._entrycombo = gtk.combo_box_entry_new_text() self._entrycombo.connect('changed', self._combo_changed_cb) self._entry = self._entrycombo.child self._entry.set_size_request(-1, style.GRID_CELL_SIZE) hbox.pack_start(self._entrycombo, expand=True) self._entry.set_editable(True) self._entry.connect('activate', self._entry_activate_cb) self._entry.connect('key-press-event', self._entry_key_press_cb) self._entry.modify_font(pango.FontDescription(str='sans bold 24')) hbox.show() self.face = face.View(fill_color=lighter) self.face.set_size_request( -1, gtk.gdk.screen_height() - 2 * style.GRID_CELL_SIZE) self.face.show() # layout the screen box = gtk.VBox(homogeneous=False) if self._tablet_mode: box.pack_start(hbox, expand=False) box.pack_start(self.face) else: box.pack_start(self.face, expand=True) box.pack_start(hbox) self.add_events(gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.POINTER_MOTION_MASK) self.connect('motion_notify_event', self._mouse_moved_cb) box.add_events(gtk.gdk.BUTTON_PRESS_MASK) box.connect('button_press_event', self._mouse_clicked_cb) # desktop self._notebook.show() self._notebook.props.show_border = False self._notebook.props.show_tabs = False box.show_all() self._notebook.append_page(box) self._chat = chat.View() self._chat.show_all() self._notebook.append_page(self._chat) # make the text box active right away if not self._tablet_mode: self._entry.grab_focus() self._entry.connect('move-cursor', self._cursor_moved_cb) self._entry.connect('changed', self._cursor_moved_cb) toolbox = ToolbarBox() self._activity_button = ActivityToolbarButton(self) self._activity_button.connect('clicked', self._configure_cb) toolbox.toolbar.insert(self._activity_button, -1) mode_type = RadioToolButton( named_icon='mode-type', tooltip=_('Type something to hear it')) mode_type.connect('toggled', self.__toggled_mode_type_cb) toolbox.toolbar.insert(mode_type, -1) mode_robot = RadioToolButton( named_icon='mode-robot', group=mode_type, tooltip=_('Ask robot any question')) mode_robot.connect('toggled', self.__toggled_mode_robot_cb) toolbox.toolbar.insert(mode_robot, -1) self._mode_chat = RadioToolButton( named_icon='mode-chat', group=mode_type, tooltip=_('Voice chat')) self._mode_chat.connect('toggled', self.__toggled_mode_chat_cb) toolbox.toolbar.insert(self._mode_chat, -1) self._voice_button = ToolbarButton( page=self._make_voice_bar(), label=_('Voice'), icon_name='voice') self._voice_button.connect('clicked', self._configure_cb) toolbox.toolbar.insert(self._voice_button, -1) self._face_button = ToolbarButton( page=self._make_face_bar(), label=_('Face'), icon_name='face') self._face_button.connect('clicked', self._configure_cb) toolbox.toolbar.insert(self._face_button, -1) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(True) toolbox.toolbar.insert(separator, -1) toolbox.toolbar.insert(StopButton(self), -1) toolbox.show_all() self.toolbar_box = toolbox gtk.gdk.screen_get_default().connect('size-changed', self._configure_cb) self._first_time = True self._new_instance() self._configure_cb() self._poll_accelerometer() if self.shared_activity: # we are joining the activity self.connect('joined', self._joined_cb) if self.get_shared(): # we have already joined self._joined_cb(self) self._mode_chat.set_active(True) self._setup_chat_mode() elif handle.uri: # XMPP non-sugar3 incoming chat, not sharable self._activity_button.props.page.share.props.visible = \ False self._one_to_one_connection(handle.uri) else: # we are creating the activity self.connect('shared', self._shared_cb) def _toolbar_expanded(self): if self._activity_button.is_expanded(): return True if self._voice_button.is_expanded(): return True if self._face_button.is_expanded(): return True return False def _configure_cb(self, event=None): self._entry.set_size_request(-1, style.GRID_CELL_SIZE) if self._toolbar_expanded(): self.face.set_size_request( -1, gtk.gdk.screen_height() - 3 * style.GRID_CELL_SIZE) self._chat.resize_chat_box(expanded=True) self._chat.resize_buddy_list() else: self.face.set_size_request( -1, gtk.gdk.screen_height() - 2 * style.GRID_CELL_SIZE) self._chat.resize_chat_box() self._chat.resize_buddy_list() def _new_instance(self): if self._first_time: # self.voices.connect('changed', self.__changed_voices_cb) self.pitchadj.connect('value_changed', self._pitch_adjusted_cb, self.pitchadj) self.rateadj.connect('value_changed', self._rate_adjusted_cb, self.rateadj) if self._active_number_of_eyes is None: self._number_of_eyes_changed_event_cb(None, None, 'two', True) if self._active_eyes is None: self._eyes_changed_event_cb(None, None, 'eyes', True) self._mouth_changed_cb(None, True) self.face.look_ahead() presenceService = presenceservice.get_instance() self.owner = presenceService.get_owner() if self._first_time: # say hello to the user if self._tablet_mode: self._entry.props.text = _('Hello %s.') \ % self.owner.props.nick.encode('utf-8', 'ignore') self.face.say_notification(_('Hello %s. Please Type something.') % self.owner.props.nick) else: if self._tablet_mode: self._entry.props.text = _('Welcome back %s.') \ % self.owner.props.nick.encode('utf-8', 'ignore') self.face.say_notification(_('Welcome back %s.') % self.owner.props.nick) self._set_idle_phrase(speak=False) self._first_time = False def read_file(self, file_path): self._cfg = json.loads(file(file_path, 'r').read()) current_voice = self.face.status.voice status = self.face.status = \ face.Status().deserialize(self._cfg['status']) found_my_voice = False for name in self._voice_evboxes.keys(): if self._voice_evboxes[name][1] == current_voice: self._voice_evboxes[name][0].modify_bg( 0, style.COLOR_BLACK.get_gdk_color()) if self._voice_evboxes[name][1] == status.voice and \ not found_my_voice: self._voice_evboxes[name][0].modify_bg( 0, style.COLOR_BUTTON_GREY.get_gdk_color()) self.face.set_voice(status.voice) if self._mode == MODE_BOT: brain.load(self, status.voice) found_my_voice = True self.pitchadj.value = self.face.status.pitch self.rateadj.value = self.face.status.rate if status.mouth in MOUTHS: self._mouth_type[MOUTHS.index(status.mouth)].set_active(True) self._number_of_eyes_changed_event_cb( None, None, NUMBERS[len(status.eyes) - 1], True) for name in EYE_DICT.keys(): if status.eyes[0] == EYE_DICT[name]['widget']: self._eye_type[name].set_icon(name + '-selected') self._eyes_changed_event_cb(None, None, name, True) break self._entry.props.text = self._cfg['text'].encode('utf-8', 'ignore') if not self._tablet_mode: for i in self._cfg['history']: self._entrycombo.append_text(i.encode('utf-8', 'ignore')) self._new_instance() def write_file(self, file_path): if self._tablet_mode: if 'history' in self._cfg: history = self._cfg['history'] # retain old history else: history = [] else: history = [unicode(i[0], 'utf-8', 'ignore') for i in self._entrycombo.get_model()] cfg = {'status': self.face.status.serialize(), 'text': unicode(self._entry.props.text, 'utf-8', 'ignore'), 'history': history, } file(file_path, 'w').write(json.dumps(cfg)) def _cursor_moved_cb(self, entry, *ignored): # make the eyes track the motion of the text cursor index = entry.props.cursor_position layout = entry.get_layout() pos = layout.get_cursor_pos(index) x = pos[0][0] / pango.SCALE - entry.props.scroll_offset y = entry.get_allocation().y self.face.look_at(pos=(x, y)) def _poll_accelerometer(self): if _has_accelerometer(): idle_time = self._test_orientation() gobject.timeout_add(idle_time, self._poll_accelerometer) def _test_orientation(self): if _has_accelerometer(): fh = open(ACCELEROMETER_DEVICE) string = fh.read() fh.close() xyz = string[1:-2].split(',') x = int(xyz[0]) y = int(xyz[1]) # DO SOMETHING HERE if ((gtk.gdk.screen_width() > gtk.gdk.screen_height() and abs(x) > abs(y)) or (gtk.gdk.screen_width() < gtk.gdk.screen_height() and abs(x) < abs(y))): sideways_phrase = SIDEWAYS_PHRASES[ random.randint(0, len(SIDEWAYS_PHRASES) - 1)] self.face.say(SIDEWAYS_PHRASES[sideways_phrase]) return IDLE_DELAY # Don't repeat the message for a while return 1000 # Test again soon def get_mouse(self): display = gtk.gdk.display_get_default() screen, mouseX, mouseY, modifiers = display.get_pointer() return mouseX, mouseY def _mouse_moved_cb(self, widget, event): # make the eyes track the motion of the mouse cursor self.face.look_at() self._chat.look_at() def _mouse_clicked_cb(self, widget, event): pass def _make_voice_bar(self): voicebar = gtk.Toolbar() all_voices = [] for name in sorted(voice_model.allVoices().keys()): if len(name) < 26: friendly_name = name else: friendly_name = name[:26] + '...' all_voices.append([voice_model.allVoices()[name], friendly_name]) # A palette for the voice selection logging.error(self.face.status.voice) self._voice_evboxes = {} self._voice_box = gtk.HBox() vboxes = [gtk.VBox(), gtk.VBox(), gtk.VBox()] count = len(voice_model.allVoices().keys()) found_my_voice = False for i, voice in enumerate(sorted(all_voices)): label = gtk.Label() label.set_use_markup(True) label.set_justify(gtk.JUSTIFY_LEFT) label.set_markup('<span size="large">%s</span>' % voice[1]) alignment = gtk.Alignment(0, 0, 0, 0) alignment.add(label) label.show() evbox = gtk.EventBox() self._voice_evboxes[voice[1]] = [evbox, voice[0]] self._voice_evboxes[voice[1]][0].connect( 'button-press-event', self._voices_changed_event_cb, voice) if voice[0] == self.face.status.voice and not found_my_voice: self._current_voice = voice evbox.modify_bg( 0, style.COLOR_BUTTON_GREY.get_gdk_color()) found_my_voice = True evbox.add(alignment) alignment.show() if i < count / 3: vboxes[0].pack_start(evbox) elif i < 2 * count / 3: vboxes[1].pack_start(evbox) else: vboxes[2].pack_start(evbox) self._voice_box.pack_start(vboxes[0], padding=style.DEFAULT_PADDING) self._voice_box.pack_start(vboxes[1], padding=style.DEFAULT_PADDING) self._voice_box.pack_start(vboxes[2], padding=style.DEFAULT_PADDING) voice_palette_button = ToolButton('module-language') voice_palette_button.set_tooltip(_('Choose voice:')) self._voice_palette = voice_palette_button.get_palette() self._voice_palette.set_content(self._voice_box) self._voice_box.show_all() voice_palette_button.connect('clicked', self._face_palette_cb) voicebar.insert(voice_palette_button, -1) voice_palette_button.show() brain_voices = [] for name in sorted(brain.BOTS.keys()): brain_voices.append([voice_model.allVoices()[name], name]) self._brain_evboxes = {} self._brain_box = gtk.HBox() vboxes = gtk.VBox() count = brain.BOTS.keys() found_my_voice = False for i, voice in enumerate(brain_voices): label = gtk.Label() label.set_use_markup(True) label.set_justify(gtk.JUSTIFY_LEFT) label.set_markup('<span size="large">%s</span>' % voice[1]) alignment = gtk.Alignment(0, 0, 0, 0) alignment.add(label) label.show() evbox = gtk.EventBox() self._brain_evboxes[voice[1]] = [evbox, voice[0]] self._brain_evboxes[voice[1]][0].connect( 'button-press-event', self._voices_changed_event_cb, voice) if voice[0] == self.face.status.voice and not found_my_voice: evbox.modify_bg( 0, style.COLOR_BUTTON_GREY.get_gdk_color()) found_my_voice = True evbox.add(alignment) alignment.show() vboxes.pack_start(evbox) self._brain_box.pack_start(vboxes, padding=style.DEFAULT_PADDING) self._brain_box.show_all() separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) voicebar.insert(separator, -1) self.pitchadj = gtk.Adjustment(self.face.status.pitch, 0, espeak.PITCH_MAX, 1, espeak.PITCH_MAX/10, 0) pitchbar = gtk.HScale(self.pitchadj) pitchbar.set_draw_value(False) # pitchbar.set_inverted(True) pitchbar.set_update_policy(gtk.UPDATE_DISCONTINUOUS) pitchbar.set_size_request(240, 15) pitchbar_toolitem = ToolWidget(widget=pitchbar, label_text=_('Pitch:')) voicebar.insert(pitchbar_toolitem, -1) self.rateadj = gtk.Adjustment(self.face.status.rate, 0, espeak.RATE_MAX, 1, espeak.RATE_MAX / 10, 0) ratebar = gtk.HScale(self.rateadj) ratebar.set_draw_value(False) # ratebar.set_inverted(True) ratebar.set_update_policy(gtk.UPDATE_DISCONTINUOUS) ratebar.set_size_request(240, 15) ratebar_toolitem = ToolWidget(widget=ratebar, label_text=_('Rate:')) voicebar.insert(ratebar_toolitem, -1) voicebar.show_all() return voicebar def _pitch_adjusted_cb(self, get, data=None): self.face.status.pitch = get.value self.face.say_notification(_('pitch adjusted')) def _rate_adjusted_cb(self, get, data=None): self.face.status.rate = get.value self.face.say_notification(_('rate adjusted')) def _make_face_bar(self): facebar = gtk.Toolbar() self._mouth_type = [] self._mouth_type.append(RadioToolButton( named_icon='mouth', group=None, tooltip=_('Simple'))) self._mouth_type[-1].connect('clicked', self._mouth_changed_cb, False) facebar.insert(self._mouth_type[-1], -1) self._mouth_type.append(RadioToolButton( named_icon='waveform', group=self._mouth_type[0], tooltip=_('Waveform'))) self._mouth_type[-1].connect('clicked', self._mouth_changed_cb, False) facebar.insert(self._mouth_type[-1], -1) self._mouth_type.append(RadioToolButton( named_icon='frequency', group=self._mouth_type[0], tooltip=_('Frequency'))) self._mouth_type[-1].connect('clicked', self._mouth_changed_cb, False) facebar.insert(self._mouth_type[-1], -1) separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) facebar.insert(separator, -1) eye_box = gtk.VBox() self._eye_type = {} for name in EYE_DICT.keys(): self._eye_type[name] = ToolButton(name) self._eye_type[name].connect('clicked', self._eyes_changed_event_cb, None, name, False) label = gtk.Label(EYE_DICT[name]['label']) hbox = gtk.HBox() hbox.pack_start(self._eye_type[name]) self._eye_type[name].show() hbox.pack_start(label) label.show() evbox = gtk.EventBox() evbox.connect('button-press-event', self._eyes_changed_event_cb, name, False) evbox.add(hbox) hbox.show() eye_box.pack_start(evbox) eye_palette_button = ToolButton('eyes') eye_palette_button.set_tooltip(_('Choose eyes:')) palette = eye_palette_button.get_palette() palette.set_content(eye_box) eye_box.show_all() eye_palette_button.connect('clicked', self._face_palette_cb) facebar.insert(eye_palette_button, -1) eye_palette_button.show() number_of_eyes_box = gtk.VBox() self._number_of_eyes_type = {} for name in NUMBERS: self._number_of_eyes_type[name] = ToolButton(name) self._number_of_eyes_type[name].connect( 'clicked', self._number_of_eyes_changed_event_cb, None, name, False) label = gtk.Label(name) hbox = gtk.HBox() hbox.pack_start(self._number_of_eyes_type[name]) self._number_of_eyes_type[name].show() hbox.pack_start(label) label.show() evbox = gtk.EventBox() evbox.connect('button-press-event', self._number_of_eyes_changed_event_cb, name, False) evbox.add(hbox) hbox.show() number_of_eyes_box.pack_start(evbox) number_of_eyes_palette_button = ToolButton('number') number_of_eyes_palette_button.set_tooltip(_('Eyes number:')) palette = number_of_eyes_palette_button.get_palette() palette.set_content(number_of_eyes_box) number_of_eyes_box.show_all() number_of_eyes_palette_button.connect('clicked', self._face_palette_cb) facebar.insert(number_of_eyes_palette_button, -1) number_of_eyes_palette_button.show() facebar.show_all() return facebar def _face_palette_cb(self, button): palette = button.get_palette() if palette: if not palette.is_up(): palette.popup(immediate=True, state=palette.SECONDARY) else: palette.popdown(immediate=True) def _get_active_mouth(self): for i, button in enumerate(self._mouth_type): if button.get_active(): return MOUTHS[i] def _mouth_changed_cb(self, ignored, quiet): value = self._get_active_mouth() if value is None: return self.face.status.mouth = value self._update_face() # this SegFaults: self.face.say(combo.get_active_text()) if not quiet: self.face.say_notification(_('mouth changed')) def _voices_changed_event_cb(self, widget, event, voice): logging.error('voices_changed_event_cb %r %s' % (voice[0], voice[1])) if self._mode == MODE_BOT: evboxes = self._brain_evboxes else: evboxes = self._voice_evboxes for old_voice in evboxes.keys(): if evboxes[old_voice][1] == self.face.status.voice: evboxes[old_voice][0].modify_bg( 0, style.COLOR_BLACK.get_gdk_color()) break evboxes[voice[1]][0].modify_bg( 0, style.COLOR_BUTTON_GREY.get_gdk_color()) self.face.set_voice(voice[0]) if self._mode == MODE_BOT: brain.load(self, voice[0]) else: self._current_voice = voice def _get_active_eyes(self): for name in EYE_DICT.keys(): if EYE_DICT[name]['index'] == self._active_eyes: return EYE_DICT[name]['widget'] return None def _eyes_changed_event_cb(self, widget, event, name, quiet): if self._active_eyes is not None: for old_name in EYE_DICT.keys(): if EYE_DICT[old_name]['index'] == self._active_eyes: self._eye_type[old_name].set_icon(old_name) break if self._active_number_of_eyes is None: self._active_number_of_eyes = 2 if name is not None: self._active_eyes = EYE_DICT[name]['index'] self._eye_type[name].set_icon(name + '-selected') value = EYE_DICT[name]['widget'] self.face.status.eyes = [value] * self._active_number_of_eyes self._update_face() if not quiet: self.face.say_notification(_('eyes changed')) def _number_of_eyes_changed_event_cb(self, widget, event, name, quiet): if self._active_number_of_eyes is not None: old_name = NUMBERS[self._active_number_of_eyes - 1] self._number_of_eyes_type[old_name].set_icon(old_name) if name in NUMBERS: self._active_number_of_eyes = NUMBERS.index(name) + 1 self._number_of_eyes_type[name].set_icon(name + '-selected') if self._active_eyes is not None: for eye_name in EYE_DICT.keys(): if EYE_DICT[eye_name]['index'] == self._active_eyes: value = EYE_DICT[eye_name]['widget'] self.face.status.eyes = \ [value] * self._active_number_of_eyes self._update_face() if not quiet: self.face.say_notification(_('eyes changed')) break def _update_face(self): self.face.update() self._chat.update(self.face.status) def _combo_changed_cb(self, combo): # when a new item is chosen, make sure the text is selected if not self._entry.is_focus(): if not self._tablet_mode: self._entry.grab_focus() self._entry.select_region(0, -1) def _entry_key_press_cb(self, combo, event): # make the up/down arrows navigate through our history if self._tablet_mode: return keyname = gtk.gdk.keyval_name(event.keyval) if keyname == 'Up': index = self._entrycombo.get_active() if index > 0: index -= 1 self._entrycombo.set_active(index) self._entry.select_region(0, -1) return True elif keyname == 'Down': index = self._entrycombo.get_active() if index < len(self._entrycombo.get_model()) - 1: index += 1 self._entrycombo.set_active(index) self._entry.select_region(0, -1) return True return False def _entry_activate_cb(self, entry): # the user pressed Return, say the text and clear it out text = entry.props.text if self._tablet_mode: self._dismiss_OSK(entry) timeout = DELAY_BEFORE_SPEAKING else: timeout = 100 gobject.timeout_add(timeout, self._speak_the_text, entry, text) def _dismiss_OSK(self, entry): entry.hide() entry.show() def _talk_cb(self, button): text = self._entry.props.text self._speak_the_text(self._entry, text) def _speak_the_text(self, entry, text): self._remove_idle() if text: self.face.look_ahead() # speak the text if self._mode == MODE_BOT: self.face.say(brain.respond(text)) else: self.face.say(text) if text and not self._tablet_mode: # add this text to our history unless it is the same as # the last item history = self._entrycombo.get_model() if len(history) == 0 or history[-1][0] != text: self._entrycombo.append_text(text) # don't let the history get too big while len(history) > 20: self._entrycombo.remove_text(0) # select the new item self._entrycombo.set_active(len(history) - 1) if text: # select the whole text entry.select_region(0, -1) # Launch an robot idle phase after 2 minutes self._robot_idle_id = gobject.timeout_add(IDLE_DELAY, self._set_idle_phrase) def _load_sleeping_face(self): current_eyes = self.face.status.eyes self.face.status.eyes = [SLEEPY_EYES] * self._active_number_of_eyes self._update_face() self.face.status.eyes = current_eyes def _set_idle_phrase(self, speak=True): if speak: self._load_sleeping_face() idle_phrase = IDLE_PHRASES[random.randint( 0, len(IDLE_PHRASES) - 1)] if self.props.active: self.face.say(idle_phrase) self._robot_idle_id = gobject.timeout_add(IDLE_DELAY, self._set_idle_phrase) def _active_cb(self, widget, pspec): # only generate sound when this activity is active if not self.props.active: self._load_sleeping_face() self.face.shut_up() self._chat.shut_up() def _set_voice(self, new_voice=None): if new_voice is not None: logging.error('set_voice %r' % new_voice) self.face.status.voice = new_voice else: logging.error('set_voice to current voice %s' % self._current_voice[1]) self.face.status.voice = self._current_voice[0] def __toggled_mode_type_cb(self, button): if not button.props.active: return self._mode = MODE_TYPE self._chat.shut_up() self.face.shut_up() self._notebook.set_current_page(0) self._voice_palette.set_content(self._voice_box) self._set_voice() def __toggled_mode_robot_cb(self, button): if not button.props.active: return self._remove_idle() self._mode = MODE_BOT self._chat.shut_up() self.face.shut_up() self._notebook.set_current_page(0) self._voice_palette.set_content(self._brain_box) new_voice = None for name in brain.BOTS.keys(): if self._current_voice[0].short_name == name: new_voice == self._current_voice[0] break if new_voice is None: new_voice = brain.get_default_voice() if new_voice.friendlyname in self._current_voice[0].friendlyname: logging.debug('skipping sorry message for %s %s' % (new_voice.friendlyname, self._current_voice[0].friendlyname)) sorry = None else: sorry = _("Sorry, I can't speak %(old_voice)s, " "let's talk %(new_voice)s instead.") % { 'old_voice': self._current_voice[0].friendlyname, 'new_voice': new_voice.friendlyname} else: new_voice = new_voice[0] sorry = None self._set_voice(new_voice) evboxes = self._brain_evboxes for old_voice in evboxes.keys(): evboxes[old_voice][0].modify_bg( 0, style.COLOR_BLACK.get_gdk_color()) if new_voice.short_name in evboxes: evboxes[new_voice.short_name][0].modify_bg( 0, style.COLOR_BUTTON_GREY.get_gdk_color()) if not brain.load(self, new_voice, sorry): if sorry: self.face.say_notification(sorry) def __toggled_mode_chat_cb(self, button): if not button.props.active: return self._remove_idle() is_first_session = not self.shared_activity self._setup_chat_mode() if is_first_session: self._chat.me.say_notification( _('You are in off-line mode, share and invite someone.')) def _remove_idle(self): if self._robot_idle_id is not None: gobject.source_remove(self._robot_idle_id) value = self._get_active_eyes() if value is not None: self.face.status.eyes = [value] * self._active_number_of_eyes self._update_face() def _setup_chat_mode(self): self._mode = MODE_CHAT self._remove_idle() self.face.shut_up() self._notebook.set_current_page(1) self._voice_palette.set_content(self._voice_box) self._set_voice() def _shared_cb(self, sender): logging.error('SHARED A CHAT') self._setup_text_channel() def _joined_cb(self, sender): '''Joined a shared activity.''' if not self.shared_activity: return logger.error('JOINED A SHARED CHAT') for buddy in self.shared_activity.get_joined_buddies(): self._buddy_already_exists(buddy) self._setup_text_channel() def _one_to_one_connection(self, tp_channel): '''Handle a private invite from a non-sugar3 XMPP client.''' if self.shared_activity or self.text_channel: return bus_name, connection, channel = json.loads(tp_channel) logger.debug('GOT XMPP: %s %s %s', bus_name, connection, channel) Connection(bus_name, connection, ready_handler=lambda conn: self._one_to_one_connection_ready_cb( bus_name, channel, conn)) def _one_to_one_connection_ready_cb(self, bus_name, channel, conn): '''Callback for Connection for one to one connection''' text_channel = Channel(bus_name, channel) self.text_channel = TextChannelWrapper(text_channel, conn) self.text_channel.set_received_callback(self._received_cb) self.text_channel.handle_pending_messages() self.text_channel.set_closed_callback( self._one_to_one_connection_closed_cb) # XXX How do we detect the sender going offline? self._chat.chat_post.set_sensitive(True) # self._chat.chat_post.props.placeholder_text = None self._chat.chat_post.grab_focus() def _one_to_one_connection_closed_cb(self): '''Callback for when the text channel closes.''' pass def _setup_text_channel(self): logging.error('_SETUP_TEXTCHANNEL') self.text_channel = TextChannelWrapper( self.shared_activity.telepathy_text_chan, self.shared_activity.telepathy_conn) 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) self._chat.messenger = self.text_channel self._chat.chat_post.set_sensitive(True) self._chat.chat_post.grab_focus() def _buddy_joined_cb(self, sender, buddy): '''Show a buddy who joined''' if buddy == self.owner: return logging.error('%s joined the chat (%r)' % (buddy.props.nick, buddy)) self._chat.post( buddy, _('%s joined the chat') % buddy.props.nick, status_message=True) def _buddy_left_cb(self, sender, buddy): '''Show a buddy who joined''' if buddy == self.owner: return logging.error('%s left the chat (%r)' % (buddy.props.nick, buddy)) self._chat.post( buddy, _('%s left the chat') % buddy.props.nick, status_message=True) self._chat.farewell(buddy) def _buddy_already_exists(self, buddy): '''Show a buddy already in the chat.''' if buddy == self.owner: return logging.error('%s is here (%r)' % (buddy.props.nick, buddy)) self._chat.post( buddy, _('%s is here') % buddy.props.nick, status_message=True) def _received_cb(self, buddy, text): '''Show message that was received.''' if buddy: if type(buddy) is dict: nick = buddy['nick'] else: nick = buddy.props.nick else: nick = '???' logger.debug('Received message from %s: %s', nick, text) self._chat.post(buddy, text)
class VncLauncherActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self.max_participants = 1 self.toolbarbox = ToolbarBox() self.toolbar = self.toolbarbox.toolbar self.start_vnc = RadioToolButton(icon_name="start_vnc", tooltip=_("Start VNC Server")) self.stop_vnc = RadioToolButton(icon_name="stop_vnc", tooltip=_("Stop VNC Server"), group=self.start_vnc) self.stop_vnc.set_active(True) self.get_ipbutton = ToolButton(icon_name="get_ip", tooltip=_("Get the current IP")) ## self.messages = gtk.TreeView() self.messages.set_rules_hint(True) modelo = gtk.ListStore(str, str, gtk.gdk.Color) self.messages.set_model(modelo) render = gtk.CellRendererText() render1 = gtk.CellRendererText() column1 = gtk.TreeViewColumn(_("Hour"), render, markup=0) column2 = gtk.TreeViewColumn(_("Message"), render1, markup=1) column1.add_attribute(render, 'foreground-gdk', 2) column2.add_attribute(render1, 'foreground-gdk', 2) self.messages.append_column(column1) self.messages.append_column(column2) color = gtk.gdk.color_parse("dark blue") modelo.insert(0, [ time.strftime("\n<b>%H:%M:%S</b>\n"), _("\n<b>Start of activity.</b>\n"), color ]) self.showed_message_stop = True self.showed_message_start = False self.isrunning = True self.stop_vnc.connect("clicked", self.__stop_vnc) self.start_vnc.connect("clicked", self.__start_vnc) self.clear_model = ToolButton(icon_name="clear_console", tooltip=_("Delete messages")) self.clear_model.connect("clicked", lambda x: modelo.clear()) self.get_ipbutton.connect("clicked", self.__get_ip) self.last_message = 1 self.__get_x11vnc_path() ## separator = gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self.stop_activity = StopButton(self) self.toolbar.insert(ActivityToolbarButton(self), -1) self.toolbar.insert(gtk.SeparatorToolItem(), -1) self.toolbar.insert(self.start_vnc, -1) self.toolbar.insert(self.stop_vnc, -1) self.toolbar.insert(gtk.SeparatorToolItem(), -1) self.toolbar.insert(self.get_ipbutton, -1) self.toolbar.insert(self.clear_model, -1) self.toolbar.insert(separator, -1) self.toolbar.insert(self.stop_activity, -1) self.messages_scroll = gtk.ScrolledWindow() self.messages_scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.messages_scroll.add_with_viewport(self.messages) self.set_toolbar_box(self.toolbarbox) self.set_canvas(self.messages_scroll) self.show_all() gobject.timeout_add(100, self.__check_is_on) def __check_is_on(self): pid = commands.getoutput("pidof x11vnc") if self.start_vnc.get_active() and pid == "" and self.isrunning: self.showed_message_stop = True self.stop_vnc.set_active(True) self.start_vnc.set_active(False) self.showed_message_start = False color = gtk.gdk.color_parse("dark red") self.messages.get_model().insert(self.last_message, [ time.strftime("\n<b>%H:%M:%S</b>\n"), ("\n<b>It has stopped unexpectedly the server..</b>\n"), color ]) self.last_message += 1 return True def __get_x11vnc_path(self): system = platform.machine() color = gtk.gdk.color_parse("dark red") if os.path.exists("/usr/bin/x11vnc"): self.path = "/usr/bin/x11vnc" message = _("PATH: %s") % self.path else: if "arm" in system: self.path = os.path.join(activity.get_bundle_path(), "bin", "arm", "x11vnc") elif "64" in system: self.path = os.path.join(activity.get_bundle_path(), "bin", "x64", "x11vnc") else: self.path = os.path.join(activity.get_bundle_path(), "bin", "i586", "x11vnc") os.environ["LD_LIBRARY_PATH"] = self.path.replace("x11vnc", "lib/") message = _("PATH: %s") % self.path self.messages.get_model().insert(self.last_message, [ time.strftime("\n<b>%H:%M:%S</b>\n"), "<b>" + message + "</b>", color ]) self.last_message += 1 def __start_vnc(self, widget): def servidor(): commands.getoutput(self.path) Thread(target=servidor).start() if not self.showed_message_start: self.showed_message_start = True pass else: return self.showed_message_stop = False self.isrunning = True color = gtk.gdk.color_parse("green") self.messages.get_model().insert(self.last_message, [ time.strftime("\n<b>%H:%M:%S</b>\n"), ("\n<b>VNC server is started</b>\n"), color ]) self.last_message += 1 def __stop_vnc(self, widget): if not self.showed_message_stop: self.showed_message_stop = True pass else: return self.showed_message_start = False self.pid_nuevo = commands.getoutput("pidof x11vnc") color = gtk.gdk.color_parse('red') os.system("kill " + self.pid_nuevo) self.messages.get_model().insert(self.last_message, [ time.strftime("\n<b>%H:%M:%S</b>\n"), ("\n<b>The VNC server is now stopped.</b>\n"), color ]) self.last_message += 1 def close(self): self.isrunning = False pid = commands.getoutput("pidof x11vnc") os.system("kill " + pid) self.destroy() def __get_ip(self, widget): system = platform.platform() if "olpc" in system: target = "eth0" else: target = "wlan0" ifconfig = "/sbin/ifconfig" cmd = "%s %s" % (ifconfig, target) output = commands.getoutput(cmd) error = _("No wireless connection.") ip = error inet = output.find('inet') if inet >= 0: start = inet + len('inet') end = output.find(" ", start + 1) ip = output[start:end] else: ip = error if ip == _("No wireless connection."): mensaje = error else: ip = ip.replace(":", "") ip = ip.replace("addr", "") ip = ip.replace(" ", "") mensaje = "IP: " + ip color = gtk.gdk.color_parse("dark blue") self.messages.get_model().insert(self.last_message, [ time.strftime("\n<b>%H:%M:%S</b>\n"), "\n<b>" + mensaje + "</b>\n", color ]) self.last_message += 1
def __init__(self, handle): activity.Activity.__init__(self, handle) self.max_participants = 1 # Canvas canvas = Canvas(self) self.set_canvas(canvas) self._download_list = canvas.gtk_list.download_list # Toolbars toolbarbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbarbox.toolbar.insert(activity_button, 0) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) # Switch store_list = RadioToolButton() store_list.set_active(True) store_list.props.icon_name = 'view-list' store_list.connect("clicked", canvas.switch_to_list) store_list.set_tooltip(_("Show the search list")) toolbarbox.toolbar.insert(store_list, -1) downloads_list = RadioToolButton() downloads_list.connect("clicked", canvas.switch_to_downloads_list) downloads_list.set_tooltip(_("Show the downloads list")) downloads_list.props.group = store_list self.downloads_icon = DownloadsIcon() downloads_list.set_icon_widget(self.downloads_icon) toolbarbox.toolbar.insert(downloads_list, -1) self.store_list = store_list self.downloads_list = downloads_list separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) # Search search_entry = iconentry.IconEntry() search_entry.set_size_request(gtk.gdk.screen_width() / 4, -1) search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, 'system-search') search_entry.connect('activate', canvas.gtk_list.search) search_entry.connect('activate', lambda w: canvas.switch_to_list(None)) search_entry.add_clear_button() search_item = gtk.ToolItem() search_item.add(search_entry) toolbarbox.toolbar.insert(search_item, -1) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(True) toolbarbox.toolbar.insert(separator, -1) stopbtn = StopButton(self) toolbarbox.toolbar.insert(stopbtn, -1) self.set_toolbar_box(toolbarbox) self.show_all() canvas.set_page(0)
def __init__(self, handle): activity.Activity.__init__(self, handle, True) self.max_participants = 1 # CHART_OPTIONS self.x_label = "" self.y_label = "" self.chart_color = utils.get_user_fill_color('str') self.chart_line_color = utils.get_user_stroke_color('str') self.current_chart = None self.charts_area = None self.chart_data = [] # TOOLBARS toolbarbox = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_btn_toolbar = activity_button.page activity_btn_toolbar.title.connect('changed', self._set_chart_title) save_as_image = ToolButton("save-as-image") save_as_image.connect("clicked", self._save_as_image) save_as_image.set_tooltip(_("Save as image")) activity_btn_toolbar.insert(save_as_image, -1) save_as_image.show() toolbarbox.toolbar.insert(activity_button, 0) import_freespace = ToolButton("import-freespace") import_freespace.connect("clicked", self.__import_freespace_cb) import_freespace.set_tooltip(_("Read Freespace data")) toolbarbox.toolbar.insert(import_freespace, -1) import_freespace.show() import_journal = ToolButton('import-journal') import_journal.connect('clicked', self.__import_journal_cb) import_journal.set_tooltip(_('Read Journal data')) toolbarbox.toolbar.insert(import_journal, -1) import_journal.show() import_turtle = ToolButton('import-turtle') import_turtle.connect('clicked', self.__import_turtle_cb) import_turtle.set_tooltip(_('Read Turtle data')) toolbarbox.toolbar.insert(import_turtle, -1) import_turtle.show() separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) add_vbar_chart = RadioToolButton() add_vbar_chart.connect("clicked", self._add_chart_cb, "vbar") add_vbar_chart.set_tooltip(_("Vertical Bar Chart")) add_vbar_chart.props.icon_name = "vbar" charts_group = add_vbar_chart toolbarbox.toolbar.insert(add_vbar_chart, -1) add_hbar_chart = RadioToolButton() add_hbar_chart.connect("clicked", self._add_chart_cb, "hbar") add_hbar_chart.set_tooltip(_("Horizontal Bar Chart")) add_hbar_chart.props.icon_name = "hbar" add_hbar_chart.props.group = charts_group toolbarbox.toolbar.insert(add_hbar_chart, -1) add_pie_chart = RadioToolButton() add_pie_chart.connect("clicked", self._add_chart_cb, "pie") add_pie_chart.set_tooltip(_("Pie Chart")) add_pie_chart.props.icon_name = "pie" add_pie_chart.props.group = charts_group add_pie_chart.set_active(True) toolbarbox.toolbar.insert(add_pie_chart, -1) self.chart_type_buttons = [add_vbar_chart, add_hbar_chart, add_pie_chart] separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) fullscreen_btn = ToolButton('view-fullscreen') fullscreen_btn.set_tooltip(_('Fullscreen')) fullscreen_btn.connect("clicked", self.__fullscreen_cb) toolbarbox.toolbar.insert(fullscreen_btn, -1) charthelp.create_help(toolbarbox.toolbar) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(True) toolbarbox.toolbar.insert(separator, -1) stopbtn = StopButton(self) toolbarbox.toolbar.insert(stopbtn, -1) self.set_toolbar_box(toolbarbox) # CANVAS paned = gtk.HPaned() box = gtk.VBox() self.box = box # Set the info box width to 1/3 of the screen: def size_allocate_cb(widget, allocation): paned.disconnect(self._setup_handle) box_width = allocation.width / 3 box.set_size_request(box_width, -1) self._setup_handle = paned.connect('size_allocate', size_allocate_cb) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.labels_and_values = ChartData(self) scroll.add(self.labels_and_values) self.labels_and_values.connect("label-changed", self._label_changed) self.labels_and_values.connect("value-changed", self._value_changed) box.pack_start(scroll, True, True, 0) paned.add1(box) # CHARTS AREA eventbox = gtk.EventBox() self.charts_area = ChartArea(self) self.charts_area.connect('size_allocate', self._chart_size_allocate) eventbox.modify_bg(gtk.STATE_NORMAL, _WHITE) eventbox.add(self.charts_area) paned.add2(eventbox) self.set_canvas(paned) self.show_all()
def __init__(self, handle): activity.Activity.__init__(self, handle, True) self.max_participants = 1 # CHART_OPTIONS self.x_label = "" self.y_label = "" self.chart_color = utils.get_user_fill_color('str') self.chart_line_color = utils.get_user_stroke_color('str') self.current_chart = None self.charts_area = None self.chart_data = [] # TOOLBARS toolbarbox = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_btn_toolbar = activity_button.page activity_btn_toolbar.title.connect('changed', self._set_chart_title) save_as_image = ToolButton("save-as-image") save_as_image.connect("clicked", self._save_as_image) save_as_image.set_tooltip(_("Save as image")) activity_btn_toolbar.insert(save_as_image, -1) save_as_image.show() import_stopwatch = ToolButton("import-stopwatch") import_stopwatch.connect("clicked", self.__import_stopwatch_cb) import_stopwatch.set_tooltip(_("Read StopWatch data")) activity_btn_toolbar.insert(import_stopwatch, -1) import_stopwatch.show() import_measure = ToolButton("import-measure") import_measure.set_tooltip(_("Read Measure data")) if utils.get_channels() == 1: import_measure.connect("clicked", self.__import_measure_cb, 1) else: import_measure.connect("clicked", self._measure_btn_clicked) self._create_measure_palette(import_measure) activity_btn_toolbar.insert(import_measure, -1) import_measure.show() activity_btn_toolbar.keep.hide() toolbarbox.toolbar.insert(activity_button, 0) add_v = ToolButton("row-insert") add_v.connect("clicked", self._add_value) add_v.set_tooltip(_("Add a value")) toolbarbox.toolbar.insert(add_v, -1) remove_v = ToolButton("row-remove") remove_v.connect("clicked", self._remove_value) remove_v.set_tooltip(_("Remove the selected value")) toolbarbox.toolbar.insert(remove_v, -1) separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) add_vbar_chart = RadioToolButton() add_vbar_chart.connect("clicked", self._add_chart_cb, "vbar") add_vbar_chart.set_tooltip(_("Vertical Bar Chart")) add_vbar_chart.props.icon_name = "vbar" charts_group = add_vbar_chart toolbarbox.toolbar.insert(add_vbar_chart, -1) add_hbar_chart = RadioToolButton() add_hbar_chart.connect("clicked", self._add_chart_cb, "hbar") add_hbar_chart.set_tooltip(_("Horizontal Bar Chart")) add_hbar_chart.props.icon_name = "hbar" add_hbar_chart.props.group = charts_group toolbarbox.toolbar.insert(add_hbar_chart, -1) add_line_chart = RadioToolButton() add_line_chart.connect("clicked", self._add_chart_cb, "line") add_line_chart.set_tooltip(_("Line Chart")) add_line_chart.props.icon_name = "line" add_line_chart.props.group = charts_group toolbarbox.toolbar.insert(add_line_chart, -1) add_pie_chart = RadioToolButton() add_pie_chart.connect("clicked", self._add_chart_cb, "pie") add_pie_chart.set_tooltip(_("Pie Chart")) add_pie_chart.props.icon_name = "pie" add_pie_chart.props.group = charts_group add_pie_chart.set_active(True) toolbarbox.toolbar.insert(add_pie_chart, -1) self.chart_type_buttons = [ add_vbar_chart, add_hbar_chart, add_line_chart, add_pie_chart ] separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) options_button = ToolbarButton(icon_name='preferences-system') options_toolbar = gtk.Toolbar() self.chart_color_btn = ColorToolButton() self.chart_color_btn.set_color(_COLOR1) self.chart_color_btn.set_title(_("Chart Color")) self.chart_color_btn.connect('notify::color', self._set_chart_color) options_toolbar.insert(self.chart_color_btn, -1) self.line_color_btn = ColorToolButton() self.line_color_btn.set_color(_COLOR2) self.line_color_btn.set_title(_("Line Color")) self.line_color_btn.connect('notify::color', self._set_chart_line_color) options_toolbar.insert(self.line_color_btn, -1) separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) options_toolbar.insert(separator, -1) h_label_icon = Icon(icon_name="hlabel") h_label_tool_item = gtk.ToolItem() h_label_tool_item.add(h_label_icon) options_toolbar.insert(h_label_tool_item, -1) self.h_label = Entry(_("Horizontal label...")) self.h_label.entry.connect("changed", self._set_h_label) options_toolbar.insert(self.h_label, -1) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(False) options_toolbar.insert(separator, -1) v_label_icon = Icon(icon_name="vlabel") v_label_tool_item = gtk.ToolItem() v_label_tool_item.add(v_label_icon) options_toolbar.insert(v_label_tool_item, -1) self.v_label = Entry(_("Vertical label...")) self.v_label.entry.connect("changed", self._set_v_label) options_toolbar.insert(self.v_label, -1) options_button.props.page = options_toolbar options_toolbar.show_all() toolbarbox.toolbar.insert(options_button, -1) separator = gtk.SeparatorToolItem() separator.set_draw(True) separator.set_expand(False) toolbarbox.toolbar.insert(separator, -1) fullscreen_btn = ToolButton('view-fullscreen') fullscreen_btn.set_tooltip(_('Fullscreen')) fullscreen_btn.connect("clicked", self.__fullscreen_cb) toolbarbox.toolbar.insert(fullscreen_btn, -1) separator = gtk.SeparatorToolItem() separator.set_draw(False) separator.set_expand(True) toolbarbox.toolbar.insert(separator, -1) simplegraphhelp.create_help(toolbarbox.toolbar) stopbtn = StopButton(self) toolbarbox.toolbar.insert(stopbtn, -1) self.set_toolbar_box(toolbarbox) # CANVAS paned = gtk.HPaned() box = gtk.VBox() self.box = box # Set the info box width to 1/3 of the screen: def size_allocate_cb(widget, allocation): paned.disconnect(self._setup_handle) box_width = allocation.width / 3 box.set_size_request(box_width, -1) self._setup_handle = paned.connect('size_allocate', size_allocate_cb) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.labels_and_values = ChartData(self) scroll.add(self.labels_and_values) self.labels_and_values.connect("label-changed", self._label_changed) self.labels_and_values.connect("value-changed", self._value_changed) box.pack_start(scroll, True, True, 0) paned.add1(box) # CHARTS AREA eventbox = gtk.EventBox() self.charts_area = ChartArea(self) self.charts_area.connect('size_allocate', self._chart_size_allocate) eventbox.modify_bg(gtk.STATE_NORMAL, _WHITE) eventbox.add(self.charts_area) paned.add2(eventbox) self.set_canvas(paned) self.show_all()
class SensorToolbar(gtk.Toolbar): ''' The toolbar for specifiying the sensor: sound, resitance, or voltage ''' LOWER = 0.0 UPPER = 1.0 STR_DC_R = \ _("Resistive sensor (connect sensor to pink 'Mic In' on left side \ of XO)" ) + ' ' STR_DC_V = \ _("Voltage sensor (connect sensor to pink 'Mic In' on left side \ of XO)" ) + ' ' STR_AC = _('Sound') + ' ' STR_RESISTANCE = _('Resistance') + ' (' + _('Ohms') + ') ' STR_VOLTAGE = _('Voltage') + ' (' + _('Volts') + ') ' STR_TIME = _('Time Base') + ' ' STR_FREQUENCY = _('Frequency Base') + ' ' STR_INVERT = ' ' + _('Invert') + ' ' STR_XAXIS_TEXT = _('X Axis Scale: 1 division = %(division)s %(unit)s') # TRANSLATORS: This is milli seconds. MS = _('ms') # TRANSLATORS: This is Hertz, so 1/second. HZ = _('Hz') def __init__(self, activity, channels): ''' By default, start with resistance mode ''' gtk.Toolbar.__init__(self) self.activity = activity self._channels = channels self._lock_radio_buttons = False self._radio_button_pushed = False self.values = [] for i in range(self._channels): self.values.append('') self.string_for_textbox = '' self.gain = 1.0 self.y_mag = 3.0 self.capture_gain = CAPTURE_GAIN self.mic_boost = MIC_BOOST self.mode = 'sound' # Set up Time-domain Button self.time = RadioToolButton(group=None) self.time.set_named_icon('media-audio') self.insert(self.time, -1) self.time.set_tooltip(_('Sound')) self.time.connect('clicked', self.analog_resistance_voltage_mode_cb, 'sound') # Set up Resistance Button self.resistance = RadioToolButton(group=self.time) self.resistance.set_named_icon('resistance') if _is_xo(self.activity.hw): self.insert(self.resistance, -1) self.resistance.show() self.resistance.set_tooltip(_('Resistance Sensor')) self.resistance.connect('clicked', self.analog_resistance_voltage_mode_cb, 'resistance') # Set up Voltage Button self.voltage = RadioToolButton(group=self.time) self.voltage.set_named_icon('voltage') if _is_xo(self.activity.hw): self.insert(self.voltage, -1) self.voltage.set_tooltip(_('Voltage Sensor')) self.voltage.connect('clicked', self.analog_resistance_voltage_mode_cb, 'voltage') separator = gtk.SeparatorToolItem() separator.props.draw = True self.insert(separator, -1) self._log_value = LOG_TIMER_VALUES[1] self.log_label = gtk.Label(self._log_to_string(self._log_value)) toolitem = gtk.ToolItem() toolitem.add(self.log_label) self.insert(toolitem, -1) self._log_button = ToolButton('timer-10') self._log_button.set_tooltip(_('Select logging interval')) self._log_button.connect('clicked', self._log_selection_cb) self.insert(self._log_button, -1) self._setup_log_palette() # Set up Logging/Stop Logging Button self._record = ToolButton('media-record') self.insert(self._record, -1) self._record.set_tooltip(_('Start logging')) self._record.connect('clicked', self.record_control_cb) separator = gtk.SeparatorToolItem() separator.props.draw = True self.insert(separator, -1) toolitem = gtk.ToolItem() self.trigger_label = gtk.Label(_('Trigger')) toolitem.add(self.trigger_label) self.insert(toolitem, -1) # Set up Trigger Combo box self.trigger_none = RadioToolButton() self.trigger_none.set_named_icon('trigger-none') self.insert(self.trigger_none, -1) self.trigger_none.set_tooltip(_('None')) self.trigger_none.connect('clicked', self.update_trigger_control_cb, self.activity.wave.TRIGGER_NONE) self.trigger_rise = RadioToolButton(group=self.trigger_none) self.trigger_rise.set_named_icon('trigger-rise') self.insert(self.trigger_rise, -1) self.trigger_rise.set_tooltip(_('Rising Edge')) self.trigger_rise.connect('clicked', self.update_trigger_control_cb, self.activity.wave.TRIGGER_POS) self.trigger_fall = RadioToolButton(group=self.trigger_none) self.trigger_fall.set_named_icon('trigger-fall') self.insert(self.trigger_fall, -1) self.trigger_fall.set_tooltip(_('Falling Edge')) self.trigger_fall.connect('clicked', self.update_trigger_control_cb, self.activity.wave.TRIGGER_NEG) self.show_all() def get_log(self): return self._log_value def get_log_idx(self): if self._log_value in LOG_TIMER_VALUES: return LOG_TIMER_VALUES.index(self._log_value) else: return LOG_TIMER_VALUES[0] def set_log_idx(self, idx): self._log_value = LOG_TIMER_VALUES[idx] self.log_label.set_text(self._log_to_string(self._log_value)) if hasattr(self, '_log_button'): self._log_button.set_icon('timer-%d' % (self._log_value)) def _log_selection_cb(self, widget): if self._log_palette: if not self._log_palette.is_up(): self._log_palette.popup(immediate=True, state=self._log_palette.SECONDARY) else: self._log_palette.popdown(immediate=True) return def _log_to_seconds(self, tenth_seconds): return tenth_seconds / 10. def _log_to_string(self, tenth_seconds): if tenth_seconds in LOG_TIMER_LABELS: return LOG_TIMER_LABELS[tenth_seconds] else: return _('1 second') def _setup_log_palette(self): self._log_palette = self._log_button.get_palette() for tenth_seconds in LOG_TIMER_VALUES: text = self._log_to_string(tenth_seconds) menu_item = MenuItem(icon_name='timer-%d' % (tenth_seconds), text_label=self._log_to_string(tenth_seconds)) menu_item.connect('activate', self._log_selected_cb, tenth_seconds) self._log_palette.menu.append(menu_item) menu_item.show() def _log_selected_cb(self, button, seconds): self.set_log_idx(LOG_TIMER_VALUES.index(seconds)) def add_frequency_slider(self, toolbox): ''' Either on the Sound toolbar or the Main toolbar ''' self._freq_stepper_up = ToolButton('freq-high') self._freq_stepper_up.set_tooltip(_('Zoom out')) self._freq_stepper_up.connect('clicked', self._freq_stepper_up_cb) self._freq_stepper_up.show() self.activity.adjustmentf = gtk.Adjustment(0.5, self.LOWER, self.UPPER, 0.01, 0.1, 0) self.activity.adjustmentf.connect('value_changed', self.cb_page_sizef) self._freq_range = gtk.HScale(self.activity.adjustmentf) self._freq_range.set_inverted(True) self._freq_range.set_draw_value(False) self._freq_range.set_update_policy(gtk.UPDATE_CONTINUOUS) self._freq_range.set_size_request(120, 15) self._freq_range.show() self._freq_stepper_down = ToolButton('freq-low') self._freq_stepper_down.set_tooltip(_('Zoom in')) self._freq_stepper_down.connect('clicked', self._freq_stepper_down_cb) self._freq_stepper_down.show() self._freq_range_tool = gtk.ToolItem() self._freq_range_tool.add(self._freq_range) self._freq_range_tool.show() toolbox.add(self._freq_stepper_up) toolbox.add(self._freq_range_tool) toolbox.add(self._freq_stepper_down) return def update_trigger_control_cb(self, button, value): if button is None: value = self.activity.wave.TRIGGER_NONE if self.activity.wave.get_fft_mode(): self.trigger_none.set_active(True) else: self.activity.wave.set_trigger(value) def analog_resistance_voltage_mode_cb(self, button=None, mode_to_set='sound'): ''' Callback for Analog/Resistance/Voltage Buttons ''' if self._lock_radio_buttons: logging.debug('mode selector locked') self._radio_button_pushed = True return if self.mode == mode_to_set: logging.debug('mode already set to %s' % mode_to_set) return self._lock_radio_buttons = True if self.activity.CONTEXT == 'sound': self.sound_context_off() else: self.sensor_context_off() # Force time domain when switching modes if self.activity.wave.get_fft_mode(): self.activity.timefreq_control() # Turn off logging when switching modes if self.activity.audiograb.we_are_logging: self.record_control_cb() self.set_mode(mode_to_set) if mode_to_set == 'sound': self.set_sound_context() elif mode_to_set == 'resistance': self.set_sensor_context() elif mode_to_set == 'voltage': self.set_sensor_context() self.update_string_for_textbox() return False def unlock_radio_buttons(self): ''' Enable radio button selection ''' logging.debug('unlocking radio buttons') if self._radio_button_pushed: if self.mode == 'sound': self.time.set_active(True) elif self.mode == 'resistance': self.resistance.set_active(True) elif self.mode == 'voltage': self.voltage.set_active(True) self._lock_radio_buttons = False self._radio_button_pushed = False def set_mode(self, mode='sound'): ''' Set the mixer settings to match the current mode. ''' self.mode = mode self.activity.audiograb.set_sensor_type(self.mode) for i in range(self._channels): self.values[i] = 0.0 return def get_mode(self): ''' Get the mixer settings. ''' return self.mode def _freq_stepper_up_cb(self, button=None): ''' Moves the horizontal zoom slider to the left one notch, where one notch is 1/100 of the total range. This correspond to zooming out as a larger number of Hertz or milliseconds will be represented by the same space on the screen. ''' new_value = self._freq_range.get_value() +\ (self.UPPER - self.LOWER) / 100.0 if new_value <= self.UPPER: self._freq_range.set_value(new_value) else: self._freq_range.set_value(self.UPPER) def _freq_stepper_down_cb(self, button=None): ''' Moves the horizontal zoom slider to the right one notch, where one notch is 1/100 of the total range. This corresponds to zooming in. ''' new_value = self._freq_range.get_value() -\ (self.UPPER - self.LOWER) / 100.0 if new_value >= self.LOWER: self._freq_range.set_value(new_value) else: self._freq_range.set_value(self.LOWER) def cb_page_sizef(self, button=None): ''' Callback to scale the frequency range (zoom in and out) ''' if self._update_page_size_id: gobject.source_remove(self._update_page_size_id) self._update_page_size_id =\ gobject.timeout_add(250, self.update_page_size) return True def update_page_size(self): ''' Set up the scaling of the display. ''' self._update_page_size_id = None new_value = round(self.activity.adjustmentf.value * 100.0) / 100.0 if self.activity.adjustmentf.value != new_value: self.activity.adjustmentf.value = new_value return False time_div = 0.001 * max(self.activity.adjustmentf.value, 0.05) freq_div = 1000 * max(self.activity.adjustmentf.value, 0.01) self.activity.wave.set_div(time_div, freq_div) self.update_string_for_textbox() return False def set_sound_context(self): ''' Called when analog sensing is selected ''' self.set_show_hide_windows(mode='sound') gobject.timeout_add(500, self.sound_context_on) self.activity.CONTEXT = 'sound' def set_sensor_context(self): ''' Called when digital sensing is selected ''' self.set_show_hide_windows(mode='sensor') gobject.timeout_add(500, self.sensor_context_on) self.activity.CONTEXT = 'sensor' def set_show_hide_windows(self, mode='sound'): ''' Shows the appropriate window identified by the mode ''' self.activity.wave.set_context_on() for i in range(self._channels): self.activity.side_toolbars[i].set_show_hide(True, mode) def sensor_context_off(self): ''' Called when a DC sensor is no longer selected ''' # self.activity.audiograb.pause_grabbing() self.activity.audiograb.stop_grabbing() def sensor_context_on(self): ''' Called when a DC sensor is selected ''' self.update_string_for_textbox() self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE) # self.activity.audiograb.resume_grabbing() self.activity.audiograb.start_grabbing() return False def sound_context_off(self): ''' Called when an analog sensor is no longer selected ''' self.gain, self.y_mag = self.activity.wave.get_mag_params() self.capture_gain = self.activity.audiograb.get_capture_gain() self.mic_boost = self.activity.audiograb.get_mic_boost() self.activity.audiograb.stop_grabbing() def sound_context_on(self): ''' Called when an analog sensor is selected ''' self.activity.wave.set_mag_params(self.gain, self.y_mag) self.update_string_for_textbox() self.update_trigger_control_cb(None, self.activity.wave.TRIGGER_NONE) self.activity.audiograb.start_grabbing() return False def set_sample_value(self, value='', channel=0): ''' Write a sample value to the textbox. ''' gtk.threads_enter() self.values[channel] = value self.update_string_for_textbox() gtk.threads_leave() return def record_control_cb(self, button=None): ''' Depending upon the selected interval, does either a logging session, or just logs the current buffer. ''' if self.activity.audiograb.we_are_logging: self.activity.audiograb.set_logging_params(start_stop=False) self._record.set_icon('media-record') self._record.show() self._record.set_tooltip(_('Start Recording')) else: Xscale = (1.00 / self.activity.audiograb.get_sampling_rate()) Yscale = 0.0 interval = self._log_value / 10. # self.interval_convert() username = self.activity.nick if self.activity.wave.get_fft_mode(): self.activity.data_logger.start_new_session( username, Xscale, Yscale, self._log_to_string(self._log_value), channels=self._channels, mode='frequency') else: self.activity.data_logger.start_new_session( username, Xscale, Yscale, self._log_to_string(self._log_value), channels=self._channels, mode=self.mode) self.activity.audiograb.set_logging_params(start_stop=True, interval=interval, screenshot=False) self._record.set_icon('record-stop') self._record.show() self._record.set_tooltip(_('Stop Recording')) self.activity.new_recording = True def update_string_for_textbox(self): ''' Update the status field at the bottom of the canvas. ''' if self.mode == 'resistance': string_for_textbox = (self.STR_DC_R + '\n') string_for_textbox += self.STR_RESISTANCE elif self.mode == 'voltage': string_for_textbox = (self.STR_DC_V + '\n') string_for_textbox += self.STR_VOLTAGE else: string_for_textbox = (self.STR_AC + '\t') if self.activity.wave.get_fft_mode(): scalex = self.STR_XAXIS_TEXT % { 'unit': self.HZ, 'division': self.activity.wave.freq_div } string_for_textbox += self.STR_FREQUENCY string_for_textbox += ('\n' + scalex) elif self.mode == 'sound': scalex = self.STR_XAXIS_TEXT % { 'unit': self.MS, 'division': self.activity.wave.time_div * 1000 } string_for_textbox += self.STR_TIME string_for_textbox += ('\n' + scalex) else: for i in range(self._channels): string_for_textbox += '\t(%s)' % (self.values[i]) invert = False for i in range(self._channels): if self.activity.wave.get_invert_state(channel=i): invert = True if invert: string_for_textbox += self.STR_INVERT self.activity.text_box.set_label(string_for_textbox)
class GeoToolbar(gtk.Toolbar): """ Tools which interacts with the currently chosen view. This toolbar is meant general: General map tools can be enabled. The toolbar serves as controller. Because you use a specific geo you have to wire specific functionality to the common tools offered by this toolbar. Tools you may want to enable: =========== ========================== enable_goto_current_position User wants to center map over current position. toggle_crosslines User wants to show crosslines. navigation User wants to navigate the map. Includes buttons for NESW. zoom-in User wants to zoom-in the current map view. zoom-out User wants to zoom-out the current map view. zoom-bestfit User wants to zoom-in the current map view. =========== ========================== Enable one of these tools by calling the appropriate method with your custom callback method before adding the toolbar to the toolbox. """ title = _('Map tools') radio_show_own_pos_btn = None radio_show_all_pos_btn = None def __init__(self, view, name=None): """ Creates general toolbar where general map tools can be enabled. @param name: The name of the toolbar. """ gtk.Toolbar.__init__(self) self.set_property('can-focus', False) self.view = view if name: self.name = name self._logger = logging.getLogger(name) else: self._logger = logging.getLogger('geo.GeoToolbar') self._logger.setLevel(constants.LOG_LEVEL) # remove predefined key bindings gtk.binding_entry_remove(self, gtk.keysyms.Left, 0) gtk.binding_entry_remove(self, gtk.keysyms.Right, 0) gtk.binding_entry_remove(self, gtk.keysyms.Up, 0) gtk.binding_entry_remove(self, gtk.keysyms.Down, 0) gtk.binding_entry_remove(self, gtk.keysyms.plus, 0) gtk.binding_entry_remove(self, gtk.keysyms.minus, 0) self.callbacks = {} self.connect('key-press-event', self.key_pressed_cb, self.callbacks) self.show_no_positions = RadioToolButton() icon_name = os.path.join(constants.ICON_PATH, "show-no-positions.svg") icon = utils.load_svg_image(icon_name, None, None, BTN_ICON_SIZE) img = gtk.image_new_from_pixbuf(icon) self.show_no_positions.set_icon_widget(img) self.show_no_positions.set_tooltip(_('Show no players.')) def enable_show_own_position(self, view): """ Shows the only the own position on the map. """ self.radio_show_own_pos_btn = RadioToolButton(group=self.show_no_positions) (fill, stroke) = ('#ffffff', '#000000') # black/white explicit buddy_icon = utils.get_xo_icon(stroke, fill, BTN_ICON_SIZE) img = gtk.image_new_from_pixbuf(buddy_icon) self.radio_show_own_pos_btn.set_icon_widget(img) self.radio_show_own_pos_btn.set_tooltip(_('Show only me.')) self.radio_show_own_pos_btn.connect('clicked', view.radio_show_own_position_cb) self.insert(self.radio_show_own_pos_btn, -1) self.radio_show_own_pos_btn.show_all() if self.radio_show_all_pos_btn: self.show_no_positions.connect("clicked", view.radio_show_no_positions_cb) self.show_no_positions.show_all() self.insert(self.show_no_positions, -1) def enable_show_all_positions(self, view): """ Shows the position of all players participating the game. """ self.radio_show_all_pos_btn = RadioToolButton(group=self.show_no_positions) icon_name = os.path.join(constants.ICON_PATH , 'show-all-players.svg') icon = utils.load_svg_image(icon_name, None, None, BTN_ICON_SIZE) img = gtk.image_new_from_pixbuf(icon) self.radio_show_all_pos_btn.set_icon_widget(img) self.radio_show_all_pos_btn.set_tooltip(_('Show all players.')) self.radio_show_all_pos_btn.connect('clicked', view.radio_show_all_position_cb) self.insert(self.radio_show_all_pos_btn, -1) self.radio_show_all_pos_btn.show_all() if self.radio_show_own_pos_btn: self.show_no_positions.connect("clicked", view.radio_show_no_positions_cb) self.show_no_positions.show_all() self.insert(self.show_no_positions, -1) self.radio_show_all_pos_btn.set_active(True) def enable_center_current_position(self, on_center_on_current_position): """ Enables tool to set the map center to current lon/lat position. @param on_goto_current_position: The callback function to be called when user wants to center the map to current position. """ goto_current_pos_btn = ToggleToolButton('goto-current-pos') goto_current_pos_btn.set_tooltip(_('Center map on my position.')) goto_current_pos_btn.connect('clicked', on_center_on_current_position) goto_current_pos_btn.set_active(GeoCanvas._CENTER_MAP) goto_current_pos_btn.show() self.insert(goto_current_pos_btn, -1) def enable_toggle_crosslines(self, view): """ Enables tool to toggle crosslines. @param view: The view for which the crosslines shall be displayed. """ toggle_crossline_btn = ToggleToolButton('toggle-crosslines') toggle_crossline_btn.set_tooltip(_('Show crossline.')) toggle_crossline_btn.set_active(GeoCanvas._CROSSLINES) toggle_crossline_btn.connect('clicked', view.toggle_crossline_cb) toggle_crossline_btn.show() self.insert(toggle_crossline_btn, -1) def enable_zoom(self, zoom_callbacks): """ Enables tools to zoom the map via buttons. @param zoom_callbacks: A dict containing zoom callbacks: =========== ============= zoom_callbacks['zoom_in'] A callback to zoom in zoom_callbacks['zoom_out'] A callback to zoom out =========== ============= """ self.zoom_in_btn = ToolButton('zoom-in') self.zoom_in_btn.set_tooltip(_('Zoom in.')) self.zoom_in_btn.connect('clicked', zoom_callbacks['zoom_in']) self.zoom_in_btn.show() self.insert(self.zoom_in_btn, -1) self.zoom_out_btn = ToolButton('zoom-out') self.zoom_out_btn.set_tooltip(_('Zoom out.')) self.zoom_out_btn.connect('clicked', zoom_callbacks['zoom_out']) self.zoom_out_btn.show() self.insert(self.zoom_out_btn, -1) self.callbacks.update(zoom_callbacks) def enable_zoom_bestfit(self, on_zoom_bestfit): """ Enables zoom-to-best-fit support on this toolbar. @param on_zoom_bestfit: The callback function to be called when user wants to zoom to best extent. """ zoom_best_fit_btn = ToolButton('zoom-best-fit') zoom_best_fit_btn.set_tooltip(_('Zoom best fitting extent.')) zoom_best_fit_btn.connect('clicked', on_zoom_bestfit) zoom_best_fit_btn.show() self.insert(zoom_best_fit_btn, -1) def enable_navigation(self, nav_callbacks): """ Enables tools to navigate the map via buttons. @param nav_callbacks: A dict containing navigation callbacks: =========== ============= nav_callbacks['west'] A callback to step west nav_callbacks['north'] A callback to step north nav_callbacks['south'] A callback to step south nav_callbacks['east'] A callback to step east =========== ============= """ self._enable_step_west(nav_callbacks['west']) self._enable_step_north(nav_callbacks['north']) self._enable_step_south(nav_callbacks['south']) self._enable_step_east(nav_callbacks['east']) self.callbacks.update(nav_callbacks) def enable_custom_Button(self, button): """ Inserts a custom button to the map toolbar. Consider to use it only, if it does not make much sense to place the button in its own toolbar (e.g. if there will be only one button, which might an extra toolbar dispensable). """ self.insert(button, -1) def key_pressed_cb(self, widget, event, callbacks): """ Callback handles all incoming keyevents and calls the appropriate callback-method. """ keyname = gtk.gdk.keyval_name(event.keyval) #self._logger.debug('\'%s\' key pressed' % keyname) if(keyname in ['KP_Up']): # up self.set_focus_child(self.step_north_btn) callbacks['north'](None) elif(keyname in ['KP_Down']): # down self.set_focus_child(self.step_south_btn) callbacks['south'](None) elif(keyname in ['KP_Left']): #left self.set_focus_child(self.step_west_btn) callbacks['west'](None) elif(keyname in ['KP_Right']): #right self.set_focus_child(self.step_east_btn) callbacks['east'](None) elif(keyname in ['plus', 'KP_Add', 'KP_Page_Up']): # zoom in self.set_focus_child(self.zoom_in_btn) callbacks['zoom_in'](None) elif(keyname in ['minus', 'KP_Substract', 'KP_Page_Down']): # zoom out self.set_focus_child(self.zoom_out_btn) callbacks['zoom_out'](None) if self.view._CROSSLINES: self.view.motion_crosslines(self.view.fixed) def _enable_step_north(self, on_step_north): """ Enables button to step north. @param on_step_north: The callback function to be called when the user wants to step north. """ self.step_north_btn = ToolButton('step-north') self.step_north_btn.set_tooltip(_('Move North.')) self.step_north_btn.connect('clicked', on_step_north) self.step_north_btn.show() self.insert(self.step_north_btn, -1) def _enable_step_east(self, on_step_east): """ Enables button to step east. @param on_step_east: The callback function to be called when the user wants to step east. """ self.step_east_btn = ToolButton('step-east') self.step_east_btn.set_tooltip(_('Move East.')) self.step_east_btn.connect('clicked', on_step_east) self.step_east_btn.show() self.insert(self.step_east_btn, -1) def _enable_step_south(self, on_step_south): """ Enables button to step south. @param on_step_south: The callback function to be called when the user wants to step south. """ self.step_south_btn = ToolButton('step-south') self.step_south_btn.set_tooltip(_('Move South.')) self.step_south_btn.connect('clicked', on_step_south) self.step_south_btn.show() self.insert(self.step_south_btn, -1) def _enable_step_west(self, on_step_west): """ Enables button to step west. @param on_step_west: The callback function to be called when the user wants to step west. """ self.step_west_btn = ToolButton('step-west') self.step_west_btn.set_tooltip(_('Move West.')) self.step_west_btn.connect('clicked', on_step_west) self.step_west_btn.show() self.insert(self.step_west_btn, -1)