QAbstractItemModel::data() is not called for all tree subitems - qt

I have a QAbstractItemModel-derived class attached to a QTreeView.
Model implements 2 top-level rows and one of them has 3 sub-rows. Only first 2 sub-rows are displayed. If I add one “dummy” top-level row then everything is displayed.
I used qDebug() to print how many times QTreeView calls my model::data() and with what indexes (only Qt::DisplayRole cases are printed) and see that it is actually called 2 times for sub-rows instead of 3.
Of course, first suspicion is that my model::rowCount() is incorrect and makes QTreeView “think” that there are only 2 sub-rows. So here are qDebug() prints:
rowCount returning 3 for parent 0xbc6f70
…….
Qt::DisplayRole for row 0 ,column 0 pointer 0xbc6fc0 parent= 0xbc6f70
Qt::DisplayRole for row 1 ,column 0 pointer 0xbc7068 parent= 0xbc6f70
where 0xbc6f70 is:
parent.internalPointer() in model::rowCount(const QModelIndex &parent)
index.parent().internalPointer() in model::data(const QModelIndex &index, int role)
So why is model::data() being called for row 0 and row 1 but not for row 2 if model::rowCount() returned 3 for index with internalPointer() 0xbc6f70?
Here is the code:
int Model_Tree::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
{
// This is 1st level
qDebug() << "rowCount returning m_RowCount" << m_RowCount << "for !parent.isValid()" << parent.internalPointer() << "row" << parent.row() << "column" << parent.column();
return m_RowCount;
}
int column = parent.column();
if(0 != column)
{
qDebug() << "rowCount returning 0 for parent 0 != column (" << column << ")";
return 0; // only item at 0th column can have children
}
const TreeItem* pTreeItem = (const TreeItem*)parent.internalPointer();
if (0 == pTreeItem)
{
qDebug() << "rowCount returning 0 for parent 0==pTreeItem" << pTreeItem;
return 0;
}
qDebug() << "rowCount returning " << pTreeItem->m_Children.size() << "for parent " << pTreeItem << "type:" << pTreeItem->m_type;
return pTreeItem->m_Children.size();
}
QVariant Model_Tree::data(const QModelIndex &index, int role) const
{
if (!(index.isValid()))
{
return QVariant();
}
switch (role)
{
case Qt::TextAlignmentRole:
return Qt::AlignTop;
case Qt::DisplayRole:
void* p = index.internalPointer();
int column = index.column();
int row = index.row();
qDebug() << "Qt::DisplayRole for row " << row << ",column " << column << "pointer" << p << "parent=" << index.parent().internalPointer();
// .... the rest of Model_Tree::data implementation
}
and here is some qDebug() output:
rowCount returning 3 for parent **0x122ee138** type: 0
....
Qt::DisplayRole for row 0 ,column 0 pointer 0x122ee168 parent= **0x122ee138**
Qt::DisplayRole for row 1 ,column 0 pointer 0x122ee198 parent= **0x122ee138**
note 0x122ee138 - this is "internalPointer" value for parent node that contains 3 children
here are index() and parent() implementations:
QModelIndex Model_Tree::index(int row, int column, const QModelIndex &parent) const
{
void* p = 0;
if (!parent.isValid())
{
// This is 1st level
// we use our whole record
if (row < m_RowCount)
{
const TreeItem& treeItem = *(m_pRootItem->m_Children.at(row));
const LogRecord* pRecord = treeItem.m_pRecord;
const LogRecord& record = *pRecord;
if (column == 0)
{
p = (void*)&treeItem; // because createIndex() wants void* a 3rd parameter
}
else
{
const QList<QVariant>& fieldList = record.fieldList;
if (column <= fieldList.size())
{
const QVariant* pField = &(fieldList[column - 1]); // -1 Because we have extra column at left side
if ( (QMetaType::Type)(pField->type()) == QMetaType::QString )
{
//const QString *pString = static_cast<const QString*>(pField->data());
p = const_cast<void*>(pField->data());
}
if ( (QMetaType::Type)(pField->type()) == QMetaType::QStringList )
{
const QStringList *pStringList = static_cast<const QStringList*>(pField->data());
//const QString *pString = &(pStringList->at(0)) ;
p = const_cast<void*>( static_cast<const void*>( &(pStringList->at(0)) ) );
}
}
}
}
//qDebug() << "Creating index: " << row << ", " << column << ", " << p;
return createIndex(row, column, p);
}
if (0 != column)
{
//qDebug() << "Creating index: " << row << ", " << column << ", 0 -- if (0 != column)";
return createIndex(row, column, (void*)0);
}
p = parent.internalPointer();
const TreeItem* pTreeItem = (const TreeItem*)p;
if (0 == pTreeItem)
{
//qDebug() << "Creating index: " << row << ", " << column << ", 0 -- if (0 == pTreeItem)";
return createIndex(row, column, (void*)0);
}
if (row < pTreeItem->m_Children.size())
{
const TreeItem* pTreeSubItem = pTreeItem->m_Children.at(row).data();
//qDebug() << "Creating subline index: " << row << ", " << column << ", " << (void*)pTreeSubItem << "parent: " << pTreeItem;
return createIndex(row, column, (void*)pTreeSubItem);
}
//qDebug() << "Creating index: " << row << ", " << column << ", 0";
return createIndex(row, column, (void*)0);
}
QModelIndex Model_Tree::parent(const QModelIndex &index) const
{
if (!index.isValid())
{
QModelIndex qi;
qDebug() << "Creating INVACHILD PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
const TreeItem* pChildItem = static_cast<const TreeItem*>(index.internalPointer());
if (0 == pChildItem)
{
QModelIndex qi;
qDebug() << "Creating NOTREEITEM PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
const TreeItem* pParentItem = pChildItem->m_pParent;
if (0 == pParentItem)
{
QModelIndex qi;
qDebug() << "Creating NOPARENT PARENT index: " << qi.row() << ", " << qi.column() << ", " << 0;
return qi;
}
qDebug() << "Creating PARENT index: " << pChildItem->m_RecordNumber << ", " << 0 << ", " << pParentItem;
return createIndex(pParentItem->m_RecordNumber, 0, (void*)pParentItem);
}
QVariant Model_Tree::data(const QModelIndex &index, int role) const
{
if (!(index.isValid()))
{
return QVariant();
}
switch (role)
{
case Qt::TextAlignmentRole:
return Qt::AlignTop;
case Qt::DisplayRole:
void* pInternal = index.internalPointer();
int column = index.column();
int row = index.row();
if (0 == column)
qDebug() << "Qt::DisplayRole for row " << row << ",column " << column << "pointer" << pInternal << "parent=" << index.parent().internalPointer();
if (0 == pInternal)
{
//qDebug() << "DR: internal pointer is 0";
return QVariant();
}
if (0 == column)
{
const TreeItem* pTreeItem = static_cast<const TreeItem*>(pInternal);
QString displayString;
QTextStream(&displayString) << pTreeItem->m_LogLineNumber;
if (pTreeItem->m_type == TreeItem::Subline)
{
QTextStream(&displayString) << " (" << row << "-th sub-line)"
<< " " << (*(pTreeItem->m_pSubline));
}
if (pTreeItem->m_type == TreeItem::Record)
{
if (pTreeItem->m_Children.size() > 0)
{
QTextStream(&displayString) << " (" << rowCount(index)/*pTreeItem->m_Children.size()*/ << " sub-lines)";
}
}
return displayString;
}
// for columns other than 0 index contains QString* as internal pointer
const QString* pText = static_cast<const QString*>(pInternal);
return *pText;
}
return QVariant();
}

Thank you Marek for trying to help me!
The problem was in my QSortFilterProxyModel-derived class that didn't take into account sub-items )))

Related

Passing map by reference in C++ and mutating its value

I am passing map by reference in the canSum function where i am mutating its value and adding pairs but at the end when I iterate over the map I find the value of map has not been updated.
canSum function is a recursive function which takes a number (targetSum) and an array and finds if it is possible to form targetSum by any combinations of number in the array (numbers can be repeated).
#include<iostream>
#include<vector>
#include<map>
using namespace std;
bool canSum(int targetSum,vector<int> a,map<int, bool> &m){
if(!(m.find(targetSum) == m.end()))
return m[targetSum];
if (targetSum == 0)
return true;
if(targetSum<0)
return false;
for (int num : a)
{
if (canSum(targetSum - num, a,m)==true)
{
// m[targetSum] = true;
m.insert(pair<int, bool>(targetSum, true));
return m[targetSum];
}
}
m[targetSum] = false;
return m[targetSum];
}
int main(){
int targetSum, t;
vector<int> a;
map<int, bool> m;
m[0] = true;
cout << "enter target" << endl;
cin >> targetSum;
cout << "enter array, press esc to stop entering"<<endl;
while(cin>>t){
a.push_back(t);
}
for (int j = 0; j < a.size(); j++)
{
cout << a[j]<<" ";
}
cout << endl;
for (auto itr = m.begin(); itr != m.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
if(canSum(targetSum, a,m)){
cout << endl << "true" << endl;
}
else cout << endl << "false" << endl;
return 0;
}
Please help me. Thank you.
The for loop to print the map should be after the function call like.
if(canSum(targetSum, a,m)){
cout << endl << "true" << endl;
}
else cout << endl << "false" << endl;
for (auto itr = m.begin(); itr != m.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
Instead of
for (auto itr = m.begin(); itr != m.end(); ++itr) {
cout << '\t' << itr->first
<< '\t' << itr->second << '\n';
}
if(canSum(targetSum, a,m)){
cout << endl << "true" << endl;
}
else cout << endl << "false" << endl;
To see mutations in the map due to the function

Sending Floats from server to client through socket (UDP)

So I am trying to send floats back and forth between clients and a server. I am able to send floats to the server and the server reads them perfectly. But unfortunately I can't seem to get the server sending the floats back to the other clients. Our current code that doesn't work looks like this.
Send function on server side
int Server::Send(float dt) {
{
char message[BUFLEN];
std::string msg = std::to_string(x2) + "#" + std::to_string(z2);
strcpy(message, (char*)msg.c_str());
if (sendto(server_socket, message, sizeof(message), 0, ptr->ai_addr, ptr->ai_addrlen) == SOCKET_ERROR)
{
std::cout << "Sendto() failed..." << std::endl;
}
else
{
std::cout << "Sent: " << message << "\n" << std::endl;
}
Receiving on Client side
int Client::Recieve(float dt) {
char buf[BUFLEN];
struct sockaddr_in fromAddr;
int fromlen;
fromlen = sizeof(fromAddr);
memset(buf, 0, BUFLEN);
int bytes_recieved = -1;
int sError = -1;
bytes_recieved = recvfrom(client_socket, buf, BUFLEN, 0, (struct sockaddr*) &fromAddr, &fromlen);
sError = WSAGetLastError();
if (sError != WSAEWOULDBLOCK && bytes_recieved > 0)
{
std::cout << "Recieved: " << buf << std::endl;
std::string tmp = buf;
std::size_t pos = tmp.find("#");
tmp = tmp.substr(0, pos - 1);
x2 = std::stof(tmp, NULL);
tmp = buf;
tmp = tmp.substr(pos + 1);
z2 = std::stof(tmp, NULL);
std::cout << "tx: " << x2 << " ty: " << z2 << std::endl;
}
else
std::cout << "Not Receiving" << std::endl;
Any help would be awesome!

Need help figuriing out correct syntax to update objects in global scope

I have this code:
int do_transact(ifstream & inFile, list<shared_ptr<Bike>> bikelist, status s)
{
int id, i = 0, size = bikelist.size();
float days;
string str, str2;
char name[50];
list<shared_ptr<Bike>>::iterator it = bikelist.begin();
if (s == NO_STATUS) //performs rental
{
inFile >> id;
inFile >> days;
inFile >> str;
inFile >> str2;
strcpy_s(name, str.c_str());
while (i < size)
{
if (id == (*it)->id_num) // rents bike
{
cout << "vvvvvv PERFORMING RENTAL vvvvvv" << endl << endl;
cout << "The price of this rental will be: $" << (days)*((*it)->cost_per_day) << endl;
strcpy_s((*it)->to_whom, name);
(*it)->rented_code = RENTED;
cout << "Thank you for your business!" << endl << endl;
return 0;
}
i++;
it++;
}
}
}
I am trying to change to_whom and rented_code in the original list, but it is not updating.
What is the syntax I need in order to change these values the way I need?

ifstream reading multiple data types from same line BAD_ACCESS

I'm trying to read in multiple element types from a text file.
Here's an example input:
push 0
push 1
push 3
push 5
add
push 3
The code below work until the last line, then I get a BAD_ACCESS error after trying anything after it reads in a line without 'b'. Any suggestions?
ifstream infile("example.txt");
while (!infile.eof())
{
infile >> a >> b;
if (a == "push")
push(b);
if (a == "add")
{
add();
}
if (a == "subtract")
{
int y = subtract();
cout << y << endl;
}
if (a == "multiply")
{
int y = multiply();
cout << y << endl;
}
if (a == "divide")
{
int y = divide();
cout << y << endl;
}
if (a == "pop")
{
cout << b;
b = NULL;
}
cout << a << b << endl;
}

Qt Delete Items from QMultiHash while Iterating

I want to delete items out of my QMultiHash. Looking at the docs, I believe I am doing it correctly but it always crashes after the first delete. What am I doing wrong?
Here is my code:
for (QMultiHash<int, Frame*>::iterator i = m_FrameBuffer.begin(); i != m_FrameBuffer.end(); ++i) {
if ( (frameNumber - i.key()) >= ( 5 ) ) { // Delete frames 5 frames old or more
qDebug() << "DELETE ==> Key:" << i.key() << "Value:" << i.value() << " Difference: " << (frameNumber - i.key());
int removed = m_FrameBuffer.remove(i.key());
qDebug() << "Removed this many: " << removed;
}
}
Here is the output:
FRAME COUNT: 1
FRAME COUNT: 2
FRAME COUNT: 3
FRAME COUNT: 4
FRAME COUNT: 5
DELETE ==> Key: 2 Value: Frame(0x138a400) Difference: 5
Removed this many: 1
The program has unexpectedly finished.
Your iterator becomes invalid after you remove items from a container while iterating it. Try this:
QList<int> keys = m_FrameBuffer.keys();
foreach (int key, keys)
{
int diff = frameNumber - key;
if (diff >= 5)
{
qDebug() << "DELETE ==> Key:" << key
<< "Value:" << m_FrameBuffer.value(key)
<< "Difference: " << diff;
int removed = m_FrameBuffer.remove(key);
qDebug() << "Removed this many: " << removed;
}
}
Also you can use QMutableHashIterator for it:
QMutableHashIterator<int, Frame*> it(m_FrameBuffer);
while (it.hasNext())
{
it.next();
int key = it.key();
int diff = frameNumber - it.key();
if (diff >= 5)
{
qDebug() << "Items to be removed:"
<< m_FrameBuffer.values(it.key()).size();
it.remove();
}
}

Resources