views:

93

answers:

2

Typically, a dialog wishes to have tab navigation proceed in an orderly fashion through a dialog that roughly corresponds to the order of reading a book.

When new fields are added to a dialog by engineers on a team, the new widgets can often not be inserted in tab correct order.

Can anyone think of a way to automate the detection of out of tab navigation order widgets within a dialog?

+1  A: 

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"&gt;
    <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).
Nikita Nemkin
A: 

It sounds like you have a .ui file with a QTabWidget and a multitude of pages all in on .ui file. I would suggest splitting things up a little bit more. Implement each Tab as a widget by itself, this can be in the desginer too. Then you have two options for the TabWidget itself. Create all the tabs in the designer and promote the content to the widget class that needs to go on that page. Or leave the TabWidget completely empty and populate it in code with the appropriate subwidgets.

Harald Scheirich