mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Commit for testing after making a tabbed window and embedding the template tester
This commit is contained in:
parent
78e9858f4d
commit
e08fb5f231
@ -935,10 +935,10 @@ class ActionTemplateTester(InterfaceActionBase):
|
||||
description = _('Show an editor for testing templates')
|
||||
|
||||
|
||||
class ActionStoredTemplates(InterfaceActionBase):
|
||||
name = 'Stored Templates'
|
||||
actual_plugin = 'calibre.gui2.actions.show_stored_templates:ShowStoredTemplatesAction'
|
||||
description = _('Show a dialog for creating and managing stored templates')
|
||||
class ActionTemplateFunctions(InterfaceActionBase):
|
||||
name = 'Template Functions'
|
||||
actual_plugin = 'calibre.gui2.actions.show_stored_templates:ShowTemplateFunctionsAction'
|
||||
description = _('Show a dialog for creating and managing template functions and stored templates')
|
||||
|
||||
|
||||
class ActionSaveToDisk(InterfaceActionBase):
|
||||
@ -1105,7 +1105,7 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
|
||||
ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore,
|
||||
ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy,
|
||||
ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper, ActionAuthorMapper,
|
||||
ActionVirtualLibrary, ActionBrowseAnnotations, ActionStoredTemplates]
|
||||
ActionVirtualLibrary, ActionBrowseAnnotations, ActionTemplateFunctions]
|
||||
|
||||
# }}}
|
||||
|
||||
@ -1278,18 +1278,6 @@ class TemplateFunctions(PreferencesPlugin):
|
||||
description = _('Create your own template functions')
|
||||
|
||||
|
||||
class StoredTemplates(PreferencesPlugin):
|
||||
name = 'StoredTemplates'
|
||||
icon = I('template_funcs.png')
|
||||
gui_name = _('Stored templates')
|
||||
category = 'Advanced'
|
||||
gui_category = _('Advanced')
|
||||
category_order = 5
|
||||
name_order = 6
|
||||
config_widget = 'calibre.gui2.preferences.stored_templates'
|
||||
description = _('Create stored calibre templates')
|
||||
|
||||
|
||||
class Email(PreferencesPlugin):
|
||||
name = 'Email'
|
||||
icon = I('mail.png')
|
||||
@ -1394,7 +1382,7 @@ class Misc(PreferencesPlugin):
|
||||
plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
|
||||
CommonOptions, OutputOptions, Adding, Saving, Sending, Plugboard,
|
||||
Email, Server, Plugins, Tweaks, Misc, TemplateFunctions,
|
||||
StoredTemplates, MetadataSources, Keyboard, IgnoredDevices]
|
||||
MetadataSources, Keyboard, IgnoredDevices]
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -11,20 +11,20 @@ from calibre.gui2.actions import InterfaceAction
|
||||
from calibre.gui2.preferences.main import Preferences
|
||||
|
||||
|
||||
class ShowStoredTemplatesAction(InterfaceAction):
|
||||
class ShowTemplateFunctionsAction(InterfaceAction):
|
||||
|
||||
name = 'Stored Template'
|
||||
action_spec = (_('Stored Templates'), 'debug.png', None, ())
|
||||
name = 'Template Functions'
|
||||
action_spec = (_('Template Functions'), 'debug.png', None, ())
|
||||
dont_add_to = frozenset(('context-menu-device',))
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
self.previous_text = _('Manage stored templates')
|
||||
self.previous_text = _('Manage template functions')
|
||||
self.first_time = True
|
||||
self.qaction.triggered.connect(self.show_template_editor)
|
||||
|
||||
def show_template_editor(self, *args):
|
||||
d = Preferences(self.gui, initial_plugin=('Advanced', 'StoredTemplates'),
|
||||
d = Preferences(self.gui, initial_plugin=('Advanced', 'TemplateFunctions'),
|
||||
close_after_initial=True)
|
||||
d.exec_()
|
||||
|
||||
|
@ -213,7 +213,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
|
||||
def __init__(self, parent, text, mi=None, fm=None, color_field=None,
|
||||
icon_field_key=None, icon_rule_kind=None, doing_emblem=False,
|
||||
text_is_placeholder=False):
|
||||
text_is_placeholder=False, dialog_is_st_editor=False):
|
||||
QDialog.__init__(self, parent)
|
||||
Ui_TemplateDialog.__init__(self)
|
||||
self.setupUi(self)
|
||||
@ -221,6 +221,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
self.coloring = color_field is not None
|
||||
self.iconing = icon_field_key is not None
|
||||
self.embleming = doing_emblem
|
||||
self.dialog_is_st_editor = dialog_is_st_editor
|
||||
|
||||
cols = []
|
||||
if fm is not None:
|
||||
@ -273,6 +274,14 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
self.icon_kind.setCurrentIndex(dex)
|
||||
self.icon_field.setCurrentIndex(self.icon_field.findData(icon_field_key))
|
||||
|
||||
if dialog_is_st_editor:
|
||||
self.buttonBox.setVisible(False)
|
||||
else:
|
||||
self.new_doc_label.setVisible(False)
|
||||
self.new_doc.setVisible(False)
|
||||
self.template_name_label.setVisible(False)
|
||||
self.template_name.setVisible(False)
|
||||
|
||||
if mi:
|
||||
self.mi = mi
|
||||
else:
|
||||
@ -467,6 +476,27 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
self.rule = ('', txt)
|
||||
QDialog.accept(self)
|
||||
|
||||
def reject(self):
|
||||
QDialog.reject(self)
|
||||
if self.dialog_is_st_editor:
|
||||
parent = self.parent()
|
||||
while True:
|
||||
if hasattr(parent, 'reject'):
|
||||
parent.reject()
|
||||
break
|
||||
parent = parent.parent()
|
||||
if parent is None:
|
||||
break
|
||||
|
||||
|
||||
class EmbeddedTemplateDialog(TemplateDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
TemplateDialog.__init__(self, parent, "Foo", text_is_placeholder=True,
|
||||
dialog_is_st_editor=True)
|
||||
self.setParent(parent)
|
||||
self.setWindowFlags(Qt.Widget)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication([])
|
||||
|
@ -141,11 +141,68 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="textbox"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="template_name_label">
|
||||
<property name="text">
|
||||
<string>Template &name:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>template_name</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="template_name">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The name of the callable template</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel">
|
||||
<property name="text">
|
||||
<string>T&emplate:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>textbox</cstring>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPlainTextEdit" name="textbox">
|
||||
<property name="toolTip">
|
||||
<string>The template program text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="new_doc_label">
|
||||
<property name="text">
|
||||
<string>D&ocumentation:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>new_doc</cstring>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QTextEdit" name="new_doc">
|
||||
<property name="toolTip">
|
||||
<string>Documentation for the function being defined or edited</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel">
|
||||
<property name="text">
|
||||
@ -173,7 +230,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="6" column="1" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="font_size_box"/>
|
||||
@ -203,14 +260,24 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<item row="7" column="0" colspan="5">
|
||||
<widget class="QFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::HLine</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Template Function Reference</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>function</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Function &name:</string>
|
||||
@ -220,10 +287,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="function"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>&Function type:</string>
|
||||
@ -236,14 +303,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="10" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="func_type">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>&Documentation:</string>
|
||||
@ -256,7 +323,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>&Code:</string>
|
||||
@ -269,7 +336,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="11" column="1" colspan="3">
|
||||
<widget class="QPlainTextEdit" name="documentation">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
@ -279,17 +346,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="12" column="1" colspan="3">
|
||||
<widget class="QPlainTextEdit" name="source_code"/>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QLabel" name="template_tutorial">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<item row="14" column="1">
|
||||
<widget class="QLabel" name="template_func_reference">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
@ -1,211 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import traceback
|
||||
|
||||
from PyQt5.Qt import (Qt, QGridLayout, QLabel, QSpacerItem, QSizePolicy,
|
||||
QComboBox, QTextEdit, QHBoxLayout, QPushButton)
|
||||
|
||||
from calibre.gui2 import error_dialog
|
||||
from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
||||
from calibre.utils.formatter_functions import (formatter_functions,
|
||||
compile_user_function, compile_user_template_functions,
|
||||
load_user_template_functions, function_pref_is_python,
|
||||
function_pref_name)
|
||||
from polyglot.builtins import native_string_type, unicode_type
|
||||
|
||||
|
||||
class ConfigWidget(ConfigWidgetBase):
|
||||
|
||||
def genesis(self, gui):
|
||||
self.gui = gui
|
||||
self.db = gui.library_view.model().db
|
||||
|
||||
help_text = '<p>' + _('''
|
||||
Here you can add and remove stored templates used in template processing.
|
||||
You use a stored template in another template with the 'call' template
|
||||
function, as in 'call(somename, arguments...). Stored templates must use
|
||||
General Program Mode -- they must begin with the text 'program:'.
|
||||
In the stored template you get the arguments using the 'arguments()'
|
||||
template function, as in arguments(var1, var2, ...). The calling arguments
|
||||
are copied to the named variables.
|
||||
''') + '</p>'
|
||||
l = QGridLayout(self)
|
||||
w = QLabel(help_text)
|
||||
w.setWordWrap(True)
|
||||
l.addWidget(w, 0, 0, 1, 2)
|
||||
|
||||
lab = QLabel(_('&Name'))
|
||||
l.addWidget(lab, 1, 0)
|
||||
self.function_name = w = QComboBox(self)
|
||||
w.setEditable(True)
|
||||
lab.setBuddy(w)
|
||||
w.setToolTip(_('The name of the function, used in a call statement'))
|
||||
l.addWidget(w, 1, 1)
|
||||
|
||||
lab = QLabel(_('&Template'))
|
||||
l.addWidget(lab, 2, 0)
|
||||
lb = QHBoxLayout()
|
||||
self.program = w = TemplateLineEditor(self)
|
||||
w.setPlaceholderText(_('The GPM template.'))
|
||||
lab.setBuddy(w)
|
||||
lb.addWidget(w, stretch=1)
|
||||
self.editor_button = b = QPushButton(_('&Open template editor'))
|
||||
b.clicked.connect(w.open_editor)
|
||||
lb.addWidget(b)
|
||||
l.addLayout(lb, 2, 1)
|
||||
|
||||
lab = QLabel(_('&Documentation'))
|
||||
l.addWidget(lab, 3, 0, Qt.AlignTop)
|
||||
self.documentation = w = QTextEdit(self)
|
||||
w.setPlaceholderText(_('A description of the template. Whatever you wish ...'))
|
||||
lab.setBuddy(w)
|
||||
l.addWidget(w, 3, 1)
|
||||
|
||||
lb = QHBoxLayout()
|
||||
lb.addStretch(1)
|
||||
self.clear_button = w = QPushButton(_('C&lear'))
|
||||
lb.addWidget(w)
|
||||
self.delete_button = w = QPushButton(_('&Delete'))
|
||||
lb.addWidget(w)
|
||||
self.replace_button = w = QPushButton(_('&Replace'))
|
||||
lb.addWidget(w)
|
||||
self.create_button = w = QPushButton(_('&Create'))
|
||||
lb.addWidget(w)
|
||||
lb.addStretch(1)
|
||||
l.addLayout(lb, 9, 1)
|
||||
|
||||
l.addItem(QSpacerItem(10, 10, vPolicy=QSizePolicy.Expanding), 10, 0, -1, -1)
|
||||
self.setLayout(l)
|
||||
|
||||
|
||||
def initialize(self):
|
||||
self.funcs = {}
|
||||
for v in self.db.prefs.get('user_template_functions', []):
|
||||
if not function_pref_is_python(v):
|
||||
self.funcs.update({function_pref_name(v):compile_user_function(*v)})
|
||||
|
||||
self.build_function_names_box()
|
||||
self.function_name.currentIndexChanged[native_string_type].connect(self.function_index_changed)
|
||||
self.function_name.editTextChanged.connect(self.function_name_edited)
|
||||
self.documentation.textChanged.connect(self.enable_replace_button)
|
||||
self.program.textChanged.connect(self.enable_replace_button)
|
||||
self.create_button.clicked.connect(self.create_button_clicked)
|
||||
self.delete_button.clicked.connect(self.delete_button_clicked)
|
||||
self.create_button.setEnabled(False)
|
||||
self.delete_button.setEnabled(False)
|
||||
self.replace_button.setEnabled(False)
|
||||
self.clear_button.clicked.connect(self.clear_button_clicked)
|
||||
self.replace_button.clicked.connect(self.replace_button_clicked)
|
||||
|
||||
def enable_replace_button(self):
|
||||
self.replace_button.setEnabled(self.delete_button.isEnabled())
|
||||
|
||||
def clear_button_clicked(self):
|
||||
self.build_function_names_box()
|
||||
self.program.clear()
|
||||
self.documentation.clear()
|
||||
self.create_button.setEnabled(False)
|
||||
self.delete_button.setEnabled(False)
|
||||
|
||||
def build_function_names_box(self, scroll_to=''):
|
||||
self.function_name.blockSignals(True)
|
||||
func_names = sorted(self.funcs)
|
||||
self.function_name.clear()
|
||||
self.function_name.addItem('')
|
||||
self.function_name.addItems(func_names)
|
||||
self.function_name.setCurrentIndex(0)
|
||||
self.function_name.blockSignals(False)
|
||||
if scroll_to:
|
||||
idx = self.function_name.findText(scroll_to)
|
||||
if idx >= 0:
|
||||
self.function_name.setCurrentIndex(idx)
|
||||
|
||||
def delete_button_clicked(self):
|
||||
name = unicode_type(self.function_name.currentText())
|
||||
if name in self.funcs:
|
||||
del self.funcs[name]
|
||||
self.changed_signal.emit()
|
||||
self.create_button.setEnabled(True)
|
||||
self.delete_button.setEnabled(False)
|
||||
self.build_function_names_box()
|
||||
self.program.setReadOnly(False)
|
||||
else:
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('Function not defined'), show=True)
|
||||
|
||||
def create_button_clicked(self, use_name=None):
|
||||
self.changed_signal.emit()
|
||||
name = use_name if use_name else unicode_type(self.function_name.currentText())
|
||||
for k,v in formatter_functions().get_functions().items():
|
||||
if k == name and v.is_python:
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('Name %s is already used for template function')%(name,), show=True)
|
||||
try:
|
||||
prog = unicode_type(self.program.text())
|
||||
if not prog.startswith('program:'):
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('The stored template must begin with "program:"'), show=True)
|
||||
|
||||
cls = compile_user_function(name, unicode_type(self.documentation.toPlainText()),
|
||||
0, prog)
|
||||
self.funcs[name] = cls
|
||||
self.build_function_names_box(scroll_to=name)
|
||||
except:
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('Exception while storing template'), show=True,
|
||||
det_msg=traceback.format_exc())
|
||||
|
||||
def function_name_edited(self, txt):
|
||||
self.documentation.setReadOnly(False)
|
||||
self.create_button.setEnabled(True)
|
||||
self.replace_button.setEnabled(False)
|
||||
self.program.setReadOnly(False)
|
||||
|
||||
def function_index_changed(self, txt):
|
||||
txt = unicode_type(txt)
|
||||
self.create_button.setEnabled(False)
|
||||
if not txt:
|
||||
self.program.clear()
|
||||
self.documentation.clear()
|
||||
self.documentation.setReadOnly(False)
|
||||
return
|
||||
func = self.funcs[txt]
|
||||
self.documentation.setText(func.doc)
|
||||
self.program.setText(func.program_text)
|
||||
self.delete_button.setEnabled(True)
|
||||
self.program.setReadOnly(False)
|
||||
self.replace_button.setEnabled(False)
|
||||
|
||||
def replace_button_clicked(self):
|
||||
name = unicode_type(self.function_name.currentText())
|
||||
self.delete_button_clicked()
|
||||
self.create_button_clicked(use_name=name)
|
||||
|
||||
def refresh_gui(self, gui):
|
||||
pass
|
||||
|
||||
def commit(self):
|
||||
# formatter_functions().reset_to_builtins()
|
||||
pref_value = [v for v in self.db.prefs.get('user_template_functions', [])
|
||||
if function_pref_is_python(v)]
|
||||
for v in self.funcs.values():
|
||||
pref_value.append(v.to_pref())
|
||||
self.db.new_api.set_pref('user_template_functions', pref_value)
|
||||
funcs = compile_user_template_functions(pref_value)
|
||||
self.db.new_api.set_user_template_functions(funcs)
|
||||
self.gui.library_view.model().refresh()
|
||||
load_user_template_functions(self.db.library_id, [], funcs)
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from PyQt5.Qt import QApplication
|
||||
app = QApplication([])
|
||||
test_widget('Advanced', 'StoredTemplates')
|
@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import json, traceback
|
||||
|
||||
from PyQt5.Qt import QDialogButtonBox
|
||||
from PyQt5.Qt import Qt, QDialogButtonBox, QSizePolicy
|
||||
|
||||
from calibre.gui2 import error_dialog, warning_dialog
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
||||
@ -78,6 +78,17 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
</p>
|
||||
''')
|
||||
self.textBrowser.setHtml(help_text)
|
||||
help_text = '<p>' + _('''
|
||||
Here you can add and remove stored templates used in template processing.
|
||||
You use a stored template in another template with the 'call' template
|
||||
function, as in 'call(somename, arguments...). Stored templates must use
|
||||
General Program Mode -- they must begin with the text 'program:'.
|
||||
In the stored template you get the arguments using the 'arguments()'
|
||||
template function, as in arguments(var1, var2, ...). The calling arguments
|
||||
are copied to the named variables.
|
||||
''') + '</p>'
|
||||
self.st_textBrowser.setHtml(help_text)
|
||||
self.st_textBrowser.adjustSize()
|
||||
|
||||
def initialize(self):
|
||||
try:
|
||||
@ -92,6 +103,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
|
||||
self.builtins = formatter_functions().get_builtins_and_aliases()
|
||||
|
||||
self.st_funcs = {}
|
||||
for v in self.db.prefs.get('user_template_functions', []):
|
||||
if not function_pref_is_python(v):
|
||||
self.st_funcs.update({function_pref_name(v):compile_user_function(*v)})
|
||||
|
||||
self.build_function_names_box()
|
||||
self.function_name.currentIndexChanged[native_string_type].connect(self.function_index_changed)
|
||||
self.function_name.editTextChanged.connect(self.function_name_edited)
|
||||
@ -108,6 +124,24 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.program.setTabStopWidth(20)
|
||||
self.highlighter = PythonHighlighter(self.program.document())
|
||||
|
||||
self.st_build_function_names_box()
|
||||
self.template_editor.template_name.currentIndexChanged[native_string_type].connect(self.st_function_index_changed)
|
||||
self.template_editor.template_name.editTextChanged.connect(self.st_template_name_edited)
|
||||
self.template_editor.new_doc.textChanged.connect(self.st_enable_replace_button)
|
||||
self.template_editor.textbox.textChanged.connect(self.st_enable_replace_button)
|
||||
self.st_create_button.clicked.connect(self.st_create_button_clicked)
|
||||
self.st_delete_button.clicked.connect(self.st_delete_button_clicked)
|
||||
self.st_create_button.setEnabled(False)
|
||||
self.st_delete_button.setEnabled(False)
|
||||
self.st_replace_button.setEnabled(False)
|
||||
self.st_clear_button.clicked.connect(self.st_clear_button_clicked)
|
||||
self.st_replace_button.clicked.connect(self.st_replace_button_clicked)
|
||||
|
||||
self.st_button_layout.insertSpacing(0, 90)
|
||||
self.template_editor.new_doc.setFixedHeight(50)
|
||||
|
||||
# Python funtion tab
|
||||
|
||||
def enable_replace_button(self):
|
||||
self.replace_button.setEnabled(self.delete_button.isEnabled())
|
||||
|
||||
@ -228,12 +262,98 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
def refresh_gui(self, gui):
|
||||
pass
|
||||
|
||||
# Stored template tab
|
||||
|
||||
def st_enable_replace_button(self):
|
||||
self.st_replace_button.setEnabled(self.st_delete_button.isEnabled())
|
||||
|
||||
def st_clear_button_clicked(self):
|
||||
self.st_build_function_names_box()
|
||||
self.template_editor.textbox.clear()
|
||||
self.template_editor.new_doc.clear()
|
||||
self.st_create_button.setEnabled(False)
|
||||
self.st_delete_button.setEnabled(False)
|
||||
|
||||
def st_build_function_names_box(self, scroll_to=''):
|
||||
self.template_editor.template_name.blockSignals(True)
|
||||
func_names = sorted(self.st_funcs)
|
||||
self.template_editor.template_name.clear()
|
||||
self.template_editor.template_name.addItem('')
|
||||
self.template_editor.template_name.addItems(func_names)
|
||||
self.template_editor.template_name.setCurrentIndex(0)
|
||||
self.template_editor.template_name.blockSignals(False)
|
||||
if scroll_to:
|
||||
idx = self.template_editor.template_name.findText(scroll_to)
|
||||
if idx >= 0:
|
||||
self.template_editor.template_name.setCurrentIndex(idx)
|
||||
|
||||
def st_delete_button_clicked(self):
|
||||
name = unicode_type(self.template_editor.template_name.currentText())
|
||||
if name in self.st_funcs:
|
||||
del self.st_funcs[name]
|
||||
self.changed_signal.emit()
|
||||
self.st_create_button.setEnabled(True)
|
||||
self.st_delete_button.setEnabled(False)
|
||||
self.st_build_function_names_box()
|
||||
self.template_editor.textbox.setReadOnly(False)
|
||||
else:
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('Function not defined'), show=True)
|
||||
|
||||
def st_create_button_clicked(self, use_name=None):
|
||||
self.changed_signal.emit()
|
||||
name = use_name if use_name else unicode_type(self.template_editor.template_name.currentText())
|
||||
for k,v in formatter_functions().get_functions().items():
|
||||
if k == name and v.is_python:
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('Name %s is already used for template function')%(name,), show=True)
|
||||
try:
|
||||
prog = unicode_type(self.template_editor.textbox.toPlainText())
|
||||
if not prog.startswith('program:'):
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('The stored template must begin with "program:"'), show=True)
|
||||
|
||||
cls = compile_user_function(name, unicode_type(self.template_editor.new_doc.toPlainText()),
|
||||
0, prog)
|
||||
self.st_funcs[name] = cls
|
||||
self.st_build_function_names_box(scroll_to=name)
|
||||
except:
|
||||
error_dialog(self.gui, _('Stored templates'),
|
||||
_('Exception while storing template'), show=True,
|
||||
det_msg=traceback.format_exc())
|
||||
|
||||
def st_template_name_edited(self, txt):
|
||||
self.st_create_button.setEnabled(True)
|
||||
self.st_replace_button.setEnabled(False)
|
||||
self.template_editor.textbox.setReadOnly(False)
|
||||
|
||||
def st_function_index_changed(self, txt):
|
||||
txt = unicode_type(txt)
|
||||
self.st_create_button.setEnabled(False)
|
||||
if not txt:
|
||||
self.template_editor.textbox.clear()
|
||||
self.template_editor.new_doc.clear()
|
||||
return
|
||||
func = self.st_funcs[txt]
|
||||
self.template_editor.new_doc.setPlainText(func.doc)
|
||||
self.template_editor.textbox.setPlainText(func.program_text)
|
||||
self.st_delete_button.setEnabled(True)
|
||||
self.template_editor.textbox.setReadOnly(False)
|
||||
self.st_replace_button.setEnabled(False)
|
||||
|
||||
def st_replace_button_clicked(self):
|
||||
name = unicode_type(self.template_editor.template_name.currentText())
|
||||
self.st_delete_button_clicked()
|
||||
self.st_create_button_clicked(use_name=name)
|
||||
|
||||
def commit(self):
|
||||
pref_value = [v for v in self.db.prefs.get('user_template_functions', [])
|
||||
if not function_pref_is_python(v)]
|
||||
pref_value = []
|
||||
for name, cls in iteritems(self.funcs):
|
||||
print(name)
|
||||
if name not in self.builtins:
|
||||
pref_value.append(cls.to_pref())
|
||||
for v in self.st_funcs.values():
|
||||
pref_value.append(v.to_pref())
|
||||
self.db.new_api.set_pref('user_template_functions', pref_value)
|
||||
funcs = compile_user_template_functions(pref_value)
|
||||
self.db.new_api.set_user_template_functions(funcs)
|
||||
|
@ -6,155 +6,251 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>798</width>
|
||||
<height>672</height>
|
||||
<width>788</width>
|
||||
<height>663</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>&Function:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>function_name</cstring>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>&Stored Templates</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2" stretch="0">
|
||||
<widget class="QTextBrowser" name="st_textBrowser"/>
|
||||
</item>
|
||||
<item row="3" column="1" stretch="1">
|
||||
<widget class="EmbeddedTemplateDialog" name="template_editor">
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="function_name">
|
||||
<property name="toolTip">
|
||||
<string>Enter the name of the function to create.</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Argument &count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>argument_count</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="argument_count">
|
||||
<property name="toolTip">
|
||||
<string>Set this to -1 if the function takes a variable number of arguments</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QTextEdit" name="documentation"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>&Documentation:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>documentation</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item row="3" column="0">
|
||||
<layout class="QVBoxLayout" name="st_button_layout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="clear_button">
|
||||
<widget class="QPushButton" name="st_clear_button">
|
||||
<property name="text">
|
||||
<string>&Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="delete_button">
|
||||
<widget class="QPushButton" name="st_delete_button">
|
||||
<property name="text">
|
||||
<string>&Delete</string>
|
||||
<string>D&elete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="replace_button">
|
||||
<widget class="QPushButton" name="st_replace_button">
|
||||
<property name="text">
|
||||
<string>&Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="create_button">
|
||||
<widget class="QPushButton" name="st_create_button">
|
||||
<property name="text">
|
||||
<string>C&reate</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>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="horizontalLayout1">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>&Program code (Follow Python indenting rules):</string>
|
||||
<item row="5" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>program</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="program">
|
||||
<property name="minimumSize">
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
<width>20</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="documentTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="tabStopWidth">
|
||||
<number>30</number>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>&Template Functions</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>F&unction:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>function_name</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="function_name">
|
||||
<property name="toolTip">
|
||||
<string>Enter the name of the function to create.</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Argument &count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>argument_count</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="argument_count">
|
||||
<property name="toolTip">
|
||||
<string>Set this to -1 if the function takes a variable number of arguments</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QTextEdit" name="documentation"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>D&ocumentation:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>documentation</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="clear_button">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="delete_button">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="replace_button">
|
||||
<property name="text">
|
||||
<string>Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="create_button">
|
||||
<property name="text">
|
||||
<string>C&reate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="horizontalLayout1">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>P&rogram code (Follow Python indenting rules):</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>program</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="program">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="documentTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="tabStopWidth">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>EmbeddedTemplateDialog</class>
|
||||
<extends>TemplateDialog</extends>
|
||||
<header>calibre/gui2/dialogs/template_dialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TemplateDialog</class>
|
||||
<extends>QDialog</extends>
|
||||
<header>calibre/gui2/dialogs/template_dialog.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user