diff --git a/picard/ui/scripteditor.py b/picard/ui/scripteditor.py index 79c78b4aa..1ed05004e 100644 --- a/picard/ui/scripteditor.py +++ b/picard/ui/scripteditor.py @@ -38,18 +38,21 @@ from picard.file import File from picard.script import ( ScriptError, ScriptParser, + script_function_documentation_all, ) from picard.util.settingsoverride import SettingsOverride from picard.ui import ( + FONT_FAMILY_MONOSPACE, PicardDialog, SingletonDialog, ) from picard.ui.options import OptionsPage from picard.ui.options.scripting import ( + DOCUMENTATION_HTML_TEMPLATE, ScriptCheckError, - ScriptingDocumentationDialog, ) +from picard.ui.theme import theme from picard.ui.ui_scripteditor import Ui_ScriptEditor @@ -289,13 +292,51 @@ class ScriptEditorPage(PicardDialog, SingletonDialog): self.ui.file_naming_format.setEnabled(True) self.ui.file_naming_format_reload.setEnabled(True) + def process_html(html, function): + if not html: + html = '' + template = '
%s%s
%s
' + if function.module is not None and function.module != 'picard.script.functions': + module = ' [' + function.module + ']' + else: + module = '' + try: + firstline, remaining = html.split("\n", 1) + return template % (firstline, module, remaining) + except ValueError: + return template % ("$%s()" % function.name, module, html) + + funcdoc = script_function_documentation_all( + fmt='html', + postprocessor=process_html, + ) + + if self.ui.textBrowser.layoutDirection() == QtCore.Qt.RightToLeft: + text_direction = 'rtl' + else: + text_direction = 'ltr' + + html = DOCUMENTATION_HTML_TEMPLATE % { + 'html': "
%s
" % funcdoc, + 'script_function_fg': theme.syntax_theme.func.name(), + 'monospace_font': FONT_FAMILY_MONOSPACE, + 'dir': text_direction, + 'inline_start': 'right' if text_direction == 'rtl' else 'left' + } + # Scripting code is always left-to-right. Qt does not support the dir + # attribute on inline tags, insert explicit left-right-marks instead. + html = html.replace('', '‎') + self.ui.textBrowser.setHtml(html) + + self.ui.textBrowser.hide() + self.ui.show_documentation.stateChanged.connect(self.toggle_documentation) + self.ui.file_naming_format.textChanged.connect(self.check_formats) self.ui.file_naming_format_reload.clicked.connect(self.load) self.ui.file_naming_word_wrap.stateChanged.connect(self.toggle_wordwrap) self.ui.import_script.clicked.connect(self.import_script) self.ui.export_script.clicked.connect(self.export_script) - self.ui.scripting_documentation_button.clicked.connect(self.show_scripting_documentation) self.ui.example_filename_sample_files_button.clicked.connect(self.update_example_files) self._sampled_example_files = [] @@ -346,6 +387,12 @@ class ScriptEditorPage(PicardDialog, SingletonDialog): self.update_examples() return False + def toggle_documentation(self): + if self.ui.show_documentation.isChecked(): + self.ui.textBrowser.show() + else: + self.ui.textBrowser.hide() + def select_preset_script(self): """Set the current script to one of the preset example scripts. """ @@ -389,11 +436,6 @@ class ScriptEditorPage(PicardDialog, SingletonDialog): """ self.ui.file_naming_format.setPlainText(self.EMPTY_SCRIPT if not script_text else str(script_text).strip()) - def show_scripting_documentation(self): - """Show the scripting documentation in a new window. - """ - ScriptingDocumentationDialog.show_instance(parent=self) - def update_example_files(self): """Update the before and after file naming examples list. """ diff --git a/picard/ui/ui_scripteditor.py b/picard/ui/ui_scripteditor.py index 4343c1f0a..61525620f 100644 --- a/picard/ui/ui_scripteditor.py +++ b/picard/ui/ui_scripteditor.py @@ -40,9 +40,8 @@ class Ui_ScriptEditor(object): self.frame_4.setFrameShape(QtWidgets.QFrame.NoFrame) self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_4.setObjectName("frame_4") - self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame_4) - self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) - self.verticalLayout_2.setObjectName("verticalLayout_2") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.frame_4) + self.verticalLayout_5.setObjectName("verticalLayout_5") self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setContentsMargins(-1, -1, -1, 0) self.horizontalLayout_2.setObjectName("horizontalLayout_2") @@ -70,15 +69,34 @@ class Ui_ScriptEditor(object): self.file_naming_word_wrap = QtWidgets.QCheckBox(self.frame_4) self.file_naming_word_wrap.setObjectName("file_naming_word_wrap") self.horizontalLayout_2.addWidget(self.file_naming_word_wrap) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - self.file_naming_format = ScriptTextEdit(self.frame_4) + self.show_documentation = QtWidgets.QCheckBox(self.frame_4) + self.show_documentation.setObjectName("show_documentation") + self.horizontalLayout_2.addWidget(self.show_documentation) + self.verticalLayout_5.addLayout(self.horizontalLayout_2) + self.frame = QtWidgets.QFrame(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMinimumSize(QtCore.QSize(0, 200)) + self.frame.setFrameShape(QtWidgets.QFrame.NoFrame) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.splitter_4 = QtWidgets.QSplitter(self.frame) + self.splitter_4.setOrientation(QtCore.Qt.Horizontal) + self.splitter_4.setObjectName("splitter_4") + self.file_naming_format = ScriptTextEdit(self.splitter_4) self.file_naming_format.setEnabled(False) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(5) sizePolicy.setHeightForWidth(self.file_naming_format.sizePolicy().hasHeightForWidth()) self.file_naming_format.setSizePolicy(sizePolicy) - self.file_naming_format.setMinimumSize(QtCore.QSize(0, 200)) + self.file_naming_format.setMinimumSize(QtCore.QSize(0, 50)) self.file_naming_format.viewport().setProperty("cursor", QtGui.QCursor(QtCore.Qt.IBeamCursor)) self.file_naming_format.setTabChangesFocus(False) self.file_naming_format.setLineWrapMode(QtWidgets.QTextEdit.NoWrap) @@ -86,12 +104,17 @@ class Ui_ScriptEditor(object): self.file_naming_format.setAcceptRichText(False) self.file_naming_format.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction) self.file_naming_format.setObjectName("file_naming_format") - self.verticalLayout_2.addWidget(self.file_naming_format) + self.textBrowser = QtWidgets.QTextBrowser(self.splitter_4) + self.textBrowser.setEnabled(True) + self.textBrowser.setMinimumSize(QtCore.QSize(0, 0)) + self.textBrowser.setObjectName("textBrowser") + self.verticalLayout_2.addWidget(self.splitter_4) + self.verticalLayout_5.addWidget(self.frame) self.renaming_error = QtWidgets.QLabel(self.frame_4) self.renaming_error.setText("") self.renaming_error.setAlignment(QtCore.Qt.AlignCenter) self.renaming_error.setObjectName("renaming_error") - self.verticalLayout_2.addWidget(self.renaming_error) + self.verticalLayout_5.addWidget(self.renaming_error) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setContentsMargins(-1, 0, -1, -1) self.horizontalLayout_4.setObjectName("horizontalLayout_4") @@ -100,16 +123,11 @@ class Ui_ScriptEditor(object): self.horizontalLayout_4.addWidget(self.example_filename_sample_files_button) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem) - self.scripting_documentation_button = QtWidgets.QPushButton(self.frame_4) - self.scripting_documentation_button.setObjectName("scripting_documentation_button") - self.horizontalLayout_4.addWidget(self.scripting_documentation_button) - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_4.addItem(spacerItem1) self.file_naming_format_reload = QtWidgets.QPushButton(self.frame_4) self.file_naming_format_reload.setObjectName("file_naming_format_reload") self.horizontalLayout_4.addWidget(self.file_naming_format_reload) - spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_4.addItem(spacerItem2) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) self.import_script = QtWidgets.QPushButton(self.frame_4) self.import_script.setObjectName("import_script") self.horizontalLayout_4.addWidget(self.import_script) @@ -119,7 +137,7 @@ class Ui_ScriptEditor(object): self.file_naming_editor_save = QtWidgets.QPushButton(self.frame_4) self.file_naming_editor_save.setObjectName("file_naming_editor_save") self.horizontalLayout_4.addWidget(self.file_naming_editor_save) - self.verticalLayout_2.addLayout(self.horizontalLayout_4) + self.verticalLayout_5.addLayout(self.horizontalLayout_4) self.groupBox = QtWidgets.QGroupBox(self.splitter_2) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) @@ -171,6 +189,10 @@ class Ui_ScriptEditor(object): self.verticalLayout_6.addWidget(self.example_filename_after) self.verticalLayout.addWidget(self.splitter) self.verticalLayout_3.addWidget(self.splitter_2) + self.splitter_3 = QtWidgets.QSplitter(ScriptEditor) + self.splitter_3.setGeometry(QtCore.QRect(0, 0, 100, 30)) + self.splitter_3.setOrientation(QtCore.Qt.Horizontal) + self.splitter_3.setObjectName("splitter_3") self.retranslateUi(ScriptEditor) QtCore.QMetaObject.connectSlotsByName(ScriptEditor) @@ -182,10 +204,9 @@ class Ui_ScriptEditor(object): self.preset_naming_script_select.setText(_("Select Preset")) self.file_naming_word_wrap.setToolTip(_("Word wrap long lines in the editor")) self.file_naming_word_wrap.setText(_("Word wrap text")) + self.show_documentation.setText(_("Show Documentation")) self.example_filename_sample_files_button.setToolTip(_("Up to 10 items chosen at random from files selected in the main window")) self.example_filename_sample_files_button.setText(_("Reload Examples")) - self.scripting_documentation_button.setToolTip(_("Display the scripting documentation in a new window")) - self.scripting_documentation_button.setText(_("Scripting Documentation")) self.file_naming_format_reload.setToolTip(_("Reload the script currently saved in the configuration option settings")) self.file_naming_format_reload.setText(_("Reload Script")) self.import_script.setToolTip(_("Import a file to replace the current script")) diff --git a/ui/scripteditor.ui b/ui/scripteditor.ui index f1797bc40..3aa5b45a3 100644 --- a/ui/scripteditor.ui +++ b/ui/scripteditor.ui @@ -62,19 +62,7 @@ QFrame::Raised - - - 0 - - - 0 - - - 0 - - - 0 - + @@ -135,17 +123,21 @@ + + + + Show Documentation + + + - - - false - + - + 0 - 5 + 0 @@ -154,24 +146,79 @@ 200 - - IBeamCursor + + QFrame::NoFrame - - false - - - QTextEdit::NoWrap - - - 20 - - - false - - - Qt::TextEditorInteraction + + QFrame::Raised + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + false + + + + 0 + 5 + + + + + 0 + 50 + + + + IBeamCursor + + + false + + + QTextEdit::NoWrap + + + 20 + + + false + + + Qt::TextEditorInteraction + + + + + true + + + + 0 + 0 + + + + + + @@ -212,29 +259,6 @@ - - - - Display the scripting documentation in a new window - - - Scripting Documentation - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -432,6 +456,19 @@ + + + + 0 + 0 + 100 + 30 + + + + Qt::Horizontal + +