Skip to content

Commit

Permalink
fix close confirmation, confirm closing of documents one by one
Browse files Browse the repository at this point in the history
  • Loading branch information
cvfosammmm committed Dec 8, 2023
1 parent bd03293 commit 28c3637
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 177 deletions.
41 changes: 32 additions & 9 deletions setzer.in
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,43 @@ class MainApplicationController(Adw.Application):
def on_quit_action(self, action=None, parameter=None):
self.save_quit()

def save_quit(self):
def save_quit(self, unsaved_documents=None):
for document in self.workspace.open_documents: DocumentSettings.save_document_state(document)

documents = self.workspace.get_unsaved_documents()
active_document = self.workspace.get_active_document()
if documents == None or active_document == None:
self.save_state_and_quit()

DialogLocator.get_dialog('close_confirmation').run({'unsaved_documents': documents}, self.save_quit_callback)
if unsaved_documents == None:
unsaved_documents = self.workspace.get_unsaved_documents()

def save_quit_callback(self, parameters, response):
if response['all_save_to_close']:
if len(unsaved_documents) > 0:
self.workspace.set_active_document(unsaved_documents[0])
dialog = DialogLocator.get_dialog('close_confirmation')
dialog.run({'unsaved_document': unsaved_documents[0], 'documents': unsaved_documents}, self.save_quit_callback)
else:
self.save_state_and_quit()

def save_quit_callback(self, parameters):
document = parameters['unsaved_document']
unsaved_documents = parameters['documents']

if parameters['response'] == 0:
unsaved_documents.remove(document)
self.save_quit(unsaved_documents)
elif parameters['response'] == 2:
document = parameters['unsaved_document']
if document.get_filename() == None:
DialogLocator.get_dialog('save_document').run(document, self.save_callback, parameters)
else:
document.save_to_disk()
unsaved_documents.remove(document)
self.save_quit(unsaved_documents)

def save_callback(self, parameters):
document = parameters['unsaved_document']
unsaved_documents = parameters['documents']

if not document.source_buffer.get_modified():
unsaved_documents.remove(document)
self.save_quit(unsaved_documents)

def save_state_and_quit(self):
self.save_window_state()
self.workspace.save_to_disk()
Expand Down
109 changes: 15 additions & 94 deletions setzer/dialogs/close_confirmation/close_confirmation.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,111 +24,32 @@


class CloseConfirmationDialog(object):
''' This dialog is asking users to save unsaved documents or discard their changes. '''

def __init__(self, main_window, workspace, save_document_dialog):
def __init__(self, main_window, workspace):
self.main_window = main_window
self.workspace = workspace
self.parameters = None
self.save_document_dialog = save_document_dialog

def run(self, parameters, callback):
if parameters['unsaved_documents'] == None: return
if parameters['unsaved_document'] == None: return

self.parameters = parameters
self.callback = callback

self.setup(self.parameters['unsaved_documents'])
self.setup(self.parameters['unsaved_document'])
self.view.choose(self.main_window, None, self.dialog_process_response)

self.view.present()
self.signal_connection_id = self.view.connect('response', self.process_response)

def process_response(self, view, response_id):
documents_not_save_to_close = list()
return_to_active_document = False
documents = self.parameters['unsaved_documents']

if response_id == Gtk.ResponseType.NO:
self.workspace.save_to_disk()
all_save_to_close = True
elif response_id == Gtk.ResponseType.YES:
selected_documents = list()
if len(documents) == 1:
selected_documents.append(documents[0])
else:
for i in range(0, len(documents)):
child = self.chooser.get_row_at_index(i)
if child.get_child().get_active():
number = int(child.get_child().get_name()[29:])
selected_documents.append(documents[number])
for document in selected_documents:
if document.get_filename() == None:
self.workspace.set_active_document(document)
return_to_active_document = True

if not self.save_document_dialog.run(document):
documents_not_save_to_close.append(document)
else:
document.save_to_disk()
if return_to_active_document == True:
self.workspace.set_active_document(document)

self.workspace.save_to_disk()
if len(documents_not_save_to_close) >= 1:
self.workspace.set_active_document(documents_not_save_to_close[-1])
all_save_to_close = False
else:
all_save_to_close = True
else:
all_save_to_close = False
documents_not_save_to_close = documents

self.close()
response = {'all_save_to_close': all_save_to_close, 'not_save_to_close_documents': documents_not_save_to_close}
self.callback(self.parameters, response)

def close(self):
self.view.close()
self.view.disconnect(self.signal_connection_id)
del(self.view)

def setup(self, documents):
self.view = Gtk.MessageDialog()
self.view.set_transient_for(self.main_window)
def setup(self, document):
self.view = Gtk.AlertDialog()
self.view.set_modal(True)
self.view.set_property('message-type', Gtk.MessageType.QUESTION)

if len(documents) == 1:
self.view.set_property('text', _('Document »{document}« has unsaved changes.').format(document=documents[0].get_displayname()))
self.view.set_property('secondary-text', _('If you close without saving, these changes will be lost.'))

if len(documents) >= 2:
self.view.set_property('text', _('There are {amount} documents with unsaved changes.\nSave changes before closing?').format(amount=str(len(documents))))
self.view.set_property('secondary-text', _('Select the documents you want to save:'))
self.view.get_message_area().get_first_child().set_xalign(0)

scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_size_request(446, 112)
scrolled_window.get_style_context().add_class('close-confirmation-list')
self.chooser = Gtk.ListBox()
self.chooser.set_selection_mode(Gtk.SelectionMode.NONE)
self.chooser.set_can_focus(False)
counter = 0
for document in documents:
button = Gtk.CheckButton.new_with_label(document.get_displayname())
button.set_name('document_to_save_checkbutton_' + str(counter))
button.set_active(True)
button.set_can_focus(False)
self.chooser.append(button)
counter += 1
scrolled_window.set_child(self.chooser)

secondary_text_label = Gtk.Label.new(_('If you close without saving, all changes will be lost.'))
message_area = self.view.get_message_area()
message_area.append(scrolled_window)
message_area.append(secondary_text_label)

self.view.add_buttons(_('Close _without Saving'), Gtk.ResponseType.NO, _('_Cancel'), Gtk.ResponseType.CANCEL, _('_Save'), Gtk.ResponseType.YES)
self.view.set_default_response(Gtk.ResponseType.YES)
self.view.set_message(_('Document »{document}« has unsaved changes.').format(document=document.get_displayname()))
self.view.set_detail(_('If you close without saving, these changes will be lost.'))
self.view.set_buttons([_('Close _without Saving'), _('_Cancel'), _('_Save')])
self.view.set_cancel_button(1)
self.view.set_default_button(2)

def dialog_process_response(self, dialog, result):
self.parameters['response'] = dialog.choose_finish(result)
self.callback(self.parameters)


72 changes: 36 additions & 36 deletions setzer/dialogs/dialog_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>

import setzer.dialogs.about.about as about_dialog
import setzer.dialogs.add_remove_packages.add_remove_packages as add_remove_packages
import setzer.dialogs.build_save.build_save as build_save_dialog
import setzer.dialogs.building_failed.building_failed as building_failed_dialog
import setzer.dialogs.close_confirmation.close_confirmation as close_confirmation_dialog
import setzer.dialogs.document_changed_on_disk.document_changed_on_disk as document_changed_on_disk_dialog
import setzer.dialogs.document_deleted_on_disk.document_deleted_on_disk as document_deleted_on_disk_dialog
import setzer.dialogs.document_wizard.document_wizard as document_wizard_dialog
import setzer.dialogs.include_bibtex_file.include_bibtex_file as include_bibtex_file_dialog
import setzer.dialogs.include_latex_file.include_latex_file as include_latex_file_dialog
import setzer.dialogs.interpreter_missing.interpreter_missing as interpreter_missing_dialog
import setzer.dialogs.keyboard_shortcuts.keyboard_shortcuts as keyboard_shortcuts_dialog
import setzer.dialogs.open_document.open_document as open_document_dialog
import setzer.dialogs.open_session.open_session as open_session_dialog
import setzer.dialogs.preferences.preferences as preferences_dialog
import setzer.dialogs.replace_confirmation.replace_confirmation as replace_confirmation_dialog
import setzer.dialogs.save_document.save_document as save_document_dialog
import setzer.dialogs.save_session.save_session as save_session_dialog
from setzer.dialogs.about.about import AboutDialog
from setzer.dialogs.add_remove_packages.add_remove_packages import AddRemovePackagesDialog
from setzer.dialogs.build_save.build_save import BuildSaveDialog
from setzer.dialogs.building_failed.building_failed import BuildingFailedDialog
from setzer.dialogs.close_confirmation.close_confirmation import CloseConfirmationDialog
from setzer.dialogs.document_changed_on_disk.document_changed_on_disk import DocumentChangedOnDiskDialog
from setzer.dialogs.document_deleted_on_disk.document_deleted_on_disk import DocumentDeletedOnDiskDialog
from setzer.dialogs.document_wizard.document_wizard import DocumentWizard
from setzer.dialogs.include_bibtex_file.include_bibtex_file import IncludeBibTeXFile
from setzer.dialogs.include_latex_file.include_latex_file import IncludeLaTeXFile
from setzer.dialogs.interpreter_missing.interpreter_missing import InterpreterMissingDialog
from setzer.dialogs.keyboard_shortcuts.keyboard_shortcuts import KeyboardShortcutsDialog
from setzer.dialogs.open_document.open_document import OpenDocumentDialog
from setzer.dialogs.open_session.open_session import OpenSessionDialog
from setzer.dialogs.preferences.preferences import PreferencesDialog
from setzer.dialogs.replace_confirmation.replace_confirmation import ReplaceConfirmationDialog
from setzer.dialogs.save_document.save_document import SaveDocumentDialog
from setzer.dialogs.save_session.save_session import SaveSessionDialog


class DialogLocator():
Expand All @@ -41,24 +41,24 @@ class DialogLocator():

def init_dialogs(main_window, workspace):
dialogs = dict()
dialogs['about'] = about_dialog.AboutDialog(main_window)
dialogs['add_remove_packages'] = add_remove_packages.AddRemovePackagesDialog(main_window)
dialogs['build_save'] = build_save_dialog.BuildSaveDialog(main_window, workspace)
dialogs['document_changed_on_disk'] = document_changed_on_disk_dialog.DocumentChangedOnDiskDialog(main_window)
dialogs['document_deleted_on_disk'] = document_deleted_on_disk_dialog.DocumentDeletedOnDiskDialog(main_window)
dialogs['document_wizard'] = document_wizard_dialog.DocumentWizard(main_window)
dialogs['include_bibtex_file'] = include_bibtex_file_dialog.IncludeBibTeXFile(main_window)
dialogs['include_latex_file'] = include_latex_file_dialog.IncludeLaTeXFile(main_window)
dialogs['keyboard_shortcuts'] = keyboard_shortcuts_dialog.KeyboardShortcutsDialog(main_window)
dialogs['open_document'] = open_document_dialog.OpenDocumentDialog(main_window, workspace)
dialogs['open_session'] = open_session_dialog.OpenSessionDialog(main_window, workspace)
dialogs['preferences'] = preferences_dialog.PreferencesDialog(main_window)
dialogs['replace_confirmation'] = replace_confirmation_dialog.ReplaceConfirmationDialog(main_window)
dialogs['save_document'] = save_document_dialog.SaveDocumentDialog(main_window, workspace)
dialogs['save_session'] = save_session_dialog.SaveSessionDialog(main_window, workspace)
dialogs['close_confirmation'] = close_confirmation_dialog.CloseConfirmationDialog(main_window, workspace, dialogs['save_document'])
dialogs['building_failed'] = building_failed_dialog.BuildingFailedDialog(main_window, dialogs['preferences'])
dialogs['interpreter_missing'] = interpreter_missing_dialog.InterpreterMissingDialog(main_window, dialogs['preferences'])
dialogs['about'] = AboutDialog(main_window)
dialogs['add_remove_packages'] = AddRemovePackagesDialog(main_window)
dialogs['build_save'] = BuildSaveDialog(main_window, workspace)
dialogs['document_changed_on_disk'] = DocumentChangedOnDiskDialog(main_window)
dialogs['document_deleted_on_disk'] = DocumentDeletedOnDiskDialog(main_window)
dialogs['document_wizard'] = DocumentWizard(main_window)
dialogs['include_bibtex_file'] = IncludeBibTeXFile(main_window)
dialogs['include_latex_file'] = IncludeLaTeXFile(main_window)
dialogs['keyboard_shortcuts'] = KeyboardShortcutsDialog(main_window)
dialogs['open_document'] = OpenDocumentDialog(main_window, workspace)
dialogs['open_session'] = OpenSessionDialog(main_window, workspace)
dialogs['preferences'] = PreferencesDialog(main_window)
dialogs['replace_confirmation'] = ReplaceConfirmationDialog(main_window)
dialogs['save_document'] = SaveDocumentDialog(main_window, workspace)
dialogs['save_session'] = SaveSessionDialog(main_window, workspace)
dialogs['close_confirmation'] = CloseConfirmationDialog(main_window, workspace)
dialogs['building_failed'] = BuildingFailedDialog(main_window, dialogs['preferences'])
dialogs['interpreter_missing'] = InterpreterMissingDialog(main_window, dialogs['preferences'])
DialogLocator.dialogs = dialogs

def get_dialog(dialog_type):
Expand Down
9 changes: 8 additions & 1 deletion setzer/dialogs/save_document/save_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ def __init__(self, main_window, workspace):
self.main_window = main_window
self.workspace = workspace
self.document = None
self.callback = None
self.arguments = None

def run(self, document):
def run(self, document, callback=None, arguments=None):
self.document = document
self.callback = callback
self.arguments = arguments
self.setup()
self.view.save(self.main_window, None, self.dialog_process_response)

Expand Down Expand Up @@ -64,4 +68,7 @@ def dialog_process_response(self, dialog, result):
self.document.save_to_disk()
self.workspace.update_recently_opened_document(filename)

if self.callback != None:
self.callback(self.arguments)


19 changes: 14 additions & 5 deletions setzer/popovers/document_switcher/document_switcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def on_button_release(self, event_controller, n_press, x, y):

self.popover_manager.popdown()
dialog = DialogLocator.get_dialog('close_confirmation')
dialog.run({'unsaved_documents': [document], 'document': document, 'previously_active_document': previously_active_document}, self.on_close_document_callback)
dialog.run({'unsaved_document': document, 'previously_active_document': previously_active_document}, self.on_close_document_callback)
return True
else:
if document == self.workspace.get_active_document():
Expand All @@ -200,10 +200,19 @@ def on_button_release(self, event_controller, n_press, x, y):
self.view.document_list.close_button_active = False
self.view.document_list.button_pressed = False

def on_close_document_callback(self, parameters, response):
not_save_to_close = response['not_save_to_close_documents']
if parameters['document'] not in not_save_to_close:
self.workspace.remove_document(parameters['document'])
def on_close_document_callback(self, parameters):
if parameters['response'] == 0:
self.workspace.remove_document(parameters['unsaved_document'])
elif parameters['response'] == 2:
document = parameters['unsaved_document']
if document.get_filename() == None:
self.workspace.set_active_document(document)
DialogLocator.get_dialog('save_document').run(document)
return
else:
document.save_to_disk()
self.workspace.remove_document(parameters['unsaved_document'])

if parameters['previously_active_document'] != None:
self.workspace.set_active_document(parameters['previously_active_document'])
self.popover_manager.popup_at_button('document_switcher')
Expand Down
32 changes: 18 additions & 14 deletions setzer/popovers/hamburger_menu/hamburger_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,24 +76,28 @@ def on_restore_session_click(self, button, parameter):
def restore_session_cb(self, filename):
if filename == None: return

documents = self.workspace.get_all_documents()
unsaved_documents = self.workspace.get_unsaved_documents()
if unsaved_documents:
if len(unsaved_documents) > 0:
self.workspace.set_active_document(unsaved_documents[0])
dialog = DialogLocator.get_dialog('close_confirmation')
dialog.run({'unsaved_documents': unsaved_documents, 'documents': documents, 'session_filename': filename}, self.close_confirmation_cb)
dialog.run({'unsaved_document': unsaved_documents[0], 'session_filename': filename}, self.close_confirmation_cb)
else:
if documents != None:
for document in documents:
self.workspace.remove_document(document)
documents = self.workspace.get_all_documents()
for document in documents:
self.workspace.remove_document(document)
self.workspace.load_documents_from_session_file(filename)

def close_confirmation_cb(self, parameters, response):
not_save_to_close_documents = response['not_save_to_close_documents']

if len(not_save_to_close_documents) == 0:
if parameters['documents'] != None:
for document in parameters['documents']:
self.workspace.remove_document(document)
self.workspace.load_documents_from_session_file(parameters['session_filename'])
def close_confirmation_cb(self, parameters):
document = parameters['unsaved_document']

if parameters['response'] == 0:
self.workspace.remove_document(document)
self.restore_session_cb(parameters['session_filename'])
elif parameters['response'] == 2:
if document.get_filename() == None:
DialogLocator.get_dialog('save_document').run(document, self.restore_session_cb, parameters['session_filename'])
else:
document.save_to_disk()
self.restore_session_cb(parameters['session_filename'])


Loading

0 comments on commit 28c3637

Please sign in to comment.