def on_link(self, link): parser = GuiActionParser() if link.startswith("quick://"): action = parser.restart(link[8:]).parse() self.reset_active_component() self.set_action(action, from_custom=True) elif link == "grab://trigger_button": def cb(action): action = TriggerAction(254, 255, action) self.set_action(action, from_custom=True) self.force_page("trigger") b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.hide_axes() b.show(self.window) elif link.startswith("page://"): def cb(): self.force_page(link[7:]) GLib.timeout_add(0.1, cb) elif link.startswith("advanced://"): exMore = self.builder.get_object("exMore") rvMore = self.builder.get_object("rvMore") ntbMore = self.builder.get_object("ntbMore") assert exMore.get_visible() exMore.set_expanded(True) rvMore.set_reveal_child(True) if "#" in link: link, name = link.split("#") self.blink_widget(name) ntbMore.set_current_page(int(link.split("/")[-1])) else: log.warning("Activated unknown link: %s", link)
def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.parser = GuiActionParser()
def on_cbTriggersAction_changed(self, cb): if self._recursing: return key = cb.get_model().get_value(cb.get_active_iter(), 1) l, r = key.split("|") profile = self._load_osk_profile() profile.triggers[LEFT] = GuiActionParser().restart(l).parse() profile.triggers[RIGHT] = GuiActionParser().restart(r).parse() self._save_osk_profile(profile)
def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.on_wayland = False self.circular = MouseAction(Rels.REL_WHEEL) self.parser = GuiActionParser()
def load_osk(self): cbStickAction = self.builder.get_object("cbStickAction") cbTriggersAction = self.builder.get_object("cbTriggersAction") profile = Profile(GuiActionParser()) profile.load(find_profile(OSDKeyboard.OSK_PROF_NAME)) self._recursing = True # Load triggers triggers = "%s|%s" % ( profile.triggers[LEFT].to_string(), profile.triggers[RIGHT].to_string() ) if not self.set_cb(cbTriggersAction, triggers, keyindex=1): self.add_custom(cbTriggersAction, triggers) # Load stick if not self.set_cb(cbStickAction, profile.stick.to_string(), keyindex=1): self.add_custom(cbStickAction, profile.stick.to_string()) # Load sensitivity s = profile.pads[LEFT].compress().speed self.builder.get_object("sclSensX").set_value(s[0]) self.builder.get_object("sclSensY").set_value(s[1]) self._recursing = False
def enable_osd_mode(self): # TODO: Support for multiple controllers here self.osd_mode_controller = 0 osd_mode_profile = Profile(GuiActionParser()) osd_mode_profile.load(find_profile(App.OSD_MODE_PROF_NAME)) try: c = self.dm.get_controllers()[self.osd_mode_controller] except IndexError: log.error("osd_mode: Controller not connected") self.quit() return def on_lock_failed(*a): log.error("osd_mode: Locking failed") self.quit() def on_lock_success(*a): log.debug("osd_mode: Locked everything") from scc.gui.osd_mode_mapper import OSDModeMapper self.osd_mode_mapper = OSDModeMapper(osd_mode_profile) self.osd_mode_mapper.set_target_window(self.window.get_window()) GLib.timeout_add(10, self.osd_mode_mapper.run_scheduled) # Locks everything but pads. Pads are emulating mouse and this is # better left in daemon - involving socket in mouse controls # adds too much lags. c.lock(on_lock_success, on_lock_failed, 'A', 'B', 'X', 'Y', 'START', 'BACK', 'LB', 'RB', 'C', 'LPAD', 'RPAD', 'STICK', 'LGRIP', 'RGRIP', 'LT', 'RT', 'STICKPRESS') # Ask daemon to temporaly reconfigure pads for mouse emulation c.replace(DaemonManager.nocallback, on_lock_failed, LEFT, osd_mode_profile.pads[LEFT]) c.replace(DaemonManager.nocallback, on_lock_failed, RIGHT, osd_mode_profile.pads[RIGHT])
def __init__(self, app): BindingEditor.__init__(self, app) self.app = app self.gladepath = app.gladepath self.imagepath = app.imagepath self.current = Profile(GuiActionParser()) self.current.load(find_profile(OSDKeyboard.OSK_PROF_NAME)) self.setup_widgets()
def _load_osk_profile(self): """ Loads and returns on-screen keyboard profile. Used by methods that are changing it. """ profile = Profile(GuiActionParser()) profile.load(find_profile(OSDKeyboard.OSK_PROF_NAME)) return profile
def load_profile(self, giofile): """ Loads profile from 'giofile' into 'profile' object Calls on_profiles_loaded when done """ # This may get asynchronous later, but that load runs under 1ms... profile = Profile(GuiActionParser()) profile.load(giofile.get_path()) self.on_profile_loaded(profile, giofile)
def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.on_wayland = False self.circular_axis = MouseAction(Rels.REL_WHEEL) self.circular_buttons = [ None, None ] self.button = None self.parser = GuiActionParser()
class CustomActionComponent(AEComponent): GLADE = "ae/custom.glade" NAME = "custom" PRIORITY = -1 CTXS = Action.AC_ALL def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser() def handles(self, mode, action): # Custom Action Editor handles all actions" return isinstance(action, Action) def get_button_title(self): return _("Custom Action") def load(self): if self.loaded : return AEComponent.load(self) try: txCustomAction = self.builder.get_object("txCustomAction") txCustomAction.set_monospace(True) except: pass def set_action(self, mode, action): action = self.editor.generate_modifiers(action) tbCustomAction = self.builder.get_object("tbCustomAction") tbCustomAction.set_text(action.to_string(True)) def on_tbCustomAction_changed(self, tbCustomAction, *a): """ Converts text from Custom Action text area into action instance and sends that instance back to editor. """ txCustomAction = self.builder.get_object("txCustomAction") txt = tbCustomAction.get_text(tbCustomAction.get_start_iter(), tbCustomAction.get_end_iter(), True) if len(txt.strip(" \t\r\n")) > 0: action = self.parser.restart(txt).parse() self.editor.set_action(action) def shown(self): self.editor.set_modifiers_enabled(False) def hidden(self): self.editor.set_modifiers_enabled(True)
def on_mnuPaste_activate(self, *a): """ Handler for 'Paste' context menu item. Reads string from clipboard, parses it as action and sets that action on selected input. """ clp = Gtk.Clipboard.get_default(Gdk.Display.get_default()) text = clp.wait_for_text() if text: a = GuiActionParser().restart(text.decode('utf-8')).parse() if not isinstance(a, InvalidAction): self.on_action_chosen(self.context_menu_for, a)
class CustomActionComponent(AEComponent): GLADE = "ae/custom.glade" NAME = "custom" PRIORITY = -1 CTXS = Action.AC_ALL def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser() def handles(self, mode, action): # Custom Action Editor handles all actions return isinstance(action, Action) def get_button_title(self): return _("Custom Action") def load(self): if self.loaded: return AEComponent.load(self) try: txCustomAction = self.builder.get_object("txCustomAction") txCustomAction.set_monospace(True) except: pass def set_action(self, mode, action): action = self.editor.generate_modifiers(action, from_custom=True) tbCustomAction = self.builder.get_object("tbCustomAction") tbCustomAction.set_text(action.to_string(True)) def on_tbCustomAction_changed(self, tbCustomAction, *a): """ Converts text from Custom Action text area into action instance and sends that instance back to editor. """ txCustomAction = self.builder.get_object("txCustomAction") txt = tbCustomAction.get_text(tbCustomAction.get_start_iter(), tbCustomAction.get_end_iter(), True) if len(txt.strip(" \t\r\n")) > 0: action = self.parser.restart(txt).parse() self.editor.set_action(action, from_custom=True) def shown(self): self.editor.set_modifiers_enabled(False) def hidden(self): self.editor.set_modifiers_enabled(True)
def load_autoswitch(self): """ Transfers autoswitch settings from config to UI """ tvItems = self.builder.get_object("tvItems") cbShowOSD = self.builder.get_object("cbShowOSD") model = tvItems.get_model() model.clear() for x in self.app.config['autoswitch']: o = GObject.GObject() o.condition = Condition.parse(x['condition']) o.action = GuiActionParser().restart(x["action"]).parse() a_str = o.action.describe(Action.AC_SWITCHER) model.append((o, o.condition.describe(), a_str)) self._recursing = True self.on_tvItems_cursor_changed() cbShowOSD.set_active(bool(self.app.config['autoswitch_osd'])) self._recursing = False
def import_scc(self, filename): """ Imports simple, single-file scc-profile. Just loads it, checks for shell() actions and asks user to enter name. """ files = self.builder.get_object("lstImportPackage") # Load profile profile = Profile(GuiActionParser()) try: profile.load(filename) except Exception, e: # Profile cannot be parsed. Display error message and let user to quit # Error message reuses page from VDF import, because they are # basically the same log.error(e) self.error(str(e)) return
def __init__(self, gladepath="/usr/share/scc", imagepath="/usr/share/scc/images"): Gtk.Application.__init__(self, application_id="me.kozec.scc", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE | Gio.ApplicationFlags.NON_UNIQUE ) UserDataManager.__init__(self) BindingEditor.__init__(self, self) # Setup Gtk.Application self.setup_commandline() # Setup DaemonManager self.dm = DaemonManager() self.dm.connect("alive", self.on_daemon_alive) self.dm.connect("controller-count-changed", self.on_daemon_ccunt_changed) self.dm.connect("dead", self.on_daemon_dead) self.dm.connect("error", self.on_daemon_error) self.dm.connect('reconfigured', self.on_daemon_reconfigured), self.dm.connect("version", self.on_daemon_version) # Set variables self.config = Config() self.gladepath = gladepath self.imagepath = imagepath self.builder = None self.recursing = False self.statusicon = None self.status = "unknown" self.context_menu_for = None self.daemon_changed_profile = False self.osd_mode = False # In OSD mode, only active profile can be editted self.osd_mode_mapper = None self.background = None self.outdated_version = None self.profile_switchers = [] self.current_file = None # Currently edited file self.controller_count = 0 self.current = Profile(GuiActionParser()) self.just_started = True self.button_widgets = {} self.hilights = { App.HILIGHT_COLOR : set(), App.OBSERVE_COLOR : set() } self.undo = [] self.redo = []
def import_scc_tar(self, filename): """ Imports packaged profiles. Checks for shell() actions everywhere and ask user to enter main name, check generated ones and optionaly change them as he wish. """ files = self.builder.get_object("lstImportPackage") try: # Open tar tar = tarfile.open(filename, "r:gz") files.clear() # Grab 1st profile name = tar.extractfile(Export.PN_NAME).read() main_profile = "%s.sccprofile" % name parser = GuiActionParser() o = GObject.GObject() o.obj = Profile(parser).load_fileobj(tar.extractfile(main_profile)) files.append((2, name, name, _("(profile)"), o)) for x in tar: name = ".".join(x.name.split(".")[0:-1]) if x.name.endswith(".sccprofile") and x.name != main_profile: o = GObject.GObject() o.obj = Profile(parser).load_fileobj(tar.extractfile(x)) files.append((True, name, name, _("(profile)"), o)) elif x.name.endswith(".menu"): o = GObject.GObject() o.obj = MenuData.from_fileobj(tar.extractfile(x), parser) files.append((True, name, name, _("(menu)"), o)) except Exception, e: # Either entire tar or some profile cannot be parsed. # Display error message and let user to quit # Error message reuses same page as above. log.error(e) self.error(str(e)) return
def on_cbMI_toggled(self, widget): """ Called when one of 'Default Menu Items' checkboxes is toggled. This actually does kind of magic: - 1st, default menu file is loaded - 2nd, based on widget name, option from DEFAULT_MENU_OPTIONS is selected - 3rd, if this option is not present in loaded menu and checkbox is toggled on, option is added - (same for option that is present while checkbox was toggled off) - 4rd, default menu is saved """ if self._recursing: return try: data = MenuData.from_fileobj(open(find_menu("Default.menu"), "r"), GuiActionParser()) index = int(widget.get_name().split("_")[-1]) instance = GlobalSettings._make_mi_instance(index) except Exception, e: log.error(traceback.format_exc()) self._recursing = True widget.set_active(not widget.get_active()) self._recursing = False return
def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser()
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO, PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger') ), (SCButtons.RT, _('Right Trigger') ), (SCButtons.LB, _('Left Bumper') ), (SCButtons.RB, _('Right Bumper') ), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched') ), (SCButtons.RPADTOUCH, _('Right Pad Touched') ), (SCButtons.LPAD, _('Left Pad Pressed') ), (SCButtons.RPAD, _('Right Pad Pressed') ), (None, None), (SCButtons.LGRIP, _('Left Grip') ), (SCButtons.RGRIP, _('Right Grip') ), (None, None), (SCButtons.A, _('A') ), (SCButtons.B, _('B') ), (SCButtons.X, _('X') ), (SCButtons.Y, _('Y') ), (None, None), (SCButtons.BACK, _('Back (select)') ), (SCButtons.C, _('Center') ), (SCButtons.START, _('Start') ), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(None) return if isinstance(action, ModeModifier): b = action.order[0] action = action.mods[b] self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, MouseAction): self.select_gyro_output("mouse") if len(action.parameters) >= 2 and action.parameters[1] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") self.select_yaw_roll(ROLL) elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") self.select_yaw_roll(ROLL) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods[action.order[0]] if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True if ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True return False if isinstance(action, MultiAction): return False return True def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, button): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") model = cb.get_model() self._recursing = True if button is not None: button = button.name for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def update(self, *a): pass def send(self, *a): if self._recursing : return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") cbGyroButton = self.builder.get_object("cbGyroButton") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) button = cbGyroButton.get_model().get_value(cbGyroButton.get_active_iter(), 0) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if button: action = ModeModifier(getattr(SCButtons, button), action) self.editor.set_action(action)
def on_cbStickAction_changed(self, cb): if self._recursing: return key = cb.get_model().get_value(cb.get_active_iter(), 1) profile = self._load_osk_profile() profile.stick = GuiActionParser().restart(key).parse() self._save_osk_profile(profile)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK, Action.AC_PAD, PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.parser = GuiActionParser() def load(self): if self.loaded: return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter: model.get_value(iter, 0) == "-") def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, TrackpadAction): self.set_cb(cb, "trackpad", 2) elif isinstance(action, TrackballAction): self.set_cb(cb, "trackball", 2) elif isinstance(action, CircularAction): self.set_cb(cb, "circular", 2) elif isinstance(action, XYAction): p = [None, None] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.set_cb(cb, "rstick", 2) elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: self.set_cb(cb, "dpad", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1: x1, x2 = x2, x1 if y2 < y1: y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active( self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False def on_ok(self, action): if isinstance(action.strip(), AreaAction): # Kinda hacky way to set action on LPAD press or RPAD press # when user selects Mouse Area as ouput and checks # 'Pressing the Pad Clicks' checkbox side = getattr(SCButtons, self.editor.get_id()) clicks = self.pressing_pad_clicks() if self.builder.get_object("cbAreaClickEnabled").get_active(): if not clicks: # Turn pad press into mouse clicks self.app.set_action(side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(side, NoAction()) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction, AreaAction)): return True if isinstance(action, XYAction): p = [None, None] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing: return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) def on_cbAxisOutput_changed(self, *a): cbAxisOutput = self.builder.get_object("cbAxisOutput") stActionData = self.builder.get_object("stActionData") key = cbAxisOutput.get_model().get_value( cbAxisOutput.get_active_iter(), 2) if key == 'area': stActionData.set_visible_child(self.builder.get_object("grArea")) action = self.make_area_action() self.update_osd_area(action) else: stActionData.set_visible_child(self.builder.get_object("nothing")) action = cbAxisOutput.get_model().get_value( cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.update_osd_area(None) self.editor.set_action(action)
def __init__(self): UserDataManager.__init__(self) self._current_menu = None self.parser = GuiActionParser() self.allow_globals = True self.allow_in_profile = True
class FirstPage(AEComponent): GLADE = "ae/first_page.glade" NAME = "first_page" CTXS = 0 PRIORITY = 999 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser() def load(self): if AEComponent.load(self): # Unlike mose region, gesutres kinda work with XWayland markup = "" if self.editor.get_mode() == Action.AC_PAD: markup = MARKUP_PAD elif self.editor.get_mode() == Action.AC_STICK: markup = MARKUP_STICK elif self.editor.get_mode() == Action.AC_GYRO: markup = MARKUP_GYRO elif self.editor.get_mode() == Action.AC_TRIGGER: markup = MARKUP_TRIGGER else: markup = MARKUP_BUTTON long_names = { 'LPAD': _("Left Pad"), 'RPAD': _("Right Pad"), 'LGRIP': _("Left Grip"), 'RGRIP': _("Right Grip"), 'LB': _("Left Bumper"), 'RB': _("Right Bumper"), 'LEFT': _("Left Trigger"), 'RIGHT': _("Right Trigger"), 'STICK': _("Stick"), } markup = markup % { 'what': long_names.get(nameof(self.editor.get_id()), nameof(self.editor.get_id()).title()) } self.builder.get_object("lblMarkup").set_markup( markup.strip(" \r\n\t")) return True def on_lblMarkup_activate_link(self, trash, link): if link.startswith("quick://"): action = self.parser.restart(link[8:]).parse() self.editor.reset_active_component() self.editor.set_action(action, from_custom=True) elif link == "grab://trigger_button": def cb(action): action = TriggerAction(254, 255, action) self.editor.set_action(action, from_custom=True) self.editor.force_page("trigger") b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.hide_axes() b.show(self.editor.window) elif link.startswith("page://"): def cb(): self.editor.force_page(link[7:]) GLib.timeout_add(0.1, cb)
class AxisActionComponent(AEComponent): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK, Action.AC_PAD, PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, TrackpadAction): self.select_axis_output("trackpad") elif isinstance(action, TrackballAction): self.select_axis_output("trackball") elif isinstance(action, CircularAction): self.select_axis_output("circular") elif isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.select_axis_output("lstick") elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.select_axis_output("rstick") elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: self.select_axis_output("dpad") elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.select_axis_output("wheel") else: self.select_axis_output("none") def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction)): return True if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def select_axis_output(self, key): """ Just sets combobox value """ model = self.builder.get_object("lstOutputMode") cb = self.builder.get_object("cbAxisOutput") self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def on_cbAxisOutput_changed(self, *a): if self._recursing : return cbAxisOutput = self.builder.get_object("cbAxisOutput") action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.editor.set_action(action)
def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self.parser = GuiActionParser()
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger') ), (SCButtons.RT, _('Right Trigger') ), (SCButtons.LB, _('Left Bumper') ), (SCButtons.RB, _('Right Bumper') ), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched') ), (SCButtons.RPADTOUCH, _('Right Pad Touched') ), (SCButtons.LPAD, _('Left Pad Pressed') ), (SCButtons.RPAD, _('Right Pad Pressed') ), (None, None), (SCButtons.LGRIP, _('Left Grip') ), (SCButtons.RGRIP, _('Right Grip') ), (STICK, _('Stick Tilted') ), (None, None), (SCButtons.A, _('A') ), (SCButtons.B, _('B') ), (SCButtons.X, _('X') ), (SCButtons.Y, _('Y') ), (None, None), (SCButtons.BACK, _('Back (select)') ), (SCButtons.C, _('Center') ), (SCButtons.START, _('Start') ), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(SCButtons.RPADTOUCH) return if isinstance(action, ModeModifier): self._recursing = True self.builder.get_object("cbInvertGyro").set_active(bool(action.default)) self._recursing = False b = action.mods.keys()[0] action = action.mods[b] or action.default self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, SensitivityModifier) and isinstance(action.action, MouseAction): # Mouse (Desktop) self.select_gyro_output("mouse") if len(action.action.parameters) > 0 and action.action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) self.editor.set_default_sensitivity(3.5, 3.5, 3.5) self.editor.set_sensitivity(*action.speeds) elif isinstance(action, MouseAction): # Mouse (Camera) self.select_gyro_output("mouse_cam") if len(action.parameters) > 0 and action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: self.select_gyro_output("mouse_stick") self.modifier_updated() def modifier_updated(self): cbInvertY = self.builder.get_object("cbInvertY") sens = self.editor.get_sensitivity() inverted = len(sens) >= 2 and sens[1] < 0 if cbInvertY.get_active() != inverted: self._recursing = True cbInvertY.set_active(inverted) self._recursing = False def cbInvertY_toggled_cb(self, cb, *a): if self._recursing: return sens = list(self.editor.get_sensitivity()) # Ensure that editor accepts Y sensitivity if len(sens) >= 2: sens[1] = abs(sens[1]) if cb.get_active(): # Ensure that Y sensitivity is negative sens[1] *= -1 self.editor.set_sensitivity(*sens) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods.values()[0] or action.default if isinstance(action, SensitivityModifier): action = action.action if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: return True return False if isinstance(action, (MouseAction, MouseAbsAction)): return True return False def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, item): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") rvSoftLevel = self.builder.get_object("rvSoftLevel") sclSoftLevel = self.builder.get_object("sclSoftLevel") model = cb.get_model() self._recursing = True button = None if isinstance(item, RangeOP): button = nameof(item.what) sclSoftLevel.set_value(item.value) rvSoftLevel.set_reveal_child(True) elif item is not None: button = nameof(item.name) for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def on_cbInvertGyro_toggled(self, cb, *a): lblGyroEnable = self.builder.get_object("lblGyroEnable") if cb.get_active(): lblGyroEnable.set_label(_("Gyro Disable Button")) else: lblGyroEnable.set_label(_("Gyro Enable Button")) if not self._recursing: self.send() def on_sclSoftLevel_format_value(self, scale, value): return "%s%%" % (int(value * 100.0),) def update(self, *a): pass def hidden(self): self.editor.set_default_sensitivity(1, 1, 1) def send(self, *a): if self._recursing : return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") rvSoftLevel = self.builder.get_object("rvSoftLevel") sclSoftLevel = self.builder.get_object("sclSoftLevel") cbGyroButton = self.builder.get_object("cbGyroButton") cbInvertGyro = self.builder.get_object("cbInvertGyro") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) key = cbMode.get_model().get_value(cbMode.get_active_iter(), 2) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) item = cbGyroButton.get_model().get_value(cbGyroButton.get_active_iter(), 0) rvSoftLevel.set_reveal_child(item in TRIGGERS) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if item and action: if item in TRIGGERS: what = RangeOP(getattr(SCButtons, item), ">=", sclSoftLevel.get_value()) elif item == STICK: what = RangeOP(item, ">=", sclSoftLevel.get_value()) else: what = getattr(SCButtons, item) if cbInvertGyro.get_active(): action = ModeModifier(what, NoAction(), action) else: action = ModeModifier(what, action) if key == "mouse": self.editor.set_default_sensitivity(3.5, 3.5, 3.5) else: self.editor.set_default_sensitivity(1, 1, 1) self.editor.set_action(action)
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger')), (SCButtons.RT, _('Right Trigger')), (SCButtons.LB, _('Left Bumper')), (SCButtons.RB, _('Right Bumper')), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched')), (SCButtons.RPADTOUCH, _('Right Pad Touched')), (SCButtons.LPAD, _('Left Pad Pressed')), (SCButtons.RPAD, _('Right Pad Pressed')), (None, None), (SCButtons.LGRIP, _('Left Grip')), (SCButtons.RGRIP, _('Right Grip')), (None, None), (SCButtons.A, _('A')), (SCButtons.B, _('B')), (SCButtons.X, _('X')), (SCButtons.Y, _('Y')), (None, None), (SCButtons.BACK, _('Back (select)')), (SCButtons.C, _('Center')), (SCButtons.START, _('Start')), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded: return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(SCButtons.RPADTOUCH) return if isinstance(action, ModeModifier): self._recursing = True self.builder.get_object("cbInvertGyro").set_active( bool(action.default)) self._recursing = False b = action.order[0] action = action.mods[b] or action.default self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, SensitivityModifier) and isinstance( action.action, MouseAction): # Mouse (Desktop) self.select_gyro_output("mouse") if len(action.action.parameters ) > 0 and action.action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) self.editor.set_default_sensitivity(3.5, 3.5, 3.5) self.editor.set_sensitivity(*action.speeds) elif isinstance(action, MouseAction): # Mouse (Camera) self.select_gyro_output("mouse_cam") if len(action.parameters) > 0 and action.parameters[0] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: self.select_gyro_output("mouse_stick") self.modifier_updated() def modifier_updated(self): cbInvertY = self.builder.get_object("cbInvertY") sens = self.editor.get_sensitivity() inverted = len(sens) >= 2 and sens[1] < 0 if cbInvertY.get_active() != inverted: self._recursing = True cbInvertY.set_active(inverted) self._recursing = False def cbInvertY_toggled_cb(self, cb, *a): if self._recursing: return sens = list(self.editor.get_sensitivity()) # Ensure that editor accepts Y sensitivity if len(sens) >= 2: sens[1] = abs(sens[1]) if cb.get_active(): # Ensure that Y sensitivity is negative sens[1] *= -1 self.editor.set_sensitivity(*sens) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods[action.order[0]] or action.default if isinstance(action, SensitivityModifier): action = action.action if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True elif ap[0] == Rels.REL_Y and ap[-1] == Rels.REL_X: return True return False if isinstance(action, (MouseAction, MouseAbsAction)): return True return False def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, button): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") model = cb.get_model() self._recursing = True if button is not None: button = button.name for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def on_cbInvertGyro_toggled(self, cb, *a): lblGyroEnable = self.builder.get_object("lblGyroEnable") if cb.get_active(): lblGyroEnable.set_label(_("Gyro Disable Button")) else: lblGyroEnable.set_label(_("Gyro Enable Button")) if not self._recursing: self.send() def update(self, *a): pass def hidden(self): self.editor.set_default_sensitivity(1, 1, 1) def send(self, *a): if self._recursing: return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") cbGyroButton = self.builder.get_object("cbGyroButton") cbInvertGyro = self.builder.get_object("cbInvertGyro") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) key = cbMode.get_model().get_value(cbMode.get_active_iter(), 2) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) button = cbGyroButton.get_model().get_value( cbGyroButton.get_active_iter(), 0) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if button and action: if cbInvertGyro.get_active(): action = ModeModifier(getattr(SCButtons, button), NoAction(), action) else: action = ModeModifier(getattr(SCButtons, button), action) if key == "mouse": self.editor.set_default_sensitivity(3.5, 3.5, 3.5) else: self.editor.set_default_sensitivity(1, 1, 1) self.editor.set_action(action)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK, Action.AC_PAD, PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" ) def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, TrackpadAction): self.set_cb(cb, "trackpad", 2) elif isinstance(action, TrackballAction): self.set_cb(cb, "trackball", 2) elif isinstance(action, CircularAction): self.set_cb(cb, "circular", 2) elif isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.set_cb(cb, "rstick", 2) elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: self.set_cb(cb, "dpad", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1 : x1, x2 = x2, x1 if y2 < y1 : y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False def on_ok(self, action): if isinstance(action.strip(), AreaAction): # Kinda hacky way to set action on LPAD press or RPAD press # when user selects Mouse Area as ouput and checks # 'Pressing the Pad Clicks' checkbox side = getattr(SCButtons, self.editor.get_id()) clicks = self.pressing_pad_clicks() if self.builder.get_object("cbAreaClickEnabled").get_active(): if not clicks: # Turn pad press into mouse clicks self.app.set_action(side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(side, NoAction()) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, TrackballAction, CircularAction, InvalidAction, AreaAction)): return True if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing : return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) def on_cbAxisOutput_changed(self, *a): cbAxisOutput = self.builder.get_object("cbAxisOutput") stActionData = self.builder.get_object("stActionData") key = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 2) if key == 'area': stActionData.set_visible_child(self.builder.get_object("grArea")) action = self.make_area_action() self.update_osd_area(action) else: stActionData.set_visible_child(self.builder.get_object("nothing")) action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.update_osd_area(None) self.editor.set_action(action)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK | Action.AC_PAD PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.on_wayland = False self.circular = MouseAction(Rels.REL_WHEEL) self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" ) self.on_wayland = "WAYLAND_DISPLAY" in os.environ or not isinstance(Gdk.Display.get_default(), GdkX11.X11Display) if self.on_wayland: self.builder.get_object("lblArea").set_text(_("Note: Mouse Region option is not available with Wayland-based display server")) self.builder.get_object("grArea").set_sensitive(False) # Remove options that are not applicable to currently editted input if self.editor.get_id() in STICKS: # Remove "Mouse Region", "Trackball", "Trackpad" # and "Mouse (Emulate Stick)" options when editing stick bindings cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_pad", "area", "mouse_pad", "trackpad", "trackball"): cb.get_model().remove(row.iter) else: # Remove "Mouse" option when editing pads # (it's effectivelly same as Trackpad) cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_stick", "mouse_stick", ): cb.get_model().remove(row.iter) def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, MouseAction): self.set_cb(cb, "trackpad", 2) elif isinstance(action, BallModifier): self.load_trackball_action(action) elif isinstance(action, CircularModifier): self.load_circular_action(action) elif isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: self.set_cb(cb, "rstick", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: if self.on_wayland: # Cannot display preview with non-X11 backends return self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_circular_action(self, action): self.circular = action.action cbAxisOutput = self.builder.get_object("cbAxisOutput") btCircularAxis = self.builder.get_object("btCircularAxis") btCircularAxis.set_label(self.circular.describe(Action.AC_PAD)) self.set_cb(cbAxisOutput, "circular", 2) def load_trackball_action(self, action): cbTracballOutput = self.builder.get_object("cbTracballOutput") cbAxisOutput = self.builder.get_object("cbAxisOutput") sclFriction = self.builder.get_object("sclFriction") self._recursing = True if isinstance(action.action, MouseAction): self.set_cb(cbTracballOutput, "mouse", 1) self.set_cb(cbAxisOutput, "trackball", 2) elif isinstance(action.action, XYAction): if isinstance(action.action.x, AxisAction): if action.action.x.parameters[0] == Axes.ABS_X: self.set_cb(cbTracballOutput, "left", 1) else: self.set_cb(cbTracballOutput, "right", 1) self.set_cb(cbAxisOutput, "trackball", 2) elif isinstance(action.action.x, MouseAction): self.set_cb(cbAxisOutput, "wheel", 2) if action.friction <= 0: sclFriction.set_value(0) else: sclFriction.set_value(math.log(action.friction * 1000.0, 10)) self._recursing = False def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1 : x1, x2 = x2, x1 if y2 < y1 : y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_btCircularAxis_clicked(self, *a): def cb(action): self.circular = action btCircularAxis = self.builder.get_object("btCircularAxis") btCircularAxis.set_label(action.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) b = SimpleChooser(self.app, "axis", cb) b.set_title(_("Select Axis")) b.display_action(Action.AC_STICK, self.circular) b.show(self.editor.window) def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False def on_ok(self, action): if isinstance(action.strip(), AreaAction): # Kinda hacky way to set action on LPAD press or RPAD press # when user selects Mouse Area as ouput and checks # 'Pressing the Pad Clicks' checkbox side = getattr(SCButtons, self.editor.get_id()) clicks = self.pressing_pad_clicks() if self.builder.get_object("cbAreaClickEnabled").get_active(): if not clicks: # Turn pad press into mouse clicks self.app.set_action(self.app.current, side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(self.app.current, side, NoAction()) def make_trackball_action(self): """ Loads values from UI into trackball-related action """ sclFriction = self.builder.get_object("sclFriction") cbTracballOutput = self.builder.get_object("cbTracballOutput") a_str = cbTracballOutput.get_model().get_value(cbTracballOutput.get_active_iter(), 2) a = self.parser.restart(a_str).parse() if sclFriction.get_value() <= 0: friction = 0 else: friction = ((10.0**sclFriction.get_value())/1000.0) return BallModifier(round(friction, 3), a) def make_circular_action(self): """ Constructs Circular Modifier """ return CircularModifier(self.circular) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick / Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, MouseAction, CircularModifier, InvalidAction, AreaAction)): return True if isinstance(action, BallModifier): if isinstance(action.action, XYAction): return ( isinstance(action.action.x, (AxisAction, MouseAction)) and isinstance(action.action.x, (AxisAction, MouseAction)) ) return isinstance(action.action, MouseAction) if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing : return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_trackball_options_changed(self, *a): if self._recursing : return action = self.make_trackball_action() self.editor.set_action(action) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) def on_btClearFriction_clicked(self, *a): sclFriction = self.builder.get_object("sclFriction") sclFriction.set_value(math.log(10 * 1000.0, 10)) def on_sclFriction_format_value(self, scale, value): if value <= 0: return "0.000" elif value >= 6: return "1000.00" else: return "%0.3f" % ((10.0**value)/1000.0) def on_cbAxisOutput_changed(self, *a): cbAxisOutput = self.builder.get_object("cbAxisOutput") stActionData = self.builder.get_object("stActionData") key = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 2) if key == 'area': stActionData.set_visible_child(self.builder.get_object("grArea")) action = self.make_area_action() self.update_osd_area(action) elif key == "circular": stActionData.set_visible_child(self.builder.get_object("vbCircular")) action = self.make_circular_action() elif key == 'trackball': stActionData.set_visible_child(self.builder.get_object("vbTrackball")) action = self.make_trackball_action() else: stActionData.set_visible_child(self.builder.get_object("nothing")) action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.update_osd_area(None) self.editor.set_action(action)
class GyroActionComponent(AEComponent): GLADE = "ae/gyro_action.glade" NAME = "gyro_action" CTXS = Action.AC_GYRO, PRIORITY = 3 BUTTONS = ( # in order as displayed in combobox (None, _('Always Active')), (None, None), (SCButtons.LT, _('Left Trigger')), (SCButtons.RT, _('Right Trigger')), (SCButtons.LB, _('Left Bumper')), (SCButtons.RB, _('Right Bumper')), (None, None), (SCButtons.LPADTOUCH, _('Left Pad Touched')), (SCButtons.RPADTOUCH, _('Right Pad Touched')), (SCButtons.LPAD, _('Left Pad Pressed')), (SCButtons.RPAD, _('Right Pad Pressed')), (None, None), (SCButtons.LGRIP, _('Left Grip')), (SCButtons.RGRIP, _('Right Grip')), (None, None), (SCButtons.A, _('A')), (SCButtons.B, _('B')), (SCButtons.X, _('X')), (SCButtons.Y, _('Y')), (None, None), (SCButtons.BACK, _('Back (select)')), (SCButtons.C, _('Center')), (SCButtons.START, _('Start')), ) def __init__(self, app, editor): AEComponent.__init__(self, app, editor) self._recursing = False self.parser = GuiActionParser() def load(self): if self.loaded: return AEComponent.load(self) self._recursing = True cbGyroButton = self.builder.get_object("cbGyroButton") fill_buttons(cbGyroButton) self._recursing = False def set_action(self, mode, action): if self.handles(mode, action): if isinstance(action, NoAction): self.select_gyro_output("none") self.select_gyro_button(None) return if isinstance(action, ModeModifier): b = action.order[0] action = action.mods[b] self.select_gyro_button(b) else: self.select_gyro_button(None) if isinstance(action, MouseAction): self.select_gyro_output("mouse") if len(action.parameters) >= 2 and action.parameters[1] == YAW: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) elif isinstance(action, GyroAction): ap = action.parameters if len(ap) == 2: self.select_yaw_roll(YAW) else: self.select_yaw_roll(ROLL) if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: if isinstance(action, GyroAbsAction): self.select_gyro_output("left_abs") else: self.select_gyro_output("left") self.select_yaw_roll(ROLL) elif ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: if isinstance(action, GyroAbsAction): self.select_gyro_output("right_abs") else: self.select_gyro_output("right") self.select_yaw_roll(ROLL) def get_button_title(self): return _("Joystick or Mouse") def handles(self, mode, action): if isinstance(action, NoAction): return True if is_gyro_enable(action): action = action.mods[action.order[0]] if isinstance(action, GyroAction): # Takes GyroAbsAction as well ap = action.parameters if (len(ap) == 3 and not ap[1]) or len(ap) == 2: if ap[0] == Axes.ABS_X and ap[-1] == Axes.ABS_Y: return True if ap[0] == Axes.ABS_RX and ap[-1] == Axes.ABS_RY: return True return False if isinstance(action, MultiAction): return False return True def select_gyro_output(self, key): """ Just sets combobox value """ cb = self.builder.get_object("cbMode") model = cb.get_model() self._recursing = True for row in model: if key == row[2]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_yaw_roll(self, yawroll): """ Just sets combobox value """ cb = self.builder.get_object("cbYawRoll") model = cb.get_model() self._recursing = True for row in model: if yawroll == row[0]: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def select_gyro_button(self, button): """ Just sets combobox value """ cb = self.builder.get_object("cbGyroButton") model = cb.get_model() self._recursing = True if button is not None: button = button.name for row in model: if button == row[0] and row[1] != None: cb.set_active_iter(row.iter) self._recursing = False return self._recursing = False def update(self, *a): pass def send(self, *a): if self._recursing: return cbMode = self.builder.get_object("cbMode") cbYawRoll = self.builder.get_object("cbYawRoll") cbGyroButton = self.builder.get_object("cbGyroButton") action = cbMode.get_model().get_value(cbMode.get_active_iter(), 0) yawroll = cbYawRoll.get_model().get_value(cbYawRoll.get_active_iter(), 0) button = cbGyroButton.get_model().get_value( cbGyroButton.get_active_iter(), 0) match = re.match(r"([^\[]+)\[([^\|]+)\|([^\]]+)\](.*)", action) if match: grps = match.groups() if yawroll == YAW: action = "%s%s%s" % (grps[0], grps[1], grps[3]) else: action = "%s%s%s" % (grps[0], grps[2], grps[3]) action = self.parser.restart(action).parse() if button: action = ModeModifier(getattr(SCButtons, button), action) self.editor.set_action(action)
class AxisActionComponent(AEComponent, TimerManager): GLADE = "ae/axis_action.glade" NAME = "axis_action" CTXS = Action.AC_STICK | Action.AC_PAD PRIORITY = 3 def __init__(self, app, editor): AEComponent.__init__(self, app, editor) TimerManager.__init__(self) self._recursing = False self.relative_area = False self.osd_area_instance = None self.on_wayland = False self.circular_axis = MouseAction(Rels.REL_WHEEL) self.circular_buttons = [ None, None ] self.button = None self.parser = GuiActionParser() def load(self): if self.loaded : return AEComponent.load(self) cbAreaType = self.builder.get_object("cbAreaType") cbAreaType.set_row_separator_func( lambda model, iter : model.get_value(iter, 0) == "-" ) self.on_wayland = "WAYLAND_DISPLAY" in os.environ or not isinstance(Gdk.Display.get_default(), GdkX11.X11Display) if self.on_wayland: self.builder.get_object("lblArea").set_text(_("Note: Mouse Region option is not available with Wayland-based display server")) self.builder.get_object("grArea").set_sensitive(False) # Remove options that are not applicable to currently editted input if self.editor.get_id() in STICKS: # Remove "Mouse Region", "Mouse" and "Mouse (Emulate Stick)" options # when editing stick bindings cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_pad", "area", "mouse", "mouse_pad"): cb.get_model().remove(row.iter) else: # Remove "Mouse" option when editing pads # (it's effectivelly same as Trackpad) cb = self.builder.get_object("cbAxisOutput") for row in cb.get_model(): if row[2] in ("wheel_stick", "mouse_stick"): cb.get_model().remove(row.iter) def hidden(self): self.update_osd_area(None) def set_action(self, mode, action): if self.handles(mode, action): cb = self.builder.get_object("cbAxisOutput") if isinstance(action, AreaAction): self.load_area_action(action) self.set_cb(cb, "area", 2) self.update_osd_area(action) return self.update_osd_area(None) if isinstance(action, MouseAction): self.load_mouse_action(action) elif isinstance(action, CircularModifier): self.load_circular_action(action) elif isinstance(action, ButtonAction): self.load_button_action(action) elif isinstance(action, XYAction): if self.editor.friction > 0: self.load_mouse_action(action) else: p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: self.set_cb(cb, "lstick", 2) elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: if isinstance(action, RelXYAction): self.set_cb(cb, "rstick_rel", 2) else: self.set_cb(cb, "rstick", 2) elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: self.set_cb(cb, "wheel_pad", 2) self.set_cb(cb, "wheel_stick", 2) else: self.set_cb(cb, "none", 2) def update_osd_area(self, action): """ Updates preview area displayed on screen """ if action: if self.osd_area_instance is None: if self.on_wayland: # Cannot display preview with non-X11 backends return self.osd_area_instance = Area() self.osd_area_instance.show() action.update_osd_area(self.osd_area_instance, FakeMapper(self.editor)) self.timer("area", 0.5, self.update_osd_area, action) elif self.osd_area_instance: self.osd_area_instance.quit() self.osd_area_instance = None self.cancel_timer("area") def load_circular_action(self, action): cbAxisOutput = self.builder.get_object("cbAxisOutput") btCircularAxis = self.builder.get_object("btCircularAxis") btCircularButton0 = self.builder.get_object("btCircularButton0") btCircularButton1 = self.builder.get_object("btCircularButton1") # Turn action into list of subactions (even if it's just single action) if isinstance(action.action, MultiAction): actions = action.action.actions else: actions = [ action.action ] # Parse that list self.circular_axis, self.circular_buttons = NoAction(), [ None, None ] for action in actions: if isinstance(action, ButtonAction): self.circular_buttons = [ action.button, action.button2 ] else: self.circular_axis = action # Set labels b0, b1 = self.circular_buttons btCircularButton0.set_label(ButtonAction.describe_button(b0)) btCircularButton1.set_label(ButtonAction.describe_button(b1)) btCircularAxis.set_label(self.circular_axis.describe(Action.AC_PAD)) self.set_cb(cbAxisOutput, "circular", 2) def load_button_action(self, action): self.button = action cbAxisOutput = self.builder.get_object("cbAxisOutput") btSingleButton = self.builder.get_object("btSingleButton") btSingleButton.set_label(self.button.describe(Action.AC_PAD)) self.set_cb(cbAxisOutput, "button", 2) def load_mouse_action(self, action): cbMouseOutput = self.builder.get_object("cbMouseOutput") cbAxisOutput = self.builder.get_object("cbAxisOutput") self._recursing = True if isinstance(action, MouseAction): self.set_cb(cbMouseOutput, "mouse", 1) self.set_cb(cbAxisOutput, "mouse", 2) elif isinstance(action, XYAction): if isinstance(action.x, AxisAction): if action.x.parameters[0] == Axes.ABS_X: self.set_cb(cbMouseOutput, "left", 1) else: self.set_cb(cbMouseOutput, "right", 1) self.set_cb(cbAxisOutput, "mouse", 2) elif isinstance(action.x, MouseAction): if self.editor.get_id() in STICKS: self.set_cb(cbAxisOutput, "wheel_stick", 2) else: self.set_cb(cbAxisOutput, "wheel_pad", 2) self._recursing = False def load_area_action(self, action): """ Load AreaAction values into UI. """ cbAreaType = self.builder.get_object("cbAreaType") x1, y1, x2, y2 = action.coords self.relative_area = False if isinstance(action, RelAreaAction): key = "screensize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 elif isinstance(action, RelWinAreaAction): key = "windowsize" self.relative_area = True x1, y1, x2, y2 = x1 * 100.0, y1 * 100.0, x2 * 100.0, y2 * 100.0 else: t1 = "1" if x1 < 0 and x2 < 0 else "0" t2 = "1" if y1 < 0 and y2 < 0 else "0" x1, y1, x2, y2 = abs(x1), abs(y1), abs(x2), abs(y2) if x2 < x1 : x1, x2 = x2, x1 if y2 < y1 : y1, y2 = y2, y1 if isinstance(action, WinAreaAction): key = "window-%s%s" % (t1, t2) else: key = "screen-%s%s" % (t1, t2) self._recursing = True self.builder.get_object("sbAreaX1").set_value(x1) self.builder.get_object("sbAreaY1").set_value(y1) self.builder.get_object("sbAreaX2").set_value(x2) self.builder.get_object("sbAreaY2").set_value(y2) self.builder.get_object("cbAreaOSDEnabled").set_active(self.editor.osd) self.builder.get_object("cbAreaClickEnabled").set_active(self.pressing_pad_clicks()) for row in cbAreaType.get_model(): if key == row[1]: cbAreaType.set_active_iter(row.iter) break self._recursing = False def on_btCircularAxis_clicked(self, *a): def cb(action): self.circular_axis = action btCircularAxis = self.builder.get_object("btCircularAxis") btCircularAxis.set_label(action.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) b = SimpleChooser(self.app, "axis", cb) b.set_title(_("Select Axis")) b.display_action(Action.AC_STICK, self.circular_axis) b.show(self.editor.window) def on_btCircularButton_clicked(self, button, *a): index = 0 if button == self.builder.get_object("btCircularButton0") else 1 def cb(action): self.circular_buttons[index] = action.button btCircularButton = self.builder.get_object("btCircularButton%s" % (index, )) btCircularButton.set_label(action.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.display_action(Action.AC_STICK, self.circular_axis) b.show(self.editor.window) def on_btClearCircularAxis_clicked(self, *a): btCircularAxis = self.builder.get_object("btCircularAxis") self.circular_axis = NoAction() btCircularAxis.set_label(self.circular_axis.describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) def on_btClearCircularButtons_clicked(self, *a): btCircularButton0 = self.builder.get_object("btCircularButton0") btCircularButton1 = self.builder.get_object("btCircularButton1") self.circular_buttons = [ None, None ] btCircularButton0.set_label(NoAction().describe(Action.AC_PAD)) btCircularButton1.set_label(NoAction().describe(Action.AC_PAD)) self.editor.set_action(self.make_circular_action()) def on_btSingleButton_clicked(self, *a): def cb(action): self.button = action btSingleButton = self.builder.get_object("btSingleButton") btSingleButton.set_label(self.button.describe(Action.AC_PAD)) self.editor.set_action(self.button) b = SimpleChooser(self.app, "buttons", cb) b.set_title(_("Select Button")) b.display_action(Action.AC_STICK, self.circular_axis) b.show(self.editor.window) def on_cbAreaOSDEnabled_toggled(self, *a): self.editor.builder.get_object("cbOSD").set_active( self.builder.get_object("cbAreaOSDEnabled").get_active()) def pressing_pad_clicks(self): """ Returns True if currently edited pad is set to press left mouse button when pressed. (yes, this is used somewhere) """ side = getattr(SCButtons, self.editor.get_id()) c_action = self.app.current.buttons[side] if isinstance(c_action, ButtonAction): return c_action.button == Keys.BTN_LEFT return False def on_ok(self, action): if isinstance(action.strip(), AreaAction): # Kinda hacky way to set action on LPAD press or RPAD press # when user selects Mouse Area as ouput and checks # 'Pressing the Pad Clicks' checkbox side = getattr(SCButtons, self.editor.get_id()) clicks = self.pressing_pad_clicks() if self.builder.get_object("cbAreaClickEnabled").get_active(): if not clicks: # Turn pad press into mouse clicks self.app.set_action(self.app.current, side, ButtonAction(Keys.BTN_LEFT)) else: if clicks: # Clear action created above if checkbox is uncheck self.app.set_action(self.app.current, side, NoAction()) def on_mouse_options_changed(self, *a): if self._recursing : return action = self.make_mouse_action() self.editor.set_action(action) def make_mouse_action(self): """ Loads values from UI into trackball-related action """ cbMouseOutput = self.builder.get_object("cbMouseOutput") a_str = cbMouseOutput.get_model().get_value(cbMouseOutput.get_active_iter(), 2) return self.parser.restart(a_str).parse() def make_circular_action(self): """ Constructs Circular Modifier """ if self.circular_axis and any(self.circular_buttons): return CircularModifier(MultiAction( self.circular_axis, ButtonAction(*self.circular_buttons))) elif any(self.circular_buttons): return CircularModifier(ButtonAction(*self.circular_buttons)) else: return CircularModifier(self.circular_axis) def make_area_action(self): """ Loads values from UI into new AreaAction or subclass. """ # Prepare cbAreaType = self.builder.get_object("cbAreaType") # Read numbers x1 = self.builder.get_object("sbAreaX1").get_value() y1 = self.builder.get_object("sbAreaY1").get_value() x2 = self.builder.get_object("sbAreaX2").get_value() y2 = self.builder.get_object("sbAreaY2").get_value() # Determine exact action type by looking into Area Type checkbox # (this part may seem little crazy) # ... numbers key = cbAreaType.get_model().get_value(cbAreaType.get_active_iter(), 1) if "-" in key: if key[-2] == "1": # Before-last character ius "1", that means that X coords are # counted from other side and has to be negated x1, x2 = -x1, -x2 if key[-1] == "1": # Key ends with "1". Same thing as above but for Y coordinate y1, y2 = -y1, -y2 if "size" in key: x1, y1, x2, y2 = x1 / 100.0, y1 / 100.0, x2 / 100.0, y2 / 100.0 # ... class if "window-" in key: cls = WinAreaAction self.relative_area = False elif "screensize" == key: cls = RelAreaAction self.relative_area = True elif "windowsize" == key: cls = RelWinAreaAction self.relative_area = True else: # "screen" in key cls = AreaAction self.relative_area = False if not self.relative_area: x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) return cls(x1, y1, x2, y2) def get_button_title(self): return _("Joystick / Mouse") def handles(self, mode, action): if isinstance(action, (NoAction, MouseAction, CircularModifier, InvalidAction, AreaAction, ButtonAction)): return True if isinstance(action, BallModifier): if isinstance(action.action, XYAction): return ( isinstance(action.action.x, (AxisAction, MouseAction)) and isinstance(action.action.x, (AxisAction, MouseAction)) ) return isinstance(action.action, MouseAction) if isinstance(action, XYAction): p = [ None, None ] for x in (0, 1): if len(action.actions[0].strip().parameters) >= x: if len(action.actions[x].strip().parameters) > 0: p[x] = action.actions[x].strip().parameters[0] if p[0] == Axes.ABS_X and p[1] == Axes.ABS_Y: return True elif p[0] == Axes.ABS_RX and p[1] == Axes.ABS_RY: return True elif p[0] == Axes.ABS_HAT0X and p[1] == Axes.ABS_HAT0Y: return True elif p[0] == Rels.REL_HWHEEL and p[1] == Rels.REL_WHEEL: return True return False def on_area_options_changed(self, *a): if self._recursing : return action = self.make_area_action() self.editor.set_action(action) self.update_osd_area(action) for x in ('sbAreaX1', 'sbAreaX2', 'sbAreaY1', 'sbAreaY2'): spin = self.builder.get_object(x) if self.relative_area: spin.get_adjustment().set_upper(100) else: spin.get_adjustment().set_upper(1000) self.on_sbArea_output(spin) def on_sbArea_output(self, button, *a): if self.relative_area: button.set_text("%s %%" % (button.get_value())) else: button.set_text("%s px" % (int(button.get_value()))) def on_sbArea_focus_out_event(self, button, *a): GLib.idle_add(self.on_sbArea_output, button) def on_sbArea_changed(self, button, *a): self.on_sbArea_output(button) self.on_area_options_changed(button) def on_lblSetupTrackball_activate_link(self, trash, link): self.editor.on_link(link) def on_cbAxisOutput_changed(self, *a): cbAxisOutput = self.builder.get_object("cbAxisOutput") stActionData = self.builder.get_object("stActionData") key = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 2) if key == 'area': stActionData.set_visible_child(self.builder.get_object("grArea")) action = self.make_area_action() self.update_osd_area(action) elif key == "button": stActionData.set_visible_child(self.builder.get_object("vbButton")) self.button = self.button or ButtonAction(Keys.BTN_GAMEPAD) action = self.button elif key == "circular": stActionData.set_visible_child(self.builder.get_object("grCircular")) action = self.make_circular_action() elif key == 'mouse': stActionData.set_visible_child(self.builder.get_object("vbMose")) if self.editor.friction == 0: # When switching to mouse, enable trackball by default self.editor.friction = 10 action = self.make_mouse_action() else: stActionData.set_visible_child(self.builder.get_object("nothing")) action = cbAxisOutput.get_model().get_value(cbAxisOutput.get_active_iter(), 0) action = self.parser.restart(action).parse() self.update_osd_area(None) self.editor.set_action(action)
def on_cbActionType_changed(self, *a): cbActionType = self.builder.get_object("cbActionType") key = cbActionType.get_model().get_value( cbActionType.get_active_iter(), 0) self.editor.set_action(GuiActionParser().restart(key).parse())