1

Basically, I have a QTableView and the last column of each row contains a QMenu where if triggered, the row should be deleted. I tried the code below, but if I click on the menu that is in a row number > 1, the returned rowNum is -1:

Code:

def addrowIntable(self, a, b):
    Column1 = QStandardItem("%s" % (a))
    Column2 = QStandardItem("%s" % (b))

    actionBTN = QPushButton("")
    actionMenu = QMenu()

    self.RemList = QtWidgets.QAction("Remove row", actionMenu)
    actionMenu.addAction(self.RemList)

    actionMenu.raise_()
    actionBTN.setMenu(actionMenu)
    self.rulesWhitelistWidgetModel.appendRow([Column1, Column2])
    self.rulesWhiteListFileTBL.setIndexWidget(
        self.rulesWhitelistWidgetModel.index(self.rulesWhitelistWidgetModel.rowCount() - 1,
                                             self.rulesWhiteListFileTBL.model().columnCount() - 1), actionBTN)
    self.RemList.triggered.connect(lambda: self.deleteRow("Hello"))

def deleteRow(self, str):
    rowNum = self.rulesWhiteListFileTBL.rowAt(self.rulesWhiteListFileTBL.viewport().mapFromGlobal(self.sender().parent().pos()).y())
    print(self.rulesWhiteListFileTBL.indexAt(self.sender().parent().pos()).row())
    print(rowNum)

I just need to know which row number was the sender from inside deleteRow where I could then use model.removeRow() to delete it.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
pefile
  • 69
  • 6
  • That seems a terrible (and unreadable) way to add a menu. If you always want a menu for the last column, override the `contextMenuEvent()` of the view, or use the custom [context menu policy](https://doc.qt.io/qt-5/qwidget.html#contextMenuPolicy-prop). Besides, if you just add the button as an argument of `deleteRow`, you'll get the proper coordinates. Btw, please just don't concatenate functions like that: there's absolutely **no** benefit in that, you only get ugly, cumbersome code that is annoying and difficult to read (which also means difficult to debug). – musicamante May 23 '22 at 09:26

1 Answers1

1

The main reason why your code doesn't work as expected is because you set the menu as the parent of the action. A menu is a popup window, so its position will be in global coordinates, whereas you want the position relative to the table. A simple way to achieve this is to make the button the parent of the action instead.

The following revision of your code should do what you want:

def addrowIntable(self, a, b):
    Column1 = QStandardItem("%s" % (a))
    Column2 = QStandardItem("%s" % (b))
    actionBTN = QPushButton()
    actionMenu = QMenu()
    actionRem = QtWidgets.QAction("Remove row", actionBTN)
    actionMenu.addAction(actionRem)
    actionBTN.setMenu(actionMenu)
    self.rulesWhitelistWidgetModel.appendRow([Column1, Column2])
    self.rulesWhiteListFileTBL.setIndexWidget(Column2.index(), actionBTN)
    actionRem.triggered.connect(lambda: self.deleteRow("Hello"))

def deleteRow(self, str):
    pos = self.sender().parent().pos()
    index = self.rulesWhiteListFileTBL.indexAt(pos)
    self.rulesWhitelistWidgetModel.removeRow(index.row())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336