mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
New commit removing the action.
This commit is contained in:
parent
58a418cca9
commit
2b625a173e
187
src/calibre/gui2/dialogs/ff_doc_editor.py
Normal file
187
src/calibre/gui2/dialogs/ff_doc_editor.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
'''
|
||||||
|
Created on 12 Nov 2024
|
||||||
|
|
||||||
|
@author: chaley
|
||||||
|
'''
|
||||||
|
|
||||||
|
from qt.core import (QApplication, QCheckBox, QComboBox, QFrame, QLabel, QGridLayout,
|
||||||
|
QHBoxLayout, QPlainTextEdit, QPushButton, QSize, QTimer)
|
||||||
|
|
||||||
|
from calibre.constants import iswindows
|
||||||
|
from calibre.gui2 import gprefs
|
||||||
|
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
|
||||||
|
from calibre.utils.ffml_processor import FFMLProcessor
|
||||||
|
from calibre.utils.formatter_functions import formatter_functions
|
||||||
|
|
||||||
|
|
||||||
|
class FFDocEditor(Dialog):
|
||||||
|
|
||||||
|
def __init__(self, can_copy_back=False, parent=None):
|
||||||
|
self.ffml = FFMLProcessor()
|
||||||
|
self.can_copy_back = can_copy_back
|
||||||
|
self.last_operation = None
|
||||||
|
super().__init__(title=_('Template function documentation editor'),
|
||||||
|
name='template_function_doc_editor_dialog', parent=parent)
|
||||||
|
|
||||||
|
def sizeHint(self):
|
||||||
|
return QSize(800, 600)
|
||||||
|
|
||||||
|
def set_document_text(self, text):
|
||||||
|
self.editable_text_widget.setPlainText(text)
|
||||||
|
|
||||||
|
def document_text(self):
|
||||||
|
return self.editable_text_widget.toPlainText()
|
||||||
|
|
||||||
|
def copy_text(self):
|
||||||
|
QApplication.instance().clipboard().setText(self.document_text())
|
||||||
|
|
||||||
|
def html_widget(self, layout, row, column):
|
||||||
|
e = HTMLDisplay()
|
||||||
|
e.setFrameStyle(QFrame.Shape.Box)
|
||||||
|
if iswindows:
|
||||||
|
e.setDefaultStyleSheet('pre { font-family: "Segoe UI Mono", "Consolas", monospace; }')
|
||||||
|
layout.addWidget(e, row, column, 1, 1)
|
||||||
|
return e
|
||||||
|
|
||||||
|
def text_widget(self, read_only, layout, row, column):
|
||||||
|
e = QPlainTextEdit()
|
||||||
|
e.setReadOnly(read_only)
|
||||||
|
e.setFrameStyle(QFrame.Shape.Box)
|
||||||
|
layout.addWidget(e, row, column, 1, 1)
|
||||||
|
return e
|
||||||
|
|
||||||
|
def label_widget(self, text, layout, row, column, colspan=None):
|
||||||
|
e = QLabel(text)
|
||||||
|
layout.addWidget(e, row, column, 1, colspan if colspan is not None else 1)
|
||||||
|
return e
|
||||||
|
|
||||||
|
def setup_ui(self):
|
||||||
|
gl = QGridLayout(self)
|
||||||
|
hl = QHBoxLayout()
|
||||||
|
|
||||||
|
so = self.show_original_cb = QCheckBox(_('Show documentation for function'))
|
||||||
|
so.setChecked(gprefs.get('template_function_doc_editor_show_original', False))
|
||||||
|
so.stateChanged.connect(self.first_row_checkbox_changed)
|
||||||
|
hl.addWidget(so)
|
||||||
|
|
||||||
|
f = self.functions_box = QComboBox()
|
||||||
|
self.builtins = formatter_functions().get_builtins()
|
||||||
|
f.addItem('')
|
||||||
|
f.addItems(self.builtins.keys())
|
||||||
|
hl.addWidget(f)
|
||||||
|
f.currentIndexChanged.connect(self.functions_box_index_changed)
|
||||||
|
|
||||||
|
so = self.show_in_english_cb = QCheckBox(_('Show original English'))
|
||||||
|
so.stateChanged.connect(self.first_row_checkbox_changed)
|
||||||
|
hl.addWidget(so)
|
||||||
|
|
||||||
|
so = self.show_formatted_cb = QCheckBox(_('Show with placeholders replaced'))
|
||||||
|
so.stateChanged.connect(self.first_row_checkbox_changed)
|
||||||
|
hl.addWidget(so)
|
||||||
|
|
||||||
|
hl.addStretch()
|
||||||
|
gl.addLayout(hl, 0, 0, 1, 2)
|
||||||
|
|
||||||
|
self.original_doc_label = self.label_widget(
|
||||||
|
_('Raw documentation for the selected function'), gl, 1, 0)
|
||||||
|
w = self.original_doc_html_label = self.label_widget(
|
||||||
|
_('Documentation for the selected function in HTML'), gl, 1, 1)
|
||||||
|
w.setVisible(so.isChecked())
|
||||||
|
w = self.original_text_widget = self.text_widget(True, gl, 2, 0)
|
||||||
|
w.setVisible(so.isChecked())
|
||||||
|
w = self.original_text_result = self.html_widget(gl, 2, 1)
|
||||||
|
w.setVisible(so.isChecked())
|
||||||
|
|
||||||
|
self.label_widget(_('Document being edited'), gl, 3, 0)
|
||||||
|
l = QHBoxLayout()
|
||||||
|
l.addWidget(QLabel(_('Document in HTML')))
|
||||||
|
cb = self.doc_show_formatted_cb = QCheckBox(_('Show with placeholders replaced'))
|
||||||
|
cb.setToolTip(_('This requires the original function documentation to be visible above'))
|
||||||
|
cb.stateChanged.connect(self._editable_box_changed)
|
||||||
|
l.addWidget(cb)
|
||||||
|
l.addStretch()
|
||||||
|
gl.addLayout(l, 3, 1)
|
||||||
|
|
||||||
|
w = self.editable_text_widget = self.text_widget(False, gl, 4, 0)
|
||||||
|
w.textChanged.connect(self.editable_box_changed)
|
||||||
|
self.editable_text_result = self.html_widget(gl, 4, 1)
|
||||||
|
if self.can_copy_back:
|
||||||
|
self.label_widget(_('Text will be stored with the saved template/function'), gl, 5, 0)
|
||||||
|
else:
|
||||||
|
self.label_widget(_('You must copy the text then paste it where it is needed'), gl, 5, 0, colspan=2)
|
||||||
|
|
||||||
|
l = QHBoxLayout()
|
||||||
|
b = QPushButton(_('&Copy text'))
|
||||||
|
b.clicked.connect(self.copy_text)
|
||||||
|
l.addWidget(b)
|
||||||
|
l.addStretch()
|
||||||
|
gl.addLayout(l, 6, 0)
|
||||||
|
gl.addWidget(self.bb, 6, 1)
|
||||||
|
|
||||||
|
self.changed_timer = QTimer()
|
||||||
|
self.fill_in_top_row()
|
||||||
|
|
||||||
|
def editable_box_changed(self):
|
||||||
|
self.changed_timer.stop()
|
||||||
|
t = self.changed_timer = QTimer()
|
||||||
|
t.timeout.connect(self._editable_box_changed)
|
||||||
|
t.setSingleShot(True)
|
||||||
|
t.setInterval(250)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def _editable_box_changed(self):
|
||||||
|
name = self.functions_box.currentText()
|
||||||
|
if name and self.doc_show_formatted_cb.isVisible() and self.doc_show_formatted_cb.isChecked():
|
||||||
|
doc = self.builtins[name].doc
|
||||||
|
self.editable_text_result.setHtml(
|
||||||
|
self.ffml.document_to_html(doc.format_again(
|
||||||
|
self.editable_text_widget.toPlainText()), 'edited text'))
|
||||||
|
else:
|
||||||
|
self.editable_text_result.setHtml(
|
||||||
|
self.ffml.document_to_html(self.editable_text_widget.toPlainText(), 'edited text'))
|
||||||
|
|
||||||
|
def fill_in_top_row(self):
|
||||||
|
to_show = self.show_original_cb.isChecked()
|
||||||
|
self.original_doc_label.setVisible(to_show)
|
||||||
|
self.original_doc_html_label.setVisible(to_show)
|
||||||
|
self.show_in_english_cb.setVisible(to_show)
|
||||||
|
self.show_formatted_cb.setVisible(to_show)
|
||||||
|
self.original_text_widget.setVisible(to_show)
|
||||||
|
self.original_text_result.setVisible(to_show)
|
||||||
|
if not to_show:
|
||||||
|
self.doc_show_formatted_cb.setVisible(False)
|
||||||
|
self._editable_box_changed()
|
||||||
|
return
|
||||||
|
name = self.functions_box.currentText()
|
||||||
|
if name in self.builtins:
|
||||||
|
doc = self.builtins[name].doc
|
||||||
|
if not self.can_copy_back:
|
||||||
|
self.doc_show_formatted_cb.setVisible(True)
|
||||||
|
if self.show_in_english_cb.isChecked():
|
||||||
|
html = doc.formatted_english if self.show_formatted_cb.isChecked() else doc.raw_english
|
||||||
|
self.original_text_widget.setPlainText(doc.raw_english.lstrip())
|
||||||
|
self.original_text_result.setHtml(self.ffml.document_to_html(html, name))
|
||||||
|
else:
|
||||||
|
html = doc.formatted_other if self.show_formatted_cb.isChecked() else doc.raw_other
|
||||||
|
self.original_text_widget.setPlainText(doc.raw_other.lstrip())
|
||||||
|
self.original_text_result.setHtml(self.ffml.document_to_html(html, name))
|
||||||
|
else:
|
||||||
|
self.original_text_widget.setPlainText('')
|
||||||
|
self.original_text_result.setHtml(self.ffml.document_to_html('', name))
|
||||||
|
self.doc_show_formatted_cb.setVisible(False)
|
||||||
|
self._editable_box_changed()
|
||||||
|
|
||||||
|
def first_row_checkbox_changed(self):
|
||||||
|
gprefs['template_function_doc_editor_show_original'] = self.show_original_cb.isChecked()
|
||||||
|
self.fill_in_top_row()
|
||||||
|
|
||||||
|
def functions_box_index_changed(self, idx):
|
||||||
|
self.show_original_cb.setChecked(True)
|
||||||
|
self.fill_in_top_row()
|
@ -119,7 +119,7 @@ class DocViewer(Dialog):
|
|||||||
self.last_operation = self.show_all_functions
|
self.last_operation = self.show_all_functions
|
||||||
result = []
|
result = []
|
||||||
a = result.append
|
a = result.append
|
||||||
for name in sorted(self.builtins):
|
for name in sorted(self.builtins, key=sort_key):
|
||||||
a(self.header_line(name))
|
a(self.header_line(name))
|
||||||
try:
|
try:
|
||||||
doc = self.get_doc(self.builtins[name])
|
doc = self.get_doc(self.builtins[name])
|
||||||
|
@ -8,6 +8,7 @@ import traceback
|
|||||||
from qt.core import QDialog, QDialogButtonBox
|
from qt.core import QDialog, QDialogButtonBox
|
||||||
|
|
||||||
from calibre.gui2 import error_dialog, gprefs, question_dialog, warning_dialog
|
from calibre.gui2 import error_dialog, gprefs, question_dialog, warning_dialog
|
||||||
|
from calibre.gui2.dialogs.ff_doc_editor import FFDocEditor
|
||||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||||
from calibre.gui2.preferences import AbortInitialize, ConfigWidgetBase, test_widget
|
from calibre.gui2.preferences import AbortInitialize, ConfigWidgetBase, test_widget
|
||||||
from calibre.gui2.preferences.template_functions_ui import Ui_Form
|
from calibre.gui2.preferences.template_functions_ui import Ui_Form
|
||||||
@ -187,6 +188,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.program.textChanged.connect(self.enable_replace_button)
|
self.program.textChanged.connect(self.enable_replace_button)
|
||||||
self.create_button.clicked.connect(self.create_button_clicked)
|
self.create_button.clicked.connect(self.create_button_clicked)
|
||||||
self.delete_button.clicked.connect(self.delete_button_clicked)
|
self.delete_button.clicked.connect(self.delete_button_clicked)
|
||||||
|
self.doc_edit_button.clicked.connect(self.doc_edit_button_clicked)
|
||||||
self.create_button.setEnabled(False)
|
self.create_button.setEnabled(False)
|
||||||
self.delete_button.setEnabled(False)
|
self.delete_button.setEnabled(False)
|
||||||
self.replace_button.setEnabled(False)
|
self.replace_button.setEnabled(False)
|
||||||
@ -206,9 +208,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.st_delete_button.setEnabled(False)
|
self.st_delete_button.setEnabled(False)
|
||||||
self.st_replace_button.setEnabled(False)
|
self.st_replace_button.setEnabled(False)
|
||||||
self.st_test_template_button.setEnabled(False)
|
self.st_test_template_button.setEnabled(False)
|
||||||
|
self.st_doc_edit_button.setEnabled(False)
|
||||||
self.st_clear_button.clicked.connect(self.st_clear_button_clicked)
|
self.st_clear_button.clicked.connect(self.st_clear_button_clicked)
|
||||||
self.st_test_template_button.clicked.connect(self.st_test_template)
|
self.st_test_template_button.clicked.connect(self.st_test_template)
|
||||||
self.st_replace_button.clicked.connect(self.st_replace_button_clicked)
|
self.st_replace_button.clicked.connect(self.st_replace_button_clicked)
|
||||||
|
self.st_doc_edit_button.clicked.connect(self.st_doc_edit_button_clicked)
|
||||||
|
|
||||||
self.st_current_program_name = ''
|
self.st_current_program_name = ''
|
||||||
self.st_current_program_text = ''
|
self.st_current_program_text = ''
|
||||||
@ -239,6 +243,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
def enable_replace_button(self):
|
def enable_replace_button(self):
|
||||||
self.replace_button.setEnabled(self.delete_button.isEnabled())
|
self.replace_button.setEnabled(self.delete_button.isEnabled())
|
||||||
|
|
||||||
|
def doc_edit_button_clicked(self):
|
||||||
|
d = FFDocEditor(can_copy_back=True, parent=self)
|
||||||
|
d.set_document_text(self.documentation.toPlainText())
|
||||||
|
if d.exec() == QDialog.DialogCode.Accepted:
|
||||||
|
self.documentation.setPlainText(d.document_text())
|
||||||
|
|
||||||
def clear_button_clicked(self):
|
def clear_button_clicked(self):
|
||||||
self.build_function_names_box()
|
self.build_function_names_box()
|
||||||
self.program.clear()
|
self.program.clear()
|
||||||
@ -425,6 +435,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.template_editor.new_doc.clear()
|
self.template_editor.new_doc.clear()
|
||||||
self.st_create_button.setEnabled(False)
|
self.st_create_button.setEnabled(False)
|
||||||
self.st_delete_button.setEnabled(False)
|
self.st_delete_button.setEnabled(False)
|
||||||
|
self.st_doc_edit_button.setEnabled(False)
|
||||||
|
|
||||||
def st_build_function_names_box(self, scroll_to=''):
|
def st_build_function_names_box(self, scroll_to=''):
|
||||||
self.te_name.blockSignals(True)
|
self.te_name.blockSignals(True)
|
||||||
@ -447,6 +458,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.changed_signal.emit()
|
self.changed_signal.emit()
|
||||||
self.st_create_button.setEnabled(True)
|
self.st_create_button.setEnabled(True)
|
||||||
self.st_delete_button.setEnabled(False)
|
self.st_delete_button.setEnabled(False)
|
||||||
|
self.st_doc_edit_button.setEnabled(False)
|
||||||
self.st_build_function_names_box()
|
self.st_build_function_names_box()
|
||||||
self.te_textbox.setReadOnly(False)
|
self.te_textbox.setReadOnly(False)
|
||||||
self.st_current_program_name = ''
|
self.st_current_program_name = ''
|
||||||
@ -483,6 +495,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.st_delete_button.setEnabled(b)
|
self.st_delete_button.setEnabled(b)
|
||||||
self.st_test_template_button.setEnabled(b)
|
self.st_test_template_button.setEnabled(b)
|
||||||
self.te_textbox.setReadOnly(False)
|
self.te_textbox.setReadOnly(False)
|
||||||
|
self.st_doc_edit_button.setEnabled(True)
|
||||||
|
|
||||||
def st_function_index_changed(self, idx):
|
def st_function_index_changed(self, idx):
|
||||||
txt = self.te_name.currentText()
|
txt = self.te_name.currentText()
|
||||||
@ -518,6 +531,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
self.st_delete_button_clicked()
|
self.st_delete_button_clicked()
|
||||||
self.st_create_button_clicked(use_name=name)
|
self.st_create_button_clicked(use_name=name)
|
||||||
|
|
||||||
|
def st_doc_edit_button_clicked(self):
|
||||||
|
d = FFDocEditor(can_copy_back=True, parent=self)
|
||||||
|
d.set_document_text(self.template_editor.new_doc.toPlainText())
|
||||||
|
if d.exec() == QDialog.DialogCode.Accepted:
|
||||||
|
self.template_editor.new_doc.setPlainText(d.document_text())
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
pref_value = []
|
pref_value = []
|
||||||
for name, cls in iteritems(self.funcs):
|
for name, cls in iteritems(self.funcs):
|
||||||
|
@ -81,6 +81,29 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="st_doc_edit_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Doc Editor</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Open an editor for function documentation</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_22">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="st_test_template_button">
|
<widget class="QPushButton" name="st_test_template_button">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -185,17 +208,44 @@ a new related user defined function.</p></string>
|
|||||||
<widget class="QTextEdit" name="documentation"/>
|
<widget class="QTextEdit" name="documentation"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<layout class="QVBoxLayout">
|
||||||
<property name="text">
|
<item>
|
||||||
<string>D&ocumentation:</string>
|
<widget class="QLabel" name="label_4">
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="alignment">
|
<string>D&ocumentation:</string>
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
</property>
|
||||||
</property>
|
<property name="alignment">
|
||||||
<property name="buddy">
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
<cstring>documentation</cstring>
|
</property>
|
||||||
</property>
|
<property name="buddy">
|
||||||
</widget>
|
<cstring>documentation</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="doc_edit_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Doc Editor</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Open an editor for function documentation</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
@ -253,7 +253,7 @@ class FFMLProcessor:
|
|||||||
self.document_name = name
|
self.document_name = name
|
||||||
|
|
||||||
node = DocumentNode()
|
node = DocumentNode()
|
||||||
return self._parse_document(node)
|
return self._parse_document(node) if doc else node
|
||||||
|
|
||||||
def tree_to_html(self, tree, depth=0):
|
def tree_to_html(self, tree, depth=0):
|
||||||
"""
|
"""
|
||||||
|
@ -49,13 +49,23 @@ class TranslatedStringWithRaw(str):
|
|||||||
instance.raw_other = raw_other
|
instance.raw_other = raw_other
|
||||||
instance.formatted_english = formatted_english
|
instance.formatted_english = formatted_english
|
||||||
instance.formatted_other = formatted_other
|
instance.formatted_other = formatted_other
|
||||||
|
instance.did_format = False
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
def format(self, *args, **kw):
|
def format(self, *args, **kw):
|
||||||
formatted_english = self.raw_english.format(*args, **kw)
|
formatted_english = self.raw_english.format(*args, **kw)
|
||||||
formatted_other = self.raw_other.format(*args, **kw)
|
formatted_other = self.raw_other.format(*args, **kw)
|
||||||
return TranslatedStringWithRaw(self.raw_english, self.raw_other,
|
v = TranslatedStringWithRaw(self.raw_english, self.raw_other,
|
||||||
formatted_english, formatted_other)
|
formatted_english, formatted_other)
|
||||||
|
v.saved_args = args
|
||||||
|
v.saved_kwargs = kw
|
||||||
|
v.did_format = True
|
||||||
|
return v
|
||||||
|
|
||||||
|
def format_again(self, txt):
|
||||||
|
if self.did_format:
|
||||||
|
return txt.format(*self.saved_args, **self.saved_kwargs)
|
||||||
|
return txt
|
||||||
|
|
||||||
|
|
||||||
def _(txt):
|
def _(txt):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user