def _build_palette(self, tool): if tool.palette_enabled: if tool.palette_mode == tools.PALETTE_MODE_ICONS: grid = Gtk.Grid() for s, settings in enumerate(tool.palette_settings): self.game.toolList[tool.name].buttons.append([]) for i, icon_value in enumerate(settings['icon_values']): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(settings['icons'][i]) button.connect('clicked', self._palette_icon_clicked, tool.name, s, settings['name'], icon_value) grid.attach(button, i, s, 1, 1) self.game.toolList[tool.name].buttons[s].append(button) button.show() if settings['active'] == settings['icons'][i]: button.set_icon_name(settings['icons'][i] + '-selected') button.set_active(True) return grid else: return None
def _build_palette(self, tool): if tool.palette_enabled: if tool.palette_mode == tools.PALETTE_MODE_ICONS: grid = Gtk.Grid() for s, settings in enumerate(tool.palette_settings): self.game.toolList[tool.name].buttons.append([]) for i, icon_value in enumerate(settings['icon_values']): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(settings['icons'][i]) button.connect('clicked', self._palette_icon_clicked, tool.name, s, settings['name'], icon_value) grid.attach(button, i, s, 1, 1) self.game.toolList[tool.name].buttons[s].append(button) button.show() if settings['active'] == settings['icons'][i]: button.set_icon_name(settings['icons'][i] + '-selected') button.set_active(True) return grid else: return None
def __init__(self, owner): GObject.GObject.__init__(self) self.owner = owner self._insert_separator(True) self.desktop = [] btn = RadioToolButton(group=None) btn.set_icon_name('jam-preset1') btn.connect('toggled', self.setDesktop, 0) btn.set_tooltip(_('Desktop 1')) self.insert(btn, -1) self.desktop.append(btn) for i in range(2, 11): btn = RadioToolButton(group=self.desktop[0]) btn.set_icon_name('jam-preset%d' % i) btn.connect('toggled', self.setDesktop, i - 1) btn.set_tooltip(_('Desktop %d' % i)) self.insert(btn, -1) self.desktop.append(btn) self._insert_separator(True) self.show_all()
def __init__(self, owner): GObject.GObject.__init__(self) self.owner = owner self.toolItem = {} self.blockBeat = False self.beatWheel = [] btn = RadioToolButton(group=None) btn.set_icon_name('beats') btn.connect('toggled', self.setBeat, 0) btn.set_tooltip(_('Jump To Beat')) self.insert(btn, -1) self.beatWheel.append(btn) for i in range(1, 12): btn = RadioToolButton(group=self.beatWheel[0]) btn.set_icon_name('beats') btn.connect('toggled', self.setBeat, i) btn.set_tooltip(_('Jump To Beat')) self.insert(btn, -1) self.beatWheel.append(btn) label = Gtk.Label(label=_("Synch to:")) self.syncLabel = Gtk.ToolItem() self.syncLabel.add(label) self.insert(self.syncLabel, 0) self.comboBox = ComboBox() self.comboBox.append_item(1, _("1 Beat")) self.comboBox.append_item(2, _("2 Beats")) self.comboBox.append_item(3, _("3 Beats")) self.comboBox.append_item(4, _("4 Beats")) self.comboBox.append_item(5, _("5 Beats")) self.comboBox.append_item(6, _("6 Beats")) self.comboBox.append_item(7, _("7 Beats")) self.comboBox.append_item(8, _("8 Beats")) self.comboBox.append_item(9, _("9 Beats")) self.comboBox.append_item(10, _("10 Beats")) self.comboBox.append_item(11, _("11 Beats")) self.comboBox.append_item(12, _("12 Beats")) self.comboBox.set_active(4 - 1) # default 4 beats self.comboBox.connect("changed", self.changeSync) self.syncBox = ToolComboBox(self.comboBox) self.insert(self.syncBox, 1) self.show_all()
def radio_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None, group=None): ''' Add a radio button to a toolbar ''' button = RadioToolButton(group=group) button.set_icon_name(icon_name) if tooltip is not None: button.set_tooltip(tooltip) if cb_arg is None: button.connect('clicked', callback) else: button.connect('clicked', callback, cb_arg) if hasattr(toolbar, 'insert'): # the main toolbar toolbar.insert(button, -1) else: # or a secondary toolbar toolbar.props.page.insert(button, -1) button.show() return button
def radio_factory(button_name, toolbar, callback, cb_arg=None, tooltip=None, group=None): """ Add a radio button to a toolbar """ button = RadioToolButton(group=group) button.set_icon_name(button_name) if callback is not None: if cb_arg is None: button.connect("clicked", callback) else: button.connect("clicked", callback, cb_arg) if hasattr(toolbar, "insert"): # Add button to the main toolbar... toolbar.insert(button, -1) else: # ...or a secondary toolbar. toolbar.props.page.insert(button, -1) button.show() if tooltip is not None: button.set_tooltip(tooltip) return button
def radio_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None, group=None): ''' Add a radio button to a toolbar ''' button = RadioToolButton(group=group) button.set_icon_name(icon_name) if tooltip is not None: button.set_tooltip(tooltip) if cb_arg is None: button.connect('clicked', callback) else: button.connect('clicked', callback, cb_arg) if hasattr(toolbar, 'insert'): # the main toolbar toolbar.insert(button, -1) else: # or a secondary toolbar toolbar.props.page.insert(button, -1) button.show() return button
def _insert_create_tools(self, create_toolbar): # Make + add the component buttons self.radioList = {} for i, c in enumerate(tools.allTools): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(c.icon) button.set_tooltip(c.toolTip) button.set_accelerator(c.toolAccelerator) button.connect("clicked", self.radioClicked) palette = self._build_palette(c) if palette is not None: palette.show() button.get_palette().set_content(palette) self._insert_item(create_toolbar, button, -1) button.show() self.radioList[button] = c.name if hasattr(c, "constructor"): self._constructors[c.name] = self.game.toolList[c.name].constructor
def _insert_create_tools(self, create_toolbar): # Make + add the component buttons self.radioList = {} for i, c in enumerate(tools.allTools): if i == 0: button = RadioToolButton(group=None) firstbutton = button else: button = RadioToolButton(group=firstbutton) button.set_icon_name(c.icon) button.set_tooltip(c.toolTip) button.set_accelerator(c.toolAccelerator) button.connect('clicked', self.radioClicked) palette = self._build_palette(c) if palette is not None: palette.show() button.get_palette().set_content(palette) self._insert_item(create_toolbar, button, -1) button.show() self.radioList[button] = c.name if hasattr(c, 'constructor'): self._constructors[c.name] = \ self.game.toolList[c.name].constructor
def _load_standard_buttons(self, toolbar): fraction_button = RadioToolButton(group=None) fraction_button.set_icon_name('fraction') fraction_button.set_tooltip(_('fractions')) fraction_button.connect('clicked', self._fraction_cb) toolbar.insert(fraction_button, -1) fraction_button.show() sector_button = RadioToolButton(group=fraction_button) sector_button.set_icon_name('sector') sector_button.set_tooltip(_('sectors')) sector_button.connect('clicked', self._sector_cb) toolbar.insert(sector_button, -1) sector_button.show() percent_button = RadioToolButton(group=fraction_button) percent_button.set_icon_name('percent') percent_button.set_tooltip(_('percents')) percent_button.connect('clicked', self._percent_cb) toolbar.insert(percent_button, -1) percent_button.show() self._player = Gtk.Image() self._player.set_from_pixbuf( svg_str_to_pixbuf( generate_xo_svg(scale=0.8, colors=['#282828', '#282828']))) self._player.set_tooltip_text(self.nick) toolitem = Gtk.ToolItem() toolitem.add(self._player) self._player.show() toolbar.insert(toolitem, -1) toolitem.show() self._label = Gtk.Label(_("Click the ball to start.")) self._label.set_line_wrap(True) if Gdk.Screen.width() < 1024: self._label.set_size_request(275, -1) else: self._label.set_size_request(500, -1) self.toolitem = Gtk.ToolItem() self.toolitem.add(self._label) self._label.show() toolbar.insert(self.toolitem, -1) self.toolitem.show()
def _load_standard_buttons(self, toolbar): fraction_button = RadioToolButton(group=None) fraction_button.set_icon_name('fraction') fraction_button.set_tooltip(_('fractions')) fraction_button.connect('clicked', self._fraction_cb) toolbar.insert(fraction_button, -1) fraction_button.show() sector_button = RadioToolButton(group=fraction_button) sector_button.set_icon_name('sector') sector_button.set_tooltip(_('sectors')) sector_button.connect('clicked', self._sector_cb) toolbar.insert(sector_button, -1) sector_button.show() percent_button = RadioToolButton(group=fraction_button) percent_button.set_icon_name('percent') percent_button.set_tooltip(_('percents')) percent_button.connect('clicked', self._percent_cb) toolbar.insert(percent_button, -1) percent_button.show() self._player = Gtk.Image() self._player.set_from_pixbuf(svg_str_to_pixbuf( generate_xo_svg(scale=0.8, colors=['#282828', '#282828']))) self._player.set_tooltip_text(self.nick) toolitem = Gtk.ToolItem() toolitem.add(self._player) self._player.show() toolbar.insert(toolitem, -1) toolitem.show() self._label = Gtk.Label(_("Click the ball to start.")) self._label.set_line_wrap(True) if Gdk.Screen.width() < 1024: self._label.set_size_request(275, -1) else: self._label.set_size_request(500, -1) self.toolitem = Gtk.ToolItem() self.toolitem.add(self._label) self._label.show() toolbar.insert(self.toolitem, -1) self.toolitem.show()
def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = 'media-playback-stop' self.stop_play_state = True self.stop_play = ToolButton('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play.set_accelerator(_('<ctrl>space')) self.stop_play.connect('clicked', self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name('slow-walk-milton-raposo') slowest_button.set_tooltip(_('Run slower')) slowest_button.connect('clicked', self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name('walking') slow_button.set_tooltip(_('Run slow')) slow_button.connect('clicked', self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name('running') fast_button.set_tooltip('Run fast') fast_button.connect('clicked', self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all()
def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = 'media-playback-stop' self.stop_play_state = True self.stop_play = ToolButton('media-playback-stop') self.stop_play.set_tooltip(_('Stop')) self.stop_play.set_accelerator(_('<ctrl>space')) self.stop_play.connect('clicked', self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name('slow-walk-milton-raposo') slowest_button.set_tooltip(_('Run slower')) slowest_button.connect('clicked', self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name('walking') slow_button.set_tooltip(_('Run slow')) slow_button.connect('clicked', self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name('running') fast_button.set_tooltip('Run fast') fast_button.connect('clicked', self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all()
def _insert_stop_play_button(self, toolbar): self.stop_play_toolbar = ToolbarButton() st_toolbar = self.stop_play_toolbar st_toolbar.props.page = Gtk.Toolbar() st_toolbar.props.icon_name = "media-playback-stop" self.stop_play_state = True self.stop_play = ToolButton("media-playback-stop") self.stop_play.set_tooltip(_("Stop")) self.stop_play.set_accelerator(_("<ctrl>space")) self.stop_play.connect("clicked", self.stop_play_cb) self._insert_item(st_toolbar, self.stop_play) self.stop_play.show() slowest_button = RadioToolButton(group=None) slowest_button.set_icon_name("slow-walk-milton-raposo") slowest_button.set_tooltip(_("Run slower")) slowest_button.connect("clicked", self._set_fps_cb, SLOWEST_FPS) self._insert_item(st_toolbar, slowest_button) slowest_button.show() slow_button = RadioToolButton(group=slowest_button) slow_button.set_icon_name("walking") slow_button.set_tooltip(_("Run slow")) slow_button.connect("clicked", self._set_fps_cb, SLOW_FPS) self._insert_item(st_toolbar, slow_button) slow_button.show() fast_button = RadioToolButton(group=slowest_button) fast_button.set_icon_name("running") fast_button.set_tooltip("Run fast") fast_button.connect("clicked", self._set_fps_cb, FAST_FPS) self._insert_item(st_toolbar, fast_button) fast_button.show() fast_button.set_active(True) toolbar.insert(self.stop_play_toolbar, -1) self.stop_play_toolbar.show_all()
def create_palette(self): self._palette = self.get_child().create_palette() color_palette_hbox = self._palette._picker_hbox self.custom_box = Gtk.VBox() self.vbox_brush_options = Gtk.VBox() # This is where we set restrictions for size: # Initial value, minimum value, maximum value, step adj = Gtk.Adjustment(self.properties['line size'], 1.0, 100.0, 1.0) self.size_scale = Gtk.HScale() self.size_scale.set_adjustment(adj) self.size_scale.set_draw_value(False) self.size_scale.set_size_request(style.zoom(200), -1) self.size_label = Gtk.Label(label=_('Size')) self.size_label.props.halign = Gtk.Align.START self.vbox_brush_options.pack_start(self.size_label, True, True, 0) self.vbox_brush_options.pack_start(self.size_scale, True, True, 0) self.size_scale.connect('value-changed', self._on_value_changed) # Control alpha alpha = self.properties['alpha'] * 100 adj_alpha = Gtk.Adjustment(alpha, 10.0, 100.0, 1.0) self.alpha_scale = Gtk.HScale() self.alpha_scale.set_adjustment(adj_alpha) self.alpha_scale.set_draw_value(False) self.alpha_scale.set_size_request(style.zoom(200), -1) self.alpha_label = Gtk.Label(label=_('Opacity')) self.alpha_label.props.halign = Gtk.Align.START self.vbox_brush_options.pack_start(self.alpha_label, True, True, 0) self.vbox_brush_options.pack_start(self.alpha_scale, True, True, 0) self.alpha_scale.connect('value-changed', self._on_alpha_changed) # User is able to choose Shapes for 'Brush' and 'Eraser' self.shape_box = Gtk.HBox() self.custom_box.pack_start(self.vbox_brush_options, True, True, 0) item1 = RadioToolButton() item1.set_icon_name('tool-shape-ellipse') item2 = RadioToolButton() item2.set_icon_name('tool-shape-rectangle') item2.props.group = item1 if self.properties['line shape'] == 'circle': item1.set_active(True) else: item2.set_active(True) item1.connect('toggled', self._on_toggled, self.properties, 'circle') item2.connect('toggled', self._on_toggled, self.properties, 'square') self.shape_box.pack_start(Gtk.Label(_('Shape')), True, True, 0) self.shape_box.pack_start(item1, True, True, 0) self.shape_box.pack_start(item2, True, True, 0) self.vbox_brush_options.pack_start(self.shape_box, True, True, 0) self.keep_aspect_checkbutton = Gtk.CheckButton(_('Keep aspect')) ratio = self._activity.area.keep_aspect_ratio self.keep_aspect_checkbutton.set_active(ratio) self.keep_aspect_checkbutton.connect( 'toggled', self._keep_aspect_checkbutton_toggled) self.vbox_brush_options.pack_start(self.keep_aspect_checkbutton, True, True, 0) self.custom_separator = Gtk.VSeparator() color_palette_hbox.pack_start(self.custom_separator, True, True, padding=style.DEFAULT_SPACING) color_palette_hbox.pack_start(self.custom_box, True, True, padding=style.DEFAULT_SPACING) color_palette_hbox.show_all() self._update_palette() return self._palette
def __init__(self, model, alerts=None): SectionView.__init__(self) self._model = model self._images_loaded = False self._append_to_store_sid = None self.connect('realize', self.__realize_cb) self.connect('unrealize', self.__unrealize_cb) self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) label_box = Gtk.Box() label_bg = Gtk.Label(label=_('Select a background:')) label_bg.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) label_bg.show() label_box.pack_start(label_bg, False, True, 0) label_box.show() self.pack_start(label_box, False, True, 1) clear_button = Gtk.Button() clear_button.set_label(_('Clear background')) clear_button.connect('clicked', self._clear_clicked_cb) clear_button.show() self.pack_end(clear_button, False, True, 0) scrolled_window = Gtk.ScrolledWindow() scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.pack_start(scrolled_window, True, True, 0) scrolled_window.show() self._store = Gtk.ListStore(GdkPixbuf.Pixbuf, str) self._icon_view = Gtk.IconView.new_with_model(self._store) self._icon_view.set_selection_mode(Gtk.SelectionMode.SINGLE) self._icon_view.connect('selection-changed', self._background_selected) self._icon_view.set_pixbuf_column(0) self._icon_view.grab_focus() scrolled_window.add(self._icon_view) self._icon_view.show() alpha = self._model.get_background_alpha_level() alpha_box = Gtk.HBox() alpha_buttons = [] alpha_icons = [ [1.0, 'network-wireless-000'], [0.8, 'network-wireless-020'], [0.6, 'network-wireless-040'], [0.4, 'network-wireless-060'], [0.2, 'network-wireless-080']] for value, icon_name in alpha_icons: if len(alpha_buttons) > 0: button = RadioToolButton(group=alpha_buttons[0]) else: button = RadioToolButton(group=None) button.set_icon_name(icon_name) button.value = value button.props.active = value == alpha button.show() alpha_box.pack_start(button, False, True, 0) alpha_buttons.append(button) for button in alpha_buttons: button.connect('toggled', self._set_alpha_cb) alpha_alignment = Gtk.Alignment() alpha_alignment.set(0.5, 0, 0, 0) alpha_alignment.add(alpha_box) alpha_box.show() self.pack_start(alpha_alignment, False, False, 0) alpha_alignment.show() self._paths_list = [] file_paths = [] for directory in self._model.BACKGROUNDS_DIRS: if directory is not None and os.path.exists(directory): for root, dirs, files in os.walk(directory): for file_ in files: file_paths.append(os.path.join(root, file_)) self._append_to_store(file_paths) self.setup()
def __init__(self, model, alerts=None): SectionView.__init__(self) self._model = model self._images_loaded = False self._append_to_store_sid = None self.connect('realize', self.__realize_cb) self.connect('unrealize', self.__unrealize_cb) self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) label_box = Gtk.Box() label_bg = Gtk.Label(label=_('Select a background:')) label_bg.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) label_bg.show() label_box.pack_start(label_bg, False, True, 0) label_box.show() self.pack_start(label_box, False, True, 1) clear_button = Gtk.Button() clear_button.set_label(_('Clear background')) clear_button.connect('clicked', self._clear_clicked_cb) clear_button.show() self.pack_end(clear_button, False, True, 0) scrolled_window = Gtk.ScrolledWindow() scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.pack_start(scrolled_window, True, True, 0) scrolled_window.show() self._store = Gtk.ListStore(GdkPixbuf.Pixbuf, str) self._icon_view = Gtk.IconView.new_with_model(self._store) self._icon_view.set_selection_mode(Gtk.SelectionMode.SINGLE) self._icon_view.connect('selection-changed', self._background_selected) self._icon_view.set_pixbuf_column(0) self._icon_view.grab_focus() scrolled_window.add(self._icon_view) self._icon_view.show() alpha = self._model.get_background_alpha_level() alpha_box = Gtk.HBox() alpha_buttons = [] alpha_icons = [[1.0, 'network-wireless-000'], [0.8, 'network-wireless-020'], [0.6, 'network-wireless-040'], [0.4, 'network-wireless-060'], [0.2, 'network-wireless-080']] for value, icon_name in alpha_icons: if len(alpha_buttons) > 0: button = RadioToolButton(group=alpha_buttons[0]) else: button = RadioToolButton(group=None) button.set_icon_name(icon_name) button.value = value button.props.active = value == alpha button.show() alpha_box.pack_start(button, False, True, 0) alpha_buttons.append(button) for button in alpha_buttons: button.connect('toggled', self._set_alpha_cb) alpha_alignment = Gtk.Alignment() alpha_alignment.set(0.5, 0, 0, 0) alpha_alignment.add(alpha_box) alpha_box.show() self.pack_start(alpha_alignment, False, False, 0) alpha_alignment.show() self._paths_list = [] file_paths = [] for directory in self._model.BACKGROUNDS_DIRS: if directory is not None and os.path.exists(directory): for root, dirs, files in os.walk(directory): for file_ in files: file_paths.append(os.path.join(root, file_)) self._append_to_store(file_paths) self.setup()
def create_palette(self): self._palette = self.get_child().create_palette() color_palette_hbox = self._palette._picker_hbox self.custom_box = Gtk.VBox() self.vbox_brush_options = Gtk.VBox() # This is where we set restrictions for size: # Initial value, minimum value, maximum value, step adj = Gtk.Adjustment(self.properties['line size'], 1.0, 100.0, 1.0) self.size_scale = Gtk.HScale() self.size_scale.set_adjustment(adj) self.size_scale.set_draw_value(False) self.size_scale.set_size_request(style.zoom(200), -1) self.size_label = Gtk.Label(label=_('Size')) self.size_label.props.halign = Gtk.Align.START self.vbox_brush_options.pack_start(self.size_label, True, True, 0) self.vbox_brush_options.pack_start(self.size_scale, True, True, 0) self.size_scale.connect('value-changed', self._on_value_changed) # Control alpha alpha = self.properties['alpha'] * 100 adj_alpha = Gtk.Adjustment(alpha, 10.0, 100.0, 1.0) self.alpha_scale = Gtk.HScale() self.alpha_scale.set_adjustment(adj_alpha) self.alpha_scale.set_draw_value(False) self.alpha_scale.set_size_request(style.zoom(200), -1) self.alpha_label = Gtk.Label(label=_('Opacity')) self.alpha_label.props.halign = Gtk.Align.START self.vbox_brush_options.pack_start(self.alpha_label, True, True, 0) self.vbox_brush_options.pack_start(self.alpha_scale, True, True, 0) self.alpha_scale.connect('value-changed', self._on_alpha_changed) # User is able to choose Shapes for 'Brush' and 'Eraser' self.shape_box = Gtk.HBox() self.custom_box.pack_start(self.vbox_brush_options, True, True, 0) item1 = RadioToolButton() item1.set_icon_name('tool-shape-ellipse') item2 = RadioToolButton() item2.set_icon_name('tool-shape-rectangle') item2.props.group = item1 if self.properties['line shape'] == 'circle': item1.set_active(True) else: item2.set_active(True) item1.connect('toggled', self._on_toggled, self.properties, 'circle') item2.connect('toggled', self._on_toggled, self.properties, 'square') self.shape_box.pack_start(Gtk.Label(_('Shape')), True, True, 0) self.shape_box.pack_start(item1, True, True, 0) self.shape_box.pack_start(item2, True, True, 0) self.vbox_brush_options.pack_start(self.shape_box, True, True, 0) self.keep_aspect_checkbutton = Gtk.CheckButton(_('Keep aspect')) ratio = self._activity.area.keep_aspect_ratio self.keep_aspect_checkbutton.set_active(ratio) self.keep_aspect_checkbutton.connect( 'toggled', self._keep_aspect_checkbutton_toggled) self.vbox_brush_options.pack_start(self.keep_aspect_checkbutton, True, True, 0) self.custom_separator = Gtk.VSeparator() color_palette_hbox.pack_start(self.custom_separator, True, True, padding=style.DEFAULT_SPACING) color_palette_hbox.pack_start(self.custom_box, True, True, padding=style.DEFAULT_SPACING) color_palette_hbox.show_all() self._update_palette() return self._palette
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 ''' super(type(self), self).__init__() 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(icon_name='media-audio', group=None) 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(icon_name='resistance', group=self.time) if _can_use_dc(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(icon_name='voltage', group=self.time) if _can_use_dc(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_icon_name('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_icon_name('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_icon_name('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) 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=text) 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.Scale(orientation=Gtk.Orientation.HORIZONTAL, adjustment=self.activity.adjustmentf) self._freq_range.set_inverted(True) self._freq_range.set_draw_value(False) 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 value = self.activity.adjustmentf.get_value() new_value = round(value * 100.0) / 100.0 if value != new_value: self.activity.adjustmentf.set_value(new_value) return False time_div = 0.001 * max(value, 0.05) freq_div = 1000 * max(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. ''' self.values[channel] = value self.update_string_for_textbox() 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_name('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) self._record.set_icon_name('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 HelpPanel(Gtk.Grid): def __init__(self, task_master): Gtk.Grid.__init__(self) self.set_row_spacing(style.DEFAULT_SPACING) self.set_column_spacing(style.DEFAULT_SPACING) self.set_column_homogeneous(True) self.set_border_width(style.DEFAULT_SPACING) self._task_master = task_master self._connected = False self._mode = _FEEDBACK_TICKET alignment = Gtk.Alignment.new(0., 0.5, 0., 0.) phone_label = Gtk.Label() phone_label.set_use_markup(True) phone_label.set_justify(Gtk.Justification.LEFT) phone_label.set_markup( '<span foreground="%s" size="large">%s</span>' % (style.COLOR_WHITE.get_html(), _('Call: 1-800 ONE EDU\n' 'Email: [email protected]'))) alignment.add(phone_label) phone_label.show() self.attach(alignment, 0, 0, 4, 1) alignment.show() alignment = Gtk.Alignment.new(0., 0.5, 0., 0.) self._info_label = Gtk.Label() self._info_label.set_use_markup(True) self._info_label.set_justify(Gtk.Justification.LEFT) self._info_label.set_markup( '<span foreground="%s" size="large">%s</span>' % (style.COLOR_WHITE.get_html(), _('Or use the form below:'))) alignment.add(self._info_label) self._info_label.show() self.attach(alignment, 0, 4, 4, 1) alignment.show() self._email_entry = Gtk.Entry() email_address = self._task_master.read_task_data(EMAIL_UID) if email_address is not None: self._email_entry.set_text(email_address) else: self._email_entry.set_text(_EMAIL_TEXT) self.attach(self._email_entry, 0, 5, 4, 1) self._email_entry.show() self._email_entry.connect('changed', self._email_changed_cb) self._email_entry.set_can_focus(True) grid = Gtk.Grid() self._feedback_button = RadioToolButton(group=None) self._feedback_button.set_icon_name('edit-description') self._feedback_button.connect('clicked', self._feedback_button_cb) grid.attach(self._feedback_button, 0, 0, 1, 1) self._feedback_button.show() label = Gtk.Label() label.set_use_markup(True) label.set_justify(Gtk.Justification.LEFT) label.set_markup('<span foreground="%s" size="large">%s</span>' % (style.COLOR_WHITE.get_html(), _('Send feedback'))) grid.attach(label, 1, 0, 1, 1) label.show() alignment = Gtk.Alignment.new(0., 0.5, 0., 0.) alignment.add(grid) grid.show() self.attach(alignment, 0, 6, 2, 1) alignment.show() grid = Gtk.Grid() self._help_button = RadioToolButton(group=self._feedback_button) self._help_button.set_icon_name('toolbar-help-gray') self._help_button.connect('clicked', self._help_button_cb) grid.attach(self._help_button, 0, 0, 1, 1) self._help_button.show() label = Gtk.Label() label.set_use_markup(True) label.set_justify(Gtk.Justification.LEFT) label.set_markup('<span foreground="%s" size="large">%s</span>' % (style.COLOR_WHITE.get_html(), _('Ask for help'))) grid.attach(label, 1, 0, 1, 1) label.show() alignment = Gtk.Alignment.new(0., 0.5, 0., 0.) alignment.add(grid) grid.show() self.attach(alignment, 2, 6, 2, 1) alignment.show() self._feedback_button.set_active(True) self._text_view = Gtk.TextView() self._text_view.set_wrap_mode(Gtk.WrapMode.WORD) self._text_view.set_size_request(-1, style.GRID_CELL_SIZE * 2) self._text_buffer = self._text_view.get_buffer() self._text_buffer.set_text(_ACTIVE_TEXT) self.attach(self._text_view, 0, 7, 4, 4) self._text_view.show() self._text_view.connect('focus-in-event', self._text_focus_in_cb) self._check_button = Gtk.CheckButton(label=_('Include screenshot?')) self._check_button.set_active(True) self.attach(self._check_button, 0, 11, 2, 1) self._check_button.show() self._send_button = Gtk.Button(_('Send')) self.attach(self._send_button, 3, 11, 1, 1) self._send_button.connect('clicked', self._send_button_cb) self._send_button.show() def _email_changed_cb(self, widget): email = self._email_entry.get_text() if email == _EMAIL_TEXT: self._email_entry.set_text('') if utils.is_valid_email_entry(email) and self._connected: self._send_button.set_sensitive(True) else: self._send_button.set_sensitive(False) def _text_focus_in_cb(self, widget, event): bounds = self._text_buffer.get_bounds() text = self._text_buffer.get_text(bounds[0], bounds[1], True) email = self._email_entry.get_text() if text == _ACTIVE_TEXT: self._text_buffer.set_text('') if utils.is_valid_email_entry(email) and self._connected: self._send_button.set_sensitive(True) else: self._send_button.set_sensitive(False) def set_connected(self, connected): self._connected = connected if connected: bounds = self._text_buffer.get_bounds() text = self._text_buffer.get_text(bounds[0], bounds[1], True) if text == _INACTIVE_TEXT: self._text_buffer.set_text(_ACTIVE_TEXT) self._text_view.set_sensitive(True) email = self._email_entry.get_text() if utils.is_valid_email_entry(email): self._send_button.set_sensitive(True) else: self._send_button.set_sensitive(False) else: bounds = self._text_buffer.get_bounds() text = self._text_buffer.get_text(bounds[0], bounds[1], True) if text == _ACTIVE_TEXT: self._text_buffer.set_text(_INACTIVE_TEXT) self._text_buffer.set_text(_INACTIVE_TEXT) self._text_view.set_sensitive(False) self._send_button.set_sensitive(False) def _feedback_button_cb(self, widget=None): self._mode = _FEEDBACK_TICKET # Necessary because of a bug with Sugar radiobuttons on palettes self._feedback_button.set_icon_name('edit-description') self._help_button.set_icon_name('toolbar-help-gray') def _help_button_cb(self, widget=None): self._mode = _HELP_TICKET # Necessary because of a bug with Sugar radiobuttons on palettes self._feedback_button.set_icon_name('edit-description-gray') self._help_button.set_icon_name('toolbar-help') def _send_button_cb(self, widget=None): email = self._email_entry.get_text() if not utils.is_valid_email_entry(email): # We cannot send w/o valid email. self._email_entry.set_text(_EMAIL_TEXT) self._send_button.set_sensitive(False) else: self._task_master.activity.help_palette.popdown(immediate=True) self._task_master.activity.help_panel_visible = False self._task_master.activity.busy_cursor() GObject.idle_add(self._prepare_send_data) def _prepare_send_data(self): bounds = self._text_buffer.get_bounds() text = self._text_buffer.get_text(bounds[0], bounds[1], True) log_file_path = utils.get_log_file('org.sugarlabs.Training') section_index, task_index = \ self._task_master.get_section_and_task_index() section_name = self._task_master.get_section_name(section_index) email = self._email_entry.get_text() name = self._task_master.read_task_data(NAME_UID) school = self._task_master.read_task_data(SCHOOL_NAME) role = self._task_master.read_task_data(ROLE_UID) self._data = {'ticket': self._mode, 'section': section_name, 'task': task_index, 'body': text, 'log': log_file_path, 'name': name, 'email': email, 'school': school, 'role': role} if len(self._task_master.activity.volume_data) == 1: training_data_path = os.path.join( self._task_master.activity.volume_data[0]['usb_path'], self._task_master.activity.volume_data[0]['uid']) self._data['data'] = training_data_path if self._check_button.get_active(): # idle_add is not sufficient... waiting for graphics to refresh GObject.timeout_add(2000, self._take_screen_shot_and_send) else: self._send_data() def _do_send(self, data): subject = data['ticket'] body = data['body'] helper = FieldHelper() fields = [] fields.append(helper.get_field(0, data['section'])) fields.append(helper.get_field(1, data['task'])) if data['school']: fields.append(helper.get_field(2, data['school'])) if data['role']: fields.append(helper.get_field(3, data['role'])) uploads = [] if 'screenshot' in data: attachment = Attachment() attachment.create(data['screenshot'], 'shot.png', 'image/png') uploads.append(attachment.token()) if 'log' in data: attachment = Attachment() attachment.create(data['log'], 'log.txt', 'text/plain') uploads.append(attachment.token()) if 'data' in data: attachment = Attachment() try: attachment.create(data['data'], 'data.txt', 'text/plain') except IOError as e: logging.error('Could not include training data: %s' % e) else: uploads.append(attachment.token()) ticket = Ticket() ticket.create(subject, body, uploads, data['name'], data['email'], fields) def _take_screen_shot_and_send(self): self._data['screenshot'] = utils.take_screen_shot() self._send_data() def _send_data(self): logging.debug(self._data) try: self._do_send(self._data) except ZendeskError as e: _logger.error('Could not upload %s to zendesk: %s' % (self._data['ticket'], e)) self._task_master.activity.transfer_failed_signal.emit() else: self._task_master.activity.transfer_completed_signal.emit() self._task_master.activity.reset_cursor()