New commit removing the action.

This commit is contained in:
Charles Haley 2024-11-13 14:29:31 +00:00
parent 58a418cca9
commit 2b625a173e
6 changed files with 280 additions and 14 deletions

View 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()

View File

@ -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])

View File

@ -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):

View File

@ -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,6 +208,8 @@ a new related user defined function.&lt;/p&gt;</string>
<widget class="QTextEdit" name="documentation"/> <widget class="QTextEdit" name="documentation"/>
</item> </item>
<item row="5" column="0"> <item row="5" column="0">
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>D&amp;ocumentation:</string> <string>D&amp;ocumentation:</string>
@ -197,6 +222,31 @@ a new related user defined function.&lt;/p&gt;</string>
</property> </property>
</widget> </widget>
</item> </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 row="6" column="1"> <item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>

View File

@ -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):
""" """

View File

@ -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):