class CompleteLineEdit(QLineEdit):
    def __init__(self, words):
        super(CompleteLineEdit, self).__init__(None)

        self.words = words                # QStringList  整个完成列表的单词
        self.listView = QListView(self)
        self.model = QStringListModel(self)
        self.listView.setWindowFlags(Qt.ToolTip)

        self.connect(self, SIGNAL("textChanged(const QString &)"),
                     self, SLOT("setCompleter(const QString &)"))

        self.connect(self.listView, SIGNAL("clicked(const QModelIndex &)"),
                     self, SLOT("completeText(const QModelIndex &)"))

    def focusOutEvent(self, focus_event):
        # self.listView.hide()
        pass

    @pyqtSlot("QKeyEvent")
    def keyPressEvent(self, e):
        if not self.listView.isHidden():
            key = e.key()
            count = self.listView.model().rowCount()
            currentIndex = self.listView.currentIndex()

            if Qt.Key_Down == key:
                # 按向下方向键时,移动光标选中下一个完成列表中的项
                row = currentIndex.row() + 1
                if (row >= count):
                    row = 0

                index = self.listView.model().index(row, 0)
                self.listView.setCurrentIndex(index)
            elif Qt.Key_Up == key:
                # 按向下方向键时,移动光标选中上一个完成列表中的项
                row = currentIndex.row() - 1
                if (row < 0):
                    row = count - 1

                index = self.listView.model().index(row, 0)
                self.listView.setCurrentIndex(index)
            elif Qt.Key_Escape == key:
                # 按下Esc键时,隐藏完成列表
                self.listView.hide()
            elif Qt.Key_Enter == key or Qt.Key_Return == key:
                # 按下回车键时,使用完成列表中选中的项,并隐藏完成列表
                if (currentIndex.isValid()):
                    text = self.listView.currentIndex().data().toString()
                    self.setText(text)

                self.listView.hide()
            else:
                # 其他情况,隐藏完成列表,并使用QLineEdit的键盘按下事件
                self.listView.hide()
                QLineEdit.keyPressEvent(self,e)
        else:
            QLineEdit.keyPressEvent(self,e)

    # 动态的显示完成列表
    @pyqtSlot("QString")
    def setCompleter(self, text):

        if (text.isEmpty()):
            self.listView.hide()
            return

        if text.length() > 1 and not self.listView.isHidden():
            return

        # 如果完整的完成列表中的某个单词包含输入的文本,则加入要显示的完成列表串中
        sl = QStringList()

        for i in range(self.words.count()):
            if self.words[i].contains(text):
                sl << self.words[i]

        self.model.setStringList(sl)
        self.listView.setModel(self.model)

        if (self.model.rowCount() == 0):
            return

        # Position the text edit
        self.listView.setMinimumWidth(self.width())
        self.listView.setMaximumWidth(self.width())

        p = QPoint(0, self.height())
        x = self.mapToGlobal(p).x()
        y = self.mapToGlobal(p).y() + 1

        self.listView.move(x, y)
        self.listView.show()

    # 点击完成列表中的项,使用此项自动完成输入的单词
    @pyqtSlot("QModelIndex")
    def completeText(self, index):
        text = index.data().toString()
        self.setText(text)
        self.listView.hide()