Gnumed.timelinelib.wxgui.frames.mainframe.mainframecontroller

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
     82 -    def set_timeline_in_readonly_mode(self):
     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
    119 -    def _timeline_path_doesnt_exists_yet(self):
    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