Search code examples
pythonqtqmlpyside2

menu selecting a source in qml and python


I have to do a menu in QML that contains the list of items in a directory and, by clicking over one of them, it plays a video (player.play())

This is what I tried, but is not working

___.qml

Menu {
    id: menu
    contentItem: ListView {
        model: ui.textMenu
    }
}
Menu {
    id: menu
    y: -200 
    x: 100
    Repeater{
        model: ui.textMenu
        MenuItem {
            text: textMenu.entry
            onClicked:{
                player.source = textMenu.address
                player.play()
            }
        } //x: model.x*(videoPlayer.width - 10)
    }
}

___.py

self.__textMenu = QStandardItemModel(self)
 menuRoles = {entryRole: b"entry", addressRole: b"address"}
 self.__textMenu.setItemRoleNames(menuRoles)

 def menu(self):
    directoryPath = os.path.join(self.__currentPath, r"video" )
    entries = os.listdir(directoryPath) 
    for entry in entries:
        menuVoice = QStandardItem()
        menuVoice.setData(entry, entryRole)
        videoPath = os.path.join(directoryPath, entry)
        menuVoice.setData(videoPath, addressRole)

Solution

  • Your QML seems inconsistent with what you want. In this case I have created a Menu within the MenuBar where the MenuItem will be created using the model and a Repeater:

    import os
    import sys
    
    from PySide2 import QtCore, QtGui, QtQml
    
    NameRole = QtCore.Qt.UserRole + 1000
    PathRole = QtCore.Qt.UserRole + 1001
    
    
    def create_model(dir_path):
        model = QtGui.QStandardItemModel()
        roles = {NameRole: b"name", PathRole: b"path"}
        model.setItemRoleNames(roles)
        for name in os.listdir(dir_path):
            it = QtGui.QStandardItem()
            it.setData(name, NameRole)
            it.setData(os.path.join(dir_path, name), PathRole)
            model.appendRow(it)
        return model
    
    
    def main(args):
        app = QtGui.QGuiApplication(args)
    
        current_dir = os.path.dirname(os.path.realpath(__file__))
        video_dir = os.path.join(current_dir, "video")
        model = create_model(video_dir)
    
        engine = QtQml.QQmlApplicationEngine()
        engine.rootContext().setContextProperty("video_model", model)
        current_dir = os.path.dirname(os.path.realpath(__file__))
        filename = os.path.join(current_dir, "main.qml")
        engine.load(QtCore.QUrl.fromLocalFile(filename))
        if not engine.rootObjects():
            return -1
        ret = app.exec_()
        return ret
    
    
    if __name__ == "__main__":
        sys.exit(main(sys.argv))
    
    import QtQuick 2.13
    import QtQuick.Controls 2.13
    import QtMultimedia 5.13
    
    ApplicationWindow {
        id: root
        width: 640
        height: 480
        visible: true
    
        menuBar: MenuBar {
            Menu {
                id: plugins_menu
                title: qsTr("&Videos")
                Repeater{
                    model: video_model
                    MenuItem{
                        text: model.name
                        onTriggered: {
                            video.source = Qt.resolvedUrl(model.path)
                            video.play()
                        }
                    }
                }
            }
        }
        Video {
            id: video
            anchors.fill: parent
        }
    }