I assume you're speaking about QtDesigner *.ui files.
Out of order tabbing occurs when the order of GridLayout
/FormLayout
items in a ui file (actually xml file) differs from the visual order (left-to-right, top-to-bottom). Like this:
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget .../>
</item>
<item row="1" column="0">
<widget .../>
</item>
...
</layout>
Note that the third row comes before the first, which means in the generated code (and also when loading ui dynamically) the widget from the third row will be added first and will come first in the tab order.
Here's the XLST you can use on a ui file to "fix" the tab order, it removes all manually set tab stops and arranges xml items in visual order.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
<!-- Copy everything -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="layout">
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<!-- Sort layout items in the visual order -->
<xsl:sort select="@row" data-type="number"/>
<xsl:sort select="@column" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="tabstops">
<!-- Remove (i.e. do not copy) manual tab stops -->
</xsl:template>
</xsl:stylesheet>
Detecting but not fixing the problem is a bit harder, because manually set tab stops must be taken into account. Basic algorithm is as follows:
- Build the "raw" tab order by walking xml depth-first and collecting widget names and associated item's row and column (when present) and layout name in a list.
- Augment the raw order with manual tab stops, i.e. rearrange the list according to
<tabstops>
section in the xml, one pair at a time (like QWidget.setTabOrder
does it).
- Scan the list and check then all rows and columns are in order (independently for each layout name).