0

I am trying to make a QTreeWidget such that each row contains a series of comboboxes. Depending on how the user interacts with the comboboxes I would like certain comboboxes to becomes line edits and some to become buttons.

It was suggested here that a QStackedWidget would serve my needs and its done a pretty good job except now I need a way to alter the QStackedWidget that is next to the one that contains the combobox sending me an indexChanged signal. (Basically I want to change the neighboring QStackWidgets index)

I thought that I would be able to simply store the QStackWidget in the childItem using setData and then retrieve it inside the indexChanged slot but for some reason it appears the QStackWidget is not set to the childItems data.

Any help is appreciated.

This is where I orginally setup my QTreeWidget and its Items

    QTreeWidgetItem *childItem = new QTreeWidgetItem(itemParent);



    QVariant itemParentVariant,widgetParentVarient;
    widgetParentVarient.setValue(widgetParent);
    itemParentVariant.setValue(itemParent);
    QList<QVariant> stackWidgetList;
    uint cycleSetup;
    for(cycleSetup = 0;cycleSetup < methodBlocks.at(rowType).size()+2;cycleSetup++)
    {

            QComboBox *itemComboBox = new QComboBox;
            itemComboBox->setProperty("rowType", rowType);
            itemComboBox->setProperty("row", 0);
            itemComboBox->setProperty("column",cycleSetup);
            itemComboBox->setProperty("widgetParent",widgetParentVarient);
            itemComboBox->setProperty("itemParent",itemParentVariant);
            itemComboBox->addItems(methodBlocks.at(0).at(cycleSetup));
            QObject::connect(itemComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnComboIndexChanged(const QString&)));
            QLineEdit *itemLineEdit = new QLineEdit;
            QPushButton *itemButton = new QPushButton;
            itemButton->setText("Reset");
            QComboBox *timeComboBox = new QComboBox;
            timeComboBox->setProperty("rowType", rowType);
            timeComboBox->setProperty("row", 0);
            timeComboBox->setProperty("column",cycleSetup);
            timeComboBox->setProperty("widgetParent",widgetParentVarient);
            timeComboBox->setProperty("itemParent",itemParentVariant);
            timeComboBox->addItems(QString("Seconds;MilliSeconds;Reset").split(";"));
            QStackedWidget *masterItemWidget = new QStackedWidget;
            masterItemWidget->addWidget(itemLineEdit);
            masterItemWidget->addWidget(itemComboBox);
            masterItemWidget->addWidget(itemButton);
            masterItemWidget->addWidget(timeComboBox);
            masterItemWidget->setCurrentIndex(1);
            QVariant stackParent;
            stackParent.setValue(masterItemWidget);
            itemComboBox->setProperty("stackParent",stackParent);
            childItem->setData(0,Qt::UserRole,stackParent);
            stackWidgetList.push_back(stackParent);
            widgetParent->setItemWidget(childItem,cycleSetup,masterItemWidget);
            itemParent->addChild(childItem);
    }

And this is inside the slot where I am trying to retrieve the data (The QStackWidget)

                QStackedWidget *itemMaster = combo->property("stackParent").value<QStackedWidget*>(); //this works
                itemMaster->setCurrentIndex(0);
                QTreeWidget *widgetParent = combo->property("widgetParent").value<QTreeWidget*>();

                QTreeWidgetItem *parentItem = combo->property("itemParent").value<QTreeWidgetItem*>();
                QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem);


                QList<QVariant> stackList = childItem->data(0,Qt::UserRole).value<QList<QVariant>>(); //this doesnt
                QStackedWidget *itemsibMaster = childItem->data(0,Qt::UserRole).value<QStackedWidget*>(); //neither does this
                itemsibMaster->setCurrentIndex(2);

EDIT:

I've tried to set the data like this

            QFrame *stackFrame = new QFrame;
            QStackedWidget *masterItemWidget = new QStackedWidget(stackFrame);
            masterItemWidget->addWidget(itemLineEdit);
            masterItemWidget->addWidget(itemComboBox);
            masterItemWidget->addWidget(itemButton);
            masterItemWidget->addWidget(timeComboBox);
            masterItemWidget->setCurrentIndex(1);
            QVariant stackParent;
            stackParent.setValue(masterItemWidget);
            itemComboBox->setProperty("stackParent",stackParent);
            QVariant frameVariant;
            frameVariant.setValue(stackFrame);
            childItem->setData(0,Qt::UserRole,frameVariant);
            stackWidgetList.push_back(stackParent);
            widgetParent->setItemWidget(childItem,cycleSetup,masterItemWidget);
            itemParent->addChild(childItem);

And retrieve it like this

                QStackedWidget *itemMaster = combo->property("stackParent").value<QStackedWidget*>();
                itemMaster->setCurrentIndex(0);
                QTreeWidget *widgetParent = combo->property("widgetParent").value<QTreeWidget*>();

                QTreeWidgetItem *parentItem = combo->property("itemParent").value<QTreeWidgetItem*>();
                QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem);


                QFrame *frameObject = childItem->data(0,Qt::UserRole).value<QFrame*>();
                //QList<QVariant> stackList = childItem->data(0,Qt::UserRole).value<QList<QVariant>>();
                QStackedWidget *itemFrameMaster = frameObject->findChild<QStackedWidget*>();
                if(itemFrameMaster)
                {
                    qDebug() << "itemFrame Exists";

                }
                else
                {
                    qDebug() << "itemFrame is NULL";//It goes to here
                }

So I'm still unable to get the desired functionality.

Reginald Marr
  • 387
  • 2
  • 16
  • Don't use a `QTreeWidget` for something so complex. Use a `QTreeView` with a model and item delegate instead. It's much more flexible and allows you to keep your code manageable. – D Drmmr Feb 23 '18 at 22:18
  • To be honest, I did try to use a QTreeView however I got a bit confused with the example that had no delegate class and instead a treeitem and treeview class. I'll try taking another crack at it, I'm starting to think this could be done with the QTreeView and just using the item delegate class. – Reginald Marr Feb 23 '18 at 22:36

2 Answers2

0

Check if it works.

As stacked widget QStackedWidget derived from QFrame, Create a Frame object and add your stacked widget to it. Set the frame to your child item.

QFrame *stackFrame = new QFrame(Parent);

QStackedWidget *masterItemWidget  = new QStackedWidget(stackFrame);

While querying first query for the frame and get the stacked widget child from it.

QStackedWidget *stackedWidget = FrameObject->findChild<QStackedWidget *>();
Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34
  • So I just tried this QFrame stackFrame = new QFrame(childItem); QStackedWidget *masterItemWidget = new QStackedWidget(stackFrame); But that gave me a few errors regarding no function to call (QFrame::QFrame(QTreeWidgetItem&)) Am I missing something? – Reginald Marr Feb 23 '18 at 19:49
  • See the edit, I'm not sure if I'm misinterpreting your suggestion but so far no luck. – Reginald Marr Feb 23 '18 at 21:46
0

Alright so I managed to get the functionality that I was after, so in case anyone else is trying to do this here's the fix.

Essentially everything I had done before was correct except for one error.

When retrieving the data stored in the comboboxes child I had originally gotten that child here.

            QTreeWidgetItem *parentItem = combo->property("itemParent").value<QTreeWidgetItem*>();
            QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem);

The issue was that since the parentItem had more than one child (I suppose in this case the minimum is two children) I was not referencing the correct child. This issue was solved by creating a custom combobox property which held the child rather than the parent (parent can be derived from the parent more accurately than visa versa).

Now where I populate the QTreeWidget with combobox items looks like this.

    QTreeWidgetItem *childItem = new QTreeWidgetItem(itemParent);

    QVariant childItemVariant,widgetParentVarient;
    widgetParentVarient.setValue(widgetParent);
    childItemVariant.setValue(childItem);
    uint cycleSetup;
    for(cycleSetup = 0;cycleSetup < methodBlocks.at(rowType).size();cycleSetup++)
    {
        if(cycleSetup < methodBlocks.at(rowType).size())
        {
            QComboBox *itemComboBox = new QComboBox;
            itemComboBox->setProperty("rowType", rowType);
            itemComboBox->setProperty("row", 0);
            itemComboBox->setProperty("column",cycleSetup);
            itemComboBox->setProperty("widgetParent",widgetParentVarient);
            itemComboBox->setProperty("childItem",childItemVariant);
            itemComboBox->addItems(methodBlocks.at(0).at(cycleSetup));
            QObject::connect(itemComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnComboIndexChanged(const QString&)));
            QLineEdit *itemLineEdit = new QLineEdit;

            QFrame *stackFrame = new QFrame;
            QStackedWidget *masterItemWidget = new QStackedWidget(stackFrame);
            masterItemWidget->addWidget(itemLineEdit);
            masterItemWidget->addWidget(itemComboBox);
            //masterItemWidget->addWidget(timeComboBox);
            masterItemWidget->setCurrentIndex(1);
            QVariant stackParent;
            stackParent.setValue(masterItemWidget);
            itemComboBox->setProperty("stackParent",stackParent);
            itemComboBox->setProperty("cycleSetupIT",cycleSetup);
            QVariant frameVariant;
            frameVariant.setValue(stackFrame);
            childItem->setData(cycleSetup,Qt::UserRole,stackParent);
            widgetParent->setItemWidget(childItem,cycleSetup,masterItemWidget);
            itemParent->addChild(childItem);
        }

    }

}

And the code in the slot where I get the data from the childItem (which holds the combobox) looks like this.

                QTreeWidget *widgetParent = combo->property("widgetParent").value<QTreeWidget*>();
                widgetParent->setColumnCount(6);
                QTreeWidgetItem *childItem = combo->property("childItem").value<QTreeWidgetItem*>();
                QTreeWidgetItem *parentItem = childItem->parent();

                int rowType = combo->property("rowType").toInt();
                int cycleIT = combo->property("cycleSetupIT").toInt();
                int offset = 0;

                QStackedWidget *itemFrameMaster = childItem->data(cycleIT+1,Qt::UserRole).value<QStackedWidget*>();
                itemFrameMaster->setCurrentIndex(0);

Hope this helps. Also if anyone knows how to get the number of data items in a QStandardItem::data() that'd be great albeit not super critical.

Cheers!

Reginald Marr
  • 387
  • 2
  • 16