1

I am trying to figure out how to do a multiline ListElement property.

I have a ListModel with ListElements as follows:

ListElement {
   key: "key";
   value: 1;
   description: "Very long, full paragraph description that extends way off the screen which I would like to wrap in code nicely."
}

I can wrap it by simply entering a newline, but then the following lines are not lined up with the block of text.

   description: "Very long, full paragraph description
that extends way off the screen which I would like to
wrap in code nicely."

When I try to tab over the text to line it up, it causes massive whitespace when the description is printed to screen (which makes sense, but obviously not what I want).

   description: "Very long, full paragraph description
               that extends way off the screen which I would like to
               wrap nicely in code."
Very long, full paragraph description             that extends way off the screen which I would like to
            wrap in code nicely.

I have tried concatenating via '+', but that produces an error: ListElement: Cannot use script for property value.

I have tried using backslashes like I do in the .pro file, but that does not work, either.

Newline characters work, but they do not matter, as they do not solve the whitespace issue.

Very long, full paragraph description
            that extends way off the screen which I would like to
            wrap in code nicely.

If anyone has any ideas, I would appreciate them.

Joseph Farrar
  • 144
  • 1
  • 1
  • 12
  • 1
    Instead of a double quote(") , try backticks(`). Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals – Manish Kumar May 08 '23 at 03:45
  • 1
    A detailed answer is posted here, https://stackoverflow.com/questions/805107/creating-multiline-strings-in-javascript – Manish Kumar May 08 '23 at 03:46
  • @ManishKumar, I had high hopes for that, but, alas, no dice. It produces the ```ListElement: Cannot use script for property value``` error. I think it has to do with the difference between being a variable and a property. – Joseph Farrar May 08 '23 at 04:47

2 Answers2

1

I don't have a direct solution for the implementation you are using with creating ListElements directly like that. But the .append() method of the ListModel does take JS objects as arguments. And those support multiline strings. So instead of creating ListElements like that you could just append them on component completion like this:

ListModel {
    id:listModel

    Component.onCompleted: {
        listModel.append({
            "key": "key",
            "value": 1,
            "description": "Very long, full paragraph description" +
            "that extends way off the screen which" +
            "I would like to wrap in code nicely."
        })
    }
}
Xic
  • 66
  • 3
  • This did exactly what I wanted (though not how I would have preferred), but iiwii sometimes with Qt. LOL! Thanks for the help! – Joseph Farrar May 08 '23 at 22:31
0

Firstly, you can consider using Javascript backtick notation to declare a multiline string.

        ListElement {
            key: "key"
            value: 1
            description: `Very long, full paragraph description
that extends way off the screen which I would like to
wrap in code nicely.`
        }

Beyond that, you may find ListElement declaration to be restrictive not supporting Javascript expressions, e.g. Date.now(). In those cases, you can consider using imperative code. If you want some semblance of declarative you can declare a Javascript array of objects and iterate through it.

When rendering, you may also consider using wrapMode: Text.Wrap to apply additional word wrapping to format your text.

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    ListModel {
        id: listModel
        ListElement {
            key: "key"
            value: 1
            time: 01683504000000
            description: `Very long, full paragraph description
that extends way off the screen which I would like to
wrap in code nicely.`
        }
        property var initData: [{
            key: "key2",
            value: 2,
            time: Date.now(),
            description: `Very long, full paragraph description
that extends way off the screen which I would like to
wrap in code nicely.`.replace(/\n/g, " ")
         },{
            key: "key3",
            value: 3,
            time: (new Date("2023-05-09").getTime()),
            description: `Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Donec odio. Quisque volutpat mattis eros.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Donec odio. Quisque volutpat mattis eros.`
         },{
            key: "key4",
            value: 4,
            time: (new Date("2023-05-10").getTime()),
            description: `Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Donec odio. Quisque volutpat mattis eros.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Donec odio. Quisque volutpat mattis eros.`.replace(/\n/g, " ")
         },{
            key: "key5",
            value: 5,
            time: (new Date("2023-05-11").getTime()),
            description: [
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"Donec odio. Quisque volutpat mattis eros.",
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"Donec odio. Quisque volutpat mattis eros.",
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"Donec odio. Quisque volutpat mattis eros."
].join(" ")
         }]
         Component.onCompleted: {
             for (let obj of initData) {
                 append(obj);
             }
         }
    }
    ListView {
        anchors.fill: parent
        model: listModel
        ScrollBar.vertical: ScrollBar {
            width: 20
            policy: ScrollBar.AlwaysOn
        }
        delegate: Frame {
            width: ListView.view.width - 20
            background: Rectangle {
                color: index & 1 ? "#eee" : "#ddd"
                border.color: "#ccc"
            }
            ColumnLayout {
                width: parent.width
                Text { text: `key: ${key}` }
                Text { text: `time: ${new Date(time)} (${time})` }
                Text { text: `value: ${value}` }
                Text {
                    Layout.fillWidth: true
                    text: description
                    wrapMode: Text.Wrap
                }
            }
        }
    }
}

You can Try it Online!

Stephen Quan
  • 21,481
  • 4
  • 88
  • 75