Skip to content

Commit

Permalink
More wifi changes
Browse files Browse the repository at this point in the history
  • Loading branch information
elParaguayo committed Dec 22, 2023
1 parent d974422 commit 8a56f2b
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 52 deletions.
20 changes: 17 additions & 3 deletions qtile_extras/widget/iwd.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from libqtile.widget import base

from qtile_extras.popup.menu import PopupMenuItem, PopupMenuSeparator
from qtile_extras.widget.mixins import GraphicalWifiMixin, MenuMixin
from qtile_extras.widget.mixins import ConnectionCheckMixin, GraphicalWifiMixin, MenuMixin

IWD_SERVICE = "net.connman.iwd"
IWD_DEVICE = IWD_SERVICE + ".Device"
Expand Down Expand Up @@ -240,7 +240,7 @@ async def connect(self):
await self.network.call_connect()


class IWD(base._TextBox, base.MarginMixin, MenuMixin, GraphicalWifiMixin):
class IWD(base._TextBox, base.MarginMixin, MenuMixin, GraphicalWifiMixin, ConnectionCheckMixin):
"""
This widget provides information about your wireless connection using iwd.
Expand Down Expand Up @@ -270,16 +270,21 @@ class IWD(base._TextBox, base.MarginMixin, MenuMixin, GraphicalWifiMixin):
("format", "{ssid} ({quality}%)", "Text format. Available fields: ssid, rssi, quality"),
("show_text", True, "Displays text in bar."),
("show_image", False, "Shows a graphical representation of signal strength."),
("active_colour", "ffffff", "Colour for wifi strength."),
("inactive_colour", "666666", "Colour for wifi background."),
("scanning_colour", "3abb3a", "Colour to use for image when scanning is active."),
]

def __init__(self, **config):
base._TextBox.__init__(self, **config)
self.add_defaults(MenuMixin.defaults)
self.add_defaults(GraphicalWifiMixin.defaults)
self.add_defaults(ConnectionCheckMixin.defaults)
self.add_defaults(IWD.defaults)
self.add_defaults(base.MarginMixin.defaults)
MenuMixin.__init__(self, **config)
GraphicalWifiMixin.__init__(self)
ConnectionCheckMixin.__init__(self)
self.bus = None
self.device = None
self.networks = {}
Expand All @@ -295,6 +300,7 @@ def __init__(self, **config):
def _configure(self, qtile, bar):
base._TextBox._configure(self, qtile, bar)
self.set_wifi_sizes()
ConnectionCheckMixin._configure(self)

def calculate_length(self):
width = 0
Expand Down Expand Up @@ -523,7 +529,15 @@ def draw(self):
self.drawer.clear(self.background or self.bar.background)
offset = self.wifi_padding_x
if self.show_image:
self.draw_wifi(self.percentage)
if self.device is not None and self.device.scanning:
foreground = self.scanning_colour
elif not self.is_connected:
foreground = self.disconnected_colour
else:
foreground = self.active_colour
self.draw_wifi(
self.percentage, foreground=foreground, background=self.inactive_colour
)
offset += self.wifi_width + self.wifi_padding_x

if self.show_text:
Expand Down
103 changes: 103 additions & 0 deletions qtile_extras/widget/mixins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import math
import socket
from contextlib import contextmanager
from copy import deepcopy
from typing import TYPE_CHECKING

Expand All @@ -35,6 +37,15 @@
PI = math.pi


@contextmanager
def socket_context(*args, **kwargs):
s = socket.socket(*args, **kwargs)
try:
yield s
finally:
s.close()


def to_rads(degrees):
return degrees * PI / 180.0

Expand Down Expand Up @@ -524,6 +535,37 @@ def draw_bar(


class GraphicalWifiMixin(_BaseMixin):
"""
Provides the ability to draw a graphical representation of wifi signal strength.
To use the mixin, your code needs to include the following:
.. code:: python
class MyGraphicalInternetWidget(GraphicalWifiMixin):
def __init__(self):
self.add_defaults(GraphicalWifiMixin.defaults)
GraphicalWifiMixin.__init__(self)
def _configure(self, qtile, bar):
... # other configuration lines here
self.set_wifi_sizes()
def draw(self):
# To draw the icon you need the following parameters:
# - percentage: a value between 0 and 1
# - foreground: the colour of the indicator
# - background: the colour of the indicator background
self.draw_wifi(percentage=percentage, foreground=foreground, background=background)
.. note::
This mixin does not set the widgth of your widget but does provide a
``self.wifi_width`` attribute which can be used for this purpose.
"""

defaults = [
("wifi_arc", 75, "Angle of arc in degrees."),
("wifi_rectangle_width", 5, "Width of rectangle in pixels."),
Expand Down Expand Up @@ -602,3 +644,64 @@ def _draw_wifi_rectangle(self, percentage, foreground, background):
ctx.fill()

ctx.restore()


class ConnectionCheckMixin(_BaseMixin):
"""
Mixin to periodically check for internet connection and set the
``self.is_connected`` flag depending on status.
Your code should include the following lines to use the mixin.
.. code:: python
class MyInternetWidget(ConnectionCheckMixin):
def __init__(self):
self.add_defaults(ConnectionCheckMixin.defaults)
ConnectionCheckMixin.__init__(self)
def _configure(self, qtile, bar):
ConnectionCheckMixin._configure(self)
"""

defaults = [
(
"check_connection_interval",
0,
"Interval to check if device connected to internet (0 to disable)",
),
("disconnected_colour", "aa0000", "Colour when device has no internet connection"),
("internet_check_host", "8.8.8.8", "IP adddress to check for internet connection"),
("internet_check_port", 53, "Port to check for internet connection"),
(
"internet_check_timeout",
5,
"Period before internet check times out and widget reports no internet connection.",
),
]

def __init__(self):
# If we're checking the internet connection then we assume we're disconnected
# until we've verified the connection
self.is_connected = not bool(self.check_connection_interval)

def _configure(self, *args):
if self.check_connection_interval:
self.timeout_add(self.check_connection_interval, self._check_connection)

def _check_connection(self):
self.qtile.run_in_executor(self._check_internet).add_done_callback(self._check_connected)

def _check_internet(self):
with socket_context(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(self.internet_check_timeout)
try:
s.connect((self.internet_check_host, self.internet_check_port))
return True
except (TimeoutError, OSError):
return False

def _check_connected(self, result):
self.is_connected = result.result()
self.timeout_add(self.check_connection_interval, self._check_connection)
54 changes: 5 additions & 49 deletions qtile_extras/widget/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,16 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import socket
from contextlib import contextmanager

from libqtile import bar
from libqtile.command.base import expose_command
from libqtile.log_utils import logger
from libqtile.widget import base
from libqtile.widget.wlan import get_status

from qtile_extras.widget.mixins import GraphicalWifiMixin


@contextmanager
def socket_context(*args, **kwargs):
s = socket.socket(*args, **kwargs)
try:
yield s
finally:
s.close()
from qtile_extras.widget.mixins import ConnectionCheckMixin, GraphicalWifiMixin


class WiFiIcon(base._Widget, base.PaddingMixin, GraphicalWifiMixin):
class WiFiIcon(base._Widget, base.PaddingMixin, GraphicalWifiMixin, ConnectionCheckMixin):
"""
An simple graphical widget that shows WiFi status.
Expand All @@ -63,19 +51,6 @@ class WiFiIcon(base._Widget, base.PaddingMixin, GraphicalWifiMixin):
5,
"Time in secs for expanded information to display when clicking on icon.",
),
(
"check_connection_interval",
0,
"Interval to check if device connected to internet (0 to disable)",
),
("disconnected_colour", "aa0000", "Colour when device has no internet connection"),
("internet_check_host", "8.8.8.8", "IP adddress to check for internet connection"),
("internet_check_port", 53, "Port to check for internet connection"),
(
"internet_check_timeout",
5,
"Period before internet check times out and widget reports no internet connection.",
),
("show_ssid", False, "Show SSID and signal strength."),
]

Expand All @@ -91,7 +66,9 @@ def __init__(self, **config):
self.add_defaults(WiFiIcon.defaults)
self.add_defaults(base.PaddingMixin.defaults)
self.add_defaults(GraphicalWifiMixin.defaults)
self.add_defaults(ConnectionCheckMixin.defaults)
GraphicalWifiMixin.__init__(self)
ConnectionCheckMixin.__init__(self)

self.add_callbacks({"Button1": self.show_text})

Expand All @@ -109,10 +86,6 @@ def __init__(self, **config):
self.essid = ""
self.percent = 0

# If we're checking the internet connection then we assume we're disconnected
# until we've verified the connection
self.is_connected = not bool(self.check_connection_interval)

def _configure(self, qtile, bar):
base._Widget._configure(self, qtile, bar)

Expand All @@ -121,24 +94,7 @@ def _configure(self, qtile, bar):
if self.update_interval:
self.timeout_add(self.update_interval, self.loop)

if self.check_connection_interval:
self.timeout_add(self.update_interval, self.check_connection)

def check_connection(self):
self.qtile.run_in_executor(self._check_internet).add_done_callback(self._check_connected)

def _check_internet(self):
with socket_context(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(self.internet_check_timeout)
try:
s.connect((self.internet_check_host, self.internet_check_port))
return True
except (TimeoutError, OSError):
return False

def _check_connected(self, result):
self.is_connected = result.result()
self.timeout_add(self.check_connection_interval, self.check_connection)
ConnectionCheckMixin._configure(self)

def loop(self):
self.timeout_add(self.update_interval, self.loop)
Expand Down

0 comments on commit 8a56f2b

Please sign in to comment.