Beispiel #1
0
class Kodos(KodosBA):
    def __init__(self, filename, debug):
        KodosBA.__init__(self)
        self.debug = debug
        self.regex = ""
        self.matchstring = ""
        self.replace = ""
        self.flags = 0
        self.is_paused = 0
        self.is_examined = 0
        self.filename = ""
        self.match_num = 1  # matches are labeled 1..n
        self.replace_num = 0  # replace all
        self.url = None
        self.group_tuples = None
        self.editstate = STATE_UNEDITED

        self.ref_win = None
        self.regexlibwin = None

        self.embedded_flags_obj = re.compile(EMBEDDED_FLAGS)
        self.embedded_flags = ""
        self.regex_embedded_flags_removed = ""

        self.createStatusBar()

        self.MSG_NA = self.tr(
            "Enter a regular expression and a string to match against")
        self.MSG_PAUSED = self.tr(
            "Kodos regex processing is paused.  Click the pause icon to unpause"
        )
        self.MSG_FAIL = self.tr("Pattern does not match")

        self.statusPixmapsDict = {
            MATCH_NA: QPixmap(xpm.yellowStatusIcon),
            MATCH_OK: QPixmap(xpm.greenStatusIcon),
            MATCH_FAIL: QPixmap(xpm.redStatusIcon),
            MATCH_PAUSED: QPixmap(xpm.pauseStatusIcon)
        }

        self.updateStatus(self.MSG_NA, MATCH_NA)

        restoreWindowSettings(self, GEO)

        self.show()

        self.prefs = Preferences(self, 1)
        self.recent_files = RecentFiles(self,
                                        self.prefs.recentFilesSpinBox.value(),
                                        self.debug)

        #self.matchTextBrowser.setTextFormat(QTextEdit.PlainText)

        if filename and self.openFile(filename):
            qApp.processEvents()

        #QtCore.QObject.connect(self.buttonOk, QtCore.SIGNAL(_fromUtf8("clicked()")), AboutBA.accept)
        self.connect(self, str('prefsSaved()'), self.prefsSaved)
        #QObject.connect(self, SIGNAL(_fromUtf8("prefsSaved()")), self.prefsSaved)
        self.connect(self.fileMenu, str('activated(int)'),
                     self.fileMenuHandler)

        QObject.connect(self, str("pasteSymbol()"), self.paste_symbol)
        QObject.connect(self, str("prefsSaved()"), self.prefsSaved)
        #        QtCore.QObject.connect(self, QtCore.SIGNAL(_fromUtf8("urlImported()")), self.urlImported)
        QObject.connect(self, str("pasteRegexLib()"), self.pasteFromRegexLib)

        #        kodos_toolbar_logo(self.toolBar)
        #        if self.replace:  self.show_replace_widgets()
        #        else:             self.hide_replace_widgets()

        self.checkForKodosDir()

    def checkForKodosDir(self):
        kdir = os.path.join(getHomeDirectory(), ".kodos")
        if os.access(kdir, os.X_OK):
            return

        try:
            os.mkdir(kdir, 0o0755)
        except Exception:
            print("Failed to create:", kdir)

        self.newuserdialog = NewUserDialog()
        self.newuserdialog.show()

    def createStatusBar(self):
        self.status_bar = Status_Bar(self, FALSE, "")

    def updateStatus(self,
                     status_string,
                     status_value,
                     duration=0,
                     replace=FALSE,
                     tooltip=''):
        pixmap = self.statusPixmapsDict.get(status_value)

        self.status_bar.set_message(status_string, duration, replace, tooltip,
                                    pixmap)

    def fileMenuHandler(self, menuid):
        if self.recent_files.isRecentFile(menuid):
            fn = str(self.fileMenu.text(menuid))
            self.recent_files.add(fn)
            self.openFile(fn)

    def prefsSaved(self):
        if self.debug: print("prefsSaved slot")
        self.recent_files.setNumShown(self.prefs.recentFilesSpinBox.value())

    def kodos_edited_slot(self):
        # invoked whenever the user has edited something
        self.editstate = STATE_EDITED

    def checkbox_slot(self):
        self.flags = 0

        if self.ignorecaseCheckBox.isChecked():
            self.flags = self.flags + re.IGNORECASE

        if self.multilineCheckBox.isChecked():
            self.flags = self.flags + re.MULTILINE

        if self.dotallCheckBox.isChecked():
            self.flags = self.flags + re.DOTALL

        if self.verboseCheckBox.isChecked():
            self.flags = self.flags + re.VERBOSE

        if self.localeCheckBox.isChecked():
            self.flags = self.flags + re.LOCALE

        if self.unicodeCheckBox.isChecked():
            self.flags = self.flags + re.UNICODE

        self.process_regex()

    def set_flags(self, flags):
        # from the given integer value of flags, set the checkboxes
        # this is used when loading a saved file
        if flags & re.IGNORECASE:
            self.ignorecaseCheckBox.setChecked(1)
        else:
            self.ignorecaseCheckBox.setChecked(0)

        if flags & re.MULTILINE:
            self.multilineCheckBox.setChecked(1)
        else:
            self.multilineCheckBox.setChecked(0)

        if flags & re.DOTALL:
            self.dotallCheckBox.setChecked(1)
        else:
            self.dotallCheckBox.setChecked(0)

        if flags & re.VERBOSE:
            self.verboseCheckBox.setChecked(1)
        else:
            self.verboseCheckBox.setChecked(0)

        if flags & re.LOCALE:
            self.localeCheckBox.setChecked(1)
        else:
            self.localeCheckBox.setChecked(0)

        if flags & re.UNICODE:
            self.unicodeCheckBox.setChecked(1)
        else:
            self.unicodeCheckBox.setChecked(0)

    def get_flags_string(self):
        flags_str = ""

        if self.ignorecaseCheckBox.isChecked():
            flags_str += "| re.IGNORECASE"

        if self.multilineCheckBox.isChecked():
            flags_str += "| re.MULTILINE"

        if self.dotallCheckBox.isChecked():
            flags_str += "| re.DOTALL"

        if self.verboseCheckBox.isChecked():
            flags_str += "| re.VERBOSE"

        if self.localeCheckBox.isChecked():
            flags_str += "| re.LOCALE"

        if self.unicodeCheckBox.isChecked():
            flags_str += "| re.UNICODE"

        if flags_str: flags_str = ", " + flags_str[1:]
        return flags_str

    def get_embedded_flags_string(self):
        flags_str = flags = ""

        if self.ignorecaseCheckBox.isChecked():
            flags += "i"

        if self.multilineCheckBox.isChecked():
            flags += "m"

        if self.dotallCheckBox.isChecked():
            flags += "s"

        if self.verboseCheckBox.isChecked():
            flags += "x"

        if self.localeCheckBox.isChecked():
            flags += "L"

        if self.unicodeCheckBox.isChecked():
            flags += "u"

        if flags:
            flags_str = "(?" + flags + ")"

        return flags_str

    def pause(self):
        self.is_paused = not self.is_paused
        if self.debug: print("is_paused:", self.is_paused)

        if self.is_paused:
            self.update_results(self.MSG_PAUSED, MATCH_PAUSED)
            self.matchNumberSpinBox.setDisabled(1)

        else:
            self.process_regex()
            self.matchNumberSpinBox.setEnabled(1)

    def examine(self):
        self.is_examined = not self.is_examined
        if self.debug: print("is_examined:", self.is_examined)

        if self.is_examined:
            color = QCOLOR_YELLOW
            regex = self.regex
            self.regex_saved = self.regex
            length = len(regex)
            found = 0
            self.regexMultiLineEdit.setReadOnly(1)
            self.stringMultiLineEdit.setReadOnly(1)
            self.replaceTextEdit.setReadOnly(1)
            for i in range(length, 0, -1):
                regex = regex[:i]
                self.process_embedded_flags(self.regex)
                try:
                    m = re.search(regex, self.matchstring, self.flags)
                    if m:
                        if self.debug: print("examined regex:", regex)
                        self.__refresh_regex_widget(color, regex)
                        return
                except Exception:
                    pass

            self.__refresh_regex_widget(color, "")
        else:
            regex = self.regex_saved
            color = QCOLOR_WHITE
            self.regexMultiLineEdit.setReadOnly(0)
            self.stringMultiLineEdit.setReadOnly(0)
            self.replaceTextEdit.setReadOnly(0)
            self.__refresh_regex_widget(color, regex)

    def __refresh_regex_widget(self, base_qcolor, regex):
        self.regexMultiLineEdit.setTextBackgroundColor(base_qcolor)

        self.regexMultiLineEdit.TextInteractionFlags(Qt.NoTextInteraction)
        self.regexMultiLineEdit.clear()
        self.regexMultiLineEdit.TextInteractionFlags(Qt.TextEditorInteraction)
        self.regexMultiLineEdit.setText(regex)

    def match_num_slot(self, num):
        self.match_num = num
        self.process_regex()

    def replace_num_slot(self, num):
        self.replace_num = num
        self.process_regex()

    def regex_changed_slot(self):
        try:
            self.regex = str(self.regexMultiLineEdit.toPlainText())
        except UnicodeError:
            self.regex = str(self.regexMultiLineEdit.toPlainText())

        self.process_regex()

    def string_changed_slot(self):
        try:
            self.matchstring = str(self.stringMultiLineEdit.toPlainText())
        except UnicodeError:
            self.matchstring = str(self.stringMultiLineEdit.toPlainText())
        self.process_regex()

    def hide_replace_widgets(self):
        self.spacerLabel.hide()
        self.replaceLabel.hide()
        self.replaceNumberSpinBox.hide()
        self.replaceTextBrowser.clear()
        self.replaceTextBrowser.setDisabled(TRUE)

    def show_replace_widgets(self):
        self.spacerLabel.show()
        self.replaceLabel.show()
        self.replaceNumberSpinBox.show()
        self.replaceNumberSpinBox.setEnabled(TRUE)
        self.replaceTextBrowser.setEnabled(TRUE)

    def replace_changed_slot(self):
        try:
            self.replace = str(self.replaceTextEdit.toPlainText())
        except UnicodeError:
            self.replace = str(self.replaceTextEdit.toPlainText())

        self.process_regex()
        if not self.replace:
            self.hide_replace_widgets()
        else:
            self.show_replace_widgets()

    def update_results(self, msg, val):
        self.updateStatus(msg, val)

    def populate_group_listview(self, tuples):
        # deprecated as of 2.4.0 - now uses QTable instead of QListView
        self.groupListView.clear()

        num_cols = 3
        for t in tuples:
            from PyQt5.QtWidgets import QListWidgetItem
            #item = QListViewItem(self.groupListView)
            item = QListWidgetItem(self.groupListView)
            for col in range(num_cols):
                try:
                    item.setText(col, str(t[col]))
                except UnicodeError:
                    item.setText(col, str(t[col]))

    def populate_group_table(self, tuples):
        self.groupTable.setRowCount(len(tuples))

        row = 0
        for t in tuples:
            self.groupTable.setText(row, 0, str(t[1]))
            self.groupTable.setText(row, 1, str(t[2]))
            self.groupTable.adjustRow(row)
            row += 1

        self.groupTable.adjustColumn(0)
        self.groupTable.adjustColumn(1)

    def populate_code_textbrowser(self):
        self.codeTextBrowser.setText("")

        code = "import re\n\n"
        code += "# common variables\n\n"
        code += "rawstr = r\"\"\"" + self.regex_embedded_flags_removed + "\"\"\"\n"
        code += "embedded_rawstr = r\"\"\"" + self.get_embedded_flags_string() + \
                self.regex_embedded_flags_removed + "\"\"\"\n"
        code += 'matchstr = \"\"\"' + self.matchstring + '\"\"\"'
        code += "\n\n"
        code += "# method 1: using a compile object\n"
        code += "compile_obj = re.compile(rawstr"
        if self.flags != 0:
            code += self.get_flags_string()
        code += ")\n"
        code += "match_obj = compile_obj.search(matchstr)\n\n"

        code += "# method 2: using search function (w/ external flags)\n"
        code += "match_obj = re.search(rawstr, matchstr"
        if self.flags != 0:
            code += self.get_flags_string()
        code += ")\n\n"

        code += "# method 3: using search function (w/ embedded flags)\n"
        embedded_str = self.get_embedded_flags_string(
        ) + self.regex_embedded_flags_removed
        code += "match_obj = re.search(embedded_rawstr, matchstr)\n\n"

        if self.group_tuples:
            code += "# Retrieve group(s) from match_obj\n"
            code += "all_groups = match_obj.groups()\n\n"
            code += "# Retrieve group(s) by index\n"
            i = 0
            named_grps = 0
            for grp in self.group_tuples:
                i += 1
                code += "group_%d = match_obj.group(%d)\n" % (i, i)
                if grp[1]: named_grps = 1

            if named_grps:
                code += "\n# Retrieve group(s) by name\n"
                for grp in self.group_tuples:
                    if grp[1]:
                        code += "%s = match_obj.group('%s')\n" % (grp[1],
                                                                  grp[1])

            code += "\n"

        if self.replace:
            code += "# Replace string\n"
            code += "newstr = compile_obj.subn('%s', %d)\n" % (
                self.replace, self.replace_num)

        self.codeTextBrowser.setText(code)

    def colorize_strings(self, strings, widget, cursorOffset=0):
        widget.clear()

        colors = (QColor(Qt.black), QColor(Qt.blue))
        i = 0
        pos = widget.getCursorPosition()
        for s in strings:
            widget.setColor(colors[i % 2])
            widget.insert(s)
            if i == cursorOffset: pos = widget.getCursorPosition()
            i += 1

        widget.setCursorPosition(pos[0], pos[1])

    def populate_match_textbrowser(self, startpos, endpos):
        pre = post = match = ""

        match = self.matchstring[startpos:endpos]

        # prepend the beginning that didn't match
        if startpos > 0:
            pre = self.matchstring[0:startpos]

        # append the end that didn't match
        if endpos < len(self.matchstring):
            post = self.matchstring[endpos:]

        strings = [pre, match, post]
        self.colorize_strings(strings, self.matchTextBrowser, 1)

    def populate_replace_textbrowser(self, spans, nummatches, compile_obj):
        self.replaceTextBrowser.clear()
        if not spans: return

        num = self.replaceNumberSpinBox.value()
        if num == 0: num = nummatches
        text = self.matchstring

        replace_text = str(self.replaceTextEdit.text())
        if RX_BACKREF.search(replace_text):
            # if the replace string contains a backref we just use the
            # python regex methods for the substitution
            replaced = compile_obj.subn(replace_text, text, num)[0]
            self.replaceTextBrowser.setText(replaced)
            return

        numreplaced = idx = 0

        strings = []

        for span in spans:
            if span[0] != 0:
                s = text[idx:span[0]]
            else:
                s = ""

            idx = span[1]
            numreplaced += 1

            strings.append(s)
            strings.append(self.replace)

            if numreplaced >= num:
                strings.append(text[span[1]:])
                break

        self.colorize_strings(strings, self.replaceTextBrowser)

    def populate_matchAll_textbrowser(self, spans):
        self.matchAllTextBrowser.clear()
        if not spans: return

        idx = 0
        text = self.matchstring
        strings = []
        for span in spans:
            if span[0] != 0:
                s = text[idx:span[0]]
            else:
                s = ""

            idx = span[1]
            strings.append(s)
            strings.append(text[span[0]:span[1]])

        if 0 <= idx <= len(text):
            strings.append(text[span[1]:])

        self.colorize_strings(strings, self.matchAllTextBrowser)

    def clear_results(self):
        #self.groupListView.clear()
        self.groupTable.setRowCount(0)
        self.codeTextBrowser.setText("")
        self.matchTextBrowser.setText("")
        self.matchNumberSpinBox.setEnabled(FALSE)
        self.replaceNumberSpinBox.setEnabled(FALSE)
        self.replaceTextBrowser.setText("")
        self.matchAllTextBrowser.setText("")

    def process_regex(self):
        def timeout(signum, frame):
            return

        if self.is_paused:
            return

        if not self.regex or not self.matchstring:
            self.update_results(self.MSG_NA, MATCH_NA)
            self.clear_results()
            return

        self.process_embedded_flags(self.regex)
        #print( self.resultTabWidget.currentPageIndex())

        if HAS_ALARM:
            signal.signal(signal.SIGALRM, timeout)
            signal.alarm(TIMEOUT)

        try:
            compile_obj = re.compile(self.regex, self.flags)
            allmatches = compile_obj.findall(self.matchstring)

            replace_spans = []
            if allmatches and len(allmatches):
                self.matchNumberSpinBox.setMaxValue(len(allmatches))
                self.matchNumberSpinBox.setEnabled(TRUE)
                self.replaceNumberSpinBox.setMaxValue(len(allmatches))
                self.replaceNumberSpinBox.setEnabled(TRUE)
            else:
                self.matchNumberSpinBox.setEnabled(FALSE)
                self.replaceNumberSpinBox.setEnabled(FALSE)

            match_obj = compile_obj.search(self.matchstring)

        except Exception as e:
            self.update_results(str(e), MATCH_FAIL)
            return

        if HAS_ALARM:
            signal.alarm(0)

        if not match_obj:
            self.update_results(self.MSG_FAIL, MATCH_FAIL)

            self.clear_results()
            return

        # match_index is the list element for match_num.
        # Therefor match_num is for ui display
        # and match_index is for application logic.
        match_index = self.match_num - 1

        if match_index > 0:
            for i in range(match_index):
                match_obj = compile_obj.search(self.matchstring,
                                               match_obj.end())

        self.populate_match_textbrowser(match_obj.start(), match_obj.end())

        self.group_tuples = []

        if match_obj.groups():
            #print( match_obj.groups())
            s = "<font color=blue>"
            num_groups = len(match_obj.groups())

            group_nums = {}
            if compile_obj.groupindex:
                keys = compile_obj.groupindex.keys()
                for key in keys:
                    group_nums[compile_obj.groupindex[key]] = key

            if self.debug:
                print("group_nums:", group_nums)
                print("grp index: ", compile_obj.groupindex)
                print("groups:", match_obj.groups())
                print("span: ", match_obj.span())

            # create group_tuple in the form: (group #, group name, group matches)
            g = allmatches[match_index]
            if type(g) == types.TupleType:
                for i in range(len(g)):
                    group_tuple = (i + 1, group_nums.get(i + 1, ""), g[i])
                    self.group_tuples.append(group_tuple)
            else:
                self.group_tuples.append((1, group_nums.get(1, ""), g))

            #print( group_tuples)
            self.populate_group_table(self.group_tuples)
            #self.populate_group_listview(self.group_tuples)

        str_pattern_matches = str(self.tr("Pattern matches"))
        str_found = str(self.tr("found"))
        str_match = str(self.tr("match"))
        str_matches = str(self.tr("matches"))

        if len(allmatches) == 1:
            status = "%s (%s 1 %s)" % (str_pattern_matches, str_found,
                                       str_match)
        else:
            status = "%s (%s %d %s)" % (str_pattern_matches, str_found,
                                        len(allmatches), str_match)

        self.update_results(status, MATCH_OK)
        self.populate_code_textbrowser()

        spans = self.findAllSpans(compile_obj)
        if self.replace:
            self.populate_replace_textbrowser(spans, len(allmatches),
                                              compile_obj)
        self.populate_matchAll_textbrowser(spans)

    def findAllSpans(self, compile_obj):
        spans = []

        match_obj = compile_obj.search(self.matchstring)

        last_span = None

        while match_obj:
            start = match_obj.start()
            end = match_obj.end()
            span = (start, end)
            if last_span == span: break

            spans.append(span)

            last_span = span
            match_obj = compile_obj.search(self.matchstring, end)

        return spans

    def closeEvent(self, ev):
        self.checkEditState(self.tr("&No, Just Exit Kodos"))
        saveWindowSettings(self, GEO)

        try:
            self.regexlibwin.close()
        except Exception:
            pass
        try:
            self.ref_win.close()
        except Exception:
            pass
        ev.accept()

    def fileNew(self):
        self.checkEditState()
        self.filename = ""

        self.regexMultiLineEdit.setText("")
        self.stringMultiLineEdit.setText("")
        self.replaceTextEdit.setText("")
        self.set_flags(0)
        self.editstate = 0

    def importFile(self):
        fn = QFileDialog.getOpenFileName(self.filename, "All (*)", self,
                                         "Import File")

        if fn.isEmpty():
            self.updateStatus(self.tr("A file was not selected for import"),
                              -1, 5, TRUE)
            return None

        filename = str(fn)

        try:
            fp = open(filename, "r")
        except Exception:
            msg = self.tr("Could not open file for reading: ") + filename
            self.updateStatus(msg, -1, 5, TRUE)
            return None

        data = fp.read()
        fp.close()
        self.stringMultiLineEdit.setText(data)

    def fileOpen(self):
        fn = QFileDialog.getOpenFileName(self, self.tr("Open Kodos File"), ".",
                                         "*.kds\nAll (*)")
        if not fn.isEmpty():
            filename = str(fn)
            if self.openFile(filename):
                self.recent_files.add(filename)

    def openFile(self, filename):
        self.checkEditState()

        self.filename = None

        try:
            fp = open(filename, "r")
        except Exception:
            msg = self.tr("Could not open file for reading: ") + filename
            self.updateStatus(msg, -1, 5, TRUE)
            return None

        try:
            u = pickle.Unpickler(fp)
            self.matchNumberSpinBox.setValue(1)
            self.regex = u.load()
            self.regexMultiLineEdit.setText(self.regex)

            self.matchstring = u.load()
            self.stringMultiLineEdit.setText(self.matchstring)

            flags = u.load()
            self.set_flags(flags)

            try:
                replace = u.load()
            except Exception:
                # versions prior to 1.7 did not have replace functionality
                # so kds files saved w/ these versions will throw exception
                # here.
                replace = ""
            self.replaceTextEdit.setText(replace)

            self.filename = filename
            msg = "%s %s" % (filename, str(self.tr("loaded successfully")))
            self.updateStatus(msg, -1, 5, TRUE)
            self.editstate = STATE_UNEDITED
            return 1
        except Exception as e:
            if self.debug: print(str(e))
            msg = "%s %s" % (str(
                self.tr("Error reading from file:")), filename)
            self.updateStatus(msg, -1, 5, TRUE)
            return 0

    def fileSaveAs(self):
        while 1:
            self.filedialog = QFileDialog(self.filename, "*.kds\nAll (*)",
                                          self, "Save", TRUE)
            self.filedialog.setCaption(self.tr("Save Kodos File"))
            self.filedialog.setMode(QFileDialog.AnyFile)
            #self.filedialog.show()
            ok = self.filedialog.exec_loop()

            filename = str(self.filedialog.selectedFile())
            if not ok or not filename:
                self.updateStatus(self.tr("No file selected to save"), -1, 5,
                                  TRUE)
                return
            filename = os.path.normcase(filename)

            basename = os.path.basename(filename)
            if basename.find(".") == -1:
                filename += ".kds"

            if os.access(filename, os.F_OK):
                message = "%s, %s %s\n%s" % (
                    str(self.tr("The file")), filename,
                    str(self.tr("already exists.")),
                    str(self.tr("Would you like to replace it?")))
                cancel = QMessageBox.information(None,
                                                 self.tr("Replace file?"),
                                                 message, self.tr("&Replace"),
                                                 self.tr("&Cancel"))
                if cancel:
                    # allow user to choose another filename
                    continue

            self.filename = filename
            self.fileSave()
            break

    def fileSave(self):
        if not self.filename:
            self.fileSaveAs()
            return

        try:
            fp = open(self.filename, "w")
        except Exception:
            msg = "%s: %s" % (str(
                self.tr("Could not open file for writing:")), self.filename)
            self.updateStatus(msg, -1, 5, TRUE)
            return None

        self.editstate = STATE_UNEDITED
        p = pickle.Pickler(fp)
        p.dump(self.regex)
        p.dump(self.matchstring)
        p.dump(self.flags)
        p.dump(self.replace)

        fp.close()
        msg = "%s %s" % (str(self.filename), str(
            self.tr("successfully saved")))
        self.updateStatus(msg, -1, 5, TRUE)
        self.recent_files.add(self.filename)

    def paste_symbol(self, symbol):
        self.regexMultiLineEdit.insertPlainText(symbol)

    def process_embedded_flags(self, regex):
        # determine if the regex contains embedded regex flags.
        # if not, return 0 -- inidicating that the regex has no embedded flags
        # if it does, set the appropriate checkboxes on the UI to reflect the flags that are embedded
        #   and return 1 to indicate that the string has embedded flags
        match = self.embedded_flags_obj.match(regex)
        if not match:
            self.embedded_flags = ""
            self.regex_embedded_flags_removed = regex
            return 0

        self.embedded_flags = match.group('flags')
        self.regex_embedded_flags_removed = self.embedded_flags_obj.sub(
            "", regex, 1)

        for flag in self.embedded_flags:
            if flag == 'i':
                self.ignorecaseCheckBox.setChecked(1)
            elif flag == 'L':
                self.localeCheckBox.setChecked(1)
            elif flag == 'm':
                self.multilineCheckBox.setChecked(1)
            elif flag == 's':
                self.dotallCheckBox.setChecked(1)
            elif flag == 'u':
                self.unicodeCheckBox.setChecked(1)
            elif flag == 'x':
                self.verboseCheckBox.setChecked(1)

        return 1

    def checkEditState(self, noButtonStr=None):
        if not noButtonStr: noButtonStr = self.tr("&No")

        if self.editstate == STATE_EDITED:
            message = self.tr(
                "You have made changes. Would you like to save them before continuing"
            )

            prompt = QMessageBox.warning(None,
                                         self.tr("Save changes?"), message,
                                         self.tr("&Yes, Save Changes"),
                                         noButtonStr)

            if prompt == 0:
                self.fileSave()
                if not self.filename: self.checkEditState(noButtonStr)

    def pasteFromRegexLib(self, d):
        self.filename = ""
        self.checkEditState()

        self.regexMultiLineEdit.setText(d.get('regex'), "")
        self.stringMultiLineEdit.setText(d.get('text'), "")
        self.replaceTextEdit.setText(d.get('replace'), "")

        try:
            # set the current page if applicable
            self.resultTabWidget.setCurrentPage(int(d['tab']))
        except Exception:
            pass
        self.editstate = STATE_UNEDITED

    def revert_file_slot(self):
        if not self.filename:
            self.updateStatus(self.tr("There is no filename to revert"), -1, 5,
                              TRUE)
            return

        self.openFile(self.filename)

    def getWidget(self):
        widget = qApp.focusWidget()
        if (widget == self.regexMultiLineEdit
                or widget == self.stringMultiLineEdit
                or widget == self.replaceTextEdit
                or widget == self.codeTextBrowser):
            return widget
        else:
            return None

    def widgetMethod(self, methodstr, anywidget=0):
        # execute the methodstr of widget only if widget
        # is one of the editable widgets OR if the method
        # may be applied to any widget.
        widget = qApp.focusWidget()
        if anywidget or (widget == self.regexMultiLineEdit
                         or widget == self.stringMultiLineEdit
                         or widget == self.replaceTextEdit
                         or widget == self.codeTextBrowser):
            try:
                eval("widget.%s" % methodstr)
            except Exception:
                pass

    def editUndo(self):
        self.widgetMethod("undo()")

    def editRedo(self):
        self.widgetMethod("redo()")

    def editCopy(self):
        self.widgetMethod("copy()", 1)

    def editCut(self):
        self.widgetMethod("cut()")

    def editPaste(self):
        self.widgetMethod("paste()")

    def preferences(self):
        self.prefs.showPrefsDialog()

    def setfont(self, font):
        #print( "font: ",  font)
        #return
        self.regexMultiLineEdit.setFontFamily(font)
        self.stringMultiLineEdit.setFontFamily(font)
        self.replaceTextEdit.setFontFamily(font)

    def setMatchFont(self, font):
        self.groupTable.setFont(font)
        self.matchTextBrowser.setFont(font)
        self.matchAllTextBrowser.setFont(font)
        self.replaceTextBrowser.setFont(font)
        self.codeTextBrowser.setFont(font)

    def getfont(self):
        return self.regexMultiLineEdit.font()

    def getMatchFont(self):
        return self.groupTable.fontFamily()

    def helpHelp(self):
        self.helpWindow = help.Help(self, "kodos.html")

    def helpPythonRegex(self):
        self.helpWindow = help.Help(self, "python" + os.sep + "module-re.html",
                                    str(self.prefs.browserEdit.text()))

    def helpRegexLib(self):
        f = os.path.join("help", "regex-lib.xml")
        self.regexlibwin = RegexLibrary(self, f)
        self.regexlibwin.show()

    def helpAbout(self):
        self.aboutWindow = About()
        self.aboutWindow.show()

    def kodos_website(self):
        self.launch_browser_wrapper("http://kodos.sourceforge.net")

    def check_for_update(self):
        url = "http://sourceforge.net/project/showfiles.php?group_id=43860"
        try:
            fp = urllib.urlopen(url)
        except Exception:
            self.status_bar.set_message(self.tr("Failed to open url"), 5, TRUE)
            return

        lines = fp.readlines()
        html = string.join(lines)

        rawstr = r"""kodos-(?P<version>.*?)\<"""
        #rawstr = r"""release_id=.*\">.*(kodos-)(?P<version>.*?)</[aA]>"""
        match_obj = re.search(rawstr, html)
        if match_obj:
            latest_version = match_obj.group('version')
            if latest_version == VERSION:
                QMessageBox.information(
                    None, self.tr("No Update is Available"),
                    str(
                        self.
                        tr("You are currently using the latest version of Kodos"
                           )) + " (%s)" % VERSION)
            else:
                message =  "%s\n\n%s: %s.\n%s: %s.\n\n%s\n" % \
                          (str(self.tr("There is a newer version of Kodos available.")),
                           str(self.tr("You are using version:")),
                           VERSION,
                           str(self.tr("The latest version is:")),
                           latest_version,
                           str(self.tr("Press OK to launch browser")))

                self.launch_browser_wrapper(url,
                                            self.tr("Kodos Update Available"),
                                            message)
        else:
            message = "%s.\n\n%s" % \
                      (str(self.tr("Unable to get version info from Sourceforge")),
                       str(self.tr("Press OK to launch browser")))
            self.launch_browser_wrapper(url,
                                        self.tr("Unknown version available"),
                                        message)

    def launch_browser_wrapper(self, url, caption=None, message=None):
        browser = str(self.prefs.browserEdit.text())
        if launch_browser(browser, url, caption, message):
            self.status_bar.set_message(self.tr("Launching web browser"), 3,
                                        TRUE)
        else:
            self.status_bar.set_message(
                self.tr("Cancelled web browser launch"), 3, TRUE)

    def reference_guide(self):
        self.ref_win = Reference(self)
        self.ref_win.show()

    def report_bug(self):
        self.bug_report_win = reportBugWindow(self)