防止在特定文本框中撤消

Prevent undo in a particular text box

简短版本:我如何子class或以其他方式修改 QLineEdit,以便上下文菜单的 "undo" 选项不会撤消任何内容?

目前我有以下内容,它阻止 Ctrl-Z 工作:

class PasswordSaveQLineEdit(QLineEdit):
    def keyPressEvent(self,event):
        if event.key()==(QtCore.Qt.Key_Control and QtCore.Qt.Key_Z):
            self.undo()
        else:
            QLineEdit.keyPressEvent(self,event)

    def undo(self):
        pass

可以 禁用上下文菜单,然后摆脱两种可能的撤消方式,但我宁愿不这样做。 undo() 函数似乎没有被 Ctrl-Z 或 select 上下文菜单选项直接调用。

我还看到 this thread 清除 撤消历史记录,这也可以正常工作,但不幸的是,这仅适用于 Q(Plain)TextEdit 而不适用于 QLineEdit .

解释为什么我需要这个(如果有人对如何做有更好的建议):

将 PyQt4 与 Qt Designer 结合使用,我正在尝试实现一个密码输入框(QLineEdit),用户可以在其中选中一个框以显示或隐藏密码。这部分工作正常:

def toggleShowPW(self):
    doShow = self.form.showPWCheck.isChecked()
    if doShow:
        self.form.passwordBox.setEchoMode(QLineEdit.Normal)
    else:
        self.form.passwordBox.setEchoMode(QLineEdit.Password)

self.form.showPWCheck.toggled.connect(self.toggleShowPW)

但是,我的应用程序还需要一个选项来保存密码并在下次打开此对话框时将其恢复。尽管密码以明文形式存储在数据库中(我计划在用户 select 保存密码的选项时向用户发出警告),但我想至少添加一点点安全性,这样路过的用户无法仅通过勾选方框来查看密码。所以我在 class 中添加了一个属性,用于跟踪是否已从配置文件加载密码,并将方法更改为:

def toggleShowPW(self):
    doShow = self.form.showPWCheck.isChecked()
    if doShow:
        # if password was saved in the config, don't let it be shown in
        # plaintext for some basic security
        if self.passwordWasLoaded:
            r = utils.questionBox("For security reasons, you cannot view "
                    "any part of a saved password. Would you like to erase "
                    "the saved password?", "Erase Password")
            if r == QMessageBox.Yes:
                self.form.passwordBox.setText("")
                self.passwordWasLoaded = False
            else:
                self.form.showPWCheck.setChecked(False)
                return
        self.form.passwordBox.setEchoMode(QLineEdit.Normal)
    else:
        self.form.passwordBox.setEchoMode(QLineEdit.Password)

我还添加并连接了一个名为 self.unsetPasswordWasLoaded 的方法,如果密码字段中的所有内容都被删除,它会将标志设置为 False。

效果很好。不幸的是,用户现在可以通过擦除所有内容、勾选方框然后执行撤消来查看密码。 (当 echoMode 设置为 QLineEdit.Password 时,无法执行撤消操作,但是当您将其更改回正常状态时,撤消历史记录仍然存在。)

您需要覆盖上下文菜单的创建方式,以便您可以禁用撤消选项。如果您将状态存储在别处,您可以根据该状态选择是启用还是禁用撤消选项。一个非常基本的例子 -

# context menu requested signal handler
def display_context_menu(point):
    global line_edit

    # grab the standard context menu
    menu = line_edit.createStandardContextMenu()

    # search through the actions i nthe menu to find undo
    for action in menu.actions():
        if action.text() == '&Undo  Ctrl+Z':
            # set undo as disabled
            action.setDisabled(True)
            break

    # show context menu where we right clicked
    menu.exec_(line_edit.mapToGlobal(point))


# create line edit, set it to use a custom context menu, connect the context menu signal to handler
line_edit = QLineEdit()
line_edit.setContextMenuPolicy(Qt.CustomContextMenu)
line_edit.customContextMenuRequested.connect(display_context_menu)

line_edit.show()