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
     81 -    def set_timeline_in_readonly_mode(self):
     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
    118 -    def _timeline_path_doesnt_exists_yet(self):
    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