Listviews
This examples shows how to work with listviews (hierarchical and multi-column).
It also shows how to subclass listview items for special reasons. It looks
and works like the main window of a mail client.
Header file:
/****************************************************************************
** $Id: $
**
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
**
** This file is part of an example program for Qt. This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/
#ifndef LISTVIEWS_H
#define LISTVIEWS_H
#include <qsplitter.h>
#include <qstring.h>
#include <qobject.h>
#include <qdatetime.h>
#include <qptrlist.h>
#include <qlistview.h>
class QListView;
class QLabel;
class QPainter;
class QColorGroup;
class QObjectList;
class QPopupMenu;
// -----------------------------------------------------------------
class MessageHeader
{
public:
MessageHeader( const QString &_sender, const QString &_subject, const QDateTime &_datetime )
: msender( _sender ), msubject( _subject ), mdatetime( _datetime )
{}
MessageHeader( const MessageHeader &mh );
MessageHeader &operator=( const MessageHeader &mh );
QString sender() { return msender; }
QString subject() { return msubject; }
QDateTime datetime() { return mdatetime; }
protected:
QString msender, msubject;
QDateTime mdatetime;
};
// -----------------------------------------------------------------
class Message
{
public:
enum State { Read = 0,
Unread};
Message( const MessageHeader &mh, const QString &_body )
: mheader( mh ), mbody( _body ), mstate( Unread )
{}
Message( const Message &m )
: mheader( m.mheader ), mbody( m.mbody ), mstate( m.mstate )
{}
MessageHeader header() { return mheader; }
QString body() { return mbody; }
void setState( const State &s ) { mstate = s; }
State state() { return mstate; }
protected:
MessageHeader mheader;
QString mbody;
State mstate;
};
// -----------------------------------------------------------------
class Folder : public QObject
{
Q_OBJECT
public:
Folder( Folder *parent, const QString &name );
~Folder()
{}
void addMessage( Message *m )
{ lstMessages.append( m ); }
QString folderName() { return fName; }
Message *firstMessage() { return lstMessages.first(); }
Message *nextMessage() { return lstMessages.next(); }
protected:
QString fName;
QPtrList<Message> lstMessages;
};
// -----------------------------------------------------------------
class FolderListItem : public QListViewItem
{
public:
FolderListItem( QListView *parent, Folder *f );
FolderListItem( FolderListItem *parent, Folder *f );
void insertSubFolders( const QObjectList *lst );
Folder *folder() { return myFolder; }
protected:
Folder *myFolder;
};
// -----------------------------------------------------------------
class MessageListItem : public QListViewItem
{
public:
MessageListItem( QListView *parent, Message *m );
virtual void paintCell( QPainter *p, const QColorGroup &cg,
int column, int width, int alignment );
Message *message() { return myMessage; }
protected:
Message *myMessage;
};
// -----------------------------------------------------------------
class ListViews : public QSplitter
{
Q_OBJECT
public:
ListViews( QWidget *parent = 0, const char *name = 0 );
~ListViews()
{}
protected:
void initFolders();
void initFolder( Folder *folder, unsigned int &count );
void setupFolders();
QListView *messages, *folders;
QLabel *message;
QPopupMenu* menu;
QPtrList<Folder> lstFolders;
protected slots:
void slotFolderChanged( QListViewItem* );
void slotMessageChanged();
void slotRMB( QListViewItem*, const QPoint &, int );
};
#endif
Implementation:
/****************************************************************************
** $Id: $
**
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
**
** This file is part of an example program for Qt. This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/
#include "listviews.h"
#include <qlabel.h>
#include <qpainter.h>
#include <qpalette.h>
#include <qobjectlist.h>
#include <qpopupmenu.h>
#include <qheader.h>
#include <qregexp.h>
// -----------------------------------------------------------------
MessageHeader::MessageHeader( const MessageHeader &mh )
{
msender = mh.msender;
msubject = mh.msubject;
mdatetime = mh.mdatetime;
}
MessageHeader &MessageHeader::operator=( const MessageHeader &mh )
{
msender = mh.msender;
msubject = mh.msubject;
mdatetime = mh.mdatetime;
return *this;
}
// -----------------------------------------------------------------
Folder::Folder( Folder *parent, const QString &name )
: QObject( parent, name ), fName( name )
{
lstMessages.setAutoDelete( TRUE );
}
// -----------------------------------------------------------------
FolderListItem::FolderListItem( QListView *parent, Folder *f )
: QListViewItem( parent )
{
myFolder = f;
setText( 0, f->folderName() );
if ( myFolder->children() )
insertSubFolders( myFolder->children() );
}
FolderListItem::FolderListItem( FolderListItem *parent, Folder *f )
: QListViewItem( parent )
{
myFolder = f;
setText( 0, f->folderName() );
if ( myFolder->children() )
insertSubFolders( myFolder->children() );
}
void FolderListItem::insertSubFolders( const QObjectList *lst )
{
Folder *f;
for ( f = ( Folder* )( ( QObjectList* )lst )->first(); f; f = ( Folder* )( ( QObjectList* )lst )->next() )
(void)new FolderListItem( this, f );
}
// -----------------------------------------------------------------
MessageListItem::MessageListItem( QListView *parent, Message *m )
: QListViewItem( parent )
{
myMessage = m;
setText( 0, myMessage->header().sender() );
setText( 1, myMessage->header().subject() );
setText( 2, myMessage->header().datetime().toString() );
}
void MessageListItem::paintCell( QPainter *p, const QColorGroup &cg,
int column, int width, int alignment )
{
QColorGroup _cg( cg );
QColor c = _cg.text();
if ( myMessage->state() == Message::Unread )
_cg.setColor( QColorGroup::Text, Qt::red );
QListViewItem::paintCell( p, _cg, column, width, alignment );
_cg.setColor( QColorGroup::Text, c );
}
// -----------------------------------------------------------------
ListViews::ListViews( QWidget *parent, const char *name )
: QSplitter( Qt::Horizontal, parent, name )
{
lstFolders.setAutoDelete( TRUE );
folders = new QListView( this );
folders->header()->setClickEnabled( FALSE );
folders->addColumn( "Folder" );
initFolders();
setupFolders();
folders->setRootIsDecorated( TRUE );
setResizeMode( folders, QSplitter::KeepSize );
QSplitter *vsplitter = new QSplitter( Qt::Vertical, this );
messages = new QListView( vsplitter );
messages->addColumn( "Sender" );
messages->addColumn( "Subject" );
messages->addColumn( "Date" );
messages->setColumnAlignment( 1, Qt::AlignRight );
messages->setAllColumnsShowFocus( TRUE );
messages->setShowSortIndicator( TRUE );
menu = new QPopupMenu( messages );
for( int i = 1; i <= 10; i++ )
menu->insertItem( QString( "Context Item %1" ).arg( i ) );
connect(messages, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ),
this, SLOT( slotRMB( QListViewItem *, const QPoint &, int ) ) );
vsplitter->setResizeMode( messages, QSplitter::KeepSize );
message = new QLabel( vsplitter );
message->setAlignment( Qt::AlignTop );
message->setBackgroundMode( PaletteBase );
connect( folders, SIGNAL( selectionChanged( QListViewItem* ) ),
this, SLOT( slotFolderChanged( QListViewItem* ) ) );
connect( messages, SIGNAL( selectionChanged() ),
this, SLOT( slotMessageChanged() ) );
connect( messages, SIGNAL( currentChanged( QListViewItem * ) ),
this, SLOT( slotMessageChanged() ) );
messages->setSelectionMode( QListView::Extended );
// some preparations
folders->firstChild()->setOpen( TRUE );
folders->firstChild()->firstChild()->setOpen( TRUE );
folders->setCurrentItem( folders->firstChild()->firstChild()->firstChild() );
folders->setSelected( folders->firstChild()->firstChild()->firstChild(), TRUE );
messages->setSelected( messages->firstChild(), TRUE );
messages->setCurrentItem( messages->firstChild() );
message->setMargin( 5 );
QValueList<int> lst;
lst.append( 170 );
setSizes( lst );
}
void ListViews::initFolders()
{
unsigned int mcount = 1;
for ( unsigned int i = 1; i < 20; i++ ) {
QString str;
str = QString( "Folder %1" ).arg( i );
Folder *f = new Folder( 0, str );
for ( unsigned int j = 1; j < 5; j++ ) {
QString str2;
str2 = QString( "Sub Folder %1" ).arg( j );
Folder *f2 = new Folder( f, str2 );
for ( unsigned int k = 1; k < 3; k++ ) {
QString str3;
str3 = QString( "Sub Sub Folder %1" ).arg( k );
Folder *f3 = new Folder( f2, str3 );
initFolder( f3, mcount );
}
}
lstFolders.append( f );
}
}
void ListViews::initFolder( Folder *folder, unsigned int &count )
{
for ( unsigned int i = 0; i < 15; i++, count++ ) {
QString str;
str = QString( "Message %1 " ).arg( count );
QDateTime dt = QDateTime::currentDateTime();
dt = dt.addSecs( 60 * count );
MessageHeader mh( "Trolltech <info@trolltech.com> ", str, dt );
QString body;
body = QString( "This is the message number %1 of this application, \n"
"which shows how to use QListViews, QListViewItems, \n"
"QSplitters and so on. The code should show how easy\n"
"this can be done in Qt." ).arg( count );
Message *msg = new Message( mh, body );
folder->addMessage( msg );
}
}
void ListViews::setupFolders()
{
folders->clear();
for ( Folder* f = lstFolders.first(); f; f = lstFolders.next() )
(void)new FolderListItem( folders, f );
}
void ListViews::slotRMB( QListViewItem* Item, const QPoint & point, int )
{
if( Item )
menu->popup( point );
}
void ListViews::slotFolderChanged( QListViewItem *i )
{
if ( !i )
return;
messages->clear();
message->setText( "" );
FolderListItem *item = ( FolderListItem* )i;
for ( Message* msg = item->folder()->firstMessage(); msg;
msg = item->folder()->nextMessage() )
(void)new MessageListItem( messages, msg );
}
void ListViews::slotMessageChanged()
{
QListViewItem *i = messages->currentItem();
if ( !i )
return;
if ( !i->isSelected() ) {
message->setText( "" );
return;
}
MessageListItem *item = ( MessageListItem* )i;
Message *msg = item->message();
QString text;
QString tmp = msg->header().sender();
tmp = tmp.replace( "<", "<" );
tmp = tmp.replace( ">", ">" );
text = QString( "<b><i>From:</i></b> <a href=\"mailto:info@trolltech.com\">%1</a><br>"
"<b><i>Subject:</i></b> <big><big><b>%2</b></big></big><br>"
"<b><i>Date:</i></b> %3<br><br>"
"%4" ).
arg( tmp ).arg( msg->header().subject() ).
arg( msg->header().datetime().toString() ).arg( msg->body() );
message->setText( text );
msg->setState( Message::Read );
}
Main:
/****************************************************************************
** $Id: $
**
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
**
** This file is part of an example program for Qt. This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/
#include "listviews.h"
#include <qapplication.h>
int main( int argc, char **argv )
{
QApplication a( argc, argv );
ListViews listViews;
listViews.resize( 640, 480 );
listViews.setCaption( "Qt Example - Listview" );
a.setMainWidget( &listViews );
listViews.show();
return a.exec();
}
See also Examples.