Add ButtonsPage to configure buttons

This commit adds the initial buttons page and a skeleton configuration
dialog to configure button mappings.
This commit is contained in:
Jente Hidskes
2017-07-17 10:23:30 +02:00
committed by Peter Hutterer
parent b08d45550b
commit 96a77f024b
5 changed files with 307 additions and 2 deletions

View File

@@ -4,6 +4,7 @@
<file>404.svg</file>
<file preprocess="xml-stripblanks">AboutDialog.ui</file>
<file preprocess="xml-stripblanks">ui/ButtonDialog.ui</file>
<file preprocess="xml-stripblanks">ui/LedDialog.ui</file>
<file preprocess="xml-stripblanks">ui/OptionButton.ui</file>
<file preprocess="xml-stripblanks">ui/ResolutionRow.ui</file>

163
data/ui/ButtonDialog.ui Normal file
View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="ButtonDialog" parent="GtkDialog">
<property name="width_request">400</property>
<property name="height_request">300</property>
<property name="can_focus">False</property>
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-left-right</property>
<child>
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">button</property>
<property name="title" translatable="yes">Button Mapping</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">key</property>
<property name="title" translatable="yes">Key Mapping</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">special</property>
<property name="title" translatable="yes">Key Sequence</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">macro</property>
<property name="title" translatable="yes">Custom</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="cancel">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Ignore any changes made</property>
</object>
</child>
<child type="title">
<object class="GtkStackSwitcher">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stack">stack</property>
</object>
</child>
<child>
<object class="GtkButton" id="apply">
<property name="label" translatable="yes">Apply</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Apply any changes made</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="cancel">cancel</action-widget>
<action-widget response="apply" default="true">apply</action-widget>
</action-widgets>
</template>
</interface>

62
piper/buttondialog.py Normal file
View File

@@ -0,0 +1,62 @@
# Copyright (C) 2017 Jente Hidskes <hjdskes@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from .gi_composites import GtkTemplate
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GObject, Gtk
@GtkTemplate(ui="/org/freedesktop/Piper/ui/ButtonDialog.ui")
class ButtonDialog(Gtk.Dialog):
"""A Gtk.Dialog subclass to implement the dialog that shows the
configuration options for button mappings."""
__gtype_name__ = "ButtonDialog"
_BUTTON_TYPE_TO_PAGE = {
RatbagdButton.ACTION_TYPE_BUTTON: "mapping",
RatbagdButton.ACTION_TYPE_SPECIAL: "special",
RatbagdButton.ACTION_TYPE_KEY: "mapping",
RatbagdButton.ACTION_TYPE_MACRO: "macro",
}
stack = GtkTemplate.Child()
def __init__(self, ratbagd_button, *args, **kwargs):
"""Instantiates a new ButtonDialog.
@param ratbagd_button The button to configure, as ratbagd.RatbagdButton.
"""
Gtk.Dialog.__init__(self, *args, **kwargs)
self.init_template()
self._button = ratbagd_button
self._action_type = self._button.action_type
self._init_ui()
def _init_ui(self):
action_types = self._button.action_types
for action_type in action_types:
page = self._BUTTON_TYPE_TO_PAGE[action_type]
self.stack.get_child_by_name(page).set_visible(True)
if self._action_type == action_type:
self.stack.set_visible_child_name(page)
@GObject.Property
def action_type(self):
return self._action_type

76
piper/buttonspage.py Normal file
View File

@@ -0,0 +1,76 @@
# Copyright (C) 2017 Jente Hidskes <hjdskes@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from gettext import gettext as _
from .buttondialog import ButtonDialog
from .mousemap import MouseMap
from .optionbutton import OptionButton
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class ButtonsPage(Gtk.Box):
"""The second stack page, exposing the button configuration."""
__gtype_name__ = "ButtonsPage"
def __init__(self, ratbagd_device, *args, **kwargs):
"""Instantiates a new ButtonsPage.
@param ratbag_device The ratbag device to configure, as
ratbagd.RatbagdDevice
"""
Gtk.Box.__init__(self, *args, **kwargs)
self._device = ratbagd_device
self._init_ui()
def _init_ui(self):
profile = self._find_active_profile()
mousemap = MouseMap("#Buttons", self._device, spacing=20, border_width=20)
self.pack_start(mousemap, True, True, 0)
sizegroup = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
for ratbagd_button in profile.buttons:
index = ratbagd_button.index
# TODO: add the correct *mapping to the label
button = OptionButton(_("Button {}").format(index))
button.connect("clicked", self._on_button_clicked, ratbagd_button)
mousemap.add(button, "#button{}".format(index))
sizegroup.add_widget(button)
def _on_button_clicked(self, button, ratbagd_button):
# Presents the ButtonDialog to configure the mouse button corresponding
# to the clicked button.
dialog = ButtonDialog(ratbagd_button, transient_for=self.get_toplevel())
dialog.connect("response", self._on_dialog_response, ratbagd_button)
dialog.present()
def _on_dialog_response(self, dialog, response, ratbagd_button):
# The user either pressed cancel or apply. If it's apply, apply the
# changes before closing the dialog, otherwise just close the dialog.
if response == Gtk.ResponseType.APPLY:
print("Apply")
dialog.destroy()
def _find_active_profile(self):
# Finds the active profile, which is guaranteed to exist.
for profile in self._device.profiles:
if profile.is_active:
return profile

View File

@@ -16,6 +16,7 @@
from gettext import gettext as _
from .buttonspage import ButtonsPage
from .gi_composites import GtkTemplate
from .ratbagd import RatbagErrorCode, RatbagdDevice
from .resolutionspage import ResolutionsPage
@@ -30,8 +31,8 @@ from gi.repository import GLib, Gtk
class Window(Gtk.ApplicationWindow):
"""A Gtk.ApplicationWindow subclass to implement the main application
window. This Window contains the overlay for the in-app notifications, the
headerbar and the stack holding a ResolutionsPage, a ButtonPage and a
LEDPage."""
headerbar and the stack holding a ResolutionsPage, a ButtonsPage and a
LedsPage."""
__gtype_name__ = "ApplicationWindow"
@@ -60,6 +61,8 @@ class Window(Gtk.ApplicationWindow):
capabilities = self._device.capabilities
if RatbagdDevice.CAP_RESOLUTION in capabilities:
self.stack.add_titled(ResolutionsPage(self._device), "resolutions", _("Resolutions"))
if RatbagdDevice.CAP_BUTTON in capabilities:
self.stack.add_titled(ButtonsPage(self._device), "buttons", _("Buttons"))
if RatbagdDevice.CAP_LED in capabilities:
self.stack.add_titled(LedsPage(self._device), "leds", _("LEDs"))
except ValueError as e: