Package Gnumed :: Package timelinelib :: Package canvas :: Package data :: Module eras
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.canvas.data.eras

  1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg 
  2  # 
  3  # This file is part of Timeline. 
  4  # 
  5  # Timeline is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Timeline is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>. 
 17   
 18   
 19  from timelinelib.canvas.data.timeperiod import TimePeriod 
 20   
 21   
22 -class Eras(object):
23 """ 24 The list of all eras defined for a timeline. 25 26 Contains function for cloning of the whole list which is a 27 necessary operation for undo/redo operations. 28 """ 29
30 - def __init__(self, now_func, eras=None):
31 self.now_func = now_func 32 if eras is None: 33 self._eras = [] 34 else: 35 self._eras = eras
36
37 - def get_all(self):
38 return sorted(self._eras)
39
40 - def get_all_periods(self):
41 42 def get_key(e): 43 return e.get_time_period().start_time
44 45 def merge_colors(c1, c2): 46 return ( 47 (c1[0] + c2[0]) // 2, 48 (c1[1] + c2[1]) // 2, 49 (c1[2] + c2[2]) // 2 50 )
51 52 def create_overlapping_era(e0, e1, start, end): 53 era = e1.duplicate() 54 era.set_time_period(TimePeriod(start, end)) 55 era.set_color(merge_colors(e0.get_color(), e1.get_color())) 56 era.set_name("%s + %s" % (e0.get_name(), e1.get_name())) 57 return era 58 59 def get_start_and_end_times(e0, e1): 60 e0start = e0.get_time_period().start_time 61 e0end = e0.get_time_period().end_time 62 e1start = e1.get_time_period().start_time 63 e1end = e1.get_time_period().end_time 64 return e0start, e0end, e1start, e1end 65 66 def return_era_for_overlapping_type_1(e0, e1): 67 e0start, e0end, e1start, e1end = get_start_and_end_times(e0, e1) 68 era = create_overlapping_era(e0, e1, e1start, e0end) 69 e0.set_time_period(TimePeriod(e0start, e1start)) 70 e1.set_time_period(TimePeriod(e0end, e1end)) 71 return era 72 73 def return_era_for_overlapping_type_2(e0, e1): 74 e0start, e0end, _, e1end = get_start_and_end_times(e0, e1) 75 era = create_overlapping_era(e0, e1, e0start, e0end) 76 self.all_eras.remove(e0) 77 e1.set_time_period(TimePeriod(e0end, e1end)) 78 return era 79 80 def return_era_for_overlapping_type_3(e0, e1): 81 return return_era_for_overlapping_type_2(e1, e0) 82 83 def return_era_for_overlapping_type_4(e0, e1): 84 _, _, e1start, e1end = get_start_and_end_times(e0, e1) 85 era = create_overlapping_era(e0, e1, e1start, e1end) 86 self.all_eras.remove(e0) 87 self.all_eras.remove(e1) 88 return era 89 90 def return_era_for_overlapping_type_5(e0, e1): 91 e0start, _, e1start, e1end = get_start_and_end_times(e0, e1) 92 era = create_overlapping_era(e0, e1, e1start, e1end) 93 e0.set_time_period(TimePeriod(e0start, e1start)) 94 self.all_eras.remove(e1) 95 return era 96 97 def return_era_for_overlapping_type_6(e0, e1): 98 e0start, e0end, e1start, e1end = get_start_and_end_times(e0, e1) 99 era = create_overlapping_era(e0, e1, e1start, e1end) 100 e0.set_time_period(TimePeriod(e0start, e1start)) 101 e1.set_time_period(TimePeriod(e1end, e0end)) 102 e1.set_name(e0.get_name()) 103 e1.set_color(e0.get_color()) 104 return era 105 106 def clone_all_eras(): 107 return [e.duplicate() for e in self.get_all()] 108 109 overlap_func = (None, 110 return_era_for_overlapping_type_1, 111 return_era_for_overlapping_type_2, 112 return_era_for_overlapping_type_3, 113 return_era_for_overlapping_type_4, 114 return_era_for_overlapping_type_5, 115 return_era_for_overlapping_type_6) 116 117 def create_overlapping_era_and_remove_hidden_eras(): 118 """ 119 self.all_eras is always sorted by Era start time. 120 This method finds the first pair of Era's that overlaps. 121 If such a pair is found, a overlapping Era is created and added 122 to the the self.all_eras list. If any or both of the original 123 Era's are hidden by the overlapping Era, they are removed from 124 the self.all_eras list. 125 When one overlapping pair has been found and processed the 126 function returns False, after updating the self.all_eras list 127 If no overlapping pairs of Era's are found the function retuns 128 True. 129 """ 130 e0 = self.all_eras[0] 131 for e1 in self.all_eras[1:]: 132 strategy = e0.overlapping(e1) 133 if strategy > 0: 134 self.all_eras.append(overlap_func[strategy](e0, e1)) 135 self.all_eras = sorted(self.all_eras, key=get_key) 136 return False 137 else: 138 e0 = e1 139 return True 140 141 def adjust_all_eras_for_ends_today(): 142 for era in self.all_eras: 143 if era.ends_today(): 144 era.set_time_period(TimePeriod(era.get_time_period().start_time, self.now_func())) 145 146 def remove_eras_with_no_duration(): 147 self.all_eras = [e for e in self.all_eras if e.is_period()] 148 149 self.all_eras = clone_all_eras() 150 adjust_all_eras_for_ends_today() 151 remove_eras_with_no_duration() 152 if self.all_eras == []: 153 return [] 154 while True: 155 if len(self.all_eras) > 0: 156 done = create_overlapping_era_and_remove_hidden_eras() 157 else: 158 done = True 159 if done: 160 return self.all_eras 161