PDA

View Full Version : QTreeWidget::topLevelItem() results in seg fault.



johnny_sparx
22nd March 2006, 23:23
Originally, I posted about a problem I was having, but got no response:

I had a QTreeView and wanted to change the color of one of the entries in the view. I opted to change the QTreeView into a QTreeWidget and called QTreeView::setModel() to set my model to match the view.

While the model-view interface works fine, I seem to get a segmentation fault when I do the following in a member function:


void DatabaseTreeWidget::Update_Tree_From_Flags()
{
QTreeWidgetItem *X;

X = topLevelItem(0);
X->setTextColor(1,QColor(Qt::darkGreen));
}

Why does this happen? I want to change the color of the top level tree item, but am clearly having difficulty.

wysota
22nd March 2006, 23:25
So are you using a QTreeView object or QTreeWidget?

johnny_sparx
22nd March 2006, 23:27
I was using a QTreeView, but am now using QTreeWidget.

wysota
22nd March 2006, 23:29
So... why are you talking about a model?

Anyway, did you check if X!=0?

johnny_sparx
22nd March 2006, 23:38
I am using a model with this view.

QTreeWidget inherits QTreeView. Since QTreeView was limited in what it could do, I changed it to a QTreeWidget calling QTreeView::setModel() where appropriate. This section works like a charm, or at least I can see/manipulate the model in the view without a problem.

As for checking if X!=0.... I commented out the setTextColor() line, (Line 6.) and see that Line 5 is the offending execution. Any further insight?

wysota
22nd March 2006, 23:55
Did you notice that setModel() in QTreeWidget is made private? It is not done this way without a reason, you know...

The mismatch between the model and the item approach probably cause the segfault.

In what way is the model approach limited? It has exactly the same capabilities like the item one (especially given the fact that item based widgets are emulated by using an internal model representation).

For example the code you pasted here in the model approach looks like so:


void DatabaseTreeView::Update_Tree_From_Flags(){
QModelIndex ind = model()->index(0,0);
model()->setData(ind, Qt::TextColorRole, Qt::darkGreen);
}

johnny_sparx
23rd March 2006, 16:39
I switched back to QTreeView to give it another shot.

Now, I am trying your suggestion (the code section you listed) and do not seem to be getting any sucess. The tree view comes up as before, after the model has been set, and thre is no change in color. As far as I can tell, your suggestion should be straightforward - so why is this not working? Do I need to refresh the view somehow?

johnny_sparx
23rd March 2006, 17:38
I am now suspecting that it is in fact my model that is not allowing for the color change but am not sure. Could this be possible? Here is my simple implementation, with some irrelevant stuff removed:


InternalScanDatabase::InternalScanDatabase(QObject *parent)
: QAbstractItemModel(parent)
{
// Set up the root of the database.
QList<QVariant> rootData;
rootData<<"Scan Directory";//<<"File Path";
rootItem = new ScanDatabaseItem(rootData);
// Make the root the start of the database list.
Database<<rootItem;
}

InternalScanDatabase::~InternalScanDatabase()
{
delete rootItem;
Temp.close(); // Debugging only.
}

int InternalScanDatabase::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return static_cast<ScanDatabaseItem*>(parent.internalPointer())->columnCount();
else
return rootItem->columnCount();
}

QVariant InternalScanDatabase::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

if (role != Qt::DisplayRole)
return QVariant();

ScanDatabaseItem *item = static_cast<ScanDatabaseItem*>(index.internalPointer());

return item->data(index.column());
}

Qt::ItemFlags InternalScanDatabase::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;

return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant InternalScanDatabase::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return rootItem->data(section);

return QVariant();
}

QModelIndex InternalScanDatabase::index(int row, int column, const QModelIndex &parent)
const
{
ScanDatabaseItem *parentItem;

if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<ScanDatabaseItem*>(parent.internalPointer());

ScanDatabaseItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}

QModelIndex InternalScanDatabase::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();

ScanDatabaseItem *childItem = static_cast<ScanDatabaseItem*>(index.internalPointer());
ScanDatabaseItem *parentItem = childItem->parent();

if (parentItem == rootItem)
return QModelIndex();

return createIndex(parentItem->row(), 0, parentItem);
}

int InternalScanDatabase::rowCount(const QModelIndex &parent) const
{
ScanDatabaseItem *parentItem;

if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<ScanDatabaseItem*>(parent.internalPointer());

return parentItem->childCount();
}

wysota
23rd March 2006, 20:46
You need to have data() and setData() properly implemented to retrieve and store those parameters accordingly.

johnny_sparx
24th March 2006, 17:51
Hello again,

My problem is not yet resolved, but feel I am getting closer thanks to your help. In my model, I have done the following (sloppy) coding to see what would happen:


QVariant InternalScanDatabase::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

//if (role != Qt::DisplayRole)
// return QVariant();

if (role == Qt::TextColorRole)
return Qt::darkGreen;

if (role== Qt::DisplayRole)
{
ScanDatabaseItem *item = static_cast<ScanDatabaseItem*>(index.internalPointer());
return item->data(index.column());
}
else return QVariant();
}

I was thinking that the view class (QTreeView) would call this function with role = Qt::TextColorRole. In this case, I would unconditionally return Qt::darkGreen. What I was expecting was that the entire tree would be green. In reality, this did not happen. Any further insight?

wysota
24th March 2006, 18:06
It should work, at least if you don't use a custom delegate.

Ah... sure it doesn't work :) The attached example shows why. Qt::darkGreen is an int, not a QColor -- you need to make sure QColor is returned. Look at the attachment for details.

johnny_sparx
24th March 2006, 19:47
ah HA! :D

Got it. Thanks for everyone's help. It worked like a charm. I also made space in the nodes of my data structrure's tree to store the color. Now I can use setData and modify the role appropriately so that color's can be changed. This was a very useful thing and I learned much about MVP.:cool:

J.