mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Remove per editor saves as they cannot be implemented robustly
Also, show busy cursor when running any potentially long winded job. Now that we have gotten rid of per editor saves, we track sync status of editor with container, instead, and when performing any task that operates on the container directly, sync open editors to the container. This avoids the confusing warning about modified files.
This commit is contained in:
parent
5a5b93f876
commit
b91fb7b502
@ -8,7 +8,7 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
|
|
||||||
import tempfile, shutil, sys, os
|
import tempfile, shutil, sys, os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from functools import partial
|
from functools import partial, wraps
|
||||||
|
|
||||||
from PyQt4.Qt import (
|
from PyQt4.Qt import (
|
||||||
QObject, QApplication, QDialog, QGridLayout, QLabel, QSize, Qt, QCursor,
|
QObject, QApplication, QDialog, QGridLayout, QLabel, QSize, Qt, QCursor,
|
||||||
@ -38,6 +38,21 @@ def get_container(*args, **kwargs):
|
|||||||
kwargs['tweak_mode'] = True
|
kwargs['tweak_mode'] = True
|
||||||
return _gc(*args, **kwargs)
|
return _gc(*args, **kwargs)
|
||||||
|
|
||||||
|
class BusyCursor(object):
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
||||||
|
|
||||||
|
def __exit__(self, *args):
|
||||||
|
QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
|
def in_thread_job(func):
|
||||||
|
@wraps(func)
|
||||||
|
def ans(*args, **kwargs):
|
||||||
|
with BusyCursor():
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return ans
|
||||||
|
|
||||||
class Boss(QObject):
|
class Boss(QObject):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
@ -73,8 +88,7 @@ class Boss(QObject):
|
|||||||
ed.apply_settings()
|
ed.apply_settings()
|
||||||
|
|
||||||
def mark_requested(self, name, action):
|
def mark_requested(self, name, action):
|
||||||
if not self.check_opf_dirtied():
|
self.commit_dirty_opf()
|
||||||
return
|
|
||||||
c = current_container()
|
c = current_container()
|
||||||
if action == 'cover':
|
if action == 'cover':
|
||||||
mark_as_cover(current_container(), name)
|
mark_as_cover(current_container(), name)
|
||||||
@ -161,7 +175,7 @@ class Boss(QObject):
|
|||||||
for name, ed in tuple(editors.iteritems()):
|
for name, ed in tuple(editors.iteritems()):
|
||||||
if c.has_name(name):
|
if c.has_name(name):
|
||||||
ed.replace_data(c.raw_data(name))
|
ed.replace_data(c.raw_data(name))
|
||||||
ed.is_modified = False
|
ed.is_synced_to_container = True
|
||||||
else:
|
else:
|
||||||
self.close_editor(name)
|
self.close_editor(name)
|
||||||
|
|
||||||
@ -172,9 +186,9 @@ class Boss(QObject):
|
|||||||
self.update_editors_from_container()
|
self.update_editors_from_container()
|
||||||
self.set_modified()
|
self.set_modified()
|
||||||
|
|
||||||
|
@in_thread_job
|
||||||
def delete_requested(self, spine_items, other_items):
|
def delete_requested(self, spine_items, other_items):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
|
||||||
self.add_savepoint(_('Delete files'))
|
self.add_savepoint(_('Delete files'))
|
||||||
c = current_container()
|
c = current_container()
|
||||||
c.remove_from_spine(spine_items)
|
c.remove_from_spine(spine_items)
|
||||||
@ -188,17 +202,13 @@ class Boss(QObject):
|
|||||||
if not editors:
|
if not editors:
|
||||||
self.gui.preview.clear()
|
self.gui.preview.clear()
|
||||||
|
|
||||||
def check_opf_dirtied(self):
|
def commit_dirty_opf(self):
|
||||||
c = current_container()
|
c = current_container()
|
||||||
if c.opf_name in editors and editors[c.opf_name].is_modified:
|
if c.opf_name in editors and not editors[c.opf_name].is_synced_to_container:
|
||||||
return question_dialog(self.gui, _('Unsaved changes'), _(
|
self.commit_editor_to_container(c.opf_name)
|
||||||
'You have unsaved changes in %s. If you proceed,'
|
|
||||||
' you will lose them. Proceed anyway?') % c.opf_name)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def reorder_spine(self, items):
|
def reorder_spine(self, items):
|
||||||
if not self.check_opf_dirtied():
|
self.commit_dirty_opf()
|
||||||
return
|
|
||||||
self.add_savepoint(_('Re-order text'))
|
self.add_savepoint(_('Re-order text'))
|
||||||
c = current_container()
|
c = current_container()
|
||||||
c.set_spine(items)
|
c.set_spine(items)
|
||||||
@ -213,8 +223,7 @@ class Boss(QObject):
|
|||||||
'You must first open a book to tweak, before trying to create new files'
|
'You must first open a book to tweak, before trying to create new files'
|
||||||
' in it.'), show=True)
|
' in it.'), show=True)
|
||||||
|
|
||||||
if not self.check_opf_dirtied():
|
self.commit_dirty_opf()
|
||||||
return
|
|
||||||
d = NewFileDialog(self.gui)
|
d = NewFileDialog(self.gui)
|
||||||
if d.exec_() != d.Accepted:
|
if d.exec_() != d.Accepted:
|
||||||
return
|
return
|
||||||
@ -241,8 +250,7 @@ class Boss(QObject):
|
|||||||
self.edit_file(d.file_name, syntax)
|
self.edit_file(d.file_name, syntax)
|
||||||
|
|
||||||
def edit_toc(self):
|
def edit_toc(self):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
|
||||||
self.add_savepoint(_('Edit Table of Contents'))
|
self.add_savepoint(_('Edit Table of Contents'))
|
||||||
d = TOCEditor(title=self.current_metadata.title, parent=self.gui)
|
d = TOCEditor(title=self.current_metadata.title, parent=self.gui)
|
||||||
if d.exec_() != d.Accepted:
|
if d.exec_() != d.Accepted:
|
||||||
@ -251,17 +259,17 @@ class Boss(QObject):
|
|||||||
self.update_editors_from_container()
|
self.update_editors_from_container()
|
||||||
|
|
||||||
def polish(self, action, name):
|
def polish(self, action, name):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
with BusyCursor():
|
||||||
self.add_savepoint(name)
|
self.add_savepoint(name)
|
||||||
try:
|
try:
|
||||||
report = tweak_polish(current_container(), {action:True})
|
report = tweak_polish(current_container(), {action:True})
|
||||||
except:
|
except:
|
||||||
self.rewind_savepoint()
|
self.rewind_savepoint()
|
||||||
raise
|
raise
|
||||||
self.apply_container_update_to_gui()
|
self.apply_container_update_to_gui()
|
||||||
from calibre.ebooks.markdown import markdown
|
from calibre.ebooks.markdown import markdown
|
||||||
report = markdown('# %s\n\n'%self.current_metadata.title + '\n\n'.join(report), output_format='html4')
|
report = markdown('# %s\n\n'%self.current_metadata.title + '\n\n'.join(report), output_format='html4')
|
||||||
d = QDialog(self.gui)
|
d = QDialog(self.gui)
|
||||||
d.l = QVBoxLayout()
|
d.l = QVBoxLayout()
|
||||||
d.setLayout(d.l)
|
d.setLayout(d.l)
|
||||||
@ -277,8 +285,7 @@ class Boss(QObject):
|
|||||||
|
|
||||||
# Renaming {{{
|
# Renaming {{{
|
||||||
def rename_requested(self, oldname, newname):
|
def rename_requested(self, oldname, newname):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
|
||||||
if guess_type(oldname) != guess_type(newname):
|
if guess_type(oldname) != guess_type(newname):
|
||||||
args = os.path.splitext(oldname) + os.path.splitext(newname)
|
args = os.path.splitext(oldname) + os.path.splitext(newname)
|
||||||
if not confirm(
|
if not confirm(
|
||||||
@ -357,16 +364,12 @@ class Boss(QObject):
|
|||||||
if hasattr(ed, 'fix_html'):
|
if hasattr(ed, 'fix_html'):
|
||||||
ed.fix_html()
|
ed.fix_html()
|
||||||
else:
|
else:
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
with BusyCursor():
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
||||||
try:
|
|
||||||
self.add_savepoint(_('Fix HTML'))
|
self.add_savepoint(_('Fix HTML'))
|
||||||
fix_all_html(current_container())
|
fix_all_html(current_container())
|
||||||
self.update_editors_from_container()
|
self.update_editors_from_container()
|
||||||
self.set_modified()
|
self.set_modified()
|
||||||
finally:
|
|
||||||
QApplication.restoreOverrideCursor()
|
|
||||||
|
|
||||||
def pretty_print(self, current):
|
def pretty_print(self, current):
|
||||||
if current:
|
if current:
|
||||||
@ -376,16 +379,12 @@ class Boss(QObject):
|
|||||||
break
|
break
|
||||||
ed.pretty_print(name)
|
ed.pretty_print(name)
|
||||||
else:
|
else:
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
with BusyCursor():
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
||||||
try:
|
|
||||||
self.add_savepoint(_('Beautify files'))
|
self.add_savepoint(_('Beautify files'))
|
||||||
pretty_all(current_container())
|
pretty_all(current_container())
|
||||||
self.update_editors_from_container()
|
self.update_editors_from_container()
|
||||||
self.set_modified()
|
self.set_modified()
|
||||||
finally:
|
|
||||||
QApplication.restoreOverrideCursor()
|
|
||||||
|
|
||||||
def mark_selected_text(self):
|
def mark_selected_text(self):
|
||||||
ed = self.gui.central.current_editor
|
ed = self.gui.central.current_editor
|
||||||
@ -539,8 +538,7 @@ class Boss(QObject):
|
|||||||
count_message(_('Replaced') if replace else _('Found'), count)
|
count_message(_('Replaced') if replace else _('Found'), count)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
with BusyCursor():
|
||||||
try:
|
|
||||||
if action == 'find':
|
if action == 'find':
|
||||||
return do_find()
|
return do_find()
|
||||||
if action == 'replace':
|
if action == 'replace':
|
||||||
@ -559,8 +557,6 @@ class Boss(QObject):
|
|||||||
if marked:
|
if marked:
|
||||||
return count_message(_('Found'), editor.all_in_marked(pat))
|
return count_message(_('Found'), editor.all_in_marked(pat))
|
||||||
return do_all(replace=False)
|
return do_all(replace=False)
|
||||||
finally:
|
|
||||||
QApplication.restoreOverrideCursor()
|
|
||||||
|
|
||||||
def create_checkpoint(self):
|
def create_checkpoint(self):
|
||||||
text, ok = QInputDialog.getText(self.gui, _('Choose name'), _(
|
text, ok = QInputDialog.getText(self.gui, _('Choose name'), _(
|
||||||
@ -569,12 +565,26 @@ class Boss(QObject):
|
|||||||
if ok:
|
if ok:
|
||||||
self.add_savepoint(text)
|
self.add_savepoint(text)
|
||||||
|
|
||||||
|
def commit_editor_to_container(self, name, container=None):
|
||||||
|
container = container or current_container()
|
||||||
|
ed = editors[name]
|
||||||
|
with container.open(name, 'wb') as f:
|
||||||
|
f.write(ed.data)
|
||||||
|
if container is current_container():
|
||||||
|
ed.is_synced_to_container = True
|
||||||
|
|
||||||
|
def commit_all_editors_to_container(self):
|
||||||
|
with BusyCursor():
|
||||||
|
for name, ed in editors.iteritems():
|
||||||
|
if not ed.is_synced_to_container:
|
||||||
|
self.commit_editor_to_container(name)
|
||||||
|
ed.is_synced_to_container = True
|
||||||
|
|
||||||
def save_book(self):
|
def save_book(self):
|
||||||
c = current_container()
|
c = current_container()
|
||||||
for name, ed in editors.iteritems():
|
for name, ed in editors.iteritems():
|
||||||
if ed.is_modified:
|
if ed.is_modified or not ed.is_synced_to_container:
|
||||||
with c.open(name, 'wb') as f:
|
self.commit_editor_to_container(name, c)
|
||||||
f.write(ed.data)
|
|
||||||
ed.is_modified = False
|
ed.is_modified = False
|
||||||
self.gui.action_save.setEnabled(False)
|
self.gui.action_save.setEnabled(False)
|
||||||
tdir = self.mkdtemp(prefix='save-')
|
tdir = self.mkdtemp(prefix='save-')
|
||||||
@ -591,9 +601,8 @@ class Boss(QObject):
|
|||||||
tdir = self.mkdtemp(prefix='save-copy-')
|
tdir = self.mkdtemp(prefix='save-copy-')
|
||||||
container = clone_container(c, tdir)
|
container = clone_container(c, tdir)
|
||||||
for name, ed in editors.iteritems():
|
for name, ed in editors.iteritems():
|
||||||
if ed.is_modified:
|
if ed.is_modified or not ed.is_synced_to_container:
|
||||||
with c.open(name, 'wb') as f:
|
self.commit_editor_to_container(name, container)
|
||||||
f.write(ed.data)
|
|
||||||
|
|
||||||
def do_save(c, path, tdir):
|
def do_save(c, path, tdir):
|
||||||
save_container(c, path)
|
save_container(c, path)
|
||||||
@ -627,42 +636,33 @@ class Boss(QObject):
|
|||||||
ed.current_line = num
|
ed.current_line = num
|
||||||
|
|
||||||
def split_start_requested(self):
|
def split_start_requested(self):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return self.gui.preview.stop_split()
|
|
||||||
self.gui.preview.do_start_split()
|
self.gui.preview.do_start_split()
|
||||||
|
|
||||||
|
@in_thread_job
|
||||||
def split_requested(self, name, loc):
|
def split_requested(self, name, loc):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
self.add_savepoint(_('Split %s') % self.gui.elided_text(name))
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
||||||
try:
|
try:
|
||||||
self.add_savepoint(_('Split %s') % self.gui.elided_text(name))
|
bottom_name = split(current_container(), name, loc)
|
||||||
try:
|
except AbortError:
|
||||||
bottom_name = split(current_container(), name, loc)
|
self.rewind_savepoint()
|
||||||
except AbortError:
|
raise
|
||||||
self.rewind_savepoint()
|
self.apply_container_update_to_gui()
|
||||||
raise
|
self.edit_file(bottom_name, 'html')
|
||||||
self.apply_container_update_to_gui()
|
|
||||||
self.edit_file(bottom_name, 'html')
|
|
||||||
finally:
|
|
||||||
QApplication.restoreOverrideCursor()
|
|
||||||
|
|
||||||
|
@in_thread_job
|
||||||
def merge_requested(self, category, names, master):
|
def merge_requested(self, category, names, master):
|
||||||
if not self.check_dirtied():
|
self.commit_all_editors_to_container()
|
||||||
return
|
self.add_savepoint(_('Merge files into %s') % self.gui.elided_text(master))
|
||||||
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
||||||
try:
|
try:
|
||||||
self.add_savepoint(_('Merge files into %s') % self.gui.elided_text(master))
|
merge(current_container(), category, names, master)
|
||||||
try:
|
except AbortError:
|
||||||
merge(current_container(), category, names, master)
|
self.rewind_savepoint()
|
||||||
except AbortError:
|
raise
|
||||||
self.rewind_savepoint()
|
self.apply_container_update_to_gui()
|
||||||
raise
|
if master in editors:
|
||||||
self.apply_container_update_to_gui()
|
self.show_editor(master)
|
||||||
if master in editors:
|
|
||||||
self.show_editor(master)
|
|
||||||
finally:
|
|
||||||
QApplication.restoreOverrideCursor()
|
|
||||||
|
|
||||||
def sync_editor_to_preview(self, name, lnum):
|
def sync_editor_to_preview(self, name, lnum):
|
||||||
editor = self.edit_file(name, 'html')
|
editor = self.edit_file(name, 'html')
|
||||||
@ -695,6 +695,7 @@ class Boss(QObject):
|
|||||||
editor.init_from_template(data)
|
editor.init_from_template(data)
|
||||||
else:
|
else:
|
||||||
editor.data = data
|
editor.data = data
|
||||||
|
editor.is_synced_to_container = True
|
||||||
editor.modification_state_changed.connect(self.editor_modification_state_changed)
|
editor.modification_state_changed.connect(self.editor_modification_state_changed)
|
||||||
self.gui.central.add_editor(name, editor)
|
self.gui.central.add_editor(name, editor)
|
||||||
|
|
||||||
@ -755,23 +756,22 @@ class Boss(QObject):
|
|||||||
self.gui.preview.start_refresh_timer()
|
self.gui.preview.start_refresh_timer()
|
||||||
|
|
||||||
def editor_undo_redo_state_changed(self, *args):
|
def editor_undo_redo_state_changed(self, *args):
|
||||||
self.apply_current_editor_state(update_keymap=False)
|
self.apply_current_editor_state()
|
||||||
|
|
||||||
def editor_copy_available_state_changed(self, *args):
|
def editor_copy_available_state_changed(self, *args):
|
||||||
self.apply_current_editor_state(update_keymap=False)
|
self.apply_current_editor_state()
|
||||||
|
|
||||||
def editor_modification_state_changed(self, is_modified):
|
def editor_modification_state_changed(self, is_modified):
|
||||||
self.apply_current_editor_state(update_keymap=False)
|
self.apply_current_editor_state()
|
||||||
if is_modified:
|
if is_modified:
|
||||||
self.set_modified()
|
self.set_modified()
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def apply_current_editor_state(self, update_keymap=True):
|
def apply_current_editor_state(self):
|
||||||
ed = self.gui.central.current_editor
|
ed = self.gui.central.current_editor
|
||||||
if ed is not None:
|
if ed is not None:
|
||||||
actions['editor-undo'].setEnabled(ed.undo_available)
|
actions['editor-undo'].setEnabled(ed.undo_available)
|
||||||
actions['editor-redo'].setEnabled(ed.redo_available)
|
actions['editor-redo'].setEnabled(ed.redo_available)
|
||||||
actions['editor-save'].setEnabled(ed.is_modified)
|
|
||||||
actions['editor-cut'].setEnabled(ed.copy_available)
|
actions['editor-cut'].setEnabled(ed.copy_available)
|
||||||
actions['editor-copy'].setEnabled(ed.cut_available)
|
actions['editor-copy'].setEnabled(ed.cut_available)
|
||||||
actions['go-to-line-number'].setEnabled(ed.has_line_numbers)
|
actions['go-to-line-number'].setEnabled(ed.has_line_numbers)
|
||||||
@ -793,7 +793,7 @@ class Boss(QObject):
|
|||||||
name = n
|
name = n
|
||||||
if not name:
|
if not name:
|
||||||
return
|
return
|
||||||
if editor.is_modified:
|
if editor.is_modified or not editor.is_synced_to_container:
|
||||||
if not question_dialog(self.gui, _('Unsaved changes'), _(
|
if not question_dialog(self.gui, _('Unsaved changes'), _(
|
||||||
'There are unsaved changes in %s. Are you sure you want to close'
|
'There are unsaved changes in %s. Are you sure you want to close'
|
||||||
' this editor?') % name):
|
' this editor?') % name):
|
||||||
@ -807,31 +807,6 @@ class Boss(QObject):
|
|||||||
if not editors:
|
if not editors:
|
||||||
self.gui.preview.clear()
|
self.gui.preview.clear()
|
||||||
|
|
||||||
def do_editor_save(self):
|
|
||||||
ed = self.gui.central.current_editor
|
|
||||||
if ed is None:
|
|
||||||
return
|
|
||||||
name = None
|
|
||||||
for n, x in editors.iteritems():
|
|
||||||
if x is ed:
|
|
||||||
name = n
|
|
||||||
break
|
|
||||||
if name is None:
|
|
||||||
return
|
|
||||||
c = current_container()
|
|
||||||
with c.open(name, 'wb') as f:
|
|
||||||
f.write(ed.data)
|
|
||||||
ed.is_modified = False
|
|
||||||
tdir = self.mkdtemp(prefix='save-')
|
|
||||||
container = clone_container(c, tdir)
|
|
||||||
self.save_manager.schedule(tdir, container)
|
|
||||||
is_modified = False
|
|
||||||
for ed in editors.itervalues():
|
|
||||||
if ed.is_modified:
|
|
||||||
is_modified = True
|
|
||||||
break
|
|
||||||
self.gui.action_save.setEnabled(is_modified)
|
|
||||||
|
|
||||||
# Shutdown {{{
|
# Shutdown {{{
|
||||||
def quit(self):
|
def quit(self):
|
||||||
if not self.confirm_quit():
|
if not self.confirm_quit():
|
||||||
|
@ -29,14 +29,15 @@ class Editor(QMainWindow):
|
|||||||
QMainWindow.__init__(self, parent)
|
QMainWindow.__init__(self, parent)
|
||||||
if parent is None:
|
if parent is None:
|
||||||
self.setWindowFlags(Qt.Widget)
|
self.setWindowFlags(Qt.Widget)
|
||||||
|
self.is_synced_to_container = False
|
||||||
self.syntax = syntax
|
self.syntax = syntax
|
||||||
self.editor = TextEdit(self)
|
self.editor = TextEdit(self)
|
||||||
self.setCentralWidget(self.editor)
|
self.setCentralWidget(self.editor)
|
||||||
self.editor.modificationChanged.connect(self.modification_state_changed.emit)
|
|
||||||
self.create_toolbars()
|
self.create_toolbars()
|
||||||
self.undo_available = False
|
self.undo_available = False
|
||||||
self.redo_available = False
|
self.redo_available = False
|
||||||
self.copy_available = self.cut_available = False
|
self.copy_available = self.cut_available = False
|
||||||
|
self.editor.modificationChanged.connect(self._modification_state_changed)
|
||||||
self.editor.undoAvailable.connect(self._undo_available)
|
self.editor.undoAvailable.connect(self._undo_available)
|
||||||
self.editor.redoAvailable.connect(self._redo_available)
|
self.editor.redoAvailable.connect(self._redo_available)
|
||||||
self.editor.textChanged.connect(self._data_changed)
|
self.editor.textChanged.connect(self._data_changed)
|
||||||
@ -124,7 +125,7 @@ class Editor(QMainWindow):
|
|||||||
def create_toolbars(self):
|
def create_toolbars(self):
|
||||||
self.action_bar = b = self.addToolBar(_('File actions tool bar'))
|
self.action_bar = b = self.addToolBar(_('File actions tool bar'))
|
||||||
b.setObjectName('action_bar') # Needed for saveState
|
b.setObjectName('action_bar') # Needed for saveState
|
||||||
for x in ('save', 'undo', 'redo'):
|
for x in ('undo', 'redo'):
|
||||||
try:
|
try:
|
||||||
b.addAction(actions['editor-%s' % x])
|
b.addAction(actions['editor-%s' % x])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -155,7 +156,12 @@ class Editor(QMainWindow):
|
|||||||
self.editor.cursorPositionChanged.disconnect()
|
self.editor.cursorPositionChanged.disconnect()
|
||||||
self.editor.setPlainText('')
|
self.editor.setPlainText('')
|
||||||
|
|
||||||
|
def _modification_state_changed(self):
|
||||||
|
self.is_synced_to_container = self.is_modified
|
||||||
|
self.modification_state_changed.emit(self.is_modified)
|
||||||
|
|
||||||
def _data_changed(self):
|
def _data_changed(self):
|
||||||
|
self.is_synced_to_container = False
|
||||||
self.data_changed.emit(self)
|
self.data_changed.emit(self)
|
||||||
|
|
||||||
def _undo_available(self, available):
|
def _undo_available(self, available):
|
||||||
|
@ -186,7 +186,7 @@ class Main(MainWindow):
|
|||||||
_('Revert book to before the last action (Undo)'))
|
_('Revert book to before the last action (Undo)'))
|
||||||
self.action_global_redo = reg('forward.png', _('&Revert to after'), self.boss.do_global_redo, 'global-redo', 'Ctrl+Right',
|
self.action_global_redo = reg('forward.png', _('&Revert to after'), self.boss.do_global_redo, 'global-redo', 'Ctrl+Right',
|
||||||
_('Revert book state to after the next action (Redo)'))
|
_('Revert book state to after the next action (Redo)'))
|
||||||
self.action_save = reg('save.png', _('&Save'), self.boss.save_book, 'save-book', 'Ctrl+Shift+S', _('Save book'))
|
self.action_save = reg('save.png', _('&Save'), self.boss.save_book, 'save-book', 'Ctrl+S', _('Save book'))
|
||||||
self.action_save.setEnabled(False)
|
self.action_save.setEnabled(False)
|
||||||
self.action_save_copy = reg('save.png', _('Save a ©'), self.boss.save_copy, 'save-copy', 'Ctrl+Alt+S', _('Save a copy of the book'))
|
self.action_save_copy = reg('save.png', _('Save a ©'), self.boss.save_copy, 'save-copy', 'Ctrl+Alt+S', _('Save a copy of the book'))
|
||||||
self.action_quit = reg('quit.png', _('&Quit'), self.boss.quit, 'quit', 'Ctrl+Q', _('Quit'))
|
self.action_quit = reg('quit.png', _('&Quit'), self.boss.quit, 'quit', 'Ctrl+Q', _('Quit'))
|
||||||
@ -198,8 +198,6 @@ class Main(MainWindow):
|
|||||||
_('Undo typing'))
|
_('Undo typing'))
|
||||||
self.action_editor_redo = reg('edit-redo.png', _('&Redo'), self.boss.do_editor_redo, 'editor-redo', 'Ctrl+Y',
|
self.action_editor_redo = reg('edit-redo.png', _('&Redo'), self.boss.do_editor_redo, 'editor-redo', 'Ctrl+Y',
|
||||||
_('Redo typing'))
|
_('Redo typing'))
|
||||||
self.action_editor_save = reg('save.png', _('&Save'), self.boss.do_editor_save, 'editor-save', 'Ctrl+S',
|
|
||||||
_('Save changes to the current file'))
|
|
||||||
self.action_editor_cut = reg('edit-cut.png', _('C&ut text'), self.boss.do_editor_cut, 'editor-cut', ('Ctrl+X', 'Shift+Delete', ),
|
self.action_editor_cut = reg('edit-cut.png', _('C&ut text'), self.boss.do_editor_cut, 'editor-cut', ('Ctrl+X', 'Shift+Delete', ),
|
||||||
_('Cut text'))
|
_('Cut text'))
|
||||||
self.action_editor_copy = reg('edit-copy.png', _('&Copy text'), self.boss.do_editor_copy, 'editor-copy', ('Ctrl+C', 'Ctrl+Insert'),
|
self.action_editor_copy = reg('edit-copy.png', _('&Copy text'), self.boss.do_editor_copy, 'editor-copy', ('Ctrl+C', 'Ctrl+Insert'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user