Package Gnumed :: Package timelinelib :: Package wxgui :: Package frames :: Package mainframe :: Module mainframecontroller
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.wxgui.frames.mainframe.mainframecontroller

  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  import getpass 
 20  import os 
 21   
 22  from timelinelib.wxgui.dialogs.slideshow.view import open_slideshow_dialog 
 23  from timelinelib.wxgui.utils import display_error_message 
 24  from timelinelib.wxgui.utils import display_warning_message 
 25  from timelinelib.wxgui.utils import get_user_ack 
 26   
 27   
28 -class LockedException(Exception):
29 pass
30 31
32 -class MainFrameController(object):
33
34 - def __init__(self, main_frame, db_open_fn, config):
35 self._main_frame = main_frame 36 self._db_open_fn = db_open_fn 37 self._config = config 38 self._timeline = None
39
40 - def on_started(self, application_arguments):
41 if application_arguments.has_files(): 42 self.open_or_create_timeline(application_arguments.get_first_file()) 43 elif self._config.has_recently_opened_files(): 44 self.open_timeline_if_exists(self._config.get_latest_recently_opened_file())
45
46 - def open_or_create_timeline(self, path):
47 self.open_timeline(path)
48
49 - def open_timeline_if_exists(self, path):
50 if os.path.exists(path): 51 self.open_timeline(path) 52 else: 53 display_error_message(_("File '%s' does not exist.") % path, self._main_frame)
54
55 - def open_gregorian_tutorial_timeline(self, *args, **kwargs):
56 self.open_timeline(":tutorial:")
57
58 - def open_numeric_tutorial_timeline(self, *args, **kwargs):
59 self.open_timeline(":numtutorial:")
60
61 - def open_timeline(self, path, timetype=None, save_current_data=True):
62 if save_current_data: 63 self._main_frame.save_current_timeline_data() 64 try: 65 self._timeline = self._db_open_fn(path, timetype=timetype) 66 except Exception as e: 67 self._main_frame.DisplayErrorMessage( 68 _("Unable to open timeline '%s'.") % path + "\n\n" + str(e) 69 ) 70 else: 71 self._config.append_recently_opened(path) 72 self._main_frame.update_open_recent_submenu() 73 self._timeline.path = path 74 self._main_frame.display_timeline(self._timeline) 75 self._timelinepath = path 76 self._last_changed = self._get_modification_date() 77 self._main_frame.update_navigation_menu_items() 78 self._main_frame.enable_disable_menus() 79 if path == ":numtutorial:": 80 self._main_frame._fit_all_events()
81
83 try: 84 self._timeline.set_readonly() 85 self._main_frame.set_timeline_readonly() 86 except: 87 pass
88
89 - def week_starts_on_monday(self):
90 return self._config.get_week_start() == "monday"
91
92 - def ok_to_edit(self):
93 if self._timeline is None: 94 return True 95 if self._timeline.is_read_only(): 96 return False 97 if self._locked(): 98 display_warning_message("The Timeline is Locked by someone else.\nTry again later") 99 return False 100 if self._timeline_path_doesnt_exists_yet(): 101 self._lock() 102 return True 103 last_changed = self._get_modification_date() 104 if last_changed > self._last_changed: 105 ack = get_user_ack( 106 _("Someoneelse has changed the Timeline.\nYou have two choices!\n 1. Set Timeline in Read-Only mode.\n 2. Synchronize Timeline.\n\nDo you want to Synchronize?")) 107 if ack: 108 self.reload_from_disk() 109 else: 110 self.set_timeline_in_readonly_mode() 111 return False 112 if last_changed > 0: 113 self._lock() 114 return True
115
116 - def start_slide_show(self, canvas):
117 open_slideshow_dialog(self._timeline, canvas)
118
120 return not os.path.exists(self._timelinepath)
121
122 - def edit_ends(self):
123 if self._the_lock_is_mine(): 124 self._last_changed = self._get_modification_date() 125 self._unlock()
126
127 - def timeline_is_readonly(self):
128 return self._timeline is not None and self._timeline.is_read_only()
129
130 - def _get_modification_date(self):
131 try: 132 return os.path.getmtime(self._timelinepath) 133 except: 134 return 0
135
136 - def reload_from_disk(self):
137 timeline_canvas = self._main_frame.main_panel.timeline_panel.timeline_canvas 138 vp = timeline_canvas.GetViewProperties() 139 displayed_period = vp.get_displayed_period() 140 self.open_timeline(self._timelinepath, save_current_data=False) 141 vp.set_displayed_period(displayed_period) 142 timeline_canvas.Redraw()
143
144 - def select_all(self):
145 timeline_canvas = self._main_frame.main_panel.timeline_panel.timeline_canvas 146 timeline_canvas.SelectAllEvents()
147
148 - def _lock(self):
149 fp = None 150 if not self._timeline.get_should_lock(): 151 return 152 try: 153 ts = self._get_timestamp_string() 154 path = self._get_lockpath() 155 fp = open(path, "w") 156 fp.write("%s\n%s\n%s" % (getpass.getuser(), ts, os.getpid())) 157 except Exception: 158 msg = _( 159 "Unable to take lock on %s\nThis means you can't edit the timeline.\nCheck if you have write access to this directory.") % self._timelinepath 160 display_warning_message(msg, self._main_frame) 161 raise LockedException() 162 finally: 163 if fp is not None: 164 fp.close()
165
166 - def _get_lockpath(self):
167 return "%s.lock" % self._timelinepath
168
169 - def _get_timestamp_string(self):
170 now = self._timeline.time_type.now() 171 return self._timeline.time_type.time_string(now)
172
173 - def _locked(self):
174 lockpath = self._get_lockpath() 175 return os.path.exists(lockpath)
176
177 - def _unlock(self):
178 lockpath = self._get_lockpath() 179 if os.path.exists(lockpath): 180 try: 181 os.remove(lockpath) 182 except WindowsError as ex: 183 if ex.winerror == 32: 184 self._report_other_process_uses_lockfile(lockpath) 185 else: 186 raise ex
187
188 - def _report_other_process_uses_lockfile(self, lockpath):
189 message = _("""The lockfile used to protect the timeline from concurrent updates is opened by another program or process. 190 This lockfile must be removed in order be able to continue editing the timeline! 191 The lockfile is found at: %s""") % lockpath 192 display_warning_message(message)
193
194 - def _the_lock_is_mine(self):
195 fp = None 196 try: 197 user = getpass.getuser() 198 pid = os.getpid() 199 lockpath = self._get_lockpath() 200 fp = open(lockpath, "r") 201 lines = fp.readlines() 202 lines = [line.strip() for line in lines] 203 return lines[0] == user and lines[2] == "%s" % pid 204 except: 205 return False 206 finally: 207 if fp is not None: 208 fp.close()
209