QML - Como criar propriedades de componentes QML para que possam ser definidas a partir do JavaScript?

3

Estou tentando criar um componente com certas propriedades que defini. A localização e o nome dos sons são dados por uma função C ++ que está realmente funcionando porque o console.log () mostra isso:

qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Amsterdam.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Blip.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Mallet.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Positive.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Rhodes.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Slick.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Soft delay.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Xylo.ogg sound

O problema é que, ao tentar definir as propriedades para um ListElement, ele simplesmente deixará o ListView vazio, como se não reconhecesse as propriedades.

Aqui estão minhas funções do JavasCript em um arquivo:

var component;
var element;

function createElement(soundName, soundLocation) {
    component = Qt.createComponent("../AlertsSettingsSounds.qml")
    if (component.status === Component.Ready)
        finishCreation(soundName, soundLocation)
    else
        component.statusChanged.connect(finishCreation)
}

function finishCreation(soundName, soundLocation) {
    if (component.status === Component.Ready) {
        element = component.createObject(alertsModel, {
                                             "Name": soundName,
                                             "Sound": soundLocation});

        if (element === null)
            // Error Handling
            console.log("Error creating object");
    } else if (component.status === Component.Error)
        // Error Handling
        console.log("Error loading component: ", component.errorString());
}

Aqui está a página usada:

import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Components.ListItems 1.0 as ListItem

import Irc_App 0.1

import "../components"

// Mobile (small screen) layout
Page {
    id: alertsSettingsPage
    objectName: "alertSettingsPage"

    title: i18n.tr("Alerts")

    Row {
        id: muteRow
        objectName: "muteRow"

        anchors {
            left: parent.left
            leftMargin: root.margins
            top: parent.top
            topMargin: root.margins
            right: parent.right
            rightMargin: root.margins
        }

        spacing: root.spacing

        Label {
            id: muteLabel
            objectName: "muteLabel"

            width: parent.width - muteCheckBox.width

            text: i18n.tr("<b>Mute</b> notifications")
        }

        CheckBox {
            id: muteCheckBox
            objectName: "muteCheckBox"

            checked: false
            onCheckedChanged: {
                if (checked === true)
                    soundsComponent.volume = 0
                else
                    soundsComponent.volume = 1
            }
        }
    }

    Flickable {
        id: soundsFlickable
        objectName: "soundsFlickable"

        anchors {
            left: parent.left
            leftMargin: root.margins
            top: muteRow.bottom
            right: parent.right
            rightMargin: root.margins
            bottom: parent.bottom
            bottomMargin: root.margins
        }

        clip: true
        contentHeight: soundsColumn.height
        contentWidth: parent.width
        flickableDirection: Flickable.VerticalFlick

        Column {
            id: soundsColumn
            objectName: "soundsColumn"

            width: parent.width
            spacing: root.spacing

            // One item selector for each notification there is.
            ListItem.ItemSelector {
                id: highlightAlertSelector
                objectName: "highlightAlertSelector"

                text: i18n.tr("Highlight Alert")
                expanded: false
                model: alertsSettingsComponent

                onSelectedChanged: {
                    console.log(selectedIndex + " selected")
                }

                delegate: OptionSelectorDelegate {
                    text: name
                    onClicked: {
                        // This functions are local and to make the alerts
                        // sound as they ought to. They will write the
                        // configuration to the xml file and, from there,
                        // the program will start with those options set
                        // and the events will read such file to set again the
                        // Audio component and make it work for just the event.
                        if (name === "Muted") {
                            console.log("Muting sound for highlights")
                            soundsComponent.source = ""
                        } else {
                            console.log("Starting sound " + name +
                                        " for highlights")
                            console.log("Setting sound option " + name +
                                        " for highlights")
                            soundsComponent.source =
                                    soundsHandler.soundsLocation + "/" + name
                            soundsComponent.play()
                        }
                    }
                }

                Component.onCompleted: {
                    // Set the muteCheckBox as it is in the configuration
                    // Set the sounds as they are in the configuration file
                }
            }

            ListItem.ItemSelector {
                id: kickedAlertsSelector
                objectName: "kickedAlertsSelector"

                text: i18n.tr("Kicked Alert")
                expanded: false
                model: alertsSettingsComponent

                onSelectedChanged: {
                    console.log(selectedIndex + " selected")
                }

                delegate: OptionSelectorDelegate {
                    text: name
                    onClicked: {
                        if (name === "Muted") {
                            console.log("Muting sound for kicked event")
                            soundsComponent.source = ""
                        } else {
                            console.log("Starting sound " + name +
                                        " for kicked event")
                            console.log("Setting sound option " + name +
                                        " for kicked event")
                            soundsComponent.source =
                                    soundsHandler.soundsLocation + "/" + name
                            soundsComponent.play()
                        }
                    }
                }

                Component.onCompleted: {
                    // Set the muteCheckBox as it is in the configuration
                    // Set the sounds as they are in the configuration file
                }
            }
        }
    }

    AlertsSettingsComponent {
        id: alertsSettingsComponent
        objectName: "alertsSettings_component"
    }

    SoundsComponent {
        id: soundsComponent
        objectName: "sounds_component"
    }
}

Aqui está o componente usado para os Seletores de lista, que é o que deve estar trabalhando com as funções JS:

import QtQuick 2.0

import Irc_App 0.1

import "../js/AlertsSettingsFunctions.js" as AlertsSettingsFunction

// Using the sounds from the folder
ListModel{
    id: alertsModel
    objectName: "alertsModel"

    Component.onCompleted: {
        for (var i = 0; i < soundsHandler.sounds.length; i++) {
            AlertsSettingsFunction.createElement(soundsHandler.sounds[i],
                        soundsHandler.soundsLocation + "/"
                        + soundsHandler.sounds[i])
            console.log("Adding", soundsHandler.soundsLocation + "/"
                        + soundsHandler.sounds[i], "sound")
        }
    }
}

E aqui está o ListElement que define as propriedades Name e Sound usadas no arquivo JS:

ListElement {
    id: soundsListElement
    objectName: "soundsListElement"

    property string Name
    property string Sound

    name: Name
    sound: Sound
}

Portanto, meu problema é que o JS não parece entender que Name e Sound são propriedades de string para o ListElement e que deve defini-los com o soundName e soundLocation fornecidos na função presente no componente ListView, de modo a mostre-o na página. Em vez disso, os Seletores de Itens aparecem completamente vazios.

Eu não consigo descobrir o que estou fazendo de errado, qualquer ajuda seria muito apreciada.

    
por Víctor Matía Rodríguez 30.09.2014 / 13:29

2 respostas

2

Acho que você seguiu o exemplo dado aqui , mas no seu caso você está tentando connect para o sinal component.statusChanged e, ao mesmo tempo, esperando ver o manipulador finishCreation aceitar argumentos. Não é possível.

Uma vez conectado ao sinal, se emitido, chamará finishCreation sem argumentos. Eu acho que isso explica porque você está vendo itens vazios.

Para garantir que, quando o manipulador de sinais for chamado, você tenha acesso a soundName e soundLocation , torná-los globais, como component e element no arquivo js (não testado):

var component;
var element;
var _soundName;
var _soundLocation;

function createElement(soundName, soundLocation) {
    component = Qt.createComponent("../AlertsSettingsSounds.qml")
    _soundName = soundName
    _soundLocation = soundLocation
    if (component.status === Component.Ready)
        finishCreation()
    else
        component.statusChanged.connect(finishCreation)
}

function finishCreation() {
    if (component.status === Component.Ready) {
        element = component.createObject(alertsModel, {
                                             "Name": _soundName,
                                             "Sound": _soundLocation});

        if (element === null)
            // Error Handling
            console.log("Error creating object");
    } else if (component.status === Component.Error)
        // Error Handling
        console.log("Error loading component: ", component.errorString());
}
    
por Sylvain Pineau 30.09.2014 / 14:00
0

Corrigido. Parece que eu não deveria criar um componente ListElement. Em vez disso, o ListModel deve se parecer com:

import QtQuick 2.0

import Irc_App 0.1

import "../js/AlertsSettingsFunctions.js" as AlertsSettingsFunction

// Using the sounds from the folder
ListModel {
    id: alertsModel
    objectName: "alertsModel"

    Component.onCompleted: {
        for (var i = 0; i < soundsHandler.sounds.length; i++)
            AlertsSettingsFunction.makeList(alertsModel,
                                            soundsHandler.sounds[i],
                                            soundsHandler.soundsLocation + "/"
                                            + soundsHandler.sounds[i])
    }
}

E o arquivo JavaScript deve se parecer com:

function makeList(id, soundName, soundLocation) {
    id.append({"name" : soundName, "sound" : soundLocation})
}

Deve ser anexado à lista.

    
por Víctor Matía Rodríguez 30.09.2014 / 19:38