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
    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
示例#3
0
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)
示例#5
0
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 createEditor(self, parent, option, index):
     """ Should return a LineEdit with all the Category Names as AutoComplete values """
     edit = QLineEdit(parent)
     completer = QCompleter()
     edit.setCompleter(completer) 
     model = QStringListModel()
     completer.setModel(model)
     self.setCompleterData(model)
     return edit
示例#7
0
文件: util.py 项目: raulvc/seareiros
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)
示例#8
0
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()
示例#9
0
class TagEdit(object):
    """Abstraction for tag edit"""

    def __init__(self, parent, widget, on_change):
        """Init and connect signals"""
        self.parent = parent
        self.app = QApplication.instance()
        self.widget = widget
        self.tags_list = map(lambda tag:
            Tag.from_tuple(tag).name,
            self.app.provider.list_tags(),
        )
        self.completer = QCompleter()
        self.completer_model = QStringListModel()
        self.completer.setModel(self.completer_model)
        self.completer.activated.connect(self.update_completion)
        self.update_completion()
        self.widget.setCompleter(self.completer)
        self.widget.textChanged.connect(Slot()(on_change))
        self.widget.textEdited.connect(self.update_completion)

    @property
    def tags(self):
        """Get tags"""
        # Split on comma and Arabic comma
        # 0x060c is the Arabic comma
        return map(lambda tag: tag.strip(),
            re.split(u',|\u060c', self.widget.text()))

    @tags.setter
    def tags(self, val):
        """Set tags"""
        self.widget.setText(', '.join(val))

    @Slot()
    def update_completion(self):
        """Update completion model with exist tags"""
        orig_text = self.widget.text()
        text = ', '.join(orig_text.replace(', ', ',').split(',')[:-1])
        tags = []
        for tag in self.tags_list:
            if ',' in orig_text:
                if orig_text[-1] not in (',', ' '):
                    tags.append('%s,%s' % (text, tag))
                tags.append('%s, %s' % (text, tag))
            else:
                tags.append(tag)
        if tags != self.completer_model.stringList():
            self.completer_model.setStringList(tags)
示例#10
0
    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)
示例#11
0
class TagEdit(object):
    """Abstraction for tag edit"""
    def __init__(self, parent, widget, on_change):
        """Init and connect signals"""
        self.parent = parent
        self.app = QApplication.instance()
        self.widget = widget
        self.tags_list = map(
            lambda tag: Tag.from_tuple(tag).name,
            self.app.provider.list_tags(),
        )
        self.completer = QCompleter()
        self.completer_model = QStringListModel()
        self.completer.setModel(self.completer_model)
        self.completer.activated.connect(self.update_completion)
        self.update_completion()
        self.widget.setCompleter(self.completer)
        self.widget.textChanged.connect(Slot()(on_change))
        self.widget.textEdited.connect(self.update_completion)

    @property
    def tags(self):
        """Get tags"""
        # Split on comma and Arabic comma
        # 0x060c is the Arabic comma
        return map(lambda tag: tag.strip(),
                   re.split(u',|\u060c', self.widget.text()))

    @tags.setter
    def tags(self, val):
        """Set tags"""
        self.widget.setText(', '.join(val))

    @Slot()
    def update_completion(self):
        """Update completion model with exist tags"""
        orig_text = self.widget.text()
        text = ', '.join(orig_text.replace(', ', ',').split(',')[:-1])
        tags = []
        for tag in self.tags_list:
            if ',' in orig_text:
                if orig_text[-1] not in (',', ' '):
                    tags.append('%s,%s' % (text, tag))
                tags.append('%s, %s' % (text, tag))
            else:
                tags.append(tag)
        if tags != self.completer_model.stringList():
            self.completer_model.setStringList(tags)
示例#12
0
    def createEditor(self,parent,option,index):

        # Qt takes ownership of the editor
        # Therefore I have recreate it each time this method is called

        combo = QComboBox(parent)
        combo.setModel(self.model)

        completer = QCompleter(combo)
        completer.setModel(self.model)
        completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) # PopupCompletion)
        combo.setCompleter(completer)

        if option:
            # This is needed to put the combobox in the right place
            combo.setGeometry(option.rect)

        return combo
    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)
示例#14
0
class TagEdit(object):
    """Abstraction for tag edit"""

    def __init__(self, parent, app, widget, on_change):
        """Init and connect signals"""
        self.parent = parent
        self.app = app
        self.widget = widget
        self.tags_list = map(lambda tag: Tag.from_tuple(tag).name, self.app.provider.list_tags())
        self.completer = QCompleter()
        self.completer_model = QStringListModel()
        self.completer.setModel(self.completer_model)
        self.completer.activated.connect(self.update_completion)
        self.update_completion()
        self.widget.setCompleter(self.completer)
        self.widget.textChanged.connect(Slot()(on_change))
        self.widget.textEdited.connect(self.update_completion)

    @property
    def tags(self):
        """Get tags"""
        return map(lambda tag: tag.strip(), self.widget.text().split(","))

    @tags.setter
    def tags(self, val):
        """Set tags"""
        self.widget.setText(", ".join(val))

    @Slot()
    def update_completion(self):
        """Update completion model with exist tags"""
        orig_text = self.widget.text()
        text = ", ".join(orig_text.replace(", ", ",").split(",")[:-1])
        tags = []
        for tag in self.tags_list:
            if "," in orig_text:
                if orig_text[-1] not in (",", " "):
                    tags.append("%s,%s" % (text, tag))
                tags.append("%s, %s" % (text, tag))
            else:
                tags.append(tag)
        if tags != self.completer_model.stringList():
            self.completer_model.setStringList(tags)
示例#15
0
class ComboBoxWithTypingSearch(QComboBox):
    def __init__(self, parent=None):
        super(ComboBoxWithTypingSearch, self).__init__(parent)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        self.completer = QCompleter(self)

        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setPopup(self.view())
        self.setCompleter(self.completer)

        self.lineEdit().textEdited.connect(
            self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)

    def setModel(self, model):
        super(ComboBoxWithTypingSearch, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ComboBoxWithTypingSearch, self).setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
示例#16
0
class EditorCodeCompletion(QTextEdit):
    def __init__(self, path_dict):
        super(EditorCodeCompletion, self).__init__()  
        self.m_completer = QCompleter(self)
        self.m_completer.setWidget(self)
        words = []
        
        self.flag_open_angle_bracket = False
        self.tag_name = ""
        
        try:
            f = open(path_dict,"r")
            for word in f:
                words.append(word.strip())
            f.close()
        except IOError:
            print ("dictionary not in anticipated location")
       
        model = QStringListModel(words, self.m_completer)
        
        self.m_completer.setModel(model)
        self.m_completer.setCompletionMode(QCompleter.PopupCompletion)
        self.m_completer.activated.connect(self.insertCompletion)

    def insertCompletion (self, completion):
        cursor = self.textCursor()
        cursor.beginEditBlock()
        cursor.movePosition(QTextCursor.Left)
        cursor.movePosition(QTextCursor.EndOfWord)
        extra = len(self.m_completer.completionPrefix())
        cursor.insertText(completion[extra:])
        self.setTextCursor(cursor)
        cursor.endEditBlock()

    def __insertTag(self):
        '''
        inserts the corresponding closing tag to an opening xml tag
        '''
        self.find('<', QTextDocument.FindBackward)
        tc = self.textCursor()        
        tc.select(QTextCursor.WordUnderCursor)
        txt = '' if self.__stringHasBracket(tc.selectedText().replace(' ', '')) else tc.selectedText()
        txt = '</' + txt + '>'
        
        self.find('>')    
        tc = self.textCursor()
        tc.clearSelection()
        
        tc.insertText(txt) 
        tc.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor, len(txt))
        self.setTextCursor(tc)
    
    def __stringHasBracket(self, s):
        return '<' in s or '>' in s

    def __insertClosingTag(self, event):
        operation_sys = sys.platform 
        flag = "linux" in operation_sys        
        if flag :
            self.__insertClosingTag_Unix(event)
        else:
            self.__insertClosingTag_Win(event)
        
    def __insertClosingTag_Unix(self, event):
        '''
        inserts a closing tag after the closing bracket of open tag
        @param key: keyboard input value as int
        '''
        if self.flag_open_angle_bracket :
            if event.key() == 47 : # /
                print ("/")
                self.flag_open_angle_bracket = False 
            elif event.key() == 62  :  # >
                print (">")
                self.__insertTag()
                self.flag_open_angle_bracket = False  
        elif event.key() == 60  :  # <
            print ("<")
            self.flag_open_angle_bracket = True
 
    def __insertClosingTag_Win(self, event) :
        if self.flag_open_angle_bracket :
            if event.modifiers() & Qt.ShiftModifier :
                if event.key() == 55 : # /
                    print ("/")
                    self.flag_open_angle_bracket = False             
                elif event.key() == 60 : # > 
                    print (">")
                    self.__insertTag()
                    self.flag_open_angle_bracket = False  
        elif event.key() == 60  :  # <
            print ("<")
            self.flag_open_angle_bracket = True    
 
    def keyPressEvent(self, event):
        '''
        checks keyboard input to set closing tag or start code completion 
        '''        
        if self.m_completer.popup().isVisible() :
            if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return or event.key() == Qt.Key_Tab or event.key() == Qt.Key_Escape :
                event.ignore()
                return
        
        # open popup
        isShortcut = (event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_Space)                
                
        if not isShortcut:        
            super(EditorCodeCompletion, self).keyPressEvent(event)
            # ============================================================================================= 
            # begin tag inline insertion         
            self.__insertClosingTag(event)
            # end tag inline insertion 
            # ============================================================================================= 
        
        cursor = self.textCursor()
        cursor.select(QTextCursor.WordUnderCursor)        
        completionPrefix = cursor.selectedText()

        if completionPrefix != self.m_completer.completionPrefix() :
            self.m_completer.setCompletionPrefix(completionPrefix)
            self.m_completer.popup().setCurrentIndex(self.m_completer.completionModel().index(0, 0))

        # if not event.text() != "" and len(completionPrefix) > 2 :
        if len(completionPrefix) > 2 and isShortcut :
            print ("hier")
            cr = self.cursorRect()
            cr.setWidth(2 * (self.m_completer.popup().sizeHintForColumn(0)
                         + self.m_completer.popup().verticalScrollBar().sizeHint().width()))

            self.m_completer.complete(cr)  # # popup it up!
示例#17
0
文件: cc.py 项目: hofoen/pcef-core
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)
示例#18
0
class RobocompDslGui(QMainWindow):
    def __init__(self, parent=None):
        super(RobocompDslGui, self).__init__(parent)
        self.setWindowTitle("Create new component")
        # self._idsl_paths = []
        self._communications = {
            "implements": [],
            "requires": [],
            "subscribesTo": [],
            "publishes": []
        }
        self._interfaces = {}
        self._cdsl_doc = CDSLDocument()
        self._command_process = QProcess()

        self._main_widget = QWidget()
        self._main_layout = QVBoxLayout()
        self.setCentralWidget(self._main_widget)

        self._name_layout = QHBoxLayout()
        self._name_line_edit = QLineEdit()
        self._name_line_edit.textEdited.connect(self.update_component_name)
        self._name_line_edit.setPlaceholderText("New component name")
        self._name_layout.addWidget(self._name_line_edit)
        self._name_layout.addStretch()

        # DIRECTORY SELECTION
        self._dir_line_edit = QLineEdit()
        # self._dir_line_edit.textEdited.connect(self.update_completer)
        self._dir_completer = QCompleter()
        self._dir_completer_model = QFileSystemModel()
        if os.path.isdir(ROBOCOMP_COMP_DIR):
            self._dir_line_edit.setText(ROBOCOMP_COMP_DIR)
            self._dir_completer_model.setRootPath(ROBOCOMP_COMP_DIR)
        self._dir_completer.setModel(self._dir_completer_model)
        self._dir_line_edit.setCompleter(self._dir_completer)

        self._dir_button = QPushButton("Select directory")
        self._dir_button.clicked.connect(self.set_output_directory)
        self._dir_layout = QHBoxLayout()
        self._dir_layout.addWidget(self._dir_line_edit)
        self._dir_layout.addWidget(self._dir_button)

        # LIST OF ROBOCOMP INTERFACES
        self._interface_list = QListWidget()
        self._interface_list.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self._interface_list.itemSelectionChanged.connect(
            self.set_comunication)

        # LIST OF CONNECTION TyPES
        self._type_combo_box = QComboBox()
        self._type_combo_box.addItems(
            ["publishes", "implements", "subscribesTo", "requires"])
        self._type_combo_box.currentIndexChanged.connect(
            self.reselect_existing)

        # BUTTON TO ADD A NEW CONNECTION
        # self._add_connection_button = QPushButton("Add")
        # self._add_connection_button.clicked.connect(self.add_new_comunication)
        self._add_connection_layout = QHBoxLayout()
        # self._add_connection_layout.addWidget(self._add_connection_button)
        self._language_combo_box = QComboBox()
        self._language_combo_box.addItems(["Python", "Cpp", "Cpp11"])
        self._language_combo_box.currentIndexChanged.connect(
            self.update_language)
        self._add_connection_layout.addWidget(self._language_combo_box)
        self._add_connection_layout.addStretch()
        self._gui_check_box = QCheckBox()
        self._gui_check_box.stateChanged.connect(self.update_gui_selection)
        self._gui_label = QLabel("Use Qt GUI")
        self._add_connection_layout.addWidget(self._gui_label)
        self._add_connection_layout.addWidget(self._gui_check_box)

        # WIDGET CONTAINING INTERFACES AND TYPES
        self._selection_layout = QVBoxLayout()
        self._selection_layout.addWidget(self._type_combo_box)
        self._selection_layout.addWidget(self._interface_list)
        self._selection_layout.addLayout(self._add_connection_layout)
        self._selection_widget = QWidget()
        self._selection_widget.setLayout(self._selection_layout)

        # TEXT EDITOR WITH THE RESULTING CDSL CODE
        self._editor = QTextEdit(self)
        self._editor.setHtml("")

        self._document = self._editor.document()
        self._component_directory = None

        # SPLITTER WITH THE SELECTION AND THE CODE
        self._body_splitter = QSplitter(Qt.Horizontal)
        self._body_splitter.addWidget(self._selection_widget)
        self._body_splitter.addWidget(self._editor)
        self._body_splitter.setStretchFactor(0, 2)
        self._body_splitter.setStretchFactor(1, 9)

        # CREATION BUTTONS
        self._create_button = QPushButton("Create .cdsl")
        self._create_button.clicked.connect(self.write_cdsl_file)
        self._creation_layout = QHBoxLayout()
        self._creation_layout.addStretch()
        self._creation_layout.addWidget(self._create_button)

        self._console = QConsole()
        self._command_process.readyReadStandardOutput.connect(
            self._console.standard_output)
        self._command_process.readyReadStandardError.connect(
            self._console.error_output)

        # ADDING WIDGETS TO MAIN LAYOUT
        self._main_widget.setLayout(self._main_layout)
        self._main_layout.addLayout(self._name_layout)
        self._main_layout.addLayout(self._dir_layout)
        self._main_layout.addWidget(self._body_splitter)
        self._main_layout.addLayout(self._creation_layout)
        self._main_layout.addWidget(self._console)
        self.setMinimumSize(800, 500)
        self._editor.setText(self._cdsl_doc.generate_doc())

    # self.editor->show();

    # def update_completer(self, path):
    # 	print "update_completer %s"%path
    # 	info = QFileInfo(path)
    # 	if info.exists() and info.isDir():
    # 			if not path.endswith(os.path.pathsep):
    # 				new_path = os.path.join(path, os.sep)
    # 				# self._dir_line_edit.setText(new_path)
    # 			all_dirs_output = [dI for dI in os.listdir(path) if os.path.isdir(os.path.join(path, dI))]
    # 			print all_dirs_output
    # 			self._dir_completer.complete()

    def load_idsl_files(self, fullpath=None):
        if fullpath is None:
            fullpath = ROBOCOMP_INTERFACES
        idsls_dir = os.path.join(ROBOCOMP_INTERFACES, "IDSLs")
        if os.path.isdir(idsls_dir):
            for full_filename in os.listdir(idsls_dir):
                file_name, file_extension = os.path.splitext(full_filename)
                if "idsl" in file_extension.lower():
                    full_idsl_path = os.path.join(idsls_dir, full_filename)
                    # self._idsl_paths.append(os.path.join(idsls_dir,full_filename))
                    self.parse_idsl_file(full_idsl_path)
        self._interface_list.addItems(self._interfaces.keys())

    def parse_idsl_file(self, fullpath):

        with open(fullpath, 'r') as fin:
            interface_name = None
            for line in fin:
                result = re.findall(r'^\s*interface\s+(\w+)\s*\{?\s*$',
                                    line,
                                    flags=re.MULTILINE)
                if len(result) > 0:
                    interface_name = result[0]
            print("%s for idsl %s" % (interface_name, fullpath))
            if interface_name is not None:
                self._interfaces[interface_name] = fullpath

    def add_new_comunication(self):
        interface_names = self._interface_list.selectedItems()
        com_type = str(self._type_combo_box.currentText())
        for iface_name_item in interface_names:
            iface_name = str(iface_name_item.text())
            self._communications[com_type].append(iface_name)
            idsl_full_path = self._interfaces[iface_name]
            idsl_full_filename = os.path.basename(idsl_full_path)
            self._cdsl_doc.add_comunication(com_type, iface_name)
            self._cdsl_doc.add_import(idsl_full_filename)
        self.update_editor()

    def set_comunication(self):
        interface_names = self._interface_list.selectedItems()
        com_type = str(self._type_combo_box.currentText())
        self._communications[com_type] = []
        self._cdsl_doc.clear_comunication(com_type)
        for iface_name_item in interface_names:
            iface_name = str(iface_name_item.text())
            self._communications[com_type].append(iface_name)
            self._cdsl_doc.add_comunication(com_type, iface_name)
        self.update_imports()
        self.update_editor()

    def update_imports(self):
        self._cdsl_doc.clear_imports()
        for com_type in self._communications:
            for iface_name in self._communications[com_type]:
                idsl_full_path = self._interfaces[iface_name]
                idsl_full_filename = os.path.basename(idsl_full_path)
                self._cdsl_doc.add_import(idsl_full_filename)

    def update_language(self):
        language = self._language_combo_box.currentText()
        self._cdsl_doc.set_language(str(language))
        self.update_editor()

    def update_gui_selection(self):
        checked = self._gui_check_box.isChecked()
        if checked:
            self._cdsl_doc.set_qui(True)
        else:
            self._cdsl_doc.set_qui(False)
        self.update_editor()

    def update_component_name(self, name):
        self._cdsl_doc.set_name(name)
        self.update_editor()

    def update_editor(self):
        self._editor.setText(self._cdsl_doc.generate_doc())

    def set_output_directory(self):
        dir_set = False
        while not dir_set:
            dir = QFileDialog.getExistingDirectory(
                self, "Select Directory", ROBOCOMP_COMP_DIR,
                QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)
            if self.check_dir_is_empty(str(dir)):
                self._dir_line_edit.setText(dir)
                dir_set = True

    def write_cdsl_file(self):
        component_dir = str(self._dir_line_edit.text())
        text = self._cdsl_doc.generate_doc()
        if not self._name_line_edit.text():
            component_name, ok = QInputDialog.getText(self,
                                                      'No component name set',
                                                      'Enter component name:')
            if ok:
                self.update_component_name(component_name)
                self._name_line_edit.setText(component_name)
            else:
                return False

        if not os.path.exists(component_dir):
            if QMessageBox.Yes == QMessageBox.question(
                    self, "Directory doesn't exist.",
                    "Do you want create the directory %s?" % component_dir,
                    QMessageBox.Yes | QMessageBox.No):
                os.makedirs(component_dir)
            else:
                QMessageBox.question(
                    self, "Directory not exist",
                    "Can't create a component witout a valid directory")
                return False

        file_path = os.path.join(component_dir,
                                 str(self._name_line_edit.text()) + ".cdsl")
        if os.path.exists(file_path):
            if QMessageBox.No == QMessageBox.question(
                    self, "File already exists", "Do you want to overwrite?",
                    QMessageBox.Yes | QMessageBox.No):
                return False

        with open(file_path, 'w') as the_file:
            the_file.write(text)
        self.execute_robocomp_cdsl()
        return True

    def execute_robocomp_cdsl(self):
        cdsl_file_path = os.path.join(
            str(self._dir_line_edit.text()),
            str(self._name_line_edit.text()) + ".cdsl")
        command = "python -u %s/robocompdsl.py %s %s" % (
            ROBOCOMPDSL_DIR, cdsl_file_path,
            os.path.join(str(self._dir_line_edit.text())))
        self._console.append_custom_text("%s\n" % command)
        self._command_process.start(command,
                                    QProcess.Unbuffered | QProcess.ReadWrite)

    def reselect_existing(self):
        com_type = self._type_combo_box.currentText()
        selected = self._communications[com_type]
        self._interface_list.clearSelection()
        for iface in selected:
            items = self._interface_list.findItems(iface,
                                                   Qt.MatchFlag.MatchExactly)
            if len(items) > 0:
                item = items[0]
                item.setSelected(True)

    def check_dir_is_empty(self, dir_path):
        if len(os.listdir(dir_path)) > 0:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Directory not empty")
            msgBox.setText(
                "The selected directory is not empty.\n"
                "For a new Component you usually want a new directory.\n"
                "Do you want to use this directory anyway?")
            msgBox.setStandardButtons(QMessageBox.Yes)
            msgBox.addButton(QMessageBox.No)
            msgBox.setDefaultButton(QMessageBox.No)
            if msgBox.exec_() == QMessageBox.Yes:
                return True
            else:
                return False
        else:
            return True
示例#19
0
class SearchBar(QToolBar):

    def __init__(self, parent):
        super(SearchBar, self).__init__(parent)
        self.parent = parent
        self.setMovable(False)
        self.setStyleSheet('QToolBar{spacing:5px;}')
        self.addWidget(QLabel("                                                                                         "))
        self.search = QLineEdit()
        self.search.setPlaceholderText("Search...")
        self.completer = QCompleter()
        self.search.setCompleter(self.completer)
        self.indexer = QApplication.instance().indexer
        self.search.selectionChanged.connect(self.changeSelection)
        self.search.textChanged.connect(self.setCompleterModel)
        self.addWidget(self.search)
        searchbtn = QPushButton("Search")
        searchbtn.clicked.connect(self.searchDocuments)
        highlighttn = QPushButton("Highlight text")
        highlighttn.clicked.connect(self.highlightText)
        self.addWidget(searchbtn)
        self.addWidget(highlighttn)
        self.addWidget(QLabel("                                                                                         "))

    def changeSelection(self):
        selekcija = self.search.selectedText()
        if selekcija != "":
            self.selectedText = selekcija

    def setCompleterModel(self):
        result = self.search.text()
        if len(result) == 1:
            wordobjects = self.indexer.data['WORDS'].start_with_prefix(result)
            words = []
            for wordobj in wordobjects:
                words.append(wordobj.word)
            model = QStringListModel()
            model.setStringList(words)
            self.completer.setModel(model)

    def clearResults(self):
        QApplication.instance().doclist.clear()

    def highlightText(self):
        QApplication.instance().webview.findText("", QWebPage.HighlightAllOccurrences)
        QApplication.instance().webview.findText(self.selectedText, QWebPage.HighlightAllOccurrences)

    def searchDocuments(self):
        QApplication.instance().doclist.show()
        result = self.search.text()
        QApplication.instance().currentWord = result
        self.clearResults()
        documents = []
        if result == "":
            for filepath in self.indexer.data['FILES']:
                QApplication.instance().doclist.addItem(Document(filepath, os.path.basename(filepath)))
                self.parent.leftDock.show()
        else:
            try:
                documentSet = parseResult(result)
                for filepath in documentSet:
                    documents.append(Document(filepath, os.path.basename(filepath), result))
                documents.sort(key=lambda x: x.rank, reverse=True)
                for doc in documents:
                    QApplication.instance().doclist.addItem(doc)
                self.parent.leftDock.show()
            except ValueError:
                pass
示例#20
0
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 &copy; 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")
示例#21
0
    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)