W
W
whoami?root root_toor2016-06-06 12:37:26
Qt
whoami?root root_toor, 2016-06-06 12:37:26

Qt QTreeView group highlighting checkbox items by itemChanged?

Good afternoon!
The essence of the question is this: there was a QTreeWidget - a good high-level class for working with a tree in the UI. Everything was fine. But it was necessary to make multithreading in the application so that the user does not see how the application "hangs" while doing work, but sees something like a progress bar, etc. - in general, one UI thread, one data processing.
Unfortunately, I don't know if it's possible to send QTreeWidgetItem* items from another thread (not ui). The matter is that at creation, QTreeWidgetItem* demands to specify parent item, ie. element in a UI QTreeWidget. The data stream, of course, does not know about it. Is it possible to create a "tree" QTreeWidgetItems that is not attached to the ui? I did not find such a way, so I had to use QTreeView:
There is a code that worked in QTreeWidget and should work in QTreeView - or rather its "model" part - QStandardItem*:

Qt::CheckState state = item->checkState();
  if ( state == Qt::Checked || state == Qt::Unchecked ) {
    for ( int i = 0; i < item->rowCount(); i++ ) {
      QStandardItem* child = item->child(i);
      if ( child->isCheckable() && child->checkState() != state )
        child->setCheckState(state);
    }
  }

  QStandardItem* parent = item->parent();
  if ( parent && parent->isCheckable() ) {
    state = parent->child(0)->checkState();
    if ( state == Qt::PartiallyChecked )
      parent->setCheckState( state );
    else {
      int i = 1;
      while ( i < parent->rowCount() && parent->child(i)->checkState() == state )
        i++;
      if ( i != parent->rowCount() ) 
        state = Qt::PartiallyChecked;
      parent->setCheckState( state );
    }				
  }

And, perhaps, the code would have worked if it had been called when clicking on each item. But it is called only when clicking on items of the highest level (levels 2 and 3 do not work).
I add Items like this:
QStandardItemModel* model = new QStandardItemModel;
QStandardItem* parentItem = model->invisibleRootItem();
QList<QStandardItem*> itemList1;
QList<QStandardItem*> itemList2;
QList<QStandardItem*> itemList3;
QStandardItem* item1 =new QStandardItem;
QStandardItem* item2 =new QStandardItem;
QStandardItem* item3 =new QStandardItem;

for(;;)  // example
{
    QStandardItem* item1 =new QStandardItem(LPCWSTR2QString(mbxItem->Text));
    item1->setToolTip(QString::fromStdWString(itemPath0.bstrVal));
    item1->setFlags(item1->flags() | Qt::ItemIsUserCheckable);
    item1->setCheckState(Qt::Unchecked);
    itemList1 << item1;
}

parentItem->appendRows(itemList1);
itemList1.clear();
// и т.д. - всего три вложенных списка, отображается модель нормально
ui.treeView->setModel(model);

// и коннект:
QStandardItemModel* model = read2UI();
bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onItemChanged(QStandardItem*)));
Q_ASSERT(ok);
update(model);

In total, I am tormented by 2 questions:
1) is it possible to somehow transfer the "model" or QList<QTreeWidgetitem*>from the thread that works with the data to the UI thread? (I don't want to "re-implement" the standard behavior for QTreeView).
2) If you still need to share Model & View - then why emit itemChanged is called only when the state changes (checkbox state changed) of the top-level elements, does not react to 2 and 3? The flags seem to be set for the elements, the model seems to be correct, the norms are displayed. itemChanged is sent when the state of any item changes, the code worked fine, checked ... how to overcome, please advise!
Thank you all in advance)
UPD: the whole point is that itemChanged(QStandardItem*) is not called every time the item's data has changed, although it should. Perhaps the reason for this is that I create a "tree" through treeView->appendRows(QList<QStandardItem*>).
I don't understand what the difference is) the task is typical ... and I haven't found a solution anywhere yet. If the assumption is correct, then how to create a QTreeView with QStandardItem with several levels of nesting, can anyone have an example? (I looked in the help, but did not understand how to create, for example, three items that have 3 more items nested and they have 3 more each))?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
W
whoami?root root_toor, 2016-06-14
@1q2w1q2w

Issue resolved.
The thing is that in qt you need to add items to the parent on each "iteration", and not a list.
Those. create a model

parentItem->appendRows(itemList1);
, and so:
for (int i = 0; i < 3; ++i)
{
    item1 = new QStandardItem;
    item1->setText("item1-" + QString::number(i));
    parentItem->appendRow(item1);

    for (int i = 0; i < 3; ++i)
    {
        item2 = new QStandardItem;
        item2->setText("item2-" + QString::number(i));
        item1->appendRow(item2);

        for (int i = 0; i < 3; ++i)
        {
            item3 = new QStandardItem;
            item3->setText("item3-" + QString::number(i));
            item2->appendRow(item3);
        }
    }
}

Then itemChanged is emitted on every data change, including in child elements..

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question