Improved time display in menu

Fri, 26 Jan 2018 10:31:21 +0000

author
Tuomo Valkonen <tuomov@iki.fi>
date
Fri, 26 Jan 2018 10:31:21 +0000
changeset 72
e0e6043779e2
parent 71
a8a5ebb64e02
child 73
4f0e9cf8f230

Improved time display in menu

ui.py file | annotate | diff | comparison | revisions
--- a/ui.py	Fri Jan 26 10:31:08 2018 +0000
+++ b/ui.py	Fri Jan 26 10:31:21 2018 +0000
@@ -83,6 +83,7 @@
             return new
 
     info=None
+    this_need_reconstruct=None
 
     if not status.errors.ok():
         info=add_info(info, str(status.errors))
@@ -91,14 +92,24 @@
         # Operation scheduled
         when=status.when()
         now=time.time()
+
         if when<now:
             whenstr='overdue'
             info=''
         else:
+            tnow=datetime.datetime.fromtimestamp(now)
+            twhen=datetime.datetime.fromtimestamp(when)
+            tendtoday=twhen.replace(hour=23,minute=59,second=59)
+            tendtomorrow=tendtoday+datetime.timedelta(days=1)
             diff=datetime.timedelta(seconds=when-now)
-            if diff.days>0:
+
+            if twhen>tendtomorrow:
                 whenday=datetime.date.fromtimestamp(when)
-                whenstr='on %s' % whenday.isoformat()
+                whenstr='on %s' % twhen.date().isoformat()
+                this_need_reconstruct=tendtoday+datetime.timedelta(seconds=1)
+            elif diff.seconds>=12*60*60: # 12 hours
+                whenstr='tomorrow'
+                this_need_reconstruct=twhen-datetime.timedelta(hours=12)
             else:
                 twhen=time.localtime(when)
                 if twhen.tm_sec>30:
@@ -137,7 +148,7 @@
     else:
         title=status.name
 
-    return title, (status.state, status.errors)
+    return title, (status.state, status.errors), this_need_reconstruct
 
 class BorgendTray(rumps.App):
     def __init__(self, backups):
@@ -161,18 +172,21 @@
                 b.set_status_update_callback(cb)
                 self.statuses[index]=b.status()
 
-            menu, state=self.__rebuild_menu()
+            self.refresh_timer=None
+            self.refresh_timer_time=None
 
-            self.refresh_timer=None
+            menu, title=self.build_menu_and_timer()
 
-            super().__init__(trayname(state), menu=menu, quit_button=None)
+            super().__init__(title, menu=menu, quit_button=None)
+
 
     def __rebuild_menu(self):
         menu=[]
         state=(backup.State.INACTIVE, backup.Errors.OK)
+        need_reconstruct=None
         for index in range(len(self.backups)):
             b=self.backups[index]
-            title, this_state=make_title(self.statuses[index])
+            title, this_state, this_need_reconstruct=make_title(self.statuses[index])
             # Python closures suck dog's balls...
             # first and the last program I write in Python until somebody
             # fixes this brain damage
@@ -185,6 +199,12 @@
             menu.append(item)
             state=combine_state(state, this_state)
 
+            # Do we have to automatically update menu display?
+            if not need_reconstruct:
+                need_reconstruct=this_need_reconstruct
+            elif this_need_reconstruct:
+                need_reconstruct=min(need_reconstruct, this_need_reconstruct)
+
         menu_log=rumps.MenuItem("Show log", callback=lambda _: showlog())
         menu.append(menu_log)
 
@@ -192,24 +212,42 @@
             menu_quit=rumps.MenuItem("Quit...", callback=lambda _: self.quit())
             menu.append(menu_quit)
 
-        return menu, state
+        return menu, state, need_reconstruct
+
+    def build_menu_and_timer(self):
+        if self.refresh_timer:
+            self.refresh_timer.cancel()
+            self.refresh_timer=None
+            self.refresh_timer_time=None
+        logger.debug('Rebuilding menu')
+        menu, state, need_reconstruct=self.__rebuild_menu()
+        title=trayname(state)
+
+        if need_reconstruct:
+            when=time.mktime(need_reconstruct.timetuple())
+            delay=when-time.time()
+            self.refresh_timer=Timer(delay, self.refresh_ui)
+            self.refresh_timer_time=need_reconstruct
+            self.refresh_timer.start()
+
+        return menu, title
 
     def refresh_ui(self):
         with self.lock:
-            self.refresh_timer=None
-            logger.debug('Rebuilding menu')
-            menu, state=self.__rebuild_menu()
+            menu, title=self.build_menu_and_timer()
             self.menu.clear()
             self.menu.update(menu)
-            self.title=trayname(state)
+            self.title=title
 
     def __status_callback(self, index, status, errorlog=None):
         logger.debug('Status callback: %s' % str(status))
 
         with self.lock:
             self.statuses[index]=status
-            if self.refresh_timer==None:
+            if self.refresh_timer==None and not self.refresh_timer_time:
                 self.refresh_timer=Timer(refresh_interval, self.refresh_ui)
+                # refresh_timer_time is only set for "long-term timers"
+                self.refresh_timer_time=None
                 self.refresh_timer.start()
 
         if errorlog:

mercurial