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