Source Files

The main source code for the application can be found in the main.py file within the src directory. The purpose of the other files is explained in other tutorials, such as the Your First Application tutorial.

The Program

Because the application is very simple, we show the whole main program here to provide an overview before looking at the details:

# -*- coding: utf-8 -*-

# Copyright (C) 2019 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>

import gi
import sys

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


class Application(Gtk.Application):

    def __init__(self):
        super().__init__(application_id='com.example.network_state')
        GLib.set_prgname('com.example.network_state')
        self.note = None

    def do_activate(self):
        window = Gtk.ApplicationWindow(application=self)
        window.set_icon_name('com.example.network_state')
        window.set_title("Network State")

        box = Gtk.Box(orientation='vertical')
        button = Gtk.Button(label='Click to check the network state')
        button.connect('clicked', self.update_label)
        self.connectivity_label = Gtk.Label(label="-")
        self.available_label = Gtk.Label(label="-")
        self.metered_label = Gtk.Label(label="-")

        box.add(button)
        box.add(self.connectivity_label)
        box.add(self.available_label)
        box.add(self.metered_label)
        window.add(box)
        window.show_all()

    def update_label(self, button):

        monitor = Gio.NetworkMonitor.get_default()
        state = monitor.get_connectivity()

        if state == Gio.NetworkConnectivity.LOCAL:
            self.connectivity_label.set_text('Local network only')
        elif state == Gio.NetworkConnectivity.PORTAL:
            self.connectivity_label.set_text('Behind a captive portal')
        elif state == Gio.NetworkConnectivity.LIMITED:
            self.connectivity_label.set_text('Limited connectivity')
        elif state == Gio.NetworkConnectivity.FULL:
            self.connectivity_label.set_text('Full network')
        else:
            self.connectivity_label.set_text('Other')

        if monitor.get_network_available():
            self.available_label.set_text("Available")
        else:
            self.available_label.set_text("Not available")

        if monitor.get_network_metered():
            self.metered_label.set_text("Metered")
        else:
            self.metered_label.set_text("Not metered")


def main(version):

    app = Application()
    return app.run(sys.argv)

Much of the is very similar to other examples and tutorials. We will focus on the parts that are specific to this example.

Relevant Modules

The Gio module provides classes and functions that perform a range of tasks, including one that allows us to read the network state. This module is imported in the same way as the Gtk module:

import gi
import sys

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

It can be helpful to specify the version of the Gio module before importing it, but it is not necessary in this case.

Application Class

The Application class provides the usual methods to set up the application and perform tasks when it is run.

In the do_activate method we set up the user interface, creating a Gtk.Button instance and adding it to the layout of the window:

    def do_activate(self):
        window = Gtk.ApplicationWindow(application=self)
        window.set_icon_name('com.example.network_state')
        window.set_title("Network State")

        box = Gtk.Box(orientation='vertical')
        button = Gtk.Button(label='Click to check the network state')
        button.connect('clicked', self.update_label)
        self.connectivity_label = Gtk.Label(label="-")
        self.available_label = Gtk.Label(label="-")
        self.metered_label = Gtk.Label(label="-")

        box.add(button)
        box.add(self.connectivity_label)
        box.add(self.available_label)
        box.add(self.metered_label)
        window.add(box)
        window.show_all()

By connecting the clicked signal of the button to the update_label method, the application can respond when the user clicks the button. The update_label method receives the button itself as an argument:

    def update_label(self, button):

        monitor = Gio.NetworkMonitor.get_default()
        state = monitor.get_connectivity()

        if state == Gio.NetworkConnectivity.LOCAL:
            self.connectivity_label.set_text('Local network only')
        elif state == Gio.NetworkConnectivity.PORTAL:
            self.connectivity_label.set_text('Behind a captive portal')
        elif state == Gio.NetworkConnectivity.LIMITED:
            self.connectivity_label.set_text('Limited connectivity')
        elif state == Gio.NetworkConnectivity.FULL:
            self.connectivity_label.set_text('Full network')
        else:
            self.connectivity_label.set_text('Other')

        if monitor.get_network_available():
            self.available_label.set_text("Available")
        else:
            self.available_label.set_text("Not available")

        if monitor.get_network_metered():
            self.metered_label.set_text("Metered")
        else:
            self.metered_label.set_text("Not metered")

In this method we create an instance of the Gio.NetworkMonitor class and call its get_connectivity method to obtain the current network state. We interpret the different values of Gio.NetworkConnectivity to provide updated text for the labels.

Summary

You can use the Gio module to query the network state. You can specify the version of the module if you require, using gi.require_version, and import the module from the gi.repository package.

To obtain the network state, create an instance of the Gio.NetworkMonitor class and call its get_connectivity method.