Добрый день!
Суть вопроса такая: был QTreeWidget - хороший высокоуровневый класс для работы с деревом в UI. Все было хорошо. Но понадобилось сделать многопоточность в приложении, чтобы пользователь не видел как приложение "висит" пока выполняет работу, а видел что то вроде прогрессбара и т.п. - вообщем один поток UI, один обработка данных.
К сожалению я не знаю, возможно ли сделать отправку item`ов QTreeWidgetItem* из другого потока (не ui). Дело в том, что при создании, QTreeWidgetItem* требует указать parent item, т.е. элемент в UI QTreeWidget. Поток данных о нем, естественно, не знает. А можно ли создать не привязанное к ui "дерево" QTreeWidgetItems? Я такого способа не нашел, поэтому пришлось использовать QTreeView:
Есть код, который работал в QTreeWidget и должен работать в QTreeView - а точнее его "модельной" частью - 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 );
}
}
И, возможно, код работал был, если бы вызывался при клике на каждый item. Но вызывается он только при клике на item`ы самого верхнего уровня (2 и3 уровни не срабатывает).
Item`ы добавляю так:
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);
Всего меня мучает 2 вопроса:
1) можно ли все таки как то передать "модель" или
QList<QTreeWidgetitem*>
из потока, работающего с данными в поток UI? (не хочется реализовывать "заново" стандартное поведение для QTreeView).
2) Если все таки нужно делить Model & View - то почему emit itemChanged вызывается только при изменении состояния (checkbox state changed) элементов верхнего уровня, на 2 и 3 не реагирует? Флаги вроде установлены для элементов, модель вроде правильная, отображается норм. itemChanged отправляется при изменении состояния любого item`а, код работал нормально, проверен ... как побороть, посоветуйте!
Всем заранее благодарен)
UPD: все дело в том, что itemChanged(QStandardItem*) вызывается не каждый раз как данные item`а изменились, хотя должен. Возможно, причина этого в том, что я создаю "дерево" через
treeView->appendRows(QList<QStandardItem*>).
В чем разница не понимаю) задача же типовая ... и решения нигде не нашел пока. Если предположение верно, то как создать QTreeView c QStandardItem с несколькими уровнями вложенности, может есть пример у кого? (в хелпе смотрел, но так и не понял как создать, допустим, три айтема у которого вложенные еще по 3 айтема и у них еще по 3))?