diff --git a/data/ui/RemarkableWindow.ui b/data/ui/RemarkableWindow.ui index 15783e9..7fd8ff3 100755 --- a/data/ui/RemarkableWindow.ui +++ b/data/ui/RemarkableWindow.ui @@ -206,6 +206,21 @@ False + + + True + False + List of recently opened files + Recent files + True + + + + + True + False + + True diff --git a/remarkable/RecentFilesMenu.py b/remarkable/RecentFilesMenu.py new file mode 100644 index 0000000..179334b --- /dev/null +++ b/remarkable/RecentFilesMenu.py @@ -0,0 +1,83 @@ +### BEGIN LICENSE +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +### END LICENSE + +import os +from gi.repository import Gtk + +class RecentFilesMenu(object): + def __init__(self, root_menu, files_list_path, max_files_num, file_choosen_callback = None): + self.root_menu = root_menu + self.files_list_path = files_list_path + self.max_files_num = max_files_num + self.file_choosen_callback = file_choosen_callback + + def __load_files_list(self): + if not os.path.isfile(self.files_list_path): + files_list = [] + else: + file = open(self.files_list_path) + files_list = eval(file.read()) + file.close() + + return files_list + + def __save_files_list(self, files_list): + file = open(self.files_list_path, 'w') + file.write(str(files_list)) + file.close() + + def __update_menu(self, files_list): + if len(files_list) > 0: + recent_submenu = Gtk.Menu() + for file in files_list: + title = file.split('/')[-1] + menu_item = Gtk.MenuItem(title) + menu_item.set_tooltip_text(file) + menu_item.connect('activate', self.on_file_selected, file) + + recent_submenu.append(menu_item) + + self.root_menu.set_submenu(recent_submenu) + self.root_menu.set_sensitive(True) + else: + self.root_menu.set_sensitive(False) + + def refresh(self): + files_list = self.__load_files_list() + self.__update_menu(files_list) + + def append_file(self, new_file_name): + files_list = self.__load_files_list() + + #remove file name from the list if it is already in the list to avoid duplications + if new_file_name in files_list: + files_list.remove(new_file_name) + + #append file name at the beginning + files_list.insert(0, new_file_name) + + if len(files_list) > self.max_files_num: + files_list = files_list[:self.max_files_num] + + self.__save_files_list(files_list) + + def on_file_selected(self, widget, file_path): + if self.file_choosen_callback != None: + self.file_choosen_callback(file_path) diff --git a/remarkable/RemarkableWindow.py b/remarkable/RemarkableWindow.py index 36d0df6..38138a4 100755 --- a/remarkable/RemarkableWindow.py +++ b/remarkable/RemarkableWindow.py @@ -40,6 +40,7 @@ import unicodedata import warnings from findBar import FindBar +from RecentFilesMenu import RecentFilesMenu #Check if gtkspellcheck is installed try: @@ -151,6 +152,12 @@ def finish_initializing(self, builder): # pylint: disable=E1002 match_case, whole_word, regex) self.findbar.set_text_view(self.text_view) + #Recent files + recent_menu = self.builder.get_object("menuitem_recent_files") + recent_path = os.path.join(self.path, "recent_files.list") + self.recent_files_menu = RecentFilesMenu(recent_menu, recent_path, 10, self.open_document) + self.recent_files_menu.refresh() + #Check if filename has been specified in terminal command if len(sys.argv) > 1: self.name = sys.argv[1] @@ -163,6 +170,7 @@ def finish_initializing(self, builder): # pylint: disable=E1002 self.text_buffer.set_modified(False) except: print(self.name + " does not exist, creating it") + self.recent_files_menu.append_file(self.name) self.update_status_bar(self) self.update_live_preview(self) @@ -395,9 +403,6 @@ def on_toolbutton_open_clicked(self, widget): Opens a file for editing / viewing """ def open(self, widget): - start, end = self.text_buffer.get_bounds() - text = self.text_buffer.get_text(start, end, False) - self.window.set_sensitive(False) chooser = Gtk.FileChooserDialog(title="Open File", action=Gtk.FileChooserAction.OPEN, buttons=( Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) @@ -405,26 +410,8 @@ def open(self, widget): response = chooser.run() if response == Gtk.ResponseType.OK: - # The user has selected a file - selected_file = chooser.get_filename() - - if len(text) == 0 and not self.text_buffer.get_modified(): - # Current file is empty. Load contents of selected file into this view - - self.text_buffer.begin_not_undoable_action() - file = open(selected_file, 'r') - text = file.read() - file.close() - self.name = chooser.get_filename() - self.text_buffer.set_text(text) - title = chooser.get_filename().split("/")[-1] - self.window.set_title("Remarkable: " + title) - self.text_buffer.set_modified(False) - self.text_buffer.end_not_undoable_action() - else: - # A file is already open. Load the selected file in a new Remarkable process - subprocess.Popen([sys.argv[0], selected_file]) - + self.open_document(chooser.get_filename()) + elif response == Gtk.ResponseType.CANCEL: # The user has clicked cancel pass @@ -432,6 +419,28 @@ def open(self, widget): chooser.destroy() self.window.set_sensitive(True) + def open_document(self, file_path): + start, end = self.text_buffer.get_bounds() + text = self.text_buffer.get_text(start, end, False) + + if len(text) == 0 and not self.text_buffer.get_modified(): + # Current file is empty. Load contents of selected file into this view + + self.text_buffer.begin_not_undoable_action() + file = open(file_path, 'r') + text = file.read() + file.close() + self.name = file_path + self.text_buffer.set_text(text) + title = file_path.split("/")[-1] + self.window.set_title("Remarkable: " + title) + self.text_buffer.set_modified(False) + self.text_buffer.end_not_undoable_action() + self.recent_files_menu.append_file(file_path) + else: + # A file is already open. Load the selected file in a new Remarkable process + subprocess.Popen([sys.argv[0], file_path]) + def check_for_save(self, widget): reply = False if self.text_buffer.get_modified(): @@ -489,6 +498,7 @@ def save_as(self, widget): self.text_buffer.set_modified(False) title = self.name.split("/")[-1] self.window.set_title("Remarkable: " + title) + self.recent_files_menu.append_file(self.name) elif response == Gtk.ResponseType.CANCEL: pass chooser.destroy()