From 28c0a0d2d67a49d1e354671a802d6a786226d05e Mon Sep 17 00:00:00 2001 From: SGOrava Date: Wed, 19 Oct 2016 00:12:14 +0200 Subject: [PATCH] Initial commit --- .gitignore | 3 ++ LICENSE | 11 ++++++ StatusUi.py | 51 ++++++++++++++++++++++++++ rtc.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ rtcwake_gui.py | 71 ++++++++++++++++++++++++++++++++++++ 5 files changed, 234 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 StatusUi.py create mode 100644 rtc.py create mode 100644 rtcwake_gui.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fe967b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +*kdev4 +__pycache__ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3843f10 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright (c) 2016 Juraj Oravec + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + + The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + + Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + + This notice may not be removed or altered from any source distribution. diff --git a/StatusUi.py b/StatusUi.py new file mode 100644 index 0000000..31f9122 --- /dev/null +++ b/StatusUi.py @@ -0,0 +1,51 @@ +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +import rtc + +class StatusDevice(): + device = "" + + def __init__(self, page, device): + self.device = device + + self.vBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) + self.vBox.set_border_width(10) + + self.line1 = line("Device:", self.device.name) + self.line2 = line("Status:", "Off") + self.line3 = line("Wake up time:", "Now") + + page.pack_start(self.line1.box, True, True, 0) + page.pack_start(self.line2.box, True, True, 0) + page.pack_start(self.line3.box, True, True, 0) + + self.update() + + page.pack_start(self.vBox, True, True, 0) + + def update(self): + self.line1.value.set_text(self.device.name) + + active = "Off" + if self.device.devStatus["active"]: + active = "On" + self.line2.value.set_text(active) + + if self.device.devStatus["active"]: + if not self.line3.box.get_visible(): + self.line3.box.show() + + self.line3.value.set_text(str(self.device.devStatus["date"])) + elif self.line3.box.get_visible(): + self.line3.box.hide() + +class line(): + def __init__(self, name, value): + self.box = Gtk.Box(spacing=10) + self.label = Gtk.Label(name, halign=Gtk.Align.START) + self.value = Gtk.Label(value, halign=Gtk.Align.END) + + self.box.pack_start(self.label, True, True, 0) + self.box.pack_start(self.value, True, True, 0) diff --git a/rtc.py b/rtc.py new file mode 100644 index 0000000..a1840a3 --- /dev/null +++ b/rtc.py @@ -0,0 +1,98 @@ +from contextlib import contextmanager +from datetime import datetime +import locale +import os +import re +import shlex +import threading +from subprocess import Popen, PIPE + + +LOCALE_LOCK = threading.Lock() + +@contextmanager +def setlocale(name): + with LOCALE_LOCK: + saved = locale.setlocale(locale.LC_ALL) + try: + yield locale.setlocale(locale.LC_ALL, name) + finally: + locale.setlocale(locale.LC_ALL, saved) + + +class RtcDevice(): + name = "" + devStatus = { + "active": False, + "date": 0 + } + modes = [] + utc = False + + def __init__(self, name = ""): + self.name = name + + self.modes() + self.status() + + def modes(self): + cmd = "rtcwake --list-modes -d " + self.name + process = Popen(shlex.split(cmd), stdout=PIPE) + (output, err) = process.communicate() + exit_code = process.wait() + + self.modes = shlex.split(str(output)) + + def status(self): + cmd = "rtcwake -m show -d " + self.name + process = Popen(shlex.split(cmd), stdout=PIPE) + (output, err) = process.communicate() + exit_code = process.wait() + + self.formatStatus(str(output)) + + def formatStatus(self, message): + re1='.*?' # Non-greedy match on filler + re2='(?:[a-z][a-z]+)' # Uninteresting: word + re3='.*?' # Non-greedy match on filler + re4='((?:[a-z][a-z]+))' # Word 1 + re5='.*?' # Non-greedy match on filler + re6='((?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))' # Month 1 + re7='.*?' # Non-greedy match on filler + re8='((?:(?:[0-2]?\\d{1})|(?:[3][01]{1})))(?![\\d])' # Day 1 + re9='.*?' # Non-greedy match on filler + re10='((?:(?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9])(?::[0-5][0-9])?(?:\\s?(?:am|AM|pm|PM))?)' # HourMinuteSec 1 + re11='.*?' # Non-greedy match on filler + re12='((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3})))(?![\\d])' # Year 1 + + rg = re.compile(re1+re2+re3+re4,re.IGNORECASE|re.DOTALL) + m = rg.search(message) + if m: + active = m.group(1) + if active == "on": + self.devStatus["active"] = True + else: + self.devStatus["active"] = False + + if self.devStatus["active"]: + rgx = re.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12,re.IGNORECASE|re.DOTALL) + mx = rgx.search(message) + if mx: + month = mx.group(2) + day = mx.group(3) + if len(day) == 1: + day = "0" + day + time = mx.group(4) + year = mx.group(5) + with setlocale('C'): + self.devStatus["date"] = datetime.strptime(year + " " + month + " " + day + " " + time, "%Y %b %d %H:%M:%S") + +def getDevices(): + mainDir = "/sys/class/rtc" + if os.path.isdir(mainDir): + devices = [ name for name in os.listdir(mainDir) if os.path.isdir(os.path.join(mainDir, name)) ] + + if len(devices) > 0: + return devices + + return False diff --git a/rtcwake_gui.py b/rtcwake_gui.py new file mode 100644 index 0000000..6f50bc3 --- /dev/null +++ b/rtcwake_gui.py @@ -0,0 +1,71 @@ +#!/usr/bit/python + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +import rtc +import StatusUi + +def readFile(path): + file = open(path) + value = file.read() + file.close() + + return value.rstrip() + +class MyWindow(Gtk.Window): + devices = {} + statusBoxes = {} + + def __init__(self): + self.initRTC() + self.initUI() + + def initRTC(self): + for device in rtc.getDevices(): + self.devices[device] = rtc.RtcDevice(name=device) + + def initUI(self): + Gtk.Window.__init__(self, title="RTCwake GUI") + self.set_border_width(3) + + self.notebook = Gtk.Notebook() + self.add(self.notebook) + + self.pageStatus = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + self.pageStatus.set_border_width(10) + + for name, device in self.devices.items(): + self.statusBoxes[name] = StatusUi.StatusDevice(self.pageStatus, device) + + buttonRefresh = Gtk.Button.new_with_label("Refresh") + buttonRefresh.connect("clicked", self.buttonRefresh_on_click) + + self.pageStatus.pack_start(buttonRefresh, False, True, 0) + + self.notebook.append_page(self.pageStatus, Gtk.Label('Status')) + + + self.pageAbout = Gtk.Box() + self.pageAbout.set_border_width(10) + self.pageAbout.pack_start(Gtk.Label('Simple GUI for rtcwake.'), True, True, 0) + + self.notebook.append_page(self.pageAbout, Gtk.Label('About')) + + def initShow(self): + self.show_all() + + for name, device in self.devices.items(): + if not self.devices[name].devStatus["active"]: + self.statusBoxes[name].line3.box.hide() + + def buttonRefresh_on_click(self, button): + for name, device in self.devices.items(): + device.status() + self.statusBoxes[name].update() + +win = MyWindow() +win.connect("delete-event", Gtk.main_quit) +win.initShow() +Gtk.main()