PDA

View Full Version : Problem with QAbstractListModel



eekhoorn12
25th August 2009, 22:03
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:
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:

#include <QDir>
#include <QMessageBox>

#include "serverlist.h"



serverList::serverList(): QAbstractListModel()
{
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>();
QDataStream outputStream(serverDataFile);
QDataStream inputStream(serverDataFile);
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();
}

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

if (index.row() >= listofServers.size() || index.row() < 0)
return QVariant();

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();
}
return QVariant();
}

QVariant serverList::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();

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:
return QVariant();
}
}
return QVariant();
}

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;
}

wysota
26th August 2009, 08:50
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?

eekhoorn12
26th August 2009, 10:43
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:

void serverView::createInterface()
{
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
QHBoxLayout *layout = new QHBoxLayout;
QStandardItemModel model;

listServers = new QTreeView;
serversList = new serverList();

listServers->setAlternatingRowColors(true);
listServers->setSelectionBehavior(QAbstractItemView::SelectRows );
listServers->setSortingEnabled(true);
listServers->setSelectionMode(QAbstractItemView::SingleSelectio n);

proxyModel->setSourceModel(serversList);
listServers->setModel(proxyModel);

layout->addWidget(listServers);
setLayout(layout);
}


This is my Server class:
server.cpp

#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

#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:
QString serverAddres;
QString serverNickname;
qint32 serverPort;
qint32 serverConnections;
QString serverUsername;
QString serverPassword;
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

eekhoorn12
26th August 2009, 14:26
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.