Skip to content
Snippets Groups Projects
Commit 2972f5aa authored by David Boddie's avatar David Boddie :speech_balloon:
Browse files

Start working on a sensor overview example


Signed-off-by: default avatarDavid Boddie <david.boddie@puri.sm>
parents
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
#!/usr/bin/env python3
from os import environ, path
from subprocess import call
prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local')
datadir = path.join(prefix, 'share')
destdir = environ.get('DESTDIR', '')
# Package managers set this so we don't need to run
if not destdir:
print('Updating icon cache...')
call(['gtk-update-icon-cache', '-qtf',
path.join(datadir, 'icons', 'hicolor')])
print('Updating desktop database...')
call(['update-desktop-database', '-q', path.join(datadir, 'applications')])
{
"app-id": "com.example.sensors",
"runtime": "org.gnome.Platform",
"runtime-version": "3.30",
"sdk": "org.gnome.Sdk",
"command": "sensors",
"finish-args": [
"--socket=wayland"
],
"modules": [
{
"name": "sensors",
"buildsystem": "meson",
"builddir": true,
"sources": [
{
"type": "dir",
"path": "."
}
]
},
{
"name" : "libhandy",
"buildsystem" : "meson",
"builddir": true,
"config-opts": [
"-Dglade_catalog=disabled"
],
"sources" : [
{
"type" : "git",
"branch": "v0.0.8",
"url" : "https://source.puri.sm/Librem5/libhandy.git"
}
]
}
]
}
[Desktop Entry]
Name=Title Bar
Icon=com.example.sensors
Exec=two-leaflets
Terminal=false
Type=Application
Categories=
StartupNotify=false
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="64" version="1.1" width="64"
viewBox="0 0 100 100">
<rect x="1" y="1" width="98" height="98" stroke="black" stroke-width="1" fill="white" />
<rect x="1" y="1" width="98" height="24" stroke="black" stroke-width="1" fill="#c0c0c0" />
</svg>
configure_file(
input: 'com.example.sensors.desktop',
output: 'com.example.sensors.desktop',
copy: true,
install: true,
install_dir: join_paths(get_option('datadir'), 'applications')
)
install_data('com.example.sensors.svg',
install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'scalable', 'apps'))
project('sensors',
version: '0.1.0',
meson_version: '>= 0.48.0',
)
subdir('data')
subdir('src')
meson.add_install_script('build-aux/meson/postinstall.py')
# -*- coding: utf-8 -*-
# Sensors example for the Adaptive UI tutorial.
# This file is part of the Librem 5 developer documentation.
# Copyright (C) 2019 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gio, GLib, GObject, Gtk
gi.require_version('Handy', '0.0')
from gi.repository import Handy
Handy.init()
from widgets import DetailsWidget
class Application(Gtk.Application):
def __init__(self):
super().__init__(application_id='com.example.sensors')
GLib.set_application_name('Sensors')
def do_activate(self):
window = Gtk.ApplicationWindow(application=self)
window.set_icon_name('com.example.sensors')
header, sub_header = self.init_title(window)
self.init_contents(window)
left_page_size_group = Gtk.SizeGroup(mode='horizontal')
left_page_size_group.add_widget(header)
left_page_size_group.add_widget(self.page1)
right_page_size_group = Gtk.SizeGroup(mode='horizontal')
right_page_size_group.add_widget(sub_header)
right_page_size_group.add_widget(self.page2)
# Ensure that the header is updated when the page changes.
self.content_leaflet.bind_property(
'visible-child-name',
self.title_leaflet, 'visible-child-name',
GObject.BindingFlags.SYNC_CREATE
)
# Hide buttons when the leaflets are folded.
self.title_leaflet.bind_property(
'folded',
self.back_button, 'visible',
GObject.BindingFlags.SYNC_CREATE
)
# End of property bindings
self.back_button.connect('clicked', self.go_back)
self.page1.connect('row-activated', self.select_item)
# Request a proxy for accessing the sensor service.
Gio.DBusProxy.new_for_bus(
Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None,
'sm.puri.librem5.understudy',
'/sm/puri/librem5/understudy',
'sm.puri.librem5.understudy', None,
self.init_dbus)
window.set_default_size(320, 512)
window.show_all()
def init_title(self, window):
# Title bar containing a leaflet
title_bar = Handy.TitleBar()
self.title_leaflet = Handy.Leaflet(
child_transition_type='slide',
mode_transition_type='slide'
)
header = Gtk.HeaderBar(
title='Sensors',
show_close_button=True
)
sub_header = Gtk.HeaderBar(
show_close_button=True,
hexpand=True
)
self.back_button = Gtk.Button.new_from_icon_name(
'go-previous-symbolic', 1)
sub_header.add(self.back_button)
self.title_leaflet.add(header)
self.title_leaflet.child_set(header, name='left_page')
self.title_leaflet.add(sub_header)
self.title_leaflet.child_set(sub_header, name='right_page')
title_bar.add(self.title_leaflet)
window.set_titlebar(title_bar)
# The header group ensures that only one header bar is visible at once.
header_group = Handy.HeaderGroup()
header_group.add_header_bar(header)
header_group.add_header_bar(sub_header)
# Window content
self.content_leaflet = Handy.Leaflet(
child_transition_type='slide',
mode_transition_type='slide'
)
return header, sub_header
def init_contents(self, window):
# Left page
self.tree_store = Gtk.ListStore(str)
self.page1 = Gtk.TreeView(
model=self.tree_store,
activate_on_single_click=True
)
self.page1.append_column(Gtk.TreeViewColumn(
'Device', Gtk.CellRendererText(), text=0))
# Right page
self.page2 = Gtk.Box(
orientation='vertical',
hexpand_set=True
)
details_label = Gtk.Label(wrap=True)
details_label.set_markup(
'<span size="large">Click a sensor to show its attributes.</span>'
)
details_label.set_padding(8, 0)
self.details_stack = Gtk.Stack()
self.details_stack.add_named(details_label, 'intro')
self.page2.pack_start(self.details_stack, True, True, 16)
# Add widgets to the leaflet.
self.content_leaflet.add(self.page1)
self.content_leaflet.child_set(self.page1, name='left_page')
self.content_leaflet.add(self.page2)
self.content_leaflet.child_set(self.page2, name='right_page')
window.add(self.content_leaflet)
def init_dbus(self, proxy, result, data=None):
self.proxy = proxy.new_finish(result)
self.proxy.call('sm.puri.librem5.understudy.GetSensors', None,
Gio.DBusCallFlags.NO_AUTO_START, -1, None,
self.update_devices, None)
def go_back(self, button):
self.content_leaflet.set_visible_child(self.page1)
# Stop the timer for the current widget in the details stack.
current = self.details_stack.get_visible_child()
if isinstance(current, DetailsWidget):
current.switch.set_active(False)
def update_devices(self, proxy, result, data):
variant = proxy.call_finish(result)
self.pages = {}
for i, device_name in enumerate(list(variant[0])):
# Populate the list model with device names.
self.tree_store.append([device_name])
# Add a widget to the stack to show the attributes of the device.
widget = DetailsWidget(device_name, self.proxy)
self.details_stack.add_named(widget, device_name)
self.pages[i] = widget
def select_item(self, sender, row, column):
current = self.details_stack.get_visible_child()
widget = self.pages[int(row.get_indices()[0])]
if widget == current:
return
# Stop the timer for the current widget.
if isinstance(current, DetailsWidget):
current.switch.set_active(False)
# Show the widget before setting it as the visible child widget.
widget.show_all()
self.details_stack.set_visible_child(widget)
# Show the second page of the leaflet.
self.content_leaflet.set_visible_child(self.page2)
def main(version):
app = Application()
return app.run(sys.argv)
# Initialize local variables to hold installation paths.
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
moduledir = join_paths(pkgdatadir, meson.project_name())
# Find the python3 program to help define the PYTHON configuration variable
# that will be used in the sensors.in template.
python3 = find_program('python3')
conf = configuration_data()
conf.set('PYTHON', python3.path())
conf.set('VERSION', meson.project_version())
conf.set('pkgdatadir', pkgdatadir)
# Replace placeholders in templates with the configuration data defined above
# and create the versions of these files for installation in the build
# directory.
configure_file(
input: 'sensors.in',
output: 'sensors',
configuration: conf,
install: true,
install_dir: get_option('bindir')
)
# Declare the application's sources and their installation directory.
sources = [
'__init__.py',
'main.py'
]
install_data(sources, install_dir: moduledir)
#!@PYTHON@
# -*- coding: utf-8 -*-
# Copyright (C) 2019 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>
import os
import signal
import sys
VERSION = '@VERSION@'
pkgdatadir = '@pkgdatadir@'
sys.path.insert(1, pkgdatadir)
signal.signal(signal.SIGINT, signal.SIG_DFL)
if __name__ == '__main__':
from sensors import main
sys.exit(main.main(VERSION))
# -*- coding: utf-8 -*-
# Sensors example for the Adaptive UI tutorial.
# This file is part of the Librem 5 developer documentation.
# Copyright (C) 2019 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gio, GLib, Gtk
class DetailsWidget(Gtk.Box):
def __init__(self, device_name, proxy):
super().__init__(orientation='vertical', spacing=16)
self.device_name = device_name
self.proxy = proxy
self.timeout_id = None
title = Gtk.Label()
title.set_markup(
'<span size="large" weight="bold">' + device_name + '</span>')
self.grid = Gtk.Grid(hexpand=True)
self.switch = Gtk.Switch(halign='center')
self.switch.connect('notify::active', self.toggled)
self.add(title)
self.add(self.grid)
self.pack_end(self.switch, True, False, 0)
proxy.call('sm.puri.librem5.understudy.GetAttributes',
GLib.Variant('(s)', [device_name]),
Gio.DBusCallFlags.NO_AUTO_START, -1, None,
self.update_attributes, None)
def update_attributes(self, proxy, result, data):
variant = proxy.call_finish(result)
attributes = variant[0]
self.value_labels = {}
# Create widgets to hold the attribute names and values.
for i, attribute in enumerate(attributes):
label = Gtk.Label(label=attribute, xalign=1)
self.grid.attach(label, 0, i, 1, 1)
def toggled(self, switch, param):
if switch.get_active():
self.start_timer()
else:
self.stop_timer()
def start_timer(self):
# Start a timer to update the attributes.
self.timeout_id = GLib.timeout_add(250, self.update_values)
def stop_timer(self):
# Destroy the timer.
if self.timeout_id != None:
GLib.source_remove(self.timeout_id)
self.timeout_id = None
def update_values(self):
print(self.device_name)
return True
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment