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)