Trier des QListViews

| Andy Shaw | traducteur : Thibaut Cuvelier | Qt Quarterly |

Le widget QListView fournit des vues, et de listes, et d'arborescences. La classe fournit un tri par n'importe quelle colonne respectant l'encodage Unicode ou bien strictement aucun tri. Cependant, il existe souvent des situations où le tri doit être plus sophistiqué qu'un simple tri lexical. Cette partie explique comment prendre le contrôle total du tri de QListView.

Cet article est une traduction autorisée de Sorting QListViews, par Andy Shaw.

Commentez

- Titre : Trier des QListViews

- Auteurs : Andy Shaw, traducteur : Thibaut Cuvelier, Qt Quarterly

- Parution : 25 février 2009

- Mise à jour : 1 août 2011

- Licence : Copyright ® 2002 Andy Shaw. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. L'article original

- II. Introduction

- III. L'exemple d'un client de messagerie

- IV. Réimplémenter QListViewItem::key()

- V. Réimplémenter QListViewItem::compare()

- VI. Divers

I - L'article original

Qt Quarterly est une revue trimestrielle électronique proposée par Qt à destination des développeurs et utilisateurs de Qt. Vous pouvez trouver les versions originales.

Nokia, Qt, Qt Quarterly et leurs logos sont des marques déposées de Nokia Corporation en Finlande et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.

Cet article est la traduction de l'article Sorting QListViews de Andy Shaw paru dans la Qt Quarterly Issue 1.

Cet article est une traduction d'un des tutoriels écrits par Nokia Corporation and/or its subsidiary(-ies) inclus dans la documentation de Qt, en anglais. Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia.

II - Introduction

Par défaut, QListView trie selon la première colonne dans un ordre ascendant. Pour désactiver le tri, il suffit d'appeler setSorting(-1). Pour trier selon une certaine colonne, un appel à setSorting() avec le numéro de la colonne, et, optionnellement, un drapeau qui mentionne l'ordre (ascendant ou descendant), suffit. Si deux items ont les mêmes entrées, très exactement, dans la colonne utilisée, Qt utilise les autres colonnes, comme nécessaire, pour obtenir une comparaison. Un tri personnalisé peut être achevé par un ajustement des fonctions suivantes de QListViewItem : key(), compare() ou sortChildItems().

Arranger sortChildItems() à notre manière contourne la réimplémentation de key() et de compare(), et permet de remplacer l'algorithme fourni par qHeapSort() par le vôtre. Dans cet article, nous allons nous contenter de couvrir les cas les plus communs de la réimplémentation de key() et/ou de compare().

III - L'exemple d'un client de messagerie

Nous allons utiliser un client de messagerie comme exemple du contrôle du tri de QListView. Nous allons créer une QListView avec les colonnes Sujet, Émetteur et Date.

QListView* mail = new QListView( this );
mail->addColumn( "Sujet" );
mail->addColumn( "Émetteur" );
mail->addColumn( "Date" );

Nous allons aussi mettre quelques données d'exemple.

new QListViewItem( mail, "Comptabilité",
"Joe Bloggs <joe@bloggs.com>", "25/12/2001" );
new QListViewItem( mail, "Re : Comptabilité",
"andy@nospam.com", "31/12/2001" );
new QListViewItem( mail, "Dépenses",
"joe@bloggs.com", "01/08/2002" );
new QListViewItem( mail, "Re : Comptabilité",
"Joe <joe@bloggs.com>", "14/01/2002" );
new QListViewItem( mail, "Re : Dépenses",
"Andy <andy@nospam.com>", "02/01/2002" );

IV - Réimplémenter QListViewItem::key()

Cette fonction est la plus utile pour comparer des données textuelles. L'implémentation par défaut retourne simplement le texte de la colonne.

Si nous devons trier la liste exemple sur la colonne Expéditeur, l'implémentation de base retourne :

"Joe Bloggs <joe@bloggs.com>", "Joe <joe@bloggs.com>", "joe@bloggs.com"

La même adresse est mise à des positions différentes, alors qu'elle reste la même ! Nous pouvons résoudre ce problème en réimplémentant la fonction key(), pour qu'elle retourne uniquement l'adresse email, sans le moindre nom.

class MyListViewItem : public QListViewItem
{
public:
MyListViewItem( QListView* parent, QString subject,
QString sender, QString date );
QString key( int column, bool ascending ) const;
};

QString MyListViewItem::key( int column,
bool ascending ) const
{
if ( column == 1 )
{
QString senderText = text( 1 );
int firstbracket = senderText.find( "<" );
if ( firstbracket == -1 )
return senderText;
else
return senderText.mid( firstbracket + 1,
senderText.length() -
firstbracket - 2 );
}
else
{
return QListViewItem::key( column, ascending );
}
}

Si la colonne Expéditeur a le symbole <, nous prenons le texte entre < et >. Sinon, nous prenons le texte en entier comme adresse email. Si le QListView n'est pas triée par la colonne Expéditeur, nous utilisons la fonction par défaut.

Une opération semblable peut être faite pour mettre Comptabilité et Re : Comptabilité à la même hauteur quand la liste est triée par la colonne Sujet.

En réimplémentant key() comme nous l'avons ici fait, il est possible de convertir n'importe quelle donnée pour qu'elle soit comparable, et que QListView puisse trier la liste avec ces données.

V - Réimplémenter QListViewItem::compare()

Si la fonction key() est réimplémentée, les chaînes résultantes seront comparées avec une méthode qui tient compte de la langue. En ce qui concerne les données qui n'en ont pas besoin, et pour de meilleures performances, la fonction compare() peut être utilisée à la place.

Dans notre exemple, la colonne Date a besoin d'être comparée, mais pas comme un texte. Il s'agit donc d'une candidate idéale pour la réimplémentation de compare().

int MyListViewItem::compare( QListViewItem* item,
int column,
bool ascending ) const
{
if ( column == 2 )
{
QDate d = QDate::fromString( text( 2 ), Qt::LocalDate );
QDate e = QDate::fromString( item->text( 2 ), Qt::LocalDate );
return e.daysTo( d );
}
else
{
return QListViewItem::compare( item, column, ascending );
}
}

Ce code convertit les dates textuelles en des objets QDate, et retourne leur différence en jours, elle peut donc être négative. Si les dates avaient été dans le format ISO (YYYY-MM-DD), nous aurions pu les comparer textuellement (viacompare(), et non pas key(), parce que nous n'avons pas besoin de reconnaître la langue), ce qui aurait été nettement plus rapide.

VI - Divers

J'aimerais, ici, adresser un grand merci au groupe Qt, pour toute l'aide et les encouragements apportés lors de la traduction de ces articles, et, plus particulièrement, à Alp, yan, IrmatDen, Buggen25, et kinji1. Un grand merci à matrix788 pour sa relecture !

Au nom de toute l'équipe Qt, j'aimerais adresser le plus grand remerciement à Nokia pour nous avoir autorisé la traduction de cet article !