PDA

View Full Version : QTreeView and QStandardModel : add children



Valheru
18th September 2006, 20:54
I have a QTreeView subclassed, and it has a QStandardModel so as to be able to provide headers. I add items to the model from a database, namely servers and the connections to them. There are multiple connections to every server, with a default of 4. The code I have adds the connections under the servers, with no indentation and no arrow or + sign to collapse the servers and make the connections invisible. I assume that I'm adding the connections wrong and they are not being added as children.


ServerList::ServerList( QWidget *p)
{
parent = p;
model = new QStandardItemModel( 0, 1 );
model->setHeaderData( 0, Qt::Horizontal, "Server List" );
setModel( model );
setSelectionMode( QAbstractItemView::SingleSelection );
///Set up the actions for the right-click context menu
connectToServer = new QAction(tr("Connect"), this);
separator = new QAction(this);
separator->setSeparator(true);
newServer = new QAction(tr("New Server"), this);
editServer = new QAction(tr("Edit Server"), this);
deleteServer = new QAction(tr("Delete Server"), this);
///Set up the menu
menu = new QMenu();
menu->addAction(connectToServer);
menu->addAction(separator);
menu->addAction(newServer);
menu->addAction(editServer);
menu->addAction(deleteServer);
///Connect the actions
connect( connectToServer, SIGNAL( triggered() ), this, SLOT( connectToServerSlot() ) );
connect( newServer, SIGNAL( triggered() ), this, SLOT( newServerSlot() ) );
connect( editServer, SIGNAL( triggered() ), this, SLOT( editServerSlot() ) );
connect( deleteServer, SIGNAL( triggered() ), this, SLOT( deleteServerSlot() ) );
}


void ServerList::addItem( const QString &hostName, quint16 port, const QString& username,
const QString& password, quint16 timeout, quint16 numberConnections )
{
QModelIndex parent = model->index( 0, 0, parent );
int rows = model->rowCount( parent );
model->insertRows( rows, 1, parent );
QModelIndex index = model->index( rows, 0, parent );
model->setData( index, hostName );
Server ns( hostName, port, username, password, timeout, numberConnections );
server.append( ns );
for( int x = 0; x < numberConnections; x++ ){
QModelIndex parentServer = model->index( rows, 0, index );
int serverRow = model->rowCount( parentServer );
model->insertRows( serverRow, 1, parentServer );
QModelIndex connectionIndex = model->index( serverRow, 0, parentServer );
QString s("Connection #");
s += QString::number( x + 1 );
model->setData( connectionIndex, s );
}
}

wysota
19th September 2006, 01:55
What are 'parent' and 'parentServer' initialised to?

Valheru
19th September 2006, 06:44
Erm, they're not :/ What you see is what you get, in this case :(

wysota
19th September 2006, 09:51
How do you expect to use them if they are not initialised?

Valheru
19th September 2006, 10:17
What should I initialize them to then? I´m sorry, but I´m new to the model/view way of doing this and am just happy that it´s working at all :p The docs themselves are rather vague on this subject as well I find :(

wysota
19th September 2006, 10:48
What should I initialize them to then?

I don't know. It is you who used them. Didn't you know what you needed them for?


The docs themselves are rather vague on this subject as well I find
Hmm.... Maybe you didn't look well enough...


An example usage of QStandardItemModel to create a tree:

QStandardItemModel *model = new QStandardItemModel();
QModelIndex parent;
for (int i = 0; i < 4; ++i) {
parent = model->index(0, 0, parent);
model->insertRows(0, 1, parent);
model->insertColumns(0, 1, parent);
QModelIndex index = model->index(0, 0, parent);
model->setData(index, i);
}
It creates a cascade of 4 elements. If you want to have a two level tree you should modify the code a little, so that the parent index doesn't get changed at each iteration:

QStandardItemModel *model = new QStandardItemModel();
int parentrow = 2; // top level row number you wish to create offsprings for
QStringList connectionData;
connectionData << "Con1" << "Con2" << "Con3" << "Con4";
QModelIndex parent = model->index(parentrow, 0);
model->insertColumns(0, 1, parent); // this creates a single column for children of the item
for (int i = 0; i < connectionData.size(); ++i) {
model->insertRows(0, 1, parent);
QModelIndex index = model->index(i, 0, parent);
model->setData(index, connectionData[i]);
}

jpn
19th September 2006, 10:50
Go through and try to understand the following code:



void ServerList::addItem( const QString &hostName, quint16 port, const QString& username,
const QString& password, quint16 timeout, quint16 numberConnections )
{
// first, insert a top level row
int rows = model()->rowCount();
model()->insertRow( rows );

// set host name to the index in the first
// column of the newly inserted row
QModelIndex parent = model()->index( rows, 0 );
model()->setData( parent, hostName );

//Server ns( hostName, port, username, password, timeout, numberConnections );
//server.append( ns );

// add a column and enough rows for connection children
// the parent is the parent we just inserted above
model()->insertColumn( 0, parent ); // one column for children
rows = model()->rowCount( parent );
model()->insertRows( rows, numberConnections, parent ); // one row for each child

// set connection names for each children
for ( int x = 0; x < numberConnections; x++ )
{
QModelIndex child = model()->index( x, 0, parent ); // all connections are under the same parent
// which is, again, the same parent we
// inserted in the first place
model()->setData( child, QString("Connection #%1").arg( x + 1 ) );
}
}

Valheru
19th September 2006, 17:24
Thanks, that works perfectly. I'm now just trying to puzzle out why :p