Search code examples
qtsignals-slotsqmap

Creating a QLineEdit Widget Which Knows Which Tab It Belongs To


Question

How do I make it so that a widget knows which tab "address" it belongs to with the eventual purpose of propagating this information to a signal?

Background

All of this below code is done in the same object hence why I can use this as a loopback signal.

There is a settings file which will create a "tree" of tabs e.g

Sh(0) -> Be(0) -> Fe(0)
Sh(0) -> Be(1) -> Fe(0)
Sh(1) -> Be(0) -> Fe(1)

This would create a Sh 0 tab which contains a tab displaying Be 0 and a tab displaying Be 1. Be 0 in this branch would contain a final tab of Fe 0. And so on.

I've simplified it here, but the final version will include many more branches. I'm not bothering with the visitor class method for this example to keep it simple, instead I mapped all of the tabs to a QMap so e.g if you wanted to access the feTab from the first example above, the tab is created then accessed like this:

QTabWidget *feTab = new QTabWidget(this);
m_mapTab[idSh][idBe] = feTab;

QGridLayout *lo = new QGridLayout;
m_mapTab[idSh][idBe][idFe]->addLayout(lo)
m_mapLo[idSh][idBe][idFe] = lo;

The Problem

Great, so I assigned all of the tabs to a map and populated the Fe tab with a QGridLayout. I then looped through the registers I wanted to add by adding a QLineEdit to the layout.

What is in the settings file doesn't concern the problem. This is just done for each branch of the tree, the settings file creates a number of predefined registers with predefined values. I would like the QLineEdit to know which branch it came from when edited.

for (auto& kv : nSettings)
{
    ... //code to work out row and column + make it all look nice + add a layout
    QLineEdit *lineRegValue = new QLineEdit(this);
    lineRegValue->setText(value[kv]);
    clo->addWidget(lineRegValue);
    m_mapLo[idSh][idBe][idFe]->addLayout(clo, row, column);
}

My Attempt

So I've played around with assigning signals to the QLineEdit when I created it like so:

connect(lineRegValue, SIGNAL(textEdited(QString)),
                    this, SLOT(onValueChanged(QString)));

Which I've hooked up with a method which outputs the changes in a qDebug(). The problem is I'm unsure how to tell the system the tree address it belonged to. I could use this information to e.g create a new settings file with the user's changed values. Any ideas?

My first thought was to have a look at the QLineEdit which was selected and try to read the tabs which were currently in focus to work out the address though I'm unsure how to do this and if there is a simpler way.


Solution

  • One of possible common solution:

    int GetTabIndex( QTabWidget *tw, QWidget *anyWidget )
    {
      Q_ASSERT( tw != nullptr );
      QWidget *p = anyWidget;
      while ( p != nullptr )
      {
        if ( p->parentWidget() == tw )
          return tw->indexOf( p );
        p = p->parentWidget();
      }
      return -1;
    }
    
    //...
    QLineEdit *le = /*some line editor, on a tab*/;
    QTabWidget *tw = /*Your tab widget*/
    
    int tabIndex = GetTabIndex( tw, le ); // index of tab, where line editor is located;
    

    You may apply it recursively to get all indexes of your child tabs.

    QLineEdit *le = /*some line editor, on a tab*/;
    QTabWidget *root = /*Root tab*/
    const int x = GetTabIndex( root, le );
    QTabWidget *tabChild1 = root->widget( x );
    const int y = GetTabIndex( tabChild1 , le );
    QTabWidget *tabChild2 = tabChild1 ->widget( y );
    const int z = GetTabIndex( tabChild2 , le );
    
    yourArray[x][y][z] ...