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 self._main_frame.create_timeline_context_menu() 80 self._main_frame._create_main_menu_bar() 81 if path == ":numtutorial:": 82 self._main_frame._fit_all_events()
83
85 try: 86 self._timeline.set_readonly() 87 self._main_frame.set_timeline_readonly() 88 except: 89 pass
90
91 - def week_starts_on_monday(self):
92 return self._config.get_week_start() == "monday"
93
94 - def ok_to_edit(self):
95 if self._timeline is None: 96 return True 97 if self._timeline.is_read_only(): 98 return False 99 if self._locked(): 100 display_warning_message("The Timeline is Locked by someone else.\nTry again later") 101 return False 102 if self._timeline_path_doesnt_exists_yet(): 103 self._lock() 104 return True 105 last_changed = self._get_modification_date() 106 if last_changed > self._last_changed: 107 ack = get_user_ack( 108 _("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?")) 109 if ack: 110 self.reload_from_disk() 111 else: 112 self.set_timeline_in_readonly_mode() 113 return False 114 if last_changed > 0: 115 self._lock() 116 return True
117
118 - def start_slide_show(self, canvas):
119 open_slideshow_dialog(self._timeline, canvas)
120
122 return not os.path.exists(self._timelinepath)
123
124 - def edit_ends(self):
125 if self._the_lock_is_mine(): 126 self._last_changed = self._get_modification_date() 127 self._unlock()
128
129 - def timeline_is_readonly(self):
130 return self._timeline is not None and self._timeline.is_read_only()
131
132 - def _get_modification_date(self):
133 try: 134 return os.path.getmtime(self._timelinepath) 135 except: 136 return 0
137
138 - def reload_from_disk(self):
139 timeline_canvas = self._main_frame.main_panel.timeline_panel.timeline_canvas 140 vp = timeline_canvas.GetViewProperties() 141 displayed_period = vp.get_displayed_period() 142 self.open_timeline(self._timelinepath, save_current_data=False) 143 vp.set_displayed_period(displayed_period) 144 timeline_canvas.Redraw()
145
146 - def select_all(self):
147 timeline_canvas = self._main_frame.main_panel.timeline_panel.timeline_canvas 148 timeline_canvas.SelectAllEvents()
149
150 - def _lock(self):
151 fp = None 152 if not self._timeline.get_should_lock(): 153 return 154 try: 155 ts = self._get_timestamp_string() 156 path = self._get_lockpath() 157 fp = open(path, "w") 158 fp.write("%s\n%s\n%s" % (getpass.getuser(), ts, os.getpid())) 159 except Exception: 160 msg = _( 161 "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 162 display_warning_message(msg, self._main_frame) 163 raise LockedException() 164 finally: 165 if fp is not None: 166 fp.close()
167
168 - def _get_lockpath(self):
169 return "%s.lock" % self._timelinepath
170
171 - def _get_timestamp_string(self):
172 now = self._timeline.time_type.now() 173 return self._timeline.time_type.time_string(now)
174
175 - def _locked(self):
176 lockpath = self._get_lockpath() 177 return os.path.exists(lockpath)
178
179 - def _unlock(self):
180 lockpath = self._get_lockpath() 181 if os.path.exists(lockpath): 182 try: 183 os.remove(lockpath) 184 except WindowsError as ex: 185 if ex.winerror == 32: 186 self._report_other_process_uses_lockfile(lockpath) 187 else: 188 raise ex
189
190 - def _report_other_process_uses_lockfile(self, lockpath):
191 message = _("""The lockfile used to protect the timeline from concurrent updates is opened by another program or process. 192 This lockfile must be removed in order be able to continue editing the timeline! 193 The lockfile is found at: %s""") % lockpath 194 display_warning_message(message)
195
196 - def _the_lock_is_mine(self):
197 fp = None 198 try: 199 user = getpass.getuser() 200 pid = os.getpid() 201 lockpath = self._get_lockpath() 202 fp = open(lockpath, "r") 203 lines = fp.readlines() 204 lines = [line.strip() for line in lines] 205 return lines[0] == user and lines[2] == "%s" % pid 206 except: 207 return False 208 finally: 209 if fp is not None: 210 fp.close()
211