--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/eric7/Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardDialog.py Thu Jul 07 11:23:56 2022 +0200 @@ -0,0 +1,866 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2013 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the QRegularExpression wizard dialog. +""" + +import os +import pathlib +import re +import json + +from PyQt6.QtCore import pyqtSlot, QProcess, QByteArray +from PyQt6.QtGui import QClipboard, QTextCursor +from PyQt6.QtWidgets import ( + QWidget, QDialog, QInputDialog, QApplication, QDialogButtonBox, + QVBoxLayout, QTableWidgetItem +) + +from EricWidgets import EricMessageBox, EricFileDialog +from EricWidgets.EricMainWindow import EricMainWindow + +from .Ui_QRegularExpressionWizardDialog import ( + Ui_QRegularExpressionWizardDialog +) + +import UI.PixmapCache + +import Globals +import Utilities +import Preferences + + +class QRegularExpressionWizardWidget(QWidget, + Ui_QRegularExpressionWizardDialog): + """ + Class implementing the QRegularExpression wizard dialog. + """ + def __init__(self, parent=None, fromEric=True): + """ + Constructor + + @param parent parent widget (QWidget) + @param fromEric flag indicating a call from within eric + """ + super().__init__(parent) + self.setupUi(self) + + # initialize icons of the tool buttons + self.commentButton.setIcon(UI.PixmapCache.getIcon("comment")) + self.charButton.setIcon(UI.PixmapCache.getIcon("characters")) + self.anycharButton.setIcon(UI.PixmapCache.getIcon("anychar")) + self.repeatButton.setIcon(UI.PixmapCache.getIcon("repeat")) + self.nonGroupButton.setIcon(UI.PixmapCache.getIcon("nongroup")) + self.atomicGroupButton.setIcon( + UI.PixmapCache.getIcon("atomicgroup")) + self.groupButton.setIcon(UI.PixmapCache.getIcon("group")) + self.namedGroupButton.setIcon(UI.PixmapCache.getIcon("namedgroup")) + self.namedReferenceButton.setIcon( + UI.PixmapCache.getIcon("namedreference")) + self.altnButton.setIcon(UI.PixmapCache.getIcon("altn")) + self.beglineButton.setIcon(UI.PixmapCache.getIcon("begline")) + self.endlineButton.setIcon(UI.PixmapCache.getIcon("endline")) + self.wordboundButton.setIcon( + UI.PixmapCache.getIcon("wordboundary")) + self.nonwordboundButton.setIcon( + UI.PixmapCache.getIcon("nonwordboundary")) + self.poslookaheadButton.setIcon( + UI.PixmapCache.getIcon("poslookahead")) + self.neglookaheadButton.setIcon( + UI.PixmapCache.getIcon("neglookahead")) + self.poslookbehindButton.setIcon( + UI.PixmapCache.getIcon("poslookbehind")) + self.neglookbehindButton.setIcon( + UI.PixmapCache.getIcon("neglookbehind")) + self.undoButton.setIcon(UI.PixmapCache.getIcon("editUndo")) + self.redoButton.setIcon(UI.PixmapCache.getIcon("editRedo")) + + self.namedGroups = re.compile(r"""\(?P<([^>]+)>""").findall + + # start the PyQt6 server part + self.__pyqt6Available = False + self.__pyqt6Server = QProcess(self) + self.__pyqt6Server.start( + Globals.getPythonExecutable(), [os.path.join( + os.path.dirname(__file__), "QRegularExpressionWizardServer.py") + ]) + if self.__pyqt6Server.waitForStarted(5000): + self.__pyqt6Server.setReadChannel( + QProcess.ProcessChannel.StandardOutput) + if self.__sendCommand("available"): + response = self.__receiveResponse() + if response and response["available"]: + self.__pyqt6Available = True + + self.saveButton = self.buttonBox.addButton( + self.tr("Save"), QDialogButtonBox.ButtonRole.ActionRole) + self.saveButton.setToolTip( + self.tr("Save the regular expression to a file")) + self.loadButton = self.buttonBox.addButton( + self.tr("Load"), QDialogButtonBox.ButtonRole.ActionRole) + self.loadButton.setToolTip( + self.tr("Load a regular expression from a file")) + if self.__pyqt6Available: + self.validateButton = self.buttonBox.addButton( + self.tr("Validate"), QDialogButtonBox.ButtonRole.ActionRole) + self.validateButton.setToolTip( + self.tr("Validate the regular expression")) + self.executeButton = self.buttonBox.addButton( + self.tr("Execute"), QDialogButtonBox.ButtonRole.ActionRole) + self.executeButton.setToolTip( + self.tr("Execute the regular expression")) + self.nextButton = self.buttonBox.addButton( + self.tr("Next match"), QDialogButtonBox.ButtonRole.ActionRole) + self.nextButton.setToolTip( + self.tr("Show the next match of the regular expression")) + self.nextButton.setEnabled(False) + else: + self.validateButton = None + self.executeButton = None + self.nextButton = None + + if fromEric: + self.buttonBox.setStandardButtons( + QDialogButtonBox.StandardButton.Cancel | + QDialogButtonBox.StandardButton.Ok) + self.copyButton = None + else: + self.copyButton = self.buttonBox.addButton( + self.tr("Copy"), QDialogButtonBox.ButtonRole.ActionRole) + self.copyButton.setToolTip( + self.tr("Copy the regular expression to the clipboard")) + self.buttonBox.setStandardButtons( + QDialogButtonBox.StandardButton.Close) + self.variableLabel.hide() + self.variableLineEdit.hide() + self.variableLine.hide() + self.regexpTextEdit.setFocus() + + def __sendCommand(self, command, **kw): + """ + Private method to send a command to the server. + + @param command dictionary with command string and related + data (dict) + @keyparam kw parameters for the command + @return flag indicating a successful transmission (boolean) + """ + result = False + if command: + commandDict = {"command": command} + commandDict.update(kw) + commandStr = json.dumps(commandDict) + "\n" + data = QByteArray(commandStr.encode("utf-8")) + self.__pyqt6Server.write(data) + result = self.__pyqt6Server.waitForBytesWritten(10000) + return result + + def __receiveResponse(self): + """ + Private method to receive a response from the server. + + @return response dictionary (dict) + """ + responseDict = {} + if self.__pyqt6Server.waitForReadyRead(10000): + data = bytes(self.__pyqt6Server.readAllStandardOutput()) + responseStr = data.decode("utf-8") + responseDict = json.loads(responseStr) + if responseDict["error"]: + EricMessageBox.critical( + self, + self.tr("Communication Error"), + self.tr("""<p>The backend reported an error.</p>""" + """<p>{0}</p>""") + .format(responseDict["error"])) + responseDict = {} + + return responseDict + + def shutdown(self): + """ + Public method to shut down the server part. + """ + self.__sendCommand("exit") + self.__pyqt6Server.waitForFinished(5000) + + def __insertString(self, s, steps=0): + """ + Private method to insert a string into line edit and move cursor. + + @param s string to be inserted into the regexp line edit + (string) + @param steps number of characters to move the cursor (integer). + Negative steps moves cursor back, positives forward. + """ + self.regexpTextEdit.insertPlainText(s) + tc = self.regexpTextEdit.textCursor() + if steps != 0: + if steps < 0: + act = QTextCursor.MoveOperation.Left + steps = abs(steps) + else: + act = QTextCursor.MoveOperation.Right + for _ in range(steps): + tc.movePosition(act) + self.regexpTextEdit.setTextCursor(tc) + + @pyqtSlot() + def on_commentButton_clicked(self): + """ + Private slot to handle the comment toolbutton. + """ + self.__insertString("(?#)", -1) + + @pyqtSlot() + def on_charButton_clicked(self): + """ + Private slot to handle the characters toolbutton. + """ + from .QRegularExpressionWizardCharactersDialog import ( + QRegularExpressionWizardCharactersDialog + ) + dlg = QRegularExpressionWizardCharactersDialog(self) + if dlg.exec() == QDialog.DialogCode.Accepted: + self.__insertString(dlg.getCharacters()) + + @pyqtSlot() + def on_anycharButton_clicked(self): + """ + Private slot to handle the any character toolbutton. + """ + self.__insertString(".") + + @pyqtSlot() + def on_repeatButton_clicked(self): + """ + Private slot to handle the repeat toolbutton. + """ + from .QRegularExpressionWizardRepeatDialog import ( + QRegularExpressionWizardRepeatDialog + ) + dlg = QRegularExpressionWizardRepeatDialog(self) + if dlg.exec() == QDialog.DialogCode.Accepted: + self.__insertString(dlg.getRepeat()) + + @pyqtSlot() + def on_nonGroupButton_clicked(self): + """ + Private slot to handle the non group toolbutton. + """ + self.__insertString("(?:)", -1) + + @pyqtSlot() + def on_atomicGroupButton_clicked(self): + """ + Private slot to handle the atomic non group toolbutton. + """ + self.__insertString("(?>)", -1) + + @pyqtSlot() + def on_groupButton_clicked(self): + """ + Private slot to handle the group toolbutton. + """ + self.__insertString("()", -1) + + @pyqtSlot() + def on_namedGroupButton_clicked(self): + """ + Private slot to handle the named group toolbutton. + """ + self.__insertString("(?P<>)", -2) + + @pyqtSlot() + def on_namedReferenceButton_clicked(self): + """ + Private slot to handle the named reference toolbutton. + """ + # determine cursor position as length into text + length = self.regexpTextEdit.textCursor().position() + + # only present group names that occur before the current + # cursor position + regex = self.regexpTextEdit.toPlainText()[:length] + names = self.namedGroups(regex) + if not names: + EricMessageBox.information( + self, + self.tr("Named reference"), + self.tr("""No named groups have been defined yet.""")) + return + + groupName, ok = QInputDialog.getItem( + self, + self.tr("Named reference"), + self.tr("Select group name:"), + names, + 0, True) + if ok and groupName: + self.__insertString("(?P={0})".format(groupName)) + + @pyqtSlot() + def on_altnButton_clicked(self): + """ + Private slot to handle the alternatives toolbutton. + """ + self.__insertString("(|)", -2) + + @pyqtSlot() + def on_beglineButton_clicked(self): + """ + Private slot to handle the begin line toolbutton. + """ + self.__insertString("^") + + @pyqtSlot() + def on_endlineButton_clicked(self): + """ + Private slot to handle the end line toolbutton. + """ + self.__insertString("$") + + @pyqtSlot() + def on_wordboundButton_clicked(self): + """ + Private slot to handle the word boundary toolbutton. + """ + self.__insertString("\\b") + + @pyqtSlot() + def on_nonwordboundButton_clicked(self): + """ + Private slot to handle the non word boundary toolbutton. + """ + self.__insertString("\\B") + + @pyqtSlot() + def on_poslookaheadButton_clicked(self): + """ + Private slot to handle the positive lookahead toolbutton. + """ + self.__insertString("(?=)", -1) + + @pyqtSlot() + def on_neglookaheadButton_clicked(self): + """ + Private slot to handle the negative lookahead toolbutton. + """ + self.__insertString("(?!)", -1) + + @pyqtSlot() + def on_poslookbehindButton_clicked(self): + """ + Private slot to handle the positive lookbehind toolbutton. + """ + self.__insertString("(?<=)", -1) + + @pyqtSlot() + def on_neglookbehindButton_clicked(self): + """ + Private slot to handle the negative lookbehind toolbutton. + """ + self.__insertString("(?<!)", -1) + + @pyqtSlot() + def on_undoButton_clicked(self): + """ + Private slot to handle the undo action. + """ + self.regexpTextEdit.document().undo() + + @pyqtSlot() + def on_redoButton_clicked(self): + """ + Private slot to handle the redo action. + """ + self.regexpTextEdit.document().redo() + + def on_buttonBox_clicked(self, button): + """ + Private slot called by a button of the button box clicked. + + @param button button that was clicked (QAbstractButton) + """ + if button == self.validateButton: + self.on_validateButton_clicked() + elif button == self.executeButton: + self.on_executeButton_clicked() + elif button == self.saveButton: + self.on_saveButton_clicked() + elif button == self.loadButton: + self.on_loadButton_clicked() + elif button == self.nextButton: + self.on_nextButton_clicked() + elif self.copyButton and button == self.copyButton: + self.on_copyButton_clicked() + + @pyqtSlot() + def on_saveButton_clicked(self): + """ + Private slot to save the QRegularExpression to a file. + """ + fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( + self, + self.tr("Save regular expression"), + "", + self.tr("RegExp Files (*.rx);;All Files (*)"), + None, + EricFileDialog.DontConfirmOverwrite) + if fname: + fpath = pathlib.Path(fname) + if not fpath.suffix: + ex = selectedFilter.split("(*")[1].split(")")[0] + if ex: + fpath = fpath.with_suffix(ex) + if fpath.exists(): + res = EricMessageBox.yesNo( + self, + self.tr("Save regular expression"), + self.tr("<p>The file <b>{0}</b> already exists." + " Overwrite it?</p>").format(fpath), + icon=EricMessageBox.Warning) + if not res: + return + + try: + with fpath.open("w", encoding="utf-8") as f: + f.write(self.regexpTextEdit.toPlainText()) + except OSError as err: + EricMessageBox.information( + self, + self.tr("Save regular expression"), + self.tr("""<p>The regular expression could not""" + """ be saved.</p><p>Reason: {0}</p>""") + .format(str(err))) + + @pyqtSlot() + def on_loadButton_clicked(self): + """ + Private slot to load a QRegularExpression from a file. + """ + fname = EricFileDialog.getOpenFileName( + self, + self.tr("Load regular expression"), + "", + self.tr("RegExp Files (*.rx);;All Files (*)")) + if fname: + fname = Utilities.toNativeSeparators(fname) + try: + with open(fname, "r", encoding="utf-8") as f: + regexp = f.read() + self.regexpTextEdit.setPlainText(regexp) + except OSError as err: + EricMessageBox.information( + self, + self.tr("Save regular expression"), + self.tr("""<p>The regular expression could not""" + """ be saved.</p><p>Reason: {0}</p>""") + .format(str(err))) + + @pyqtSlot() + def on_copyButton_clicked(self): + """ + Private slot to copy the QRegularExpression string into the clipboard. + + This slot is only available, if not called from within eric. + """ + escaped = self.regexpTextEdit.toPlainText() + if escaped: + escaped = escaped.replace("\\", "\\\\") + cb = QApplication.clipboard() + cb.setText(escaped, QClipboard.Mode.Clipboard) + if cb.supportsSelection(): + cb.setText(escaped, QClipboard.Mode.Selection) + + @pyqtSlot() + def on_validateButton_clicked(self): + """ + Private slot to validate the entered QRegularExpression. + """ + if not self.__pyqt6Available: + # only available for PyQt6 + return + + regexp = self.regexpTextEdit.toPlainText() + if regexp: + options = [] + if self.caseInsensitiveCheckBox.isChecked(): + options.append("CaseInsensitiveOption") + if self.multilineCheckBox.isChecked(): + options.append("MultilineOption") + if self.dotallCheckBox.isChecked(): + options.append("DotMatchesEverythingOption") + if self.extendedCheckBox.isChecked(): + options.append("ExtendedPatternSyntaxOption") + if self.greedinessCheckBox.isChecked(): + options.append("InvertedGreedinessOption") + if self.unicodeCheckBox.isChecked(): + options.append("UseUnicodePropertiesOption") + if self.captureCheckBox.isChecked(): + options.append("DontCaptureOption") + + if self.__sendCommand("validate", options=options, regexp=regexp): + response = self.__receiveResponse() + if response and "valid" in response: + if response["valid"]: + EricMessageBox.information( + self, + self.tr("Validation"), + self.tr( + """The regular expression is valid.""")) + else: + EricMessageBox.critical( + self, + self.tr("Error"), + self.tr("""Invalid regular expression: {0}""") + .format(response["errorMessage"])) + # move cursor to error offset + offset = response["errorOffset"] + tc = self.regexpTextEdit.textCursor() + tc.setPosition(offset) + self.regexpTextEdit.setTextCursor(tc) + self.regexpTextEdit.setFocus() + return + else: + EricMessageBox.critical( + self, + self.tr("Communication Error"), + self.tr("""Invalid response received from backend.""")) + else: + EricMessageBox.critical( + self, + self.tr("Communication Error"), + self.tr("""Communication with backend failed.""")) + else: + EricMessageBox.critical( + self, + self.tr("Error"), + self.tr("""A regular expression must be given.""")) + + @pyqtSlot() + def on_executeButton_clicked(self, startpos=0): + """ + Private slot to execute the entered QRegularExpression on the test + text. + + This slot will execute the entered QRegularExpression on the entered + test data and will display the result in the table part of the dialog. + + @param startpos starting position for the QRegularExpression matching + """ + if not self.__pyqt6Available: + # only available for PyQt6 + return + + regexp = self.regexpTextEdit.toPlainText() + text = self.textTextEdit.toPlainText() + if regexp and text: + options = [] + if self.caseInsensitiveCheckBox.isChecked(): + options.append("CaseInsensitiveOption") + if self.multilineCheckBox.isChecked(): + options.append("MultilineOption") + if self.dotallCheckBox.isChecked(): + options.append("DotMatchesEverythingOption") + if self.extendedCheckBox.isChecked(): + options.append("ExtendedPatternSyntaxOption") + if self.greedinessCheckBox.isChecked(): + options.append("InvertedGreedinessOption") + if self.unicodeCheckBox.isChecked(): + options.append("UseUnicodePropertiesOption") + if self.captureCheckBox.isChecked(): + options.append("DontCaptureOption") + + if self.__sendCommand("execute", options=options, regexp=regexp, + text=text, startpos=startpos): + response = self.__receiveResponse() + if response and ("valid" in response or "matched" in response): + if "valid" in response: + EricMessageBox.critical( + self, + self.tr("Error"), + self.tr("""Invalid regular expression: {0}""") + .format(response["errorMessage"])) + # move cursor to error offset + offset = response["errorOffset"] + tc = self.regexpTextEdit.textCursor() + tc.setPosition(offset) + self.regexpTextEdit.setTextCursor(tc) + self.regexpTextEdit.setFocus() + return + else: + row = 0 + OFFSET = 5 + + self.resultTable.setColumnCount(0) + self.resultTable.setColumnCount(3) + self.resultTable.setRowCount(0) + self.resultTable.setRowCount(OFFSET) + self.resultTable.setItem( + row, 0, QTableWidgetItem(self.tr("Regexp"))) + self.resultTable.setItem( + row, 1, QTableWidgetItem(regexp)) + if response["matched"]: + captures = response["captures"] + # index 0 is the complete match + offset = captures[0][1] + self.lastMatchEnd = captures[0][2] + self.nextButton.setEnabled(True) + row += 1 + self.resultTable.setItem( + row, 0, + QTableWidgetItem(self.tr("Offset"))) + self.resultTable.setItem( + row, 1, + QTableWidgetItem("{0:d}".format(offset))) + + row += 1 + self.resultTable.setItem( + row, 0, + QTableWidgetItem(self.tr("Captures"))) + self.resultTable.setItem( + row, 1, + QTableWidgetItem( + "{0:d}".format(len(captures) - 1))) + row += 1 + self.resultTable.setItem( + row, 1, + QTableWidgetItem(self.tr("Text"))) + self.resultTable.setItem( + row, 2, + QTableWidgetItem(self.tr("Characters"))) + + row += 1 + self.resultTable.setItem( + row, 0, + QTableWidgetItem(self.tr("Match"))) + self.resultTable.setItem( + row, 1, + QTableWidgetItem(captures[0][0])) + self.resultTable.setItem( + row, 2, + QTableWidgetItem( + "{0:d}".format(captures[0][3]))) + + for i in range(1, len(captures)): + if captures[i][0]: + row += 1 + self.resultTable.insertRow(row) + self.resultTable.setItem( + row, 0, + QTableWidgetItem( + self.tr("Capture #{0}") + .format(i))) + self.resultTable.setItem( + row, 1, + QTableWidgetItem(captures[i][0])) + self.resultTable.setItem( + row, 2, + QTableWidgetItem( + "{0:d}".format(captures[i][3]))) + + # highlight the matched text + tc = self.textTextEdit.textCursor() + tc.setPosition(offset) + tc.setPosition( + self.lastMatchEnd, + QTextCursor.MoveMode.KeepAnchor) + self.textTextEdit.setTextCursor(tc) + else: + self.nextButton.setEnabled(False) + self.resultTable.setRowCount(2) + row += 1 + if startpos > 0: + self.resultTable.setItem( + row, 0, + QTableWidgetItem( + self.tr("No more matches"))) + else: + self.resultTable.setItem( + row, 0, + QTableWidgetItem( + self.tr("No matches"))) + + # remove the highlight + tc = self.textTextEdit.textCursor() + tc.setPosition(0) + self.textTextEdit.setTextCursor(tc) + + self.resultTable.resizeColumnsToContents() + self.resultTable.resizeRowsToContents() + self.resultTable.verticalHeader().hide() + self.resultTable.horizontalHeader().hide() + else: + EricMessageBox.critical( + self, + self.tr("Communication Error"), + self.tr("""Invalid response received from backend.""")) + else: + EricMessageBox.critical( + self, + self.tr("Communication Error"), + self.tr("""Communication with backend failed.""")) + else: + EricMessageBox.critical( + self, + self.tr("Error"), + self.tr("""A regular expression and a text must""" + """ be given.""")) + + @pyqtSlot() + def on_nextButton_clicked(self): + """ + Private slot to find the next match. + """ + self.on_executeButton_clicked(self.lastMatchEnd) + + @pyqtSlot() + def on_regexpTextEdit_textChanged(self): + """ + Private slot called when the regexp changes. + """ + if self.nextButton: + self.nextButton.setEnabled(False) + + def getCode(self, indLevel, indString): + """ + Public method to get the source code. + + @param indLevel indentation level (int) + @param indString string used for indentation (space or tab) (string) + @return generated code (string) + """ + # calculate the indentation string + i1string = (indLevel + 1) * indString + estring = os.linesep + indLevel * indString + + # now generate the code + reVar = self.variableLineEdit.text() + if not reVar: + reVar = "regexp" + + regexp = self.regexpTextEdit.toPlainText() + + options = [] + if self.caseInsensitiveCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.CaseInsensitiveOption") + if self.multilineCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.MultilineOption") + if self.dotallCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.DotMatchesEverythingOption") + if self.extendedCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.ExtendedPatternSyntaxOption") + if self.greedinessCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.InvertedGreedinessOption") + if self.unicodeCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.UseUnicodePropertiesOption") + if self.captureCheckBox.isChecked(): + options.append( + "QRegularExpression.PatternOption.DontCaptureOption") + options = " |{0}{1}".format(os.linesep, i1string).join(options) + + code = '{0} = QRegularExpression('.format(reVar) + if options: + code += '{0}{1}r"""{2}""",'.format( + os.linesep, i1string, regexp.replace('"', '\\"')) + code += '{0}{1}{2}'.format(os.linesep, i1string, options) + else: + code += 'r"""{0}"""'.format(regexp.replace('"', '\\"')) + code += '{0}){0}'.format(estring) + return code + + +class QRegularExpressionWizardDialog(QDialog): + """ + Class for the dialog variant. + """ + def __init__(self, parent=None, fromEric=True): + """ + Constructor + + @param parent parent widget (QWidget) + @param fromEric flag indicating a call from within eric + """ + super().__init__(parent) + self.setModal(fromEric) + self.setSizeGripEnabled(True) + + self.__layout = QVBoxLayout(self) + self.__layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(self.__layout) + + self.cw = QRegularExpressionWizardWidget(self, fromEric) + size = self.cw.size() + self.__layout.addWidget(self.cw) + self.resize(size) + self.setWindowTitle(self.cw.windowTitle()) + + self.cw.buttonBox.accepted.connect(self.accept) + self.cw.buttonBox.rejected.connect(self.reject) + + def getCode(self, indLevel, indString): + """ + Public method to get the source code. + + @param indLevel indentation level (int) + @param indString string used for indentation (space or tab) (string) + @return generated code (string) + """ + return self.cw.getCode(indLevel, indString) + + def accept(self): + """ + Public slot to hide the dialog and set the result code to Accepted. + """ + self.cw.shutdown() + super().accept() + + def reject(self): + """ + Public slot to hide the dialog and set the result code to Rejected. + """ + self.cw.shutdown() + super().reject() + + +class QRegularExpressionWizardWindow(EricMainWindow): + """ + Main window class for the standalone dialog. + """ + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent widget (QWidget) + """ + super().__init__(parent) + self.cw = QRegularExpressionWizardWidget(self, fromEric=False) + size = self.cw.size() + self.setCentralWidget(self.cw) + self.resize(size) + self.setWindowTitle(self.cw.windowTitle()) + + self.setStyle( + Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) + + self.cw.buttonBox.accepted.connect(self.close) + self.cw.buttonBox.rejected.connect(self.close) + + def closeEvent(self, evt): + """ + Protected method handling the close event. + + @param evt close event (QCloseEvent) + """ + self.cw.shutdown() + super().closeEvent(evt)