JokerMartini
JokerMartini

Reputation: 6147

How to subclass QListView doubleclick and contextmenu

How do I subclass the QListView's doubleclick item and contextmenu event?

In my case I want to subclass QListview and when the user doubleclicks and item, i would like the to print the data (display role text) of the double clicked item.

Secondly i would like to build the context menu into the QListView. I'm not sure how to properly have it display where the user right-clicks.

class MyListView(QtGui.QListView):
    def __init__(self, *args, **kwargs):
        QtGui.QListView.__init__(self, *args, **kwargs)
        self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.setViewMode(QtGui.QListView.IconMode)
        self.setResizeMode(QtGui.QListView.Adjust)
        self.setMovement(QtGui.QListView.Static)
        self.setSpacing(5)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        # self.customContextMenuRequested.connect(self.open_tags_list_menu)
        self.setStyleSheet('''
            QListView::item {
                border: 1px solid rgba(0,0,0,60);
                background: rgba(0,0,0,30);
                border-radius: 2px;
            }
            QListView::item:selected {
                border: 1px solid rgba(70,150,255,255);
                background: rgba(70,150,255,200);
                border-radius: 2px;
            }
        ''')

        self.act_delete_selected = QtGui.QAction('Delete Selected', self)

        self.act_delete_all = QtGui.QAction('Delete All', self)

        self.my_menu = QtGui.QMenu()
        self.my_menu.addAction(self.act_delete_selected)
        self.my_menu.addAction(self.act_delete_all)


    def mouseDoubleClickEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            print 'text of item clickd'
        QtGui.QListView.mouseDoubleClickEvent(self, event)


    def onCustomContextMenuRequested(self, point):
        print 'my_menu'

Upvotes: 0

Views: 607

Answers (1)

eyllanesc
eyllanesc

Reputation: 243887

To obtain the data you need the QModelIndex, as we have the position event.pos(), you must use itemAt():

def mouseDoubleClickEvent(self, event):
    if event.button() == QtCore.Qt.LeftButton:
        ix = self.indexAt(event.pos())
        print(ix.data())
    QtGui.QListView.mouseDoubleClickEvent(self, event)

The customContextMenuRequested signal must be connected to a slot, it provides the position information, it is used to tell you where the menu should be displayed, exec_() returns the selected QAction:

    self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
    self.customContextMenuRequested.connect(self.onCustomContextMenuRequested)


def onCustomContextMenuRequested(self, point):
    my_menu = QtGui.QMenu(self)
    act_delete_selected = QtGui.QAction('Delete Selected', self)
    act_delete_all = QtGui.QAction('Delete All', self)
    my_menu.addAction(act_delete_selected)
    my_menu.addAction(act_delete_all)
    action = my_menu.exec_(self.mapToGlobal(point))
    if action == act_delete_selected:
        [some code]
    elif action == act_delete_all:
        self.model().removeRows(0, self.model().rowCount())

Example:

from PySide import QtGui, QtCore

class MyListView(QtGui.QListView):
    def __init__(self, *args, **kwargs):
        QtGui.QListView.__init__(self, *args, **kwargs)
        self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.setViewMode(QtGui.QListView.IconMode)
        self.setResizeMode(QtGui.QListView.Adjust)
        self.setMovement(QtGui.QListView.Static)
        self.setSpacing(5)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.onCustomContextMenuRequested)
        self.setStyleSheet('''
            QListView::item {
                border: 1px solid rgba(0,0,0,60);
                background: rgba(0,0,0,30);
                border-radius: 2px;
            }
            QListView::item:selected {
                border: 1px solid rgba(70,150,255,255);
                background: rgba(70,150,255,200);
                border-radius: 2px;
            }
        ''')

    def mouseDoubleClickEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            ix = self.indexAt(event.pos())
            print(ix.data())
        QtGui.QListView.mouseDoubleClickEvent(self, event)


    def onCustomContextMenuRequested(self, point):
        my_menu = QtGui.QMenu(self)
        act_delete_selected = QtGui.QAction('Delete Selected', self)
        act_delete_all = QtGui.QAction('Delete All', self)
        my_menu.addAction(act_delete_selected)
        my_menu.addAction(act_delete_all)
        action = my_menu.exec_(self.mapToGlobal(point))
        if action == act_delete_selected:
            for ix in self.selectedIndexes():
                self.model().removeRows(ix.row(), 1)
            self.clearSelection()
        elif action == act_delete_all:
            self.model().removeRows(0, self.model().rowCount())


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MyListView()
    model = QtGui.QStringListModel([str(i) for i in range(100)])
    w.setModel(model)
    w.show()
    sys.exit(app.exec_())

Upvotes: 2

Related Questions