# HG changeset patch # User Matti Hamalainen # Date 1468233446 -10800 # Node ID 4891ed8d77d51ae49d5a5f9439a52a6f2712a847 # Parent 9fe4faa80687af70bc7781e7bf717da7a2077100 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. diff -r 9fe4faa80687 -r 4891ed8d77d5 multimerge.py --- 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: