@1q2w1q2w
sudo make install

Qt QTreeView групповое выделение элементов checkbox по itemChanged?

Добрый день!
Суть вопроса такая: был 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))?
  • Вопрос задан
  • 1976 просмотров
Решения вопроса 1
@1q2w1q2w Автор вопроса
sudo make install
Вопрос решен.
Все дело в том, что в qt нужно добавлять item`ы к parent`у на каждой "итерации", а не списком.
Т.е. создавать модель не
parentItem->appendRows(itemList1);
, а так:
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);
        }
    }
}

Тогда itemChanged эмитится на каждое изменение данных и в дочерних элементах в том числе..
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы