Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1720846
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
8 KB
Subscribers
None
View Options
diff --git a/workrave-auto.py b/workrave-auto.py
new file mode 100755
--- /dev/null
+++ b/workrave-auto.py
@@ -0,0 +1,256 @@
+#!/usr/bin/env python
+
+from PyQt5.QtCore import QTimer, pyqtSignal, QObject, pyqtSlot, QCoreApplication, QMetaObject, Qt
+from dbus.mainloop.pyqt5 import DBusQtMainLoop
+import dbus
+import os
+import configparser
+import datetime
+import time
+import sys
+import signal
+
+def wk2int(day):
+ if day == 'mon':
+ return 0
+ elif day == 'tue':
+ return 1
+ elif day == 'wed':
+ return 2
+ elif day == 'thu':
+ return 3
+ elif day == 'fri':
+ return 4
+ elif day == 'sat':
+ return 5
+ elif day == 'sun':
+ return 6
+ else:
+ return -1
+
+def time2diff(now, time):
+ datetime.datetime.now()
+ to = time.split(':')
+ hr = int(to[0])
+ mi = 0
+ sec = 0
+ if len(to) == 2:
+ mi = int(to[1])
+ if len(to) == 3:
+ sec = int(to[2])
+ return datetime.datetime.combine(datetime.date.today(), datetime.time(hr, mi, sec)) - now
+
+class autoEntry:
+ def __init__(self, options):
+ self.options = options
+ self.next_action = options['default']
+ self.next_run = 0
+ self.in_interval = False
+ self.update()
+
+ def print_options(self):
+
+ print(self.options)
+
+ def update(self):
+ self.in_interval = False
+ now = datetime.datetime.now()
+ days = 0
+ starttime = time2diff(now, '00:00')
+ endtime = time2diff(now, '23:59')
+ if 'weekday' in self.options:
+ curr_day = now.weekday()
+ wanted_day = wk2int(self.options['weekday'])
+ if wanted_day == -1:
+ print('Error parsing weekday')
+ return -1
+ diff_day = wanted_day - curr_day
+ if diff_day < 0:
+ diff_day += 7
+ days = diff_day
+ if 'starttime' in self.options:
+ starttime = time2diff(now, self.options['starttime'])
+ if 'endtime' in self.options:
+ endtime = time2diff(now, self.options['endtime'])
+
+ if starttime.total_seconds() < 0 and endtime.total_seconds() < 0:
+ # After interval, if it's today, we need to add a week
+ if days == 0:
+ starttime = starttime + datetime.timedelta(days=7)
+ endtime = endtime + datetime.timedelta(days=7)
+ self.next_run = days * 24 * 60 * 60 + starttime.total_seconds()
+ self.next_action = self.options['mode']
+ elif starttime.total_seconds() < 0 and endtime.total_seconds() >= 0:
+ # Inside of interval
+ if days == 0:
+ self.next_action = self.options['default']
+ self.next_run = endtime.total_seconds()
+ self.in_interval = True
+ else:
+ self.next_run = days * 24 * 60 * 60 + starttime.total_seconds()
+ self.next_action = self.options['mode']
+ elif starttime.total_seconds() >= 0 and endtime.total_seconds() >= 0:
+ # Before interval
+ self.next_action = self.options['mode']
+ self.next_run = days * 24 * 60 * 60 + starttime.total_seconds()
+ else:
+ print('Invalid settings detected!')
+
+ def get_next_action(self):
+ self.update()
+ return self.next_action
+
+ def get_interval_action(self):
+ return self.options['mode']
+
+ def get_next_run(self):
+ self.update()
+ return int(self.next_run)
+
+ def is_in_interval(self):
+ self.update()
+ return self.in_interval
+
+
+def load_config(cfgFile):
+ config = configparser.ConfigParser()
+ config.read(cfgFile)
+ return config
+
+def save_config(config, cfgFile):
+ with open(cfgFile, 'w') as configFile:
+ config.write(configFile)
+
+def recreate_config(cfgFile):
+ config = configparser.ConfigParser()
+ config['general'] = {
+ 'mode' : 'normal'
+ }
+ config['entry1'] = {
+ 'name' : 'workrave',
+ 'mode' : 'suspended',
+ 'weekday' : 'wed',
+ 'starttime' : '07:00',
+ 'endtime' : '15:10'
+ }
+ config['entry2'] = {
+ 'name' : 'workrave',
+ 'mode' : 'suspended',
+ 'weekday' : 'thu',
+ 'starttime' : '07:00',
+ 'endtime' : '18:00'
+ }
+ save_config(config, cfgFile)
+
+class workraveManager(QObject):
+ def __init__(self, cfg):
+ QObject.__init__(self)
+ self.cfg = cfg
+ entries = self.parse_config(cfg)
+ self.entryobjects = []
+
+ self.default_mode = cfg['general']['mode']
+ self.timer = QTimer()
+ self.timer.setSingleShot(True)
+ self.timer.timeout.connect(self.run_action)
+
+ for entry in entries:
+ entryCfg = entries[entry]
+ entryCfg['default'] = self.default_mode
+ self.entryobjects.append(autoEntry(entryCfg))
+
+ @pyqtSlot()
+ def run_action(self):
+ print('Timer fired, about to run action: ' + self.action)
+ self.set_workrave_mode(self.action)
+ # This prevents the timer from firing several times
+ time.sleep(1000)
+ self.setup_timer()
+
+ def suspend_handler(self, suspended):
+ if suspended:
+ print('Going to sleep...')
+ self.timer.stop()
+ else:
+ print('Resuming, doing the recalculation math!')
+ self.startup_check()
+ self.setup_timer()
+
+ def init_dbus(self):
+
+ dbus_loop = DBusQtMainLoop(set_as_default=True)
+ self.system_bus = dbus.SystemBus(mainloop = dbus_loop)
+
+ manager_interface = 'org.freedesktop.login1.Manager'
+
+ self.system_bus.add_signal_receiver(self.suspend_handler, 'PrepareForSleep', manager_interface)
+
+ def parse_config(self, cfg):
+ ret = {}
+ for sec in cfg.sections():
+ if sec != 'general':
+ ret[sec] = {}
+ for key in cfg[sec]:
+ ret[sec][key] = cfg[sec][key]
+ return ret
+
+ def startup_check(self):
+ print('Startup check...')
+ in_interval = False
+ for entry in self.entryobjects:
+ if entry.is_in_interval():
+ action = entry.get_interval_action()
+ print('Interval currently running, setting mode: ' + action)
+ self.set_workrave_mode(action)
+ in_interval = True
+
+ if not in_interval:
+ print('Not in interval, setting default workrave mode: ' + self.default_mode)
+ self.set_workrave_mode(self.default_mode)
+
+ def set_workrave_mode(self, action):
+ wr = dbus.SessionBus().get_object('org.workrave.Workrave', '/org/workrave/Workrave/Core')
+ iface = dbus.Interface(wr, 'org.workrave.CoreInterface')
+ mode = iface.GetOperationMode()
+ if mode == action:
+ print('Mode already set, no action')
+ else:
+ iface.SetOperationMode(action)
+
+ @pyqtSlot()
+ def startup(self):
+ self.init_dbus()
+ self.startup_check()
+ self.setup_timer()
+
+ def setup_timer(self):
+ self.timer.stop()
+ next_action_list = []
+ next_run_list = []
+ for entry in self.entryobjects:
+ next_action_list.append(entry.get_next_action())
+ next_run_list.append(entry.get_next_run())
+ sleep_time = min(next_run_list)
+ self.action = next_action_list[next_run_list.index(sleep_time)]
+ print('Setting up timer for ' + str(sleep_time) + ' seconds and then running action: ' + self.action)
+ self.timer.start(sleep_time * 1000)
+
+def main():
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ cfgPath = os.path.expanduser("~") + "/.workrave-auto/"
+ if not os.path.isdir(cfgPath):
+ os.makedirs(cfgPath)
+ cfgFile = cfgPath + "config.ini"
+ if not os.path.exists(cfgFile):
+ recreate_config(cfgFile)
+
+ cfg = load_config(cfgFile)
+
+ m = workraveManager(cfg)
+ QMetaObject.invokeMethod(m, "startup", Qt.QueuedConnection)
+ app = QCoreApplication(sys.argv)
+ sys.exit(app.exec_())
+
+if __name__ == '__main__':
+ main()
+
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 1:34 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
529835
Default Alt Text
(8 KB)
Attached To
rWRA workrave-auto
Event Timeline
Log In to Comment