Creating GUI for configuring SUSI Linux Settings

SUSI Linux app provides access to SUSI on Linux distributions on desktop as well as hardware devices like Raspberry Pi. The settings for SUSI Linux are controlled with the use of a config.json file. You may edit the file manually, but to provide safe configurations, we have a config generator script. You may run the script to configure settings like TTS Engine, STT Engine, authentication, choice about the hotword engine etc. Generally, it is easier to configure application settings through a GUI. Thus, we added a GUI for it using PyGTK and Glade.

Glade is a GUI designer for GNOME based Linux systems. I wrote a blog about how to create user interfaces in Glade and access it from Python code in SUSI Linux. Now, for creating UI for Configuration screen, we need to choose an ideal layout. Glade provides various choices like BoxLayout, GridLayout, FlowBox, ListBox , Notebook etc. Since, we need to display only basic settings options, we select the BoxLayout for this purpose.

BoxLayout as the name suggests, forms a box like arrangement for widgets. You can arrange the widgets in either Landscape or Horizontal Layout. We select Application Window as a top-level container and add a BoxLayout container in it. Now, in each box of the BoxLayout, we need to add the widgets like ComboBox and Switch for user’s choice and a Label. This can be done by using a horizontal BoxLayout with corresponding widgets. After arranging the UI in above described manner, we have a GUI like below.

If you see the current window in the preview now, you will find that the ComboBox do not have any items. We need to define items in the ComboBox using a GTKListStore. You may refer to this video tutorial to see how this can be done.

Now, when we see the preview, our GUI is fully functional. We have options for Speech Recognition Service, Text to Speech Service in ComboBox. Other simple settings are available as switches.

Now, we need to add functionality to our UI. We want our code to be modular and structured, therefore, we declare a ConfigurationWindow class. Though the ideal way to handle such cases is inheriting from the Gtk.Window class, but reading the documentation of PyGTK+ 3, I could not find a way to do this for windows created through Glade. Thus, we will use composition for storing the window object. We add window and other widgets present in the UI as properties of ConfigurationWindow class like this.

class ConfigurationWindow:
   def __init__(self) -> None:
       super().__init__()
       builder = Gtk.Builder()
       builder.add_from_file(os.path.join("glade_files/configure.glade"))

       self.window = builder.get_object("configuration_window")
       self.stt_combobox = builder.get_object("stt_combobox")
       self.tts_combobox = builder.get_object("tts_combobox")
       self.auth_switch = builder.get_object("auth_switch")
       self.snowboy_switch = builder.get_object("snowboy_switch")
       self.wake_button_switch = builder.get_object("wake_button_switch")

Now, we need to connect the Signals from our configuration window to the Handler. We declare the Handler as a nested class in the ConfigurationWindow class because its scope of usage is inside the ConfigurationWindow object. Then you may connect signals to an object of the Handler class.

builder.connect_signals(ConfigurationWindow.Handler(self))

Since we may need to modify the state of the widgets, we hold a reference of the parent ConfigurationWindow object in the Handler and pass the self as a parameter to the Handler. You may read more about using the handlers in my previous blog.

In the Handler, we connect to the config.json file and change the parameters of the the file based on the user inputs on the GUI. We handle it for the Text to Speech selection comboBox in the following manner. We also declare two addition Dialogs for handling the input of credentials by the users for the Watson and Bing services.

def on_stt_combobox_changed(self, combo: Gtk.ComboBox):
   selection = combo.get_active()

   if selection == 0:
       config['default_stt'] = 'google'

   elif selection == 1:
       credential_dialog = WatsonCredentialsDialog(self.config_window.window)
       response = credential_dialog.run()

       if response == Gtk.ResponseType.OK:
           username = credential_dialog.username_field.get_text()
           password = credential_dialog.password_field.get_text()
           config['default_stt'] = 'watson'
           config['watson_stt_config']['username'] = username
           config['watson_stt_config']['password'] = password
       else:
           self.config_window.init_stt_combobox()

       credential_dialog.destroy()

   elif selection == 2:
       credential_dialog = BingCredentialDialog(self.config_window.window)
       response = credential_dialog.run()

       if response == Gtk.ResponseType.OK:
           api_key = credential_dialog.api_key_field.get_text()
           config['default_stt'] = 'bing'
           config['bing_speech_api_key']['username'] = api_key
       else:
           self.config_window.init_stt_combobox()

       credential_dialog.destroy()

Now, we declare two more methods to show and exit the Window.

def show_window(self):
   self.window.show_all()
   Gtk.main()

def exit_window(self):
   self.window.destroy()
   Gtk.main_quit()

Now, we may use the ConfigurationWindow class object anywhere from our code. This modularized approach is better when you need to manage multiple windows as you can just declare the Window of a particular type and show it whenever need in your code.

Resources

  • Glade usage Youtube tutorial: https://www.youtube.com/watch?v=vOGK3TveDDk
  • Creating GUI using PyGTK for SUSI Linux: https://blog.fossasia.org/making-gui-for-susi-linux-with-pygtk/
  • PyGObject Documentation: http://pygobject.readthedocs.io/en/latest/getting_started.html

Migration of LXDE Desktop of Meilix to LXQt

Meilix is originally based on LXDE and our task is to migrate Meilix desktop to LXQt. Originally LXQt is a fusion of LXDE and the Razor-Qt desktop.

What is LXDE and LXQt ?
Both are desktop environment. They are light weight with a beautiful GUI and a user-friendly touch.

Older code to install a LXDE desktop in a Debian-based environment is (source):

apt-get -q -y --purge install --no-install-recommends \
lxsession lightdm lightdm-gtk-greeter lxterminal gvfs-backends seahorse \
network-manager-gnome xorg dbus-x11 openbox ubiquity-frontend-gtk vlc \
xfce4-mixer gstreamer0.10-alsa pulseaudio pavucontrol lxpanel \
mozilla-plugin-vlc lubuntu-core jockey-gtk

In the chroot environment, the maintainer has pick up the it’s dependencies and recommend packages and listed all packages which required to install a LXDE desktop. He keeps the size as small as possible. The maintainer had hand-picked only the required packages which can run the desktop.

What we did:
We tried with several approaches. Few worked and few did not. We removed all the packages related to desktop like gnome-games, gdm and gnome-language-en since we don’t want any sort of problem conflicts in the new desktop. We had also remove all the lines mentioned above which install LXDE.

Then I simply typed the line:

apt-get -q -y install lxqt

This way we only reach to the CLI version of the OS, and we actually don’t know whether we actually have the desktop install or not.
We tried to install lighdm their by

sudo apt-get install xinit

but that was also giving errors.

We changes the line to:

apt-get -q -y install xorg sddm lxqt

And suddenly the same approach which brought to a black screen and that was a desktop and the window manager was openbox.

Then we tried to add sddm.conf to get the desktop and realized that sddm starts plasma instead of LXQt. Then we added a config file for sddm to start up LXQt by default. This file is present in the location `/etc/sddm.conf` in the meilix-default-settings metapackage with the code as:

[Autologin]
User=hotelos
Session=lxqt.desktop

But due to a bug reported here, it still starts plasma instead of LXQt. So now I have to patch a script in the location /usr/share/initramfs-tools/scripts/casper-bottom/15autologin

In last paragraph of the script it will first detect the presence of sddm, if that exists, it will assume that plasma will be default desktop and try to detect Lubuntu.desktop and QLubuntu.desktop .
So, change plasma.desktop to lxqt.desktop.

In the 15autologin changes line 84:

if [ -f /root/usr/bin/sddm ]; then
	sddm_session=lxqt.desktop
	if [ -f /root/usr/share/xsessions/Lubuntu.desktop ]; then
    	    sddm_session=Lubuntu.desktop
	fi
	if [ -f /root/usr/share/xsessions/QLubuntu.desktop ]; then
    	    sddm_session=QLubuntu.desktop
	fi
fi

Here, sddm is made to configure it must use lxqt desktop.

And this worked. Finally we get the LXQt desktop for Meilix.

Since this script along with other scripts will be packed into a small filesystem called initramfs, therefore we have to write `update-initramfs -u ` after the installation of the meilix-default-settings package.

I had made a table of the things that worked and that didn’t.

Things which do not work Things which work
1. Firstly, we removed all these lines and replace it with `apt-get -q -y install lxqt`, but this will take us to a CLI and ask to install xinit which takes us to another error. We want to straight forward go to GUI.
2. Removing of all the others desktop dependencies like gnome (here), LXDE. The way build.sh was written is that it includes suggests and recommends packages to take less space.
3. Giving less RAM to the live boot ISO which gives the error in the installation of xinit in CLI mode.
4. Removing single line and adding single line and keep on testing rather than testing on a big code. This helped us to find that where actually the issue lies.
5. Removing the rc.xml file which is responsible for openbox configuration that we don’t need in the LXQt. Screenshots are attached below.
6. Finally I booted into CLI and there I type startx which ask me to do apt-get install xinit then after that I did startx from where it takes me to the black screen.
7. I included lightdm but it’s not working and when i tried to start it using the terminal of openbox “systemctl start lightdm” , it gives the error as “failed to start lightdm.service: Unit lightdm.service not found”.
8. When I tried to install lightdm “sudo apt-get install lightdm-gtx-greeter” and we get the error pasted below.
9. Then I though to go for sddm which is a “Simple Desktop Display Manager” a replacement for lightdm.
10. Finally we make it something like this “sudo apt-get install -q -y xorg sddm lxqt”
11. sddm starts plasma (KDE) instead of LXQt for getting the desire result we need is to add /etc/sddm.conf and set its login default to lxqt.desktop
12. After screenshot of number 10, I clicked ok and logout myself to CLI and login and type startx to get the screenshot.
13. All of the things that I was doing is in the xenial version of meilix and when I tried the same in zesty. I get the following result.
14. We think there must be something why Casper uses plasma by default instead of lxqt. We can also try preventing plasma.desktop being installed in the first place.
15. Casper will set up the login when live cd is started, and the file will be changed too.
So writing to the config file (sddm.conf) actually does nothing.
16. apt install lubuntu installs lubuntu.desktop while Casper (It is actually responsible for setting up live environment, which also needs to takes care of auto login) checks for Lubuntu.desktop (noting the capital letter)
It is in the script `/usr/share/initramfs-tools/scripts/casper-bottom/15autologin`
Probably we have to patch that.
So Casper will write configs to login manager like sddm.At the time of booting the ISO into the live desktop.
The problem is, the script Casper is using, detects a different file name for LXQt.
17. We get the “15autologin file” inside chroot directory if you build the iso by yourself.
18. Then we added the line to update – initramfs (initramfs is a small filesystem that linux will mount first, which will only have basic functions, then other partitions).

Number 3

xinit error after increasing of the RAM

Number 5

Number 6

This is Openbox.

Number 8

Number 10

Number 12

Number 13.

Finally the desktop LXQt

References:
LXQt Desktop
LXDE Desktop
Switching Desktop Environment

Making GUI for SUSI Linux with PyGTK

SUSI Linux app provides access to SUSI on Linux distributions on desktop as well as hardware devices like Raspberry Pi. It started off as a headless client but we decided to add a minimalist GUI to SUSI Linux for performing login and configuring settings. Since, SUSI Linux is a Python App, it was desirable to use a GUI Framework compatible with Python. Many popular GUI frameworks now provide bindings for Python. Some popular available choices are:

wxPython: wxPython is a Python GUI framework based on wxWidgets, a cross-platform GUI library written in C++. In addition to the standard dialogs, it includes a 2D path drawing API, dockable windows, support for many file formats and both text-editing and word-processing widgets. wxPython though mainly support Python 2 as programming language.

PyQT: Qt is a multi-licensed cross-platform framework written in C++. Qt needs a commercial licence for use but if application is completely Open Source, community license can be used. Qt is an excellent choice for GUIs and many applications are based on it.

PyGTK / PyGObject: PyGObject is a Python module that lets you write GUI applications in GTK+. It provides bindings to GObject, a cross platform C library. GTK+ applications are natively supported in most distros and you do not need to install any other development tools for developing with PyGTK.

Comparing all these frameworks, PyGTK was found to meet our needs very well. To make UIs in PyGTK, you have a WYSIWYG (What you see is what you get) editor called Glade. Though you can design whole UI programmatically, it is always convenient to use an editor like Glade to simplify the creation and styling of widgets.

To create a UI, you need to install Glade in your specific distribution. After that open glade, and add a Top Level container Window or AppWindow to your app.

Once that is done, you may pick from the available Layout Managers. We are using BoxLayout Manager in SUSI Linux GUIs. Once that is done, add your widgets to the Application Window using Drag and Drop.

Properties of widgets are available on the right panel. Edit your widget properties to give them meaningful IDs so we can address them later in our code. GTK also provides Signals for signaling about a events associated with the widgets. Open the Signals tab in the Widget properties pane. Then, you need to write name of the signal handler for the events associated with Widgets. A signal handler is a function that is fired upon the occurrence of the associated event. For example, we have signals like text_changed in Text Entry boxes, and clicked for Button.

After completing the design of GUI, we can address the .glade file of the UI we just created in the Python code. We can do this using the following snippet.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

builder = Gtk.Builder()
builder.add_from_file("glade_files/signin.glade")

You can reference each widget from the Glade file using its ID like below.

email_field = builder.get_object("email_field")

Now, to handle all the declared signals in the Glade file, we need to make a Handler class. In this class, you need to define call the valid callbacks for your signals. On the occurrence of the signal, respective callback is fired.

class Handler:

   def onDeleteWindow(self, *args):
       Gtk.main_quit(*args)

   def signInButtonClicked(self, *args):
       # implementation

   def input_changed(self, *args):
       # implementation

We may associate a handler function to more than one Signal. For that, we just need to specify the respective function in both the Signals.

Now, we need to connect this Handler to builder signals. This can be done using the following line.

builder.connect_signals(Handler())

Now, we can show our window using the following lines.

window.show_all()
Gtk.main()

The above lines displays the window and start the Gtk main loop. The script waits on the Gtk main loop. The app may be quitted using the Gtk.main_quit() call. Running this script shows the Login Screen of our app like below.

Resources:

GNOME.Asia Vietnam Wrap Up

15773456877_d6660b9d94_o

GNOME.Asia Summit 2009 was a big success as one of the one of the very first Open Source conferences in South East Asia. The event took place on Nov 20 – 22, 2009 at Quang Trung Software Park in Ho Chi Minh City, Vietnam. Quang Trung Software Park is a home of more than 200 tech-companies (including local start-ups, multi-nationals, and state-owned companies such as FDI).

The conference was organized by the GNOME.Asia community in cooperation with the organization team in Vietnam. The Ho Chi Minh City government supported the event through the Department of Information and Communications Technology.

Numbers and facts
* 1000+ attendees
* 79 speakers
* 138 volunteers
* 5 keynotes
* 109 presentations
* 25 lightning talks
* 17 workshops

Main Tracks
Six tracks were organized in parallel during the 3-day conference. The focus was only on GNOME technologies and desktop deployments based on GNOME  but also a variety of topics including:

* GNOME 3.0
* GNOME library and application development
* Localization & Internationalization
* Mobile platforms and thin clients
* Desktop deployments
* School software

Inside the keynote track
Inside the keynote track

In addition to the majority of software presentations, hardware talks such as ‘How to build an Open Source printer’ by Frederic Muller gathered a big interest.

Workshops
A focus of the workshops were applications for thin clients, localization and translation for Asian users. In parallel, there was also Linux course for beginners, map party, installation fest, and Ubuntu release party which was organized by the Vietnamese Ubuntu user group.

Linux Course for beginners Q&A
Linux Course for beginners Q&A

Women in IT Panel
Unlike many tech-conferences around the world, more than 50% of GNOME.Asia 2009 participants were female. They were young, curious and enthusiastic. Therefore the “Women in IT” Panel was somewhat overwhelmed with tons of questions. Stormy Peters from the US, chair of GNOME.Asia, shared her inspired story of being a mother, a housewife, an employee, an active open source contributor and a chair of the GNOME Foundation.

15771978930_5a95fb330c_k
Women in IT Panel

Pockey Lam and Emily Chen, two founders of the Beijing linux users group explained how to start, grow and maintain a successful open source community.

Hong Phuc Dang, who brought the first open source conference to Vietnam spoke of how her open source journey was started and encouraged female audience to explore the beauty and value of sharing, openness and collaboration which can be found easily in an open source community.

Mini job fair
A mini job fair was organized at the conference site with 15 companies on board. Every year thousands of computer science fresh-graduates in Vietnam are seeking for job opportunities in the tech field. Less 20% is able to get a right job of his/her major. More than 80% is forced to start their career in a non-tech environment. The idea of the job fair is (1) to provide a platform where tech companies can announce their vacant positions, recruitment process, job requirements, expectation; (2) to organize a meeting place of employers and their potential employees; (3) to foster knowledge sharing community which aims to help students prepare themselves with skill sets that fit the current marketplace.

Vietnam – a great host country
Visitors from oversea could not be happier with the hospitality, warmness, and friendliness of their host country, Vietnam. Volunteers welcomed speakers/visitors at the airport, brought them to the hotel, provided them local SIM cards, showed them around city etc.

Speakers and volunteers
Speakers and volunteers

The event ended by a beautiful tour along the Mekong. It was an unforgettable experience for all of us.

Stormy Peters of GNOME Foundation is getting on the boat tour
Stormy Peters of GNOME Foundation is getting on the boat tour
Andrew super enjoys the tour.
Andrew super enjoys the mekong tour.

Sponsors and Partners
We would like to thank our sponsors: Sun Microsystems, IBM, Google and Intel for their support of GNOME.Asia Summit and thank to our media partner PCWorld, DatVietNews, VietnamInvestmentNews for their coverage of the conference.

Bringing forward Asia’s Open Source Communities
The FOSSASIA team and volunteers will continue to grow the community across Asia and to support Open Technologies with the annual FOSSASIA Summit, regional meetups and developer programs.

Links

GNOME.Asia Wiki: https://wiki.gnome.org/GnomeAsia/2009
GNOME.Asia: http://gnome.asia
FOSSASIA Events: http://events.fossasia.org