<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Factoring out complex delegate - has slowed down]]></title><description><![CDATA[<p dir="auto">I am looking for advice on how to go about factoring out some fairly complex delegate code that is currently embedded directly in a <code>ListView</code>-based component. I would like to be able to reuse the delegate in a slightly different <code>ListView</code> or, potentially, a different view altogether. I have done a preliminary refactor that sort of works but has slowed it down considerably for reasons I don't fully understand. I would like advice on whether I have gone about the refactor in the right way and also whether there is anything obvious that could be causing the slowdown.</p>
<p dir="auto">My <code>ListView</code> component contains a table of settable values of different types. It is driven by a model that provides information such as the name of each item, its data type, its current value, etc. Because the entries are of different types, they need different controls to display and edit the values. The data type determines the type of control to use for each entry. This is based on using a <code>Loader</code> in the delegate, with a switch on the data type to select the correct component. (I am currently constrained to use Qt 5.9.6 - not for much longer I hope - so do not have access to DelegateChooser.)</p>
<p dir="auto">This is one of the first things I wrote when I started with QML and it has grown somewhat "organically" in the meantime. All of the code is currently inside the <code>ListView</code>-based component. I now want to be able to reuse all of the delegate code so I essentially want to factor the delegate code out of the <code>ListView</code> component.</p>
<p dir="auto">This is the structure at the moment:</p>
<pre><code>ListView {
    ...
    model: myModel
    ...
    
    // Various helper functions used in the delegate
    function deriveType(...) { ... }
    function anotherHelper(...) { ... }
    ...
    
    // This is used by some of the property type Components below
    MyFileDialog { id: dlg }
    
    Component {
        id: intDelegate
        IntControl { ... } // text field geared to integer input
    }
    
    Component {
        id: optionDelegate
        OptionControl { ... } // essentially combo with string options
    }
    
    Component {
        id: fileDelegate
        FileControl { // selects a file path
            dialog: dlg // uses the common dialog above
            ...
        }
    }
    
    ...
    
    delegate: RowLayout {
       Label {
          text: label // 'label' from model
       }
       Loader {
          // Loaded components don't get automatic access to the model
          // fields so need to copy into new variables here that will
          // be in the scope of the loaded components.
          // Various massaging of the data goes on here too using the
          // helper functions.
       
          property loader_type: deriveType( /* access model fields */ ...)
          property ...
          ...
          
          switch (loader_type) {
          case "int":
              return intDelegate;
          case ...
          }
       }
    }
</code></pre>
<p dir="auto">Virtually everything I have shown above, the <code>Components</code>, the helper functions, the delegate,<br />
are all related to the delegate implementation so I want to factor this out into a separate component.</p>
<p dir="auto">This is what I have done (in <code>ValueDelegate.qml</code> say):</p>
<pre><code>Item {
    
    // Various helper functions used in the delegate
    function deriveType(...) { ... }
    function anotherHelper(...) { ... }
    ...
    
    // This is used by some of the property type Components below
    MyFileDialog { id: dlg }
    
    Component {
        id: intDelegate
        IntControl { ... } // text field geared to integer input
    }
    ...     
    ... // as above
    
    RowLayout { // exactly as the delegate in the original code above
       Label { ... }
       Loader { ... }
    }
</code></pre>
<p dir="auto">whereas the <code>ListView</code> is now very small and looks more like this:</p>
<pre><code>ListView {
    model: myModel
    ...
    
    delegate: ValueDelegate {
    }
}
</code></pre>
<p dir="auto">I have only done a rudimentary factoring out so far. I should probably define properties at the <code>Item</code> level to receive the model fields. At the moment these are visible to the <code>RowLayout</code> in <code>ValueDelegate</code> because the context in which the <code>ValueDelegate</code> is created in the <code>ListView</code>.</p>
<p dir="auto">Anyway, this works after a fashion but it is extremely slow. This table is filled based on selections elsewhere in the GUI. When a new selection is made, the model changes, the table is effectively cleared and refreshed. Before this refactor, this was very snappy, but now I am waiting a couple of seconds.</p>
<p dir="auto">One thing I am wondering is whether it is because the delegate is now a lot "heavier" than it was before. The delegate is now this <code>Item</code> that has all the helper functions, the <code>Component</code>s for the value types as well as the original <code>RowLayout</code>. Whereas in the original code a lot of that existed at the <code>ListView</code> level, it is now all in the delegate itself. I don't have a feel for what sort of overhead this introduces.</p>
<p dir="auto">If it is likely that the delegate is too heavyweight now, is there a better approach I could take to refactoring this?</p>
]]></description><link>https://forum.qt.io/topic/141173/factoring-out-complex-delegate-has-slowed-down</link><generator>RSS for Node</generator><lastBuildDate>Sun, 26 Apr 2026 01:28:30 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/141173.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 01 Dec 2022 10:06:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Factoring out complex delegate - has slowed down on Thu, 01 Dec 2022 10:28:09 GMT]]></title><description><![CDATA[<p dir="auto">Seconds after writing all that and posting it, it occurred to me to try one thing, which was to remove the file dialog from the delegate and to pass that in instead. That appears to have solved the speed issue.</p>
<p dir="auto">Still interested to hear whether the approach seems OK otherwise - is it OK to have all those embedded <code>Component</code>s in the delegate and is there any alternative?</p>
<p dir="auto">So I now have something more like this:</p>
<p dir="auto"><code>ValueDelegate.qml</code>:</p>
<pre><code>Item {
     property dlg
     // **remove embedded MyFileDialog from delegate**
     // everything else the same...
</code></pre>
<p dir="auto">The <code>ListView</code>:</p>
<pre><code>ListView {
    model: myModel
    ...
    MyFileDialog { id: myDlg }

    delegate: ValueDelegate {
         dlg: myDlg
    }
}</code></pre>
]]></description><link>https://forum.qt.io/post/738594</link><guid isPermaLink="true">https://forum.qt.io/post/738594</guid><dc:creator><![CDATA[Bob64]]></dc:creator><pubDate>Thu, 01 Dec 2022 10:28:09 GMT</pubDate></item></channel></rss>