2015-08-10 2 views
0

Краткая версия: Как я могу подклассифицировать или иным образом модифицировать QLineEdit, чтобы опция «отменить» контекстного меню ничего не отменила?Предотвращение отмены в определенном текстовом поле

В настоящее время у меня есть следующие, который блокирует 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 или выбора опции контекстного меню.

Я также видел this thread на клирингового историю отмены, который также будет работать хорошо, но это относится только к сожалению, Q (Plain) TextEdit и не QLineEdit.

Объяснение того, почему мне это нужно (в случае, если кто-то есть лучшее предложение о том, как это сделать):

Использование PyQt4 с помощью конструктора Qt, я пытаюсь реализовать поле ввода пароля (а 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) 

Однако мое приложение также нуждается возможность сохранить пароль и вернуть его в следующий раз, когда открывается этот диалог. Хотя пароль хранится в открытом тексте в базе данных (и я планирую предоставить предупреждение пользователю об этом, когда они выбирают вариант сохранения пароля), я хотел бы добавить хотя бы немного безопасности, чтобы пользователь, который ходит, не может смотреть на пароль, просто отметив поле. Поэтому я добавил атрибут к классу, который отслеживает, загружен ли пароль из конфигурационного файла, и изменил способ это:

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, который устанавливает flag to False, если все содержимое поля пароля стерто.

Это прекрасно работает. К сожалению, пользователь теперь может просматривать пароль, удаляя все содержимое, пометив поле и затем отменив его. (Невозможно выполнить отмену, если для echoMode установлено значение QLineEdit.Password, но если вы измените его обратно, история отмены сохранится раньше.)

+0

Это абсолютное безумие. Почему вы намеренно подрываете безопасность пароля пользователя, позволяя ему отображаться в виде обычного текста? Пожалуйста, не говорите «потому что это более удобно». Лично, если бы я когда-либо сталкивался с приложением/веб-сайтом, который работал так, как вы предлагаете, я бы сразу отказался от него и посоветовал другим делать то же самое. – ekhumoro

+0

Я не согласен с тем, что маскирование паролей в большинстве случаев повышает безопасность, а [я не единственный] (http://www.nngroup.com/articles/stop-password-masking/) (как упоминалось в этой ссылке, Internet Explorer 10 теперь применяет эту функцию ко всем полям ввода пароля веб-сайта, также как и запись беспроводного ключа в Windows 7, мой веб-сайт банка и множество других программ, которые я использую). Большую часть времени большинство пользователей одиноки на своем компьютере, и никто не смотрит. Если кто-то есть, вы не установите флажок - это так просто. –

+0

Кроме того, было предложено (в том числе в ссылке), что маскировка может фактически * уменьшить * безопасность - это препятствует пользователям выбирать более длинные и сложные пароли, поскольку их сложнее напечатать без ошибок, когда вы не можете видеть, сделав. –

ответ

1

Вам необходимо переопределить, как создается контекстное меню, чтобы вы может отключить опцию Отменить. Если вы сохраняете состояние в другом месте, вы можете выбрать, включать или отключать вариант отмены в зависимости от этого состояния. Очень простой пример -

# 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() 
+0

Чтобы улучшить защиту от любых нечетных возможностей, о которых я, возможно, и не подумал, я решил просто отключить этот вариант безоговорочно. Это отлично работает, спасибо! –

Смежные вопросы