class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = "advanced" SORT_ORDER = 30 ACTIVE = True options = [ BoolOption("setting", "enable_tagger_script", False), TextOption("setting", "tagger_script", ""), ] STYLESHEET_ERROR = "QWidget { background-color: #f55; color: white; font-weight:bold }" def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.connect(self.ui.tagger_script, QtCore.SIGNAL("textChanged()"), self.live_checker) def live_checker(self): self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError, e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return
def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_checker)
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = "advanced" SORT_ORDER = 30 ACTIVE = True options = [ BoolOption("setting", "enable_tagger_script", False), TextOption("setting", "tagger_script", ""), ] STYLESHEET_ERROR = "QWidget { background-color: #f55; color: white; font-weight:bold }" def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_checker) def live_checker(self): self.ui.script_error.setStyleSheet(""); self.ui.script_error.setText("") try: self.check() except OptionsCheckError, e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR); self.ui.script_error.setText(e.info) return
def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.ui.tagger_script.setEnabled(False) self.ui.scripting_options_splitter.setStretchFactor(1, 2) self.move_view = MoveableListView(self.ui.script_list, self.ui.move_up_button, self.ui.move_down_button) self.ui.scripting_documentation_button.clicked.connect( self.show_scripting_documentation) self.ui.scripting_documentation_button.setToolTip( _("Show scripting documentation in new window.")) self.ui.import_button.clicked.connect(self.import_script) self.ui.import_button.setToolTip( _("Import a script file as a new script.")) self.ui.export_button.clicked.connect(self.export_script) self.ui.export_button.setToolTip( _("Export the current script to a file.")) self.FILE_TYPE_ALL = _("All files") + " (*)" self.FILE_TYPE_SCRIPT = _("Picard script files") + " (*.pts *.txt)" self.FILE_TYPE_PACKAGE = _( "Picard tagging script package") + " (*.ptsp *.yaml)" self.ui.script_list.signal_reset_selected_item.connect( self.reset_selected_item)
def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.ui.tagger_script.setEnabled(False) self.ui.scripting_options_splitter.setStretchFactor(1, 2) self.move_view = MoveableListView(self.ui.script_list, self.ui.move_up_button, self.ui.move_down_button) self.ui.scripting_documentation_button.clicked.connect(self.show_scripting_documentation)
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = "advanced" SORT_ORDER = 30 ACTIVE = True options = [ config.BoolOption("setting", "enable_tagger_script", False), config.TextOption("setting", "tagger_script", ""), ] def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_checker) def live_checker(self): self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(unicode(self.ui.tagger_script.toPlainText())) except Exception as e: raise OptionsCheckError(_("Script Error"), str(e)) def load(self): self.ui.enable_tagger_script.setChecked( config.setting["enable_tagger_script"]) self.ui.tagger_script.document().setPlainText( config.setting["tagger_script"]) args = { "picard-doc-scripting-url": PICARD_URLS['doc_scripting'], } text = _(u'<a href="%(picard-doc-scripting-url)s">Open Scripting' ' Documentation in your browser</a>') % args self.ui.scripting_doc_link.setText(text) def save(self): config.setting[ "enable_tagger_script"] = self.ui.enable_tagger_script.isChecked() config.setting["tagger_script"] = self.ui.tagger_script.toPlainText() def display_error(self, error): pass
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = "advanced" SORT_ORDER = 30 ACTIVE = True options = [ config.BoolOption("setting", "enable_tagger_script", False), config.TextOption("setting", "tagger_script", ""), ] def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_checker) def live_checker(self): self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(unicode(self.ui.tagger_script.toPlainText())) except Exception as e: raise OptionsCheckError(_("Script Error"), str(e)) def load(self): self.ui.enable_tagger_script.setChecked(config.setting["enable_tagger_script"]) self.ui.tagger_script.document().setPlainText(config.setting["tagger_script"]) args = { "picard-doc-scripting-url": PICARD_URLS['doc_scripting'], } text = _(u'<a href="%(picard-doc-scripting-url)s">Open Scripting' ' Documentation in your browser</a>') % args self.ui.scripting_doc_link.setText(text) def save(self): config.setting["enable_tagger_script"] = self.ui.enable_tagger_script.isChecked() config.setting["tagger_script"] = self.ui.tagger_script.toPlainText() def display_error(self, error): pass
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = "advanced" SORT_ORDER = 30 ACTIVE = True options = [ config.BoolOption("setting", "enable_tagger_script", False), config.TextOption("setting", "tagger_script", ""), ] STYLESHEET_ERROR = "QWidget { background-color: #f55; color: white; font-weight:bold }" def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_checker) def live_checker(self): self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(unicode(self.ui.tagger_script.toPlainText())) except Exception as e: raise OptionsCheckError(_("Script Error"), str(e)) def load(self): self.ui.enable_tagger_script.setChecked(config.setting["enable_tagger_script"]) self.ui.tagger_script.document().setPlainText(config.setting["tagger_script"]) def save(self): config.setting["enable_tagger_script"] = self.ui.enable_tagger_script.isChecked() config.setting["tagger_script"] = self.ui.tagger_script.toPlainText() def display_error(self, error): pass
def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.ui.tagger_script.setEnabled(False) self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2) font = QtGui.QFont('Monospace') font.setStyleHint(QtGui.QFont.TypeWriter) self.ui.tagger_script.setFont(font) self.move_view = MoveableListView(self.ui.script_list, self.ui.move_up_button, self.ui.move_down_button)
def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_update_and_check) self.ui.script_name.textChanged.connect(self.script_name_changed) self.ui.add_script.clicked.connect(self.add_to_list_of_scripts) self.ui.script_list.itemSelectionChanged.connect(self.script_selected) self.ui.tagger_script.setEnabled(False) self.ui.script_name.setEnabled(False) self.listitem_to_scriptitem = {} self.list_of_scripts = [] self.last_selected_script_pos = 0
def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_update_and_check) self.ui.script_name.textChanged.connect(self.script_name_changed) self.ui.add_script.clicked.connect(self.add_to_list_of_scripts) self.ui.script_list.itemSelectionChanged.connect(self.script_selected) self.ui.tagger_script.setEnabled(False) self.ui.script_name.setEnabled(False) self.listitem_to_scriptitem = {} self.list_of_scripts = [] self.last_selected_script_pos = 0 self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2) self.delete_shortcut = QtWidgets.QShortcut(self.ui.script_list) self.delete_shortcut.setKey(QtGui.QKeySequence.Delete) self.delete_shortcut.activated.connect(self.delete_selected_script)
def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_update_and_check) self.ui.script_name.textChanged.connect(self.script_name_changed) self.ui.add_script.clicked.connect(self.add_to_list_of_scripts) self.ui.script_list.itemSelectionChanged.connect(self.script_selected) self.ui.tagger_script.setEnabled(False) self.ui.script_name.setEnabled(False) self.listitem_to_scriptitem = {} self.list_of_scripts = [] self.last_selected_script_pos = 0 self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2)
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = None SORT_ORDER = 85 ACTIVE = True HELP_URL = '/config/options_scripting.html' options = [ config.BoolOption("setting", "enable_tagger_scripts", False), config.ListOption("setting", "list_of_scripts", []), config.IntOption("persist", "last_selected_script_pos", 0), config.Option("persist", "scripting_splitter", QtCore.QByteArray()), ] def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.ui.tagger_script.setEnabled(False) self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2) self.move_view = MoveableListView(self.ui.script_list, self.ui.move_up_button, self.ui.move_down_button) self.ui.scripting_documentation_button.clicked.connect( self.show_scripting_documentation) self.scripting_documentation_shown = None def show_scripting_documentation(self): if not self.scripting_documentation_shown: self.scriptdoc_dialog = ScriptingDocumentationDialog(parent=self) self.scriptdoc_dialog.show() else: self.scriptdoc_dialog.raise_() self.scriptdoc_dialog.activateWindow() def enable_tagger_scripts_toggled(self, on): if on and self.ui.script_list.count() == 0: self.ui.script_list.add_script() def script_selected(self): items = self.ui.script_list.selectedItems() if items: item = items[0] self.ui.tagger_script.setEnabled(True) self.ui.tagger_script.setText(item.script) self.ui.tagger_script.setFocus(QtCore.Qt.OtherFocusReason) else: self.ui.tagger_script.setEnabled(False) self.ui.tagger_script.setText("") def live_update_and_check(self): items = self.ui.script_list.selectedItems() if items: script = items[0] script.script = self.ui.tagger_script.toPlainText() self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(self.ui.tagger_script.toPlainText()) except Exception as e: raise ScriptCheckError(_("Script Error"), str(e)) def restore_defaults(self): # Remove existing scripts self.ui.script_list.clear() self.ui.tagger_script.setText("") super().restore_defaults() def load(self): self.ui.enable_tagger_scripts.setChecked( config.setting["enable_tagger_scripts"]) for pos, name, enabled, text in config.setting["list_of_scripts"]: list_item = ScriptListWidgetItem(name, enabled, text) self.ui.script_list.addItem(list_item) # Select the last selected script item last_selected_script_pos = config.persist["last_selected_script_pos"] last_selected_script = self.ui.script_list.item( last_selected_script_pos) if last_selected_script: self.ui.script_list.setCurrentItem(last_selected_script) last_selected_script.setSelected(True) self.restore_state() def _all_scripts(self): for row in range(0, self.ui.script_list.count()): item = self.ui.script_list.item(row) yield item.get_all() @restore_method def restore_state(self): # Preserve previous splitter position self.ui.splitter.restoreState(config.persist["scripting_splitter"]) def save(self): config.setting[ "enable_tagger_scripts"] = self.ui.enable_tagger_scripts.isChecked( ) config.setting["list_of_scripts"] = list(self._all_scripts()) config.persist[ "last_selected_script_pos"] = self.ui.script_list.currentRow() config.persist["scripting_splitter"] = self.ui.splitter.saveState() def display_error(self, error): # Ignore scripting errors, those are handled inline if not isinstance(error, ScriptCheckError): super().display_error(error)
def __init__(self, parent=None): super(ScriptingOptionsPage, self).__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_checker)
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = None SORT_ORDER = 85 ACTIVE = True options = [ config.BoolOption("setting", "enable_tagger_scripts", False), config.ListOption("setting", "list_of_scripts", []), config.IntOption("persist", "last_selected_script_pos", 0), config.Option("persist", "scripting_splitter", QtCore.QByteArray()), ] def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_update_and_check) self.ui.script_name.textChanged.connect(self.script_name_changed) self.ui.add_script.clicked.connect(self.add_to_list_of_scripts) self.ui.script_list.itemSelectionChanged.connect(self.script_selected) self.ui.tagger_script.setEnabled(False) self.ui.script_name.setEnabled(False) self.listitem_to_scriptitem = {} self.list_of_scripts = [] self.last_selected_script_pos = 0 self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2) def script_name_changed(self): items = self.ui.script_list.selectedItems() if items: script = self.listitem_to_scriptitem[items[0]] script.name = self.ui.script_name.text() list_widget = self.ui.script_list.itemWidget(items[0]) list_widget.update_name(script.name) self.list_of_scripts[script.pos] = script.get_all() def script_selected(self): items = self.ui.script_list.selectedItems() if items: self.ui.tagger_script.setEnabled(True) self.ui.script_name.setEnabled(True) script = self.listitem_to_scriptitem[items[0]] self.ui.tagger_script.setText(script.text) self.ui.script_name.setText(script.name) self.last_selected_script_pos = script.pos def setSignals(self, list_widget, item): list_widget.set_up_connection( lambda: self.move_script(self.ui.script_list.row(item), 1)) list_widget.set_down_connection( lambda: self.move_script(self.ui.script_list.row(item), -1)) list_widget.set_remove_connection( lambda: self.remove_from_list_of_scripts( self.ui.script_list.row(item))) list_widget.set_checkbox_connection(lambda: self.update_check_state( item, list_widget.checkbox_state())) list_widget.set_rename_connection(lambda: self.rename_script(item)) def rename_script(self, item): item.setSelected(True) self.ui.script_name.setFocus() self.ui.script_name.selectAll() def update_check_state(self, item, checkbox_state): script = self.listitem_to_scriptitem[item] script.enabled = checkbox_state self.list_of_scripts[script.pos] = script.get_all() def add_to_list_of_scripts(self): count = self.ui.script_list.count() numbered_name = _(DEFAULT_NUMBERED_SCRIPT_NAME) % (count + 1) script = ScriptItem(pos=count, name=numbered_name) list_item = HashableListWidgetItem() list_widget = AdvancedScriptItem(numbered_name) self.setSignals(list_widget, list_item) self.ui.script_list.addItem(list_item) self.ui.script_list.setItemWidget(list_item, list_widget) self.listitem_to_scriptitem[list_item] = script self.list_of_scripts.append(script.get_all()) list_item.setSelected(True) def update_script_positions(self): for i, script in enumerate(self.list_of_scripts): self.list_of_scripts[i] = (i, script[1], script[2], script[3]) item = self.ui.script_list.item(i) self.listitem_to_scriptitem[item].pos = i def remove_from_list_of_scripts(self, row): item = self.ui.script_list.item(row) confirm_remove = QtWidgets.QMessageBox() msg = _("Are you sure you want to remove this script?") reply = confirm_remove.question(confirm_remove, _('Confirm Remove'), msg, QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No) if item and reply == QtWidgets.QMessageBox.Yes: item = self.ui.script_list.takeItem(row) script = self.listitem_to_scriptitem[item] del self.listitem_to_scriptitem[item] del self.list_of_scripts[script.pos] del script item = None # update positions of other items self.update_script_positions() if not self.ui.script_list: self.ui.tagger_script.setText("") self.ui.tagger_script.setEnabled(False) self.ui.script_name.setText("") self.ui.script_name.setEnabled(False) # update position of last_selected_script if row == self.last_selected_script_pos: self.last_selected_script_pos = 0 # workaround to remove residue on UI if not self.ui.script_list.selectedItems(): current_item = self.ui.script_list.currentItem() if current_item: current_item.setSelected(True) else: item = self.ui.script_list.item(0) item.setSelected(True) elif row < self.last_selected_script_pos: self.last_selected_script_pos -= 1 def move_script(self, row, step): item1 = self.ui.script_list.item(row) item2 = self.ui.script_list.item(row - step) if item1 and item2: # make changes in the ui list_item = self.ui.script_list.takeItem(row) script = self.listitem_to_scriptitem[list_item] # list_widget has to be set again list_widget = AdvancedScriptItem(name=script.name, state=script.enabled) self.setSignals(list_widget, list_item) self.ui.script_list.insertItem(row - step, list_item) self.ui.script_list.setItemWidget(list_item, list_widget) # make changes in the picklable list script1 = self.listitem_to_scriptitem[item1] script2 = self.listitem_to_scriptitem[item2] # workaround since tuples are immutable indices = script1.pos, script2.pos self.list_of_scripts = [ i for j, i in enumerate(self.list_of_scripts) if j not in indices ] new_script1 = (script1.pos - step, script1.name, script1.enabled, script1.text) new_script2 = (script2.pos + step, script2.name, script2.enabled, script2.text) self.list_of_scripts.append(new_script1) self.list_of_scripts.append(new_script2) self.list_of_scripts = sorted(self.list_of_scripts, key=lambda x: x[0]) # corresponding mapping support also has to be updated self.listitem_to_scriptitem[item1] = ScriptItem( script1.pos - step, script1.name, script1.enabled, script1.text) self.listitem_to_scriptitem[item2] = ScriptItem( script2.pos + step, script2.name, script2.enabled, script2.text) def live_update_and_check(self): items = self.ui.script_list.selectedItems() if items: script = self.listitem_to_scriptitem[items[0]] script.text = self.ui.tagger_script.toPlainText() self.list_of_scripts[script.pos] = script.get_all() self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(self.ui.tagger_script.toPlainText()) except Exception as e: raise OptionsCheckError(_("Script Error"), string_(e)) def restore_defaults(self): # Remove existing scripts self.ui.script_list.clear() self.ui.script_name.setText("") self.ui.tagger_script.setText("") super().restore_defaults() def load(self): self.ui.enable_tagger_scripts.setChecked( config.setting["enable_tagger_scripts"]) self.list_of_scripts = config.setting["list_of_scripts"] for s_pos, s_name, s_enabled, s_text in self.list_of_scripts: script = ScriptItem(s_pos, s_name, s_enabled, s_text) list_item = HashableListWidgetItem() list_widget = AdvancedScriptItem(name=s_name, state=s_enabled) self.setSignals(list_widget, list_item) self.ui.script_list.addItem(list_item) self.ui.script_list.setItemWidget(list_item, list_widget) self.listitem_to_scriptitem[list_item] = script # Select the last selected script item self.last_selected_script_pos = config.persist[ "last_selected_script_pos"] last_selected_script = self.ui.script_list.item( self.last_selected_script_pos) if last_selected_script: last_selected_script.setSelected(True) # Preserve previous splitter position self.ui.splitter.restoreState(config.persist["scripting_splitter"]) args = { "picard-doc-scripting-url": PICARD_URLS['doc_scripting'], } text = _('<a href="%(picard-doc-scripting-url)s">Open Scripting' ' Documentation in your browser</a>') % args self.ui.scripting_doc_link.setText(text) def save(self): config.setting[ "enable_tagger_scripts"] = self.ui.enable_tagger_scripts.isChecked( ) config.setting["list_of_scripts"] = self.list_of_scripts config.persist[ "last_selected_script_pos"] = self.last_selected_script_pos config.persist["scripting_splitter"] = self.ui.splitter.saveState() def display_error(self, error): pass
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = None SORT_ORDER = 85 ACTIVE = True options = [ config.BoolOption("setting", "enable_tagger_scripts", False), config.ListOption("setting", "list_of_scripts", []), config.IntOption("persist", "last_selected_script_pos", 0), config.Option("persist", "scripting_splitter", QtCore.QByteArray()), ] def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter( self.ui.tagger_script.document()) self.ui.tagger_script.setEnabled(False) self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2) font = QtGui.QFont('Monospace') font.setStyleHint(QtGui.QFont.TypeWriter) self.ui.tagger_script.setFont(font) self.move_view = MoveableListView(self.ui.script_list, self.ui.move_up_button, self.ui.move_down_button) def script_selected(self): items = self.ui.script_list.selectedItems() if items: item = items[0] self.ui.tagger_script.setEnabled(True) self.ui.tagger_script.setText(item.script) else: self.ui.tagger_script.setEnabled(False) self.ui.tagger_script.setText("") def live_update_and_check(self): items = self.ui.script_list.selectedItems() if items: script = items[0] script.script = self.ui.tagger_script.toPlainText() self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(self.ui.tagger_script.toPlainText()) except Exception as e: raise ScriptCheckError(_("Script Error"), str(e)) def restore_defaults(self): # Remove existing scripts self.ui.script_list.clear() self.ui.tagger_script.setText("") super().restore_defaults() def load(self): self.ui.enable_tagger_scripts.setChecked( config.setting["enable_tagger_scripts"]) for pos, name, enabled, text in config.setting["list_of_scripts"]: list_item = ScriptListWidgetItem(name, enabled, text) self.ui.script_list.addItem(list_item) # Select the last selected script item last_selected_script_pos = config.persist["last_selected_script_pos"] last_selected_script = self.ui.script_list.item( last_selected_script_pos) if last_selected_script: self.ui.script_list.setCurrentItem(last_selected_script) last_selected_script.setSelected(True) self.restore_state() args = { "picard-doc-scripting-url": PICARD_URLS['doc_scripting'], } text = _('<a href="%(picard-doc-scripting-url)s">Open Scripting' ' Documentation in your browser</a>') % args self.ui.scripting_doc_link.setText(text) def _all_scripts(self): for row in range(0, self.ui.script_list.count()): item = self.ui.script_list.item(row) yield item.get_all() @restore_method def restore_state(self): # Preserve previous splitter position self.ui.splitter.restoreState(config.persist["scripting_splitter"]) def save(self): config.setting[ "enable_tagger_scripts"] = self.ui.enable_tagger_scripts.isChecked( ) config.setting["list_of_scripts"] = list(self._all_scripts()) config.persist[ "last_selected_script_pos"] = self.ui.script_list.currentRow() config.persist["scripting_splitter"] = self.ui.splitter.saveState() def display_error(self, error): # Ignore scripting errors, those are handled inline if not isinstance(error, ScriptCheckError): super().display_error(error)
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = None SORT_ORDER = 85 ACTIVE = True options = [ config.BoolOption("setting", "enable_tagger_scripts", False), config.ListOption("setting", "list_of_scripts", []), config.IntOption("persist", "last_selected_script_pos", 0), config.Option("persist", "scripting_splitter", QtCore.QByteArray()), ] def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.highlighter = TaggerScriptSyntaxHighlighter(self.ui.tagger_script.document()) self.ui.tagger_script.textChanged.connect(self.live_update_and_check) self.ui.script_name.textChanged.connect(self.script_name_changed) self.ui.add_script.clicked.connect(self.add_to_list_of_scripts) self.ui.script_list.itemSelectionChanged.connect(self.script_selected) self.ui.tagger_script.setEnabled(False) self.ui.script_name.setEnabled(False) self.listitem_to_scriptitem = {} self.list_of_scripts = [] self.last_selected_script_pos = 0 self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 2) self.delete_shortcut = QtWidgets.QShortcut(self.ui.script_list) self.delete_shortcut.setKey(QtGui.QKeySequence.Delete) self.delete_shortcut.activated.connect(self.delete_selected_script) def delete_selected_script(self): items = self.ui.script_list.selectedItems() if items: self.remove_from_list_of_scripts(self.ui.script_list.row(items[0])) def script_name_changed(self): items = self.ui.script_list.selectedItems() if items: script = self.listitem_to_scriptitem[items[0]] script.name = self.ui.script_name.text() list_widget = self.ui.script_list.itemWidget(items[0]) list_widget.update_name(script.name) self.list_of_scripts[script.pos] = script.get_all() def script_selected(self): items = self.ui.script_list.selectedItems() if items: self.ui.tagger_script.setEnabled(True) self.ui.script_name.setEnabled(True) script = self.listitem_to_scriptitem[items[0]] self.ui.tagger_script.setText(script.text) self.ui.script_name.setText(script.name) self.last_selected_script_pos = script.pos def setSignals(self, list_widget, item): list_widget.set_up_connection(lambda: self.move_script(self.ui.script_list.row(item), 1)) list_widget.set_down_connection(lambda: self.move_script(self.ui.script_list.row(item), -1)) list_widget.set_remove_connection(lambda: self.remove_from_list_of_scripts(self.ui.script_list.row(item))) list_widget.set_checkbox_connection(lambda: self.update_check_state(item, list_widget.checkbox_state())) list_widget.set_rename_connection(lambda: self.rename_script(item)) def rename_script(self, item): item.setSelected(True) self.ui.script_name.setFocus() self.ui.script_name.selectAll() def update_check_state(self, item, checkbox_state): script = self.listitem_to_scriptitem[item] script.enabled = checkbox_state self.list_of_scripts[script.pos] = script.get_all() def add_to_list_of_scripts(self): count = self.ui.script_list.count() numbered_name = _(DEFAULT_NUMBERED_SCRIPT_NAME) % (count + 1) script = ScriptItem(pos=count, name=numbered_name) list_item = HashableListWidgetItem() list_widget = AdvancedScriptItem(numbered_name) self.setSignals(list_widget, list_item) self.ui.script_list.addItem(list_item) self.ui.script_list.setItemWidget(list_item, list_widget) self.listitem_to_scriptitem[list_item] = script self.list_of_scripts.append(script.get_all()) list_item.setSelected(True) def update_script_positions(self): for i, script in enumerate(self.list_of_scripts): self.list_of_scripts[i] = (i, script[1], script[2], script[3]) item = self.ui.script_list.item(i) self.listitem_to_scriptitem[item].pos = i def remove_from_list_of_scripts(self, row): item = self.ui.script_list.item(row) confirm_remove = QtWidgets.QMessageBox() msg = _("Are you sure you want to remove this script?") reply = confirm_remove.question(confirm_remove, _('Confirm Remove'), msg, QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No) if item and reply == QtWidgets.QMessageBox.Yes: item = self.ui.script_list.takeItem(row) script = self.listitem_to_scriptitem[item] del self.listitem_to_scriptitem[item] del self.list_of_scripts[script.pos] del script item = None # update positions of other items self.update_script_positions() if not self.ui.script_list: self.ui.tagger_script.setText("") self.ui.tagger_script.setEnabled(False) self.ui.script_name.setText("") self.ui.script_name.setEnabled(False) # update position of last_selected_script if row == self.last_selected_script_pos: self.last_selected_script_pos = 0 # workaround to remove residue on UI if not self.ui.script_list.selectedItems(): current_item = self.ui.script_list.currentItem() if current_item: current_item.setSelected(True) else: item = self.ui.script_list.item(0) if item: item.setSelected(True) elif row < self.last_selected_script_pos: self.last_selected_script_pos -= 1 def move_script(self, row, step): item1 = self.ui.script_list.item(row) item2 = self.ui.script_list.item(row - step) if item1 and item2: # make changes in the ui list_item = self.ui.script_list.takeItem(row) script = self.listitem_to_scriptitem[list_item] # list_widget has to be set again list_widget = AdvancedScriptItem(name=script.name, state=script.enabled) self.setSignals(list_widget, list_item) self.ui.script_list.insertItem(row - step, list_item) self.ui.script_list.setItemWidget(list_item, list_widget) # make changes in the picklable list script1 = self.listitem_to_scriptitem[item1] script2 = self.listitem_to_scriptitem[item2] # workaround since tuples are immutable indices = script1.pos, script2.pos self.list_of_scripts = [i for j, i in enumerate(self.list_of_scripts) if j not in indices] new_script1 = (script1.pos - step, script1.name, script1.enabled, script1.text) new_script2 = (script2.pos + step, script2.name, script2.enabled, script2.text) self.list_of_scripts.append(new_script1) self.list_of_scripts.append(new_script2) self.list_of_scripts = sorted(self.list_of_scripts, key=lambda x: x[0]) # corresponding mapping support also has to be updated self.listitem_to_scriptitem[item1] = ScriptItem(script1.pos - step, script1.name, script1.enabled, script1.text) self.listitem_to_scriptitem[item2] = ScriptItem(script2.pos + step, script2.name, script2.enabled, script2.text) def live_update_and_check(self): items = self.ui.script_list.selectedItems() if items: script = self.listitem_to_scriptitem[items[0]] script.text = self.ui.tagger_script.toPlainText() self.list_of_scripts[script.pos] = script.get_all() self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return def check(self): parser = ScriptParser() try: parser.eval(self.ui.tagger_script.toPlainText()) except Exception as e: raise OptionsCheckError(_("Script Error"), str(e)) def restore_defaults(self): # Remove existing scripts self.ui.script_list.clear() self.ui.script_name.setText("") self.ui.tagger_script.setText("") super().restore_defaults() def load(self): self.ui.enable_tagger_scripts.setChecked(config.setting["enable_tagger_scripts"]) self.list_of_scripts = config.setting["list_of_scripts"] for s_pos, s_name, s_enabled, s_text in self.list_of_scripts: script = ScriptItem(s_pos, s_name, s_enabled, s_text) list_item = HashableListWidgetItem() list_widget = AdvancedScriptItem(name=s_name, state=s_enabled) self.setSignals(list_widget, list_item) self.ui.script_list.addItem(list_item) self.ui.script_list.setItemWidget(list_item, list_widget) self.listitem_to_scriptitem[list_item] = script # Select the last selected script item self.last_selected_script_pos = config.persist["last_selected_script_pos"] last_selected_script = self.ui.script_list.item(self.last_selected_script_pos) if last_selected_script: last_selected_script.setSelected(True) self.restore_state() args = { "picard-doc-scripting-url": PICARD_URLS['doc_scripting'], } text = _('<a href="%(picard-doc-scripting-url)s">Open Scripting' ' Documentation in your browser</a>') % args self.ui.scripting_doc_link.setText(text) @restore_method def restore_state(self): # Preserve previous splitter position self.ui.splitter.restoreState(config.persist["scripting_splitter"]) def save(self): config.setting["enable_tagger_scripts"] = self.ui.enable_tagger_scripts.isChecked() config.setting["list_of_scripts"] = self.list_of_scripts config.persist["last_selected_script_pos"] = self.last_selected_script_pos config.persist["scripting_splitter"] = self.ui.splitter.saveState() def display_error(self, error): pass
class ScriptingOptionsPage(OptionsPage): NAME = "scripting" TITLE = N_("Scripting") PARENT = None SORT_ORDER = 75 ACTIVE = True HELP_URL = '/config/options_scripting.html' options = [ BoolOption("setting", "enable_tagger_scripts", False), ListOption("setting", "list_of_scripts", []), IntOption("persist", "last_selected_script_pos", 0), ] default_script_directory = os.path.normpath( QtCore.QStandardPaths.writableLocation( QtCore.QStandardPaths.StandardLocation.DocumentsLocation)) default_script_extension = "ptsp" def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_ScriptingOptionsPage() self.ui.setupUi(self) self.ui.tagger_script.setEnabled(False) self.ui.scripting_options_splitter.setStretchFactor(1, 2) self.move_view = MoveableListView(self.ui.script_list, self.ui.move_up_button, self.ui.move_down_button) self.ui.scripting_documentation_button.clicked.connect( self.show_scripting_documentation) self.ui.scripting_documentation_button.setToolTip( _("Show scripting documentation in new window.")) self.ui.import_button.clicked.connect(self.import_script) self.ui.import_button.setToolTip( _("Import a script file as a new script.")) self.ui.export_button.clicked.connect(self.export_script) self.ui.export_button.setToolTip( _("Export the current script to a file.")) self.FILE_TYPE_ALL = _("All files") + " (*)" self.FILE_TYPE_SCRIPT = _("Picard script files") + " (*.pts *.txt)" self.FILE_TYPE_PACKAGE = _( "Picard tagging script package") + " (*.ptsp *.yaml)" self.ui.script_list.signal_reset_selected_item.connect( self.reset_selected_item) def show_scripting_documentation(self): ScriptingDocumentationDialog.show_instance(parent=self) def output_error(self, title, fmt, filename, msg): """Log error and display error message dialog. Args: title (str): Title to display on the error dialog box fmt (str): Format for the error type being displayed filename (str): Name of the file being imported or exported msg (str): Error message to display """ log.error(fmt, filename, msg) error_message = _(fmt) % (filename, _(msg)) self.display_error(ScriptFileError(_(title), error_message)) def output_file_error(self, fmt, filename, msg): """Log file error and display error message dialog. Args: fmt (str): Format for the error type being displayed filename (str): Name of the file being imported or exported msg (str): Error message to display """ self.output_error(_("File Error"), fmt, filename, msg) def import_script(self): """Import from an external text file to a new script. Import can be either a plain text script or a Picard script package. """ try: script_item = TaggingScript().import_script(self) except ScriptImportExportError as error: self.output_file_error(error.format, error.filename, error.error_msg) return if script_item: title = _("%s (imported)") % script_item["title"] list_item = ScriptListWidgetItem(title, False, script_item["script"]) self.ui.script_list.addItem(list_item) self.ui.script_list.setCurrentRow(self.ui.script_list.count() - 1) def export_script(self): """Export the current script to an external file. Export can be either as a plain text script or a naming script package. """ items = self.ui.script_list.selectedItems() if not items: return item = items[0] script_text = item.script script_title = item.name if item.name.strip() else _("Unnamed Script") if script_text: script_item = TaggingScript(title=script_title, script=script_text) try: script_item.export_script(parent=self) except ScriptImportExportError as error: self.output_file_error(error.format, error.filename, error.error_msg) def enable_tagger_scripts_toggled(self, on): if on and self.ui.script_list.count() == 0: self.ui.script_list.add_script() def script_selected(self): items = self.ui.script_list.selectedItems() if items: item = items[0] self.ui.tagger_script.setEnabled(True) self.ui.tagger_script.setText(item.script) self.ui.tagger_script.setFocus( QtCore.Qt.FocusReason.OtherFocusReason) self.ui.export_button.setEnabled(True) else: self.ui.tagger_script.setEnabled(False) self.ui.tagger_script.setText("") self.ui.export_button.setEnabled(False) def live_update_and_check(self): items = self.ui.script_list.selectedItems() if not items: return script = items[0] script.script = self.ui.tagger_script.toPlainText() self.ui.script_error.setStyleSheet("") self.ui.script_error.setText("") try: self.check() except OptionsCheckError as e: script.has_error = True self.ui.script_error.setStyleSheet(self.STYLESHEET_ERROR) self.ui.script_error.setText(e.info) return script.has_error = False def reset_selected_item(self): widget = self.ui.script_list widget.setCurrentRow(widget.bad_row) def check(self): parser = ScriptParser() try: parser.eval(self.ui.tagger_script.toPlainText()) except Exception as e: raise ScriptCheckError(_("Script Error"), str(e)) def restore_defaults(self): # Remove existing scripts self.ui.script_list.clear() self.ui.tagger_script.setText("") super().restore_defaults() def load(self): config = get_config() self.ui.enable_tagger_scripts.setChecked( config.setting["enable_tagger_scripts"]) self.ui.script_list.clear() for pos, name, enabled, text in config.setting["list_of_scripts"]: list_item = ScriptListWidgetItem(name, enabled, text) self.ui.script_list.addItem(list_item) # Select the last selected script item last_selected_script_pos = config.persist["last_selected_script_pos"] last_selected_script = self.ui.script_list.item( last_selected_script_pos) if last_selected_script: self.ui.script_list.setCurrentItem(last_selected_script) last_selected_script.setSelected(True) def _all_scripts(self): for row in range(0, self.ui.script_list.count()): item = self.ui.script_list.item(row) yield item.get_all() def save(self): config = get_config() config.setting[ "enable_tagger_scripts"] = self.ui.enable_tagger_scripts.isChecked( ) config.setting["list_of_scripts"] = list(self._all_scripts()) config.persist[ "last_selected_script_pos"] = self.ui.script_list.currentRow() def display_error(self, error): # Ignore scripting errors, those are handled inline if not isinstance(error, ScriptCheckError): super().display_error(error)