def __init__(self, history, commands): self.history = history self.reset_history() super(CommandBox, self).__init__() completer = QCompleter(['!' + name for name in commands]) completer.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(completer)
def __create_filter_ui(self): """ Create filter widgets """ filter_layout = QHBoxLayout() filter_layout.setSpacing(1) filter_layout.setContentsMargins(0, 0, 0, 0) self.filter_reset_btn = QPushButton() icon = QIcon(':/filtersOff.png') self.filter_reset_btn.setIcon(icon) self.filter_reset_btn.setIconSize(QSize(22, 22)) self.filter_reset_btn.setFixedSize(24, 24) self.filter_reset_btn.setToolTip('Reset filter') self.filter_reset_btn.setFlat(True) self.filter_reset_btn.clicked.connect( partial(self.on_filter_set_text, '')) self.filter_line = QLineEdit() self.filter_line.setPlaceholderText('Enter filter string here') self.filter_line.textChanged.connect(self.on_filter_change_text) completer = QCompleter(self) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setModel(QStringListModel([], self)) self.filter_line.setCompleter(completer) filter_layout.addWidget(self.filter_reset_btn) filter_layout.addWidget(self.filter_line) return filter_layout
class Completer(QGraphicsProxyWidget, object): ''' Class for handling text autocompletion in the SDL scene ''' def __init__(self, parent): ''' Create an autocompletion list popup ''' widget = QListWidget() super(Completer, self).__init__(parent) self.setWidget(widget) self.string_list = QStringListModel() self._completer = QCompleter() self.parent = parent self._completer.setCaseSensitivity(Qt.CaseInsensitive) # For some reason the default minimum size is (61,61) # Set it to 0 so that the size of the box is not taken # into account when it is hidden. self.setMinimumSize(0, 0) self.prepareGeometryChange() self.resize(0, 0) self.hide() def set_completer_list(self): ''' Set list of items for the autocompleter popup ''' compl = [item.replace('-', '_') for item in self.parent.parentItem().completion_list] self.string_list.setStringList(compl) self._completer.setModel(self.string_list) def set_completion_prefix(self, completion_prefix): ''' Set the current completion prefix (user-entered text) and set the corresponding list of words in the popup widget ''' self._completer.setCompletionPrefix(completion_prefix) self.widget().clear() count = self._completer.completionCount() for i in xrange(count): self._completer.setCurrentRow(i) self.widget().addItem(self._completer.currentCompletion()) self.prepareGeometryChange() if count: self.resize(self.widget().sizeHintForColumn(0) + 40, 70) else: self.resize(0, 0) return count # pylint: disable=C0103 def keyPressEvent(self, e): super(Completer, self).keyPressEvent(e) if e.key() == Qt.Key_Escape: self.parentItem().setFocus() # Consume the event so that it is not repeated at EditableText level e.accept() # pylint: disable=C0103 def focusOutEvent(self, event): ''' When the user leaves the popup, return focus to parent ''' super(Completer, self).focusOutEvent(event) self.hide() self.resize(0, 0) self.parentItem().setFocus()
def setList(self, list): self.clear() self.addItems(list) autoCompleteModel = QStringListModel(list) completer = QCompleter() completer.setModel(autoCompleteModel) completer.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(completer)
class RuleTextEdit(QLineEdit): _valid = True _rule = None completer = None def __init__(self, *args, **kwargs): super(RuleTextEdit, self).__init__(*args, **kwargs) self.setAutoFillBackground(True) self.textChanged.connect(self.onTextChange) model = QStringListModel() model.setStringList(['<', '>', '=', 'vasya']) self.completer = QCompleter(model) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(self.completer) @property def rule(self): return self._rule @rule.setter def rule(self, value): self._rule = value self.gen_rule() def regen_rule(self): text = self.text() m = re.search('\\b(.)([<>=])(\d+)\\b', text) self._valid = False if m: shear = 1 if m.group(2) == '>' else -1 if m.group(2) == '<' else 0 self._rule.new_symbol = str(m.group(1)) self._rule.shear = shear self._rule.next_state = int(m.group(3)) self._valid = True palette = self.palette() assert (isinstance(palette, QPalette)) clr = QColor(255, 255, 128) if self._valid else QColor(255, 128, 128) palette.setColor(self.backgroundRole(), clr) self.setPalette(palette) def onTextChange(self): self.regen_rule() def gen_rule(self): if not self._rule: return self.setText('{0}{1}{2}'.format( self._rule.new_symbol, '<' if self._rule.shear == -1 else '>' if self._rule.shear == 1 else '=', self._rule.next_state) ) self._valid = True
class Completer(QGraphicsProxyWidget, object): ''' Class for handling text autocompletion in the SDL scene ''' def __init__(self, parent): ''' Create an autocompletion list popup ''' widget = QListWidget() super(Completer, self).__init__(parent) self.setWidget(widget) self.string_list = QStringListModel() self._completer = QCompleter() self.parent = parent self._completer.setCaseSensitivity(Qt.CaseInsensitive) # For some reason the default minimum size is (61,61) # Set it to 0 so that the size of the box is not taken # into account when it is hidden. self.setMinimumSize(0, 0) self.prepareGeometryChange() self.resize(0, 0) self.hide() def set_completer_list(self): ''' Set list of items for the autocompleter popup ''' compl = list(self.parent.parentItem().completion_list) self.string_list.setStringList(compl) self._completer.setModel(self.string_list) def set_completion_prefix(self, completion_prefix): ''' Set the current completion prefix (user-entered text) and set the corresponding list of words in the popup widget ''' self._completer.setCompletionPrefix(completion_prefix) self.widget().clear() count = self._completer.completionCount() for i in xrange(count): self._completer.setCurrentRow(i) self.widget().addItem(self._completer.currentCompletion()) self.prepareGeometryChange() if count: self.resize(self.widget().sizeHintForColumn(0) + 40, 70) else: self.resize(0, 0) return count # pylint: disable=C0103 def keyPressEvent(self, e): super(Completer, self).keyPressEvent(e) if e.key() == Qt.Key_Escape: self.parentItem().setFocus() # Consume the event so that it is not repeated at EditableText level e.accept() # pylint: disable=C0103 def focusOutEvent(self, event): ''' When the user leaves the popup, return focus to parent ''' super(Completer, self).focusOutEvent(event) self.hide() self.resize(0, 0) self.parentItem().setFocus()
def config_completer(line_edit, model, field): # sets up a completer based on a QSqlTableModel for the specified field on a QLineEdit completer = QCompleter() completer.setModel(model) completer.setCompletionColumn(model.fieldIndex(field)) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.activated.connect(line_edit.returnPressed) line_edit.setCompleter(completer)
class RuleTextEdit(QLineEdit): _valid = True _rule = None completer = None def __init__(self, *args, **kwargs): super(RuleTextEdit, self).__init__(*args, **kwargs) self.setAutoFillBackground(True) self.textChanged.connect(self.onTextChange) model = QStringListModel() model.setStringList(['<', '>', '=', 'vasya']) self.completer = QCompleter(model) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(self.completer) @property def rule(self): return self._rule @rule.setter def rule(self, value): self._rule = value self.gen_rule() def regen_rule(self): text = self.text() m = re.search('\\b(.)([<>=])(\d+)\\b', text) self._valid = False if m: shear = 1 if m.group(2) == '>' else -1 if m.group(2) == '<' else 0 self._rule.new_symbol = str(m.group(1)) self._rule.shear = shear self._rule.next_state = int(m.group(3)) self._valid = True palette = self.palette() assert (isinstance(palette, QPalette)) clr = QColor(255, 255, 128) if self._valid else QColor(255, 128, 128) palette.setColor(self.backgroundRole(), clr) self.setPalette(palette) def onTextChange(self): self.regen_rule() def gen_rule(self): if not self._rule: return self.setText('{0}{1}{2}'.format( self._rule.new_symbol, '<' if self._rule.shear == -1 else '>' if self._rule.shear == 1 else '=', self._rule.next_state)) self._valid = True
def configure_search_lineedit(self, lineEdit): if not self._configured: # no data received yet. hold on configuration self._search_lineedit = lineEdit else: splitter = lineEdit.column_query_splitter completer = QCompleter([header+splitter for header in self._headers[1:]]) # search anything but the image column completer.setCaseSensitivity(Qt.CaseInsensitive) lineEdit.setCompleter(completer) lineEdit.textEdited.connect(self.query) self._column_query_sep = splitter
def configure_search_lineedit(self, lineEdit): if not self._configured: # no data received yet. hold on configuration self._search_lineedit = lineEdit else: splitter = lineEdit.column_query_splitter completer = QCompleter([ header + splitter for header in self._headers[1:] ]) # search anything but the image column completer.setCaseSensitivity(Qt.CaseInsensitive) lineEdit.setCompleter(completer) lineEdit.textEdited.connect(self.query) self._column_query_sep = splitter
class GlobalClipboard(QtGui.QDialog): def __init__(self): def paste(): loadPath = (self.repository+self.filename_base+"%s.nk")%(self.cb_list.currentText()) print loadPath nuke.nodePaste(loadPath) self.close() self.user = os.environ.get("USERNAME") self.repository = "T://_Nuke_tools//global_clipboard//" self.filename_base = "tempClipBoard_" os.chdir(self.repository) self.items = [] for file in glob.glob("*.nk"): self.items.append(file.split(self.filename_base)[-1].split('.')[0]) super(GlobalClipboard, self).__init__(QtGui.QApplication.activeWindow()) self.setWindowTitle('Global Clipboard') self.hbox=QtGui.QHBoxLayout() self.cb_list=QtGui.QComboBox() self.cb_list.setEditable(True) for item in self.items: self.cb_list.addItem(item) self.completer = QCompleter() self.cb_list.setCompleter(self.completer) self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) model_autocomplete = QStringListModel() self.completer.setModel(model_autocomplete) model_autocomplete.setStringList(self.items) self.description=QtGui.QLabel(self) self.description.setText("Paste from") self.hbox.addWidget(self.description)#desc self.hbox.addWidget(self.cb_list)#menu self.button=QtGui.QPushButton("Paste") self.hbox.addWidget(self.button)#button self.button.clicked.connect(paste) self.setLayout(self.hbox) def copy(self): savePath = (self.repository+self.filename_base+"%s.nk")%(self.user) nuke.nodeCopy(savePath) print "Selected nodes saved to "+ savePath def showDialog(self): wnd = GlobalClipboard() wnd.show()
def _createApiChooserLineedit(self): """ Create the I{QLineEdit }used for selecting API names. This includes a QCompleter to make suggestions based on the keyword database. """ self.api_chooser_lineedit = QLineEdit() self.api_chooser_lineedit.returnPressed.connect(self.populateBrowserWindow) self.api_chooser_lineedit.textChanged.connect(self._updateCompleterModel) completer = QCompleter() completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) completer.setModelSorting(QCompleter.CaseSensitivelySortedModel) self.completer_model = QStringListModel([]) completer.setModel(self.completer_model) self.api_chooser_lineedit.setCompleter(completer)
def __init__(self, parent=None, list=[]): QComboBox.__init__(self, parent) self.setEditable(True) self.setInsertPolicy(QComboBox.NoInsert) self.addItems(list) autoCompleteModel = QStringListModel(list) completer = QCompleter() completer.setModel(autoCompleteModel) completer.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(completer) self.setEditText("") self.__textChangeStatus = True self.editTextChanged.connect(self.__onTextChange) shortcut = QShortcut(QKeySequence(Qt.Key_Return), self, self.__onEnter) shortcut = QShortcut(QKeySequence(Qt.Key_Enter), self, self.__onEnter)
class GraphWidget(RWWidget, Ui_Form): """ Displays a graph of the Ontology and passes all modifications to the SyntaxController. Variables: - abstractGraph: The currently displayed AbstractGraph. - gv: The layouted version of the current DotGraph. """ def __init__(self, mainwindow): """ Initializes the GraphWidget. """ super(GraphWidget, self).__init__(mainwindow) self.setupUi(self.mw) self.startRelation = None self.abstractGraph = None self.gv = pygraphviz.AGraph(strict=False) self.widget = self.layoutWidget self.log = logging.getLogger('.' + __name__) self.nodesToQNodes = {} self.qLines = [] self.qpens = {} self.completer = QCompleter(list("")) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWidget(self.lineEdit) self.lastScale = 1 self.initMenu() self.roots = set() self.doubleSpinBox.valueChanged[float].connect(self.changeScale) self.lineEdit.textChanged.connect(self.searchNode) self.rootSelector.insertItem(0, "---") self.rootSelector.currentIndexChanged[str].connect(self.newRoot) self.relations.currentIndexChanged[str].connect(self.newVariant) self.depth.valueChanged.connect(self.newRoot) self._updateActiveOntology() self.graphicsView.setScene(QGraphicsScene()) # def initRelationBox(self): # m = self.relations.model() # for i in self.getIndexAbstractor().get_graph('instance').relations.keys(): # m.appendRow(QStandardItem(i)) def refresh(self): """ Override Widget Updates the GraphWidget regarding to latest indexabstractor changes """ self.newVariant() super(GraphWidget, self).refresh() def getActiveOntology(self): idx = self.activeOntology.currentIndex() return self.activeOntology.itemData(idx) def _updateActiveOntology(self): currentText = self.activeOntology.currentText() self.activeOntology.clear() idx = -1 count = 0 for i in self.getIndexAbstractor().ontologies: if currentText == i.name: idx = count self.activeOntology.addItem(i.name, i) count = count + 1 self.activeOntology.setCurrentIndex(idx) def searchNode(self, search): """Search the node and focus the GraphicView to the node """ try: #self.completer.setCompletionPrefix(search) #self.completer.complete() node = self.nodesToQNodes[search] self.graphicsView.centerOn(node) except KeyError: pass # TODO: Mach hier einen Log def addRelation(self, qnode): """ Adds a relation or save a starting point """ if self.startRelation != None: # yeah a new relation self.log.info("Add relation from " + self.startRelation.node + " to " + qnode.node) if self.relations.currentText() == "---": msg = QMessageBox() msg.setText("Please choose a valid variant.") msg.exec_() return addstr = "\n(" + self.relations.currentText( ) + " " + self.startRelation.node + " " + qnode.node + ")\n" self.startRelation = None ontology = None for i in self.getIndexAbstractor().ontologies: if i.name == self.activeOntology.currentText(): ontology = i if ontology is None: msg = QMessageBox() msg.setText("Please choose a valid Ontology to write to.") msg.exec_() return self.lineEdit.setText(qnode.node) x = self.getIndexAbstractor().get_ontology_file(ontology) x.seek(0, 2) x.write(addstr) QApplication.setOverrideCursor(Qt.BusyCursor) self.SyntaxController.add_ontology(ontology, newversion=x.getvalue()) QApplication.setOverrideCursor(Qt.ArrowCursor) self.commit() else: self.log.info("Starting node is " + qnode.node) self.startRelation = qnode def _printPreview_(self): dialog = QPrintPreviewDialog() dialog.paintRequested.connect(self.print_) dialog.exec_() def print_(self, printer): painter = QPainter(printer) painter.setRenderHint(QPainter.Antialiasing) self.graphicsView.render(painter) def zoomIn(self): val = self.doubleSpinBox.value() + 0.10 self.doubleSpinBox.setValue(val) def zoomOut(self): val = self.doubleSpinBox.value() - 0.10 self.doubleSpinBox.setValue(val) @Slot(float) def changeScale(self, val): """ Scale the GraphicView to val Arguments: - val: The value to scale to. In Designer: 0.01 <= val <= 5 """ toScale = val / self.lastScale self.lastScale = val self.graphicsView.scale(toScale, toScale) @Slot() def renewplot(self): """ Do not layout anything, but redraw all lines""" scene = self.graphicsView.scene() self.roots = set() # scene.changed.disconnect(self.renewplot) for i in self.qLines: scene.removeItem(i) self.qLines = [] for edge in self.gv.edges_iter(): qnode1 = self.nodesToQNodes[edge[0]] qnode2 = self.nodesToQNodes[edge[1]] line = QLineF(qnode1.pos(), qnode2.pos()) line.setLength(line.length() - 40) end = line.p2() arrowLine1 = QLineF() arrowLine1.setP1(end) arrowLine1.setLength(10) arrowLine1.setAngle(line.angle() + 210) arrowLine2 = QLineF() arrowLine2.setP1(end) arrowLine2.setLength(10) arrowLine2.setAngle(line.angle() - 210) if edge.attr['color'] not in self.qpens: self.qpens[edge.attr['color']] = QPen( QColor(edge.attr['color'])) item = scene.addLine(line, self.qpens[edge.attr['color']]) item.setZValue(-1) item.setFlag(QGraphicsItem.ItemIsSelectable, True) self.qLines.append(item) item = scene.addLine(arrowLine1, self.qpens[edge.attr['color']]) self.qLines.append(item) item = scene.addLine(arrowLine2, self.qpens[edge.attr['color']]) self.qLines.append(item) self.roots.add(edge[0]) # scene.changed.connect(self.renewplot) def plot(self): """ Creates a QGraphicScene for the layouted graph in self.gv This function has to be called every time, a node change happened. """ scene = self.graphicsView.scene() scene.clear() self.nodesToQNodes = {} self.qLines = [] for node in self.gv.nodes_iter(): (x, y) = node.attr['pos'].split(',') x = float(x) y = float(y) point = self.graphicsView.mapToScene(int(x), int(y)) qnode = self.createQtNode(node, point.x(), point.y()) scene.addItem(qnode) self.nodesToQNodes[node] = qnode self.completer = QCompleter(list(self.nodesToQNodes.keys())) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWidget(self.lineEdit) self.lineEdit.setCompleter(self.completer) self.renewplot() self.searchNode(self.lineEdit.text()) def createQtNode(self, node, posx, posy, color=QColor(255, 150, 150)): """ Create a QtNode with given position, color for given node Arguments: - node: The graphviz node - posx: The x position from graphviz layout - posy: The y position from graphviz layout - color: The color of circle (red by default) """ #dpi = float(self.gv.graph_attr['dpi']) dpi = 96 try: width = float(node.attr['width']) height = float(node.attr['height']) except ValueError: #New created node width = 300 / 96 height = 40 / 96 qnode = QtNode(-width * dpi / 2, -height * dpi / 2, width * dpi, height * dpi) qnode.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) qnode.setPos(posx, posy) qnode.setFlag(QGraphicsItem.ItemIsMovable) qnode.setCallback(weakref.ref(self)) qnode.setNode(node) qnode.setBrush(color) txt = QGraphicsSimpleTextItem(qnode) font = txt.font() font.setPointSize(14) txt.setFont(font) txt.setText(node) txtwidth = QFontMetricsF(font).width(node) txtheight = QFontMetricsF(font).height() toLeft = (-width * dpi / 2) + (width * dpi - txtwidth) / 2 toBottom = (-height * dpi / 2) + (height * dpi - txtheight) / 2 txt.setPos(toLeft, toBottom) return qnode def initMenu(self): """ Configure the Widget to provide a handmade CustomContextMenu """ self.graphicsView.setContextMenuPolicy(Qt.CustomContextMenu) self.graphicsView.customContextMenuRequested.connect( self.showContextMenu) def showContextMenu(self, pos): """ Shows a context menu to add a node in the graph widget """ gpos = self.graphicsView.mapToGlobal(pos) menu = QMenu() actionAddNode = menu.addAction("Add Node") QAction = menu.exec_(gpos) if (actionAddNode == QAction): (text, ok) = QInputDialog.getText(self.graphicsView, "Insert Node Name", "Please insert a name for the node") if ok: if text not in self.nodesToQNodes: #User clicked on ok. Otherwise do nothing self.gv.add_node(text) node = self.gv.get_node(text) qnode = self.createQtNode(node, 0, 0, QColor(204, 255, 255)) self.graphicsView.scene().addItem(qnode) qnode.setPos(self.graphicsView.mapToScene(gpos)) qnode.setPos(qnode.x(), qnode.y() - 200) self.nodesToQNodes[node] = qnode else: msg = QMessageBox() msg.setText("The node already exists.") msg.exec_() self.searchNode(text) @Slot() def newRoot(self): """ Change to new root set in the widget and redraw""" root = self.rootSelector.currentText() variant = [(0, self.relations.currentText())] if root == "---": root = None depth = None if self.depth.value() != -1: depth = self.depth.value() if variant == "---": variant = '' self.createGV(variant, root, depth) self.plot() self.searchNode(root) def newVariant(self): """ Change to new variant set in the widget and redraw""" self.rootSelector.currentIndexChanged[str].disconnect(self.newRoot) self.rootSelector.clear() self.rootSelector.insertItem(0, "---") self.newRoot() self.rootSelector.insertItems(1, list(self.roots)) self.rootSelector.currentIndexChanged[str].connect(self.newRoot) def createGV(self, variant='instance', r=None, d=None): """ Create a pygraphviz graph from pysumo abstract graph and layout it. Arguments: - variant: The variant to use (e.g. instance) - r: The root - d: The depth (none for infinite depth """ gv = pygraphviz.AGraph(strict=False, overlap="scale") y = self.getIndexAbstractor().get_graph(variant, root=r, depth=d) if y is None or len(y.relations) == 0: return QApplication.setOverrideCursor(Qt.BusyCursor) colors = [ "black", "red", "blue", "green", "darkorchid", "gold2", "yellow", "turquoise", "sienna", "darkgreen" ] for k in y.relations.keys(): l = [(k, v) for v in y.relations[k]] gv.add_edges_from(l, color=random.choice(colors)) gv.layout("sfdp") self.gv = gv QApplication.setOverrideCursor(Qt.ArrowCursor)
class mainwin(QMainWindow): def __init__(self, parent=None): super(mainwin, self).__init__(parent) self.setWindowTitle("Nigandu English to Tamil Dictionary") self.setGeometry(200, 50, 650, 600) self.setMinimumHeight(620) self.setMinimumWidth(650) self.setMaximumHeight(660) self.setMaximumWidth(800) #Setting up status bar self.myStatusBar = QStatusBar() self.myStatusBar.showMessage('Ready', 7000) self.setStatusBar(self.myStatusBar) #Setting up application icon appIcon = QIcon(":/icons/njnlogo.png") self.setWindowIcon(appIcon) # defining the central widget self.central = QWidget(self) #combobox plus search button self.whole = QVBoxLayout(self.central) self.gridlayout = QGridLayout() self.comboBox = QLineEdit(self) #self.comboBox.setEditable(True) self.comboBox.setObjectName("comboBox") self.completer = QCompleter(self.comboBox) self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setMaxVisibleItems(10) self.comboBox.setCompleter(self.completer) #self.comboBox.setCompleter() self.gridlayout.addWidget(self.comboBox, 1, 1, 1, 2) self.searchbtn = QPushButton() self.searchbtn.setObjectName("searchbtn") self.searchbtn.setText("&Search") self.gridlayout.addWidget(self.searchbtn, 1, 3) vbox = QVBoxLayout() self.tamtext = QTextBrowser() self.listview = QListWidget(self) #self.listview.setEditTriggers(QAbstractItemView.NoEditTriggers) self.listview.setWindowTitle("Suggested words") self.tamtext.setMinimumHeight(100) self.tamtext.setMaximumHeight(150) vbox.addWidget(self.tamtext) self.suglbl = QLabel(self) self.suglbl.setText("Suggested Words:") vbox.addWidget(self.suglbl) vbox.addWidget(self.listview) self.whole.addLayout(self.gridlayout) self.whole.addLayout(vbox) self.setCentralWidget(self.central) #setting docks self.histdockwidg = QDockWidget("History", self) self.bkmdockwidg = QDockWidget("Book Marks", self) self.histdockwidg.setObjectName("self.histdockwidg") self.bkmdockwidg.setObjectName("self.bkmdockwidg") #self.histdockwidg.setMaximumWidth(histwidth) self.histdockwidg.setAllowedAreas(Qt.RightDockWidgetArea) self.bkmdockwidg.setAllowedAreas(Qt.RightDockWidgetArea) self.histdockwidg.setMaximumWidth(250) self.bkmdockwidg.setMaximumWidth(250) self.histdockwidg.setMinimumWidth(200) self.bkmdockwidg.setMinimumWidth(200) #self.bkmdockwidg.setMaximumWidth(histwidth) self.histli = QListWidget() self.bkmli = QListWidget() self.histlis = [0] self.bkmlistfromfile = [] self.histdockwidg.setWidget(self.histli) self.bkmdockwidg.setWidget(self.bkmli) self.addDockWidget(Qt.RightDockWidgetArea, self.histdockwidg) self.addDockWidget(Qt.RightDockWidgetArea, self.bkmdockwidg) #file menu fi_addwrd = self.createactions("&Add a word...", self.addwrdf, "Alt+A", ":/icons/add.png", "Add a word to the dictionary. . .") fi_options = self.createactions("&Options", self.optionsf, "None", ":/icons/options.png", "Change the default settings. . .") fi_help = self.createactions("&Help", self.helpf, QKeySequence.HelpContents, ":/icons/help.png", "Help contents. . .") fi_quit = self.createactions("&Quit", self.close, QKeySequence.Close, ":/icons/quit.png", "Close the application. . .") fplus = self.createactions("FontPlus", self.fplusf, "None", ":/icons/fplus.png", "Increase the font size") fminus = self.createactions("FontMinus", self.fminusf, "None", ":/icons/fminus.png", "Decrease the font size") #list of file actions fi_menu = (fi_addwrd, fi_options, fi_help, None, fi_quit) #go menu self.go_prev = self.createactions("&Previous Word", self.prevf, "Alt+Z", ":/icons/prev.png", "Previous Word") self.go_next = self.createactions("&Next Word", self.nextf, "Alt+X", ":/icons/next.png", "Next Word") self.go_rand = self.createactions("&Random Word", self.randf, "Ctrl+R", ":/icons/rand.png", "Select a random word") #list of go actions go_menu = (self.go_prev, self.go_next, self.go_rand ) self.go_next.setEnabled(False) self.go_prev.setEnabled(False) #book mark menu self.bkm_addfav = self.createactions("&Bookmark", self.addfavf, "Ctrl+B", ":/icons/bookmark.png", "Book mark this word") self.bkm_viewbkm = self.createactions("&View Bookmarks", self.viewbkmf, "Alt+V", ":/icons/viewbkm.png", "View bookmarked words") #list of book mark items bkm_menu = (self.bkm_addfav, self.bkm_viewbkm) #help menu hlp_about = self.createactions("Abo&ut", self.aboutf, "Ctrl+U", ":/icons/about.png", "About") hlp_visitblog = self.createactions("&Visit Blog", self.visitblogf, "None", ":/icons/visitblog.png", "Visit our blog") hlp_help = self.createactions("&Help", self.helpf, "Ctrl+H", ":/icons/help.png", "Help Contents") #list of help menu items hlp_menu = (hlp_about, hlp_visitblog, hlp_help) #Setting up the menubar filemenu = self.menuBar().addMenu("&File") self.addmenu(filemenu, fi_menu) gomenu = self.menuBar().addMenu("&Go") self.addmenu(gomenu, go_menu) bkmmenu = self.menuBar().addMenu("&Book Mark") self.addmenu(bkmmenu, bkm_menu) helpmenu = self.menuBar().addMenu("&Help") self.addmenu(helpmenu, hlp_menu) intn = QSize(40, 40) self.setIconSize(intn) #Setting up the tool bar filetools = self.addToolBar("File") filetools.setObjectName("filetools") self.addmenu(filetools, (fi_addwrd, fplus, fminus)) gotools = self.addToolBar("Go") gotools.setObjectName("gotools") self.addmenu(gotools, go_menu) bkmtools = self.addToolBar("Bkm") bkmtools.setObjectName("bkmtools") self.addmenu(bkmtools, bkm_menu) hlptools = self.addToolBar("Help") hlptools.setObjectName("helptools") self.addmenu(hlptools, hlp_menu) self.loadfiles() self.returncount = 0 self.bkm_addfav.setEnabled(False) #clipboard function if self.clipauto: clip = QApplication.clipboard() cliptxt = clip.text() self.comboBox.setText(cliptxt) self.setevent() #connections self.connect(self.comboBox, SIGNAL("textChanged(QString)"), self.search) self.connect(self.comboBox, SIGNAL("returnPressed()"), self.returnpressedevent) self.connect(self.searchbtn, SIGNAL("clicked()"), self.onenter) self.connect(self.listview, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.listwidcall) self.connect(self.histli, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.listwidcall) self.connect(self.bkmli, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.listwidcall) def writehistlis(self, lis): if len(lis) >= 2: for i in range(1, len(lis)): cur.execute("insert into HISTORY values(?)", (lis[i], )) def writebkmlis(self, lis): cur.execute("delete from BOOKMARKS") if len(lis) > 0: for i in range(len(lis)): cur.execute("insert into BOOKMARKS values(?)", (lis[i], )) def listwidcall(self, item): self.comboBox.setText(item.text()) self.setevent() def search(self, text, *args): li = [] tplus = text + "%" cur.execute("select ENGW from ENGTAM where ENGW like ? limit 20", (tplus, )) cuf = cur.fetchall() model = QStringListModel() for i in range(len(cuf)): k = cuf[i][0] li.append(k) model.setStringList(li) self.completer.setModel(model) def returnpressedevent(self, *args): self.comboBox.selectAll() self.returncount += 1 if self.returncount % 2 == 0: self.setevent() else: self.comboBox.selectAll() def setevent(self): self.comboBox.selectAll() self.bkm_addfav.setEnabled(True) lis = [] eng = self.comboBox.text() cur.execute("SELECT rowid, TAMW FROM ENGTAM WHERE ENGW like ? limit 1", (eng,)) cuf = cur.fetchall() if len(cuf) == 0: self.tamtext.setText("No words found. . . ") self.listview.addItem("No Suggestions. . .") else: for i in range(len(cuf)): tam = cuf[0][1] rowid = cuf[0][0] self.tamtext.setText(tam) if rowid <= 25: start = 0 end = 50 elif rowid >= 190513: start = rowid - 190487 end = rowid + 190537 else: start = rowid - 25 end = rowid + 25 cur.execute("SELECT ENGW FROM ENGTAM WHERE rowid>=? and rowid<=?", (start, end, )) cuff = cur.fetchall() for i in range(len(cuff)): engw = cuff[i][0] lis.append(engw) if self.listview.count() is not None: self.listview.clear() self.listview.addItems(lis) self.addtoli(eng, self.histlis) if self.histlis[0] >= 2: self.go_prev.setEnabled(True) self.comboBox.setFocus() if self.histdock: self.histli.addItem(eng) def addtoli(self, addw, lis, c=1): if len(lis) > 0: if type(lis[0]) == int: if len(lis) >= 2: for i in range(1, len(lis)): if lis[i] == addw: c = 0 pass if c == 1: lis.append(addw) else: lis.append(addw) lis[0] = len(lis) - 1 def addtobkmli(self, addw, lis, nc=1): for i in range(len(lis)): if lis[i] == addw: nc = 0 pass if nc == 1: lis.append(addw) def onenter(self, *args): self.comboBox.selectAll() self.setevent() def loadfiles(self): self.loadsettings() self.loadhistlis() self.loadbkm() self.setfontsize(int(self.fontsize)) self.setdocks() def setdocks(self): ist = str(self.histdock) jst = str(self.bkmdock) if ist == "False": self.removedock(self.histdockwidg) else: self.adddock(self.histdockwidg) if jst == "False": self.removedock(self.bkmdockwidg) else: self.adddock(self.bkmdockwidg) def loadsettings(self): cur.execute("select * from SETTINGS") cuffun = cur.fetchall() fn = int(cuffun[0][1]) self.fontsize = fn self.clipauto = cuffun[1][1] self.histdock = cuffun[2][1] self.savehist = cuffun[3][1] self.bkmdock = cuffun[4][1] self.delhist = cuffun[5][1] self.delbkm = cuffun[6][1] def loadhistlis(self): histtodockli = [] cur.execute("select * from HISTORY") historyfetch = cur.fetchall() for i in range(len(historyfetch)): self.addtobkmli(historyfetch[i][0], histtodockli) for i in histtodockli: self.histli.addItem(i) def loadbkm(self): cur.execute("select * from BOOKMARKS") bkmfetch = cur.fetchall() for i in range(len(bkmfetch)): self.addtobkmli(bkmfetch[i][0], self.bkmlistfromfile) for i in self.bkmlistfromfile: self.bkmli.addItem(i) def createactions(self, text, slot=None, shortcut="None", icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action def addmenu(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) #Actions def addwrdf(self): self.dlg = addawrd() self.dlg.show() self.connect(self.dlg.buttonBox, SIGNAL("rejected()"), self.dlg.close) self.connect(self.dlg.buttonBox, SIGNAL("accepted()"), self.addawordtodb) def addawordtodb(self): eng = self.dlg.lineEdit.text() tam = self.dlg.lineEdit_2.text() if len(eng) != 0 and len(tam) != 0: cur.execute("INSERT INTO ENGTAM(ENGW, TAMW) VALUES(?, ?)", (eng, tam, )) self.dlg.close() QMessageBox.information(self, "Nigandu Eng -> Tam Dictionary", "Added Successfully. . .") else: self.dlg.lineEdit.setFocus() self.dlg.close() QMessageBox.warning(self, "Nigandu Eng -> Tam Dictionary", "Invalid Entry. . .") def optionsf(self): self.opt = optdlg(self) self.opt.spinBox.setProperty("value", int(self.fontsize)) font = QFont() font.setPixelSize(int(self.fontsize)) self.opt.sampletxt.setFont(font) if str(self.clipauto) == "True": self.opt.checkclip.setChecked(True) elif str(self.clipauto) == "False": self.opt.checkclip.setChecked(False) if str(self.histdock) == "True": self.opt.checkshowhistdock.setChecked(True) elif str(self.histdock) == "False": self.opt.checkshowhistdock.setChecked(False) if str(self.bkmdock) == "True": self.opt.checkshowbkmdock.setChecked(True) elif str(self.bkmdock) == "False": self.opt.checkshowbkmdock.setChecked(False) self.opt.show() self.connect(self.opt.buttonBox, SIGNAL("accepted()"), self.optok) self.connect(self.opt.buttonBox.button(QDialogButtonBox.Apply), SIGNAL("clicked()"), self.optapply) self.connect(self.opt.checkdelhist, SIGNAL("stateChanged(int)"), self.deleteallhist) self.connect(self.opt.checkshowhistdock, SIGNAL("stateChanged(int)"), self.shownexttime) self.connect(self.opt.checkshowbkmdock, SIGNAL("stateChanged(int)"), self.shownexttime) def shownexttime(self, i): if i == 0: pass if i == 2: QMessageBox.information(self, self.windowTitle(), "Click Apply or Ok \n The Dock window will be added, \n the next time you start the application. . .") def optok(self): self.optapply() self.opt.close() def optapply(self): self.updatesettings() self.applyopt() def updatesettings(self): self.fontsize = self.opt.spinBox.value() self.clipauto = self.opt.checkclip.isChecked() self.histdock = self.opt.checkshowhistdock.isChecked() self.bkmdock = self.opt.checkshowbkmdock.isChecked() self.delhist = self.opt.checkdelhist.isChecked() for i, j in [("fontsize", self.fontsize),("clipauto", str(self.clipauto)),("histdock", str(self.histdock)), ("bkmdock", str(self.bkmdock)),("delhist", str(self.delhist))]: cur.execute("UPDATE SETTINGS SET setting=? WHERE field=?", (j, i, )) def applyopt(self): self.loadsettings() self.setfontsize(int(self.fontsize)) if str(self.bkmdock) == "False" or str(self.histdock) == "False": self.setdocks() def removedock(self, dock): self.removeDockWidget(dock) def adddock(self, dock): self.addDockWidget(Qt.RightDockWidgetArea, dock) def deleteallhist(self, i): if i == 0: pass elif i == 2: self.histli.clear() self.histlis = [0] cur.execute("delete from HISTORY") QMessageBox.information(self, self.windowTitle(), "All the History Records are deleted. . .") def setfontsize(self, i): if i >= 8 or i <= 24: font = QFont() font.setPixelSize(i) self.comboBox.setFont(font) self.searchbtn.setFont(font) self.bkmli.setFont(font) self.histli.setFont(font) self.listview.setFont(font) self.tamtext.setFont(font) def helpf(self): form = helpform.HelpForm("index.html", self) form.show() def closeEvent(self, *args, **kwargs): self.writehistlis(self.histlis) self.writebkmlis(self.bkmlistfromfile) for i, j in [("fontsize", int(self.fontsize)),("clipauto", str(self.clipauto)),("histdock", str(self.histdock)), ("bkmdock", str(self.bkmdock)),("delhist", str(self.delhist))]: cur.execute("UPDATE SETTINGS SET setting=? WHERE field=?", (j, i, )) con.commit() con.close() def fplusf(self): self.fontsize += 1 if self.fontsize <= 24: self.setfontsize(self.fontsize) def fminusf(self): self.fontsize -= 1 if self.fontsize >= 10: self.setfontsize(self.fontsize) def prevf(self): pr = self.histlis[0] - 1 if pr > 1: self.comboBox.setText(self.histlis[pr]) self.setevent() self.histlis[0] = pr self.go_next.setEnabled(True) elif pr == 1: self.comboBox.setText(self.histlis[pr]) self.setevent() self.histlis[0] = pr self.go_next.setEnabled(True) self.go_prev.setEnabled(False) else: pass def nextf(self): pr = self.histlis[0] + 1 if pr < len(self.histlis) - 1: self.comboBox.setText(self.histlis[pr]) self.setevent() self.histlis[0] = pr self.go_prev.setEnabled(True) elif pr == len(self.histlis) - 1: self.comboBox.setText(self.histlis[pr]) self.setevent() self.histlis[0] = pr self.go_prev.setEnabled(True) self.go_next.setEnabled(False) else: pass def randf(self): import random n = random.randrange(190538) cur.execute("select ENGW from ENGTAM where rowid = ?", (n, )) cuf = cur.fetchone() self.comboBox.setText(cuf[0]) self.setevent() def addfavf(self): txt = self.comboBox.text() if len(txt) != 0: self.addtobkmli(txt, self.bkmlistfromfile) self.writetolistwidget(self.bkmlistfromfile, self.bkmli) def sortit(self): self.bkmlistfromfile.sort() self.writetolistwidget(self.bkmlistfromfile, self.form.listWidget) self.writetolistwidget(self.bkmlistfromfile, self.bkmli) cur.execute("delete from BOOKMARKS") def writetolistwidget(self, lis, liswid): liswid.clear() for i in lis: liswid.addItem(i) def deletecurrentbkm(self): ct = self.form.listWidget.currentItem().text() self.bkmlistfromfile.remove(ct) self.writetolistwidget(self.bkmlistfromfile, self.bkmli) self.writetolistwidget(self.bkmlistfromfile, self.form.listWidget) cur.execute("delete from BOOKMARKS") def deleteallbkm(self): self.form.listWidget.clear() self.bkmli.clear() self.bkmlistfromfile = [] cur.execute("delete from BOOKMARKS") def viewbkmf(self): self.form = managebkm(self) self.writetolistwidget(self.bkmlistfromfile, self.form.listWidget) self.form.show() self.connect(self.form.closebtn, SIGNAL("clicked()"), self.form.close) self.connect(self.form.sortbtn, SIGNAL("clicked()"), self.sortit) self.connect(self.form.deletebtn, SIGNAL("clicked()"), self.deletecurrentbkm) self.connect(self.form.deleteallbtn, SIGNAL("clicked()"), self.deleteallbkm) def aboutf(self): QMessageBox.about(self, "About Nigandu English to Tamil Dictionary", """<b>Nigandu English to Tamil Dictionary</b> v %s <p>This is the first corss-platform English to Tamil bilingual dictionary; Free to use.</p> <p>Copyright © 2014 NJN Private Ltd. All rights reserved.</p> <p>Thanks to Python and PySide Project.</p> <p>Using Python 3.3, Qt 4.8 and PySide 1.2.1</p>""" % (__version__)) def visitblogf(self): webbrowser.open("http://www.e-nool.blogspot.com")
class CommandBox(QtGui.QPlainTextEdit, object): newCommand = QtCore.Signal(str) def reset_history(self): self.history_index = len(self.history) def __init__(self, history, commands, prefix): self.prefix = prefix self.history_index = 0 self.history = history self.reset_history() super(CommandBox, self).__init__() # Autocompleter self.completer = QCompleter([prefix + name for name in commands], self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWidget(self) self.completer.activated.connect(self.onAutoComplete) self.autocompleteStart = None def onAutoComplete(self, text): # Select the text from autocompleteStart until the current cursor cursor = self.textCursor() cursor.setPosition(0, cursor.KeepAnchor) # Replace it with the selected text cursor.insertText(text) self.autocompleteStart = None # noinspection PyStringFormat def keyPressEvent(self, *args, **kwargs): event = args[0] key = event.key() ctrl = event.modifiers() == QtCore.Qt.ControlModifier # don't disturb the completer behavior if self.completer.popup().isVisible() and key in ( Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab, Qt.Key_Backtab): event.ignore() return if self.autocompleteStart is not None and not event.text().isalnum() and \ not (key == Qt.Key_Backspace and self.textCursor().position() > self.autocompleteStart): self.completer.popup().hide() self.autocompleteStart = None if key == Qt.Key_Space and ctrl: # Pop-up the autocompleteList rect = self.cursorRect(self.textCursor()) rect.setSize(QtCore.QSize(100, 150)) self.autocompleteStart = self.textCursor().position() self.completer.complete( rect) # The popup is positioned in the next if block if self.autocompleteStart: prefix = self.toPlainText() cur = self.textCursor() cur.setPosition(self.autocompleteStart) self.completer.setCompletionPrefix(prefix) # Select the first one of the matches self.completer.popup().setCurrentIndex( self.completer.completionModel().index(0, 0)) if key == Qt.Key_Up and ctrl: if self.history_index > 0: self.history_index -= 1 self.setPlainText(BOT_PREFIX + '%s %s' % self.history[self.history_index]) key.ignore() return elif key == Qt.Key_Down and ctrl: if self.history_index < len(self.history) - 1: self.history_index += 1 self.setPlainText(BOT_PREFIX + '%s %s' % self.history[self.history_index]) key.ignore() return elif key == QtCore.Qt.Key_Return and ctrl: self.newCommand.emit(self.toPlainText()) self.reset_history() super(CommandBox, self).keyPressEvent(*args, **kwargs)
class CommandBox(QtGui.QPlainTextEdit, object): newCommand = QtCore.Signal(str) def reset_history(self): self.history_index = len(self.history) def __init__(self, history, commands): self.history_index = 0 self.history = history self.reset_history() super(CommandBox, self).__init__() #Autocompleter self.completer = QCompleter([BOT_PREFIX + name for name in commands], self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWidget(self) self.completer.activated.connect(self.onAutoComplete) self.autocompleteStart = None def onAutoComplete(self, text): #Select the text from autocompleteStart until the current cursor cursor = self.textCursor() cursor.setPosition(0, cursor.KeepAnchor) #Replace it with the selected text cursor.insertText(text) self.autocompleteStart = None #noinspection PyStringFormat def keyPressEvent(self, *args, **kwargs): event = args[0] key = event.key() ctrl = event.modifiers() == QtCore.Qt.ControlModifier # don't disturb the completer behavior if self.completer.popup().isVisible() and key in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab, Qt.Key_Backtab): event.ignore() return if self.autocompleteStart is not None and not event.text().isalnum() and \ not (key == Qt.Key_Backspace and self.textCursor().position() > self.autocompleteStart): self.completer.popup().hide() self.autocompleteStart = None if key == Qt.Key_Space and ctrl: #Pop-up the autocompleteList rect = self.cursorRect(self.textCursor()) rect.setSize(QtCore.QSize(100, 150)) self.autocompleteStart = self.textCursor().position() self.completer.complete(rect) # The popup is positioned in the next if block if self.autocompleteStart: prefix = self.toPlainText() cur = self.textCursor() cur.setPosition(self.autocompleteStart) self.completer.setCompletionPrefix(prefix) #Select the first one of the matches self.completer.popup().setCurrentIndex(self.completer.completionModel().index(0, 0)) if key == Qt.Key_Up and ctrl: if self.history_index > 0: self.history_index -= 1 self.setPlainText(BOT_PREFIX + '%s %s' % self.history[self.history_index]) key.ignore() return elif key == Qt.Key_Down and ctrl: if self.history_index < len(self.history) - 1: self.history_index += 1 self.setPlainText(BOT_PREFIX + '%s %s' % self.history[self.history_index]) key.ignore() return elif key == QtCore.Qt.Key_Return and ctrl: self.newCommand.emit(self.toPlainText()) self.reset_history() super(CommandBox, self).keyPressEvent(*args, **kwargs)
def __init__(self, model, index, parent=None): super(ObservationDialog, self).__init__(parent) self.logger = Logger('root.observationDialog') self.logger.debug('Debug set to: %s' % str(parent.logger.debugging)) self.setupUi(self) # self.dateTimeEdit.setDateTime(QDateTime.currentDateTime()) # An observation model is passed to the constructor as a parameter self.model = model # Build a QCompleter that is based on a species model's species name. # This way user can start typing the name in a line edit and the # completion will suggest suitable species names based on the model # TODO: language for the species name completion needs to be handled # TODO: both completers have model column indexes hard coded in, thus # they will break if the model is modified sppCompleter = QCompleter(self) sppCompleter.setModel(self.model.data_model) sppCompleter.setCompletionColumn(4) sppCompleter.setCompletionMode(QCompleter.InlineCompletion) sppCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.sppLineEdit.setCompleter(sppCompleter) # Build a QCompleter that is based on a species model's abbreviation. # This way user can start typing the abbreviation in a line edit and the # completion will suggest suitable species names based on the model abbrCompleter = QCompleter(self) abbrCompleter.setModel(self.model.data_model) abbrCompleter.setCompletionColumn(1) abbrCompleter.setCompletionMode(QCompleter.InlineCompletion) self.abbrLineEdit.setCompleter(abbrCompleter) # The underlying (observation) model is automatically updated through # a QDataWidgetMapper self.mapper = QDataWidgetMapper(self) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.setModel(model) # ID is mapped to a disabled dummy label in order to include it in the # WidgetMapper --> not very elegant self.mapper.addMapping(self.idLineEdit, model.ID) self.mapper.addMapping(self.sppLineEdit, model.SPECIES) self.mapper.addMapping(self.abbrLineEdit, model.ABBR) self.mapper.addMapping(self.countSpinBox, model.COUNT) self.mapper.addMapping(self.dateTimeEdit, model.TIME) self.mapper.addMapping(self.locLineEdit, model.LOCATION) self.mapper.addMapping(self.notesTextEdit, model.NOTES) self.mapper.setCurrentModelIndex(index) self.firstButton.clicked.connect( lambda: self.saveRecord(ObservationDialog.FIRST)) self.prevButton.clicked.connect( lambda: self.saveRecord(ObservationDialog.PREV)) self.nextButton.clicked.connect( lambda: self.saveRecord(ObservationDialog.NEXT)) self.lastButton.clicked.connect( lambda: self.saveRecord(ObservationDialog.LAST)) self.saveButton.clicked.connect( lambda: self.saveRecord(ObservationDialog.CURRENT)) self.closeButton.clicked.connect(self.reject) self.sppLineEdit.editingFinished.connect(self.update_fields)
class CodeCompletionMode(Mode): """ This mode provides code completion to the CodeEdit widget. The list of suggestion is supplied by a CodeCompletionModel. Code completion may use more than one completion model. The suggestions list is then filled model per model by beginning by the highest priority as long as the number of suggestions is lower than :attr:`pcef.modes.code_completion.CodeCompletion.minSuggestions`. For example, a python editor will use a smart completion model with a high priority and use the DocumentWordsCompletion model as a fallback system when the smart model fails to provide enough suggestions. The mode uses a QCompleter to provides display the list of suggestions. Code completion is triggered using ctrl+space or when there is at least three characters in the word being typed. """ #: Mode identifier IDENTIFIER = "Code completion" #: Mode description DESCRIPTION = "Provides code completion though completion models" def __init__(self): super(CodeCompletionMode, self).__init__( self.IDENTIFIER, self.DESCRIPTION) self.thread_pool = QThreadPool() self.thread_pool.setMaxThreadCount(2) self.__cached_request = None self.__active_thread_count = 0 self.__updating_models = False self.__timer = QTimer() #: Defines the min number of suggestions. This is used to know we should # avoid using lower priority models. # If there is at least minSuggestions in the suggestions list, we won't # use other completion model. self.minSuggestions = 50 #: Trigger key (automatically associated with the control modifier) self.triggerKey = Qt.Key_Space #: Number of chars needed to trigger the code completion self.nbTriggerChars = 1 #: Tells if the completion should be triggered automatically (when # len(wordUnderCursor) > nbTriggerChars ) # Default is True. Turning this option off might enhance performances # and usability self.autoTrigger = True self.periodIsTrigger = True #: Show/Hide current suggestion tooltip self.displayTooltips = True self.__caseSensitivity = Qt.CaseSensitive #: The internal QCompleter self.__completer = QCompleter() # self.__completer.activated.connect(self._insertCompletion) self.__completer.highlighted.connect(self._onHighlighted) self.__completer.activated.connect(self._insertCompletion) self.__prev_txt_len = 0 #: List of completion models self._models = [] self.__tooltips = {} def __del__(self): self.__completer.setWidget(None) self.__completer = None def addModel(self, model): """ Adds a completion model to the completion models list. :param model: CompletionModel to add """ self._models.append(model) self._models = sorted(self._models, key=lambda mdl: mdl.priority, reverse=True) def install(self, editor): """ Setup the completer with the CodeEdit. :param editor: CodeEditorWidget instance """ super(CodeCompletionMode, self).install(editor) self.__completer.setWidget(editor.codeEdit) self.__completer.setCaseSensitivity(self.__caseSensitivity) self.__completer.setCompletionMode(QCompleter.PopupCompletion) def __set_case(self, case): if case != self.__caseSensitivity: self.__caseSensitivity = case self.__completer.setCaseSensitivity(case) def __get_case(self): return self.__caseSensitivity #: The completion case sensitivity caseSensitivity = property(__get_case, __set_case) def _onStateChanged(self, state): """ Enables/Disables code completion. :param state: True to enable, False to disable """ if state: self.editor.codeEdit.keyPressed.connect(self._onKeyPressed) self.editor.codeEdit.postKeyPressed.connect(self._onKeyReleased) self.editor.codeEdit.focusedIn.connect(self._onFocusIn) self.__completer.highlighted.connect( self._displayHighlightedTooltip) else: self.editor.codeEdit.keyPressed.disconnect(self._onKeyPressed) self.editor.codeEdit.postKeyPressed.disconnect(self._onKeyReleased) self.editor.codeEdit.focusedIn.disconnect(self._onFocusIn) self.__completer.highlighted.disconnect( self._displayHighlightedTooltip) def _onFocusIn(self, event): """ Resets completer widget :param event: QFocusEvent """ self.__completer.setWidget(self.editor.codeEdit) def _onHighlighted(self, completion): """ Remembers the current completion when the hilighted signal is emitted. :param completion: Current completion """ self.currentCompletion = completion def _onKeyReleased(self, event): """ Handles the key released event to adapt completer prefix, run the cc library if necessary or prevent completer popup when removing text. :param event: :return: """ word = self._textUnderCursor() isShortcut = self._isShortcut(event) or event.key() == Qt.Key_Period tooShort = len(word) < self.nbTriggerChars # closes popup if completion prefix is empty and we are not removing # some text if (not self.__completer.popup().isVisible() and event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete) or\ (not isShortcut and event.modifiers() == 0 and ( word.isspace() or word == "")): self._hideCompletions() return # . is an auto-trigger if self.periodIsTrigger and \ (event.key() == Qt.Key_Period and self.autoTrigger): self._requestCompletion(completionPrefix=word, onlyAdapt=False) return # adapt completion prefix if self.__completer.popup().isVisible(): self._requestCompletion(completionPrefix=word, onlyAdapt=True) # run cc if word is long enough and auto trigger is on elif not tooShort and self.autoTrigger and event.text() != "" \ and (event.modifiers() == 0 or event.modifiers() & Qt.ShiftModifier): self._requestCompletion(completionPrefix=word, onlyAdapt=False) def _isShortcut(self, event): """ Checks if the event's key and modifiers make the completion shortcut. :param event: QKeyEvent :return: bool """ return ((event.modifiers() & Qt.ControlModifier > 0) and event.key() == self.triggerKey) def _onKeyPressed(self, event): """ Trigger the completion with ctrl+triggerKey and handle completion events ourselves (insert completion and hide completer) :param event: QKeyEvent """ isShortcut = self._isShortcut(event) completionPrefix = self._textUnderCursor() # handle completer popup events ourselves if self.__completer.popup().isVisible(): # complete if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return: self._insertCompletion(self.currentCompletion) self.__completer.popup().hide() event.stop = True return # hide elif event.key() == Qt.Key_Escape or event.key() == Qt.Key_Backtab: self.__completer.popup().hide() event.stop = True return # user completion request: update models and show completions if isShortcut: self._requestCompletion(completionPrefix, onlyAdapt=False) if event.key() == self.triggerKey: event.stop = True def selectWordUnderCursor(self): tc = self.editor.codeEdit.textCursor() original_pos = pos = tc.position() space_found = False how_many = 0 while not space_found and pos != 0: tc.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor, 1) tc.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 1) ch = tc.selectedText()[0] if tc.selectedText() in WORD_SEPARATORS or ch.isspace(): space_found = True how_many += 1 pos = tc.position() tc.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, 1) tc.setPosition(original_pos) tc.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, how_many) return tc def _textUnderCursor(self): """ Returns the word under the cursor """ tc = self.selectWordUnderCursor() selectedText = tc.selectedText() tokens = selectedText.split('.') wuc = tokens[len(tokens) - 1] if selectedText == ".": wuc = '.' return wuc def _lastCharOfLine(self): """ Returns the last char of the active line. :return: unicode """ tc = self.editor.codeEdit.textCursor() tc.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 1) return tc.selectedText() def _getCCRequest(self, completionPrefix): """ Creates a CompletionRequest from context (line nbr, ...) :param completionPrefix: the completion request prefix """ tc = self.editor.codeEdit.textCursor() line = tc.blockNumber() + 1 col = tc.columnNumber() fn = self.editor.codeEdit.tagFilename encoding = self.editor.codeEdit.tagEncoding source = self.editor.codeEdit.toPlainText() return CompletionRequest( col=col, encoding=encoding, filename=fn, line=line, source_code=source, completionPrefix=completionPrefix) def _execRequest(self, request): """ Executes a cc request and emit __completionResultsAvailable when the execution is done. :param request: The CodeCompletionRequest to execute. """ pass def _createCompleterModel(self, completionPrefix): """ Creates a QStandardModel that holds the suggestion from the completion models for the QCompleter :param completionPrefix: """ # build the completion model cc_model = QStandardItemModel() cptSuggestion = 0 displayedTexts = [] self.__tooltips.clear() for model in self._models: for s in model.suggestions: # skip redundant completion if s.display != completionPrefix and \ not s.display in displayedTexts: displayedTexts.append(s.display) items = [] item = QStandardItem() items.append(item) item.setData(s.display, Qt.DisplayRole) if s.description is not None: self.__tooltips[s.display] = s.description if s.decoration is not None: item.setData(QIcon(s.decoration), Qt.DecorationRole) cc_model.appendRow(items) cptSuggestion += 1 # do we need to use more completion model? if cptSuggestion >= self.minSuggestions: break # enough suggestions return cc_model, cptSuggestion def _showCompletions(self, completionPrefix): """ Shows the completion popup :param completionPrefix: completion prefix use to set the popup pos """ c = self.__completer c.setCompletionPrefix(completionPrefix) c.popup().setCurrentIndex( self.__completer.completionModel().index(0, 0)) cr = self.editor.codeEdit.cursorRect() charWidth = self.editor.codeEdit.fm.width('A') cr.setX(cr.x() - len(completionPrefix) * charWidth) cr.setWidth(400) c.complete(cr) # popup it up! self._displayHighlightedTooltip(c.currentCompletion()) def _hideCompletions(self): """ Hides the completion popup """ self.__completer.popup().hide() QToolTip.hideText() def _requestCompletion(self, completionPrefix, onlyAdapt=False): """ Requests a code completion. The request will be transmitted to the background thread and treated by the __applyRequestResults slot when __completionResultsAvailable is emitted. :param completionPrefix: :param onlyAdapt: :return: """ # cancel prev running request if not onlyAdapt: request = self._getCCRequest(completionPrefix) else: request = CompletionRequest(completionPrefix=completionPrefix, onlyAdapt=True) # only one at a time if self.__active_thread_count == 0: if self.__cached_request: self.__cached_request, request = request, self.__cached_request self.__active_thread_count += 1 runnable = RunnableCompleter(self._models, request) runnable.connect(self._applyRequestResults) self.thread_pool.start(runnable) # cache last request else: self.__cached_request = request def _applyRequestResults(self, request): """ Updates the completer model and show the popup """ self.__active_thread_count -= 1 # is the request still up to date ? if request.completionPrefix == self._textUnderCursor(): if not request.onlyAdapt: # update completion model and show completer cc_model, cptSuggestion = self._createCompleterModel( request.completionPrefix) if cptSuggestion > 1: self.__completer.setModel(cc_model) self.__cc_model = cc_model self._showCompletions(request.completionPrefix) else: self._hideCompletions() else: # only adapt completion prefix, the completer is already visible self.__completer.setCompletionPrefix(request.completionPrefix) idx = self.__completer.completionModel().index(0, 0) self.__completer.popup().setCurrentIndex(idx) if self.__completer.currentCompletion() == "" or \ self.__completer.currentCompletion() == \ request.completionPrefix: self._hideCompletions() # do we have any cached requests? if self.__cached_request and self.__active_thread_count == 0: self.__active_thread_count += 1 # prevent normal start immediately self.__timer.singleShot(10, self.__start_cached_request) def __start_cached_request(self): request = self.__cached_request self.__cached_request = None runnable = RunnableCompleter(self._models, request) runnable.connect(self._applyRequestResults) self.thread_pool.start(runnable) @Slot(unicode) def _displayHighlightedTooltip(self, txt): """ Shows/hides current suggestion tooltip next to the completer popup :param txt: :return: """ if not self.displayTooltips or not txt in self.__tooltips: QToolTip.hideText() return tooltip = self.__tooltips[txt] charWidth = self.editor.codeEdit.fm.width('A') # show tooltip pos = self.__completer.popup().pos() pos.setX(pos.x() + 400) pos.setY(pos.y() - 15) QToolTip.showText(pos, tooltip, self.editor.codeEdit) def _insertCompletion(self, completion): """ Inserts the completion (replace the word under cursor) :param completion: the completion text to insert """ offset = 0 if len(self._textUnderCursor()) > 1: offset = 1 tc = self.selectWordUnderCursor() tc.insertText(completion) self.editor.codeEdit.setTextCursor(tc)
class TextEditor(RWWidget, Ui_Form): """ Contains many features of popular text editors adapted for use with Ontologies such as syntax highlighting, and autocompletion. One column on the left of the text editor contains line numbers and another contains other contextual information such as whether a block of code has been hidden/collapsed and can be displayed/expanded later. It also contains an incremental search and an interface to pySUMO's settings so font size and family can be changed at will. Variables: - syntax_highlighter: The syntax highlighter object for the text editor. Methods: - __init__: Initalizes the Object and the QPlainTextEdit - commit: Notifies other Widgets of changes. - show_autocomplete: Returns autocompletion choices. - getWidget: returns the QPlainTextEdit - numberbarPaint: Paints the numberbar - searchCompletion: Asks QCompleter if a whole word exists starting with user input - hideFrom: Starts hides all lines from the ()-block started by line - insertCompletion: Puts the selected Completion into the TextEditor """ def __init__(self, mainwindow, settings=None): """ Initializes the text editor widget. """ super(TextEditor, self).__init__(mainwindow) self.setupUi(self.mw) self.plainTextEdit.clear() self.plainTextEdit.setEnabled(False) self.plainTextEdit.show() self.highlighter = SyntaxHighlighter(self.plainTextEdit.document(), settings) self.initAutocomplete() self._initNumberBar() self.hidden = {} self.printer = QPrinter(QPrinterInfo.defaultPrinter()) self.plainTextEdit.setTextCursor( self.plainTextEdit.cursorForPosition(QPoint(0, 0))) self.canUndo = False self.canRedo = False self.ontologySelector.setCurrentIndex(-1) self.timer = QTimer(self) self.timer.setSingleShot(True) self.timer.timeout.connect(self.commit) #Connects self.getWidget().textChanged.connect(self.searchCompletion) self.plainTextEdit.undoAvailable.connect(self.setCanUndo) self.plainTextEdit.redoAvailable.connect(self.setCanRedo) self.ontologySelector.currentIndexChanged[int].connect( self.showOtherOntology) self.plainTextEdit.textChanged.connect(self.expandIfBracketRemoved) self.plainTextEdit.textChanged.connect(self.setTextChanged) self._updateOntologySelector() #must be after connects @Slot() def setTextChanged(self): """Is called if the text changed signal is thrown and sets a timer of 3 seconds to reparse the ontology. """ self.timer.stop() self.timer.start(3000) def setCanUndo(self, b): self.canUndo = b def setCanRedo(self, b): self.canRedo = b def _print_(self): """ Creates a print dialog with the latest text""" dialog = QPrintDialog() if dialog.exec_() == QDialog.Accepted: doc = self.plainTextEdit.document() doc.print_(dialog.printer()) def _quickPrint_(self): """ No dialog, just print""" if self.printer is None: return doc = self.plainTextEdit.document() doc.print_(self.printer) def _printPreview_(self): """ Create a print preview""" dialog = QPrintPreviewDialog() dialog.paintRequested.connect(self.plainTextEdit.print_) dialog.exec_() def saveOntology(self): """ Save the ontology to disk""" idx = self.ontologySelector.currentIndex() ontology = self.ontologySelector.itemData(idx) if ontology is None: return if type(ontology) is Ontology: ontology.save() def getActiveOntology(self): idx = self.ontologySelector.currentIndex() return self.ontologySelector.itemData(idx) def undo(self): if self.canUndo: self.plainTextEdit.undo() try: self.SyntaxController.add_ontology( self.getActiveOntology(), self.plainTextEdit.toPlainText()) except ParseError: return self.commit() else: super(TextEditor, self).undo() def redo(self): if self.canRedo: self.plainTextEdit.redo() try: self.SyntaxController.add_ontology( self.getActiveOntology(), self.plainTextEdit.toPlainText()) except ParseError: return self.commit() else: super(TextEditor, self).redo() def _initNumberBar(self): """ Init the number bar""" self.number_bar = NumberBar(self) self.number_bar.setMinimumSize(QSize(30, 0)) self.number_bar.setObjectName("number_bar") self.gridLayout.addWidget(self.number_bar, 1, 0, 1, 1) self.plainTextEdit.blockCountChanged.connect( self.number_bar.adjustWidth) self.plainTextEdit.updateRequest.connect( self.number_bar.updateContents) @Slot(int) def jumpToLocation(self, location, ontology): if ontology == str(self.getActiveOntology()): textBlock = self.plainTextEdit.document().findBlockByNumber( location) pos = textBlock.position() textCursor = self.plainTextEdit.textCursor() textCursor.setPosition(pos) self.plainTextEdit.setTextCursor(textCursor) self.plainTextEdit.centerCursor() def _updateOntologySelector(self): """ Update the ontology selector where you can select which Ontology to show in the editor""" current = self.ontologySelector.currentText() self.ontologySelector.currentIndexChanged[int].disconnect( self.showOtherOntology) self.ontologySelector.clear() index = -1 count = 0 for i in self.getIndexAbstractor().ontologies: if current == i.name: index = count self.ontologySelector.addItem(i.name, i) count = count + 1 self.ontologySelector.setCurrentIndex(index) # if index == -1 : # the ontology was removed. # self.showOtherOntology(index) if index == -1: self.plainTextEdit.setEnabled(False) self.plainTextEdit.clear() self.ontologySelector.currentIndexChanged[int].connect( self.showOtherOntology) def setActiveOntology(self, ontology): index = -1 count = 0 for i in self.getIndexAbstractor().ontologies: if ontology.name == i.name: index = count break count = count + 1 self.ontologySelector.setCurrentIndex(index) @Slot(int) def showOtherOntology(self, idx): """ Show other ontology in the plaintextedit Arguments: - idx: The id of the current Ontologyselector """ dced = False try: self.plainTextEdit.textChanged.disconnect(self.setTextChanged) except RuntimeError: dced = True idx = self.ontologySelector.currentIndex() if idx == -1: self.plainTextEdit.setEnabled(False) self.plainTextEdit.clear() return ontologyname = self.ontologySelector.currentText() for i in self.getIndexAbstractor().ontologies: if i.name == ontologyname: self.plainTextEdit.setEnabled(True) self.getWidget().setPlainText( self.getIndexAbstractor().get_ontology_file(i).getvalue()) if not dced: self.plainTextEdit.textChanged.connect(self.setTextChanged) return self.plainTextEdit.textChanged.connect(self.commit) assert False @Slot() def expandIfBracketRemoved(self): """ Check if a line with ( or ) was changed and expand the possible hidden lines """ current_line = self.getWidget().document().findBlock( self.getWidget().textCursor().position()).blockNumber() + 1 if current_line in self.hidden: self.toggleVisibility(current_line) @Slot() def zoomIn(self): """ Increase the size of the font in the TextEditor """ doc = self.getWidget().document() font = doc.defaultFont() font.setPointSize(font.pointSize() + 1) font = QFont(font) doc.setDefaultFont(font) @Slot() def zoomOut(self): """ Decrease the size of the font in the TextEditor""" doc = self.getWidget().document() font = doc.defaultFont() font.setPointSize(font.pointSize() - 1) font = QFont(font) doc.setDefaultFont(font) @Slot() def expandAll(self): """ Expands all hidden code blocks""" for see in list(self.hidden.keys()): self.toggleVisibility(see) @Slot() def collapseAll(self): """ Collapse all code blocks (where possible)""" block = self.getWidget().document().firstBlock() while block.isValid(): if block.isVisible(): if block.text().count("(") > block.text().count(")"): self.toggleVisibility(block.blockNumber() + 1) block = block.next() def _hideLines(self, lines): for line in lines: if line == 0: continue block = self.getWidget().document().findBlockByNumber(line - 1) assert block.isVisible() block.setVisible(False) assert not block.isVisible(), "Problem with line %r" % (line) def _showLines(self, lines): """ Show the lines not visible starting by lines Arguments: - lines: The first line followed by an unvisible block """ for line in lines: block = self.getWidget().document().findBlockByNumber(line - 1) block.setVisible(True) def getLayoutWidget(self): """ Returns the layout widget""" return self.widget def numberbarPaint(self, number_bar, event): """Paints the line numbers of the code file""" self.number_bar.link = [] font_metrics = self.getWidget().fontMetrics() current_line = self.getWidget().document().findBlock( self.getWidget().textCursor().position()).blockNumber() + 1 block = self.getWidget().firstVisibleBlock() line_count = block.blockNumber() painter = QPainter(self.number_bar) # TODO: second argument is color -> to settings painter.fillRect(self.number_bar.rect(), self.getWidget().palette().base()) # Iterate over all visible text blocks in the document. while block.isValid(): line_count += 1 text = str(line_count) block_top = self.getWidget().blockBoundingGeometry( block).translated(self.getWidget().contentOffset()).top() if not block.isVisible(): block = block.next() while not block.isVisible(): line_count += 1 block = block.next() continue self.number_bar.link.append((block_top, line_count)) # Check if the position of the block is out side of the visible # area. if block_top >= event.rect().bottom(): break # We want the line number for the selected line to be bold. if line_count == current_line: font = painter.font() font.setBold(True) else: font = painter.font() font.setBold(False) # line opens a block if line_count in self.hidden: text += "+" font.setUnderline(True) elif block.text().count("(") > block.text().count(")"): text += "-" font.setUnderline(True) else: font.setUnderline(False) painter.setFont(font) # Draw the line number right justified at the position of the # line. paint_rect = QRect(0, block_top, self.number_bar.width(), font_metrics.height()) painter.drawText(paint_rect, Qt.AlignLeft, text) block = block.next() painter.end() def initAutocomplete(self): """Inits the QCompleter and gives him a list of words""" self.completer = QCompleter( list( OrderedDict.fromkeys( re.split("\\W", self.plainTextEdit.toPlainText())))) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWidget(self.getWidget()) self.completer.activated.connect(self.insertCompletion) def searchCompletion(self): """Searches for possible completion from QCompleter to the current text position""" tc = self.getWidget().textCursor() tc.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) if tc.selectedText() in string.whitespace: self.completer.popup().hide() return tc.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) beginning = tc.selectedText() if len(beginning) >= 3: self.completer.setCompletionPrefix(beginning) self.completer.complete() shortcut = QShortcut(QKeySequence("Ctrl+Enter"), self.getWidget(), self.insertCompletion) def toggleVisibility(self, line): """ Shows or hides a line """ if line in self.hidden: self._showLines(self.hidden[line]) del self.hidden[line] else: self.hideFrom(line) # update views self.getWidget().hide() self.getWidget().show() self.number_bar.update() def hideFrom(self, line): """ Hides a block starting by line. Do nothing if not hidable""" block = self.getWidget().document().findBlockByNumber(line - 1) openB = block.text().count("(") closeB = block.text().count(")") startline = line # go to line >= line: block starts counting by 0 block = self.getWidget().document().findBlockByNumber(line - 1) hidden = [] assert block.isValid() while openB > closeB and block.isValid(): assert block.isValid() block = block.next() line = block.blockNumber() + 1 if block.isVisible(): hidden.append(line) openB += block.text().count("(") closeB += block.text().count(")") if hidden == []: return self._hideLines(hidden) self.hidden[startline] = hidden # set current line in viewable area current_line = self.getWidget().document().findBlock( self.getWidget().textCursor().position()).blockNumber() + 1 if (startline < current_line and current_line <= line): block = block.next() cursor = QTextCursor(block) self.getWidget().setTextCursor(cursor) @Slot(str) def insertCompletion(self, completion): """ Adds the completion to current text""" tc = self.getWidget().textCursor() tc.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) tc.removeSelectedText() tc.insertText(completion) def getWidget(self): """ Return the QPlainTextEdit Widget""" return self.plainTextEdit @Slot() def commit(self): """ Overrides commit from RWWidget. """ idx = self.ontologySelector.currentIndex() if idx == -1: return ontology = self.ontologySelector.itemData(idx) if ontology is None: return try: QApplication.setOverrideCursor(Qt.BusyCursor) self.SyntaxController.add_ontology( ontology, self.plainTextEdit.toPlainText()) QApplication.setOverrideCursor(Qt.ArrowCursor) except ParseError: return super(TextEditor, self).commit() @Slot() def refresh(self): """ Refreshes the content of the TextEditor (syncing with other widgets)""" textCursorPos = self.plainTextEdit.textCursor().position() super(TextEditor, self).refresh() dced = False try: self.plainTextEdit.textChanged.disconnect(self.setTextChanged) except RuntimeError: dced = True idx = self.ontologySelector.currentIndex() ontology = self.ontologySelector.itemData(idx) if ontology in self.IA.ontologies: f = self.IA.get_ontology_file(ontology) self.plainTextEdit.setPlainText(f.getvalue()) if not dced: self.plainTextEdit.textChanged.connect(self.setTextChanged) cursor = self.plainTextEdit.textCursor() cursor.setPosition(textCursorPos) self.plainTextEdit.setTextCursor(cursor) self.plainTextEdit.centerCursor()