1

I try to extend the contextmenu of a QLineEdit with an additional entry for replacing text. I can extend the contextmenu with .createStandardContextMenu(), which works fine. But when I try to add a shortcut with .setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R)) it will not react on the key. Same with different keys, which I tried. In addition the shortcut made with QAction('&Replace', self) doesn't work too. Some examples here in SO and other sources are constructed in the same way, so I'm wondering that nobody else has got the same problem. Seems that I'm missing anything. But what? I can't figure out, checked the docs multiple times.

Working Example:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys


class ECM(QWidget):

    def __init__(self):
        super(ECM, self).__init__()
        self.setWindowTitle("Extended Context Menu")
        self.lineEdit = QLineEdit()
        self.lineEdit.setContextMenuPolicy(Qt.CustomContextMenu)                            
        self.lineEdit.customContextMenuRequested.connect(self.my_contextMenuEvent)

        layout = QVBoxLayout()
        layout.addWidget(self.lineEdit)
        self.setLayout(layout)

        self.setFixedSize(800,200)
        self.show()

    def replace(self):
        print("replace")

    def my_contextMenuEvent(self):                                           
        print("my_contextMenuEvent")                                         
        menu = self.lineEdit.createStandardContextMenu()
        action = QAction('&Replace', self)
        action.setStatusTip('Replace values')
        action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        action.triggered.connect(self.replace)
        menu.addAction(action)                                               
        menu.exec_()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    sender = ECM()
    app.exec_()
Papageno
  • 305
  • 3
  • 15
  • Keyboard shortcuts work if you add the action to the widget with `addAction()` (which means that you should not create new actions everytime, but reuse the current ones). – musicamante Apr 16 '21 at 17:19

1 Answers1

0

Based on musicamante's comment I came to the following solution:

Extract from the docs:

  1. If you want to extend the standard context menu, reimplement this function, call createStandardContextMenu() and extend the menu returned.
  2. The default use of the QAction list (as returned by actions()) is to create a context QMenu.

It's not totally logically to me, not for the 1st time ;-)

Final code:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys


class ECM(QWidget):

    def __init__(self):
        super(ECM, self).__init__()
        self.setWindowTitle("Extended Context Menu")
        self.lineEdit = QLineEdit()
        self.lineEdit.setContextMenuPolicy(Qt.CustomContextMenu)                            
        self.lineEdit.customContextMenuRequested.connect(self.my_contextMenuEvent)

        layout = QVBoxLayout()
        layout.addWidget(self.lineEdit)
        self.setLayout(layout)

        self.setFixedSize(800,200)

        action = QAction('&Replace', self)
        action.setStatusTip('Replace values')
        action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        action.triggered.connect(self.replace)

        self.lineEdit.addAction(action)

        self.show()

    def replace(self):
        print("replace")

    def my_contextMenuEvent(self):                                           
        menu = self.lineEdit.createStandardContextMenu()
        menu.addActions(self.lineEdit.actions())
        menu.exec_()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    sender = ECM()
    app.exec_()
Papageno
  • 305
  • 3
  • 15