From c9dd044c174a5c1ca1735d8c67abd614d60c7f0d Mon Sep 17 00:00:00 2001 From: Billy Date: Sun, 14 Apr 2024 00:52:35 +0530 Subject: [PATCH] feat: Move hash calculation code to `components/TextEditor` --- .../components/editors/texteditor/__init__.py | 28 ++++++++++++++++++- .../components/editors/texteditor/text.py | 4 +-- .../core/layout/base/content/editors/tab.py | 14 ---------- .../core/layout/base/content/editors/tabs.py | 23 ++++++--------- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/biscuit/core/components/editors/texteditor/__init__.py b/biscuit/core/components/editors/texteditor/__init__.py index a8e961d8..d6554dfa 100644 --- a/biscuit/core/components/editors/texteditor/__init__.py +++ b/biscuit/core/components/editors/texteditor/__init__.py @@ -1,6 +1,7 @@ from __future__ import annotations import tkinter as tk +from hashlib import md5 from tkinter.font import Font from biscuit.core.utils import Scrollbar @@ -24,7 +25,8 @@ def __init__(self, master, path=None, exists=True, language=None, minimalist=Fal self.editable = True self.run_command_value = None self.unsupported = False - + self.content_hash = '' + if not self.standalone: self.__buttons__ = [('sync', self.base.editorsmanager.reopen_active_editor),] @@ -81,6 +83,29 @@ def __init__(self, master, path=None, exists=True, language=None, minimalist=Fal if self.base.settings.config.auto_save_enabled: self.auto_save() + def file_loaded(self): + self.recalculate_content_hash() + self.event_generate("<>", when="tail") + + def recalculate_content_hash(self): + """ Recalculate the hash of the editor content """ + + self.content_hash = self.calculate_content_hash() + + def calculate_content_hash(self): + """ Calculate the hash of the editor content """ + + if self.exists and self.editable: + text = self.text.get_all_text() + return md5(text.encode()).hexdigest() + + @property + def unsaved_changes(self): + """ Check if the editor content has changed """ + + if self.editable: + return self.content_hash != self.calculate_content_hash() + def run_file(self, dedicated=False, external=False): if not self.run_command_value: self.base.notifications.show("No programs are configured to run this file.") @@ -137,6 +162,7 @@ def set_fontsize(self, size): def save(self, path=None): if self.editable: + self.recalculate_content_hash() self.text.save_file(path) def auto_save(self): diff --git a/biscuit/core/components/editors/texteditor/text.py b/biscuit/core/components/editors/texteditor/text.py index 6c8b846d..bc82e5c8 100644 --- a/biscuit/core/components/editors/texteditor/text.py +++ b/biscuit/core/components/editors/texteditor/text.py @@ -32,7 +32,7 @@ class Text(BaseText): def __init__(self, master: TextEditor, path: str=None, exists: bool=True, minimalist: bool=False, standalone: bool=False, language: str=None, *args, **kwargs) -> None: super().__init__(master, *args, **kwargs) - self.master = master + self.master: TextEditor = master self.path = path self.filename = os.path.basename(path) if path else None self.encoding = 'utf-8' @@ -901,7 +901,7 @@ def process_queue(self, eol: str=None): # If the queue is empty, schedule the next check after a short delay self.master.after(100, self.process_queue) - self.master.event_generate("<>", when="tail") + self.master.file_loaded() def custom_get(self, start, end): content = self.get(start, end) diff --git a/biscuit/core/layout/base/content/editors/tab.py b/biscuit/core/layout/base/content/editors/tab.py index fb70d51b..4b01a000 100644 --- a/biscuit/core/layout/base/content/editors/tab.py +++ b/biscuit/core/layout/base/content/editors/tab.py @@ -8,7 +8,6 @@ import os import tkinter as tk -from hashlib import md5 from biscuit.core.utils import Frame, Icon, IconButton @@ -38,8 +37,6 @@ def __init__(self, master: Tabs, editor: Editor, *args, **kwargs) -> None: self.bind("", self.on_hover) self.bind("", self.off_hover) - self.content_hash = "" - def close(self, *_) -> None: self.master.close_tab(self) @@ -78,14 +75,3 @@ def select(self, *_) -> None: self.apply_color(self.hbg) self.closebtn.config(activeforeground=self.hfg) self.selected = True - self.content_hash = self.calculate_content_hash() - - def calculate_content_hash(self): - """ Calculate the hash of the editor content """ - - if self.editor.content: # Welcome editor returns a None value - - # Cannot get contents when using self.editor.content.get(..), - # so had to directly call get() - editor_contents = self.editor.content.text.get(index1="1.0", index2="end-1c") - return md5(editor_contents.encode()).hexdigest() diff --git a/biscuit/core/layout/base/content/editors/tabs.py b/biscuit/core/layout/base/content/editors/tabs.py index cfaf7e82..f7e19b8c 100644 --- a/biscuit/core/layout/base/content/editors/tabs.py +++ b/biscuit/core/layout/base/content/editors/tabs.py @@ -34,12 +34,15 @@ def close_active_tab(self) -> None: self.close_tab(self.active_tab) def close_tab(self, tab: Tab) -> None: - - if self.content_has_changed(): - if askyesno("Save File", f"You have unsaved changes. Do you want to save {tab.editor.filename}"): - filepath = os.path.join(self.base.active_directory, tab.editor.filename) - tab.editor.save(filepath) - print(f"Saved changes to {filepath}.") + if e := tab.editor: + # checking if its a text editor + if e.content and e.content.editable and e.content.unsaved_changes: + if askyesno(f"Unsaved changes", f"Do you want to save the changes you made to {tab.editor.filename}"): + if e.exists: + e.save() + else: + self.base.commands.save_as() + print(f"Saved changes to {e.path}.") try: i = self.tabs.index(tab) @@ -96,11 +99,3 @@ def switch_tabs(self, path) -> None: if tab.editor.path == path: tab.select() return tab.editor - - def content_has_changed(self): - current_file_hash = self.active_tab.calculate_content_hash() - if current_file_hash == self.active_tab.content_hash: - # No changes has been made in the editor - return False - else: - return True \ No newline at end of file