changeset 62:4891ed8d77d5

Implement nearest matching color search via cubic distance, and use it for finding best matching color from available event colors based on source calendar color.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 11 Jul 2016 13:37:26 +0300
parents 9fe4faa80687
children 6e38692e341f
files multimerge.py
diffstat 1 files changed, 73 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/multimerge.py	Mon Jul 11 12:04:08 2016 +0300
+++ b/multimerge.py	Mon Jul 11 13:37:26 2016 +0300
@@ -12,6 +12,7 @@
 import signal
 import re
 import codecs
+import math
 #import time
 #import datetime
 
@@ -132,6 +133,60 @@
             return False
     return True
 
+class GCMColor():
+    def __init__(self, src = None):
+        if src == None:
+            self.r = self.g = self.b = 0
+        elif isinstance(src, basestring):
+            if len(src) == 6:
+                self.r = int(src[0:2], 16)
+                self.g = int(src[2:4], 16)
+                self.b = int(src[4:6], 16)
+            elif len(src) == 7 and src[0] == "#":
+                self.r = int(src[1:3], 16)
+                self.g = int(src[3:5], 16)
+                self.b = int(src[6:7], 16)
+            else:
+                gcm_fatal("Expected hex-triplet string for GCMColor() initializer: {0}".format(src))
+        elif isinstance(src, GCMColor):
+            self.r = src.r
+            self.g = src.g
+            self.b = src.b
+        else:
+            gcm_fatal("Invalid initializer for GCMColor() object.")
+
+    def delta(self, other):
+        ctmp = GCMColor()
+        ctmp.r = other.r - self.r
+        ctmp.g = other.g - self.g
+        ctmp.b = other.b - self.b
+        return ctmp
+
+    def dist(self, other):
+        ctmp = self.delta(other)
+        return math.sqrt(ctmp.r * ctmp.r + ctmp.g * ctmp.g + ctmp.b * ctmp.b)
+
+
+def gcm_find_nearest_color(colors, cfind, maxdist):
+    c_fg = GCMColor(cfind["foreground"])
+    c_bg = GCMColor(cfind["background"])
+
+    bdist_fg = 99999999999
+    bdist_bg = 99999999999
+    best_fit = None
+    for id, col in colors.iteritems():
+        dist_fg = GCMColor(col["foreground"]).dist(c_fg)
+        dist_bg = GCMColor(col["background"]).dist(c_bg)
+        if dist_fg <= bdist_fg and dist_bg <= bdist_bg:
+            best_fit = id
+            bdist_fg = dist_fg
+            bdist_bg = dist_bg
+
+    if bdist_fg <= maxdist and bdist_bg <= maxdist:
+        return best_fit
+    else:
+        return None
+
 
 ##
 ## Class for handling configuration / settings
@@ -410,6 +465,13 @@
     gcm_debug(u"Target calendar '{0}' id {1}.".format(dst_calendar["summary"], dst_calendar["id"]))
 
 
+## Fetch colors
+try:
+    colors = service.colors().get().execute()
+except Exception as e:
+    gcm_fatal("Failed to fetch calendar color settings:\n\n{0}".format(str(e)))
+
+
 ## Now, we fetch and collect events
 gcm_debug(u"Fetching calendar events .. ")
 src_events = []
@@ -423,12 +485,21 @@
 #        orderBy="startTime",
         ).execute()
 
+    c_found = None
+    if "colorId" in calendar and calendar["colorId"] in colors["calendar"]:
+        gcm_debug("Calendar color: {0}".format(colors["calendar"][calendar["colorId"]]))
+        c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100)
+        if c_found:
+            gcm_debug("Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found]))
+        else:
+            gcm_debug("No matching event color found!")
+
     # Add events, if any, to main list
     events = gcm_generate_ids(result.get("items", []), calendar["id"])
     if events:
         for event in events:
-            if "colorId" in calendar:
-                event["colorId"] = calendar["colorId"]
+            if c_found != None:
+                event["colorId"] = c_found
             event["summary"] = u"[{1}] {0}".format(event["summary"], calendar["gcm_id"])
         src_events.extend(events)
         if cfg.debug: