Hi all,
I am a newbie using Qt and I am stuck with this problem. Let me resume ...
I am trying to display a tree containing nodes representing resource items.
Those items have several attributes (image id, ...) and booleans such as resourceVisible [true|false].
I am able to display the tree with icons representing my booleans (using a delegate). I also use a QSortFilterProxyModel to filter the rows.
Now I would like to update the model when the user click on the icon representing the boolean resourceVisible. But I can't have it work :-\
Here is my program
Structure defining a resource:
struct ResourceTreeItem {
ResourceTreeItem(std::string resourceID=""):m_resourceID(resourceID), m_resourceVisible(true), m_contentVisible(true),
m_boundaryBoxVisible(true), m_mosaicked(true), m_IDVisible(true) {}
ResourceTreeItem(const ResourceTreeItem& copy): m_resourceID(copy.m_resourceID), m_resourceVisible(copy.m_resourceVisible), m_contentVisible(copy.m_contentVisible),
m_boundaryBoxVisible(copy.m_boundaryBoxVisible), m_mosaicked(copy.m_mosaicked), m_IDVisible(copy.m_IDVisible) {}
std::string m_resourceID;
bool m_resourceVisible;
bool m_contentVisible;
bool m_boundaryBoxVisible;
bool m_mosaicked;
bool m_IDVisible;
};
struct ResourceTreeItem {
ResourceTreeItem(std::string resourceID=""):m_resourceID(resourceID), m_resourceVisible(true), m_contentVisible(true),
m_boundaryBoxVisible(true), m_mosaicked(true), m_IDVisible(true) {}
ResourceTreeItem(const ResourceTreeItem& copy): m_resourceID(copy.m_resourceID), m_resourceVisible(copy.m_resourceVisible), m_contentVisible(copy.m_contentVisible),
m_boundaryBoxVisible(copy.m_boundaryBoxVisible), m_mosaicked(copy.m_mosaicked), m_IDVisible(copy.m_IDVisible) {}
std::string m_resourceID;
bool m_resourceVisible;
bool m_contentVisible;
bool m_boundaryBoxVisible;
bool m_mosaicked;
bool m_IDVisible;
};
To copy to clipboard, switch view to plain text mode
A node (based on Editable Tree Model Example):
class ResourceTreeNode {
public:
ResourceTreeNode(const ResourceTreeItem& data, ResourceTreeNode* parent = 0);
~ResourceTreeNode();
bool setData(int column, const QVariant& value);
ResourceTreeNode* child(int number);
ResourceTreeNode* parent();
int childCount() const;
int childNumber() const;
bool insertChildren(int position, int count, ResourceTreeItem resourceTreeItem);
bool removeChildren(int position, int count);
private:
ResourceTreeNode* m_parent;
ResourceTreeItem m_resourceTreeItem;
QList<ResourceTreeNode*> m_childrens;
};
class ResourceTreeNode {
public:
ResourceTreeNode(const ResourceTreeItem& data, ResourceTreeNode* parent = 0);
~ResourceTreeNode();
QVariant data(int column) const;
bool setData(int column, const QVariant& value);
ResourceTreeNode* child(int number);
ResourceTreeNode* parent();
int childCount() const;
int childNumber() const;
bool insertChildren(int position, int count, ResourceTreeItem resourceTreeItem);
bool removeChildren(int position, int count);
private:
ResourceTreeNode* m_parent;
ResourceTreeItem m_resourceTreeItem;
QList<ResourceTreeNode*> m_childrens;
};
To copy to clipboard, switch view to plain text mode
A custom model (also based on Editable Tree Model Example):
{
Q_OBJECT
public slots:
public:
static const int NB_COLUMN = 6;
void setRootNode(ResourceTreeNode* node);
QVariant headerData
(int section, Qt
::Orientation orientation,
int role
= Qt
::DisplayRole) const;
private:
ResourceTreeNode* getNode(const QModelIndex& index) const;
ResourceTreeNode* m_root;
};
class QResourceTreeModel : public QAbstractItemModel
{
Q_OBJECT
public slots:
void itemClicked(const QModelIndex &index);
public:
static const int NB_COLUMN = 6;
QResourceTreeModel(QObject *parent = 0) : QAbstractItemModel(parent), m_root(0) {}
QResourceTreeModel(ResourceTreeNode* root, QObject *parent = 0) : QAbstractItemModel(parent), m_root(root) {}
void setRootNode(ResourceTreeNode* node);
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex& index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
private:
ResourceTreeNode* getNode(const QModelIndex& index) const;
ResourceTreeNode* m_root;
};
To copy to clipboard, switch view to plain text mode
Basically I connect the signal clicked(const QModelIndex &) to my slot itemClicked(const QModelIndex &index) so I can update the corresponding cell in the tree.
Here is some key methods ...
QVariant ResourceTreeNode
::data(int column
) const {
switch (column) {
case 0:
return QVariant(m_resourceTreeItem.
m_resourceVisible);
case 1:
return QVariant(m_resourceTreeItem.
m_resourceID.
c_str());
case 2:
return QVariant(m_resourceTreeItem.
m_contentVisible);
case 3:
return QVariant(m_resourceTreeItem.
m_boundaryBoxVisible);
case 4:
return QVariant(m_resourceTreeItem.
m_mosaicked);
case 5:
return QVariant(m_resourceTreeItem.
m_IDVisible);
default:
}
}
QVariant ResourceTreeNode::data(int column) const
{
switch (column) {
case 0:
return QVariant(m_resourceTreeItem.m_resourceVisible);
case 1:
return QVariant(m_resourceTreeItem.m_resourceID.c_str());
case 2:
return QVariant(m_resourceTreeItem.m_contentVisible);
case 3:
return QVariant(m_resourceTreeItem.m_boundaryBoxVisible);
case 4:
return QVariant(m_resourceTreeItem.m_mosaicked);
case 5:
return QVariant(m_resourceTreeItem.m_IDVisible);
default:
return QVariant();
}
return QVariant();
}
To copy to clipboard, switch view to plain text mode
bool ResourceTreeNode::setData(int column, const QVariant& value) {
if (column < 0 || column >= 5) {
return false;
}
switch (column) {
case 0:
m_resourceTreeItem.m_resourceVisible = value.toBool();
case 1:
m_resourceTreeItem.m_resourceID = value.toString().toStdString();
case 2:
m_resourceTreeItem.m_contentVisible = value.toBool();
case 3:
m_resourceTreeItem.m_boundaryBoxVisible = value.toBool();
case 4:
m_resourceTreeItem.m_mosaicked = value.toBool();
case 5:
m_resourceTreeItem.m_IDVisible = value.toBool();
default:
break;
}
return true;
}
bool ResourceTreeNode::setData(int column, const QVariant& value) {
if (column < 0 || column >= 5) {
return false;
}
switch (column) {
case 0:
m_resourceTreeItem.m_resourceVisible = value.toBool();
case 1:
m_resourceTreeItem.m_resourceID = value.toString().toStdString();
case 2:
m_resourceTreeItem.m_contentVisible = value.toBool();
case 3:
m_resourceTreeItem.m_boundaryBoxVisible = value.toBool();
case 4:
m_resourceTreeItem.m_mosaicked = value.toBool();
case 5:
m_resourceTreeItem.m_IDVisible = value.toBool();
default:
break;
}
return true;
}
To copy to clipboard, switch view to plain text mode
void QResourceTreeModel
::itemClicked(const QModelIndex &index
) { if ((index.isValid()) && (index.column() != 1)) {
/* The idea is to store false if it was true or true if it was false */
ResourceTreeNode* node = getNode(index);
bool result
= node
->setData
(index.
column(),
QVariant(!node
->data
(index.
column()).
toBool()));
if (result) {
emit dataChanged(index, index);
}
}
}
void QResourceTreeModel::itemClicked(const QModelIndex &index) {
if ((index.isValid()) && (index.column() != 1)) {
/* The idea is to store false if it was true or true if it was false */
ResourceTreeNode* node = getNode(index);
bool result = node->setData(index.column(), QVariant(!node->data(index.column()).toBool()));
if (result) {
emit dataChanged(index, index);
}
}
}
To copy to clipboard, switch view to plain text mode
My problem comes from the method ResourceTreeNode::getNode(index) in QResourceTreeModel::itemClicked(index). The returned node does not contain any ResourceTreeItem? I used a log in getNode() and the problem only happen when I call getNode() from my slot. Somebody have any hints?
Bookmarks