1#!/usr/bin/env python3 2# coding: utf-8 3 4# Copyright (C) 2017, 2018 Robert Griesel 5# This program 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# This program 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 this program. If not, see <http://www.gnu.org/licenses/> 17 18import os.path 19import time 20 21import setzer.document.document_controller as document_controller 22import setzer.document.document_presenter as document_presenter 23import setzer.document.context_menu.context_menu as context_menu 24import setzer.document.document_switcher_item.document_switcher_item as document_switcher_item 25import setzer.document.document_viewgtk as document_view 26import setzer.document.search.search as search 27import setzer.document.shortcutsbar.shortcutsbar_presenter as shortcutsbar_presenter 28import setzer.document.source_buffer.source_buffer as source_buffer 29import setzer.document.spellchecker.spellchecker as spellchecker 30import setzer.document.gutter.gutter as gutter 31import setzer.document.line_numbers.line_numbers as line_numbers 32from setzer.helpers.observable import Observable 33from setzer.app.service_locator import ServiceLocator 34from setzer.helpers.timer import timer 35 36 37class Document(Observable): 38 39 def __init__(self): 40 Observable.__init__(self) 41 42 self.settings = ServiceLocator.get_settings() 43 44 self.displayname = '' 45 self.filename = None 46 self.save_date = None 47 self.deleted_on_disk_dialog_shown_after_last_save = False 48 self.last_activated = 0 49 self.dark_mode = False 50 self.is_root = False 51 self.root_is_set = False 52 53 self.source_buffer = source_buffer.SourceBuffer(self) 54 55 self.view = document_view.DocumentView(self, self.source_buffer.view) 56 self.gutter = gutter.Gutter(self, self.view) 57 self.search = search.Search(self, self.view, self.view.search_bar) 58 self.spellchecker = spellchecker.Spellchecker(self.view.source_view) 59 self.document_switcher_item = document_switcher_item.DocumentSwitcherItem(self) 60 self.context_menu = context_menu.ContextMenu(self, self.view) 61 self.shortcutsbar = shortcutsbar_presenter.ShortcutsbarPresenter(self, self.view) 62 63 self.presenter = document_presenter.DocumentPresenter(self, self.view) 64 self.controller = document_controller.DocumentController(self, self.view) 65 66 self.line_numbers = line_numbers.LineNumbers(self, self.view) 67 68 def set_search_text(self, search_text): 69 self.source_buffer.search_settings.set_search_text(search_text) 70 71 def set_dark_mode(self, dark_mode): 72 self.dark_mode = dark_mode 73 self.get_buffer().set_use_dark_scheme(dark_mode) 74 75 def get_buffer(self): 76 return self.source_buffer 77 78 def get_search_context(self): 79 return self.source_buffer.search_context 80 81 def set_filename(self, filename): 82 if filename == None: 83 self.filename = filename 84 else: 85 self.filename = os.path.realpath(filename) 86 self.add_change_code('filename_change', filename) 87 88 def get_filename(self): 89 return self.filename 90 91 def get_dirname(self): 92 if self.filename != None: 93 return os.path.dirname(self.filename) 94 else: 95 return '' 96 97 def get_displayname(self): 98 if self.filename != None: 99 return self.get_filename() 100 else: 101 return self.displayname 102 103 def set_displayname(self, displayname): 104 self.displayname = displayname 105 self.add_change_code('displayname_change') 106 107 def get_basename(self): 108 if self.filename != None: 109 return os.path.basename(self.filename) 110 else: 111 return self.displayname 112 113 def get_last_activated(self): 114 return self.last_activated 115 116 def set_last_activated(self, date): 117 self.last_activated = date 118 119 def get_modified(self): 120 return self.get_buffer().get_modified() 121 122 def populate_from_filename(self): 123 if self.filename == None: return False 124 if not os.path.isfile(self.filename): 125 self.set_filename(None) 126 return False 127 if self.get_buffer() == None: return False 128 129 with open(self.filename) as f: 130 text = f.read() 131 self.initially_set_text(text) 132 self.place_cursor(0, 0) 133 self.update_save_date() 134 return True 135 136 def save_to_disk(self): 137 if self.filename == None: return False 138 if self.get_buffer() == None: return False 139 140 text = self.get_text() 141 if text != None: 142 with open(self.filename, 'w') as f: 143 f.write(text) 144 self.update_save_date() 145 self.deleted_on_disk_dialog_shown_after_last_save = False 146 self.get_buffer().set_modified(False) 147 148 def update_save_date(self): 149 self.save_date = os.path.getmtime(self.filename) 150 151 def get_changed_on_disk(self): 152 return self.save_date <= os.path.getmtime(self.filename) - 0.001 153 154 def get_deleted_on_disk(self): 155 return not os.path.isfile(self.filename) 156 157 def initially_set_text(self, text): 158 self.get_buffer().initially_set_text(text) 159 160 #@timer 161 def get_text(self): 162 return self.get_buffer().get_all_text() 163 164 def get_text_after_offset(self, offset): 165 return self.get_buffer().get_text_after_offset(offset) 166 167 def get_selected_text(self): 168 return self.get_buffer().get_selected_text() 169 170 def get_line_at_cursor(self): 171 return self.get_buffer().get_line_at_cursor() 172 173 def get_char_at_cursor(self): 174 return self.get_buffer().get_char_at_cursor() 175 176 def get_line(self, line_number): 177 return self.get_buffer().get_line(line_number) 178 179 def get_current_line_number(self): 180 return self.get_buffer().get_current_line_number() 181 182 def is_empty(self): 183 return self.source_buffer.is_empty() 184 185 def place_cursor(self, line_number, offset=0): 186 self.get_buffer().place_cursor_and_scroll(line_number, offset) 187 188 def get_cursor_offset(self): 189 return self.get_buffer().get_cursor_offset() 190 191 def get_cursor_line_offset(self): 192 return self.get_buffer().get_cursor_line_offset() 193 194 def cursor_inside_latex_command_or_at_end(self): 195 current_word = self.get_latex_command_at_cursor() 196 if ServiceLocator.get_regex_object(r'\\(\w*(?:\*){0,1})').fullmatch(current_word): 197 return True 198 return False 199 200 def cursor_at_latex_command_end(self): 201 current_word = self.get_latex_command_at_cursor() 202 if ServiceLocator.get_regex_object(r'\\(\w*(?:\*){0,1})').fullmatch(current_word): 203 return self.get_buffer().cursor_ends_word() 204 return False 205 206 def insert_before_document_end(self, text): 207 self.get_buffer().insert_before_document_end(text) 208 209 def insert_text(self, line_number, offset, text, indent_lines=True): 210 self.get_buffer().insert_text(line_number, offset, text, indent_lines) 211 212 def insert_text_at_cursor(self, text, indent_lines=True, scroll=True, select_dot=True): 213 self.get_buffer().insert_text_at_cursor(text, indent_lines, scroll, select_dot) 214 215 def replace_range(self, offset, length, text, indent_lines=True, select_dot=True): 216 self.get_buffer().replace_range_by_offset_and_length(offset, length, text, indent_lines, select_dot) 217 218 def insert_before_after(self, before, after): 219 self.get_buffer().insert_before_after(before, after) 220 221 def add_backslash_with_space(self): 222 self.get_buffer().add_backslash_with_space() 223 224 def autoadd_latex_brackets(self, char): 225 self.get_buffer().autoadd_latex_brackets(char) 226 227 def undo(self): 228 self.get_buffer().undo() 229 230 def redo(self): 231 self.get_buffer().redo() 232 233 def cut(self): 234 self.get_buffer().cut() 235 236 def copy(self): 237 self.get_buffer().copy() 238 239 def paste(self): 240 self.get_buffer().paste() 241 242 def delete_selection(self): 243 self.get_buffer().delete_selection(True, True) 244 245 def select_all(self): 246 self.get_buffer().select_all() 247 248 249