Problem with QAbstractListModel
Hey all
I have a problem with a QAbstractListModel. I have a model that contains a list of custom classes type server. Of that list I want to show some information from each server item in the list in my gui. So I made a model in which I subclassed QAbstractListModel. When my application ends I write the list to a file and I load that file on the next startup of the application
But here is my problem when I run the program for the first time and there doesn't exist a file with the list I get an error when adding new servers to the list. The first item I add doesn't throw an error but also isn't visible in the gui but when I add a second item I get the following error in my Application Output window in QtCreator:
Code:
QTreeView::rowsInserted internal representation of the model has been corrupted, resetting.
But when I close the application and I restart it, it loads the servers I just added so they are written to the file and shows them in the gui. After that I can add servers and they are shown in the gui.
I run Windows 7 64 bit, program in QtCreator 1.2.0 with Qt 4.5.2
Here is my code:
Code:
#include <QDir>
#include <QMessageBox>
#include "serverlist.h"
{
settings = new Settings();
serverDataFile
= new QFile(settings
->getappDataDir
() + QDir::separator() + "servers" + QDir::separator() + "servers.dat");
serverDataFileInfo
= new QFileInfo(settings
->getappDataDir
() + QDir::separator() + "servers" + QDir::separator() + "servers.dat");
QList<Server> listofServers = QList<Server>();
this->loadServers();
}
void serverList::saveServers()
{
if(!serverDataFileInfo->exists())
{
QDir newFile
(serverDataFileInfo
->absoluteFilePath
());
newFile.mkpath(serverDataFileInfo->absolutePath());
}
if(!serverDataFile
->open
(QIODevice::ReadWrite)) {
QMessageBox::critical( 0,
"Post program",
"There was a problem writing the server settings file" );
return;
}
outputStream.setDevice(serverDataFile);
outputStream << this->listofServers;
serverDataFile->close();
return;
}
void serverList::addServer(Server newServer)
{
if(!this->listofServers.contains(newServer))
{
this
->insertRows
(this
->listofServers.
size(),
1,newServer,
QModelIndex());
this->saveServers();
}
}
void serverList::loadServers()
{
if(!serverDataFileInfo->exists())
{
QDir newFile
(serverDataFileInfo
->absoluteFilePath
());
newFile.mkpath(serverDataFileInfo->absolutePath());
}
if(!serverDataFile
->open
(QIODevice::ReadWrite)) {
QMessageBox::critical( 0,
"Post program",
"There was a problem reading the server settings file" );
return;
}
inputStream.setDevice(serverDataFile);
QList<Server> tempList;
inputStream >> tempList;
this->listofServers = tempList;
serverDataFile->close();
return;
}
int serverList
::columnCount(const QModelIndex &parent
) const {
if( listofServers.count() == 0)
{
return 0;
}
else
{
return listofServers.first().getColumnCount();
}
}
int serverList
::rowCount(const QModelIndex &parent
) const {
return listofServers.count();
}
{
if (!index.isValid())
if (index.row() >= listofServers.size() || index.row() < 0)
if (role == Qt::DisplayRole) {
if (index.column() == 0)
return listofServers.at(index.row()).getAddres();
else if (index.column() == 1)
return listofServers.at(index.row()).getPort();
else if (index.column() == 2)
return listofServers.at(index.row()).getNickname();
}
}
QVariant serverList
::headerData(int section, Qt
::Orientation orientation,
int role
) const {
if (role != Qt::DisplayRole)
if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return tr("Server Address");
case 1:
return tr("Server Port");
case 2:
return tr("Server Nickname");
default:
}
}
}
bool serverList
::insertRows(int position,
int rows, Server newServer,
const QModelIndex &index
) {
Q_UNUSED(index);
beginInsertRows
(QModelIndex(), position, position
+rows
-1);
for(int row = 0; row<rows; row++)
{
this->listofServers.insert(position,newServer);
}
endInsertRows();
return true;
}
Re: Problem with QAbstractListModel
Hmm... doesn't your implementation add items to the list in reverse order?
Unfortunately apart from that your implementation seems correct... Is this the exact code you have?
Re: Problem with QAbstractListModel
This is the exact code how I use it.
I will post some extra code maybe I made a mistake there:
This is the code where I create the list and add the model:
Code:
void serverView::createInterface()
{
serversList = new serverList();
listServers->setAlternatingRowColors(true);
listServers->setSortingEnabled(true);
proxyModel->setSourceModel(serversList);
listServers->setModel(proxyModel);
layout->addWidget(listServers);
setLayout(layout);
}
This is my Server class:
server.cpp
Code:
#include "server.h"
#include <QDataStream>
#include <QString>
#include <QDebug>
Server::Server()
{
}
QDataStream& operator<<(QDataStream& out, const Server& server)
{
out << server.getAddres();
out << server.getNickname();
out << server.getPort();
out << server.getConnections();
out << server.getUsername();
out << server.getPassword();
out << server.getRequireLogin();
out << server.getUseSsl();
return out;
}
QDataStream& operator>>(QDataStream& in,Server& server)
{
QString tempA, tempN, tempUn, tempPa;
qint32 tempPo, tempC;
bool tempR, tempUS;
in >> tempA;
server.setAddres(tempA);
in >> tempN;
server.setNickname(tempN);
in >> tempPo;
server.setPort(tempPo);
in >> tempC;
server.setConnections(tempC);
in >> tempUn;
server.setUsername(tempUn);
in >> tempPa;
server.setPassword(tempPa);
in >> tempR;
server.setRequireLogin(tempR);
in >> tempUS;
server.setUseSsl(tempUS);
return in;
}
server.h
Code:
#ifndef SERVER_H
#define SERVER_H
#include <QString>
#include <QtGlobal>
class Server
{
public:
Server();
//Set functions
void setAddres
(QString newAddres
) { serverAddres
= newAddres;
} void setNickname
(QString newNickname
) { serverNickname
= newNickname;
} void setPort(qint32 newPort) {serverPort = newPort; }
void setConnections(qint32 newConnections) { serverConnections = newConnections; }
void setUsername
(QString newUsername
) { serverUsername
= newUsername;
} void setPassword
(QString newPassword
) { serverPassword
= newPassword;
} void setRequireLogin(bool newRequireLogin) { serverRequireLogin = newRequireLogin; }
void setUseSsl(bool newUseSsl) { serverUseSsl = newUseSsl; }
//Get functions
QString getAddres
() { return serverAddres;
} QString getAddres
() const { return serverAddres;
} QString getNickname
() { return serverNickname;
} QString getNickname
() const { return serverNickname;
} qint32 getPort() { return serverPort; }
qint32 getPort() const { return serverPort; }
qint32 getConnections() { return serverConnections; }
qint32 getConnections() const { return serverConnections; }
QString getUsername
() { return serverUsername;
} QString getUsername
() const { return serverUsername;
} QString getPassword
() { return serverPassword;
} QString getPassword
() const { return serverPassword;
} bool getRequireLogin() { return serverRequireLogin; }
bool getRequireLogin() const { return serverRequireLogin; }
bool getUseSsl() { return serverUseSsl; }
bool getUseSsl() const { return serverUseSsl; }
int getColumnCount() { return 3; }
int getColumnCount() const { return 3; }
private:
qint32 serverPort;
qint32 serverConnections;
bool serverRequireLogin;
bool serverUseSsl;
};
QDataStream& operator<<(QDataStream& out, const Server& server);
QDataStream& operator>>(QDataStream& in,Server& server);
inline bool operator==(Server s1, Server s2) { return (s1.getAddres() == s2.getAddres() && s1.getUsername() == s2.getUsername() && s1.getPassword() == s2.getPassword() && s1.getUseSsl() == s2.getUseSsl() );}
#endif // SERVER_H
Re: Problem with QAbstractListModel
I think I have found the solution. In the function columnCount from my serverList class I return 0 when the list is empty so I think it remembers that and when I add servers it gives an error on that because I now have set that to return 3 and now it works.