QModelIndex returns wrong InternalPointer - c++

I have an own Qt-Model class derieved from QAbstractTableModel. By background data structure consists of Row, Column and Cell classes. So every Row has n Cells whose can bound to their belonging Column. The Cell carries the actual Grid-field-value, Background-Color, Font, etc...
My index-Method looks like this:
QModelIndex TableModel::index(int row, int column, const QModelIndex& parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
// modelData is my background data-structure-class
Cell* cell = modelData->Rows.at(row)->Cells.at(column); // retreiving the cell
if (cell != Q_NULLPTR)
return createIndex(row, column, cell); // Storing the Cell-object in every index
return QModelIndex();
}
Now, when the Grid accesses data I have the data-method like this:
QVariant TableModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
Cell* cell = static_cast<Cell*>(index.internalPointer()); // retreiving the Cell
// it works when I say
// Cell* cell = modelData->Rows.at(index.row()).Cells.at(index.column());
switch (role)
{
case Qt::DisplayRole:
...
// return the value
break;
case Qt::DecorationRole: return cell->Column->Icon;
case Qt::BackgroundRole: return cell->Column->BackgroundColor;
case Qt::TextAlignmentRole: return static_cast<qint32>(cell->Column->TextAlignment);
}
return QVariant();
}
My problem is, that inside the data-function the internal-pointer (static_cast<Cell*>(index.internalPointer())) always returns the same Cell (row 0, column 0) and not the Cell according to the row and column coordinate. Because of this my grid has created all rows and columns but their cell-value is always the same because it only uses the Cell from row 0 and column 0 (example below to visualize the problem).
Retreiving the Cell* via modelData->Rows.at(index.row()).Cells.at(index.column()) works though, but I really have to use the internalPointer because I would like to extend my model with hierarchy (parent-child-relations like a tree) or use the actual Cell* elsewhere.

Related

Change what column of QTreeView displays expand/collapse icon

Qt version 4.8.4
I have a QTreeView that reflects a QAbstractItemModel-derived model. The model provides data in multiple columns. The expand/collapse icon for a row of the view is always displayed in the cell that is in the column that has a logical index of zero, even if that column has been moved so that it has a visual index other than zero.
Is QTreeView compelled to always draw the expand/collapse icon in logical column zero? Can that be customized, either via the QTreeView or the model?
The expand/collapse icon, along with all the other tree branching lines, is indeed compelled to always draw in logical column zero. In Qt/4.8.4/src/gui/itemviews/qtreeview.cpp, in the QTreeView::drawRow() method, it is hardcoded to only call QTreeView::drawBranches() if the headerSection (which contains the logical index of the column) is zero.
void QTreeView::drawRow( QPainter * painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
...
for ( int currentLogicalSection = 0; currentLogicalSection < logicalIndices.count(); ++currentLogicalSection )
{
int headerSection = logicalIndices.at(currentLogicalSection);
...
// If the zeroeth logical column, ...
if ( headerSection == 0 )
{
...
// ... draw tree branches and stuff.
drawBranches(painter, branches, index);
}
else
{
...
}
...
}
...
}

Change Row Label Start Index (vertical header) in QtableView

While displaying data, on a QTableView , due to an internal reason, i cannot display the first row and hence have to hide it, using
(qtableobj)->hideRow(0);
The problem is that, now the row labels start from 2.
How is it possible to start the index from 1, while keeping the first row hidden ?
Thanks.
You can try to involve the QSortFilterProxyModel that will filter out the first row in your model.
The code could look like:
class FilterModel : QSortFilterProxyModel
{
[..]
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
if (index.row() == 0) // The first row to filter.
return false;
else
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
}
Finally you need to set this model to your table view:
QTableView *table = new QTableView;
MyItemModel *sourceModel = new MyItemModel;
QSortFilterProxyModel *proxyModel = new FilterModel;
proxyModel->setSourceModel(sourceModel);
table->setModel(proxyModel);
UPDATE
Since the issue is in how the header view displays row numbers, here is the alternative solution which based on special handling of header data in the model:
class Model : public QAbstractTableModel
{
public:
[..]
virtual QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const
{
if (role == Qt::DisplayRole) {
if (orientation == Qt::Vertical) {
// Decrease the row number value for vertical header view.
return section - 1;
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
[..]
};
Set up the table view with the hidden first row.
QTableView *table = new QTableView;
Model *sourceModel = new Model;
table->setModel(sourceModel);
table->hideRow(0);
table->show();

how can i paint row with different color in QTreeWidget (Qt)

i have in my application that when i click on row i have the default blue row marked
but beside this blue color i what to paint the row in different color via function not depending on user clicked signal , in sort i need a function that i will pass the row index and it will paint the row in x color.
create a delegate function with an item role. set the item role in each tree item. Access the item in the paint event of tree delegate and paint the row accordingly.
For QStandardItem you can set the back ground role to your desired color.
void customSelect(const QModelIndex &index)
{
if( !index.isValid() )
return;
QStandardItemModel* myModel = dynamic_cast<QStandardItemModel*> ( index.model() );
if( !myModel )
return;
int row = index.row();
for( int col = 0 , colCount = myModel.columnCount(); col < colCount ; ++i)
{
QStandardItem *item = myModel.item( row, col );
item->setData(Qt::blue, Qt::BackgroundColorRole);
}
}

Displaying multiple icons in a single cell of a QTableView

I am writing a small gui app with QT4.5 in QtCreator.
The main screen on the app contains a QTreeView with two columns, the first is text the second is a group of icons. These icons represent the last few states of the item displayed in the row.
I am not sure what the best way to do this is. I have currently implemented this by generating a QPixmap the model's data() method.
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole || role == Qt::EditRole) {
switch(index.column()) {
case 0:
return item_.at(index.row()).title();
}
}
if (role == Qt::DecorationRole) {
switch(index.column()) {
case 1:
return makeImage(item_.add(index.row()).lastStates());
}
}
return QVariant();
}
QVariant MyModel::makeImage(const QList<MyState> &states) const
{
const int IconSize = 22;
QPixmap image(IconSize * states.size(), IconSize);
QPainter painter(&image);
painter.fillRect(0, 0, IconSize * count, IconSize, Qt::transparent);
for (int i = 0; i < states.size(); ++i) {
QIcon * icon = stateIcon(state.at(i));
icon->paint(&painter, IconSize * i, 0, IconSize, IconSize);
}
return image;
}
This works but for some small problems, the background which should be transparent is full of random noise, even filling this with a transparent colour does not fix it.
Second this does not seem very efficient, I am generating a new Image every time this is called, should I not just draw the icons onto the widget for the cell?
What is the best way to display multiple icons in a single cell?
I would create a custom delegate, based on a hbox, into which you can place all the pictures. Have a look at delegates in the Qt Documentation about model view programming.

Selecting an index in a QListView

This might be a stupid question, but I can't for the life of me figure out how to select the row of a given index in a QListView.
QAbstractItemView , QListView's parent has a setCurrentIndex(const QModelIndex &index). The problem is, I can't construct a QModelIndex with the row number I want since the row and column field of the QModelIndex has no mutators.
QTableView, which also inherits from QAbstractItemView has a selectRow(int row) function, why in the seven hells doesn't the QListView have this?
Good ol' windows forms has the SelectedIndex property on it's listviews.
This should help you get started
QModelIndex index = model->createIndex( row, column );
if ( index.isValid() )
model->selectionModel()->select( index, QItemSelectionModel::Select );
You construct the QModelIndex by using the createIndex(int row, int column) function of the model you gave to the view. QModelIndexes should only be used once, and must be created by the factory in the model.
My working sample at Qt4.8.0 (MSVC2010 Compiller) based on Michael Bishop
QStandardItemModel *Model = (QStandardItemModel *)this->ui->listView_OptionsCategories->model();
QModelIndex index = Model->index(this->ui->stackedWidget->currentIndex(), 0);
if ( index.isValid() )
this->ui->listView_OptionsCategories->selectionModel()->select( index, QItemSelectionModel::Select );
For Qt 6.3.x:
void selectRowInQListView(int row, QListView *listView) {
QModelIndex index = listView->model()->index(row, 0);
if (index.isValid()) {
//listView->selectionModel()->select(index, QItemSelectionModel::Select);
//listView->selectionModel()->select(index, QItemSelectionModel::Current);
listView->setCurrentIndex(index);
}
}