0

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)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Dade
  • 25
  • 4

1 Answers1

0

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
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks, but there was only an error in the qml: model instead of textMenu, without changing all the code. By the way, I still not understand the meaning of "QtCore.Qt.UserRole + 1000" – Dade Oct 30 '19 at 07:28
  • @DavideFaggian 1) The changes that you indicate are only in form but not in substance, that is, you want me to change the name to the variables and that I will not do since they seem to me that the names I use are simple and easier to understand If the bottom line was understood then changing the names is a trivial thing that anyone could do. Does my solution work or not? If it works then I let you change the names as an exercise. – eyllanesc Oct 30 '19 at 08:06
  • @DavideFaggian [cont.] Understand that Qt is written in C++ so many of the implementations take advantage of the memory management and speed of that language, considering in QML the name of a role is used, for example "name", then if you modify name you must to find what element you modified but to search for "name" implies to search to compare "n", then "a", then "m", etc. that has a lot of cost, if instead I associate "name" with a number, for example 333 then in the search I compare it with 333 that no longer depends on the number of characters in the word. – eyllanesc Oct 30 '19 at 08:07
  • @DavideFaggian [cont.] In conclusion, for reasons of efficiency in the search for information (which occurs when it is deleted, modified, etc.), it is associated with a 2 elements role: "name" and NameRole, where the first one is used in QML since it is more understandable and the second in the internal part of the search obtaining an easy to read and efficient code – eyllanesc Oct 30 '19 at 08:07